diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index f4d7e814f..000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,7 +0,0 @@ -# These are supported funding model platforms - -github: [headroom-sdk] -# patreon: headroom -# open_collective: headroom -# ko_fi: headroom -# custom: ["https://headroomlabs.ai/sponsor"] diff --git a/.gitignore b/.gitignore index 34fe52207..52f01de44 100644 --- a/.gitignore +++ b/.gitignore @@ -118,6 +118,9 @@ env.bak/ venv.bak/ .python-version +# Node.js dependencies (never commit vendored deps) +node_modules/ + # Secrets and API keys - NEVER commit these *.pem *.key @@ -229,10 +232,7 @@ CLAUDE.md # Vitals provenance data .vitals/ -# Superpowers working files (plans, specs, brainstorming) -# docs/spec/ (lives in git - git-versioned living specification) - -# Managed platform (separate private repo) +# Separate private repos — never commit here headroom-managed/ # Local act testing (never commit test tokens) diff --git a/ENTERPRISE.md b/ENTERPRISE.md deleted file mode 100644 index 9fb04b27d..000000000 --- a/ENTERPRISE.md +++ /dev/null @@ -1,5 +0,0 @@ -# Enterprise - -## Enterprise Support - -Interested in using Headroom at scale? We're happy to discuss your deployment requirements! Email us at: **hello@headroomlabs.ai** \ No newline at end of file diff --git a/PR.md b/PR.md deleted file mode 100644 index 3a311c869..000000000 --- a/PR.md +++ /dev/null @@ -1,170 +0,0 @@ -## Description - -Implement unified CI/CD release automation with semantic versioning across all three packages: -- **Python (headroom-ai)** — pip package on PyPI -- **TypeScript SDK (headroom-ai)** — npm package on npmjs.org -- **OpenClaw plugin (headroom-openclaw)** — npm package on npmjs.org and GitHub Package Registry - -Currently the three packages are independently versioned (0.5.25 / 0.1.0 / 0.1.0). This PR introduces a single-source-of-truth version in `pyproject.toml` that propagates to all packages on every release, driven by conventional commit messages. - -Fixes #(issue number) - -## Type of Change - -- [ ] Bug fix (non-breaking change that fixes an issue) -- [x] New feature (non-breaking change that adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to change) -- [x] Documentation update -- [ ] Performance improvement -- [x] Code refactoring (no functional changes) - -## Changes Made - -### New Files - -**Scripts:** -- `scripts/version-sync.py` — Reads version from `pyproject.toml`, updates all 4 version files. Supports `--version X.Y.Z` and `--bump {major,minor,patch}`. -- `scripts/changelog-gen.py` — Parses conventional commits since last tag, groups by type, generates markdown changelog with breaking change detection. -- `scripts/verify-versions.py` — Pre-release sanity check that all 4 version files are in sync. -- `scripts/tests/test_version_sync.py` — 5 tests for version-sync.py -- `scripts/tests/test_changelog_gen.py` — 23 tests for changelog-gen.py - -**Workflows:** -- `.github/workflows/release.yml` — Unified release pipeline: detect → build → publish-pypi → publish-npm → publish-github-packages → create-release -- `.commitlintrc.json` — Conventional commit enforcement via `@commitlint/config-conventional` - -**Local Testing (act):** -- `.actrc` — Default `act` flags (Ubuntu runner, reuse, quiet) -- `.github/act/dry-run.json` — `act` event file for dry-run testing -- `.github/act/push-feat.json` — `act` event file for simulating a feat commit -- `.actrc.local.example` — Local override template for `act` -- `.env.act.example` — Secrets documentation template for `act` local testing - -**Documentation:** -- `docs/content/docs/releases.mdx` — Full documentation for the release pipeline, testing guide, and configuration reference - -### Modified Files - -- `.github/workflows/ci.yml` — Added `commitlint` job to enforce conventional commits -- `.github/workflows/publish.yml` — Changed from `release` trigger to `workflow_dispatch` only (superseded by `release.yml`) -- `.github/workflows/release.yml` — **Rewritten** with canonical+commit-height algorithm (no more commit loop) -- `.gitignore` — Added `!scripts/version-sync.py`, `!scripts/changelog-gen.py`, `!scripts/verify-versions.py`, `!scripts/tests/`, `.env.act`, `.actrc.local` - -## Testing - -- [x] Unit tests pass (`pytest`) - - `scripts/tests/test_version_sync.py` — 5/5 passing - - `scripts/tests/test_changelog_gen.py` — 23/23 passing -- [x] Linting passes (`ruff check .`) -- [ ] Type checking passes (`mypy headroom`) — pre-existing issue in `headroom/cli/wrap.py:487` (unrelated) -- [x] New tests added for new functionality -- [x] Workflow tested with `act` (dry-run passes all jobs through build step — no infinite loop) - -## Algorithm Validation - -The canonical+commit-height algorithm was validated with test cases: -- Canonical `0.5.25`, no prior tag, `feat:` commit → git tag `v0.6.0.0`, npm `0.6.0` ✅ -- Canonical `0.5.25`, tag `v0.5.25.2`, `fix:` commit → git tag `v0.5.25.3`, npm `0.5.26` ✅ -- Canonical `0.5.25`, no prior tag, `fix:` commit → git tag `v0.5.25.0`, npm `0.5.25` ✅ -- Manual override `1.2.3` → git tag `v1.2.3`, npm `1.2.3` ✅ - -## Test Output - -``` -scripts/tests/test_version_sync.py ..... -scripts/tests/test_changelog_gen.py ....................... -``` - -## Checklist - -- [x] My code follows the project's style guidelines -- [x] I have performed a self-review of my code -- [x] I have commented my code, particularly in hard-to-understand areas -- [x] My changes generate no new warnings -- [x] I have added tests that prove my fix is effective or that my feature works -- [x] New and existing unit tests pass locally with my changes -- [x] I have made corresponding changes to the documentation -- [ ] I have updated the CHANGELOG.md if applicable - -## Additional Notes - -### Version Bump Logic - -**Canonical + Commit Height Algorithm** — The workflow NEVER commits back to the repo. `pyproject.toml` is the canonical source of truth, updated manually before merging. - -| Commit | Bump | Git Tag | npm Version | -|--------|------|---------|-------------| -| `fix:`, `ci:`, `chore:`, `perf:`, `refactor:` | patch | `v0.5.25.3` | `0.5.26` | -| `feat:` | minor | `v0.6.0.0` | `0.6.0` | -| `feat!:` or `feat:` + `BREAKING CHANGE` body | major | `v1.0.0.0` | `1.0.0` | - -The git tag uses `v{canonical}.{height}` (e.g., `v0.5.25.3` = 3 commits since canonical `0.5.25`). npm versions use 3-part semver, bumped from canonical. - -### Package Publishing Targets - -| Package | Target | Status | -|---------|--------|--------| -| `headroom-ai` (Python) | PyPI | ✅ via `pypa/gh-action-pypi-publish` | -| `headroom-ai` (TypeScript SDK) | npmjs.org | ✅ via `npm publish` | -| `headroom-openclaw` | npmjs.org | ✅ via `npm publish` | -| `headroom-openclaw` | GitHub Package Registry | ✅ via `npm publish --registry npm.pkg.github.com` | - -### Safety Gates - -Each publish job requires both `dry_run != 'true'` **and** the corresponding skip variable not set: - -| Variable | Effect | -|----------|--------| -| `PYPI_SKIP=true` | Skip PyPI publish | -| `NPM_SKIP=true` | Skip both npm publishes | -| `GH_PACKAGES_SKIP=true` | Skip GitHub Package Registry publish | - -Set in: **GitHub repo → Settings → Variables → Actions Variables**. - -### Workflow Triggers - -- **Auto:** On push to `main` — analyzes latest commit, bumps version, builds, publishes, creates GitHub Release -- **Manual:** `workflow_dispatch` with optional `version` override and `dry_run` flag -- **Paths ignore:** Skips runs when only `docs/`, `.github/workflows/ci.yml`, `.github/workflows/publish.yml`, `scripts/`, `.commitlintrc.json`, `.actrc`, `.github/act/`, or `.env.act.example` change - -### Local Testing - -```bash -# Install act -winget install act - -# Dry-run (no publishes) -act -W .github/workflows/release.yml -e .github/act/dry-run.json - -# Test feat: commit (minor bump) -act -W .github/workflows/release.yml -e .github/act/push-feat.json -``` - -### Required GitHub Secrets - -| Secret | Purpose | -|--------|---------| -| `NPM_TOKEN` | Publishing to npmjs.org | -| `GITHUB_TOKEN` | GitHub Package Registry (auto-provided by GitHub Actions) | - -PyPI uses trusted publisher OIDC — no secret required, only the `pypi` GitHub Environment must be configured. - -### First Release Note - -The TypeScript packages are currently at `0.1.0` while Python is at `0.5.25`. The first release will align all three to the same version. Update `pyproject.toml` to the desired canonical version before merging, then use `workflow_dispatch` with a manual `version` input to set the target explicitly. - -After each release, update `pyproject.toml` to match the published version to keep the canonical current and ensure unique git tags. - -### Parameterized Configuration - -All package names and registries are top-level `env` constants in `release.yml`: - -```yaml -env: - PYPI_PACKAGE: headroom-ai - PYPI_ENVIRONMENT: pypi - NPM_REGISTRY_URL: https://registry.npmjs.org - NPM_SDK_PACKAGE: headroom-ai - NPM_OPENCLAW_PACKAGE: headroom-openclaw - GITHUB_PACKAGES_REGISTRY_URL: https://npm.pkg.github.com -``` diff --git a/README.md b/README.md index 2fd3ecfe9..066807597 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,7 @@ Proof · Agents · Discord · - llms.txt · - Enterprise + llms.txt

@@ -181,7 +180,7 @@ unshaped as a control group: `export HEADROOM_OUTPUT_HOLDOUT=0.1`. The dashboard shows an **Output Tokens Saved** card next to input compression, labelled `measured` or `estimated` with the confidence band. -→ Full write-up incl. the measurement methodology: [`docs/proposals/output-token-reduction.md`](docs/proposals/output-token-reduction.md) +→ Full write-up incl. the measurement methodology: [Output token reduction](https://headroom-docs.vercel.app/docs/savings) diff --git a/RUST_DEV.md b/RUST_DEV.md index f2abab522..863ea61c1 100644 --- a/RUST_DEV.md +++ b/RUST_DEV.md @@ -288,9 +288,8 @@ doesn't rediscover them. ## Multi-worker deployment — CCR fragmentation -**Status:** PR-B7 (`REALIGNMENT/04-phase-B-live-zone.md`) introduced two -persistent CCR backends. The single-`--workers` recommendation no longer -applies once you select a persistent backend. +**Status:** two persistent CCR backends are available. The single-`--workers` +recommendation no longer applies once you select a persistent backend. ### Backend selection diff --git a/docs/auth-modes.md b/docs/auth-modes.md deleted file mode 100644 index 0fb8a9af8..000000000 --- a/docs/auth-modes.md +++ /dev/null @@ -1,132 +0,0 @@ -# Auth Modes - -Headroom classifies every inbound request into one of three **auth modes** at request entry. The mode drives every downstream compression, cache, and header policy decision. Detection is a pure function of HTTP headers — no I/O, no allocation beyond a single `to_lowercase` of the User-Agent, runs in <10us per call. - -The classifier ships in two equivalent implementations: - -- **Rust:** `crates/headroom-core/src/auth_mode.rs` (`classify`) -- **Python:** `headroom/proxy/auth_mode.py` (`classify_auth_mode`) - -Both are byte-for-byte identical on every header set covered by the parity test suite (`crates/headroom-core/tests/auth_mode.rs` + `tests/test_auth_mode.py`). - -## The three modes - -### `Payg` — pay-as-you-go API key - -| Signal | Examples | -|---|---| -| `Authorization: Bearer sk-ant-api*` | Anthropic PAYG key | -| `Authorization: Bearer sk-*` (excluding `sk-ant-oat-`) | OpenAI PAYG key | -| `x-api-key: ...` | Anthropic API key style | -| `x-goog-api-key: ...` | Google Gemini key | - -**Compression policy:** aggressive. The caller pays per token; compression directly saves them money. Cache hit-rate matters financially (Anthropic 1.25-2× cache write, 0.10× cache read). Live-zone compression, CCR, type-aware compressors all turn on. This is the OSS default. - -### `OAuth` — OAuth bearer / IAM-signed - -| Signal | Examples | -|---|---| -| `Authorization: Bearer sk-ant-oat-*` | Claude Pro / Max OAuth | -| `Authorization: Bearer ` (3-segment) | Codex / Cursor / Copilot OAuth | -| `Authorization: AWS4-HMAC-SHA256 ...` | Bedrock SigV4 | -| Any other non-`Bearer` Authorization scheme | Vertex ADC, custom proxies | - -**Compression policy:** passthrough-prefer. Per-token cost is opaque (subscription) or zero from the caller's POV (IAM-bound usage); compression value is **extending effective context within rate-limit / quota windows**, not saving money. Cache safety is paramount because OAuth scopes pin to `(account, model, session)` and beta-header drift can break OAuth-issued scopes. **No auto-`cache_control`, no auto-`prompt_cache_key`, no lossy compressors.** Lossless-only. - -### `Subscription` — UX-bound CLI / IDE - -| Signal | UA prefix | -|---|---| -| Claude Code | `claude-code/` | -| Claude CLI | `claude-cli/` | -| Codex CLI | `codex-cli/` | -| Cursor | `cursor/` | -| Claude VS Code | `claude-vscode/` | -| GitHub Copilot | `github-copilot/` | -| Anthropic CLI | `anthropic-cli/` | -| Antigravity | `antigravity/` | - -**Compression policy:** stealth. Provider rate-limits by request count; programmatic-fingerprint detection means Headroom MUST look like the upstream agent. Same compression policy as `OAuth` **plus**: - -- Preserve `accept-encoding` byte-for-byte. -- Never inject `X-Headroom-*` headers on upstream-bound requests. -- Never mutate `User-Agent`. -- Skip `X-Forwarded-*` headers on upstream-bound requests (see Phase F PR-F4). - -The Subscription UA wins over any bearer token shape — a Claude Code session that happens to carry a `sk-ant-oat-*` token is still a subscription client, never OAuth. - -## Detection signals — full decision order - -The classifier evaluates these in order; the **first** matching rule wins. - -1. **User-Agent contains a `SUBSCRIPTION_UA_PREFIXES` entry** → `Subscription`. -2. **`Authorization: Bearer sk-ant-oat-*`** → `OAuth`. -3. **`Authorization: Bearer sk-ant-api*` or `Bearer sk-*`** → `Payg`. -4. **`Authorization: Bearer `** (3 dot-separated segments) → `OAuth`. -5. **`Authorization` present but not `Bearer ...`** (e.g., `AWS4-HMAC-SHA256`) → `OAuth`. -6. **`x-api-key` present** → `Payg`. -7. **`x-goog-api-key` present** → `Payg`. -8. **Default** → `Payg`. - -The subscription-UA check is intentionally first because the same OAuth token shape appears in both Claude Pro (web) and Claude Code (CLI), and only the User-Agent disambiguates them. - -The "default to PAYG" rule is intentionally conservative: misclassifying a non-PAYG client as PAYG over-compresses, which only costs us a re-run; under-compressing a PAYG client leaves money on the table, which is worse for the OSS-default user. - -## How to extend - -### Adding a new subscription CLI - -Add the UA prefix to **both** files — they must agree: - -- `crates/headroom-core/src/auth_mode.rs` → `SUBSCRIPTION_UA_PREFIXES` -- `headroom/proxy/auth_mode.py` → `SUBSCRIPTION_UA_PREFIXES` - -Then add a parametrised parity test case in **both**: - -- `crates/headroom-core/tests/auth_mode.rs` → add a `#[test] fn ..._ua_classified_subscription`. -- `tests/test_auth_mode.py` → covered automatically by the existing `test_every_subscription_prefix_classified_subscription` parametrised test. - -### Adding a new OAuth token shape - -Add the prefix check **before** the `sk-` PAYG branch in both `classify` and `classify_auth_mode`. Order matters: any token shape that's a strict prefix of `sk-` must be checked first. - -### Making the prefix list user-configurable - -The list lives in a `const` so a future Phase F follow-up PR can swap it for a configurable source (env var, TOML config, CLI flag) without touching the function body. The recommended path: - -1. Read the list from `Config::subscription_ua_prefixes` (Rust) / `headroom.config.Settings.subscription_ua_prefixes` (Python). -2. Default to the current static list if unset. -3. Pass the list as a parameter to `classify` / `classify_auth_mode`. - -The classifier itself is a pure function — adding a parameter is a localized change. - -## Performance - -| Path | Per-call latency (p50) | -|---|---| -| Rust empty headers | ~20 ns | -| Rust PAYG (Bearer prefix match) | ~50 ns | -| Rust Subscription (UA lowercase + scan) | ~600 ns | -| Python empty headers | ~3 us | -| Python Subscription | ~12 us | - -All paths are well under the <10us Rust budget and the <100us Python budget asserted by the test suite. - -## Where the auth-mode value flows - -After classification, the value is stored on the request object so downstream code reads it without re-classifying: - -- **Rust:** `req.extensions_mut().insert(auth_mode)`. Read with `req.extensions().get::()`. -- **Python:** `request.state.auth_mode`. Read with `request.state.auth_mode`. - -A structured log line (`event = auth_mode_classified`) fires once per request at request entry; the value is logged as `auth_mode = "payg" | "oauth" | "subscription"`. - -## Phase F roadmap - -PR-F1 (this PR) lands the helper. The rest of Phase F wires it into specific policy gates: - -- **PR-F2:** per-mode compression policy gates (auto-`cache_control`, `prompt_cache_key`, lossy compressors). -- **PR-F3:** TOIN per-tenant aggregation key includes `(auth_mode, model_family, structure_hash)`. -- **PR-F4:** `X-Forwarded-*` skipped on Subscription mode. - -See `REALIGNMENT/08-phase-F-auth-mode.md` for the full phase plan. diff --git a/docs/bedrock.md b/docs/bedrock.md deleted file mode 100644 index c3a51bc45..000000000 --- a/docs/bedrock.md +++ /dev/null @@ -1,218 +0,0 @@ -# AWS Bedrock — Operator Guide - -Headroom's Rust proxy ships a native AWS Bedrock InvokeModel surface. After Phase D (PRs D1–D3), Anthropic-on-Bedrock requests are signed, compressed, and observed by the proxy directly — no LiteLLM Python shim on the request path. - -This document covers how to deploy the Bedrock-native surface, how compression policy is applied, and how to read the Prometheus metrics the proxy exports. - -## What's in scope - -| Capability | Status | -|---|---| -| `POST /model/{model}/invoke` | PR-D1 — native Rust handler | -| `POST /model/{model}/converse` | PR-D1 — same handler (Bedrock accepts both paths for the Anthropic envelope) | -| `POST /model/{model}/invoke-with-response-stream` | PR-D2 — binary EventStream parsed and translated to SSE | -| AWS SigV4 signing (post-compression) | PR-D1 | -| `AuthMode::OAuth` classification | PR-D3 — Bedrock IAM is OAuth-equivalent under the policy matrix | -| Per-model + per-region Prometheus metrics | PR-D3 — exposed at `GET /metrics` | -| OAuth compression policy gates (no auto cache_control, lossless-only) | Phase F PR-F2/F3 (gates the marker D3 wires) | - -## Running the proxy - -The native surface lives in the `headroom-proxy` binary, which ships in the published -container images (every `proxy`-extra tag) at `/usr/local/bin/headroom-proxy`. You can run -it directly from any published image — no separate build: - -```sh -docker run --rm -p 8787:8787 \ - -v "$HOME/.aws:/home/nonroot/.aws:ro" \ - -e HEADROOM_PROXY_AWS_PROFILE=my-profile \ - --entrypoint headroom-proxy \ - ghcr.io/chopratejas/headroom:latest \ - --listen 0.0.0.0:8787 \ - --upstream https://bedrock-runtime.us-east-1.amazonaws.com \ - --bedrock-region us-east-1 -``` - -The published images default to the `nonroot` user (home `/home/nonroot`), so AWS -credentials are mounted at `/home/nonroot/.aws` — that is where the SDK looks for -`~/.aws`. For a root-based image (`RUNTIME_USER=root` build), mount to `/root/.aws` -instead, or pass `--user root`. - -Then point the AWS SDK / CLI at the proxy: - -```sh -AWS_ENDPOINT_URL_BEDROCK_RUNTIME=http://localhost:8787 \ - aws bedrock-runtime invoke-model --model-id anthropic.claude-3-haiku-20240307-v1:0 ... -``` - -The proxy can also drop in front of the Python proxy (`--upstream http://127.0.0.1:8788`) -so non-Bedrock traffic is forwarded while Bedrock requests are signed + compressed -natively. The default `--enable-bedrock-native=true` mounts the Bedrock routes; everything -else is passed through to `--upstream`. - -## AWS credential configuration - -The proxy uses the [aws-config default credential chain](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html), resolved once at startup. - -The chain searches in this order, stopping at the first source that yields valid credentials: - -1. **Environment variables** — `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, optional `AWS_SESSION_TOKEN`. Useful for ECS task roles that inject creds via env or for `aws sts assume-role` shells. -2. **Shared credentials file** — `~/.aws/credentials`. Profile selected by `--aws-profile` (or `AWS_PROFILE`). Falls back to `[default]`. -3. **IAM instance profile / IMDS** — when running on EC2. -4. **ECS task role / EKS pod identity** — when running on the AWS-managed compute platforms. -5. **AWS SSO** — `~/.aws/sso/cache/...` when `aws sso login` has been run. - -If the chain does NOT resolve any credentials at startup, the proxy logs `event=bedrock_credentials_unavailable` at WARN and continues to start. Bedrock invoke routes will then return `500` with `event=bedrock_credentials_missing` per request — there is **no silent fallback to unsigned requests**, by design. - -### Required IAM permissions - -The proxy needs: - -- `bedrock:InvokeModel` for non-streaming -- `bedrock:InvokeModelWithResponseStream` for streaming - -Scope these to the specific model ARNs you intend to use. Example IAM policy snippet: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "bedrock:InvokeModel", - "bedrock:InvokeModelWithResponseStream" - ], - "Resource": [ - "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-haiku-20240307-v1:0", - "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-5-sonnet-20241022-v2:0" - ] - } - ] -} -``` - -## Region configuration - -```sh -headroom-proxy \ - --upstream http://unused-when-bedrock-only \ - --bedrock-region us-east-1 -``` - -| Flag | Env var | Default | Notes | -|---|---|---|---| -| `--bedrock-region` | `HEADROOM_PROXY_BEDROCK_REGION` (or `AWS_REGION`) | `us-east-1` | Drives both the SigV4 region and the derived endpoint hostname. | -| `--bedrock-endpoint` | `HEADROOM_PROXY_BEDROCK_ENDPOINT` | derived from region | Override for FIPS endpoints (`bedrock-runtime-fips.{region}.amazonaws.com`), VPC endpoints, or local mock servers. | -| `--aws-profile` | `HEADROOM_PROXY_AWS_PROFILE` | unset | Selects the named profile from the shared credentials file. | -| `--enable-bedrock-native` | `HEADROOM_PROXY_ENABLE_BEDROCK_NATIVE` | `true` | Set to `false` to mount no Bedrock routes at all (Bedrock requests will then fall through to the catch-all and fail without SigV4). | - -## Supported model IDs - -The proxy classifies model IDs by **literal vendor match** — no regexes. It strips a known cross-region inference-profile geo prefix (`eu.`, `us.`, `apac.`, `global.`) if present, then takes the leading dot-segment as the vendor. A model is treated as Anthropic-shape when that canonical vendor is `anthropic` — so both the bare `anthropic.…` foundation models and the geo-prefixed inference profiles (`eu.anthropic.…`, `us.anthropic.…`, `apac.anthropic.…`, `global.anthropic.…`) qualify. For those, the live-zone compression dispatcher runs over the body, the envelope is re-emitted with `anthropic_version` preserved as the first key, and the request is signed with SigV4. - -Examples that hit the Anthropic compression path: - -- `anthropic.claude-3-haiku-20240307-v1:0` (foundation model) -- `anthropic.claude-3-5-sonnet-20241022-v2:0` -- `eu.anthropic.claude-haiku-4-5-20251001-v1:0` (EU cross-region inference profile) -- `us.anthropic.claude-3-5-sonnet-20241022-v2:0` (US inference profile) -- `global.anthropic.claude-haiku-4-5-20251001-v1:0` - -Other Bedrock vendors (`amazon.titan-...`, `meta.llama3-...`, `cohere.command-...`, `ai21.j2-...`, `stability.stable-diffusion-...`, and their geo-prefixed inference profiles such as `eu.amazon.nova-...`) are signed and forwarded **without compression** — the proxy does not yet understand their body shapes and would risk corrupting them. These model IDs log `event=bedrock_compression_skipped, reason=non_anthropic_vendor` per request. Full Anthropic envelopes only. - -The contract: **any new model ID that AWS adds under the `anthropic.` vendor (as a bare prefix or behind a cross-region geo prefix) automatically picks up the full compression + signing pipeline.** No code change in the proxy is needed for new versions of Claude on Bedrock. - -## Compression behaviour - -Bedrock requests are subject to the **same** live-zone compression rules as direct Anthropic (`/v1/messages`): - -- Only the live-zone messages (latest user turn, latest tool/output blocks) are eligible for compression. -- The cache hot zone (older messages, system prompt, tools list) is byte-faithful passthrough. -- The dispatcher only mutates body bytes when at least one block compressed. The byte-equality invariant for unchanged blocks is enforced at `debug_assert!` granularity. - -### OAuth policy (PR-D3 → PR-F2/F3) - -The Bedrock auth-mode middleware classifies every Bedrock request as `AuthMode::OAuth`. Even when the inbound request has no Authorization header (the common case where the AWS SDK signs after our proxy), the middleware **coerces** to OAuth and emits `event=bedrock_auth_mode_unexpected` at WARN if F1's classifier disagreed — so the divergence is loud, not silent. - -Under the OAuth policy matrix (see `docs/auth-modes.md`): - -- **No auto-`cache_control` injection.** OAuth subscriptions pin the cache scope to `(account, model, session)`; auto-injecting markers can void cache hits. -- **No auto-`prompt_cache_key`.** Same reasoning. -- **Lossless-only compressors.** Lossy compressors (text rewriting, summarisation) are gated off for OAuth. - -PR-D3 lands the classification + the resulting `AuthMode` in `request.extensions()`. PR-F2 and PR-F3 wire the actual policy gates that read it. Until those PRs land, the Bedrock route uses the existing dispatcher (which is a no-op in `compression_mode=off`); the OAuth contract above is the documented forward direction. - -### Cache safety - -The bytes signed by SigV4 are exactly the bytes Bedrock receives — the signer hashes the post-compression body. There is no "sign before compress" shortcut that would produce a signature mismatched to the wire payload. Compression mutates the body once, then the signer runs once, then the bytes are forwarded once. - -## Prometheus metrics - -The proxy exposes a `GET /metrics` endpoint that serves the standard Prometheus text-format scrape. Three Bedrock-specific metric families are exported: - -| Metric | Type | Labels | Source | -|---|---|---|---| -| `bedrock_invoke_count_total` | Counter | `model`, `region`, `auth_mode` | One increment per `/model/.../invoke` (and `/converse` and `/invoke-with-response-stream`) request. | -| `bedrock_invoke_latency_seconds` | Histogram | `model`, `region` | Observed at request completion (success or failure). | -| `bedrock_eventstream_message_count_total` | Counter | `model`, `region`, `event_type` | One increment per parsed binary EventStream message in the streaming path. `event_type` is the `:event-type` header (`chunk`, `metadata`, `internalServerException`, etc.). | - -All labels are bounded by infrastructure config (`region` from `--bedrock-region`, `auth_mode` from the 3-variant enum) or by the path parameter (`model`, supplied by the axum extractor — never by user-controlled body bytes). Cardinality is bounded by deployment fan-out, not by traffic volume. - -### Sample PromQL queries - -**p99 latency by model:** -```promql -histogram_quantile( - 0.99, - sum by (model, le) (rate(bedrock_invoke_latency_seconds_bucket[5m])) -) -``` - -**Request rate by region (RPS):** -```promql -sum by (region) (rate(bedrock_invoke_count_total[1m])) -``` - -**EventStream message rate by event type (debugging the streaming path):** -```promql -sum by (event_type) (rate(bedrock_eventstream_message_count_total[1m])) -``` - -**Error breakdown by HTTP status (cross-references the structured logs `event=bedrock_upstream_error`):** -```promql -sum by (model) (rate(bedrock_invoke_count_total{auth_mode="oauth"}[5m])) - / sum by (model) (rate(bedrock_invoke_latency_seconds_count[5m])) -``` - -(The denominator is the total observed latency samples — useful for sanity-checking that every counted invoke also got a histogram observation. They should be equal.) - -### Structured-log correlation - -Every metric increment in the Bedrock path is paired with a `tracing::debug!` log line carrying: - -- `event = "metric_recorded"` -- `metric = "bedrock_invoke_count_total" | "bedrock_invoke_latency_seconds" | "bedrock_eventstream_message_count_total"` -- the same labels as the metric - -Enable with `RUST_LOG=headroom_proxy::observability=debug` for incident correlation. In normal operation keep this at the default `info` level — debug volume per request is bounded by the same cardinality the metric uses. - -## Live cloud validation - -The PR-D1, D2, D3 implementations are exercised end-to-end against a wiremock upstream (`crates/headroom-proxy/tests/integration_bedrock_*.rs`). The wiremock-based tests are the canonical correctness gate. - -A real Bedrock smoke test (`aws bedrock-runtime invoke-model ...` through the proxy) requires `bedrock:InvokeModel` permissions in the developer's AWS account. Set the proxy upstream to the proxy URL (`http://localhost:8787`) via the AWS SDK's `AWS_ENDPOINT_URL_BEDROCK_RUNTIME` env var: - -```sh -AWS_ENDPOINT_URL_BEDROCK_RUNTIME=http://localhost:8787 \ - aws bedrock-runtime invoke-model \ - --model-id anthropic.claude-3-haiku-20240307-v1:0 \ - --body '{"anthropic_version":"bedrock-2023-05-31","max_tokens":32,"messages":[{"role":"user","content":"hi"}]}' \ - /tmp/out.json -``` - -If the SDK signs the request before sending to the proxy, the proxy will see a SigV4 `Authorization` header and classify as OAuth via the standard rule. If the SDK is configured to sign downstream of the proxy (some IAM-instance-profile setups), the proxy still classifies as OAuth via the middleware's coerce-and-log fallback. - -## Rollback - -Set `--enable-bedrock-native=false` to unmount all Bedrock routes; the catch-all proxy then forwards Bedrock requests unchanged to `--upstream`. This is an emergency rollback only — without SigV4 re-signing, the catch-all path will fail closed unless the upstream is itself a Bedrock-aware proxy (e.g., the Python LiteLLM converter on a different port). diff --git a/docs/claude-code-vertex-headroom.md b/docs/claude-code-vertex-headroom.md deleted file mode 100644 index c8b0b655e..000000000 --- a/docs/claude-code-vertex-headroom.md +++ /dev/null @@ -1,163 +0,0 @@ -# Claude Code + Google Vertex AI, with Headroom compression - -*Validated end-to-end on 2026-06-19 (Claude Code 2.1.181, Headroom 0.27.0).* - -This is the **working, tested** way to run **Claude Code** against **Claude models on -Google Vertex AI** with **Headroom compressing the context** in the middle. - -## TL;DR - -Run Claude Code in **normal Anthropic mode** (NOT Vertex mode) pointed at a local -Headroom proxy, and let **Headroom** be the thing that talks to Vertex: - -``` -Claude Code ──ANTHROPIC_BASE_URL──▶ Headroom proxy ──LiteLLM (vertex_ai)──▶ Vertex AI - (normal mode) (plain http) (compresses) (your GCP ADC) (Claude) -``` - -Two non-obvious requirements make the difference between "works" and "silently does nothing": - -1. **`pip install "google-cloud-aiplatform>=1.38"`** into the proxy's environment — - LiteLLM's `vertex_ai` provider needs it, or every request 500s with - `No module named 'vertexai'`. -2. **Start the proxy with `--code-aware`** — coding sessions are mostly *source code*, - which routes to the AST/code-aware compressor. It is **disabled by default**, so - without this flag compression no-ops on code and you see `tokens_saved: 0`. - -## Why not "just point Claude Code's Vertex URL at Headroom"? - -That approach (Vertex mode + `ANTHROPIC_VERTEX_BASE_URL`=proxy) **does not work** with -Claude Code today. In Vertex mode Claude Code runs a **client-side `probeVertexModel` -check before any request**. When `ANTHROPIC_VERTEX_BASE_URL` points at a non-Google -host, that probe fails *instantly* (no network call is made) with a misleading -`"The model … is not available on your vertex deployment"`, and the proxy never -receives a byte. This is a Claude Code limitation, not a Headroom bug. The native -`:rawPredict` passthrough in Headroom is correct and compresses (verified by direct -curl) — but the client won't route to it. So we use the Anthropic-mode path below. - -## Prerequisites - -- **Google Cloud auth (ADC).** Run once: `gcloud auth application-default login` - (and `gcloud config set project `). The proxy uses ADC to call Vertex; no - API key is held by Headroom. A service-account JSON via - `GOOGLE_APPLICATION_CREDENTIALS` works too. -- **Vertex Claude quota** for the model + location you intend to use. Confirm with a - direct call before involving Headroom: - ```bash - ACCESS_TOKEN="$(gcloud auth application-default print-access-token)" - curl -sS -X POST \ - -H "Authorization: Bearer ${ACCESS_TOKEN}" -H "Content-Type: application/json" \ - "https://aiplatform.googleapis.com/v1/projects//locations/global/publishers/anthropic/models/claude-sonnet-4-6:rawPredict" \ - -d '{"anthropic_version":"vertex-2023-10-16","max_tokens":20,"messages":[{"role":"user","content":"hi"}]}' - ``` - HTTP 200 → good. 429 → model exists but no quota in that location. 404 → model not - enabled in that project/location. -- **Headroom ML extra** for compression: `pip install "google-cloud-aiplatform>=1.38"` - plus the Kompress ML stack (`torch`, `transformers`, `onnxruntime` — the - `headroom-ai[ml]` extra). The `kompress-v2-base` model downloads from Hugging Face - on first use. - -## Terminal 1 — start the Headroom proxy (Vertex backend) - -```bash -cd /path/to/headroom -source .venv/bin/activate - -export VERTEXAI_PROJECT= -export GOOGLE_CLOUD_PROJECT= -export VERTEXAI_LOCATION=global # match where your quota lives - -headroom proxy --port 8787 \ - --backend litellm-vertex_ai \ # NOTE: the _ai suffix is required - --region global \ # becomes LiteLLM vertex_location - --code-aware # REQUIRED for code compression -``` - -On startup, confirm components loaded: `curl -s localhost:8787/debug/warmup` should -show `kompress: loaded`, `code_aware: loaded`, `tree_sitter: loaded`, -`smart_crusher: loaded`. - -## Terminal 2 — run Claude Code (normal Anthropic mode) against the proxy - -```bash -cd /path/to/your/project - -export ANTHROPIC_BASE_URL=http://127.0.0.1:8787 -export ANTHROPIC_API_KEY=sk-placeholder-not-used # Claude Code needs *a* key to start -export ANTHROPIC_MODEL=claude-sonnet-4-6 # sent to Headroom, mapped to vertex_ai/claude-sonnet-4-6 -export ANTHROPIC_SMALL_FAST_MODEL=claude-sonnet-4-6 # pin background model to one you have quota for - -# Do NOT set CLAUDE_CODE_USE_VERTEX or ANTHROPIC_VERTEX_BASE_URL — those put Claude -# Code into Vertex mode and trigger the broken probe described above. - -claude -``` - -Claude Code now talks plain Anthropic `/v1/messages` to Headroom; Headroom compresses -and forwards to Vertex via LiteLLM, then translates the answer back. - -## Verify compression is happening - -- Dashboard: — "tokens saved" climbs as you work. -- `curl -s localhost:8787/stats` → `tokens.saved`, and `request_logs[].transforms_applied` - (look for `router:tool_result:mixed`, `kompress:*`, `code_aware:*`). -- Savings appear on **large tool outputs** (Bash/Grep/web fetches) and accumulate over - turns. Note: **`Read`/`Glob`/`Grep`/`Write`/`Edit` outputs are protected from the - ContentRouter by default** (safest for coding agents); stale `Read`s are handled - separately by the Read-lifecycle system. So the biggest wins come from non-excluded - large outputs and multi-turn sessions, not single one-shot reads. - -## What `--code-aware` does — and what it never touches - -**What it does.** Code-Aware is an **AST (tree-sitter) compressor for source code that -passes through the proxy inside a request**. It parses the code, **keeps the structure -that matters** — imports, function/class signatures, type annotations, error handlers — -and **shrinks the less-important function bodies**, always emitting **syntactically -valid code** (the output still parses). Languages: Python, JS, TS (tier 1); Go, Rust, -Java, C, C++ (tier 2). The original is **stored for retrieval (CCR, ~5-minute TTL)**, so -if the model needs the exact bytes it can pull them back via the `headroom_retrieve` -tool — compression is reversible, not destructive. - -**What it does NOT touch:** - -- **Your files on disk.** Headroom is a network proxy: it only rewrites the *request - body* in flight on the way to Vertex. It never reads, writes, or modifies any local - file. Code-Aware operates on text that is *already inside the API request*, not on - your repository. -- **Claude Code's `Read` tool output.** `Read`, `Glob`, `Grep`, `Write`, and `Edit` - are in `DEFAULT_EXCLUDE_TOOLS` and are **protected from the ContentRouter by default** - (`protect_recent_reads_fraction = 0.0` ⇒ protect-all). So when Claude Code opens a - file the normal way, **the model sees it verbatim** — Code-Aware does not alter it. - (Stale `Read`s — files you later edit — are handled separately and reversibly by the - Read-lifecycle, replacing the superseded copy with a retrievable marker.) - -**Where it actually applies:** code that reaches the model through *other* channels — -most commonly **`Bash` output that prints code** (`cat file.py`, `sed`, `nl`, build -logs with snippets) or large code in results from non-excluded/custom tools. That is -the content that gets AST-compressed. In the validation run, the ~22% savings came -exactly from two `Bash` commands that dumped source files — not from `Read`. - -**Net:** with the default config your real file reads and edits go to the model -untouched; Code-Aware only trims bulky *incidental* code (shell dumps, logs, pasted -snippets) and keeps the originals retrievable. Omit `--code-aware` if you want zero -code transformation at all (you lose code compression but keep everything else). - -## Model-string notes (Vertex) - -- Headroom maps clean ids to Vertex publisher ids: `claude-sonnet-4-6` → - `vertex_ai/claude-sonnet-4-6` (see `headroom/backends/litellm.py`). Newer models use - the bare alias; older ones are date-pinned (e.g. `claude-sonnet-4-5@20250929`). -- `--region global` works (LiteLLM targets the `aiplatform.googleapis.com` global - endpoint). Use a specific region (`us-east5`, `europe-west1`, …) only if that's where - your quota is. - -## Troubleshooting - -| Symptom | Cause | Fix | -|---|---|---| -| `500 … No module named 'vertexai'` | LiteLLM vertex provider dep missing | `pip install "google-cloud-aiplatform>=1.38"`, restart proxy | -| `tokens_saved: 0` on code | Code-Aware disabled | start proxy with `--code-aware` | -| `tokens_saved: 0` everywhere, `/debug/warmup` shows `kompress: not installed` | ML extra missing | install `headroom-ai[ml]` (torch/transformers/onnxruntime) | -| `"model … not available on your vertex deployment"`, proxy logs nothing | Claude Code is in Vertex mode (probe) | unset `CLAUDE_CODE_USE_VERTEX` / `ANTHROPIC_VERTEX_BASE_URL`; use Anthropic mode above | -| `429 RESOURCE_EXHAUSTED` | no quota in that location | switch `--region`/`VERTEXAI_LOCATION` to where your quota is | -| `404 Publisher Model not found` | model not enabled in project/location | enable it in Vertex Model Garden / request quota | diff --git a/docs/content/docs/configuration.mdx b/docs/content/docs/configuration.mdx index 15d51e8f5..da88261d9 100644 --- a/docs/content/docs/configuration.mdx +++ b/docs/content/docs/configuration.mdx @@ -233,7 +233,7 @@ headroom proxy --learn --min-evidence 3 | `HEADROOM_STATELESS` | Set to `true` to disable filesystem writes | `false` | | `HEADROOM_MODEL_LIMITS` | Custom model config (JSON string or file path) | -- | | `HEADROOM_BASE_URL` | Base URL of the Headroom proxy (TypeScript SDK) | `http://localhost:8787` | -| `HEADROOM_API_KEY` | API key for Headroom Cloud authentication | -- | +| `HEADROOM_API_KEY` | Optional API key for authenticated Headroom endpoints (TypeScript SDK) | -- | | `HEADROOM_CONFIG_DIR` | Canonical config (read-mostly) root. Derives `models.json` and per-plugin config paths when set. | `~/.headroom/config` | | `HEADROOM_WORKSPACE_DIR` | Canonical workspace (read-write state) root. Derives savings, memory DB, logs, TOIN, subscription state, and more when set. | `~/.headroom` | | `HEADROOM_SAVINGS_PATH` | Override persistent savings file location. Always wins when set. | derived from `${HEADROOM_WORKSPACE_DIR}` | diff --git a/docs/cortex-code.md b/docs/cortex-code.md deleted file mode 100644 index 3d93d7afe..000000000 --- a/docs/cortex-code.md +++ /dev/null @@ -1,247 +0,0 @@ -# Cortex Code + Headroom — Integration Guide - -Headroom compresses the context Cortex Code (CoCo) sends to `claude-sonnet-4-6` -before it reaches the Snowflake Cortex inference endpoint. The result is 60–65% -fewer prompt tokens billed, with the same answers. - -## Benchmark (measured, not estimated) - -Token counts are from `usage.prompt_tokens` in the actual Snowflake Cortex API -response — not headroom's local estimate. - -| Payload | Before | After | Saved | -|---|---:|---:|---:| -| Full CoCo session (tables + dbt + search) | 17,827 | 6,781 | **62%** | -| `INFORMATION_SCHEMA` tables (79 rows) | 10,161 | 3,979 | **61%** | -| `dbt` run-results (40 models) | 4,968 | 1,927 | **61%** | -| Cortex Search results (15 docs) | 2,764 | 956 | **65%** | - -At 1,000 calls/day: **~$16/day saved**, **~$6,000/year saved**. - -> Numbers above are per-call averages across the four benchmark payloads. -> The full-session payload alone saves ~$33/1,000 calls/day. - -## How it works - -``` -CoCo (cortex CLI) - │ OPENAI_BASE_URL=http://127.0.0.1:8787/v1 - ▼ -Headroom proxy (local, your data never leaves your machine) - │ SmartCrusher compresses JSON context - │ CacheAligner stabilises KV-cache prefixes - ▼ -Snowflake Cortex /api/v2/cortex/inference:complete - │ claude-sonnet-4-6 - ▼ -Response (same answer, fewer billed tokens) -``` - -Headroom's **SmartCrusher** targets the large JSON blobs that CoCo produces: -`INFORMATION_SCHEMA` query results, `dbt` run-results, Cortex Search payloads, -and schema introspection output. These are highly repetitive structures that -compress 60–99% without any loss of information. - -## Quick start - -```bash -pip install "headroom-ai[all]" -headroom wrap cortex-code # starts proxy + prints the env var to set -``` - -`headroom wrap cortex-code` starts the local proxy and prints: - -``` - Headroom proxy is running. Configure Cortex Code (CoCo): - - Set the following environment variable before launching cortex: - OPENAI_BASE_URL=http://127.0.0.1:8787/v1 -``` - -Then in a new shell: - -```bash -OPENAI_BASE_URL=http://127.0.0.1:8787/v1 cortex -``` - -Or add it to your shell profile so it applies to every CoCo session: - -```bash -# ~/.zshrc or ~/.bashrc -export OPENAI_BASE_URL=http://127.0.0.1:8787/v1 -``` - -## Manual proxy startup - -If you prefer to manage the proxy lifecycle yourself: - -```bash -# Terminal 1 — start the proxy -headroom proxy --port 8787 - -# Terminal 2 — launch CoCo through the proxy -OPENAI_BASE_URL=http://127.0.0.1:8787/v1 cortex -``` - -Point the proxy at your Snowflake Cortex endpoint explicitly with -`--openai-api-url`: - -```bash -headroom proxy \ - --port 8787 \ - --openai-api-url https://.snowflakecomputing.com -``` - -## Library mode (inline, no proxy) - -If you are building an application on top of the Snowflake Cortex REST API -and want to compress context before every call: - -```python -from headroom import compress -import json, urllib.request - -# Build your messages (large JSON tool results, search results, etc.) -messages = [ - {"role": "system", "content": json.dumps(cortex_search_results, indent=2)}, - {"role": "assistant", "content": "I have reviewed the context."}, - {"role": "user", "content": "What is failing and how do I fix it?"}, -] - -# Compress before sending — local, no API call, no data leaves your machine -result = compress(messages, model="claude-sonnet-4-6") -print(f"Saved {result.tokens_saved} tokens ({result.tokens_saved / result.tokens_before:.0%})") - -# Send compressed messages to Snowflake Cortex REST API -response = call_cortex(result.messages, token=sf_token) -``` - -### What to put in the system message - -The Snowflake Cortex REST API supports `system`, `user`, and `assistant` roles. -For maximum compression, inject large retrieved context into `system`: - -```python -# Query results, search results, schema — these compress 60–99% -system_context = { - "tables": json.loads(show_tables_result), - "search_results": cortex_search_results, - "schema": describe_table_result, - "dbt_results": dbt_run_results_json, -} -messages = [ - {"role": "system", "content": json.dumps(system_context, indent=2)}, - {"role": "assistant", "content": "Context loaded."}, - {"role": "user", "content": user_question}, -] -result = compress(messages, model="claude-sonnet-4-6") -``` - -## Authentication - -Cortex Code authenticates using your Snowflake connection. Headroom sits -between CoCo and the Cortex endpoint and forwards auth headers unchanged — -it never reads or stores your credentials. - -If you use `snowflake-connector-python` directly, keep the connection open -while making API calls; closing it invalidates the OAuth session token: - -```python -import snowflake.connector, sys, io - -# Suppress connector's browser-auth console output -_s = sys.stdout; sys.stdout = io.StringIO() -conn = snowflake.connector.connect(connection_name="my_connection") -token = conn.rest.token -sys.stdout = _s - -# Make all API calls while conn is open, then: -conn.close() -``` - -## Per-project savings attribution - -Use `headroom wrap cortex-code --project ` to attribute savings to a -specific project in the headroom dashboard: - -```bash -headroom wrap cortex-code --project my-dbt-project -``` - -The dashboard at `http://127.0.0.1:8787` shows per-project token and cost -savings across all your CoCo sessions. - -## Verifying savings - -After a CoCo session, check what headroom saved: - -```bash -headroom perf # token savings for the last session -headroom perf --hours 24 # last 24 hours -``` - -Or run the included end-to-end benchmark against your own Snowflake account: - -```bash -# Measures real usage.prompt_tokens from claude-sonnet-4-6 -python3 tests/e2e_cortex_savings.py -``` - -## Testing - -Unit tests for the provider slice: - -```bash -uv run --with pytest pytest tests/test_provider_cortex_code.py -v -``` - -Compression benchmark (no API key needed — local only): - -```bash -uv run --with pytest pytest tests/test_cortex_code_compression.py -v -s -``` - -Real E2E test against Snowflake Cortex (requires Snowflake connection): - -```bash -python3 tests/e2e_cortex_savings.py -``` - -## How the provider is implemented - -Cortex Code routes through headroom's OpenAI-compatible pipeline. The provider -slice lives in `headroom/providers/cortex_code/`: - -| File | Purpose | -|---|---| -| `runtime.py` | `proxy_base_url(port)` → `http://127.0.0.1:{port}/v1`; `default_api_url()` reads `SNOWFLAKE_HOST` / `SNOWFLAKE_ACCOUNT` | -| `install.py` | `build_install_env()` → `{"OPENAI_BASE_URL": ...}`; `render_setup_lines()` | -| `__init__.py` | Public exports | - -Registered in `headroom/providers/install_registry.py` under the key -`"cortex-code"`, which is what `headroom wrap cortex-code` resolves to. - -## Limitations - -- The Snowflake Cortex REST API at `/api/v2/cortex/inference:complete` does not - support `role: "tool"` messages or OpenAI-style `tool_calls`. Use the - `system` message to inject large retrieved context (where SmartCrusher - achieves the highest compression ratios). - -- The headroom proxy cannot rewrite the Cortex inference path - (`/api/v2/cortex/inference:complete` ≠ `/v1/chat/completions`), so - **library mode** (`from headroom import compress`) is required when calling - the Cortex REST API directly. The proxy mode works for any - OpenAI-compatible client that points at Cortex via a gateway that exposes - `/v1/chat/completions`. - -- Output-token reduction (`HEADROOM_OUTPUT_SHAPER=1`) is supported in proxy - mode. In library mode only input compression applies. - -## See also - -- [Architecture](ARCHITECTURE.md) -- [Proxy configuration](proxy.md) -- [CCR — reversible compression](ccr.md) -- [Claude Code + Vertex](claude-code-vertex-headroom.md) -- [Benchmarks](benchmarks.md) diff --git a/docs/output-token-reduction-guide.md b/docs/output-token-reduction-guide.md deleted file mode 100644 index 5a54f21d0..000000000 --- a/docs/output-token-reduction-guide.md +++ /dev/null @@ -1,145 +0,0 @@ -# Output Token Reduction — User Guide - -A plain-English guide to cutting the tokens the model **writes back**. - -## Why this exists - -Headroom normally shrinks the prompt you **send**. This feature shrinks what the -model **returns**. That matters because: - -- Output tokens cost **5× more** than input on Opus-class models. -- A lot of model output is waste: "Great, let me help with that…" intros, - re-printing code you already showed it, restating tool results, and long - internal "thinking" even on trivial steps. - -You don't change any code. It runs in the Headroom proxy. - -## Turn it on - -```bash -export HEADROOM_OUTPUT_SHAPER=1 # off by default -headroom proxy --port 8787 -``` - -> **If a proxy is already running** (e.g. `headroom wrap claude` attaches to one -> on port 8787 instead of starting a fresh one), it reads this switch from the -> environment it was launched with — so exporting it afterwards wouldn't reach -> it. `headroom wrap` handles this for you: it hot-syncs your current output -> settings to the running proxy (loopback `POST /admin/runtime-env`), applied -> immediately with no restart. Set the variables before you run `wrap`. Because -> one proxy is shared by every session attached to it, these settings are global -> — the most recent explicit value wins. - -That's it. Two things now happen on every request: - -1. **Verbosity steering** — a short "be terse, don't restate context" instruction - is added to the **end** of the system prompt. (The end, so your prompt cache - still works.) -2. **Effort routing** — if a turn is just the model continuing after a tool ran - (e.g. it read a file and there were no errors), Headroom turns the model's - "thinking effort" down for that one turn. Real questions and error-handling - turns keep full effort. - -## The verbosity dial (levels 0–4) - -| Level | What the model is told | Good for | -|------:|------------------------|----------| -| 0 | (off) | disable steering | -| 1 | Skip the intro/outro chit-chat | people who read everything | -| 2 | Also: don't restate code/output already on screen | **default** — safe | -| 3 | Also: conclusions only, skip the reasoning | people who skim | -| 4 | Bare minimum, fragments OK | maximum savings, terse | - -Set it by hand if you want: - -```bash -export HEADROOM_VERBOSITY_LEVEL=3 -``` - -Or — better — let Headroom learn it from your habits (next section). - -## Let Headroom pick the level for you - -People rarely *say* "be brief." They *show* it: they interrupt long answers, or -reply so fast they couldn't have read the whole thing. `headroom learn ---verbosity` reads your past sessions and picks a level from those signals. - -```bash -# Preview what it found (doesn't change anything) -headroom learn --verbosity - -# Save it — the proxy uses this level from now on -headroom learn --verbosity --apply -``` - -Example output: - -``` -Verbosity — headroom - Interrupts: 29 (11% of turns) ← push-back signal - Fast-skips: 31 / 119 long answers (26% unread) ← strongest signal - >> Recommended verbosity level: 3 (confidence: high) -``` - -Add `--llm-judge` to have an LLM double-check the level (needs an API key). - -## See how much you saved - -Here's the honest part. We **can't directly measure** output savings — we never -see what the model *would* have written without our nudge. So Headroom reports an -**estimate with a confidence range**, never a fake exact number: - -```bash -headroom output-savings -``` - -``` -Output-token reduction - Method: ESTIMATED (synthetic control) - Requests: 1,240 shaped - Saved: ~410,000 output tokens - Reduction: 28.0% (95% CI 24.1% … 31.9%) -``` - -- **ESTIMATED** = compared against a baseline of your past (unshaped) sessions. -- **MEASURED** = the gold standard, if you opt into a holdout (below). - -### Want a *measured* number? - -Leave a slice of traffic unshaped as a control group: - -```bash -export HEADROOM_OUTPUT_HOLDOUT=0.1 # 10% of conversations stay unshaped -``` - -Now `headroom output-savings` compares shaped vs unshaped directly and reports a -**measured** reduction. The trade-off: you give up the savings on that 10%. - -## On the dashboard - -Open `http://localhost:8787/dashboard`. Next to the input-compression card -you'll see an **Output Tokens Saved** card showing the token count, the percent, -a `measured`/`estimated` badge, and the confidence range. - -## FAQ - -**Will this make answers worse?** -At level 2 (default), no — in our tests the model finds the same bugs and writes -the same fixes; it just stops re-printing code and skipping the "let me…" intro. -Levels 3–4 are terser by design; that's why learning the level per user matters. - -**Does it break prompt caching?** -No. The steering text is added at the *end* of the system prompt and is -byte-stable, so your cached prefix is untouched. - -**Is it safe with extended thinking / tool loops?** -Yes. It never disables thinking outright (that can error), it only lowers effort -on routine turns, and it never adds settings the model doesn't support. - -**How do I turn it off?** -Unset `HEADROOM_OUTPUT_SHAPER` (or set it to `0`) and restart the proxy. You can -also send `x-headroom-bypass: true` on a request to skip it for that call. - ---- - -Deep dive (design + the counterfactual math): [`proposals/output-token-reduction.md`](proposals/output-token-reduction.md) diff --git a/docs/proposals/output-token-reduction.md b/docs/proposals/output-token-reduction.md deleted file mode 100644 index c768e5f35..000000000 --- a/docs/proposals/output-token-reduction.md +++ /dev/null @@ -1,461 +0,0 @@ -# Output Token Reduction - -**Branches:** `feat/output-token-reduction` (Phase 1) → `feat/verbosity-learning-and-counterfactual` (Phase 2). -**Status:** Phase 1 (output shaper) and Phase 2 (`learn --verbosity`, AIMD controller, counterfactual estimator, dashboard) both implemented + tested. Runtime AIMD signal-capture is staged (controller built/tested, live emission off by default). - -See **§7** for the counterfactual measurement methodology (how we honestly report a number we can't directly observe). - ---- - -## 1. The problem in one line - -Headroom's entire transform pipeline compresses what goes **into** the model. -Nothing today touches what comes **out**. But output tokens are billed at -5× input on Opus-class models ($25 vs $5 per MTok on `claude-opus-4-8`), and in -agentic coding loops a large fraction of the bill is output: thinking tokens, -restated code, ceremony ("Great, let me…"), and full-file rewrites where a -10-line edit would do. - -**The constraint that shapes everything:** the proxy never generates output -tokens — the model does. Once a token is streamed it is already billed. So -every output-token lever is **request-side**: change what we ask for, cap what -we allow, or avoid the generation entirely. There is no post-hoc lever. - -That gives three lever families plus a learning loop: - -| Lever | Mechanism | Status | -|---|---|---| -| **Verbosity steering** | Append a terse-style instruction to the system-prompt tail | ✅ built | -| **Effort routing** | Lower `output_config.effort` on mechanical turns | ✅ built | -| **Thinking-budget clamp** | Clamp legacy `thinking.budget_tokens` on mechanical turns | ✅ built | -| **Per-user learned level** | Mine past sessions for the right verbosity per user (`learn --verbosity`) | ✅ built | -| **Counterfactual estimator** | Honestly estimate output tokens saved + dashboard surfacing | ✅ built | -| **Runtime AIMD auto-tune** | Adjust level live from interrupt / skip signals | 🟡 controller built/tested; live signal emission off by default | - ---- - -## 2. Phase 1 — the output shaper (built) - -### 2.1 What it is - -`headroom/proxy/output_shaper.py` — a request-body rewriter invoked in -`handle_anthropic_messages` after every other body mutation (so the turn -classifier sees the final message list) and gated behind the same -`x-headroom-bypass` header as compression. Opt-in via `HEADROOM_OUTPUT_SHAPER=1`. - -### 2.2 Lever A — verbosity steering - -A deterministic instruction block is appended to the **tail** of the system -prompt. Five levels, cumulative: - -- **L0** — off (touch nothing). -- **L1** — no ceremony: skip preamble/postamble, don't announce what you're about to do. -- **L2** — L1 + no echo: never restate code/diffs/tool output already in context; reference by path:line; don't narrate tool results. **(default)** -- **L3** — L2 + conclusions only, omit rationale unless asked, prefer smallest edit. -- **L4** — caveman: fragments, minimum tokens, nothing but the answer. - -**Why the tail, not the head.** Prompt caching is a prefix match — any byte -change ahead of a `cache_control` breakpoint invalidates everything after it. -Prepending steering text would bust the provider prefix cache and cost more -than it saves. Appending after the last system block leaves the cached prefix -byte-identical; only the small, byte-stable steering block is reprocessed. The -steering text is frozen per level and applied idempotently (sentinel-tagged), -so repeated requests keep an identical prefix and a level change replaces the -block in place rather than stacking. - -### 2.3 Lever B — effort routing - -In an agentic loop, most API calls are **mechanical continuations**: the last -message is a clean `tool_result` (a file read, a passing test) and the model is -just resuming. Harnesses like Claude Code pin `output_config.effort` at `xhigh` -for *every* turn, including these — and effort drives thinking depth, which -bills as output. The router lowers effort to `low` on mechanical turns only. - -Turn classification is **purely structural** — no content regexes, no keyword -lists (per the project's no-hardcoded-patterns rule): - -| Last user message contains… | Classification | Action | -|---|---|---| -| Any text / image / document block | `NEW_USER_ASK` | leave effort alone | -| Only `tool_result`, none `is_error` | `MECHANICAL_CONTINUATION` | lower effort → `low` | -| Any `tool_result` with `is_error: true` | `ERROR_CONTINUATION` | leave effort alone (model must reason about the failure) | -| Anything else | `UNKNOWN` | leave alone | - -### 2.4 Lever C — legacy thinking-budget clamp - -On older models still sending `thinking: {type: "enabled", budget_tokens: N}`, -the router clamps `N` to the API floor (1024) on mechanical turns. The `type` -field is **never** toggled. - -### 2.5 Safety rules (each prevents a concrete failure) - -1. **Never inject `output_config.effort` where the client didn't send it.** - Models without effort support return 400 on it. Lowering an - already-present value is always valid — its presence proves the target - model accepts the param. -2. **Never toggle `thinking.type`.** Disabling thinking while history carries - thinking blocks 400s on some models, and the toggle busts the messages - cache tier (per the caching invalidation hierarchy). -3. **Byte-stable, idempotent steering** — repeated requests keep an identical - prefix; cache stays warm. -4. **Respect `x-headroom-bypass`** — sub-agent calls that opt out of - compression also opt out of shaping. - -### 2.6 Configuration - -| Env var | Default | Meaning | -|---|---|---| -| `HEADROOM_OUTPUT_SHAPER` | off | master switch (`1`/`true`/`yes`) | -| `HEADROOM_VERBOSITY_LEVEL` | `2` | 0–4 (clamped) | -| `HEADROOM_EFFORT_ROUTER` | on | set `0` to disable effort routing | -| `HEADROOM_MECHANICAL_EFFORT` | `low` | floor effort for mechanical turns | - -### 2.7 Tests - -`tests/test_output_shaper.py` — 34 tests, all passing. Covers turn -classification (every block-type path), cache-safe steering (string→block -conversion, append-after-`cache_control`, idempotency, level change), -effort routing (lower / never-inject / untouched-on-non-mechanical / -configurable target), legacy budget clamp, and the env gate. Ruff + mypy clean. - ---- - -## 3. Live before/after results - -Measured against `claude-opus-4-8` via `scripts/eval_output_shaper.py`, -comparing the exact body a client sends vs. the body the proxy forwards. -`usage.output_tokens` includes thinking. - -### 3.1 Verbosity steering — complex code-review ask - -Prompt: "review this TTLCache, find every bug, show fixes." - -| Condition | Mean output tokens | Reduction | -|---|---|---| -| Baseline | ~1,800–1,930 | — | -| L2 (no ceremony, no echo) | ~1,180–1,470 | **−22% to −39%** | -| L3 (conclusions only) | ~670 | **−63%** | - -**Quality check — same bugs found, only redundancy removed.** The baseline -opens with a title + "Let me go through them," finds the bugs, **re-prints the -entire fixed class**, then adds a **summary table restating all six bugs**, -then a trailing notes section — the same information appears ~2.5×. L2 opens -directly with the findings, gives the same fixed code block once, and stops. -Both correctly identify the no-locking race, `popitem(last=True)` evicting the -wrong end, and the mutate-during-iteration `RuntimeError`. Nothing of substance -is lost at L2; L3 additionally drops rationale prose (only for users who don't -read explanations). - -### 3.2 Effort routing — agentic mechanical continuation - -Transcript ending in a clean `tool_result`, `effort: xhigh` the way Claude Code -sends it. - -| Condition | Mean output tokens | Reduction | -|---|---|---| -| Baseline (xhigh) | ~1,120 | — | -| Shaped (routed to low) | 793 | **−29%** | - -### 3.3 Honest framing - -Caveman (L4) would get ~60–70% but degrades the experience. The taxonomy-driven -default (L2 + effort routing on mechanical turns) gets a realistic **25–40%** -with the user barely noticing. The learning loop (Phase 2) finds where each -user sits between those poles. - ---- - -## 4. Phase 2 — learning the right level per user - -### 4.1 Why this is necessary - -The right verbosity is **per-user**, not global. A fixed `HEADROOM_VERBOSITY_LEVEL` -is a guess. We can do better: mine the user's own past sessions to infer what -they actually tolerate — exactly the philosophy of `headroom learn`, which -already reads `~/.claude/projects/*.jsonl` and turns history into learned -context. - -### 4.2 The key insight (validated on real data) - -I prototyped the signal extraction and ran it over **24 real sessions** for -this project. The finding that shapes the whole design: - -| Signal | This user's data | Carries signal? | -|---|---|---| -| Explicit "be brief" keywords | **1** of 210 human msgs | ❌ almost none | -| Explicit "explain more" keywords | **1** of 210 | ❌ almost none | -| **Interruptions** (user cuts Claude off) | **29** (~1 per 7 turns) | ✅ strong | -| **Fast-skips** (reply <30s after a >250-word answer) | **15 of 100 long outputs** | ✅ strong | -| Long-output frequency | 100 outputs >250 words | ✅ context | - -**Users almost never *say* what verbosity they want — they show it -behaviorally.** Keyword matching (the obvious approach) is nearly empty. The -behavioral signals are rich. The strongest is **fast-skip**: a reply arriving -faster than the answer could have been read is a direct measurement of -"generated tokens nobody consumed," computable from timestamps + lengths -already in the JSONL. - -For this user — 29 interrupts, 15% unread-long-output rate, zero "explain more" -requests — the data reads as a clear **L2, arguably L3** user. - -### 4.3 Design — `headroom learn --verbosity` - -Slots into the existing `learn` architecture. `headroom/learn/plugins/claude.py` -already parses the JSONL; `analyzer.py` already does cheap-extraction → digest → -LLM-returns-JSON. We add a verbosity analysis path: - -**Step 1 — structural pass (pure Python, no patterns).** Per session, compute: -- **interrupt rate** — `[Request interrupted by user…]` markers per human turn -- **fast-skip rate** — human reply latency vs. preceding assistant output length -- **long-output frequency** — share of assistant texts over N words -- **echo ratio** — n-gram overlap between assistant output and prior context (restated code) -- reply-latency distribution vs. output length - -All mechanical, all from data already on disk. (Prototype: -`scripts/verbosity_scan.py`, validated above.) - -**Step 2 — LLM judgment pass (mirrors today's `learn`).** Feed a digest of -human messages + the structural stats to the analyzer LLM with one question: -*"Does this user read long explanations, and when they push back, is it for -more detail or less?"* This replaces brittle keyword lists with judgment — -consistent with the no-hardcoded-patterns rule. Returns a level + confidence + -rationale as JSON. - -**Step 3 — output (this is what `--verbosity` produces).** See §4.4. - -**Step 4 — runtime AIMD auto-tune.** The offline pass sets the *starting* level; -a live loop tracks drift. An interrupt or fast-skip nudges the level up one; an -"explain"/"why" follow-up drops it back. Hysteresis (require 2–3 consistent -signals before moving) prevents oscillation. Like TCP congestion control: probe -toward terser, back off on a "too terse" signal. - -### 4.4 What `--verbosity` outputs — and how it helps - -The command produces three concrete artifacts: - -**(a) A human-readable report (stdout):** -``` -Verbosity analysis — /Users/tcms/demo/headroom (24 sessions, 210 turns) - - Interrupts: 29 (1 per 7.2 turns) ← strong "too much" signal - Fast-skips: 15 / 100 long outputs ← 15% of long answers unread - Explicit brevity: 1 explicit verbose: 1 ← behavioral, not stated - - LLM read: "User interrupts frequently and rarely reads long - explanations; pushes back for less, never more detail." - - Recommended verbosity level: 2 (confidence: high) - Estimated output-token reduction at L2: ~25–35% -``` - -**(b) A persisted setting** written to `~/.headroom/` (alongside the existing -savings tracker) — per-project verbosity level + confidence: -```json -{"project": "/Users/tcms/demo/headroom", - "verbosity_level": 2, "confidence": "high", - "signals": {"interrupt_rate": 0.138, "fast_skip_rate": 0.15}, - "learned_at": "2026-06-12T…"} -``` - -**(c) The shaper reads it as its default.** `OutputShaperSettings.from_env()` -gains a fallback: if `HEADROOM_VERBOSITY_LEVEL` is unset, load the learned -per-project level instead of the hardcoded `2`. So **the output of `--verbosity` -directly becomes the live verbosity the proxy applies** — no manual tuning. - -**How it helps, concretely:** -1. **Removes the guess.** Today you set `HEADROOM_VERBOSITY_LEVEL=2` by hand. - After `learn --verbosity`, the level is derived from *your* behavior — a - heavy-interrupter gets L3, a "read everything" user gets L1. -2. **Per-project, not global.** Your exploratory side-project and your - production repo can carry different levels. -3. **Justified, not magic.** The report shows the signals and the LLM's read, - so the recommendation is auditable (matches the dashboard philosophy of - showing directional data, not opaque scores). -4. **Seeds the runtime loop.** The learned level is the AIMD starting point; - live signals refine it without re-running the offline pass. - -### 4.5 Mapping signals → level (initial heuristic, LLM-refined) - -| Interrupt rate | Fast-skip rate | "explain more" present | → Level | -|---|---|---|---| -| low | low | yes | 1 | -| low–med | low–med | no | 2 | -| high | high | no | 3 | -| very high | very high | no | 4 (offer, don't auto-apply) | - -The LLM judgment pass adjusts this — the table is the prior, not the verdict. - ---- - -## 5. Files - -| File | Status | Purpose | -|---|---|---| -| `headroom/proxy/output_shaper.py` | ✅ built | the shaper (steering + effort routing) | -| `headroom/proxy/handlers/anthropic.py` | ✅ wired | invoke shaper after body mutations | -| `tests/test_output_shaper.py` | ✅ 34 passing | unit coverage | -| `scripts/eval_output_shaper.py` | ✅ built | live before/after eval | -| `scripts/verbosity_scan.py` | 🔬 prototype | session-mining signal extraction | -| `headroom/learn/plugins/claude.py` (+ analyzer) | 🔜 extend | `--verbosity` analysis path | -| `~/.headroom/verbosity.json` | 🔜 | persisted per-project learned level | - ---- - -## 6. Roadmap - -1. ✅ **Measure** — live eval establishes the realistic ceiling and baseline. -2. ✅ **Effort router** — biggest win per unit risk, fully mechanical, invisible. -3. ✅ **Verbosity ladder at fixed L2** — safe default, cache-safe tail injection. -4. 🔜 **`learn --verbosity`** — derive the per-user starting level from sessions. -5. 🔜 **Runtime AIMD auto-tune** — refine the level live from interrupt/skip signals. -6. 🔭 **Waste taxonomy on the dashboard** — echo ratio, ceremony ratio, - full-file-rewrite detection, as token counts (no dollar estimates). -7. 🔭 **Budget whispering** — tell the model its token budget per turn-type, - sized from the historical output distribution in SQLite. - ---- - -## 7. Counterfactual measurement — how we show a % we can't directly observe - -This is the hard part, and it deserves its own section. - -### 7.1 Why output savings are not directly measurable - -Input compression is a **pure function**: Headroom takes a request, shrinks it, -and can count `tokens_before` and `tokens_after` — both are observable on the -same request. Output is different. When the shaper makes a request terser, the -model emits N output tokens. We **never observe** what it *would* have emitted -without the steering. Only one side of the counterfactual ever happens. So a -flat "we saved 30%" is a guess dressed as a fact. - -The design rule that follows: **never report a single number as if it were -measured.** Separate what is genuinely measured from what is estimated, label -each, and always attach uncertainty. - -### 7.2 Three tiers of honesty - -**Tier 1 — Estimated (synthetic control).** Build a per-stratum baseline of -*unshaped* output tokens from session history that predates the shaper -(`learn --verbosity` does this in the same pass that picks the level). For each -shaped request, the expected unshaped output is the baseline mean for that -request's stratum. Aggregate estimate: - -``` -tokens_saved = Σ over shaped requests ( baseline_mean[stratum] − observed_output ) -``` - -Summed as **signed** deltas — never clamped per-request. Clamping each delta at -zero would throw away the cases where a shaped response happened to be *longer* -by chance, biasing the total upward. Over many requests the noise averages out; -the systematic effect remains. Reported with a propagated 95% CI (see §7.5) and -always labelled "estimated." - -**Tier 2 — Measured (A/B holdout).** Set `HEADROOM_OUTPUT_HOLDOUT=0.1` and 10% -of conversations are deliberately left **unshaped** as a control arm. Within -each stratum, `mean(control) − mean(treatment)` is an **unbiased causal -estimate** of the per-request saving. This is the only number we call -"measured." It self-corrects: if steering doesn't actually help on some -workload, the holdout reveals it. The cost is real (you forgo savings on 10% of -traffic), so it's opt-in; default holdout is 0 (estimate-only). - -**Tier 3 — Direct waste (no counterfactual at all).** Echo ratio — the n-gram -overlap between a response and the context it was given — is a property of a -single response. "32% of this output restated context already on screen" needs -no counterfactual; it's a measured fact about output we *did* see, and it's -exactly what the shaper targets. Surfaced in `learn --verbosity` as -`mean_echo_ratio`. - -### 7.3 Stratification — comparing like with like - -You can't compare a "fix this typo" response to "design a caching layer." The -estimator buckets every request by features observable **before** the response: - -``` -stratum = model_family | turn_kind | input_token_bucket | has_tools - = e.g. "opus | mechanical_continuation | xl | tools" -``` - -Coarse on purpose (~25–50 strata) so per-stratum baselines stay dense. The live -proxy computes the stratum the exact same way the offline baseline does, so -treatment requests line up with their baseline. Unseen strata fall back -hierarchically (drop `has_tools`, then the bucket, …, then the global mean). - -### 7.4 The two constraints that happen to align - -Holdout assignment is **conversation-stable** — a whole conversation is either -treatment or control, decided by hashing a conversation-stable key (model + -first user message). This matters for two independent reasons that point the -same way: - -1. **Measurement validity** — mixing shaped and unshaped turns within one - conversation would contaminate the comparison (the history itself differs). -2. **Cache safety** — flipping a conversation's verbosity mid-stream changes the - system-prompt tail, which busts the provider prefix cache. - -So the same rule (assign per conversation, never per turn) is forced by both -the statistics and the caching. Nice when constraints agree. - -### 7.5 The confidence interval - -For the estimated tier, uncertainty comes from two sources, both propagated: - -``` -Var(tokens_saved) ≈ Σ_s [ n_s · σ²_observed,s + n_s² · σ²_baseline,s / m_s ] - └─ spread of shaped outputs ─┘ └─ finite-baseline error ─┘ -``` - -where `n_s` is treatment count in stratum `s` and `m_s` the baseline sample -count. For the measured tier it's the standard difference-of-means variance -`σ²_c/n_c + σ²_t/n_t` per stratum. The 95% band is `point ± 1.96·√Var`, surfaced -everywhere the number is (CLI and dashboard), so the reader sees the precision, -not just a point estimate. - -Output-token counts are right-skewed (a few huge responses). Means are still the -right statistic for *totals* (you're billed on the sum), but the CI widens -honestly when a stratum is dominated by a few large responses — which is the -correct signal that the estimate is soft there. - -### 7.6 How it flows end to end - -``` -learn --verbosity --apply - ├─ writes verbosity.json (the level the shaper applies) - └─ seeds output_savings.json (the per-stratum baseline = synthetic control) - -proxy request (HEADROOM_OUTPUT_SHAPER=1) - ├─ assign_arm(conversation) → treatment | control (holdout) - ├─ stratum_key(request features) - ├─ treatment: shape body; control: leave unshaped - └─ tag (arm, stratum) onto transforms_applied ← rides existing plumbing - -response completes → emit_request_outcome (one funnel, all paths) - └─ recorder.record(arm, stratum, output_tokens) → output_savings.json - -headroom output-savings / dashboard "Output Tokens Saved" card - └─ best_estimate(): measured if a holdout exists, else estimated; with CI -``` - -The recording rides the existing `transforms_applied` label channel, so it -works for streaming, non-streaming, and backend paths with no change to -`RequestOutcome` or its construction sites. - -### 7.7 What the user sees - -- **CLI:** `headroom output-savings` → - `Reduction: 31.7% (95% CI 27.7% … 35.7%) [MEASURED, 400 shaped requests]` -- **Dashboard:** an "Output Tokens Saved" hero card next to input compression — - token count, percent, a `measured`/`estimated` badge, and the CI band. -- **No dollar estimates** on the output card (per project convention) — token - counts and directional percentages only. - -### 7.8 Honest limitations - -- Estimated-tier accuracy depends on the baseline matching current workload; if - your tasks drift, re-run `learn --verbosity` or turn on a small holdout. -- The baseline must come from *unshaped* history. If you learn from sessions - where the shaper was already active, the baseline is contaminated — the live - holdout is the clean path forward. -- Runtime AIMD upward-ratcheting is gated off by default: we can reliably detect - "too much output" (fast-skip timing, stream cancellation) but not yet "too - little" at runtime without content heuristics, so auto-escalation stays - behind `HEADROOM_VERBOSITY_AUTOTUNE` until both directions are trustworthy. diff --git a/docs/proposals/vertex-claude-compression-review.md b/docs/proposals/vertex-claude-compression-review.md deleted file mode 100644 index e4486b7cd..000000000 --- a/docs/proposals/vertex-claude-compression-review.md +++ /dev/null @@ -1,266 +0,0 @@ -# Claude Code + Vertex AI + Headroom compression — does it work? - -*A plain-English deep code review. Last updated 2026-06-18.* - -## TL;DR (read this first) - -**Yes — and the working path is now validated end-to-end (2026-06-19). See the -copy-paste runbook: [`docs/claude-code-vertex-headroom.md`](../claude-code-vertex-headroom.md).** - -> **2026-06-19 update — tested against live Vertex quota (Claude Code 2.1.181):** -> Of the two setups below, **only Setup B works in practice.** -> -> - **Setup A (Vertex mode + `ANTHROPIC_VERTEX_BASE_URL`→proxy) is blocked by Claude -> Code itself.** In Vertex mode Claude Code runs a client-side `probeVertexModel` -> check *before any request*; pointing its Vertex URL at a non-Google host makes that -> probe fail instantly ("model … not available on your vertex deployment") and the -> proxy never receives a byte. Not a Headroom bug — the native `:rawPredict` -> passthrough is correct and compresses (verified by direct curl), but the client -> won't route to it. -> - **Setup B (normal Anthropic mode + `--backend litellm-vertex_ai`) is the working -> path.** Verified: Claude Code → Headroom → LiteLLM → Vertex (`global`), real -> answers, and **~22% context compression on a code-heavy request**. Two gotchas: -> (1) `pip install "google-cloud-aiplatform>=1.38"` or requests 500 with -> `No module named 'vertexai'`; (2) start the proxy with **`--code-aware`** or code -> content silently no-ops (it is disabled by default). - -There is still **no `headroom wrap claude` turnkey** for Vertex, and the one backend -flag older help text advertises (`--backend litellm-vertex`) is broken — use -`--backend litellm-vertex_ai`. - -Everything in the *middle* (compression, request/response translation, streaming, -tool calls) is implemented correctly. The gaps are all at the **edges**: how the -client is pointed at Headroom, one mis-named backend, a missing pip extra, a -default-off compressor, and a few env vars Headroom never sets for you. - -> Correction to an earlier claim: it is **not** true that "the Python proxy just -> passes Vertex through without compressing." For the Anthropic publisher it runs -> the full compression pipeline. That earlier statement was based on an incomplete -> read of the routing code; the verified behavior is in this doc. - ---- - -## The thing we're trying to do - -An enterprise runs **Claude Code**, but their Claude models live on **Google -Vertex AI** (not the direct Anthropic API). They want **Headroom** in the middle so -their prompts get compressed (fewer input tokens = lower cost), without changing -the answers. - -For that to happen, three things must all be true: - -1. **The client's traffic must actually reach Headroom** (the proxy must be in the path). -2. **Headroom must compress it.** -3. **Headroom must forward it to Vertex correctly** (right URL, right auth, right body shape) and translate the answer back so Claude Code understands it. - -This review checks all three. - ---- - -## The map: where Claude-on-Vertex can run, and what compresses - -There are **two proxies** in this repo and **three** possible routes. Only some compress. - -| Route | What it is | Compresses? | Notes | -|---|---|---|---| -| **Python proxy, native Vertex `:rawPredict`** (publisher = `anthropic`) | Client sends a real Vertex request to Headroom | ✅ **Yes** | Runs the full Anthropic compression pipeline, keeps the Vertex body shape, forwards the client's own Google token. `proxy_routes.py:648` | -| **Python proxy, `--backend litellm-vertex_ai`** | Client speaks plain Anthropic; Headroom translates to Vertex | ✅ **Yes** (correct string only) | Full Anthropic↔Vertex translation incl. streaming + tools. **`litellm-vertex` is broken — must use `litellm-vertex_ai`.** | -| **Rust proxy, native Vertex `:rawPredict`** | A separate `headroom-proxy` binary | ✅ **Yes** | Correct and well-built — **but never run by `headroom proxy`/`wrap`.** Dead code for normal users. | -| **Python proxy, passthrough** (any *other* publisher) | Generic verbatim forward | ❌ No | Only used for non-Anthropic, non-Google publishers. `openai.py:6014` | - -**Key takeaway:** the *compression engine* for Vertex+Claude exists and works in the -Python proxy. The problems are getting traffic into it and one naming bug. - ---- - -## Does it work end-to-end? The honest answer - -**Through `headroom wrap claude` with zero extra setup: no.** `wrap claude` only -sets `ANTHROPIC_BASE_URL`. If Claude Code is in Vertex mode it ignores that and -talks straight to Google — Headroom is never in the path. And `wrap claude` has no -`--backend`/`--region` flags and sets no Vertex environment variables. - -**With manual setup: yes, one of two ways.** Both are below. Both work *around* -issues, not because the product wires them for you. - ---- - -## Setup A — Claude Code stays in Vertex mode (recommended for Vertex shops) - -Idea: Claude Code keeps using its native Vertex mode and its own Google login. -You just tell it "send Vertex requests to Headroom instead of straight to Google," -and you tell Headroom where the real Vertex endpoint is. - -```bash -# 1) Run Headroom, telling it the real Vertex endpoint (match your region!) -headroom proxy --port 8787 \ - --vertex-api-url https://us-east5-aiplatform.googleapis.com # use YOUR region - -# 2) Run Claude Code in Vertex mode, but point its Vertex base URL at Headroom -export CLAUDE_CODE_USE_VERTEX=1 -export ANTHROPIC_VERTEX_PROJECT_ID= -export CLOUD_ML_REGION=us-east5 -export ANTHROPIC_VERTEX_BASE_URL=http://127.0.0.1:8787 # <-- the redirect that makes it work -claude -``` - -What happens: Claude Code → `ANTHROPIC_VERTEX_BASE_URL` (Headroom) → Headroom -matches the `:rawPredict` route, sees `publisher=anthropic`, **compresses**, then -forwards to the real Vertex endpoint using Claude Code's own Google token. - -Caveats: you must set `--vertex-api-url` to your region (see Issue #6), and -`wrap claude` won't set `ANTHROPIC_VERTEX_BASE_URL` for you (Issue #3). - ---- - -## Setup B — Claude Code in normal Anthropic mode; Headroom talks to Vertex - -Idea: Claude Code thinks it's talking to plain Anthropic. Headroom holds the Google -credentials and is the one that actually talks to Vertex. - -```bash -# Headroom does the Vertex talking — note the backend name carefully -export HEADROOM_BACKEND=litellm-vertex_ai # NOT "litellm-vertex" (that's broken — Issue #1) -export HEADROOM_REGION=us-east5 # becomes the Vertex location -export VERTEXAI_PROJECT= # Headroom does NOT set this for you (Issue #4) -export GOOGLE_APPLICATION_CREDENTIALS=/path/sa.json # or use `gcloud auth application-default login` -export ANTHROPIC_API_KEY=placeholder-not-used # Claude Code needs *a* key to start (Issue #5) - -# Do NOT set CLAUDE_CODE_USE_VERTEX here — Claude Code must stay in normal mode -headroom wrap claude -``` - -What happens: Claude Code → Headroom (plain Anthropic `/v1/messages`) → -**compresses** → LiteLLM converts to Vertex and calls Claude on Vertex → converts -the answer back to Anthropic shape → Claude Code reads it. - -Caveats: the backend-name bug (Issue #1), the missing project env (Issue #4), and -this path has **no automated tests** (Issue #8) — smoke-test it before relying on it. - ---- - -## How to verify compression is really happening - -1. Open the dashboard: `http://localhost:8787/dashboard` — "tokens saved" should - climb as you use Claude Code. -2. Or check response headers on a request: `x-headroom-tokens-before`, - `x-headroom-tokens-after`, `x-headroom-tokens-saved`. -3. Confirm it actually hit Vertex (proxy logs show a `vertex_ai/claude-…` model or - a Vertex host, not `api.anthropic.com`). - -If `tokens-saved` is 0 on large prompts, compression isn't running — re-check the -setup against the issues below. - ---- - -## Every issue we found (the full list) - -Severity: **BROKEN** = doesn't work; **GAP** = works only with manual workaround; -**BUG** = wrong behavior in an edge case; **HOUSEKEEPING** = confusing but harmless. - -### 1. BROKEN — `--backend litellm-vertex` never reaches Vertex -The backend name is turned into a provider by chopping off `litellm-`, so -`litellm-vertex` becomes the provider `vertex`. But the Vertex integration is keyed -on `vertex_ai`, not `vertex`. So Headroom falls back to a generic "unknown -provider" mode: it builds the wrong model name (`vertex/claude-…` instead of -`vertex_ai/claude-…`), **ignores the region**, and mishandles auth. -**You must use `--backend litellm-vertex_ai`.** Worse: every help message and the -`wrap` example tell users the broken `litellm-vertex`. -*Where:* `providers/registry.py:174-178`, `backends/litellm.py:291,326-336,681-682`; -help text at `cli/proxy.py:524`, `cli/wrap.py:3645`, `proxy/server.py:3913`. -*Fix (small):* alias `vertex` → `vertex_ai` in `create_proxy_backend`, or add a -`"vertex"` entry to the provider registry. Then fix the help text. - -### 2. GAP — `headroom wrap claude` has no Vertex support -The `claude` wrap command has no `--backend` and no `--region` (the `aider` wrap -command has both). It only ever sets `ANTHROPIC_BASE_URL`. So there's no flag to -turn on a Vertex backend for Claude Code — you must pre-export env vars. -*Where:* `cli/wrap.py:2780-2819` (vs `cli/wrap.py:3612,3615` for aider). -*Fix:* add `--backend`/`--region` to `wrap claude`, mirroring `aider`. - -### 3. GAP — Vertex-mode Claude Code bypasses the proxy, and Headroom never sets the fix -With `CLAUDE_CODE_USE_VERTEX=1`, Claude Code ignores `ANTHROPIC_BASE_URL` and goes -straight to Google. There **is** a documented override — `ANTHROPIC_VERTEX_BASE_URL` -— that points Claude Code's Vertex traffic at a gateway. But Headroom never sets it -(0 references in the codebase). So the proxy has the right routes, but nothing -connects the client to them automatically. -*Where:* repo-wide grep for `ANTHROPIC_VERTEX_BASE_URL` = 0 hits. -*Fix:* in a Vertex-aware `wrap claude`, set `ANTHROPIC_VERTEX_BASE_URL` to the proxy. - -### 4. GAP — the GCP project is never passed to LiteLLM -For Setup B, Headroom passes the region to LiteLLM but never the project. You must -export `VERTEXAI_PROJECT` (or `GOOGLE_CLOUD_PROJECT`) yourself or it fails. -*Where:* `backends/litellm.py:682` sets only `vertex_location`. -*Fix:* thread a project config/env through to the LiteLLM call. - -### 5. GAP — no placeholder API key for Claude Code -With a custom `ANTHROPIC_BASE_URL`, Claude Code needs *an* `ANTHROPIC_API_KEY` to -start, even though the proxy uses Google creds upstream. `wrap claude` never sets a -placeholder, so the user must. -*Where:* `cli/wrap.py:2984-2988`. -*Fix:* set a placeholder key (or `ANTHROPIC_AUTH_TOKEN`) when launching. - -### 6. BUG — region/host mismatch -Headroom pins the Vertex host to one region (default `us-central1`) but throws away -the region in the client's request path. If your client targets, say, -`europe-west1` while Headroom is on the default host, the request goes to the wrong -region unless you set `--vertex-api-url` to match. -*Where:* `copilot_auth.py:936` (host = base + path, no region reconciliation), -`providers/proxy_routes.py:647` (path `location` is discarded), `registry.py:16`. -*Fix:* derive the upstream host from the request path's `location`, or validate they match. - -### 7. HOUSEKEEPING — the Rust Vertex proxy is correct but unwired -There's a second, Rust proxy (`crates/headroom-proxy/src/vertex/`) that compresses -Vertex traffic correctly. But `headroom proxy` and `headroom wrap` run the **Python** -server and never call it — it's a separate binary you'd run by hand. This is a -frequent source of "but I thought Vertex compression was added" confusion: it was, -in Rust, on a path nobody runs by default. -*Where:* `crates/headroom-proxy/Cargo.toml` (`[[bin]]`), no Python→Rust bridge to it. -*Fix:* either document that the Rust proxy is separate, or wire/retire it. - -### 8. GAP — no tests for the Vertex compression paths -No test instantiates the LiteLLM Vertex backend with a mocked Vertex call, and the -native-Vertex compression route isn't covered against a real Vertex shape. The -translation code is correct by inspection, but unproven by CI. -*Fix:* add a mocked round-trip test (Anthropic in → compressed → Vertex call asserted → Anthropic out). - -### 9. HOUSEKEEPING — stale Rust doc comment -`crates/headroom-proxy/src/vertex/mod.rs:42-47` describes a "synthetic model -injection" strategy the code no longer implements. Doc only; behavior is correct. - ---- - -## What's actually solid (so we don't over-correct) - -These were verified and are **correct**: - -- **Native Vertex `:rawPredict` for `publisher=anthropic` compresses** and preserves - the Vertex body shape (keeps `anthropic_version`, never injects `model`). - `proxy_routes.py:648`, `anthropic.py:604-606,1941-1949`. -- **LiteLLM translation is real and complete** (with the `vertex_ai` provider): - response is rebuilt into Anthropic shape (`backends/litellm.py:575-628`), streaming - emits proper Anthropic SSE events (`streaming.py:1344-1472`, `litellm.py:736-947`), - and tool calls round-trip both directions (`litellm.py:525-565,593-602`). -- **Compression runs before the backend dispatch** (`anthropic.py:1671` then - `:1781`), so the backend always gets the compressed body. -- **Auth is forwarded correctly** on the native path — the client's Google token is - passed through untouched (`copilot_auth.py:1156-1157`). - ---- - -## Recommended fixes, smallest-first - -1. **Fix the backend name (Issue #1)** — one-line alias `vertex`→`vertex_ai`, then - correct the help text. This is the highest-impact, lowest-effort fix; it turns the - *documented* command from broken to working. -2. **Add `--backend`/`--region` to `wrap claude` (Issue #2)** — copy from `aider`. -3. **Add a Vertex mode to `wrap claude` (Issues #3, #5)** — detect/set - `ANTHROPIC_VERTEX_BASE_URL` → proxy, set a placeholder API key, and configure the - proxy's Vertex upstream — so Setup A becomes one command. -4. **Pass the GCP project (Issue #4)** and **reconcile the region/host (Issue #6).** -5. **Add a mocked round-trip test (Issue #8).** -6. **Decide the Rust proxy's fate (Issue #7)** — document-as-separate or wire it in. - -After #1–#3, the honest customer message becomes: *"`headroom wrap claude` works -with Vertex out of the box."* Until then, it's *"works with a documented manual -setup."* diff --git a/docs/rtk-loop-weighting.md b/docs/rtk-loop-weighting.md deleted file mode 100644 index e0b580a90..000000000 --- a/docs/rtk-loop-weighting.md +++ /dev/null @@ -1,125 +0,0 @@ -# Loop weighting in Headroom Learn + RTK-loop eval - -**Status:** proposed (branch `purva/rtk-loop-evals`). -**Context:** Tejas asked for (1) an eval that reproduces the RTK loop, runs it -through Headroom Learn, and checks the generated rule prevents re-triggering, -and (2) a change so Headroom Learn gives loops more weight. - -## The gap - -Before this change, `headroom learn` ranked every recommendation by a single -LLM-guessed `estimated_tokens_saved`, with a flat hardcoded `confidence` -(`0.9`/`0.7`). It had **no notion of a loop**. Two consequences: - -1. **RTK re-fetch loops were invisible.** RTK truncates a shell command's - output (`grep foo` → `grep foo | head -50`, see `docs/rtk-architecture.md`). - When the truncation drops what the agent needed, the agent re-runs a - *variant* to fetch more. **Those calls succeed** (`is_error=False`), so the - analyzer's failure-oriented path ignored them — and `analyze()` even - early-returned when a session had no failures and no events. - -2. **Even when surfaced, a loop ranked no higher than a one-off.** A pattern - that wastes 5,000 tokens by repeating 6× was ranked the same as a one-time - 200-token mistake, because ranking trusted the LLM's per-rule guess. - -## The change - -A new module `headroom/learn/loops.py`: - -- **`detect_loops(sessions)`** groups tool calls within a session by a - *canonical signature* that collapses RTK re-fetch variants (it strips - pagination/limit fragments — `head -N`, `-n N`, `LIMIT N`, … — and bare - integers), then flags any signature repeated `>= 3×`. It classifies each as - an `error-loop` or an `rtk-refetch-loop` and computes **measured** wasted - tokens (error loops waste every call; re-fetch loops credit the first, - legitimate call and count the N−1 redundant re-fetches). -- **`format_loops_for_digest(loops)`** prepends a `=== Detected Loops (HIGHEST - PRIORITY) ===` block to the LLM digest, with each loop's measured waste. -- **`apply_loop_weighting(recs, loops)`** raises a matching recommendation's - `estimated_tokens_saved` to at least the loop's measured waste and tags it - `is_loop_guardrail=True`. Because measured loop waste aggregates many - repetitions, this reliably lifts loop guardrails above one-offs **without - trusting the LLM** to have weighted them. - -Wiring in `analyzer.py`: loops are detected up front (so a no-failure re-fetch -loop is now a first-class reason to analyze, fixing the early-return), surfaced -in the digest, the system prompt makes loops the #1 priority, and weighting + -re-sort run after parsing. - -### Why measured-waste weighting (vs. relying on the LLM's estimate) - -The LLM's `estimated_tokens_saved` is a free-form guess, not grounded in the -transcript, so ranking on it alone is unreliable. Deriving the weight from -*observed repetition* — the real output bytes summed across the repeated calls -— is deterministic and auditable: the boost equals waste we actually counted. - -Honest caveat on the current implementation: we do BOTH — the digest also tells -the model the measured waste and asks it to rank loops first. In real-LLM runs -that prompt hint is doing much of the work (the model echoes the measured -figure), while the post-hoc `apply_loop_weighting` boost is fuzzy-match-based -and does not always fire. Making the measured-waste boost the deterministic, -load-bearing mechanism — independent of the model's wording — is tracked as -follow-up. - -## The eval - -`benchmarks/rtk_loop_learn_eval.py` (CI wrapper: `tests/test_learn/ -test_rtk_loop_eval.py`). Two phases: - -- **Phase 1 — trigger + learn:** reproduce the RTK re-fetch loop, run the - analyzer, and score the guardrail: produced? ranked first? names the command? - prescribes a fix? does its savings estimate reflect measured waste? -- **Phase 2 — guardrail holds:** inject that guardrail as a prior pattern, feed - a session where the agent *followed* it (one full-output fetch, no loop), and - assert no new loop guardrail is re-emitted — i.e. once the rule exists and is - honored, the loop does not re-trigger. - -Runs deterministically in CI (stubbed analyzer LLM) and against a real LLM with -`--real` — via an API key or an installed CLI backend (`HEADROOM_LEARN_CLI=claude`). - -``` -$ python benchmarks/rtk_loop_learn_eval.py - [PASS] loop_detected (1 loop(s), ~5,005 tok wasted) - [PASS] guardrail_produced - [PASS] ranked_first - [PASS] names_command - [PASS] prescribes_fix - [PASS] weight_reflects_waste - [PASS] guardrail_holds - RESULT: PASS — loop caught, guardrail ranked first, and it holds. -``` - -### Real-LLM run (claude CLI backend) - -Running `--real` against the actual analyzer model proved the weighting works -end-to-end *and* caught an over-brittle check. The model produced this rule, -ranked **first** with the measured 5,005-token weight: - -> **Commands** — When grepping logs (or any large file), never loop with -> increasing `| head -N` limits — tool output is capped at ~4 KB regardless of -> N, so repeated attempts return identical bytes. Instead: redirect to a temp -> file (`grep ... > /tmp/out.txt`) then read it, or use `grep -c` first… - -That rule is *more general* than the fixture's — it identifies the looping -command (`grep` + `head -N`) without echoing the incidental search string. An -early `names_command` check required the literal "TimeoutError" and wrongly -failed; the real run exposed it, and the check now verifies the rule names the -looping command, not an incidental literal. This is exactly why the governance -treats real output — not mocks — as proof. - -## Honest limitations / open questions for review - -- **Phase 2 is a non-recurrence check, not a live agent.** It proves the - guardrail is *adequate* (names the command, prescribes the fix) and that a - guarded, non-looping session produces no new rule. It does **not** run a real - agent that obeys the rule end-to-end — that needs a live agent harness and is - the natural next step if we want a stronger claim. -- **Loop signature is heuristic.** The pagination-stripping regex covers the - common RTK truncation shapes (`head`/`tail`/`-n`/`LIMIT`/`OFFSET`); exotic - truncations may not collapse to one signature. Easy to extend as we see real - transcripts. -- **`min_occurrences = 3`** treats a single retry as not-yet-a-loop. If we have - data showing 2× re-fetches are already worth a rule, lower it. -- **Matching rules to loops is fuzzy** (token overlap between the rule text and - the looped command). A structured loop→rule id from the LLM would be tighter - but adds prompt/parse surface. diff --git a/docs/spec/001-vision.md b/docs/spec/001-vision.md deleted file mode 100644 index 46860cb04..000000000 --- a/docs/spec/001-vision.md +++ /dev/null @@ -1,109 +0,0 @@ -# 001. Vision - -**Status:** done - -## What Headroom Is - -Headroom is a **context compression proxy** for AI provider APIs. It sits between AI coding tools (Claude Code, Copilot, Codex, etc.) and provider APIs (OpenAI, Anthropic, Google, Cohere), compressing context before it reaches the provider to reduce token usage and costs. - -### Core Value Proposition - -1. **Token Savings** — 30-90% reduction in tokens sent to providers through semantic compression -2. **Cost Reduction** — Lower API costs via compression before provider transmission -3. **Context Window Extension** — Effective 2-10x larger context windows via compression -4. **Privacy** — Prompts never logged by default; all processing stays local -5. **Compatibility** — Works with existing AI coding tools via proxy or SDK - -### What Headroom Is Not - -- A model provider — Headroom does not host or run AI models -- A data store — No prompt storage by default (local SQLite is optional) -- A logging service — No prompt logging by default -- A billing service — Usage tracking is internal only - ---- - -## Design Principles - -### 1. Local-First Privacy - -**Principle:** Prompt data never leaves the proxy unless explicitly exported. - -**Implications:** -- All compression happens locally or through the proxy -- No third-party data sharing -- Optional SQLite storage with user control -- Export must be explicitly configured - -### 2. Transparent Compression - -**Principle:** Users see exactly what is being compressed and why. - -**Implications:** -- Full observability into compression decisions -- Metrics and logs show savings -- Transform audit trail available -- Dashboard visualizes all compression activity - -### 3. Composable Integration - -**Principle:** Headroom works alongside existing tools without requiring workflow changes. - -**Implications:** -- Proxy mode: route traffic through Headroom -- SDK mode: integrate into custom applications -- CLI mode: wrap existing AI commands -- Agent mode: MCP/LiteLLM/ASGI integrations - -### 4. Production-Ready Defaults - -**Principle:** Safe defaults that work out of the box. - -**Implications:** -- Compression enabled by default -- No logging by default -- Cache enabled by default -- Learning disabled by default - ---- - -## Core Guarantees - -| Guarantee | Description | -|-----------|-------------| -| **Never logs prompts** | No prompt data in logs unless exporter configured | -| **Never leaves proxy** | All data stays local unless explicitly exported | -| **Composable** | Works alongside Claude Code, Copilot, Codex, etc. | -| **Transparent** | Full observability into compression decisions | -| **Type-safe** | Full type annotations, mypy compliance | -| **Test-covered** | Unit, integration, and E2E test coverage | - ---- - -## Target Users - -| User | Use Case | -|------|----------| -| **Individual Developers** | Reduce API costs for personal AI coding | -| **Development Teams** | Shared compression with learn plugins | -| **Enterprises** | Self-hosted deployment with security guarantees | -| **Plugin Authors** | Extend Headroom via plugin ABI | - ---- - -## Success Metrics - -| Metric | Target | Measurement | -|--------|--------|-------------| -| Token savings | >30% | (tokens_before - tokens_after) / tokens_before | -| Compression latency | <50ms | Per-request proxy overhead | -| Cache hit rate | >60% | cache_hits / total_requests | -| Zero data exfiltration | 100% | No prompts in logs by default | - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial vision document | diff --git a/docs/spec/002-architecture.md b/docs/spec/002-architecture.md deleted file mode 100644 index 742558d1f..000000000 --- a/docs/spec/002-architecture.md +++ /dev/null @@ -1,339 +0,0 @@ -# 002. Architecture - -**Status:** done - -## System Overview - -Headroom is a context compression proxy for LLM applications, featuring intelligent transforms, semantic caching, and CCR (Compress-Cache-Retrieve) architecture. - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Headroom │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │ -│ │ Proxy │ │ SDK │ │ Wrap │ │ CCR MCP │ │ -│ │ Server │ │ (Python) │ │ CLI │ │ Server │ │ -│ │ (8787) │ │ │ │ │ │ │ │ -│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └──────┬──────┘ │ -│ │ │ │ │ │ -│ ┌────┴──────────────┴──────────────┴─────────────────┴──────┐ │ -│ │ Compression Layer │ │ -│ │ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │ │ -│ │ │SmartCrusher│ │CacheAligner│ │ RollingWindow │ │ │ -│ │ │(JSON array │ │(Prefix │ │ (Token cap) │ │ │ -│ │ │ crush) │ │ stabilization)│ │ │ │ │ -│ │ └────────────┘ └────────────┘ └────────────────────┘ │ │ -│ └───────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌───────────────────────────────────────────────────────────┐ │ -│ │ Learn System │ │ -│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────────────┐ │ │ -│ │ │Claude │ │Codex │ │Gemini │ │ Generic │ │ │ -│ │ │Scanner │ │Scanner │ │Scanner │ │ Writer │ │ │ -│ │ └────────┘ └────────┘ └────────┘ └────────────────┘ │ │ -│ └───────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │ -│ │ Dashboard │ │ CCR │ │ TOIN │ │ -│ │ (HTML) │ │ (Compress- │ │ (Telemetry-based │ │ -│ │ │ │ Cache- │ │ Intelligence) │ │ -│ │ │ │ Retrieve) │ │ │ │ -│ └──────────────┘ └──────────────┘ └──────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - ---- - -## Component Specifications - -### Proxy Server (`headroom/proxy/server.py`) - -**`HeadroomProxy` class** — Main proxy server (default port 8787): - -```python -class HeadroomProxy: - def __init__(self, config: ProxyConfig) -> None: - self.config = config - self.compression_cache = CompressionCache(...) - self.transform_pipeline = [...] - self.ccr_store = CompressionStore(...) - self.prefix_freeze = PrefixFreeze(...) - - async def startup(self) -> None: ... - async def shutdown(self) -> None: ... - async def handle_request(request: Request) -> Response: ... -``` - -**`ProxyConfig` dataclass** (from `headroom/models/config.py`): -```python -@dataclass -class ProxyConfig: - store_url: str = "sqlite:///headroom.db" - default_mode: HeadroomMode = HeadroomMode.AUDIT - tool_crusher: ToolCrusherConfig = field(default_factory=ToolCrusherConfig) - smart_crusher: SmartCrusherConfig = field(default_factory=SmartCrusherConfig) - cache_aligner: CacheAlignerConfig = field(default_factory=CacheAlignerConfig) - rolling_window: RollingWindowConfig = field(default_factory=RollingWindowConfig) - cache_optimizer: CacheOptimizerConfig = field(default_factory=CacheOptimizerConfig) - ccr: CCRConfig = field(default_factory=CCRConfig) - prefix_freeze: PrefixFreezeConfig = field(default_factory=PrefixFreezeConfig) -``` - -**`HeadroomMode` enum** (actual modes): -```python -class HeadroomMode(str, Enum): - AUDIT = "audit" # Observe only, no modifications - OPTIMIZE = "optimize" # Apply deterministic transforms - SIMULATE = "simulate" # Return transform plan without API call -``` - -**HTTP Endpoints (actual):** -| Endpoint | Method | Description | -|----------|--------|-------------| -| `/v1/messages` | POST | Proxy chat completions | -| `/v1/embeddings` | POST | Proxy embeddings | -| `/health` | GET | Basic health check | -| `/livez` | GET | Liveness check | -| `/readyz` | GET | Readiness check | -| `/metrics` | GET | Prometheus metrics | -| `/v1/compress` | POST | Direct compression | -| `/v1/retrieve` | POST | CCR retrieval | -| `/stats` | GET | Compression statistics | - -**Default Port:** 8787 (not 8765) - ---- - -### Python SDK (`headroom/client.py`) - -**`HeadroomClient` class:** -```python -class HeadroomClient: - def __init__( - self, - api_key: str | None = None, - base_url: str = "http://localhost:8787", - timeout: float = 60.0, - fallback: bool = True, - retries: int = 3, - ) -> None: - pass - - async def compress( - self, - messages: list[dict], - options: CompressOptions | None = None, - ) -> CompressResult: ... - - async def get_stats(self) -> Stats: ... - - async def close(self) -> None: ... -``` - ---- - -### Wrap CLI (`headroom/cli/wrap.py`) - -**Commands (all use default port 8787):** -- `claude` — Wrap Claude Code -- `copilot` — Wrap GitHub Copilot -- `codex` — Wrap OpenAI Codex -- `aider` — Wrap Aider -- `cursor` — Wrap Cursor -- `openclaw` — Wrap OpenClaw - -```python -@click.command() -@click.option("--port", "-p", default=8787, help="Proxy port") -@click.argument("command", nargs=-1, required=True) -def wrap(command: tuple, port: int) -> None: - """Wrap a command with Headroom proxy.""" - ... -``` - ---- - -### CCR MCP Server (`headroom/ccr/mcp_server.py`) - -Model Context Protocol server for Claude Desktop integration. - -```python -class CCRMcpServer: - async def compress(messages: list[dict]) -> CompressResult: ... - async def retrieve(hash: str, query: str) -> RetrieveResult: ... - async def get_stats() -> Stats: ... -``` - -**MCP Tools:** -- `headroom_compress` — Compress messages -- `headroom_retrieve` — Retrieve cached content -- `headroom_stats` — Get statistics - ---- - -### ASGI Middleware (`headroom/integrations/asgi.py`) - -ASGI-compatible middleware for Python web frameworks. - -```python -class HeadroomMiddleware: - def __init__( - self, - app: ASGIApplication, - headroom_url: str = "http://localhost:8787", - ) -> None: ... -``` - ---- - -### LiteLLM Callback (`headroom/integrations/litellm_callback.py`) - -Callback for LiteLLM proxy integration. - -```python -class LiteLLMCallback: - def on_completion(self, completion_response: dict) -> dict: ... - def on_error(self, error: Exception) -> None: ... -``` - ---- - -## Compression Layer (`headroom/transforms/`) - -### SmartCrusher (`headroom/transforms/smart_crusher.py`) - -Statistical JSON array compression preserving schema. - -```python -class SmartCrusher: - def __init__(self, config: SmartCrusherConfig) -> None: ... - def crush(self, content: str, context: TransformContext) -> TransformResult: ... -``` - -### CacheAligner (`headroom/transforms/cache_aligner.py`) - -Prefix stabilization for provider cache optimization. - -```python -class CacheAligner: - def __init__(self, config: CacheAlignerConfig) -> None: ... - def align(self, messages: list[dict]) -> TransformResult: ... -``` - -### RollingWindow (`headroom/transforms/rolling_window.py`) - -Rolling window token cap. - -```python -class RollingWindow: - def __init__(self, config: RollingWindowConfig) -> None: ... - def apply(self, messages: list[dict]) -> TransformResult: ... -``` - -### ContentRouter (`headroom/transforms/content_router.py`) - -Routes content to appropriate compressor based on type. - -```python -class ContentRouter: - def route(self, messages: list[dict]) -> list[dict]: ... -``` - ---- - -## Learn System (`headroom/learn/`) - -**`LearnPlugin` interface** (actual): - -```python -class LearnPlugin(ConversationScanner): - @property - def name(self) -> str: ... - @property - def display_name(self) -> str: ... - @abstractmethod - def detect(self) -> bool: ... - @abstractmethod - def discover_projects(self) -> list[ProjectInfo]: ... - @abstractmethod - def scan_project(self, project: ProjectInfo, max_workers: int = 1) -> list[SessionData]: ... - @abstractmethod - def create_writer(self) -> ContextWriter: ... -``` - -**Scanner implementations:** -- `ClaudeScanner` — Claude Code session parsing -- `CodexScanner` — Codex session parsing -- `CursorScanner` — Cursor session parsing - ---- - -## CCR System (`headroom/ccr/`) - -CCR (Compress-Cache-Retrieve) makes compression reversible. - -```python -class CompressionStore: - def store(self, hash: str, original: str, metadata: dict) -> None: ... - def retrieve(self, hash: str) -> str | None: ... - -class ContextTracker: - def track(self, session_id: str, messages: list[dict]) -> CCRContext: ... - def get_context(self, session_id: str) -> CCRContext | None: ... -``` - -**CCRConfig fields:** -- `enabled: bool = True` -- `store_max_entries: int = 1000` -- `store_ttl_seconds: int = 300` -- `inject_retrieval_marker: bool = True` -- `feedback_enabled: bool = True` - ---- - -## TOIN (`headroom/telemetry/toin.py`) - -Tool Output Intelligence Network — telemetry-based compression hints. - -```python -class TOINCollector: - def record_retrieval(self, tool_name: str, field: str, query: str) -> None: ... - def get_hints(self, tool_name: str) -> dict[str, float]: ... -``` - ---- - -## Dashboard (`headroom/dashboard/`) - -Simple HTML dashboard served by the proxy. - -```python -def get_dashboard_html() -> str: - """Load the dashboard HTML template.""" - return (TEMPLATES_DIR / "dashboard.html").read_text() -``` - ---- - -## Data Flow - -``` -Client → Headroom Proxy → [ContentRouter] → [SmartCrusher/CacheAligner/RollingWindow] - │ │ │ - │ [CCR Store] ←───────────────────────┘ - │ - │ [Telemetry/Metrics] - │ - ▼ - Provider API -``` - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial architecture document | diff --git a/docs/spec/003-adrs.md b/docs/spec/003-adrs.md deleted file mode 100644 index d18b0a30c..000000000 --- a/docs/spec/003-adrs.md +++ /dev/null @@ -1,164 +0,0 @@ -# 003. Architecture Decision Records - -**Status:** done - -## ADR-001: Why a Proxy Instead of SDK Injection - -**Context:** Headroom could be implemented as an SDK that users import, or as a network proxy. - -**Decision:** Network proxy with SDK for complex use cases. - -**Rationale:** -- Works with any HTTP client without code changes -- No need to modify existing applications -- Centralized configuration -- Can intercept all traffic, not just explicit SDK calls - -**Consequences:** -- Requires running a separate service (or using wrap mode) -- Network latency added (~5-10ms) -- Need to handle connection pooling - ---- - -## ADR-002: Why SQLite for Local Storage - -**Context:** Headroom needs to store compression cache, savings history, memory graphs. - -**Decision:** SQLite with optional external stores (Redis, PostgreSQL, etc.). - -**Rationale:** -- Zero configuration — works out of the box -- Single file, easy backup -- ACID compliant transactions -- Good performance for single-node deployments -- sqlite-vec for vector similarity search -- FTS5 for full-text search - -**Consequences:** -- Not distributed by default -- Must configure external stores for multi-node deployments -- Cloud-hosted databases require additional setup - ---- - -## ADR-003: Why CCR (Compress-Cache-Retrieve) Pattern - -**Context:** Compression alone doesn't leverage repeated context patterns. - -**Decision:** CCR pattern for semantic caching and retrieval. - -**Rationale:** -- Semantic similarity enables cache hits across different phrasings -- Retrieves relevant compressed context for new requests -- Reduces provider API calls for similar patterns -- Enables cross-session learning - -**Consequences:** -- Requires storing compressed content -- Semantic hashing adds latency -- Cache invalidation is complex - ---- - -## ADR-004: Why Per-Agent Plugins for Learn System - -**Context:** Different AI agents (Claude, Codex, Gemini) have different context patterns. - -**Decision:** Plugin architecture with agent-specific analyzers. - -**Rationale:** -- Tailored compression per agent type -- Extensible for new agents -- Clear interface contract -- Independent versioning - -**Consequences:** -- Plugin API must be stable -- Multiple plugins may conflict -- Testing complexity increases - ---- - -## ADR-005: Why ONNX for TOIN - -**Context:** TOIN (Tenant-specific ONNX) requires ML inference. - -**Decision:** Use ONNX Runtime for portable ML inference. - -**Rationale:** -- Hardware acceleration (CPU/GPU) -- Cross-platform (Windows, Linux, macOS) -- Model interchange format -- Single model file deployment - -**Consequences:** -- ONNX model files must be hosted -- Version compatibility issues -- Larger package size - ---- - -## ADR-006: Why Python for Core Implementation - -**Context:** Language choice for the main implementation. - -**Decision:** Python as the primary language. - -**Rationale:** -- Primary language for AI/ML ecosystem -- Easy integration with provider APIs -- Rich async ecosystem (asyncio, httpx) -- Strong type annotation support (mypy) -- Good testing infrastructure - -**Consequences:** -- GIL limitations for threading -- Slower than compiled languages -- Type checking adds build time - ---- - -## ADR-007: Why TypeScript SDK for npm - -**Context:** JavaScript/TypeScript ecosystem for frontend integrations. - -**Decision:** Official TypeScript SDK published to npm. - -**Rationale:** -- Node.js compatibility -- TypeScript type safety -- Wide adoption in AI tooling -- ESM and CommonJS support - -**Consequences:** -- Dual language maintenance -- Must keep SDK in sync with Python core -- Additional CI/CD pipeline needed - ---- - -## ADR-008: Why HierarchicalMemory with SQLite + vec + FTS5 - -**Context:** Memory system needs to store, search, and reason over context. - -**Decision:** Hierarchical memory using SQLite + sqlite-vec + FTS5. - -**Rationale:** -- SQLite: ACID transactions, single file -- sqlite-vec: Vector similarity for semantic search -- FTS5: Full-text search for keyword matching -- Hierarchical: Session < Conversation < Message structure - -**Consequences:** -- Memory hierarchy adds complexity -- SQLite limitations for concurrent writes -- Vector search accuracy depends on embedding quality - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial ADRs | diff --git a/docs/spec/004-domain-model.md b/docs/spec/004-domain-model.md deleted file mode 100644 index 450ba15cb..000000000 --- a/docs/spec/004-domain-model.md +++ /dev/null @@ -1,363 +0,0 @@ -# 004. Domain Model - -**Status:** done - -## Core Entities - -### Session - -A session represents a conversation context between a user and an AI agent. - -**Fields:** -- `session_id: UUID` — Unique identifier -- `created_at: datetime` — Creation time -- `updated_at: datetime` — Last modification -- `agent_type: str` — "claude", "codex", "gemini", etc. -- `messages: list[Message]` — Conversation history -- `metadata: dict` — Agent-specific metadata - -```python -@dataclass -class Session: - session_id: UUID - created_at: datetime - updated_at: datetime - agent_type: str - messages: list[Message] = field(default_factory=list) - metadata: dict = field(default_factory=dict) -``` - ---- - -### Message - -A single message in a conversation. - -**Fields:** -- `message_id: UUID` — Unique identifier -- `session_id: UUID` — Associated session -- `role: str` — "user", "assistant", "system", "tool" -- `content: str` — Message content -- `tokens: int | None` — Token count (if known) -- `created_at: datetime` — Creation time -- `attachments: list[Attachment] | None` — Optional attachments - -```python -@dataclass -class Message: - message_id: UUID - session_id: UUID - role: str - content: str - tokens: int | None = None - created_at: datetime = field(default_factory=datetime.utcnow) - attachments: list[Attachment] | None = None -``` - ---- - -### Request - -A single API request to an AI provider. - -**Fields:** -- `request_id: UUID` — Unique identifier -- `session_id: UUID` — Associated session -- `provider: str` — "anthropic", "openai", "google", etc. -- `model: str` — Model identifier -- `input_tokens: int` — Tokens in request -- `output_tokens: int` — Tokens in response -- `compressed: bool` — Whether compression was applied -- `savings_percentage: float` — Savings as decimal -- `timestamp: datetime` — Request time -- `duration_ms: int` — Request duration -- `error: str | None` — Error message if failed - -```python -@dataclass -class Request: - request_id: UUID - session_id: UUID - provider: str - model: str - input_tokens: int - output_tokens: int - compressed: bool = False - savings_percentage: float = 0.0 - timestamp: datetime = field(default_factory=datetime.utcnow) - duration_ms: int = 0 - error: str | None = None -``` - ---- - -### Savings - -A record of token savings from a compressed request. - -**Fields:** -- `savings_id: UUID` — Unique identifier -- `request_id: UUID` — Associated request -- `original_tokens: int` — Tokens before compression -- `compressed_tokens: int` — Tokens after compression -- `savings_percentage: float` — Savings as decimal -- `savings_amount: float` — Absolute token savings -- `provider: str` — Provider name -- `model: str` — Model used -- `window_start: datetime | None` — Billing window start - -```python -@dataclass -class Savings: - savings_id: UUID - request_id: UUID - original_tokens: int - compressed_tokens: int - savings_percentage: float - savings_amount: float - provider: str - model: str - window_start: datetime | None = None -``` - ---- - -### CacheEntry - -A cached compression result. - -**Fields:** -- `cache_key: str` — Hash of input -- `input_hash: str` — Hash of original content -- `output: str` — Compressed output -- `compression_type: str` — "semantic", "summary", "ccr" -- `tokens_before: int` — Tokens before compression -- `tokens_after: int` — Tokens after compression -- `created_at: datetime` — Creation time -- `ttl: int` — Time to live in seconds -- `hit_count: int` — Number of cache hits -- `last_accessed: datetime` — Last access time - -```python -@dataclass -class CacheEntry: - cache_key: str - input_hash: str - output: str - compression_type: str - tokens_before: int - tokens_after: int - created_at: datetime = field(default_factory=datetime.utcnow) - ttl: int = 3600 - hit_count: int = 0 - last_accessed: datetime = field(default_factory=datetime.utcnow) -``` - ---- - -### ToolDefinition - -A tool/function definition available to an AI agent. - -**Fields:** -- `tool_id: UUID` — Unique identifier -- `name: str` — Tool name -- `description: str` — Tool description -- `parameters: dict` — JSON Schema for parameters -- `provider: str` — Provider that defined this tool -- `created_at: datetime` — Creation time - -```python -@dataclass -class ToolDefinition: - tool_id: UUID - name: str - description: str - parameters: dict - provider: str - created_at: datetime = field(default_factory=datetime.utcnow) -``` - ---- - -### PluginInterface - -A learn plugin for agent-specific compression. - -**Fields:** -- `plugin_id: UUID` — Unique identifier -- `name: str` — Plugin name -- `agent_type: str` — Supported agent type -- `version: str` — Plugin version -- `entry_point: str` — Import path or file path -- `config: dict` — Plugin configuration -- `enabled: bool` — Whether plugin is active - -```python -@dataclass -class PluginInterface: - plugin_id: UUID - name: str - agent_type: str - version: str - entry_point: str - config: dict = field(default_factory=dict) - enabled: bool = True -``` - ---- - -### TOINTenant - -A tenant configuration for TOIN (Tenant-specific ONNX). - -**Fields:** -- `tenant_id: UUID` — Unique identifier -- `name: str` — Tenant name -- `model_path: str | Path` — Path to ONNX model -- `model_version: str` — Model version -- `config: dict` — Tenant-specific configuration -- `created_at: datetime` — Creation time -- `updated_at: datetime` — Last modification - -```python -@dataclass -class TOINTenant: - tenant_id: UUID - name: str - model_path: str | Path - model_version: str - config: dict = field(default_factory=dict) - created_at: datetime = field(default_factory=datetime.utcnow) - updated_at: datetime = field(default_factory=datetime.utcnow) -``` - ---- - -### CCRContext - -Claude Code Relay context tracking. - -**Fields:** -- `context_id: UUID` — Unique identifier -- `session_id: UUID` — Associated session -- `agent_type: str` — "claude", "claude-desktop", etc. -- `window_start: datetime` — Context window start -- `window_end: datetime` — Context window end -- `messages_tracked: int` — Number of messages -- `compressed_content: str | None` — Compressed context - -```python -@dataclass -class CCRContext: - context_id: UUID - session_id: UUID - agent_type: str - window_start: datetime - window_end: datetime - messages_tracked: int = 0 - compressed_content: str | None = None -``` - ---- - -### SubscriptionState - -Subscription/quota tracking state. - -**Fields:** -- `subscription_id: UUID` — Unique identifier -- `provider: str` — Provider name -- `plan_name: str` — Plan name -- `window_start: datetime` — Billing window start -- `window_end: datetime` — Billing window end -- `max_tokens: int | None` — Maximum tokens in window -- `tokens_used: int` — Tokens used in window -- `tokens_remaining: int | None` — Tokens remaining -- `is_active: bool` — Whether subscription is active -- `last_updated: datetime` — Last update time - -```python -@dataclass -class SubscriptionState: - subscription_id: UUID - provider: str - plan_name: str - window_start: datetime - window_end: datetime - max_tokens: int | None = None - tokens_used: int = 0 - tokens_remaining: int | None = None - is_active: bool = True - last_updated: datetime = field(default_factory=datetime.utcnow) -``` - ---- - -## Relationships - -``` -Session 1───N Message -Session 1───N Request -Request 1───1 Savings -Request 1───1 CacheEntry -Session 1───N CCRContext -TOINTenant 1───N Request -ToolDefinition N───N Session (via tool_use) -``` - ---- - -## Value Objects - -### CompressResult - -```python -@dataclass -class CompressResult: - messages: list[dict] - tokens_before: int - tokens_after: int - tokens_saved: int - compression_ratio: float - transforms_applied: list[str] - content_type: ContentType - model: str | None - ccr_hash: str | None - cached: bool -``` - -### ContentType (Enum) - -```python -class ContentType(Enum): - PLAINTEXT = "text/plain" - MARKDOWN = "text/markdown" - JSON = "application/json" - HTML = "text/html" - XML = "text/xml" - PYTHON = "text/x-python" - JAVASCRIPT = "text/javascript" - TYPESCRIPT = "text/typescript" - YAML = "text/yaml" - MARKDOWN_SNAPSHOT = "text/markdown-snapshot" - UNKNOWN = "application/octet-stream" -``` - -### ProxyMode (Enum) - -```python -class ProxyMode(Enum): - PASSTHROUGH = "passthrough" - COMPRESS = "compress" - LEARN = "learn" - DETACHED = "detached" -``` - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial domain model | diff --git a/docs/spec/005-integrations.md b/docs/spec/005-integrations.md deleted file mode 100644 index 8ba09b538..000000000 --- a/docs/spec/005-integrations.md +++ /dev/null @@ -1,353 +0,0 @@ -# 005. Integrations - -**Status:** done - -## Supported Agents - -### Claude (`headroom/learn/plugins/claude/`) - -**Plugin:** `ClaudeLearnPlugin` - -**Capabilities:** -- Session branch comparison -- Token headroom mode detection -- Tool use tracking -- Multi-modal support (images) - -**Interface:** -```python -class ClaudeLearnPlugin(LearnPlugin, ConversationScanner): - @property - def name(self) -> str: - return "claude" - - @property - def display_name(self) -> str: - return "Claude Code" - - def detect(self) -> bool: - """Check if Claude Code has data on the current machine.""" - pass - - def discover_projects(self) -> list[ProjectInfo]: - """Discover all projects with Claude sessions.""" - pass - - def scan_project(self, project: ProjectInfo, max_workers: int = 1) -> list[SessionData]: - """Scan all sessions for a project.""" - pass - - def create_writer(self) -> ContextWriter: - """Return Claude-specific ContextWriter.""" - pass -``` - -**Configuration:** -```bash -HEADROOM_LEARN_CLI=claude -``` - ---- - -### Codex (OpenAI) (`headroom/learn/plugins/codex/`) - -**Plugin:** `CodexLearnPlugin` - -**Capabilities:** -- Rate limit handling -- Code completion optimization -- Batch request support - -**Interface:** -```python -class CodexLearnPlugin(LearnPlugin, ConversationScanner): - @property - def name(self) -> str: - return "codex" - - @property - def display_name(self) -> str: - return "OpenAI Codex" - - def detect(self) -> bool: - pass - - def discover_projects(self) -> list[ProjectInfo]: - pass - - def scan_project(self, project: ProjectInfo, max_workers: int = 1) -> list[SessionData]: - pass - - def create_writer(self) -> ContextWriter: - pass -``` - -**Configuration:** -```bash -HEADROOM_LEARN_CLI=codex -``` - ---- - -### Gemini (Google) (`headroom/learn/plugins/gemini/`) - -**Plugin:** `GeminiLearnPlugin` - -**Capabilities:** -- Multimodal inputs -- Function calling support -- Context caching API - -**Interface:** -```python -class GeminiLearnPlugin(LearnPlugin, ConversationScanner): - @property - def name(self) -> str: - return "gemini" - - @property - def display_name(self) -> str: - return "Google Gemini" - - def detect(self) -> bool: - pass - - def discover_projects(self) -> list[ProjectInfo]: - pass - - def scan_project(self, project: ProjectInfo, max_workers: int = 1) -> list[SessionData]: - pass - - def create_writer(self) -> ContextWriter: - pass -``` - -**Configuration:** -```bash -HEADROOM_LEARN_CLI=gemini -``` - ---- - -## Integration Points - -### LiteLLM Callback (`headroom/integrations/litellm_callback.py`) - -LiteLLM proxy callback for integrating with LiteLLM-based setups. - -**`LiteLLMCallback` class:** -```python -class LiteLLMCallback: - def __init__( - self, - headroom_url: str = "http://localhost:8787", - api_key: str | None = None, - ) -> None: - self.headroom_url = headroom_url - self.api_key = api_key - - def on_completion(self, completion_response: dict) -> dict: - """Called after completion. Can modify response.""" - pass - - def on_error(self, error: Exception) -> None: - """Called on error.""" - pass -``` - -**Usage:** -```python -from headroom.integrations import LiteLLMCallback - -callback = LiteLLMCallback(headroom_url="http://localhost:8787") -# Register with LiteLLM proxy -``` - ---- - -### ASGI Middleware (`headroom/integrations/asgi.py`) - -ASGI-compatible middleware for Python web frameworks (FastAPI, Starlette, etc.). - -**`HeadroomMiddleware` class:** -```python -class HeadroomMiddleware: - def __init__( - self, - app: ASGIApplication, - headroom_url: str = "http://localhost:8787", - mode: ProxyMode = ProxyMode.COMPRESS, - ) -> None: - self.app = app - self.headroom_url = headroom_url - self.mode = mode - - async def __call__( - self, - scope: Scope, - receive: Receive, - send: Send, - ) -> None: - """ASGI application interface.""" - pass -``` - -**Usage:** -```python -from headroom.integrations import HeadroomMiddleware -from fastapi import FastAPI - -app = FastAPI() -app.add_middleware( - HeadroomMiddleware, - headroom_url="http://localhost:8787", - mode=ProxyMode.COMPRESS, -) -``` - ---- - -### MCP integration helpers (`headroom/integrations/mcp/server.py`) - -Helpers for MCP-aware host applications and custom wrappers. This module does -not currently ship a standalone `HeadroomMCPProxy` server implementation. - -**`HeadroomMCPCompressor` class:** -```python -class HeadroomMCPCompressor: - def __init__( - self, - config: HeadroomConfig | None = None, - profiles: list[MCPToolProfile] | None = None, - token_counter: Callable[[str], int] | None = None, - ) -> None: - ... - - def compress( - self, - content: str, - tool_name: str, - tool_args: dict[str, Any] | None = None, - user_query: str = "", - ) -> MCPCompressionResult: - """Compress an MCP tool result.""" - pass -``` - -**Companion helpers:** -- `compress_tool_result(...)` — standalone helper for host applications -- `HeadroomMCPClientWrapper` — wraps an MCP client and compresses tool results -- `create_headroom_mcp_proxy(...)` — returns config for a custom wrapper/proxy - -**Ready-to-run MCP tools server:** -```bash -headroom mcp serve -``` - ---- - -### Strands (`headroom/integrations/strands/`) - -Strands framework integration. - -**Usage:** -```python -from headroom.integrations.strands import HeadroomStrandsPlugin - -plugin = HeadroomStrandsPlugin() -``` - ---- - -### LangChain (`headroom/integrations/langchain/`) - -LangChain callback handler integration. - -**`HeadroomLangChainCallback` class:** -```python -class HeadroomLangChainCallback(BaseCallbackHandler): - def __init__( - self, - headroom_url: str = "http://localhost:8787", - api_key: str | None = None, - ) -> None: - self.headroom_url = headroom_url - self.api_key = api_key - - async def on_llm_start(self, serialized, prompts, **kwargs) -> None: - pass - - async def on_llm_end(self, response, **kwargs) -> None: - pass -``` - -**Usage:** -```python -from langchain.callbacks import HeadroomLangChainCallback - -callback = HeadroomLangChainCallback() -# Pass to LangChain chain -``` - ---- - -## Agent Contract - -All learn plugins must implement the `LearnPlugin` interface: - -```python -from abc import ABC, abstractmethod -from headroom.learn.base import ConversationScanner, ContextWriter -from headroom.learn.models import ProjectInfo, SessionData - -class LearnPlugin(ConversationScanner): - """A self-contained learn plugin for a single coding agent.""" - - @property - @abstractmethod - def name(self) -> str: - """Short lowercase identifier (e.g., 'claude', 'cursor').""" - ... - - @property - @abstractmethod - def display_name(self) -> str: - """Human-readable name (e.g., 'Claude Code', 'Cursor').""" - ... - - @abstractmethod - def detect(self) -> bool: - """Return True if this agent has data on the current machine.""" - ... - - @abstractmethod - def discover_projects(self) -> list[ProjectInfo]: - """Discover all projects with conversation data.""" - ... - - @abstractmethod - def scan_project(self, project: ProjectInfo, max_workers: int = 1) -> list[SessionData]: - """Scan all sessions for a project.""" - ... - - @abstractmethod - def create_writer(self) -> ContextWriter: - """Return the appropriate ContextWriter for this agent.""" - ... -``` - -**Plugin Registration:** -```python -# Module-level instance for auto-discovery -plugin = MyAgentPlugin() -``` - -Plugins are auto-discovered from `headroom.learn.plugins.*` or via `headroom.learn_plugin` entry points. - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial integrations document | diff --git a/docs/spec/006-actors.md b/docs/spec/006-actors.md deleted file mode 100644 index c9fe2053d..000000000 --- a/docs/spec/006-actors.md +++ /dev/null @@ -1,230 +0,0 @@ -# 006. Actors - -**Status:** done - -## Actor Types - -### End User - -The developer using an AI coding agent with Headroom. - -**Interactions:** -- Configures Headroom via environment variables or config file -- Uses wrapped CLI commands or SDK -- Views savings in dashboard -- Optionally enables learn mode - -**Needs:** -- Transparent compression (doesn't break workflows) -- Clear savings metrics -- Easy opt-out of specific features - -**Configuration:** -```bash -# Minimal setup -export ANTHROPIC_API_KEY=sk-... - -# Optional overrides -export HEADROOM_MODE=token -``` - ---- - -### Operator - -The person deploying and managing Headroom in production. - -**Interactions:** -- Deploys Headroom (Docker, native, or embedded) -- Configures profiles and presets -- Monitors health endpoints -- Reviews metrics and logs -- Manages upgrades - -**Needs:** -- Clear deployment documentation -- Health and readiness checks -- Metrics for capacity planning -- Upgrade and rollback procedures - -**Configuration:** -```yaml -# ~/.headroom/config.yaml -proxy: - host: 0.0.0.0 - port: 8787 - -compression: - enabled: true - cache: - enabled: true - ttl: 3600 - -telemetry: - metrics: - enabled: true -``` - -**Health Endpoints:** -```bash -curl http://localhost:8787/health -curl http://localhost:8787/livez -curl http://localhost:8787/readyz -curl http://localhost:8787/metrics -``` - ---- - -### Plugin Author - -The developer creating a custom learn plugin for a specific agent. - -**Interactions:** -- Implements `LearnPlugin` interface -- Plugins auto-discovered from `headroom/learn/plugins/` directory -- Contributes to Headroom - -**Needs:** -- Clear plugin interface documentation -- Example plugins to reference -- Test utilities - -**Plugin Template:** -```python -from headroom.learn.base import LearnPlugin, ConversationScanner - -class MyAgentPlugin(LearnPlugin): - @property - def name(self) -> str: - return "my_agent" - - @property - def display_name(self) -> str: - return "My Agent" - - def detect(self) -> bool: - # Check if this agent has data on the current machine - pass - - def discover_projects(self) -> list[ProjectInfo]: - # Discover all projects with conversation data - pass - - def scan_project(self, project: ProjectInfo, max_workers: int = 1) -> list[SessionData]: - # Scan all sessions for a project - pass - - def create_writer(self) -> ContextWriter: - # Return the appropriate ContextWriter for this agent - pass -``` - ---- - -### Enterprise Evaluator - -The person assessing Headroom for organizational adoption. - -**Interactions:** -- Reviews security documentation -- Assesses compliance guarantees -- Evaluates operational characteristics - -**Needs:** -- Clear data handling guarantees -- Security and privacy documentation -- Compliance certifications (if any) -- SOC2/GDPR considerations - -**Security Configuration:** -```bash -# Maximum privacy settings -HEADROOM_TELEMETRY=off -HEADROOM_STATELESS=true -headroom proxy --no-cache --no-optimize -``` - ---- - -## Interaction Patterns - -### User → Headroom - -``` -┌──────────────┐ ┌────────────────┐ ┌─────────────┐ -│ User's AI │──────▶│ Headroom │──────▶│ Provider │ -│ Agent │ │ Proxy │ │ API │ -└──────────────┘ └───────┬────────┘ └─────────────┘ - │ - ▼ - ┌──────────────┐ - │ Dashboard │ - │ (optional) │ - └──────────────┘ -``` - -**Flow:** -1. User's AI agent sends request to Headroom proxy -2. Headroom compresses context -3. Compressed request sent to provider API -4. Response returned to agent -5. Optional: savings logged to dashboard - ---- - -### Operator → Headroom - -``` -┌──────────┐ ┌────────────────┐ ┌─────────────┐ -│ Operator │──────▶│ Health │──────▶│ Metrics │ -│ │ │ Endpoints │ │ Server │ -└──────────┘ └────────────────┘ └─────────────┘ - │ - ▼ -┌────────────────┐ -│ Logs │ -│ (stdout/file) │ -└────────────────┘ -``` - -**Flow:** -1. Operator checks health endpoints -2. Reviews Prometheus metrics -3. Monitors logs for errors -4. Manages configuration - ---- - -### Plugin Author → Headroom - -``` -┌──────────────┐ ┌────────────────┐ ┌─────────────┐ -│ Plugin │──────▶│ Plugin │──────▶│ Registry │ -│ Author │ │ Interface │ │ + Tests │ -└──────────────┘ └────────────────┘ └─────────────┘ -``` - -**Flow:** -1. Plugin author implements LearnPlugin -2. Plugins are auto-discovered from `headroom/learn/plugins/` directory -3. Writes unit tests -4. Submits contribution - ---- - -## Permissions Model - -| Actor | Config | Read Metrics | Admin | Plugin | -|-------|--------|--------------|-------|--------| -| End User | ✓ (own) | ✓ (own) | - | - | -| Operator | ✓ (full) | ✓ (all) | ✓ | - | -| Plugin Author | - | - | - | ✓ (write) | -| Enterprise Evaluator | - | ✓ (security) | - | - | - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial actors document | diff --git a/docs/spec/007-behavior.md b/docs/spec/007-behavior.md deleted file mode 100644 index b0bcabbb7..000000000 --- a/docs/spec/007-behavior.md +++ /dev/null @@ -1,178 +0,0 @@ -# 007. Behavior - -**Status:** done - -## Proxy Modes - -### Passthrough - -Headroom forwards requests without modification. - -**Behavior:** -- All requests pass through unchanged -- Response headers may be modified for telemetry -- No compression applied -- Useful for testing or debugging - -**Configuration:** `headroom proxy --no-optimize` - -**Request Flow:** -``` -Client → Proxy → Provider API → Response -``` - ---- - -### Token Mode - -Headroom applies deterministic transforms to requests. - -**Behavior:** -- SmartCrusher compresses JSON tool outputs -- CacheAligner stabilizes prefixes -- RollingWindow caps context tokens -- CCR caching enabled -- Token budget enforced - -**Configuration:** `HEADROOM_MODE=token` or `headroom proxy --mode token` - -**Request Flow:** -``` -Client → Proxy → [SmartCrusher] → [CacheAligner] - → [RollingWindow] → [CCR Cache] - → Provider API → Response -``` - ---- - -### Cache Mode - -Headroom preserves prior turns where possible to maximize provider prefix-cache hit rate. - -**Behavior:** -- Freezes provider-confirmed cached prefixes -- Compresses the mutable tail of the request -- Trades some token savings for better cache stability - -**Configuration:** `HEADROOM_MODE=cache` or `headroom proxy --mode cache` - ---- - -## Session Modes - -Session modes control how Headroom handles context windows. - -| Mode | Description | Use Case | -|------|-------------|----------| -| `token` | Prioritize token removal | Default proxy mode | -| `cache` | Preserve prior turns for provider prefix-cache stability | Long Claude/Codex sessions | -| passthrough | Disable optimization with `--no-optimize` | Debugging | - ---- - -## Request Lifecycle - -``` -1. Request received at proxy endpoint - │ - ▼ -2. Session lookup/creation - │ - Extract session ID from headers - │ - Create new session if not found - │ - ▼ -3. Mode determination - │ - Check HEADROOM_MODE - │ - Check runtime headers - │ - Determine active plugins - │ - ▼ -4. Compression pipeline execution - │ a. Token counting - │ b. Semantic cache check - │ c. Content type detection - │ d. Transform selection - │ e. Summary compression (if eligible) - │ f. Token budget enforcement - │ - ▼ -5. Forward to provider API - │ - Route to correct provider - │ - Apply API key from config - │ - Handle timeouts - │ - ▼ -6. Response capture - │ - Log request/response metadata - │ - Calculate savings - │ - ▼ -7. Savings calculation - │ - tokens_before - tokens_after - │ - percentage = savings / tokens_before - │ - ▼ -8. Telemetry emission - │ - Prometheus metrics - │ - Optional tracing - │ - ▼ -9. Response returned to client - - X-Headroom-Savings header - - X-Headroom-Original-Tokens header - - X-Headroom-Compressed-Tokens header -``` - ---- - -## Error Handling - -| Error Type | HTTP Code | Behavior | -|------------|----------|----------| -| Provider timeout | 504 | Retry up to 3 times with exponential backoff | -| Invalid request | 400 | Return error details in body | -| Compression failure | 500 | Fall back to passthrough mode | -| Provider error | Provider code | Return provider error to client | -| Internal error | 500 | Return 500, log details | -| Rate limited | 429 | Return retry-after header | - -**Retry Configuration:** -```python -@dataclass -class RetryConfig: - max_retries: int = 3 - base_delay: float = 1.0 - max_delay: float = 60.0 - exponential_base: float = 2.0 -``` - ---- - -## Response Headers - -Headroom adds headers to all compressed responses: - -``` -X-Headroom-Savings: 0.35 -X-Headroom-Original-Tokens: 8192 -X-Headroom-Compressed-Tokens: 5325 -X-Headroom-Compression-Type: semantic,summary -X-Headroom-Request-Id: abc123 -X-Headroom-Cache-Hit: false -``` - -**Header Descriptions:** -- `X-Headroom-Savings` — Token savings percentage (0.35 = 35%) -- `X-Headroom-Original-Tokens` — Token count before compression -- `X-Headroom-Compressed-Tokens` — Token count after compression -- `X-Headroom-Compression-Type` — Types of compression applied -- `X-Headroom-Request-Id` — Unique request identifier -- `X-Headroom-Cache-Hit` — Whether result was from cache - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial behavior document | diff --git a/docs/spec/008-capabilities.md b/docs/spec/008-capabilities.md deleted file mode 100644 index fabf11305..000000000 --- a/docs/spec/008-capabilities.md +++ /dev/null @@ -1,254 +0,0 @@ -# 008. Capabilities - -**Status:** done - -## Feature Matrix - -| Capability | Proxy | SDK | Wrap | MCP | ASGI | LiteLLM | -|------------|:-----:|:---:|:----:|:---:|:----:|:-------:| -| Semantic compression | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Summary compression | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Token budget management | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Learn mode | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Session tracking | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| CCR feedback | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| TOIN tagging | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Savings tracking | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Dashboard | ✓ | - | ✓ | - | - | - | -| Health endpoints | ✓ | - | - | - | - | - | -| Metrics (Prometheus) | ✓ | - | - | - | - | - | - ---- - -## Compression Capabilities - -### Proxy Cache - -**Description:** The proxy has semantic cache support and CCR-backed retrieval, controlled by CLI configuration. - -**Configuration:** -```bash -headroom proxy # cache enabled by default -headroom proxy --no-cache -``` - -**Behavior:** -1. Hash input content -2. Check cache for similar entries (configurable threshold) -3. Return cached response if match found (CCR retrieval) -4. Update cache on miss -5. Store compressed content for future retrieval - -**CCR Configuration:** -```python -@dataclass -class CCRConfig: - enabled: bool = True - storage: ContentStorage | None = None - cache_ttl: int = 3600 - similarity_threshold: float = 0.85 - max_results: int = 10 -``` - ---- - -### Summary Compression - -**Description:** Compresses long context using summarization. - -**Configuration:** -```bash -# Note: HEADROOM_SUMMARY_* env vars are not yet implemented. -# Summary compression is currently configured programmatically only. -``` - -**Behavior:** -1. Count input tokens -2. If over threshold, apply summary compression -3. Preserve key information (configurable priority) -4. Track summary statistics - -**Summary Pipeline:** -```python -class SummaryCompressor: - def __init__( - self, - threshold: int = 5000, - target_ratio: float = 0.3, - priority_preservation: bool = True, - ) -> None: - pass - - def compress( - self, - content: str, - context: TransformContext, - ) -> TransformResult: - pass -``` - ---- - -### Token Budget Manager - -**Description:** Enforces token budget limits per session via RollingWindow. - -**Configuration:** -```python -@dataclass -class RollingWindowConfig: - enabled: bool = True - keep_system: bool = True # Never drop system prompt - keep_last_turns: int = 2 # Never drop last N turns - output_buffer_tokens: int = 4000 # Reserve for output -``` - -**Behavior:** -1. Track token usage per session -2. Enforce budget limits via rolling window -3. Preserve system prompt and last N turns -4. Reserve output buffer tokens - ---- - -## Intelligent Context Management - -**Description:** Semantic-aware context management with TOIN integration. - -```python -@dataclass -class IntelligentContextConfig: - enabled: bool = True - use_importance_scoring: bool = True - scoring_weights: ScoringWeights = field(default_factory=ScoringWeights) - toin_integration: bool = True - toin_confidence_threshold: float = 0.3 -``` - -**Scoring Weights:** -```python -@dataclass -class ScoringWeights: - recency: float = 0.20 - semantic_similarity: float = 0.20 - toin_importance: float = 0.25 - error_indicator: float = 0.15 - forward_reference: float = 0.15 - token_density: float = 0.05 -``` - ---- - -## CCR Configuration - -**Description:** Compress-Cache-Retrieve makes compression reversible. - -```python -@dataclass -class CCRConfig: - enabled: bool = True - store_max_entries: int = 1000 - store_ttl_seconds: int = 300 - inject_retrieval_marker: bool = True - feedback_enabled: bool = True - min_items_to_cache: int = 20 - inject_tool: bool = True - inject_system_instructions: bool = False -``` - ---- - -## SmartCrusher (Statistical JSON Compression) - -**Description:** Preserves JSON schema while reducing array size via statistical analysis. - -```python -@dataclass -class SmartCrusherConfig: - enabled: bool = True - min_items_to_analyze: int = 5 - min_tokens_to_crush: int = 200 - variance_threshold: float = 2.0 - uniqueness_threshold: float = 0.1 - similarity_threshold: float = 0.8 - max_items_after_crush: int = 15 - preserve_change_points: bool = True - use_feedback_hints: bool = True - toin_confidence_threshold: float = 0.3 - relevance: RelevanceScorerConfig = field(default_factory=RelevanceScorerConfig) - anchor: AnchorConfig = field(default_factory=AnchorConfig) - dedup_identical_items: bool = True - first_fraction: float = 0.3 - last_fraction: float = 0.15 -``` - -**Relevance Scoring:** -```python -@dataclass -class RelevanceScorerConfig: - tier: Literal["bm25", "embedding", "hybrid"] = "hybrid" - bm25_k1: float = 1.5 - bm25_b: float = 0.75 - embedding_model: str = field(default_factory=lambda: ML_MODEL_DEFAULTS.sentence_transformer) - hybrid_alpha: float = 0.5 - adaptive_alpha: bool = True - relevance_threshold: float = 0.25 -``` - -**Anchor Allocation:** -```python -@dataclass -class AnchorConfig: - anchor_budget_pct: float = 0.25 - min_anchor_slots: int = 3 - max_anchor_slots: int = 12 - default_front_weight: float = 0.5 - default_back_weight: float = 0.4 - default_middle_weight: float = 0.1 - search_front_weight: float = 0.75 - logs_back_weight: float = 0.75 -``` - ---- - -## Agent-Specific Capabilities - -### Claude - -- Session branch comparison -- Token headroom mode -- Tool use tracking -- Multi-modal support (images) - -### Codex - -- Rate limit handling -- Code completion optimization -- Batch request support - -### Gemini - -- Multi-modal inputs -- Function calling support -- Context caching API - ---- - -## Deployment Capabilities - -| Feature | Docker | Native | Embedded | -|---------|:------:|:------:|:--------:| -| Standalone proxy | ✓ | ✓ | - | -| Health endpoints | ✓ | ✓ | - | -| Prometheus metrics | ✓ | ✓ | - | -| Dashboard | ✓ | ✓ | - | -| Volume mounts | ✓ | - | - | -| Environment overrides | ✓ | ✓ | ✓ | - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial capabilities document | diff --git a/docs/spec/009-compliance.md b/docs/spec/009-compliance.md deleted file mode 100644 index d7046c68a..000000000 --- a/docs/spec/009-compliance.md +++ /dev/null @@ -1,82 +0,0 @@ -# 009. Compliance - -**Status:** done - -## Data Handling Guarantees - -### Default Behavior (No Export) - -| Data Type | Stored | Exported | Logged | -|-----------|:------:|:--------:|:------:| -| Prompts | Optional (cache) | Never | Never | -| Responses | Optional (cache) | Never | Never | -| Savings metrics | Yes | Never | Never | -| Session metadata | Yes | Never | Never | -| Telemetry | Aggregated | Never | Never | - ---- - -### With Exporters Configured - -**Warning:** Enabling exporters may send data outside your infrastructure. - -| Exporter | Data Sent | Destination | -|----------|-----------|-------------| -| Prometheus | Metrics only | Prometheus server | -| OpenTelemetry | Traces/spans | OTLP endpoint | -| Custom webhook | Configurable | HTTP endpoint | - ---- - -## Privacy Commitments - -1. **No prompt logging by default** — Headroom never logs prompt content unless explicitly configured -2. **No data leaves proxy by default** — All processing happens locally -3. **User control** — All data handling is configurable via environment variables -4. **Transparency** — Response headers indicate compression was applied -5. **No telemetry to Headroom project** — No data sent to external servers without explicit opt-in - ---- - -## Compliance Considerations - -### SOC 2 - -*To be documented if applicable.* - -### GDPR - -| Requirement | Headroom Support | -|-------------|:----------------:| -| Data minimization | ✓ Default no-logging | -| Right to deletion | ✓ Cache can be cleared | -| Data portability | Export available via API | -| Breach notification | N/A (no external data) | - -### HIPAA - -*To be documented if applicable.* - ---- - -## Configuration for Maximum Privacy - -```bash -HEADROOM_TELEMETRY=off -HEADROOM_STATELESS=true -headroom proxy --no-cache --no-optimize -``` - -This configuration results in: -- No prompt data stored -- No data exported -- No analytics collected -- Headroom acts as a passthrough proxy - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial compliance document | diff --git a/docs/spec/010-data.md b/docs/spec/010-data.md deleted file mode 100644 index c1a75234d..000000000 --- a/docs/spec/010-data.md +++ /dev/null @@ -1,174 +0,0 @@ -# 010. Data - -**Status:** done - -## Storage Overview - -| Store | Location | Type | Purpose | -|-------|----------|------|---------| -| SQLite | `headroom.db` (cwd or `~/.headroom/`) | Local file | Metrics, sessions, compression store | -| Memory DB | `~/.headroom/headroom_memory.db` | Local file | Memory system (optional) | -| Vector Index | `~/.headroom/headroom_memory_vectors.db` | Local file | Semantic search (optional, requires sqlite-vec) | -| Graph Store | `~/.headroom/headroom_memory_graph.db` | Local file | Memory relationships | -| Compression cache | `~/.headroom/cache/` | Directory | Semantic + summary cache | - -**Note:** Default store URL is `sqlite:///headroom.db` (relative to working directory). - ---- - -## SQLite Schema - -### Core Tables - -**sessions:** -```sql -CREATE TABLE sessions ( - session_id TEXT PRIMARY KEY, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - metadata TEXT -- JSON -); -``` - -**requests:** -```sql -CREATE TABLE requests ( - id TEXT PRIMARY KEY, - timestamp TEXT NOT NULL, - model TEXT NOT NULL, - stream INTEGER NOT NULL, - mode TEXT NOT NULL, - tokens_input_before INTEGER NOT NULL, - tokens_input_after INTEGER NOT NULL, - tokens_output INTEGER, - block_breakdown TEXT NOT NULL, -- JSON - waste_signals TEXT NOT NULL, -- JSON - stable_prefix_hash TEXT, - cache_alignment_score REAL, - cached_tokens INTEGER, - transforms_applied TEXT NOT NULL, -- JSON - tool_units_dropped INTEGER DEFAULT 0, - turns_dropped INTEGER DEFAULT 0, - messages_hash TEXT, - error TEXT -); - -CREATE INDEX idx_timestamp ON requests(timestamp); -CREATE INDEX idx_model ON requests(model); -CREATE INDEX idx_mode ON requests(mode); -``` - -**cache_entries:** -```sql -CREATE TABLE cache_entries ( - cache_key TEXT PRIMARY KEY, - input_hash TEXT NOT NULL, - output TEXT NOT NULL, - compression_type TEXT NOT NULL, - tokens_before INTEGER NOT NULL, - tokens_after INTEGER NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - ttl INTEGER DEFAULT 3600, - hit_count INTEGER DEFAULT 0, - last_accessed TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); -``` - -**compression_store (CCR):** -```sql -CREATE TABLE compression_store ( - hash TEXT PRIMARY KEY, - original TEXT NOT NULL, - metadata TEXT, -- JSON - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - expires_at TIMESTAMP NOT NULL -); -``` - ---- - -## Environment Variables - -### Database - -| Variable | Default | Description | -|----------|---------|-------------| -| `HEADROOM_WORKSPACE_DIR` | `~/.headroom` | Workspace root; all DBs live under this directory | -| `HEADROOM_CONFIG_DIR` | `~/.headroom/config` | Config root (read-mostly: models.json, per-plugin config) | - -### Cache - -| Variable | Default | Description | -|----------|---------|-------------| -| CLI `--no-cache` | unset | Disable semantic cache for the proxy process | -| `HEADROOM_WORKSPACE_DIR` | `~/.headroom` | Workspace root for proxy state, logs, memory, and savings | -| `HEADROOM_STATELESS` | `false` | Disable filesystem writes and keep runtime state in memory | - ---- - -## Data Retention - -| Data Type | Retention | Auto-cleanup | -|-----------|-----------|:------------:| -| Savings history | Forever | No | -| Session history | 30 days | Yes (configurable) | -| Compression cache | 7 days | Yes | -| Telemetry | 90 days | Yes | -| Dashboard state | 30 days | Yes | - ---- - -## Data Export - -### Savings Export - -```bash -curl http://localhost:8787/stats -``` - -Response: -```json -{ - "savings": [ - { - "date": "2026-04-16", - "original_tokens": 8192, - "compressed_tokens": 5325, - "savings_percentage": 0.35 - } - ], - "total_savings": 1234567 -} -``` - -### Session Export - -```bash -curl http://localhost:8787/stats -``` - ---- - -## Backup - -### Manual Backup - -```bash -tar -czf headroom-backup.tar.gz ~/.headroom/ -``` - -### Storage Location - -Relocate all storage by setting the workspace root: - -```bash -export HEADROOM_WORKSPACE_DIR=/mnt/state -``` - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial data document | diff --git a/docs/spec/011-deployment.md b/docs/spec/011-deployment.md deleted file mode 100644 index b9be6f433..000000000 --- a/docs/spec/011-deployment.md +++ /dev/null @@ -1,177 +0,0 @@ -# 011. Deployment - -**Status:** done - -## Deployment Profiles - -### Docker Profile - -**Image:** `headroom-ai/headroom:latest` - -**Dockerfile:** -```dockerfile -FROM python:3.12-slim - -RUN pip install headroom-ai - -EXPOSE 8787 - -ENTRYPOINT ["headroom", "proxy"] -CMD ["--host", "0.0.0.0", "--port", "8787"] -``` - -**docker-compose.yml:** -```yaml -version: '3.8' -services: - headroom: - image: headroom-ai/headroom:latest - ports: - - "8787:8787" - environment: - - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - - HEADROOM_MODE=token - volumes: - - headroom-data:/root/.headroom - -volumes: - headroom-data: -``` - -**Run:** -```bash -docker-compose up -d -``` - ---- - -### Native Profile - -**Installation:** -```bash -pip install headroom-ai -``` - -**Run:** -```bash -headroom proxy --host 0.0.0.0 --port 8787 -``` - ---- - -### Embedded Profile - -**Usage:** -```python -from headroom import HeadroomClient - -client = HeadroomClient( - api_key="your-api-key", - base_url="http://localhost:8787" -) - -result = await client.compress(messages) -``` - ---- - -## Cloud Presets - -### AWS (EC2/ECS) - -```yaml -# ~/.headroom/config.yaml -deployment: - profile: aws - instance_type: t3.medium - -compression: - enabled: true - max_tokens: 8192 - -cache: - backend: redis - redis_url: redis://localhost:6379 -``` - -### Google Cloud (Cloud Run) - -```yaml -deployment: - profile: gcp - region: us-central1 - memory: 512Mi - cpu: 1 -``` - -### Azure (Container Apps) - -```yaml -deployment: - profile: azure - resource_group: headroom-rg -``` - ---- - -## Runtime Configuration - -### Environment Variables - -| Variable | Default | Description | -|----------|---------|-------------| -| `HEADROOM_MODE` | `token` | Proxy mode (`token` or `cache`) | -| `HEADROOM_PORT` | `8787` | Proxy port | -| `HEADROOM_HOST` | `127.0.0.1` | Proxy host | -| `ANTHROPIC_API_KEY` | - | Anthropic API key | -| `OPENAI_API_KEY` | - | OpenAI API key | -| `HEADROOM_TELEMETRY` | `off` (opt-in) | Set to `on` to opt in to telemetry | - -### Config File - -```yaml -# ~/.headroom/config.yaml -proxy: - host: 0.0.0.0 - port: 8787 - -compression: - enabled: true - max_tokens: 4096 - overlap_tokens: 512 - content_sensitivity: 0.5 - preserve_system_messages: true - priority_tokens: 1024 - -cache: - enabled: true - ttl: 3600 - max_size: 10000 - -telemetry: - metrics: - enabled: true - tracing: - enabled: false - -learn: - enabled: false -``` - ---- - -## Resource Requirements - -| Deployment | CPU | Memory | Storage | -|------------|-----|--------|---------| -| Minimal | 0.5 core | 512MB | 1GB | -| Default | 1 core | 1GB | 5GB | -| Enterprise | 2 cores | 2GB | 20GB | - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial deployment document | diff --git a/docs/spec/012-diagrams.md b/docs/spec/012-diagrams.md deleted file mode 100644 index d471b5021..000000000 --- a/docs/spec/012-diagrams.md +++ /dev/null @@ -1,140 +0,0 @@ -# 012. Diagrams - -**Status:** done - -## Component Diagram - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Headroom │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │ -│ │ Proxy │ │ SDK │ │ Wrap │ │ MCP │ │ -│ │ Server │ │ (Python) │ │ CLI │ │ Server │ │ -│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └──────┬──────┘ │ -│ │ │ │ │ │ -│ ┌────┴──────────────┴──────────────┴─────────────────┴──────┐ │ -│ │ Compression Layer │ │ -│ │ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │ │ -│ │ │ Semantic │ │ Summary │ │ Token Budget │ │ │ -│ │ │ Cache │ │ Compress │ │ Manager │ │ │ -│ │ └────────────┘ └────────────┘ └────────────────────┘ │ │ -│ └───────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌───────────────────────────────────────────────────────────┐ │ -│ │ Learn System │ │ -│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────────────┐ │ │ -│ │ │Claude │ │ Codex │ │ Gemini │ │ ...more │ │ │ -│ │ │Plugin │ │ Plugin │ │ Plugin │ │ plugins │ │ │ -│ │ └────────┘ └────────┘ └────────┘ └────────────────┘ │ │ -│ └───────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │ -│ │ Dashboard │ │ CCR │ │ TOIN │ │ -│ │ (Next.js) │ │ (Claude │ │ (Tenant-specific │ │ -│ │ │ │ Code Relay)│ │ ONNX) │ │ -│ └──────────────┘ └──────────────┘ └──────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - ---- - -## Request Flow Sequence Diagram - -``` -Client Headroom Compression CCR Provider - Proxy Layer Cache API - │ │ │ │ │ - │──POST /v1/msg──▶│ │ │ │ - │ │ │ │ │ - │ │──Count tokens──▶│ │ │ - │ │ │ │ │ - │ │────Cache check────▶│ │ │ - │ │ │◀───hit──────│ │ - │ │ │◀───CCR retrieval───────│ - │ │ │ │ │ - │ │───Summary compression───▶│ │ - │ │ │◀──budget enforcement─────│ - │ │ │ │ │ - │ │─────Forward compressed─────▶│ │ - │ │ │ │◀──Response──│ - │ │◀──────────────────────────────────────│ - │◀──Response──│ │ │ │ -``` - ---- - -## CCR Cache Flow - -``` -Request Headroom CCR Storage - │ Proxy Cache - │ │ │ - │──compress──▶│ │ - │ │──hash────▶│ - │ │ │──store──▶│ - │ │◀──stored──│ │ - │ │──CCR hash │ - │◀──Response──│ │ - │ │ │ -``` - ---- - -## Learn System Flow - -``` -Session Headroom Learn Plugin - Data Proxy System Registry - │ │ │ │ - │──session──▶│ │ │ - │ │──analyze──▶│ │ - │ │ │──load────▶│ - │ │ │◀─Result───│ - │ │◀──Feedback──│ │ - │ │──Improve compression │ - │◀───────────│ │ │ -``` - ---- - -## Data Flow - -``` -┌──────────────┐ -│ User's │ -│ AI Agent │ -└──────┬───────┘ - │ HTTP - ▼ -┌──────────────┐ ┌─────────────────────────────────────┐ -│ Headroom │────▶│ Compression Layer │ -│ Proxy │ │ │ -└──────┬───────┘ │ ┌─────────┐ ┌──────────────┐ │ - │ │ │ Semantic│ │ Summary │ │ - │ │ │ Cache │ │ Compression │ │ - │ │ └────┬───┘ └──────┬───────┘ │ - │ │ │ │ │ - │ │ ┌────┴─────────────┴──────┐ │ - │ │ │ Token Budget │ │ - │ │ │ Manager │ │ - │ │ └────────────┬───────────┘ │ - │ └───────────────┼─────────────────┘ - │ │ - │ │ Compressed request - ▼ ▼ -┌──────────────┐ ┌──────────────┐ -│ Dashboard │ │ Provider │ -│ (optional) │ │ API │ -└──────────────┘ └──────────────┘ -``` - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial diagrams document | diff --git a/docs/spec/013-disaster-recovery.md b/docs/spec/013-disaster-recovery.md deleted file mode 100644 index dcc5f6a08..000000000 --- a/docs/spec/013-disaster-recovery.md +++ /dev/null @@ -1,159 +0,0 @@ -# 013. Disaster Recovery - -**Status:** done - -## Failure Modes - -### Proxy Failures - -| Failure | Impact | Recovery | -|---------|--------|----------| -| Proxy crash | Service unavailable | Restart or failover | -| OOM | Service unavailable | Restart with more memory | -| Network partition | Cannot reach providers | Retry with backoff | - -### Compression Failures - -| Failure | Impact | Recovery | -|---------|--------|----------| -| Compression timeout | Request delayed | Retry with passthrough | -| Transform error | Compression skipped | Log error, passthrough | -| Budget exceeded | Truncation | Notify via headers | - -### Storage Failures - -| Failure | Impact | Recovery | -|---------|--------|----------| -| SQLite corruption | Data loss | Restore from backup | -| Cache full | CCR disabled | Clear old entries | -| Disk full | Write failures | Expand storage | - ---- - -## Backup Strategies - -### Manual Backup - -```bash -# Full backup -tar -czf headroom-backup-$(date +%Y%m%d).tar.gz ~/.headroom/ - -# Incremental (last 24h) -sqlite3 ~/.headroom/headroom_memory.db ".backup /tmp/headroom_incremental.db" -``` - -### Automated Backup - -```bash -# Cron job (daily at 2am) -0 2 * * * tar -czf /backup/headroom-$(date +\%Y\%m\%d).tar.gz ~/.headroom/ -``` - -### External Storage - -> **Note:** External PostgreSQL/Redis storage is not yet implemented. Headroom uses SQLite at `~/.headroom/` (configurable via `HEADROOM_WORKSPACE_DIR`). The `HEADROOM_DB_URL` and `HEADROOM_CACHE_BACKEND` vars do not exist. - ---- - -## Recovery Procedures - -### Proxy Recovery - -1. **Restart proxy:** -```bash -# Docker -docker-compose restart headroom - -# Native -pkill headroom && headroom proxy & -``` - -2. **Check health:** -```bash -curl http://localhost:8787/health -curl http://localhost:8787/readyz -``` - -### Database Recovery - -1. **Restore from backup:** -```bash -# Stop headroom -pkill headroom - -# Restore SQLite -rm ~/.headroom/headroom_memory.db -tar -xzf headroom-backup-20260416.tar.gz -C ~/ - -# Restart headroom -headroom proxy & -``` - -2. **Verify data:** -```bash -curl http://localhost:8787/stats -``` - ---- - -## Data Migration - -### Schema Migration - -```python -async def migrate_v1_to_v2(): - async with aiosqlite.connect(DB_PATH) as db: - await db.execute(""" - ALTER TABLE sessions - ADD COLUMN agent_version TEXT - """) - await db.commit() -``` - -### Data Export/Import - -```bash -# Export -curl http://localhost:8787/api/v1/export > backup.json - -# Import -curl -X POST http://localhost:8787/api/v1/import \ - -H "Content-Type: application/json" \ - -d @backup.json -``` - ---- - -## High Availability - -### Active-Active - -```yaml -services: - headroom-1: - image: headroom-ai/headroom:latest - ports: - - "8787:8787" - - headroom-2: - image: headroom-ai/headroom:latest - ports: - - "8788:8787" - - redis: - image: redis:latest -``` - -### Health Check Failover - -```bash -curl http://primary:8787/health || curl http://backup:8787/health -``` - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial disaster recovery document | diff --git a/docs/spec/014-governance.md b/docs/spec/014-governance.md deleted file mode 100644 index 03640193a..000000000 --- a/docs/spec/014-governance.md +++ /dev/null @@ -1,129 +0,0 @@ -# 014. Governance - -**Status:** done - -## Project Structure - -- **Repository:** `github.com/JerrettDavis/headroom` -- **License:** Apache 2.0 -- **Main Languages:** Python (core), TypeScript (SDK/dashboard) - ---- - -## Release Cadence - -| Channel | Frequency | Stability | -|---------|-----------|-----------| -| Stable | Monthly | Production-ready | -| Beta | As needed | May have issues | -| Nightly | Daily | Unstable | - ---- - -## Semantic Versioning - -Headroom follows semver: - -- **MAJOR:** Breaking changes to API, CLI, or core behavior -- **MINOR:** New features, backwards-compatible -- **PATCH:** Bug fixes, backwards-compatible - ---- - -## Decision Making - -### RFC Process - -1. Open GitHub issue with `[RFC]` prefix -2. Gather community feedback (2 weeks minimum) -3. Core team reviews -4. Decision documented in ADRs -5. Implementation proceeds - -### Criteria for Core Team Approval - -- Consistent with project vision -- Does not break existing guarantees -- Implementation is feasible -- Tests can be written - ---- - -## Spec-Driven Development - -This specification is the **canonical source of truth** for Headroom behavior: - -| Rule | Description | -|------|-------------| -| **Canonical** | When code and spec diverge, the spec is the target | -| **Living** | Spec updates required for behavior-changing changes | -| **Comprehensive** | Spec covers every user-visible surface | -| **Language-agnostic** | Enables complete rewrite in any language | - -### Spec Change Process - -1. Propose change in GitHub issue -2. Discuss in RFC format -3. Update relevant spec section -4. Update SPEC.md version and change log -5. Implement code change -6. Verify implementation matches spec - ---- - -## Supply Chain Posture - -| Component | Policy | -|-----------|--------| -| Dependencies | Pin versions, audit regularly | -| Build artifacts | Reproducible builds | -| Signing | Code signed for releases | -| Vulnerability reporting | See SECURITY.md | - ---- - -## Contributing - -### Development Setup - -```bash -# Clone repository -git clone https://github.com/JerrettDavis/headroom.git -cd headroom - -# Create virtual environment -python -m venv venv -source venv/bin/activate - -# Install dependencies -pip install -e ".[dev]" - -# Run tests -pytest -``` - -### Code Style - -- Format: `ruff format` -- Lint: `ruff check` -- Type check: `mypy` - ---- - -## Code of Conduct - -See `CODE_OF_CONDUCT.md`. - ---- - -## Security - -See `SECURITY.md` for vulnerability reporting and response timeline. - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial governance document | diff --git a/docs/spec/015-interfaces.md b/docs/spec/015-interfaces.md deleted file mode 100644 index 3972cd87e..000000000 --- a/docs/spec/015-interfaces.md +++ /dev/null @@ -1,351 +0,0 @@ -# 015. Interfaces - -**Status:** done - -## CLI Surface - -### `headroom proxy` - -Start the Headroom proxy server. - -```bash -headroom proxy [OPTIONS] -``` - -**Options:** -| Flag | Default | Description | -|------|---------|-------------| -| `--host` | `127.0.0.1` | Bind host | -| `--port` | `8787` | Bind port | -| `--mode` | `token` | Optimization mode: `token` or `cache` | -| `--workers` | `1` | Uvicorn worker processes | -| `--limit-concurrency` | `1000` | Maximum concurrent connections before 503 | -| `--no-optimize` | `false` | Passthrough mode | -| `--no-cache` | `false` | Disable semantic cache | -| `--no-rate-limit` | `false` | Disable rate limiting | -| `--memory` | `false` | Enable persistent memory | -| `--learn` | `false` | Enable live traffic learning | -| `--backend` | `anthropic` | Backend: anthropic, bedrock, openrouter, anyllm, or litellm-* | -| `--telemetry` | `false` | Opt in to anonymous telemetry (off by default) | -| `--no-telemetry` | `false` | Force anonymous telemetry off (already the default) | -| `--stateless` | `false` | Disable filesystem writes | - ---- - -### `headroom evals` - -Run evaluation suite. - -```bash -headroom evals [OPTIONS] -``` - -**Options:** -| Flag | Default | Description | -|------|---------|-------------| -| `--suite` | `all` | Evaluation suite to run | -| `--output` | - | Output file for results | - ---- - -### `headroom install` - -Install agent integrations. - -```bash -headroom install [OPTIONS] -``` - -**Options:** -| Flag | Default | Description | -|------|---------|-------------| -| `--agent` | - | Agent type (claude/copilot/codex/aider/cursor/openclaw) | - ---- - -### `headroom mcp` - -Manage the Headroom MCP server. - -```bash -headroom mcp [OPTIONS] COMMAND [ARGS]... -``` - -**Commands:** -- `install` — Install the MCP server into detected coding agents -- `serve` — Start the stdio MCP server -- `status` — Check configuration status -- `uninstall` — Remove Headroom MCP config - ---- - -### `headroom perf` - -Run performance tests. - -```bash -headroom perf [OPTIONS] -``` - ---- - -### `headroom wrap` - -Wrap a command with Headroom proxy. - -```bash -headroom wrap [OPTIONS] -- [args...] -``` - -**Options:** -| Flag | Default | Description | -|------|---------|-------------| -| `--port` | `8787` | Proxy port | -| `--no-context-tool` / `--no-rtk` | `false` | Skip CLI context-tool setup | - -**Supported Commands:** -- `claude` — Wrap Claude Code -- `copilot` — Wrap GitHub Copilot -- `codex` — Wrap OpenAI Codex -- `aider` — Wrap Aider -- `cursor` — Wrap Cursor -- `openclaw` — Wrap OpenClaw - ---- - -### `headroom memory` - -Memory system management (requires numpy/hnswlib). - -```bash -headroom memory [OPTIONS] -``` - -**Commands:** -- `list` — List stored memories -- `stats` — Show memory statistics -- `search QUERY` — Search memories - ---- - -### `headroom learn` - -Run learn mode analysis. - -```bash -headroom learn [OPTIONS] -``` - -**Options:** -| Flag | Default | Description | -|------|---------|-------------| -| `--project` | current directory | Project directory to analyze | -| `--all` | `false` | Analyze all discovered projects | -| `--apply` | `false` | Write recommendations instead of dry-run | -| `--agent` | `auto` | Agent to analyze: auto, claude, codex, gemini, or plugin | -| `--model` | auto | LLM model for analysis | -| `--workers` | auto | Parallel workers for session scanning | - ---- - -### `headroom stats` - -Show savings statistics. - -```bash -headroom stats [OPTIONS] -``` - -**Options:** -| Flag | Default | Description | -|------|---------|-------------| -| `--period` | `24h` | Time period | -| `--format` | `table` | Output format (table, json, csv) | - ---- - -### `headroom config` - -Manage configuration. - -```bash -headroom config [COMMAND] [OPTIONS] -``` - -**Commands:** -- `get KEY` — Get config value -- `set KEY VALUE` — Set config value -- `list` — List all config -- `export` — Export config to file - ---- - -## HTTP API - -### Endpoints - -| Method | Path | Description | -|--------|------|-------------| -| `GET` | `/health` | Health check | -| `GET` | `/livez` | Liveness check | -| `GET` | `/readyz` | Readiness check | -| `POST` | `/v1/messages` | Proxy chat completions | -| `POST` | `/v1/embeddings` | Proxy embeddings | -| `POST` | `/v1/compress` | Direct compression | -| `POST` | `/v1/retrieve` | CCR retrieval | -| `GET` | `/stats` | Compression statistics | -| `GET` | `/metrics` | Prometheus metrics | - -### Request/Response Examples - -**POST /v1/messages:** -```bash -curl -X POST http://localhost:8787/v1/messages \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer sk-..." \ - -d '{ - "model": "gpt-4o", - "messages": [{"role": "user", "content": "Hello"}] - }' -``` - -**Response headers:** -``` -X-Headroom-Savings: 0.35 -X-Headroom-Original-Tokens: 8192 -X-Headroom-Compressed-Tokens: 5325 -``` - ---- - -## Environment Variables - -### Core - -| Variable | Default | Description | -|----------|---------|-------------| -| `HEADROOM_MODE` | `token` | Proxy optimization mode (`token` or `cache`) | -| `HEADROOM_PORT` | `8787` | Proxy port | -| `HEADROOM_HOST` | `127.0.0.1` | Proxy host | -| `HEADROOM_WORKERS` | `1` | Uvicorn worker count | -| `HEADROOM_LIMIT_CONCURRENCY` | `1000` | Maximum concurrent connections before 503 | -| `HEADROOM_MAX_CONNECTIONS` | `500` | Maximum upstream HTTP connections | -| `HEADROOM_MAX_KEEPALIVE` | `100` | Maximum upstream keep-alive connections | -| `HEADROOM_BUDGET` | - | Daily budget limit in USD | -| `HEADROOM_TELEMETRY` | `off` (opt-in) | Set to `on` to opt in to anonymous telemetry | -| `HEADROOM_STATELESS` | `false` | Disable filesystem writes | - -### Provider - -| Variable | Default | Description | -|----------|---------|-------------| -| `ANTHROPIC_API_KEY` | - | Anthropic API key | -| `OPENAI_API_KEY` | - | OpenAI API key | -| `GOOGLE_API_KEY` | - | Google AI API key | -| `COHERE_API_KEY` | - | Cohere API key | - -### Features - -| Variable | Default | Description | -|----------|---------|-------------| -| `HEADROOM_TELEMETRY` | `off` (opt-in) | Set to `on` to opt in to telemetry | -| `HEADROOM_MIN_EVIDENCE` | `5` | Minimum observations before live learning persists a pattern | -| `HEADROOM_PROXY_EXTENSIONS` | - | Comma-separated proxy extensions to enable | -| `HEADROOM_STATELESS` | `false` | Disable filesystem writes | -| `HEADROOM_MODEL_LIMITS` | - | Model limits override as JSON or file path | - -### Compression - -| Variable | Default | Description | -|----------|---------|-------------| -| `HEADROOM_MAX_TOKENS` | `4096` | Max tokens per request | -| `HEADROOM_TARGET_TOKENS` | - | Target tokens after compression | -| `HEADROOM_OVERLAP_TOKENS` | `512` | Overlap tokens for chunking | -| `HEADROOM_CONTENT_SENSITIVITY` | `0.5` | Content sensitivity (0-1) | -| `HEADROOM_PRESERVE_SYSTEM` | `true` | Preserve system messages | - ---- - -## Plugin ABI - -### Plugin Interface - -```python -from abc import ABC, abstractmethod -from headroom.learn.base import ConversationScanner, ContextWriter -from headroom.learn.models import ProjectInfo, SessionData - -class LearnPlugin(ConversationScanner): - """A self-contained learn plugin for a single coding agent.""" - - @property - @abstractmethod - def name(self) -> str: - """Short lowercase identifier (e.g., 'claude', 'cursor').""" - ... - - @property - @abstractmethod - def display_name(self) -> str: - """Human-readable name (e.g., 'Claude Code', 'Cursor').""" - ... - - @abstractmethod - def detect(self) -> bool: - """Return True if this agent has data on the current machine.""" - ... - - @abstractmethod - def discover_projects(self) -> list[ProjectInfo]: - """Discover all projects with conversation data.""" - ... - - @abstractmethod - def scan_project(self, project: ProjectInfo, max_workers: int = 1) -> list[SessionData]: - """Scan all sessions for a project.""" - ... - - @abstractmethod - def create_writer(self) -> ContextWriter: - """Return the appropriate ContextWriter for this agent.""" - ... -``` - -### Plugin Registration - -Plugins are auto-discovered from `headroom/learn/plugins/` directory. - -**Manual registration:** -```python -from headroom.learn import plugin_registry - -plugin_registry.register(MyPlugin()) -``` - -### Plugin Config - -```yaml -# ~/.headroom/config.yaml -learn: - enabled: true - plugins: - - name: claude - enabled: true - config: - session_modes: - - auto - - learn - - disabled - - name: my_plugin - enabled: true - config: - custom_option: value -``` - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial interfaces document | diff --git a/docs/spec/016-observability.md b/docs/spec/016-observability.md deleted file mode 100644 index fae8b5fcf..000000000 --- a/docs/spec/016-observability.md +++ /dev/null @@ -1,173 +0,0 @@ -# 016. Observability - -**Status:** done - -## Telemetry - -### Metrics - -Headroom exposes Prometheus metrics at `/metrics`. - -**Key Metrics:** - -| Metric | Type | Description | -|--------|------|-------------| -| `headroom_requests_total` | Counter | Total requests | -| `headroom_tokens_original` | Counter | Original token count | -| `headroom_tokens_compressed` | Counter | Compressed token count | -| `headroom_savings_percent` | Histogram | Savings distribution | -| `headroom_cache_hits_total` | Counter | Cache hits | -| `headroom_cache_misses_total` | Counter | Cache misses | -| `headroom_compression_duration_seconds` | Histogram | Compression latency | -| `headroom_request_duration_seconds` | Histogram | Total request latency | - -**Prometheus scrape config:** -```yaml -scrape_configs: - - job_name: 'headroom' - static_configs: - - targets: ['localhost:8787'] - metrics_path: '/metrics' -``` - ---- - -### Tracing - -OpenTelemetry tracing support. - -**Configuration (Langfuse):** -```bash -LANGFUSE_PUBLIC_KEY=pk-lf-... -LANGFUSE_SECRET_KEY=sk-lf-... -HEADROOM_LANGFUSE_ENABLED=1 -# Optional: override endpoint and service name -# LANGFUSE_BASE_URL=https://cloud.langfuse.com -# HEADROOM_LANGFUSE_SERVICE_NAME=headroom -``` - -**Spans:** -| Span | Description | -|------|-------------| -| `headroom.proxy.request` | Full request lifecycle | -| `headroom.compression` | Compression operation | -| `headroom.cache.lookup` | Cache check | -| `headroom.provider.call` | Provider API call | - ---- - -### Logging - -**Log Levels:** - -| Level | Use Case | -|-------|----------| -| `DEBUG` | Detailed debugging | -| `INFO` | General operation | -| `WARNING` | Degraded operation | -| `ERROR` | Failures | - -**Log Format (JSON):** -```json -{ - "timestamp": "2026-04-16T12:00:00Z", - "level": "INFO", - "message": "Request completed", - "request_id": "abc123", - "savings": 0.45, - "duration_ms": 120 -} -``` - -**Configuration:** -```bash -# Logging level is controlled via the --log-level CLI flag (headroom proxy --log-level debug) -# or RUST_LOG env var for the Rust proxy. No HEADROOM_LOG_LEVEL env var exists. -``` - -Or in config: -```yaml -logging: - level: INFO - format: json -``` - ---- - -## Dashboard - -**URL:** `http://localhost:8787/dashboard` - -**Metrics Shown:** -- Total savings over time -- Requests per day -- Cache hit rate -- Top compressed endpoints -- Session overview - -**Requires:** the proxy process to be running. The dashboard is served by default at `/dashboard`. - ---- - -## Alerting - -### Recommended Alerts - -| Alert | Condition | Severity | -|-------|-----------|----------| -| HighErrorRate | error_rate > 5% | warning | -| LowSavings | savings < 20% | warning | -| CacheDown | cache_hits < 10% for 1h | critical | -| ProxyDown | health check fails | critical | - -**Alert rule example (Prometheus):** -```yaml -groups: - - name: headroom - rules: - - alert: HighErrorRate - expr: rate(headroom_errors_total[5m]) / rate(headroom_requests_total[5m]) > 0.05 - for: 5m - labels: - severity: warning - annotations: - summary: "High error rate in Headroom" -``` - ---- - -## Health Endpoints - -| Endpoint | Method | Description | -|----------|--------|-------------| -| `/health` | GET | Basic health check | -| `/livez` | GET | Liveness check (process alive) | -| `/readyz` | GET | Readiness check (can serve traffic) | - -**Health response:** -```json -{ - "status": "healthy", - "version": "1.0.0" -} -``` - -**Readiness response:** -```json -{ - "ready": true, - "checks": { - "database": true, - "cache": true, - "provider": true - } -} -``` - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial observability document | diff --git a/docs/spec/017-operations.md b/docs/spec/017-operations.md deleted file mode 100644 index ec429ba10..000000000 --- a/docs/spec/017-operations.md +++ /dev/null @@ -1,176 +0,0 @@ -# 017. Operations - -**Status:** done - -## Health Endpoints - -### `GET /health` - -Basic health check. Returns 200 if process is running. - -```bash -curl http://localhost:8787/health -``` - -**Response:** -```json -{ - "status": "healthy", - "version": "1.0.0" -} -``` - ---- - -### `GET /livez` - -Liveness check. Returns 200 if process is alive. - -```bash -curl http://localhost:8787/livez -``` - ---- - -### `GET /readyz` - -Readiness check. Returns 200 if ready to serve traffic. - -```bash -curl http://localhost:8787/readyz -``` - -**Response:** -```json -{ - "ready": true, - "checks": { - "database": true, - "cache": true, - "provider": true - } -} -``` - ---- - -## Logs - -### Log Locations - -| Installation | Location | -|-------------|----------| -| Docker | `docker logs headroom` | -| Native | `~/.headroom/logs/` | -| Systemd | `journalctl -u headroom` | - -### Log Levels - -Set via CLI flag or `RUST_LOG` env var for the Rust proxy: -```bash -# Python proxy -headroom proxy --log-level debug - -# Rust proxy -RUST_LOG=debug headroom-proxy --upstream http://... -``` - ---- - -## Metrics - -### Prometheus - -**Scrape Config:** -```yaml -scrape_configs: - - job_name: 'headroom' - static_configs: - - targets: ['localhost:8787'] - metrics_path: '/metrics' -``` - ---- - -## Upgrade Procedure - -### Docker - -```bash -docker pull headroom-ai/headroom:latest -docker-compose down -docker-compose up -d -``` - -### Native - -```bash -pip install --upgrade headroom-ai -# Restart headroom service -``` - -### Embedded - -```bash -pip install --upgrade headroom-ai -# Restart application -``` - ---- - -## Rollback - -### Docker - -```bash -docker-compose down -docker tag headroom-ai/headroom:latest headroom-ai/headroom:rollback -# Edit docker-compose.yml to use rollback tag -docker-compose up -d -``` - ---- - -## Monitoring - -### Key Metrics to Watch - -1. **Request rate** — requests per second -2. **Error rate** — 4xx + 5xx / total -3. **Savings rate** — average savings percentage -4. **Latency** — p50, p95, p99 -5. **Cache hit rate** — hits / total - -**Prometheus queries:** -```promql -# Request rate -rate(headroom_requests_total[5m]) - -# Error rate -rate(headroom_errors_total[5m]) / rate(headroom_requests_total[5m]) - -# Average savings -rate(headroom_tokens_original[5m] - headroom_tokens_compressed[5m]) / rate(headroom_tokens_original[5m]) - -# Cache hit rate -rate(headroom_cache_hits_total[5m]) / (rate(headroom_cache_hits_total[5m]) + rate(headroom_cache_misses_total[5m])) -``` - ---- - -## Runbook - -| Symptom | Cause | Solution | -|---------|-------|----------| -| "Connection refused" | Proxy not running | Start it with `headroom proxy` | -| "Cache miss on every request" | Cache disabled | Start without `--no-cache` | -| "No savings shown" | Database locked | Check file permissions | -| "Provider timeout" | Network issue | Check firewall/proxy | - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial operations document | diff --git a/docs/spec/018-policies.md b/docs/spec/018-policies.md deleted file mode 100644 index 6a989351f..000000000 --- a/docs/spec/018-policies.md +++ /dev/null @@ -1,118 +0,0 @@ -# 018. Policies - -**Status:** done - -## Default Behaviors - -### Compression - -| Setting | Default | Description | -|---------|---------|-------------| -| Compression enabled | `true` | Apply compression by default | -| Cache enabled | `true` | Use semantic cache | -| Summary enabled | `true` | Use summary compression | -| Token budget enforced | `false` | No budget limit by default | - -### Telemetry - -| Setting | Default | Description | -|---------|---------|-------------| -| Metrics enabled | `true` | Emit Prometheus metrics | -| Tracing enabled | `false` | No OTEL tracing | -| Dashboard enabled | `false` | No built-in dashboard | - -### Learn - -| Setting | Default | Description | -|---------|---------|-------------| -| Learn enabled | `false` | Learning disabled | -| Plugin auto-detect | `true` | Auto-load plugins | -| Feedback collection | `false` | No CCR feedback | - ---- - -## Override Mechanisms - -### Environment Variables - -All settings can be overridden via environment variables: -```bash -HEADROOM_MODE=token -headroom proxy --no-cache -``` - -### Config File - -```yaml -# ~/.headroom/config.yaml -proxy: - host: 0.0.0.0 - port: 8787 - -compression: - enabled: true - cache: - enabled: true - ttl: 3600 - -telemetry: - metrics: - enabled: true - tracing: - enabled: false - -learn: - enabled: false -``` - -### Runtime API - -```bash -# Disable compression for single request -curl -X POST http://localhost:8787/v1/messages \ - -H "X-Headroom-Compress: false" -``` - -### Runtime Headers - -| Header | Description | -|--------|-------------| -| `X-Headroom-Compress` | Override compression (true/false) | -| `X-Headroom-Mode` | Override mode (passthrough/compress/learn) | -| `X-Headroom-Cache` | Override cache (true/false) | - ---- - -## Policy Hierarchy - -Settings are evaluated in this order (highest wins): - -1. **Runtime headers** — Per-request overrides -2. **Environment variables** — Process-level -3. **Config file** — Persistent settings -4. **Defaults** — Built-in defaults - ---- - -## Per-Tenant Policies (TOIN) - -TOIN tenants can have custom policies: - -```yaml -tenant: - id: "acme-corp" - policies: - compression: - enabled: true - threshold: 3000 - budget: - daily_limit: 1000000 -``` - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial policies document | diff --git a/docs/spec/019-quality.md b/docs/spec/019-quality.md deleted file mode 100644 index 0cd0af1bd..000000000 --- a/docs/spec/019-quality.md +++ /dev/null @@ -1,111 +0,0 @@ -# 019. Quality - -**Status:** done - -## Test Pyramid - -``` - ┌─────────────┐ - │ E2E │ ← Few, slow, comprehensive - │ Tests │ - └──────┬──────┘ - │ - ┌──────┴──────┐ - │ Integration │ ← Medium, moderate - │ Tests │ - └──────┬──────┘ - │ - ┌────────────┴────────────┐ - │ │ -┌────┴────┐ ┌────┴────┐ -│ Unit │ │ Unit │ -│ Tests │ │ Tests │ -└─────────┘ └─────────┘ -Many, fast, isolated -``` - ---- - -## Test Coverage - -| Surface | Unit | Integration | E2E | -|---------|:----:|:------------:|:---:| -| Proxy Server | ✓ | ✓ | ✓ | -| SDK | ✓ | ✓ | - | -| Compression | ✓ | ✓ | ✓ | -| Cache | ✓ | ✓ | - | -| Learn | ✓ | ✓ | - | -| CCR | ✓ | ✓ | ✓ | -| TOIN | ✓ | ✓ | - | -| Dashboard | ✓ | - | ✓ | - ---- - -## Coverage Targets - -| Metric | Target | Threshold | -|--------|--------|-----------| -| Line coverage | 80% | 70% | -| Branch coverage | 70% | 60% | -| Critical path | 100% | 100% | - ---- - -## Critical Paths - -These must always pass: - -1. **Compression pipeline** — Input → Compress → Output -2. **Cache hit path** — Input → Cache check → Return -3. **Provider proxy** — Request → Proxy → Provider → Response -4. **Learn feedback** — Session → Analyze → Compress → Store - ---- - -## Performance Benchmarks - -| Operation | Target | Threshold | -|-----------|--------|-----------| -| Compression | < 50ms | < 200ms | -| Cache lookup | < 5ms | < 20ms | -| Proxy latency | +10ms | +50ms | - ---- - -## CI/CD - -### Required Checks - -| Check | Command | Timeout | -|-------|---------|---------| -| Lint | `ruff check` | 2m | -| Type check | `mypy` | 5m | -| Unit tests | `pytest tests/unit/` | 10m | -| Integration | `pytest tests/ -k integration` | 15m | -| E2E | `pytest e2e/` | 30m | - -### Workflow (`.github/workflows/`) - -1. **Lint** — `ruff check` + `ruff format --check` -2. **Type check** — `mypy src/` -3. **Unit tests** — `pytest tests/unit/ --cov` -4. **Integration** — `pytest tests/ -k integration` -5. **E2E** — `pytest e2e/ --api-key=$ANTHROPIC_API_KEY` - ---- - -## Quality Gates - -PRs must pass: -- All tests green -- Type checking passes (`mypy`) -- Lint passes (`ruff`) -- Coverage maintained or improved - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial quality document | diff --git a/docs/spec/020-security.md b/docs/spec/020-security.md deleted file mode 100644 index 8c5477c61..000000000 --- a/docs/spec/020-security.md +++ /dev/null @@ -1,120 +0,0 @@ -# 020. Security - -**Status:** done - -## Threat Model - -### Threats - -| Threat | Impact | Mitigation | -|--------|--------|------------| -| Prompt data exfiltration | High | No logging, local-only | -| API key theft | High | Key rotation, secrets management | -| Cache poisoning | Medium | Input validation | -| DoS via large prompts | Medium | Token limits | -| SSRF via redirects | Medium | URL validation | - ---- - -### Trust Boundaries - -``` -┌──────────────────┐ ┌──────────────────┐ -│ User's App │────▶│ Headroom Proxy │ -└──────────────────┘ └────────┬─────────┘ - │ - ┌────────┴─────────┐ - │ │ - ┌─────▼─────┐ ┌──────▼──────┐ - │ Provider │ │ Database │ - │ APIs │ │ (SQLite) │ - └───────────┘ └─────────────┘ -``` - ---- - -## Security Controls - -### Authentication - -| Surface | Auth Method | -|---------|-------------| -| Proxy | API key (optional) | -| Dashboard | None by default | -| Health endpoints | None | -| Metrics | None | - -### Authorization - -- **No multi-user support** — Single-tenant by design -- **API keys** — For proxy authentication -- **CORS** — Configurable origins - ---- - -## Data Protection - -| Data | At Rest | In Transit | -|------|---------|------------| -| Prompts | Encrypted (if DB encrypted) | TLS | -| Responses | Encrypted (if DB encrypted) | TLS | -| API keys | Encrypted | TLS | -| Metrics | Plain text | TLS | - ---- - -## Input Validation - -- **Prompt length** — Enforced via token budget -- **URL validation** — For provider redirects -- **Schema validation** — For all API inputs - ---- - -## Secrets Management - -### Environment Variables - -```bash -ANTHROPIC_API_KEY=sk-... -OPENAI_API_KEY=sk-... -``` - -### Secrets Management Systems - -Headroom supports: -- AWS Secrets Manager -- HashiCorp Vault -- Azure Key Vault - ---- - -## Supply Chain Security - -### Dependencies - -- **Pinned versions** — All dependencies pinned -- **Audit** — Regular `pip audit` -- **SBOM** — Software Bill of Materials generated - -### Build - -- **Reproducible** — Docker builds are reproducible -- **Signed releases** — Code signed - ---- - -## Vulnerability Reporting - -See `SECURITY.md` for: -- Reporting process -- Response timeline -- Disclosure policy - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial security document | diff --git a/docs/spec/021-testing.md b/docs/spec/021-testing.md deleted file mode 100644 index 47e9e8a31..000000000 --- a/docs/spec/021-testing.md +++ /dev/null @@ -1,162 +0,0 @@ -# 021. Testing - -**Status:** done - -## Test Strategy by Surface - -### Proxy Server - -**Unit Tests:** -- Request routing -- Response header injection -- Mode switching -- Error handling - -**Integration Tests:** -- Full request/response cycle -- Provider mocking -- Cache integration - -**E2E Tests:** -- Against real provider APIs (with API keys) - ---- - -### Compression - -**Unit Tests:** -- Token counting -- Semantic hashing -- Summary compression -- Budget enforcement - -**Integration Tests:** -- Cache round-trip -- Multi-stage compression - -**Benchmarks:** -- Latency at scale -- Memory usage - ---- - -### Learn System - -**Unit Tests:** -- Plugin interface compliance -- Error classification -- Session analysis - -**Integration Tests:** -- Plugin discovery -- Cross-plugin interaction - -**E2E Tests:** -- Real session analysis - ---- - -### CCR (Claude Code Relay) - -**Unit Tests:** -- Context tracking -- Feedback collection -- Batch processing - -**Integration Tests:** -- Tool injection -- Response handling - -**E2E Tests:** -- Full CCR workflow - ---- - -## Test Utilities - -### Fixtures - -Located in `tests/conftest.py`: -- `mock_provider` — Mock AI provider -- `sample_session` — Sample conversation -- `temp_db` — Temporary database - -### Mock Libraries - -- `responses` — HTTP mocking -- `pytest-mock` — Function mocking -- `aioresponses` — Async HTTP mocking - ---- - -## Running Tests - -### All Tests - -```bash -pytest -``` - -### By Surface - -```bash -pytest tests/test_proxy/ -pytest tests/test_compression/ -pytest tests/test_learn/ -``` - -### With Coverage - -```bash -pytest --cov=headroom --cov-report=html -``` - -### E2E Tests - -```bash -# Requires API keys -pytest e2e/ --api-key=$ANTHROPIC_API_KEY -``` - ---- - -## Test Data - -### Sample Sessions - -Stored in `tests/fixtures/sessions/`: -- `claude_code_short.json` — Short Claude Code session -- `claude_code_long.json` — Long session with tool use -- `codex_completion.json` — Codex completion -- `gemini_multimodal.json` — Gemini with images - ---- - -## Continuous Integration - -### Required Checks - -| Check | Command | Timeout | -|-------|---------|---------| -| Lint | `ruff check` | 2m | -| Type check | `mypy` | 5m | -| Unit tests | `pytest tests/` | 10m | -| Integration | `pytest tests/ -k integration` | 15m | -| E2E | `pytest e2e/` | 30m | - ---- - -## Test Maintenance - -- **Fixtures** — Keep realistic but small -- **Mocks** — Don't over-mock providers -- **Flaky tests** — Mark with `@pytest.mark.flaky` -- **Coverage drops** — PR blocked if coverage drops - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial testing document | diff --git a/docs/spec/022-rust-migration.md b/docs/spec/022-rust-migration.md deleted file mode 100644 index dadc03089..000000000 --- a/docs/spec/022-rust-migration.md +++ /dev/null @@ -1,98 +0,0 @@ -# 022. Rust Migration - -**Status:** in-progress (Stage 0 complete) - -Headroom is evolving from a pure-Python proxy into a Rust engine with a Python SDK layer. This document describes the motivation, target architecture, and phased execution plan. It is the source of truth for the migration; the Discord announcement and contributor docs are derived from it. - -## Why Rust - -Three forces push us toward Rust: - -1. **Latency.** Every LLM request flows through compression transforms on the hot path. Rust runs that math 2–10× faster than Python, with negligible interpreter overhead and near-instant cold starts. -2. **Deployment.** A Rust proxy is a single static binary (~10 MB). No Python interpreter, no pip, no wheel matrix, no model downloads at startup. It drops cleanly into containers, serverless runtimes, or bare hosts. -3. **Non-Python consumers.** Integrations like the TypeScript OpenClaw plugin talk to Headroom over HTTP. A faster proxy makes every downstream client faster without changing any client code. - -The Python code is not being thrown away. Rust lives alongside Python in the same repository, the HTTP contract stays stable, and existing users see no breaking changes. - -## Target architecture - -Two new artifacts, built over time: - -- **`headroom-proxy`** — a standalone Rust binary that speaks the existing Headroom HTTP API and contains native implementations of the proxy's hot-path logic (routing, streaming, compression, telemetry). This is the deployable artifact. -- **`headroom-core`** — a Rust library with the compression transforms (CCR, log compressor, diff compressor, tokenizer, code compressor, content router, etc.). Consumed by `headroom-proxy` directly; optionally exposed to Python via a PyO3 binding if/when embedded SDK use warrants it. - -Both live in a Cargo workspace under `crates/` at the repo root. They are built, tested, and released together with the Python package. - -## Migration strategy - -**Trunk-based, no long-lived branch.** Every Rust change ships as a small PR to `main`. Rust and Python live side by side. CI enforces parity on every PR — if the Rust port diverges from the Python reference, the build fails. - -**Proxy-first, not transforms-first.** We build the Rust proxy binary as the primary deliverable, starting from a pure HTTP passthrough that forwards upstream to the existing Python proxy. Native Rust implementations of individual routes then replace passthroughs one at a time, gated by feature flags. This lets us ship a deployable Rust binary on day one and iterate without modifying Python internals. - -**Feature-flagged cutover.** Each native Rust route is toggled by config. Default is passthrough-to-Python until a route has been shadow-tested and validated. Rollback is a flag flip, not a redeploy. - -**Parity by shadow traffic.** Recorded input/output fixtures give us a unit-test-level parity check. Shadow mode — running both proxies on live traffic and diffing outputs — gives us the real validation gate before any cutover. - -## Stages - -### Stage 0 — Foundation ✅ - -Cargo workspace with four crates (`headroom-core`, `headroom-proxy`, `headroom-py`, `headroom-parity`), CI, build tooling (Makefile, GitHub Actions), and a parity test harness seeded with 125 recorded fixtures across 5 leaf transforms. No production behavior changed. - -### Stage 1 — Rust proxy as passthrough - -`headroom-proxy` accepts requests on the same HTTP contract as the Python proxy and forwards everything upstream to Python. No transforms yet, no intelligence. The point is a deployable binary that can run in front of the existing stack with zero risk. - -### Stage 2 — First native route - -Replace the passthrough for `/v1/chat/completions` (OpenAI) with a native Rust implementation: Rust transforms, direct provider call, streamed response. Feature-flagged. Python proxy handles everything else unchanged. - -### Stage 3 — Shadow mode validation - -Run both proxies on real traffic. Diff outputs with tolerance for chunk timing (SSE). Gate: one week of ≤ 0.1% content divergence before flipping the flag for real. - -### Stage 4 — Provider expansion - -Anthropic, Google, Cohere, Mistral, Bedrock, others. Each provider goes through its own shadow period before cutover. - -### Stage 5 — Code-aware transforms - -Port `code_compressor` (tree-sitter, already Rust-native upstream), `content_router`, `content_detector`. These are larger transforms but have no ML dependencies. - -### Stage 6 — Storage layer - -SQLite (`rusqlite` + `sqlite-vec`), HNSW vector index (`instant-distance`), graph store (`neo4rs`). Feature-flagged backend for the memory subsystem. - -### Stage 7 — ONNX migration - -Remove the torch-dependent LLMLingua compressor. Convert remaining ML models (SmartCrusher, IntelligentContext, memory embedders) to ONNX with fixed opset. Run via the `ort` crate. Remove `torch`, `transformers`, `sentence-transformers`, `llmlingua` from runtime dependencies. - -### Stage 8 — Retire the Python proxy - -Delete `headroom/proxy/server.py` and the Python HTTP routes. The Python package (`import headroom`) continues to exist for SDK users and integration adapters (LangChain, Agno, MCP, Strands), which talk HTTP and don't care which proxy implementation is behind the endpoint. - -## What does not change - -- `pip install headroom` continues to work. -- The HTTP API contract is preserved. -- LangChain, Agno, MCP, Strands integrations keep working unchanged. -- The CLI, dashboard, eval framework, examples, and documentation site are all unaffected. -- Python contributions remain welcome for integrations, tooling, examples, and any code paths not yet ported. - -## Contributing - -- **Python contributors** do not need to learn Rust. CI will flag a PR if a Python change diverges from a Rust-ported counterpart; in that case either update both implementations or disable the feature flag for the affected route. -- **Rust contributors** should read `RUST_DEV.md` for workspace setup, then pick a transform or proxy route from the open issues. - -## Risks and open questions - -- **ONNX export parity** for embedding models: numerical reproducibility must be validated per model before cutover. Some models may resist clean export and require keeping a Python inference path behind PyO3 as a fallback. -- **LLMLingua removal** is a feature removal visible to users relying on it; deprecation timing will be announced on Discord before Stage 7 begins. -- **PyO3 binding scope**: we may ultimately not need a PyO3-exposed `headroom._core` at all, if existing Python SDK users are happy with the HTTP contract. Decision deferred to Stage 8. - -## References - -- `RUST_DEV.md` — developer setup and workspace reference -- `crates/` — Rust sources -- `tests/parity/` — fixtures and parity harness -- `Makefile` — `make test`, `make test-parity`, `make build-proxy`, `make build-wheel`, `make fmt`, `make lint` diff --git a/docs/spec/SPEC.md b/docs/spec/SPEC.md deleted file mode 100644 index 4005d99d3..000000000 --- a/docs/spec/SPEC.md +++ /dev/null @@ -1,88 +0,0 @@ -# Headroom Living Specification - -**Version:** 1.0.0-draft -**Date:** 2026-04-16 -**Status:** Draft — In Progress -**Related Issue:** GitHub #183 - ---- - -## Constitution - -This specification is the **canonical source of truth** for how Headroom is designed to behave. It serves: - -1. **New contributors** — One place to understand how Headroom works -2. **Enterprises evaluating adoption** — Clear guarantees about behavior, privacy, security -3. **Operators running managed deployments** — Operational guidance for all surfaces -4. **Plugin authors** — Clear contracts for extension points -5. **PR review** — A checklist target: "does the code match the spec?" - -### Spec Governance - -| Rule | Description | -|------|-------------| -| **Canonical** | When code and spec diverge, the spec is the target; the code needs updating | -| **Living** | Spec updates are required for behavior-changing changes (PR checklist) | -| **Comprehensive** | Spec covers every user-visible surface, behavior, and guarantee | -| **Language-agnostic** | Spec enables complete rewrite in any language with parity | -| **Versioned** | Changes increment version; breaking changes require major version bump | - -### Spec Sections - -| # | Section | Status | Description | -|---|---------|:------:|-------------| -| 001 | [Vision](001-vision.md) | done | What Headroom is, what it is not | -| 002 | [Architecture](002-architecture.md) | done | Component diagram + descriptions | -| 003 | [ADRs](003-adrs.md) | done | Architecture Decision Records | -| 004 | [Domain Model](004-domain-model.md) | done | Core entities | -| 005 | [Integrations](005-integrations.md) | done | Agent contracts | -| 006 | [Actors](006-actors.md) | done | User types + interactions | -| 007 | [Behavior](007-behavior.md) | done | Mode-by-mode specification | -| 008 | [Capabilities](008-capabilities.md) | done | Feature matrix | -| 009 | [Compliance](009-compliance.md) | done | Data guarantees, privacy | -| 010 | [Data](010-data.md) | done | Storage, retention, env vars | -| 011 | [Deployment](011-deployment.md) | done | Profiles, presets, runtimes | -| 012 | [Diagrams](012-diagrams.md) | done | Component, sequence, data-flow | -| 013 | [Disaster Recovery](013-disaster-recovery.md) | done | Failure modes + recovery | -| 014 | [Governance](014-governance.md) | done | Decision-making, releases | -| 015 | [Interfaces](015-interfaces.md) | done | CLI, HTTP, env var, plugin ABI | -| 016 | [Observability](016-observability.md) | done | Telemetry, metrics, logs | -| 017 | [Operations](017-operations.md) | done | Health, logs, upgrades | -| 018 | [Policies](018-policies.md) | done | Defaults + overrides | -| 019 | [Quality](019-quality.md) | done | Test pyramid coverage | -| 020 | [Security](020-security.md) | done | Threat model, supply-chain | -| 021 | [Testing](021-testing.md) | done | Test strategy per surface | - ---- - -## Quick Reference - -### What Headroom Is - -- A **context compression proxy** for AI provider APIs -- A **Python package** (`headroom-ai`) with proxy, SDK, and CLI -- A **TypeScript SDK** (`@headroom/sdk`) for Node.js -- A **dashboard** for visualizing savings -- A **learn system** with per-agent plugins - -### What Headroom Is Not - -- A model provider -- A data store for prompts (by default) -- A logging service (by default) -- A billing service - -### Core Guarantees - -1. **Never logs prompts by default** — No prompt data leaves the proxy unless an exporter is configured -2. **Never leaves the proxy by default** — All data stays local unless explicitly exported -3. **Composable** — Works alongside existing tools (Claude Code, Copilot, etc.) -4. **Transparent** — Full observability into what's being compressed and why - ---- - -## Change Log - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0-draft | 2026-04-16 | Initial draft — 21 sections outlined | diff --git a/docs/superpowers/plans/2026-06-19-deepseek-pricing.md b/docs/superpowers/plans/2026-06-19-deepseek-pricing.md deleted file mode 100644 index 9c6a5458b..000000000 --- a/docs/superpowers/plans/2026-06-19-deepseek-pricing.md +++ /dev/null @@ -1,699 +0,0 @@ -# DeepSeek V4 Pricing Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Add `deepseek-v4-flash` and `deepseek-v4-pro` pricing to Headroom so cost estimation works when routing through `--anthropic-api-url https://api.deepseek.com/anthropic`. - -**Architecture:** Four independent layers — (1) a new pricing data module following the `anthropic_prices.py` pattern, (2) runtime injection into `litellm.model_cost` so the primary cost-per-token path resolves DeepSeek V4, (3) a fallback in the Anthropic provider's `_get_pricing()` when LiteLLM is unavailable, and (4) vendored JSON entries for Rust-side context window lookups. - -**Tech Stack:** Python 3.12+, LiteLLM, Rust (vendored JSON), pytest - -## Global Constraints - -- All prices in USD per 1 million tokens (`ModelPricing` dataclass convention) -- LiteLLM injection must not overwrite upstream entries if litellm already has DeepSeek V4 -- Provider field must be `"deepseek"` for all DeepSeek models -- Follow exact patterns from `anthropic_prices.py` / `openai_prices.py` / `test_anthropic.py` -- Vendored JSON entries at `crates/headroom-proxy/data/model_prices_and_context_window.json` - ---- - -### Task 1: DeepSeek Pricing Data Module - -**Files:** -- Create: `headroom/pricing/deepseek_prices.py` -- Modify: `headroom/pricing/__init__.py` -- Test: `tests/test_providers/test_deepseek.py` (first test class) - -**Interfaces:** -- Consumes: `ModelPricing`, `PricingRegistry` from `headroom.pricing.registry` -- Produces: `DEEPSEEK_PRICES: dict[str, ModelPricing]`, `get_deepseek_registry() -> PricingRegistry`, exported via `headroom.pricing` - -- [ ] **Step 1: Write the failing tests for the pricing data module** - -Create `tests/test_providers/test_deepseek.py`: - -```python -"""Tests for DeepSeek model pricing and cost estimation.""" - -from headroom.pricing.deepseek_prices import ( - DEEPSEEK_PRICES, - get_deepseek_registry, -) -from headroom.pricing.registry import PricingRegistry - - -class TestDeepSeekPricingModule: - """Tests for the DeepSeek pricing data module.""" - - def test_deepseek_pricing_contains_v4_models(self): - assert "deepseek-v4-flash" in DEEPSEEK_PRICES - assert "deepseek-v4-pro" in DEEPSEEK_PRICES - assert len(DEEPSEEK_PRICES) == 2 - - def test_deepseek_v4_flash_pricing(self): - pricing = DEEPSEEK_PRICES["deepseek-v4-flash"] - assert pricing.input_per_1m == 0.14 - assert pricing.output_per_1m == 0.28 - assert pricing.cached_input_per_1m == 0.0028 - assert pricing.context_window == 1_000_000 - assert pricing.provider == "deepseek" - assert pricing.notes is not None - - def test_deepseek_v4_pro_pricing(self): - pricing = DEEPSEEK_PRICES["deepseek-v4-pro"] - assert pricing.input_per_1m == 0.435 - assert pricing.output_per_1m == 0.87 - assert pricing.cached_input_per_1m == 0.003625 - assert pricing.context_window == 1_000_000 - assert pricing.provider == "deepseek" - assert pricing.notes is not None - - def test_get_deepseek_registry(self): - registry = get_deepseek_registry() - assert isinstance(registry, PricingRegistry) - assert registry.get_price("deepseek-v4-flash") is not None - assert registry.get_price("deepseek-v4-pro") is not None - assert registry.get_price("nonexistent") is None - - def test_registry_staleness_and_source_url(self): - registry = get_deepseek_registry() - assert registry.source_url == "https://api-docs.deepseek.com/quick_start/pricing" - assert not registry.is_stale() - - def test_deepseek_registry_estimate_cost(self): - registry = get_deepseek_registry() - cost = registry.estimate_cost("deepseek-v4-flash", input_tokens=1_000_000) - assert cost.cost_usd == 0.14 - assert "input" in cost.breakdown - assert cost.pricing_date is not None - - def test_deepseek_registry_estimate_cost_with_cached(self): - registry = get_deepseek_registry() - cost = registry.estimate_cost( - "deepseek-v4-flash", - input_tokens=1_000_000, - cached_input_tokens=1_000_000, - ) - assert cost.cost_usd == 0.14 + 0.0028 -``` - -- [ ] **Step 2: Run tests to verify they fail** - -```bash -cd D:/headroom && python -m pytest tests/test_providers/test_deepseek.py::TestDeepSeekPricingModule -v -``` - -Expected: ModuleNotFoundError or ImportError — `deepseek_prices` doesn't exist yet. - -- [ ] **Step 3: Create the pricing data module** - -Create `headroom/pricing/deepseek_prices.py`: - -```python -"""DeepSeek model pricing information.""" - -from datetime import date - -from .registry import ModelPricing, PricingRegistry - -# Last verified date for pricing information -LAST_UPDATED = date(2026, 6, 19) - -# Official pricing page -SOURCE_URL = "https://api-docs.deepseek.com/quick_start/pricing" - -# All prices are in USD per 1 million tokens -DEEPSEEK_PRICES: dict[str, ModelPricing] = { - "deepseek-v4-flash": ModelPricing( - model="deepseek-v4-flash", - provider="deepseek", - input_per_1m=0.14, - output_per_1m=0.28, - cached_input_per_1m=0.0028, - context_window=1_000_000, - notes="DeepSeek V4 Flash - 13B active params; non-thinking + thinking modes", - ), - "deepseek-v4-pro": ModelPricing( - model="deepseek-v4-pro", - provider="deepseek", - input_per_1m=0.435, - output_per_1m=0.87, - cached_input_per_1m=0.003625, - context_window=1_000_000, - notes="DeepSeek V4 Pro - 49B active params", - ), -} - - -def get_deepseek_registry() -> PricingRegistry: - """Create and return a DeepSeek pricing registry. - - Returns: - PricingRegistry configured with DeepSeek model prices. - """ - return PricingRegistry( - last_updated=LAST_UPDATED, - source_url=SOURCE_URL, - prices=DEEPSEEK_PRICES.copy(), - ) -``` - -- [ ] **Step 4: Wire into `__init__.py`** - -Edit `headroom/pricing/__init__.py` — add these imports after the existing OpenAI imports: - -```python -from .deepseek_prices import ( - DEEPSEEK_PRICES, - get_deepseek_registry, -) -from .deepseek_prices import ( - LAST_UPDATED as DEEPSEEK_LAST_UPDATED, -) -``` - -And add to `__all__`: - -```python - # DeepSeek - "DEEPSEEK_LAST_UPDATED", - "DEEPSEEK_PRICES", - "get_deepseek_registry", -``` - -- [ ] **Step 5: Run tests to verify they pass** - -```bash -cd D:/headroom && python -m pytest tests/test_providers/test_deepseek.py::TestDeepSeekPricingModule -v -``` - -Expected: 7 passed - -- [ ] **Step 6: Commit** - -```bash -git add headroom/pricing/deepseek_prices.py headroom/pricing/__init__.py tests/test_providers/test_deepseek.py -git commit -m "feat(pricing): add DeepSeek V4 pricing data module - -Add deepseek-v4-flash and deepseek-v4-pro ModelPricing entries and -registry factory, following the pattern of anthropic_prices.py. -Wire into pricing/__init__.py exports. - -Co-Authored-By: Claude " -``` - ---- - -### Task 2: LiteLLM Runtime Injection - -**Files:** -- Modify: `headroom/pricing/litellm_pricing.py` (add injection after `LITELLM_AVAILABLE` block) -- Test: `tests/test_providers/test_deepseek.py` (add `TestDeepSeekLiteLLMInjection` class) - -**Interfaces:** -- Consumes: `litellm.model_cost` dict (available after import) -- Produces: `"deepseek-v4-flash"`, `"deepseek/deepseek-v4-flash"`, `"deepseek-v4-pro"`, `"deepseek/deepseek-v4-pro"` keys in `litellm.model_cost` -- Depends on: DEEPSEEK_V4_PRICING constant defined within litellm_pricing.py - -- [ ] **Step 1: Write failing injection tests** - -Append to `tests/test_providers/test_deepseek.py`: - -```python -import pytest - - -class TestDeepSeekLiteLLMInjection: - """Tests for DeepSeek V4 pricing injection into litellm.""" - - def test_deepseek_v4_models_in_litellm_model_cost(self): - from headroom.pricing.litellm_pricing import litellm, LITELLM_AVAILABLE - if not LITELLM_AVAILABLE: - pytest.skip("litellm not available") - assert "deepseek-v4-flash" in litellm.model_cost - assert "deepseek-v4-pro" in litellm.model_cost - - def test_deepseek_v4_prefixed_models_in_litellm_model_cost(self): - from headroom.pricing.litellm_pricing import litellm, LITELLM_AVAILABLE - if not LITELLM_AVAILABLE: - pytest.skip("litellm not available") - assert "deepseek/deepseek-v4-flash" in litellm.model_cost - assert "deepseek/deepseek-v4-pro" in litellm.model_cost - - def test_deepseek_v4_flash_litellm_pricing(self): - from headroom.pricing.litellm_pricing import litellm, LITELLM_AVAILABLE - if not LITELLM_AVAILABLE: - pytest.skip("litellm not available") - flash = litellm.model_cost["deepseek-v4-flash"] - assert flash["input_cost_per_token"] == 0.14 / 1_000_000 - assert flash["output_cost_per_token"] == 0.28 / 1_000_000 - assert flash["cache_read_input_token_cost"] == 0.0028 / 1_000_000 - assert flash["litellm_provider"] == "deepseek" - - def test_deepseek_v4_pro_litellm_pricing(self): - from headroom.pricing.litellm_pricing import litellm, LITELLM_AVAILABLE - if not LITELLM_AVAILABLE: - pytest.skip("litellm not available") - pro = litellm.model_cost["deepseek-v4-pro"] - assert pro["input_cost_per_token"] == 0.435 / 1_000_000 - assert pro["output_cost_per_token"] == 0.87 / 1_000_000 - assert pro["cache_read_input_token_cost"] == 0.003625 / 1_000_000 - assert pro["litellm_provider"] == "deepseek" - - def test_cost_per_token_resolves_deepseek_v4_flash(self): - from headroom.pricing.litellm_pricing import litellm, LITELLM_AVAILABLE - if not LITELLM_AVAILABLE: - pytest.skip("litellm not available") - input_cost, output_cost = litellm.cost_per_token( - model="deepseek-v4-flash", - prompt_tokens=1_000_000, - completion_tokens=1_000_000, - ) - assert input_cost == pytest.approx(0.14, rel=0.01) - assert output_cost == pytest.approx(0.28, rel=0.01) - - def test_injection_does_not_overwrite_existing_upstream_entries(self): - """If litellm upstream already has these, our injection is a no-op.""" - from headroom.pricing.litellm_pricing import litellm, LITELLM_AVAILABLE - if not LITELLM_AVAILABLE: - pytest.skip("litellm not available") - # Force-inject with wrong value, then verify the injection guard - litellm.model_cost["deepseek-v4-flash"] = {"input_cost_per_token": 999} - # Reimport to trigger _inject_deepseek_pricing — but it should NOT overwrite - import importlib - import headroom.pricing.litellm_pricing as lp - importlib.reload(lp) - assert litellm.model_cost["deepseek-v4-flash"]["input_cost_per_token"] == 999 - # Reset to correct value - litellm.model_cost["deepseek-v4-flash"] = { - "input_cost_per_token": 0.14 / 1_000_000, - "output_cost_per_token": 0.28 / 1_000_000, - "cache_read_input_token_cost": 0.0028 / 1_000_000, - "litellm_provider": "deepseek", - "max_tokens": 384_000, - "max_input_tokens": 1_000_000, - } -``` - -- [ ] **Step 2: Run the injection tests to verify they fail** - -```bash -cd D:/headroom && python -m pytest tests/test_providers/test_deepseek.py::TestDeepSeekLiteLLMInjection -v -``` - -Expected: Tests fail because `litellm.model_cost` doesn't have DeepSeek V4 entries yet. - -- [ ] **Step 3: Add the runtime injection to `litellm_pricing.py`** - -At the end of `headroom/pricing/litellm_pricing.py`, before the `_resolved_model_cache` and function definitions, add: - -```python -# ============================================================ -# DeepSeek V4 pricing injection -# ============================================================ -# Vendored LiteLLM JSON predates DeepSeek V4 models. Inject pricing at -# import time so the primary cost-per-token path resolves them. Once -# upstream litellm adds these entries, injection becomes a no-op. -# ============================================================ - -_DEEPSEEK_V4_PRICING: dict[str, dict[str, float | str | int]] = { - "deepseek-v4-flash": { - "input_cost_per_token": 0.14 / 1_000_000, - "output_cost_per_token": 0.28 / 1_000_000, - "cache_read_input_token_cost": 0.0028 / 1_000_000, - "litellm_provider": "deepseek", - "max_tokens": 384_000, - "max_input_tokens": 1_000_000, - }, - "deepseek-v4-pro": { - "input_cost_per_token": 0.435 / 1_000_000, - "output_cost_per_token": 0.87 / 1_000_000, - "cache_read_input_token_cost": 0.003625 / 1_000_000, - "litellm_provider": "deepseek", - "max_tokens": 384_000, - "max_input_tokens": 1_000_000, - }, -} - - -def _inject_deepseek_pricing() -> None: - """Inject DeepSeek V4 pricing into litellm's model_cost dict. - - Only injects entries not already present, so upstream litellm additions - (once available) take precedence. Both bare and provider-prefixed keys - are added so resolve_litellm_model() catches them via its deepseek/ - prefix loop. - """ - if not LITELLM_AVAILABLE: - return - for model_name, pricing in _DEEPSEEK_V4_PRICING.items(): - if model_name not in litellm.model_cost: - litellm.model_cost[model_name] = pricing - prefixed = f"deepseek/{model_name}" - if prefixed not in litellm.model_cost: - litellm.model_cost[prefixed] = pricing - - -_inject_deepseek_pricing() -``` - -- [ ] **Step 4: Run tests to verify they pass** - -```bash -cd D:/headroom && python -m pytest tests/test_providers/test_deepseek.py::TestDeepSeekLiteLLMInjection -v -``` - -Expected: All 6 tests pass (or some skip if litellm is unavailable — that's acceptable). - -- [ ] **Step 5: Commit** - -```bash -git add headroom/pricing/litellm_pricing.py tests/test_providers/test_deepseek.py -git commit -m "feat(pricing): inject DeepSeek V4 pricing into litellm model_cost - -Add runtime injection so litellm.cost_per_token() resolves -deepseek-v4-flash and deepseek-v4-pro pricing. Includes both bare -and provider-prefixed keys. No-ops if entries already exist. - -Co-Authored-By: Claude " -``` - ---- - -### Task 3: Anthropic Provider DeepSeek Fallback - -**Files:** -- Modify: `headroom/providers/anthropic.py` (add `_get_deepseek_pricing()` helper and call in `_get_pricing()`) -- Test: `tests/test_providers/test_deepseek.py` (add `TestDeepSeekAnthropicProviderFallback` class) - -**Interfaces:** -- Consumes: `_get_pricing(self, model: str) -> dict | None` (inside `AnthropicProvider`) -- Produces: DeepSeek pricing dicts from `_get_pricing("deepseek-*")` and `estimate_cost("deepseek-*")` - -- [ ] **Step 1: Write failing fallback tests** - -Append to `tests/test_providers/test_deepseek.py`: - -```python -class TestDeepSeekAnthropicProviderFallback: - """Tests that Anthropic provider's _get_pricing handles DeepSeek models.""" - - def test_deepseek_v4_flash_fallback(self): - from headroom.providers.anthropic import AnthropicProvider - provider = AnthropicProvider() - pricing = provider._get_pricing("deepseek-v4-flash") - assert pricing is not None - assert pricing["input"] == 0.14 - assert pricing["output"] == 0.28 - assert pricing["cached_input"] == 0.0028 - - def test_deepseek_v4_pro_fallback(self): - from headroom.providers.anthropic import AnthropicProvider - provider = AnthropicProvider() - pricing = provider._get_pricing("deepseek-v4-pro") - assert pricing is not None - assert pricing["input"] == 0.435 - assert pricing["output"] == 0.87 - assert pricing["cached_input"] == 0.003625 - - def test_deepseek_unknown_model_returns_none(self): - from headroom.providers.anthropic import AnthropicProvider - provider = AnthropicProvider() - pricing = provider._get_pricing("deepseek-unknown-model") - assert pricing is None - - def test_deepseek_partial_match_v4_flash_alias(self): - from headroom.providers.anthropic import AnthropicProvider - provider = AnthropicProvider() - # Should match via partial match (flash in v4-flash) - pricing = provider._get_pricing("deepseek-v4-flash-v1") - assert pricing is not None - - def test_estimate_cost_deepseek_v4_flash(self): - from headroom.providers.anthropic import AnthropicProvider - provider = AnthropicProvider() - cost = provider.estimate_cost( - input_tokens=1_000_000, - output_tokens=0, - model="deepseek-v4-flash", - ) - assert cost is not None - assert cost == 0.14 - - def test_estimate_cost_deepseek_v4_flash_with_cache(self): - from headroom.providers.anthropic import AnthropicProvider - provider = AnthropicProvider() - cost = provider.estimate_cost( - input_tokens=1_000_000, - output_tokens=0, - model="deepseek-v4-flash", - cached_tokens=1_000_000, - ) - assert cost is not None - assert cost == 0.14 + 0.0028 -``` - -- [ ] **Step 2: Run fallback tests to verify they fail** - -```bash -cd D:/headroom && python -m pytest tests/test_providers/test_deepseek.py::TestDeepSeekAnthropicProviderFallback -v -``` - -Expected: Fail because `_get_pricing()` returns `None` for `deepseek-*` models. - -- [ ] **Step 3: Add DeepSeek fallback to Anthropic provider** - -In `headroom/providers/anthropic.py`, add a new helper function after the `_UNKNOWN_CLAUDE_DEFAULT` dict (around line 151) and modify `_get_pricing()`: - -Add the helper (after `_UNKNOWN_CLAUDE_DEFAULT` at line 151): - -```python -# DeepSeek fallback pricing for --anthropic-api-url deepseek routing -_DEEPSEEK_FALLBACK_PRICING: dict[str, dict[str, float]] = { - "deepseek-v4-flash": {"input": 0.14, "output": 0.28, "cached_input": 0.0028}, - "deepseek-v4-pro": {"input": 0.435, "output": 0.87, "cached_input": 0.003625}, -} - - -def _get_deepseek_pricing(model: str) -> dict[str, float] | None: - """Get fallback pricing for a DeepSeek model. - - Used when the Anthropic provider encounters a deepseek-* model name - (via --anthropic-api-url pointing at DeepSeek's Anthropic-compatible - endpoint) and LiteLLM is unavailable. - - Args: - model: The model name to look up. - - Returns: - Pricing dict with input/output/cached_input keys, or None. - """ - # Direct match - if model in _DEEPSEEK_FALLBACK_PRICING: - return cast(dict[str, float], _DEEPSEEK_FALLBACK_PRICING[model]) - # Partial match - for known_model, prices in _DEEPSEEK_FALLBACK_PRICING.items(): - if model in known_model or known_model in model: - return cast(dict[str, float], prices) - return None -``` - -Modify `_get_pricing()` in the `AnthropicProvider` class. Add after the Claude default check (line 698): - -```python - # Default for unknown Claude models - if model.startswith("claude"): - return cast(dict[str, float], _UNKNOWN_CLAUDE_DEFAULT["pricing"]) - - # DeepSeek model fallback (via --anthropic-api-url) - if model.startswith("deepseek"): - return _get_deepseek_pricing(model) - - return None -``` - -- [ ] **Step 4: Run tests to verify they pass** - -```bash -cd D:/headroom && python -m pytest tests/test_providers/test_deepseek.py::TestDeepSeekAnthropicProviderFallback -v -``` - -Expected: All 6 tests pass. - -- [ ] **Step 5: Run full test suite for pricing-related tests** - -```bash -cd D:/headroom && python -m pytest tests/test_providers/test_anthropic.py tests/test_providers/test_deepseek.py tests/test_pricing.py tests/test_pricing_litellm.py tests/test_litellm_optional.py -v -``` - -Expected: All existing tests still pass, plus new tests pass. - -- [ ] **Step 6: Commit** - -```bash -git add headroom/providers/anthropic.py tests/test_providers/test_deepseek.py -git commit -m "feat(providers): add DeepSeek pricing fallback to Anthropic provider - -When routing through --anthropic-api-url with a DeepSeek endpoint, -_get_pricing() now handles deepseek-* model names. Falls back to -hardcoded V4 pricing when LiteLLM is unavailable. - -Co-Authored-By: Claude " -``` - ---- - -### Task 4: Vendored Rust JSON Entries - -**Files:** -- Modify: `crates/headroom-proxy/data/model_prices_and_context_window.json` - -**Interfaces:** -- Consumes: The existing DeepSeek JSON entry structure around line 12516 -- Produces: `"deepseek-v4-flash"` and `"deepseek-v4-pro"` entries in the JSON - -- [ ] **Step 1: Add DeepSeek V4 entries to the vendored JSON** - -Open `crates/headroom-proxy/data/model_prices_and_context_window.json` and insert the following after the `"deepseek/deepseek-v3.2"` entry (after line 12516): - -```json - "deepseek-v4-flash": { - "input_cost_per_token": 1.4e-07, - "output_cost_per_token": 2.8e-07, - "cache_read_input_token_cost": 2.8e-09, - "litellm_provider": "deepseek", - "max_input_tokens": 1000000, - "max_output_tokens": 384000, - "max_tokens": 384000, - "mode": "chat", - "supports_function_calling": true, - "supports_native_streaming": true, - "supports_prompt_caching": true, - "source": "https://api-docs.deepseek.com/quick_start/pricing" - }, - "deepseek-v4-pro": { - "input_cost_per_token": 4.35e-07, - "output_cost_per_token": 8.7e-07, - "cache_read_input_token_cost": 3.625e-09, - "litellm_provider": "deepseek", - "max_input_tokens": 1000000, - "max_output_tokens": 384000, - "max_tokens": 384000, - "mode": "chat", - "supports_function_calling": true, - "supports_native_streaming": true, - "supports_prompt_caching": true, - "source": "https://api-docs.deepseek.com/quick_start/pricing" - }, -``` - -Also add provider-prefixed variants after the bare entries (following the pattern where `deepseek/deepseek-v3.2` exists alongside `deepseek-v3-2-251201`): - -```json - "deepseek/deepseek-v4-flash": { - "input_cost_per_token": 1.4e-07, - "output_cost_per_token": 2.8e-07, - "cache_read_input_token_cost": 2.8e-09, - "input_cost_per_token_cache_hit": 2.8e-09, - "litellm_provider": "deepseek", - "max_input_tokens": 1000000, - "max_output_tokens": 384000, - "max_tokens": 384000, - "mode": "chat", - "supports_function_calling": true, - "supports_native_streaming": true, - "supports_prompt_caching": true, - "supports_assistant_prefill": true, - "source": "https://api-docs.deepseek.com/quick_start/pricing" - }, - "deepseek/deepseek-v4-pro": { - "input_cost_per_token": 4.35e-07, - "output_cost_per_token": 8.7e-07, - "cache_read_input_token_cost": 3.625e-09, - "input_cost_per_token_cache_hit": 3.625e-09, - "litellm_provider": "deepseek", - "max_input_tokens": 1000000, - "max_output_tokens": 384000, - "max_tokens": 384000, - "mode": "chat", - "supports_function_calling": true, - "supports_native_streaming": true, - "supports_prompt_caching": true, - "supports_assistant_prefill": true, - "source": "https://api-docs.deepseek.com/quick_start/pricing" - }, -``` - -Note: The prefixed variants use `input_cost_per_token_cache_hit` (LiteLLM modern field) alongside `cache_read_input_token_cost` (legacy field) following the convention of existing entries like `deepseek/deepseek-v3.2`. - -- [ ] **Step 2: Validate the JSON is still well-formed** - -```bash -cd D:/headroom && python -m json.tool crates/headroom-proxy/data/model_prices_and_context_window.json > /dev/null && echo "Valid JSON" -``` - -Expected: "Valid JSON" - -- [ ] **Step 3: Run full test suite to confirm no regressions** - -```bash -cd D:/headroom && python -m pytest tests/test_pricing.py tests/test_pricing_litellm.py tests/test_providers/test_deepseek.py -v -``` - -Expected: All tests pass. - -- [ ] **Step 4: Commit** - -```bash -git add crates/headroom-proxy/data/model_prices_and_context_window.json -git commit -m "feat(proxy): add DeepSeek V4 context window entries to vendored JSON - -Add bare and provider-prefixed JSON entries for deepseek-v4-flash -and deepseek-v4-pro so Rust-side context window lookups work. - -Co-Authored-By: Claude " -``` - ---- - -### Task 5: Run All Tests and Final Verification - -- [ ] **Step 1: Run all pricing-related tests** - -```bash -cd D:/headroom && python -m pytest tests/test_pricing.py tests/test_pricing_litellm.py tests/test_litellm_optional.py tests/test_providers/test_anthropic.py tests/test_providers/test_openai.py tests/test_providers/test_deepseek.py tests/test_providers/test_universal.py tests/test_cost_tracker_counterfactual.py tests/test_proxy_savings_history.py tests/test_provider_model_fallback.py -v -``` - -Expected: All tests pass. Note any skips (some may require litellm installed). - -- [ ] **Step 2: Verify imports work cleanly** - -```bash -cd D:/headroom && python -c "from headroom.pricing import DEEPSEEK_PRICES, get_deepseek_registry; print('Direct import OK:', list(DEEPSEEK_PRICES.keys()))" -cd D:/headroom && python -c "from headroom.pricing.litellm_pricing import get_model_pricing; p = get_model_pricing('deepseek-v4-flash'); print('LiteLLM pricing OK:', p.input_cost_per_1m if p else 'None')" -cd D:/headroom && python -c "from headroom.providers.anthropic import AnthropicProvider; p = AnthropicProvider(); print('Anthropic fallback OK:', p._get_pricing('deepseek-v4-flash'))" -``` - -Expected: All three commands print correct pricing values without errors. - -- [ ] **Step 3: Verify the full proxy cost tracker end-to-end** - -```bash -cd D:/headroom && python -c " -from headroom.proxy.cost import CostTracker -t = CostTracker() -cost = t.estimate_cost('deepseek-v4-flash', input_tokens=1000000, output_tokens=1000000) -print(f'CostTracker estimate: \${cost:.4f}' if cost else 'CostTracker returned None') -" -``` - -Expected: Prints `CostTracker estimate: $0.4200` (0.14 input + 0.28 output, may vary if litellm is available). - -- [ ] **Step 4: Final commit if any fixes were needed** - -```bash -git log --oneline -5 -``` - -Expected: Shows the 4 commit history for this feature. diff --git a/docs/superpowers/specs/2026-06-25-kompress-finetune-design.md b/docs/superpowers/specs/2026-06-25-kompress-finetune-design.md deleted file mode 100644 index f2588f9c2..000000000 --- a/docs/superpowers/specs/2026-06-25-kompress-finetune-design.md +++ /dev/null @@ -1,169 +0,0 @@ -# Kompress Fine-Tune Design - -**Date:** 2026-06-25 -**Status:** Approved -**Owner:** peterlodri-sec - -## Goal - -Fine-tune `chopratejas/kompress-v2-base` (ModernBERT ~149M) to: - -- **B — Quality push:** lower keep_rate from 0.81 toward 0.72–0.75 while holding must_keep_recall above 0.97 -- **C2 — Domain profiles:** teach domain-specific compression intuitions for five input types (code diffs, log streams, JSON blobs, prose/markdown, file trees) -- **C3 — Self-distillation:** use headroom's own proxy compression logs as labeled training data - -Deliverables: fine-tuned model + ONNX artifacts, a blog post, and a Jupyter notebook with a Colab quick-start path and a vast.ai production path. - ---- - -## 1. Data Pipeline - -### 1.1 Domain-tagged datasets - -Each input sequence is prefixed with a domain token so the model builds per-domain compression intuitions rather than one global policy. - -| Domain | Prefix | Source | Keep signal | Drop signal | -|--------|--------|--------|-------------|-------------| -| Code diffs | `[CODE]` | `codeparrot/github-code` + open PR diffs | `+`/`-` lines, function/class signatures, imports | whitespace, unchanged context, comments | -| Log streams | `[LOG]` | Loghub (Apache/HDFS/Linux) | ERROR/WARN/EXCEPTION, stack frames, unique messages | repeated INFO, timestamps, DEBUG noise | -| JSON blobs | `[JSON]` | headroom test data + synthetic API responses | non-null leaf values, rare keys (<5% frequency) | null, empty arrays, boilerplate schema | -| Prose/markdown | `[PROSE]` | HuggingFace docs, GitHub READMEs | key claims, numbers, definitions (TF-IDF top-20%) | transition sentences, repeated examples | -| File trees | `[TREE]` | synthetic from real filesystem structures | non-standard paths, recently modified indicators | `.git/`, stdlib paths, permission columns | - -**Total:** ~50k samples. Colab subset: ~3k (one domain). -**Split:** 80/10/10 train/val/test, stratified by domain. - -### 1.2 C3 — Headroom self-distillation - -headroom's proxy compression logs contain (original_text, compressed_text) pairs from real production requests. Token-level keep/drop labels are recovered by diffing the token sequences. These are real usage decisions — the strongest training signal for the model's actual deployment context. - -Extraction script: reads from headroom's local proxy log directory, tokenizes both sides with the kompress tokenizer, aligns, and outputs labeled sequences tagged `[HDR]`. - -### 1.3 Labeling heuristics - -Heuristics generate weak labels for the five domain datasets. They are intentionally conservative — false positives (keep too much) are preferred over false negatives (drop something important). The model learns to be more aggressive; the heuristics just establish the floor. - ---- - -## 2. Training Setup - -**Platform:** RTX 4090 24GB on vast.ai. ~$0.50/hr. Full run costs ~$0.70–1.00. Budget ($6–7) covers 6–10 experiments. - -**Full fine-tune, no LoRA.** ModernBERT at 149M sits at ~4GB in bf16. A 4090 has 24GB — no reason to constrain. - -### 2.1 Hyperparameters - -| Setting | Value | Reason | -|---------|-------|--------| -| Base model | `chopratejas/kompress-v2-base` | existing checkpoint | -| Task | token classification, binary (0=drop, 1=keep) | same as kompress v2 | -| Loss | weighted cross-entropy, keep_weight=2.5 | penalizes false drops to protect recall | -| Learning rate | 2e-5, cosine decay | standard for BERT-class fine-tune | -| Warmup | 10% of total steps | | -| Batch size | 32 sequences, seq_len=512 | fits 4090; matches kompress inference window | -| Epochs | 3 with early stopping on val must_keep_recall | | -| Optimizer | AdamW, weight_decay=0.01 | | -| Precision | bf16 | | - -### 2.2 B — Threshold calibration (post-training) - -After training, sweep the classification threshold from 0.3 to 0.7 in steps of 0.02. For each threshold compute keep_rate and must_keep_recall on the validation set. Select the highest-compression threshold (lowest keep_rate) where must_keep_recall stays above 0.97. One forward pass — no retraining. - -### 2.3 Evaluation - -Metrics reported per domain and blended: - -- **f1** — overall classification quality -- **must_keep_recall** — fraction of ground-truth keep tokens that are kept; hard floor 0.97 -- **keep_rate** — fraction of tokens kept; target 0.72–0.75 (down from 0.81) - -Compared against kompress-v2-base baseline on the same held-out test splits. - -### 2.4 ONNX export - -Two artifacts, matching headroom's existing naming: - -- `kompress-int8-wo.onnx` — weight-only int8 (MatMulNBits), drop-in replacement for the current 261MB artifact -- `kompress-fp32.onnx` — lossless reference - -Both pushed to HuggingFace Hub as a new model repo. - ---- - -## 3. Blog Post - -**Title:** "Language Immersion at 149M Parameters" -**Published to:** `pocoo.vaked.dev` (existing post format) - -**Framing:** The Sapir-Whorf hypothesis says the language you speak shapes the thoughts you can have. Kompress is trained to think in compressed language — not filtering noise but internalizing a new grammar where redundant tokens don't exist. Domain fine-tuning is immersion: the model develops native compression intuitions per dialect (code, logs, JSON, prose, trees) instead of one blunt global policy. - -**Structure:** - -1. **Hook** — the hypothesis; one paragraph; "what if the way an AI reads context determines what it's capable of thinking?" -2. **The problem** — tool output noise filling context; kompress's token classification job -3. **What kompress does** — ModernBERT architecture, current metrics (f1=0.913, keep_rate=0.81) -4. **Domain immersion** — why code diffs compress differently than log streams; the domain prefix token trick -5. **The dogfood loop** — headroom proxy traffic as teacher; self-distillation; eating your own cooking -6. **The training run** — vast.ai, the numbers, total cost (~$0.70) -7. **Results** — before/after metrics table per domain; threshold calibration curve -8. **Notebook** — link + how to reproduce on Colab or your own GPU - ---- - -## 4. Jupyter Notebook - -**File:** `kompress-finetune.ipynb` -**Hosted:** HuggingFace Hub alongside the model, linked from the blog post. - -### Part 1: Quick Start (Colab / Kaggle, T4, ~15 min) - -- Install deps (`transformers`, `datasets`, `torch`) -- Load `kompress-v2-base` -- Load 3k-sample subset (one domain, pre-labeled) -- Fine-tune 1 epoch -- Threshold calibration sweep -- Eval: f1 / must_keep_recall / keep_rate - -### Part 2: Production Run (vast.ai / self-hosted 4090) - -- Rent instance walkthrough (vast.ai CLI commands) -- Full 5-domain data pipeline -- Headroom log extraction (C3 self-distillation) -- Full fine-tune (3 epochs) -- Per-domain eval -- ONNX export (int8-wo + fp32) -- Push to HuggingFace Hub - -Both parts share the same training cell. Only the dataset loading and export differ. A Colab reader sees the full pipeline structure and can swap in their own data later. - ---- - -## 5. File Layout - -``` -headroom/ - scripts/ - kompress_finetune/ - data/ - build_dataset.py # domain dataset builder + headroom log extractor - label_heuristics.py # weak labeling per domain - train.py # training entry point (HF Trainer) - calibrate.py # threshold sweep post-training - export_onnx.py # int8-wo + fp32 ONNX export - eval.py # per-domain metrics - notebooks/ - kompress-finetune.ipynb # the split notebook - -pocoo.vaked.dev/ - src/posts/ - kompress-finetune-sapir-whorf.md # blog post -``` - ---- - -## 6. Out of Scope - -- LoRA / adapter-per-domain (full fine-tune is sufficient at 149M) -- Contrastive training objective (deferred to a future run) -- Deploying the new model to headroom main branch (separate PR, after eval) -- Training on GPU larger than 4090 (A100 is overkill and burns budget) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.bin/esbuild b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.bin/esbuild deleted file mode 120000 index c83ac0707..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.bin/esbuild +++ /dev/null @@ -1 +0,0 @@ -../esbuild/bin/esbuild \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.bin/tsc b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.bin/tsc deleted file mode 120000 index 0863208a6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.bin/tsc +++ /dev/null @@ -1 +0,0 @@ -../typescript/bin/tsc \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.bin/tsserver b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.bin/tsserver deleted file mode 120000 index f8f8f1a0c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.bin/tsserver +++ /dev/null @@ -1 +0,0 @@ -../typescript/bin/tsserver \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.bin/tsx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.bin/tsx deleted file mode 120000 index f7282dd89..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.bin/tsx +++ /dev/null @@ -1 +0,0 @@ -../tsx/dist/cli.mjs \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.package-lock.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.package-lock.json deleted file mode 100644 index 15855a50c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/.package-lock.json +++ /dev/null @@ -1,324 +0,0 @@ -{ - "name": "@example/node-headroom-compression", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "node_modules/@ai-sdk/anthropic": { - "version": "3.0.64", - "resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-3.0.64.tgz", - "integrity": "sha512-rwLi/Rsuj2pYniQXIrvClHvXDzgM4UQHHnvHTWEF14efnlKclG/1ghpNC+adsRujAbCTr6gRsSbDE2vEqriV7g==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "3.0.8", - "@ai-sdk/provider-utils": "4.0.21" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@ai-sdk/gateway": { - "version": "3.0.80", - "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-3.0.80.tgz", - "integrity": "sha512-uM7kpZB5l977lW7+2X1+klBUxIZQ78+1a9jHlaHFEzcOcmmslTl3sdP0QqfuuBcO0YBM2gwOiqVdp8i4TRQYcw==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "3.0.8", - "@ai-sdk/provider-utils": "4.0.21", - "@vercel/oidc": "3.1.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@ai-sdk/openai": { - "version": "3.0.48", - "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-3.0.48.tgz", - "integrity": "sha512-ALmj/53EXpcRqMbGpPJPP4UOSWw0q4VGpnDo7YctvsynjkrKDmoneDG/1a7VQnSPYHnJp6tTRMf5ZdxZ5whulg==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "3.0.8", - "@ai-sdk/provider-utils": "4.0.21" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-3.0.8.tgz", - "integrity": "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@ai-sdk/provider-utils": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-4.0.21.tgz", - "integrity": "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "3.0.8", - "@standard-schema/spec": "^1.1.0", - "eventsource-parser": "^3.0.6" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz", - "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "license": "MIT" - }, - "node_modules/@vercel/oidc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.1.0.tgz", - "integrity": "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==", - "license": "Apache-2.0", - "engines": { - "node": ">= 20" - } - }, - "node_modules/ai": { - "version": "6.0.138", - "resolved": "https://registry.npmjs.org/ai/-/ai-6.0.138.tgz", - "integrity": "sha512-49OfPe0f5uxJ6jUdA5BBXjIinP6+ZdYfAtpF2aEH64GA5wPcxH2rf/TBUQQ0bbamBz/D+TLMV18xilZqOC+zaA==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/gateway": "3.0.80", - "@ai-sdk/provider": "3.0.8", - "@ai-sdk/provider-utils": "4.0.21", - "@opentelemetry/api": "1.9.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/dotenv": { - "version": "17.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", - "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/esbuild": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz", - "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.4", - "@esbuild/android-arm": "0.27.4", - "@esbuild/android-arm64": "0.27.4", - "@esbuild/android-x64": "0.27.4", - "@esbuild/darwin-arm64": "0.27.4", - "@esbuild/darwin-x64": "0.27.4", - "@esbuild/freebsd-arm64": "0.27.4", - "@esbuild/freebsd-x64": "0.27.4", - "@esbuild/linux-arm": "0.27.4", - "@esbuild/linux-arm64": "0.27.4", - "@esbuild/linux-ia32": "0.27.4", - "@esbuild/linux-loong64": "0.27.4", - "@esbuild/linux-mips64el": "0.27.4", - "@esbuild/linux-ppc64": "0.27.4", - "@esbuild/linux-riscv64": "0.27.4", - "@esbuild/linux-s390x": "0.27.4", - "@esbuild/linux-x64": "0.27.4", - "@esbuild/netbsd-arm64": "0.27.4", - "@esbuild/netbsd-x64": "0.27.4", - "@esbuild/openbsd-arm64": "0.27.4", - "@esbuild/openbsd-x64": "0.27.4", - "@esbuild/openharmony-arm64": "0.27.4", - "@esbuild/sunos-x64": "0.27.4", - "@esbuild/win32-arm64": "0.27.4", - "@esbuild/win32-ia32": "0.27.4", - "@esbuild/win32-x64": "0.27.4" - } - }, - "node_modules/eventsource-parser": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", - "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-tsconfig": { - "version": "4.13.7", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", - "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/headroom-ai": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/headroom-ai/-/headroom-ai-0.1.0.tgz", - "integrity": "sha512-SM5i2kptwsO+KnQqpaLThZVx1ZrmobVw5JRXwF5OvnMvhV/3WbwUI+VvXHTwTCvVq+AAyhkhuVcNXod1piAVuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@ai-sdk/provider": ">=1.0.0", - "@anthropic-ai/sdk": ">=0.30.0", - "ai": ">=6.0.0", - "openai": ">=4.0.0" - }, - "peerDependenciesMeta": { - "@ai-sdk/provider": { - "optional": true - }, - "@anthropic-ai/sdk": { - "optional": true - }, - "ai": { - "optional": true - }, - "openai": { - "optional": true - } - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", - "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.27.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/typescript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz", - "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/zod": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", - "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - } - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/CHANGELOG.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/CHANGELOG.md deleted file mode 100644 index 7c0bda09b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/CHANGELOG.md +++ /dev/null @@ -1,2560 +0,0 @@ -# @ai-sdk/anthropic - -## 3.0.64 - -### Patch Changes - -- 05b8ca2: feat (provider/anthropic): support passing metadata.user_id - -## 3.0.63 - -### Patch Changes - -- 055cd68: fix: publish v6 to latest npm dist tag -- Updated dependencies [055cd68] - - @ai-sdk/provider-utils@4.0.21 - -## 3.0.62 - -### Patch Changes - -- 41c6a56: fix(anthropic): skip passing beta header for tool search tools - -## 3.0.61 - -### Patch Changes - -- 2381567: fix(vertex): throw warning when strict: true for vertexAnthropic - -## 3.0.60 - -### Patch Changes - -- ffe0f90: fix(anthropic): preserve the error code returned by model - -## 3.0.59 - -### Patch Changes - -- Updated dependencies [64ac0fd] - - @ai-sdk/provider-utils@4.0.20 - -## 3.0.58 - -### Patch Changes - -- 3fb4e70: feat(anthropic): support eagerInputStreaming option for fine-grained tool streaming -- Updated dependencies [ad4cfc2] - - @ai-sdk/provider-utils@4.0.19 - -## 3.0.57 - -### Patch Changes - -- Updated dependencies [824b295] - - @ai-sdk/provider-utils@4.0.18 - -## 3.0.56 - -### Patch Changes - -- e49c34d: feat(anthropic): expose anthropic.anthropicBeta to downstream providers -- e49c34d: feat(anthropic): expose anthropic.anthropicBeta to downstream provider - -## 3.0.55 - -### Patch Changes - -- 7531e72: fix(provider/anthropic): handle encrypted_code_execution_result for multi-turn with web_fetch/web_search 20260209 - -## 3.0.54 - -### Patch Changes - -- 56c67d5: feat(provider/anthropic): add support for Anthropic web tools `web_fetch_20260209` and `web_search_20260209` - -## 3.0.53 - -### Patch Changes - -- 89caf28: fix(openai-compat): decode base64 string data - -## 3.0.52 - -### Patch Changes - -- Updated dependencies [08336f1] - - @ai-sdk/provider-utils@4.0.17 - -## 3.0.51 - -### Patch Changes - -- 64a8fae: chore: remove obsolete model IDs for Anthropic, Google, OpenAI, xAI - -## 3.0.50 - -### Patch Changes - -- Updated dependencies [58bc42d] - - @ai-sdk/provider-utils@4.0.16 - -## 3.0.49 - -### Patch Changes - -- d98d9ba: Migrated deprecated `output_format` parameter to `output_config.format` for structured outputs + Enabled native structured output support for Bedrock Anthropic models via `output_config.format`. - -## 3.0.48 - -### Patch Changes - -- 2164cdf: feat(anthropic): add the new code_execution tool - -## 3.0.47 - -### Patch Changes - -- 17978c6: Pass `cacheControl` provider option as top-level `cache_control` in Anthropic API request body to support automatic caching. - -## 3.0.46 - -### Patch Changes - -- b094c07: fix compaction_delta streaming schema to allow null content - -## 3.0.45 - -### Patch Changes - -- 2a1c664: feat(provider/anthropic): add support for new Claude Sonnet 4.6 model - -## 3.0.44 - -### Patch Changes - -- 23ac4a3: fix(provider/anthropic): minor follow up to support no-op speed standard - -## 3.0.43 - -### Patch Changes - -- Updated dependencies [4024a3a] - - @ai-sdk/provider-utils@4.0.15 - -## 3.0.42 - -### Patch Changes - -- 99fbed8: feat: normalize provider specific model options type names and ensure they are exported - -## 3.0.41 - -### Patch Changes - -- c60b393: feat(anthropic): add the new compaction feature - -## 3.0.40 - -### Patch Changes - -- 8c2b1e1: fix(provider/anthropic): include actual raw usage data for `response.usage.raw` when streaming - -## 3.0.39 - -### Patch Changes - -- 0a0d29c: feat(anthropic): add support for Opus 4.6 fast mode - -## 3.0.38 - -### Patch Changes - -- Updated dependencies [7168375] - - @ai-sdk/provider@3.0.8 - - @ai-sdk/provider-utils@4.0.14 - -## 3.0.37 - -### Patch Changes - -- e288302: feat(anthropic): add support for Opus 4.6 - -## 3.0.36 - -### Patch Changes - -- 1652320: feat(anthropic): support custom tool-reference content for deferred tool loading - -## 3.0.35 - -### Patch Changes - -- Updated dependencies [53f6731] - - @ai-sdk/provider@3.0.7 - - @ai-sdk/provider-utils@4.0.13 - -## 3.0.34 - -### Patch Changes - -- Updated dependencies [96936e5] - - @ai-sdk/provider-utils@4.0.12 - -## 3.0.33 - -### Patch Changes - -- 445cbe3: fix streaming context_management field location - was incorrectly expected inside delta object but API returns it at message_delta root level - -## 3.0.32 - -### Patch Changes - -- c33343b: fix(anthropic): add missing param in tool schema - -## 3.0.31 - -### Patch Changes - -- Updated dependencies [2810850] - - @ai-sdk/provider-utils@4.0.11 - - @ai-sdk/provider@3.0.6 - -## 3.0.30 - -### Patch Changes - -- 1524271: chore: add skill information to README files - -## 3.0.29 - -### Patch Changes - -- b9d105f: Fix cache usage reporting for anthropic stream - -## 3.0.28 - -### Patch Changes - -- 2445da4: fix(provider/anthropic): populate outputTokens.text field in usage - -## 3.0.27 - -### Patch Changes - -- 572ea12: feat(anthropic): allow custom/dynamic key for providerOptions - -## 3.0.26 - -### Patch Changes - -- 2c70b90: chore: update provider docs - -## 3.0.25 - -### Patch Changes - -- 0bb9bcd: feat(provider/anthropic): add computer_20251124 tool for claude opus 4.5 - -## 3.0.24 - -### Patch Changes - -- Updated dependencies [462ad00] - - @ai-sdk/provider-utils@4.0.10 - -## 3.0.23 - -### Patch Changes - -- 4de5a1d: chore: excluded tests from src folder in npm package -- Updated dependencies [4de5a1d] - - @ai-sdk/provider@3.0.5 - - @ai-sdk/provider-utils@4.0.9 - -## 3.0.22 - -### Patch Changes - -- 8ccf04b: Add `authToken` option to support `Authorization: Bearer` authentication as an alternative to `x-api-key` header authentication. - -## 3.0.21 - -### Patch Changes - -- 662d359: feat(anthropic): deferred results for tool search tool - -## 3.0.20 - -### Patch Changes - -- 2b8369d: chore: add docs to package dist - -## 3.0.19 - -### Patch Changes - -- 8dc54db: chore: add src folders to package bundle - -## 3.0.18 - -### Patch Changes - -- c10bd49: fix(anthropic): handle web_search_result_location citations and add webFetch documents to citationDocuments - -## 3.0.17 - -### Patch Changes - -- 4729bed: Fix JSON parsing crash when handling Anthropic web_fetch tool error results - -## 3.0.16 - -### Patch Changes - -- d36fa72: Not sending structured output beta header for json response tool - -## 3.0.15 - -### Patch Changes - -- Updated dependencies [5c090e7] - - @ai-sdk/provider@3.0.4 - - @ai-sdk/provider-utils@4.0.8 - -## 3.0.14 - -### Patch Changes - -- Updated dependencies [46f46e4] - - @ai-sdk/provider-utils@4.0.7 - -## 3.0.13 - -### Patch Changes - -- Updated dependencies [1b11dcb] - - @ai-sdk/provider-utils@4.0.6 - - @ai-sdk/provider@3.0.3 - -## 3.0.12 - -### Patch Changes - -- Updated dependencies [34d1c8a] - - @ai-sdk/provider-utils@4.0.5 - -## 3.0.11 - -### Patch Changes - -- 8c1c6e3: fix(anthropic): add application/json type regex matching - -## 3.0.10 - -### Patch Changes - -- 02d9b68: fix `input_tokens` compatibility - -## 3.0.9 - -### Patch Changes - -- de2399b: fix(anthropic): assign type urls in file parts correctly - -## 3.0.8 - -### Patch Changes - -- bee4f82: fix(anthropic): enable structured output support for claude-haiku-4-5 - - This fixes an issue where the `strict: true` property was not included in the request body when using tools with Claude Haiku 4.5, because `supportsStructuredOutput` was incorrectly set to `false` for this model. - - Claude Haiku 4.5 supports structured outputs, so the `strict` property should be forwarded to the Anthropic API when specified on tools. - -## 3.0.7 - -### Patch Changes - -- Updated dependencies [d937c8f] - - @ai-sdk/provider@3.0.2 - - @ai-sdk/provider-utils@4.0.4 - -## 3.0.6 - -### Patch Changes - -- 2231e84: fix(anthropic): implement temperature/topP mutual exclusivity - - Resolves the Anthropic API breaking change where sampling parameters must use only `temperature` OR `top_p`, not both. When both parameters are provided: - - - Temperature takes priority and topP is ignored - - A warning is added to inform users: "topP is not supported when temperature is set. topP is ignored." - - The validation only runs when thinking mode is not enabled (thinking mode has its own parameter validation) - - See Anthropic migration guide: https://platform.claude.com/docs/en/about-claude/models/migrating-to-claude-4 - -## 3.0.5 - -### Patch Changes - -- Updated dependencies [0b429d4] - - @ai-sdk/provider-utils@4.0.3 - -## 3.0.4 - -### Patch Changes - -- bf39dac: Fix: Use provider tool name in Tool Search Tool results - -## 3.0.3 - -### Patch Changes - -- 77b760d: fix(anthropic): support deferred results for web search/fetch tool - -## 3.0.2 - -### Patch Changes - -- 863d34f: fix: trigger release to update `@latest` -- Updated dependencies [863d34f] - - @ai-sdk/provider@3.0.1 - - @ai-sdk/provider-utils@4.0.2 - -## 3.0.1 - -### Patch Changes - -- Updated dependencies [29264a3] - - @ai-sdk/provider-utils@4.0.1 - -## 3.0.0 - -### Major Changes - -- dee8b05: ai SDK 6 beta - -### Minor Changes - -- 78928cb: release: start 5.1 beta - -### Patch Changes - -- 0c3b58b: fix(provider): add specificationVersion to ProviderV3 -- 0adc679: feat(provider): shared spec v3 -- 50b70d6: feat(anthropic): add programmatic tool calling -- b8ea36e: feat(provider/anthropic): Anthropic-native structured outputs -- ed537e1: Add support for pdf file in tool result in anthropic -- 2109385: 'fix(anthropic): Opus 4.5 `maxOutputTokens` bump `32000` -> `64000`' -- 7c4328e: Adds url-based pdf and image support for anthropic tool results -- 8d9e8ad: chore(provider): remove generics from EmbeddingModelV3 - - Before - - ```ts - model.textEmbeddingModel("my-model-id"); - ``` - - After - - ```ts - model.embeddingModel("my-model-id"); - ``` - -- f33a018: chore: add model ID for Haiku 4.5 -- b2dbfbf: add context_management for anthropic -- dce03c4: feat: tool input examples -- 2625a04: feat(openai); update spec for mcp approval -- 11e4abe: feat(provider/anthropic): web search tool updates -- f13958c: chore(antropic): allow custom names for provider-defined tools -- afb00e3: feat(provider/anthropic): add text_editor_20250728 tool support - - Add text_editor_20250728 tool for Claude 4 models (Sonnet 4, Opus 4, Opus 4.1) with optional max_characters parameter and no undo_edit command support. - -- 95f65c2: chore: use import \* from zod/v4 -- 954c356: feat(openai): allow custom names for provider-defined tools -- 9e35785: fix(anthropic): send {} as tool input when streaming tool calls without arguments -- 544d4e8: chore(specification): rename v3 provider defined tool to provider tool -- a5f77a6: fix(anthropic): remove outdated tool name docs -- ca07285: feat(anthropic): add prompt caching validation -- a5a8db4: chore: add model ID for Sonnet 4.5 -- 1742445: Support for custom provider name in google and anthropic providers -- e8109d3: feat: tool execution approval -- 87db851: fix(vertex/anthropic): passing beta header only for structured outputs -- f6603b7: fix(provider/anthropic): correct raw usage information -- ed329cb: feat: `Provider-V3` -- 3bd2689: feat: extended token usage -- 1cad0ab: feat: add provider version to user-agent header -- 2049c5b: Fix handling of error in web fetch tool in anthropic -- 4c5a6be: feat(provider/anthropic): default and limit maxTokens based on model -- 9e1e758: fix(anthropic): use default thinking budget when unspecified -- 589a4ee: fix(anthropic): simplify pulling first chunk -- 8dac895: feat: `LanguageModelV3` -- 6f845b4: Add support for 2025-08-25 code execution tool -- 9354297: feat(provider/anthropic): add support for Agent Skills -- 03849b0: throw 500 error when the first stream chunk is an error -- 0ae783e: feat(anthropic): add the new tool search tools -- 457318b: chore(provider,ai): switch to SharedV3Warning and unified warnings -- eb56fc6: fix(anthropic): pull first chunk without async IIFE -- fa35e95: feat(provider/anthropic): add web fetch tool -- 80894b3: add return `file_id` property for anthropic code-execution-20250825 to download output files. -- 366f50b: chore(provider): add deprecated textEmbeddingModel and textEmbedding aliases -- 81d4308: feat(provider/anthropic): mcp connector support -- 6fc35cb: Retain user-supplied betas. -- f4db7b5: feat(provider/anthropic): expose container from response in provider metadata -- 6c38080: fix(anthropic): support pdf responses in web_fetch_tool_result schema validation -- 4616b86: chore: update zod peer depenedency version -- dedf206: feat(provider/anthropic): expose stop_sequence in provider metadata -- 983e394: chore(provider/anthropic): add missing provider options jsdoc -- 0e38a79: support ANTHROPIC_BASE_URL -- cf4e2a9: Add support for tool calling with structured output -- f4e4a95: feat(provider/anthropic): enable fine grained tool streaming by default -- 21f378c: fix(provider/anthropic): do not limit maxTokens when model id is unknown -- c5440c5: chore(provider/anthropic): update anthropic model ids -- 1d15673: fix(provider/anthropic): clamp temperature to valid 0-1 range with warnings -- 9cff587: chore(provider/anthropic): lazy schema loading -- d129d89: chore(anthropic): remove unnecessary doc -- 3794514: feat: flexible tool output content support -- e1e2821: fix(provider/anthropic): support null title in web fetch tool -- cbf52cd: feat: expose raw finish reason -- 10c1322: fix: moved dependency `@ai-sdk/test-server` to devDependencies -- d08308b: feat(provider/anthropic): memory tool -- 05d5b9a: fix(anthropic): make title field nullable in web_fetch and web_search tool output schemas -- 1bd7d32: feat: tool-specific strict mode -- 83aaad8: Opus 4.5 and `effort` provider option -- Updated dependencies - - @ai-sdk/provider@3.0.0 - - @ai-sdk/provider-utils@4.0.0 - -## 3.0.0-beta.98 - -### Patch Changes - -- 2049c5b: Fix handling of error in web fetch tool in anthropic - -## 3.0.0-beta.97 - -### Patch Changes - -- Updated dependencies [475189e] - - @ai-sdk/provider@3.0.0-beta.32 - - @ai-sdk/provider-utils@4.0.0-beta.59 - -## 3.0.0-beta.96 - -### Patch Changes - -- 2625a04: feat(openai); update spec for mcp approval -- Updated dependencies [2625a04] - - @ai-sdk/provider@3.0.0-beta.31 - - @ai-sdk/provider-utils@4.0.0-beta.58 - -## 3.0.0-beta.95 - -### Patch Changes - -- cbf52cd: feat: expose raw finish reason -- Updated dependencies [cbf52cd] - - @ai-sdk/provider@3.0.0-beta.30 - - @ai-sdk/provider-utils@4.0.0-beta.57 - -## 3.0.0-beta.94 - -### Patch Changes - -- Updated dependencies [9549c9e] - - @ai-sdk/provider@3.0.0-beta.29 - - @ai-sdk/provider-utils@4.0.0-beta.56 - -## 3.0.0-beta.93 - -### Patch Changes - -- 50b70d6: feat(anthropic): add programmatic tool calling -- Updated dependencies [50b70d6] - - @ai-sdk/provider-utils@4.0.0-beta.55 - -## 3.0.0-beta.92 - -### Patch Changes - -- Updated dependencies [9061dc0] - - @ai-sdk/provider-utils@4.0.0-beta.54 - - @ai-sdk/provider@3.0.0-beta.28 - -## 3.0.0-beta.91 - -### Patch Changes - -- d129d89: chore(anthropic): remove unnecessary doc - -## 3.0.0-beta.90 - -### Patch Changes - -- 366f50b: chore(provider): add deprecated textEmbeddingModel and textEmbedding aliases -- Updated dependencies [366f50b] - - @ai-sdk/provider@3.0.0-beta.27 - - @ai-sdk/provider-utils@4.0.0-beta.53 - -## 3.0.0-beta.89 - -### Patch Changes - -- Updated dependencies [763d04a] - - @ai-sdk/provider-utils@4.0.0-beta.52 - -## 3.0.0-beta.88 - -### Patch Changes - -- 87db851: fix(vertex/anthropic): passing beta header only for structured outputs - -## 3.0.0-beta.87 - -### Patch Changes - -- Updated dependencies [c1efac4] - - @ai-sdk/provider-utils@4.0.0-beta.51 - -## 3.0.0-beta.86 - -### Patch Changes - -- Updated dependencies [32223c8] - - @ai-sdk/provider-utils@4.0.0-beta.50 - -## 3.0.0-beta.85 - -### Patch Changes - -- Updated dependencies [83e5744] - - @ai-sdk/provider-utils@4.0.0-beta.49 - -## 3.0.0-beta.84 - -### Patch Changes - -- Updated dependencies [960ec8f] - - @ai-sdk/provider-utils@4.0.0-beta.48 - -## 3.0.0-beta.83 - -### Patch Changes - -- 6c38080: fix(anthropic): support pdf responses in web_fetch_tool_result schema validation - -## 3.0.0-beta.82 - -### Patch Changes - -- Updated dependencies [e9e157f] - - @ai-sdk/provider-utils@4.0.0-beta.47 - -## 3.0.0-beta.81 - -### Patch Changes - -- Updated dependencies [81e29ab] - - @ai-sdk/provider-utils@4.0.0-beta.46 - -## 3.0.0-beta.80 - -### Patch Changes - -- 05d5b9a: fix(anthropic): make title field nullable in web_fetch and web_search tool output schemas - -## 3.0.0-beta.79 - -### Patch Changes - -- 3bd2689: feat: extended token usage -- Updated dependencies [3bd2689] - - @ai-sdk/provider@3.0.0-beta.26 - - @ai-sdk/provider-utils@4.0.0-beta.45 - -## 3.0.0-beta.78 - -### Patch Changes - -- 9e1e758: fix(anthropic): use default thinking budget when unspecified - -## 3.0.0-beta.77 - -### Patch Changes - -- b2dbfbf: add context_management for anthropic - -## 3.0.0-beta.76 - -### Patch Changes - -- Updated dependencies [53f3368] - - @ai-sdk/provider@3.0.0-beta.25 - - @ai-sdk/provider-utils@4.0.0-beta.44 - -## 3.0.0-beta.75 - -### Patch Changes - -- 0ae783e: feat(anthropic): add the new tool search tools - -## 3.0.0-beta.74 - -### Patch Changes - -- dce03c4: feat: tool input examples -- Updated dependencies [dce03c4] - - @ai-sdk/provider-utils@4.0.0-beta.43 - - @ai-sdk/provider@3.0.0-beta.24 - -## 3.0.0-beta.73 - -### Patch Changes - -- Updated dependencies [3ed5519] - - @ai-sdk/provider-utils@4.0.0-beta.42 - -## 3.0.0-beta.72 - -### Patch Changes - -- a5f77a6: fix(anthropic): remove outdated tool name docs - -## 3.0.0-beta.71 - -### Patch Changes - -- 1bd7d32: feat: tool-specific strict mode -- Updated dependencies [1bd7d32] - - @ai-sdk/provider-utils@4.0.0-beta.41 - - @ai-sdk/provider@3.0.0-beta.23 - -## 3.0.0-beta.70 - -### Patch Changes - -- f13958c: chore(antropic): allow custom names for provider-defined tools - -## 3.0.0-beta.69 - -### Patch Changes - -- 589a4ee: fix(anthropic): simplify pulling first chunk - -## 3.0.0-beta.68 - -### Patch Changes - -- 9e35785: fix(anthropic): send {} as tool input when streaming tool calls without arguments - -## 3.0.0-beta.67 - -### Patch Changes - -- eb56fc6: fix(anthropic): pull first chunk without async IIFE - -## 3.0.0-beta.66 - -### Patch Changes - -- 544d4e8: chore(specification): rename v3 provider defined tool to provider tool -- Updated dependencies [544d4e8] - - @ai-sdk/provider-utils@4.0.0-beta.40 - - @ai-sdk/provider@3.0.0-beta.22 - -## 3.0.0-beta.65 - -### Patch Changes - -- 954c356: feat(openai): allow custom names for provider-defined tools -- Updated dependencies [954c356] - - @ai-sdk/provider-utils@4.0.0-beta.39 - - @ai-sdk/provider@3.0.0-beta.21 - -## 3.0.0-beta.64 - -### Patch Changes - -- 03849b0: throw 500 error when the first stream chunk is an error -- Updated dependencies [03849b0] - - @ai-sdk/provider-utils@4.0.0-beta.38 - -## 3.0.0-beta.63 - -### Patch Changes - -- 457318b: chore(provider,ai): switch to SharedV3Warning and unified warnings -- Updated dependencies [457318b] - - @ai-sdk/provider@3.0.0-beta.20 - - @ai-sdk/provider-utils@4.0.0-beta.37 - -## 3.0.0-beta.62 - -### Patch Changes - -- 8d9e8ad: chore(provider): remove generics from EmbeddingModelV3 - - Before - - ```ts - model.textEmbeddingModel("my-model-id"); - ``` - - After - - ```ts - model.embeddingModel("my-model-id"); - ``` - -- Updated dependencies [8d9e8ad] - - @ai-sdk/provider@3.0.0-beta.19 - - @ai-sdk/provider-utils@4.0.0-beta.36 - -## 3.0.0-beta.61 - -### Patch Changes - -- Updated dependencies [10d819b] - - @ai-sdk/provider@3.0.0-beta.18 - - @ai-sdk/provider-utils@4.0.0-beta.35 - -## 3.0.0-beta.60 - -### Patch Changes - -- 6fc35cb: Retain user-supplied betas. - -## 3.0.0-beta.59 - -### Patch Changes - -- 2109385: 'fix(anthropic): Opus 4.5 `maxOutputTokens` bump `32000` -> `64000`' - -## 3.0.0-beta.58 - -### Patch Changes - -- 83aaad8: Opus 4.5 and `effort` provider option - -## 3.0.0-beta.57 - -### Patch Changes - -- b8ea36e: feat(provider/anthropic): Anthropic-native structured outputs - -## 3.0.0-beta.56 - -### Patch Changes - -- 983e394: chore(provider/anthropic): add missing provider options jsdoc - -## 3.0.0-beta.55 - -### Patch Changes - -- Updated dependencies [db913bd] - - @ai-sdk/provider@3.0.0-beta.17 - - @ai-sdk/provider-utils@4.0.0-beta.34 - -## 3.0.0-beta.54 - -### Patch Changes - -- 1d15673: fix(provider/anthropic): clamp temperature to valid 0-1 range with warnings - -## 3.0.0-beta.53 - -### Patch Changes - -- Updated dependencies [b681d7d] - - @ai-sdk/provider@3.0.0-beta.16 - - @ai-sdk/provider-utils@4.0.0-beta.33 - -## 3.0.0-beta.52 - -### Patch Changes - -- Updated dependencies [32d8dbb] - - @ai-sdk/provider-utils@4.0.0-beta.32 - -## 3.0.0-beta.51 - -### Patch Changes - -- 1742445: Support for custom provider name in google and anthropic providers - -## 3.0.0-beta.50 - -### Patch Changes - -- Updated dependencies [bb36798] - - @ai-sdk/provider@3.0.0-beta.15 - - @ai-sdk/provider-utils@4.0.0-beta.31 - -## 3.0.0-beta.49 - -### Patch Changes - -- Updated dependencies [4f16c37] - - @ai-sdk/provider-utils@4.0.0-beta.30 - -## 3.0.0-beta.48 - -### Patch Changes - -- Updated dependencies [af3780b] - - @ai-sdk/provider@3.0.0-beta.14 - - @ai-sdk/provider-utils@4.0.0-beta.29 - -## 3.0.0-beta.47 - -### Patch Changes - -- Updated dependencies [016b111] - - @ai-sdk/provider-utils@4.0.0-beta.28 - -## 3.0.0-beta.46 - -### Patch Changes - -- Updated dependencies [37c58a0] - - @ai-sdk/provider@3.0.0-beta.13 - - @ai-sdk/provider-utils@4.0.0-beta.27 - -## 3.0.0-beta.45 - -### Patch Changes - -- f4e4a95: feat(provider/anthropic): enable fine grained tool streaming by default - -## 3.0.0-beta.44 - -### Patch Changes - -- cf4e2a9: Add support for tool calling with structured output - -## 3.0.0-beta.43 - -### Patch Changes - -- Updated dependencies [d1bdadb] - - @ai-sdk/provider@3.0.0-beta.12 - - @ai-sdk/provider-utils@4.0.0-beta.26 - -## 3.0.0-beta.42 - -### Patch Changes - -- Updated dependencies [4c44a5b] - - @ai-sdk/provider@3.0.0-beta.11 - - @ai-sdk/provider-utils@4.0.0-beta.25 - -## 3.0.0-beta.41 - -### Patch Changes - -- 0c3b58b: fix(provider): add specificationVersion to ProviderV3 -- Updated dependencies [0c3b58b] - - @ai-sdk/provider@3.0.0-beta.10 - - @ai-sdk/provider-utils@4.0.0-beta.24 - -## 3.0.0-beta.40 - -### Patch Changes - -- Updated dependencies [a755db5] - - @ai-sdk/provider@3.0.0-beta.9 - - @ai-sdk/provider-utils@4.0.0-beta.23 - -## 3.0.0-beta.39 - -### Patch Changes - -- Updated dependencies [58920e0] - - @ai-sdk/provider-utils@4.0.0-beta.22 - -## 3.0.0-beta.38 - -### Patch Changes - -- Updated dependencies [293a6b7] - - @ai-sdk/provider-utils@4.0.0-beta.21 - -## 3.0.0-beta.37 - -### Patch Changes - -- 7c4328e: Adds url-based pdf and image support for anthropic tool results - -## 3.0.0-beta.36 - -### Patch Changes - -- 21f378c: fix(provider/anthropic): do not limit maxTokens when model id is unknown - -## 3.0.0-beta.35 - -### Patch Changes - -- 80894b3: add return `file_id` property for anthropic code-execution-20250825 to download output files. - -## 3.0.0-beta.34 - -### Patch Changes - -- Updated dependencies [fca786b] - - @ai-sdk/provider-utils@4.0.0-beta.20 - -## 3.0.0-beta.33 - -### Patch Changes - -- 0e38a79: support ANTHROPIC_BASE_URL - -## 3.0.0-beta.32 - -### Patch Changes - -- f4db7b5: feat(provider/anthropic): expose container from response in provider metadata - -## 3.0.0-beta.31 - -### Patch Changes - -- ca07285: feat(anthropic): add prompt caching validation - -## 3.0.0-beta.30 - -### Patch Changes - -- 9354297: feat(provider/anthropic): add support for Agent Skills - -## 3.0.0-beta.29 - -### Patch Changes - -- 3794514: feat: flexible tool output content support -- Updated dependencies [3794514] - - @ai-sdk/provider-utils@4.0.0-beta.19 - - @ai-sdk/provider@3.0.0-beta.8 - -## 3.0.0-beta.28 - -### Patch Changes - -- 81d4308: feat(provider/anthropic): mcp connector support -- Updated dependencies [81d4308] - - @ai-sdk/provider@3.0.0-beta.7 - - @ai-sdk/provider-utils@4.0.0-beta.18 - -## 3.0.0-beta.27 - -### Patch Changes - -- 4c5a6be: feat(provider/anthropic): default and limit maxTokens based on model - -## 3.0.0-beta.26 - -### Patch Changes - -- f33a018: chore: add model ID for Haiku 4.5 - -## 3.0.0-beta.25 - -### Patch Changes - -- Updated dependencies [703459a] - - @ai-sdk/provider-utils@4.0.0-beta.17 - -## 3.0.0-beta.24 - -### Patch Changes - -- d08308b: feat(provider/anthropic): memory tool - -## 3.0.0-beta.23 - -### Patch Changes - -- 6f845b4: Add support for 2025-08-25 code execution tool - -## 3.0.0-beta.22 - -### Patch Changes - -- ed537e1: Add support for pdf file in tool result in anthropic - -## 3.0.0-beta.21 - -### Patch Changes - -- Updated dependencies [6306603] - - @ai-sdk/provider-utils@4.0.0-beta.16 - -## 3.0.0-beta.20 - -### Patch Changes - -- Updated dependencies [f0b2157] - - @ai-sdk/provider-utils@4.0.0-beta.15 - -## 3.0.0-beta.19 - -### Patch Changes - -- Updated dependencies [3b1d015] - - @ai-sdk/provider-utils@4.0.0-beta.14 - -## 3.0.0-beta.18 - -### Patch Changes - -- Updated dependencies [d116b4b] - - @ai-sdk/provider-utils@4.0.0-beta.13 - -## 3.0.0-beta.17 - -### Patch Changes - -- Updated dependencies [7e32fea] - - @ai-sdk/provider-utils@4.0.0-beta.12 - -## 3.0.0-beta.16 - -### Patch Changes - -- 9cff587: chore(provider/anthropic): lazy schema loading - -## 3.0.0-beta.15 - -### Patch Changes - -- 95f65c2: chore: use import \* from zod/v4 -- Updated dependencies - - @ai-sdk/provider-utils@4.0.0-beta.11 - -## 3.0.0-beta.14 - -### Major Changes - -- dee8b05: ai SDK 6 beta - -### Patch Changes - -- Updated dependencies [dee8b05] - - @ai-sdk/provider@3.0.0-beta.6 - - @ai-sdk/provider-utils@4.0.0-beta.10 - -## 2.1.0-beta.13 - -### Patch Changes - -- Updated dependencies [521c537] - - @ai-sdk/provider-utils@3.1.0-beta.9 - -## 2.1.0-beta.12 - -### Patch Changes - -- Updated dependencies [e06565c] - - @ai-sdk/provider-utils@3.1.0-beta.8 - -## 2.1.0-beta.11 - -### Patch Changes - -- e8109d3: feat: tool execution approval -- Updated dependencies - - @ai-sdk/provider@2.1.0-beta.5 - - @ai-sdk/provider-utils@3.1.0-beta.7 - -## 2.1.0-beta.10 - -### Patch Changes - -- dedf206: feat(provider/anthropic): expose stop_sequence in provider metadata - -## 2.1.0-beta.9 - -### Patch Changes - -- 0adc679: feat(provider): shared spec v3 -- Updated dependencies - - @ai-sdk/provider-utils@3.1.0-beta.6 - - @ai-sdk/provider@2.1.0-beta.4 - -## 2.1.0-beta.8 - -### Patch Changes - -- a5a8db4: chore: add model ID for Sonnet 4.5 - -## 2.1.0-beta.7 - -### Patch Changes - -- e1e2821: fix(provider/anthropic): support null title in web fetch tool - -## 2.1.0-beta.6 - -### Patch Changes - -- 8dac895: feat: `LanguageModelV3` -- 10c1322: fix: moved dependency `@ai-sdk/test-server` to devDependencies -- Updated dependencies [8dac895] - - @ai-sdk/provider-utils@3.1.0-beta.5 - - @ai-sdk/provider@2.1.0-beta.3 - -## 2.1.0-beta.5 - -### Patch Changes - -- 11e4abe: feat(provider/anthropic): web search tool updates -- afb00e3: feat(provider/anthropic): add text_editor_20250728 tool support - - Add text_editor_20250728 tool for Claude 4 models (Sonnet 4, Opus 4, Opus 4.1) with optional max_characters parameter and no undo_edit command support. - -- f6603b7: fix(provider/anthropic): correct raw usage information -- fa35e95: feat(provider/anthropic): add web fetch tool -- c5440c5: chore(provider/anthropic): update anthropic model ids - -## 2.1.0-beta.4 - -### Patch Changes - -- 4616b86: chore: update zod peer depenedency version -- Updated dependencies [4616b86] - - @ai-sdk/provider-utils@3.1.0-beta.4 - -## 2.1.0-beta.3 - -### Patch Changes - -- ed329cb: feat: `Provider-V3` -- Updated dependencies - - @ai-sdk/provider@2.1.0-beta.2 - - @ai-sdk/provider-utils@3.1.0-beta.3 - -## 2.1.0-beta.2 - -### Patch Changes - -- 1cad0ab: feat: add provider version to user-agent header -- Updated dependencies [0c4822d] - - @ai-sdk/provider@2.1.0-beta.1 - - @ai-sdk/provider-utils@3.1.0-beta.2 - -## 2.1.0-beta.1 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/test-server@1.0.0-beta.0 - - @ai-sdk/provider-utils@3.1.0-beta.1 - -## 2.1.0-beta.0 - -### Minor Changes - -- 78928cb: release: start 5.1 beta - -### Patch Changes - -- Updated dependencies [78928cb] - - @ai-sdk/provider@2.1.0-beta.0 - - @ai-sdk/provider-utils@3.1.0-beta.0 - -## 2.0.17 - -### Patch Changes - -- da92132: fix(provider/anthorpic): add cacheControl to AnthropicProviderOptions - -## 2.0.16 - -### Patch Changes - -- Updated dependencies [0294b58] - - @ai-sdk/provider-utils@3.0.9 - -## 2.0.15 - -### Patch Changes - -- c8aab0a: fix (provider/anthropic): revert cd458a8c1667df86e6987a1f2e06159823453864 - -## 2.0.14 - -### Patch Changes - -- 2338c79: feat (provider/anthropic): update jsdoc of anthropic tools - -## 2.0.13 - -### Patch Changes - -- cd458a8: fix(anthropic): reorder tool_result parts to front of combined user messages - - Reorders tool_result content to appear before user text within combined user messages, ensuring Claude API validation requirements are met while preserving the intentional message combining behavior that prevents role alternation errors. Fixes #8318. - -## 2.0.12 - -### Patch Changes - -- Updated dependencies [99964ed] - - @ai-sdk/provider-utils@3.0.8 - -## 2.0.11 - -### Patch Changes - -- c7fee29: feat(anthropic): handle `pause_turn` as value for `stop_reason` - -## 2.0.10 - -### Patch Changes - -- c152ef7: feat(providers/anthropic): map 'refusal' stop reason to 'content-filter' finishReason - -## 2.0.9 - -### Patch Changes - -- cdc6b7a: fix(provider/anthropic): disable parallel tool use when using json output tool for structured responses - -## 2.0.8 - -### Patch Changes - -- Updated dependencies [886e7cd] - - @ai-sdk/provider-utils@3.0.7 - -## 2.0.7 - -### Patch Changes - -- Updated dependencies [1b5a3d3] - - @ai-sdk/provider-utils@3.0.6 - -## 2.0.6 - -### Patch Changes - -- Updated dependencies [0857788] - - @ai-sdk/provider-utils@3.0.5 - -## 2.0.5 - -### Patch Changes - -- Updated dependencies [68751f9] - - @ai-sdk/provider-utils@3.0.4 - -## 2.0.4 - -### Patch Changes - -- ae859ce: Added support for Anthropic provider's server-side code execution tool - -## 2.0.3 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@3.0.3 - -## 2.0.2 - -### Patch Changes - -- Updated dependencies [38ac190] - - @ai-sdk/provider-utils@3.0.2 - -## 2.0.1 - -### Patch Changes - -- Updated dependencies [90d212f] - - @ai-sdk/provider-utils@3.0.1 - -## 2.0.0 - -### Major Changes - -- d5f588f: AI SDK 5 - -### Patch Changes - -- ad66c0e: feat (provider/anthropic): json response schema support via tool calls -- 8f2854f: feat (provider/anthropic): send web search tool calls -- 5d959e7: refactor: updated openai + anthropic tool use server side -- 8dfcb11: feat(anthropic/citation): text support for citations -- 9f73965: feat (provider/anthropic): parse websearch tool args -- e2aceaf: feat: add raw chunk support -- fdff8a4: fix(provider/anthropic): correct Claude 4 model ID format -- eb173f1: chore (providers): remove model shorthand deprecation warnings -- 4f26d59: feat(provider/anthropic): add disable parallel tool use option -- 25f3454: feat(provider/anthropic): add PDF citation support with document sources for streamText -- a85c85f: fix (provider/anthropic): streaming json output -- 5c9eec4: chore(providers/anthropic): switch to providerOptions -- 2e13791: feat(anthropic): add server-side web search support -- 66962ed: fix(packages): export node10 compatible types -- 075711d: fix (provider/anthropic): return stop finish reason for json output with tool -- 269683f: Add raw Anthropic usage information to provider metadata -- d601ed9: fix (provider/anthropic): send tool call id in tool-input-start chunk -- b9ddcdd: feat(anthropic): add text_editor_20250429 tool for Claude 4 models -- 91715e5: fix (provider/google-vertex): fix anthropic support for image urls in messages -- ca8aac6: feat (providers/anthropic): add claude v4 models -- 61ab528: Add support for URL-based PDF documents in the Anthropic provider -- 84577c8: fix (providers/anthropic): remove fine grained tool streaming beta -- d1a034f: feature: using Zod 4 for internal stuff -- 6392f60: fix(anthropic): resolve web search API validation errors with partial location + provider output -- 205077b: fix: improve Zod compatibility -- ee5a9c0: feat: streamText onChunk raw chunk support -- f418dd7: Added anthropic provider defined tool support to amazon bedrock -- 362b048: add web search tool support -- 399e056: fix: anthropic computer tool -- 0b678b2: feat (provider/anthropic): enable streaming tool calls -- f10304b: feat(tool-calling): don't require the user to have to pass parameters -- a753b3a: feat (provider/anthropic): cache control for tools -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0 - - @ai-sdk/provider@2.0.0 - -## 2.0.0-beta.13 - -### Patch Changes - -- Updated dependencies [88a8ee5] - - @ai-sdk/provider-utils@3.0.0-beta.10 - -## 2.0.0-beta.12 - -### Patch Changes - -- f418dd7: Added anthropic provider defined tool support to amazon bedrock -- Updated dependencies [27deb4d] - - @ai-sdk/provider@2.0.0-beta.2 - - @ai-sdk/provider-utils@3.0.0-beta.9 - -## 2.0.0-beta.11 - -### Patch Changes - -- eb173f1: chore (providers): remove model shorthand deprecation warnings -- Updated dependencies [dd5fd43] - - @ai-sdk/provider-utils@3.0.0-beta.8 - -## 2.0.0-beta.10 - -### Patch Changes - -- 269683f: Add raw Anthropic usage information to provider metadata -- Updated dependencies [e7fcc86] - - @ai-sdk/provider-utils@3.0.0-beta.7 - -## 2.0.0-beta.9 - -### Patch Changes - -- 4f26d59: feat(provider/anthropic): add disable parallel tool use option -- a753b3a: feat (provider/anthropic): cache control for tools -- Updated dependencies [ac34802] - - @ai-sdk/provider-utils@3.0.0-beta.6 - -## 2.0.0-beta.8 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-beta.5 - -## 2.0.0-beta.7 - -### Patch Changes - -- 205077b: fix: improve Zod compatibility -- Updated dependencies [205077b] - - @ai-sdk/provider-utils@3.0.0-beta.4 - -## 2.0.0-beta.6 - -### Patch Changes - -- Updated dependencies [05d2819] - - @ai-sdk/provider-utils@3.0.0-beta.3 - -## 2.0.0-beta.5 - -### Patch Changes - -- b9ddcdd: feat(anthropic): add text_editor_20250429 tool for Claude 4 models - -## 2.0.0-beta.4 - -### Patch Changes - -- fdff8a4: fix(provider/anthropic): correct Claude 4 model ID format -- 84577c8: fix (providers/anthropic): remove fine grained tool streaming beta - -## 2.0.0-beta.3 - -### Patch Changes - -- a85c85f: fix (provider/anthropic): streaming json output -- d1a034f: feature: using Zod 4 for internal stuff -- 0b678b2: feat (provider/anthropic): enable streaming tool calls -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-beta.2 - -## 2.0.0-beta.2 - -### Patch Changes - -- d601ed9: fix (provider/anthropic): send tool call id in tool-input-start chunk - -## 2.0.0-beta.1 - -### Patch Changes - -- 8f2854f: feat (provider/anthropic): send web search tool calls -- 5d959e7: refactor: updated openai + anthropic tool use server side -- 9f73965: feat (provider/anthropic): parse websearch tool args -- 399e056: fix: anthropic computer tool -- Updated dependencies - - @ai-sdk/provider@2.0.0-beta.1 - - @ai-sdk/provider-utils@3.0.0-beta.1 - -## 2.0.0-alpha.15 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-alpha.15 - - @ai-sdk/provider-utils@3.0.0-alpha.15 - -## 2.0.0-alpha.14 - -### Patch Changes - -- 2e13791: feat(anthropic): add server-side web search support -- 6392f60: fix(anthropic): resolve web search API validation errors with partial location + provider output -- Updated dependencies - - @ai-sdk/provider@2.0.0-alpha.14 - - @ai-sdk/provider-utils@3.0.0-alpha.14 - -## 2.0.0-alpha.13 - -### Patch Changes - -- 8dfcb11: feat(anthropic/citation): text support for citations -- ee5a9c0: feat: streamText onChunk raw chunk support -- Updated dependencies [68ecf2f] - - @ai-sdk/provider@2.0.0-alpha.13 - - @ai-sdk/provider-utils@3.0.0-alpha.13 - -## 2.0.0-alpha.12 - -### Patch Changes - -- e2aceaf: feat: add raw chunk support -- Updated dependencies [e2aceaf] - - @ai-sdk/provider@2.0.0-alpha.12 - - @ai-sdk/provider-utils@3.0.0-alpha.12 - -## 2.0.0-alpha.11 - -### Patch Changes - -- 25f3454: feat(provider/anthropic): add PDF citation support with document sources for streamText -- Updated dependencies [c1e6647] - - @ai-sdk/provider@2.0.0-alpha.11 - - @ai-sdk/provider-utils@3.0.0-alpha.11 - -## 2.0.0-alpha.10 - -### Patch Changes - -- Updated dependencies [c4df419] - - @ai-sdk/provider@2.0.0-alpha.10 - - @ai-sdk/provider-utils@3.0.0-alpha.10 - -## 2.0.0-alpha.9 - -### Patch Changes - -- 362b048: add web search tool support -- Updated dependencies [811dff3] - - @ai-sdk/provider@2.0.0-alpha.9 - - @ai-sdk/provider-utils@3.0.0-alpha.9 - -## 2.0.0-alpha.8 - -### Patch Changes - -- ad66c0e: feat (provider/anthropic): json response schema support via tool calls -- 075711d: fix (provider/anthropic): return stop finish reason for json output with tool -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-alpha.8 - - @ai-sdk/provider@2.0.0-alpha.8 - -## 2.0.0-alpha.7 - -### Patch Changes - -- Updated dependencies [5c56081] - - @ai-sdk/provider@2.0.0-alpha.7 - - @ai-sdk/provider-utils@3.0.0-alpha.7 - -## 2.0.0-alpha.6 - -### Patch Changes - -- Updated dependencies [0d2c085] - - @ai-sdk/provider@2.0.0-alpha.6 - - @ai-sdk/provider-utils@3.0.0-alpha.6 - -## 2.0.0-alpha.4 - -### Patch Changes - -- ca8aac6: feat (providers/anthropic): add claude v4 models -- Updated dependencies [dc714f3] - - @ai-sdk/provider@2.0.0-alpha.4 - - @ai-sdk/provider-utils@3.0.0-alpha.4 - -## 2.0.0-alpha.3 - -### Patch Changes - -- Updated dependencies [6b98118] - - @ai-sdk/provider@2.0.0-alpha.3 - - @ai-sdk/provider-utils@3.0.0-alpha.3 - -## 2.0.0-alpha.2 - -### Patch Changes - -- Updated dependencies [26535e0] - - @ai-sdk/provider@2.0.0-alpha.2 - - @ai-sdk/provider-utils@3.0.0-alpha.2 - -## 2.0.0-alpha.1 - -### Patch Changes - -- Updated dependencies [3f2f00c] - - @ai-sdk/provider@2.0.0-alpha.1 - - @ai-sdk/provider-utils@3.0.0-alpha.1 - -## 2.0.0-canary.19 - -### Patch Changes - -- Updated dependencies [faf8446] - - @ai-sdk/provider-utils@3.0.0-canary.19 - -## 2.0.0-canary.18 - -### Patch Changes - -- Updated dependencies [40acf9b] - - @ai-sdk/provider-utils@3.0.0-canary.18 - -## 2.0.0-canary.17 - -### Patch Changes - -- Updated dependencies [ea7a7c9] - - @ai-sdk/provider-utils@3.0.0-canary.17 - -## 2.0.0-canary.16 - -### Patch Changes - -- Updated dependencies [87b828f] - - @ai-sdk/provider-utils@3.0.0-canary.16 - -## 2.0.0-canary.15 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.15 - - @ai-sdk/provider@2.0.0-canary.14 - -## 2.0.0-canary.14 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.14 - - @ai-sdk/provider@2.0.0-canary.13 - -## 2.0.0-canary.13 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.12 - - @ai-sdk/provider-utils@3.0.0-canary.13 - -## 2.0.0-canary.12 - -### Patch Changes - -- 5c9eec4: chore(providers/anthropic): switch to providerOptions -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.11 - - @ai-sdk/provider-utils@3.0.0-canary.12 - -## 2.0.0-canary.11 - -### Patch Changes - -- 66962ed: fix(packages): export node10 compatible types -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.11 - - @ai-sdk/provider@2.0.0-canary.10 - -## 2.0.0-canary.10 - -### Patch Changes - -- Updated dependencies [e86be6f] - - @ai-sdk/provider@2.0.0-canary.9 - - @ai-sdk/provider-utils@3.0.0-canary.10 - -## 2.0.0-canary.9 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.8 - - @ai-sdk/provider-utils@3.0.0-canary.9 - -## 2.0.0-canary.8 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.8 - - @ai-sdk/provider@2.0.0-canary.7 - -## 2.0.0-canary.7 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.6 - - @ai-sdk/provider-utils@3.0.0-canary.7 - -## 2.0.0-canary.6 - -### Patch Changes - -- f10304b: feat(tool-calling): don't require the user to have to pass parameters -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.5 - - @ai-sdk/provider-utils@3.0.0-canary.6 - -## 2.0.0-canary.5 - -### Patch Changes - -- Updated dependencies [6f6bb89] - - @ai-sdk/provider@2.0.0-canary.4 - - @ai-sdk/provider-utils@3.0.0-canary.5 - -## 2.0.0-canary.4 - -### Patch Changes - -- Updated dependencies [d1a1aa1] - - @ai-sdk/provider@2.0.0-canary.3 - - @ai-sdk/provider-utils@3.0.0-canary.4 - -## 2.0.0-canary.3 - -### Patch Changes - -- 61ab528: Add support for URL-based PDF documents in the Anthropic provider -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.3 - - @ai-sdk/provider@2.0.0-canary.2 - -## 2.0.0-canary.2 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.1 - - @ai-sdk/provider-utils@3.0.0-canary.2 - -## 2.0.0-canary.1 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.1 - -## 2.0.0-canary.0 - -### Major Changes - -- d5f588f: AI SDK 5 - -### Patch Changes - -- 91715e5: fix (provider/google-vertex): fix anthropic support for image urls in messages -- Updated dependencies [d5f588f] - - @ai-sdk/provider-utils@3.0.0-canary.0 - - @ai-sdk/provider@2.0.0-canary.0 - -## 1.2.4 - -### Patch Changes - -- Updated dependencies [28be004] - - @ai-sdk/provider-utils@2.2.3 - -## 1.2.3 - -### Patch Changes - -- Updated dependencies [b01120e] - - @ai-sdk/provider-utils@2.2.2 - -## 1.2.2 - -### Patch Changes - -- aeaa92b: feat (provider/anthropic): expose type for validating Anthropic responses provider options - -## 1.2.1 - -### Patch Changes - -- Updated dependencies [f10f0fa] - - @ai-sdk/provider-utils@2.2.1 - -## 1.2.0 - -### Minor Changes - -- 5bc638d: AI SDK 4.2 - -### Patch Changes - -- Updated dependencies [5bc638d] - - @ai-sdk/provider@1.1.0 - - @ai-sdk/provider-utils@2.2.0 - -## 1.1.19 - -### Patch Changes - -- Updated dependencies [d0c4659] - - @ai-sdk/provider-utils@2.1.15 - -## 1.1.18 - -### Patch Changes - -- Updated dependencies [0bd5bc6] - - @ai-sdk/provider@1.0.12 - - @ai-sdk/provider-utils@2.1.14 - -## 1.1.17 - -### Patch Changes - -- Updated dependencies [2e1101a] - - @ai-sdk/provider@1.0.11 - - @ai-sdk/provider-utils@2.1.13 - -## 1.1.16 - -### Patch Changes - -- Updated dependencies [1531959] - - @ai-sdk/provider-utils@2.1.12 - -## 1.1.15 - -### Patch Changes - -- e1d3d42: feat (ai): expose raw response body in generateText and generateObject -- Updated dependencies [e1d3d42] - - @ai-sdk/provider@1.0.10 - - @ai-sdk/provider-utils@2.1.11 - -## 1.1.14 - -### Patch Changes - -- 0e8b66c: feat (provider/anthropic): support image urls - -## 1.1.13 - -### Patch Changes - -- 3004b14: feat(provider/anthropic): add bash_20250124 and text_editor_20250124 tools - -## 1.1.12 - -### Patch Changes - -- b3e5a15: fix (provider/anthropic): add model setting to allow omitting reasoning content from model requests - -## 1.1.11 - -### Patch Changes - -- 00276ae: feat (provider/anthropic): update types for Anthropic computer_20250124 tool -- a4f8714: feat (provider/anthropic): update beta flag for sonnet-3-7 when using new computer-use tool - -## 1.1.10 - -### Patch Changes - -- ddf9740: feat (ai): add anthropic reasoning -- Updated dependencies [ddf9740] - - @ai-sdk/provider@1.0.9 - - @ai-sdk/provider-utils@2.1.10 - -## 1.1.9 - -### Patch Changes - -- Updated dependencies [2761f06] - - @ai-sdk/provider@1.0.8 - - @ai-sdk/provider-utils@2.1.9 - -## 1.1.8 - -### Patch Changes - -- Updated dependencies [2e898b4] - - @ai-sdk/provider-utils@2.1.8 - -## 1.1.7 - -### Patch Changes - -- Updated dependencies [3ff4ef8] - - @ai-sdk/provider-utils@2.1.7 - -## 1.1.6 - -### Patch Changes - -- Updated dependencies [d89c3b9] - - @ai-sdk/provider@1.0.7 - - @ai-sdk/provider-utils@2.1.6 - -## 1.1.5 - -### Patch Changes - -- Updated dependencies [3a602ca] - - @ai-sdk/provider-utils@2.1.5 - -## 1.1.4 - -### Patch Changes - -- Updated dependencies [066206e] - - @ai-sdk/provider-utils@2.1.4 - -## 1.1.3 - -### Patch Changes - -- Updated dependencies [39e5c1f] - - @ai-sdk/provider-utils@2.1.3 - -## 1.1.2 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@2.1.2 - - @ai-sdk/provider@1.0.6 - -## 1.1.1 - -### Patch Changes - -- 858f934: feat (provider/anthropic): default cache-control on and mark model setting deprecated -- b284e2c: feat (provider/google-vertex): support prompt caching for Anthropic Claude models -- Updated dependencies - - @ai-sdk/provider-utils@2.1.1 - - @ai-sdk/provider@1.0.5 - -## 1.1.0 - -### Minor Changes - -- 62ba5ad: release: AI SDK 4.1 - -### Patch Changes - -- Updated dependencies [62ba5ad] - - @ai-sdk/provider-utils@2.1.0 - -## 1.0.9 - -### Patch Changes - -- Updated dependencies [00114c5] - - @ai-sdk/provider-utils@2.0.8 - -## 1.0.8 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@2.0.7 - -## 1.0.7 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@1.0.4 - - @ai-sdk/provider-utils@2.0.6 - -## 1.0.6 - -### Patch Changes - -- 5ed5e45: chore (config): Use ts-library.json tsconfig for no-UI libs. -- Updated dependencies [5ed5e45] - - @ai-sdk/provider-utils@2.0.5 - - @ai-sdk/provider@1.0.3 - -## 1.0.5 - -### Patch Changes - -- Updated dependencies [09a9cab] - - @ai-sdk/provider@1.0.2 - - @ai-sdk/provider-utils@2.0.4 - -## 1.0.4 - -### Patch Changes - -- bcd892e: feat (provider/google-vertex): Add support for Anthropic models. - -## 1.0.3 - -### Patch Changes - -- Updated dependencies [0984f0b] - - @ai-sdk/provider-utils@2.0.3 - -## 1.0.2 - -### Patch Changes - -- Updated dependencies [b446ae5] - - @ai-sdk/provider@1.0.1 - - @ai-sdk/provider-utils@2.0.2 - -## 1.0.1 - -### Patch Changes - -- Updated dependencies [c3ab5de] - - @ai-sdk/provider-utils@2.0.1 - -## 1.0.0 - -### Major Changes - -- 66060f7: chore (release): bump major version to 4.0 -- 0d3d3f5: chore (providers): remove baseUrl option -- 8ad0504: chore (provider/anthropic): remove Anthropic facade -- 2f6e8c0: chore (provider/anthropic): remove topK model setting - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@2.0.0 - - @ai-sdk/provider@1.0.0 - -## 1.0.0-canary.4 - -### Major Changes - -- 2f6e8c0: chore (provider/anthropic): remove topK model setting - -## 1.0.0-canary.3 - -### Patch Changes - -- Updated dependencies [8426f55] - - @ai-sdk/provider-utils@2.0.0-canary.3 - -## 1.0.0-canary.2 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@2.0.0-canary.2 - -## 1.0.0-canary.1 - -### Major Changes - -- 0d3d3f5: chore (providers): remove baseUrl option -- 8ad0504: chore (provider/anthropic): remove Anthropic facade - -### Patch Changes - -- Updated dependencies [b1da952] - - @ai-sdk/provider-utils@2.0.0-canary.1 - -## 1.0.0-canary.0 - -### Major Changes - -- 66060f7: chore (release): bump major version to 4.0 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@2.0.0-canary.0 - - @ai-sdk/provider@1.0.0-canary.0 - -## 0.0.56 - -### Patch Changes - -- e6042b1: feat (provider/anthropic): add haiku 3.5 model ids - -## 0.0.55 - -### Patch Changes - -- ac380e3: fix (provider/anthropic): continuation mode with 3+ steps - -## 0.0.54 - -### Patch Changes - -- 4d2e53b: feat (provider/anthropic): pdf support -- c8afcb5: feat (provider/anthropic): allow using computer use and cache control at the same time - -## 0.0.53 - -### Patch Changes - -- 3b1b69a: feat (provider/anthropic): add computer use tools -- 3b1b69a: feat: provider-defined tools -- 8c222cd: feat (provider/anthropic): update model ids -- 811a317: feat (ai/core): multi-part tool results (incl. images) -- Updated dependencies - - @ai-sdk/provider-utils@1.0.22 - - @ai-sdk/provider@0.0.26 - -## 0.0.52 - -### Patch Changes - -- b9b0d7b: feat (ai): access raw request body -- Updated dependencies [b9b0d7b] - - @ai-sdk/provider@0.0.25 - - @ai-sdk/provider-utils@1.0.21 - -## 0.0.51 - -### Patch Changes - -- Updated dependencies [d595d0d] - - @ai-sdk/provider@0.0.24 - - @ai-sdk/provider-utils@1.0.20 - -## 0.0.50 - -### Patch Changes - -- Updated dependencies [273f696] - - @ai-sdk/provider-utils@1.0.19 - -## 0.0.49 - -### Patch Changes - -- 03313cd: feat (ai): expose response id, response model, response timestamp in telemetry and api -- 3be7c1c: fix (provider/anthropic): support prompt caching on assistant messages -- Updated dependencies - - @ai-sdk/provider-utils@1.0.18 - - @ai-sdk/provider@0.0.23 - -## 0.0.48 - -### Patch Changes - -- 26515cb: feat (ai/provider): introduce ProviderV1 specification -- Updated dependencies [26515cb] - - @ai-sdk/provider@0.0.22 - - @ai-sdk/provider-utils@1.0.17 - -## 0.0.47 - -### Patch Changes - -- Updated dependencies [09f895f] - - @ai-sdk/provider-utils@1.0.16 - -## 0.0.46 - -### Patch Changes - -- Updated dependencies [d67fa9c] - - @ai-sdk/provider-utils@1.0.15 - -## 0.0.45 - -### Patch Changes - -- 95a53a3: chore (provider/anthropic): remove tool calls beta header - -## 0.0.44 - -### Patch Changes - -- Updated dependencies [f2c025e] - - @ai-sdk/provider@0.0.21 - - @ai-sdk/provider-utils@1.0.14 - -## 0.0.43 - -### Patch Changes - -- 6ac355e: feat (provider/anthropic): add cache control support -- Updated dependencies [6ac355e] - - @ai-sdk/provider@0.0.20 - - @ai-sdk/provider-utils@1.0.13 - -## 0.0.42 - -### Patch Changes - -- dd712ac: fix: use FetchFunction type to prevent self-reference -- Updated dependencies [dd712ac] - - @ai-sdk/provider-utils@1.0.12 - -## 0.0.41 - -### Patch Changes - -- 89b18ca: fix (ai/provider): send finish reason 'unknown' by default -- Updated dependencies [dd4a0f5] - - @ai-sdk/provider@0.0.19 - - @ai-sdk/provider-utils@1.0.11 - -## 0.0.40 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@1.0.10 - - @ai-sdk/provider@0.0.18 - -## 0.0.39 - -### Patch Changes - -- Updated dependencies [029af4c] - - @ai-sdk/provider@0.0.17 - - @ai-sdk/provider-utils@1.0.9 - -## 0.0.38 - -### Patch Changes - -- Updated dependencies [d58517b] - - @ai-sdk/provider@0.0.16 - - @ai-sdk/provider-utils@1.0.8 - -## 0.0.37 - -### Patch Changes - -- Updated dependencies [96aed25] - - @ai-sdk/provider@0.0.15 - - @ai-sdk/provider-utils@1.0.7 - -## 0.0.36 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@1.0.6 - -## 0.0.35 - -### Patch Changes - -- fe2128f0: feat (provider/anthropic): combine sequential assistant messages into one - -## 0.0.34 - -### Patch Changes - -- 7d0fd5a8: fix (provider/anthropic): handle error stream chunks - -## 0.0.33 - -### Patch Changes - -- a8d1c9e9: feat (ai/core): parallel image download -- Updated dependencies [a8d1c9e9] - - @ai-sdk/provider-utils@1.0.5 - - @ai-sdk/provider@0.0.14 - -## 0.0.32 - -### Patch Changes - -- Updated dependencies [4f88248f] - - @ai-sdk/provider-utils@1.0.4 - -## 0.0.31 - -### Patch Changes - -- 2b9da0f0: feat (core): support stopSequences setting. -- a5b58845: feat (core): support topK setting -- 4aa8deb3: feat (provider): support responseFormat setting in provider api -- 13b27ec6: chore (ai/core): remove grammar mode -- Updated dependencies - - @ai-sdk/provider@0.0.13 - - @ai-sdk/provider-utils@1.0.3 - -## 0.0.30 - -### Patch Changes - -- 4c6b80f7: chore (provider/anthropic): improve object-tool mode - -## 0.0.29 - -### Patch Changes - -- Updated dependencies [b7290943] - - @ai-sdk/provider@0.0.12 - - @ai-sdk/provider-utils@1.0.2 - -## 0.0.28 - -### Patch Changes - -- Updated dependencies [d481729f] - - @ai-sdk/provider-utils@1.0.1 - -## 0.0.27 - -### Patch Changes - -- 7e86b45e: fix (provider/anthropic): automatically trim trailing whitespace on pre-filled assistant responses - -## 0.0.26 - -### Patch Changes - -- 5edc6110: feat (ai/core): add custom request header support -- Updated dependencies - - @ai-sdk/provider@0.0.11 - - @ai-sdk/provider-utils@1.0.0 - -## 0.0.25 - -### Patch Changes - -- 91dc4296: chore (@ai-sdk/anthropic): remove anthropic-beta header - -## 0.0.24 - -### Patch Changes - -- 04800838: fix (@ai-sdk/anthropic): combine tool and user messages, combine system messages - -## 0.0.23 - -### Patch Changes - -- Updated dependencies [02f6a088] - - @ai-sdk/provider-utils@0.0.16 - -## 0.0.22 - -### Patch Changes - -- 0a22b05b: feat (@ai-sdk/anthropic): add claude-3.5-sonnet model - -## 0.0.21 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@0.0.15 - -## 0.0.20 - -### Patch Changes - -- 4728c37f: feat (core): add text embedding model support to provider registry -- 7910ae84: feat (providers): support custom fetch implementations -- Updated dependencies [7910ae84] - - @ai-sdk/provider-utils@0.0.14 - -## 0.0.19 - -### Patch Changes - -- Updated dependencies [102ca22f] - - @ai-sdk/provider@0.0.10 - - @ai-sdk/provider-utils@0.0.13 - -## 0.0.18 - -### Patch Changes - -- 09295e2e: feat (@ai-sdk/anthropic): automatically download image URLs -- Updated dependencies - - @ai-sdk/provider@0.0.9 - - @ai-sdk/provider-utils@0.0.12 - -## 0.0.17 - -### Patch Changes - -- f39c0dd2: feat (provider): implement toolChoice support -- Updated dependencies [f39c0dd2] - - @ai-sdk/provider@0.0.8 - - @ai-sdk/provider-utils@0.0.11 - -## 0.0.16 - -### Patch Changes - -- 24683b72: fix (providers): Zod is required dependency -- Updated dependencies [8e780288] - - @ai-sdk/provider@0.0.7 - - @ai-sdk/provider-utils@0.0.10 - -## 0.0.15 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@0.0.6 - - @ai-sdk/provider-utils@0.0.9 - -## 0.0.14 - -### Patch Changes - -- 06e3934: feat (provider/anthropic): streaming tool calls - -## 0.0.13 - -### Patch Changes - -- Updated dependencies [0f6bc4e] - - @ai-sdk/provider@0.0.5 - - @ai-sdk/provider-utils@0.0.8 - -## 0.0.12 - -### Patch Changes - -- Updated dependencies [325ca55] - - @ai-sdk/provider@0.0.4 - - @ai-sdk/provider-utils@0.0.7 - -## 0.0.11 - -### Patch Changes - -- 5b01c13: feat (ai/core): add system message support in messages list - -## 0.0.10 - -### Patch Changes - -- Updated dependencies [276f22b] - - @ai-sdk/provider-utils@0.0.6 - -## 0.0.9 - -### Patch Changes - -- Updated dependencies [41d5736] - - @ai-sdk/provider@0.0.3 - - @ai-sdk/provider-utils@0.0.5 - -## 0.0.8 - -### Patch Changes - -- Updated dependencies [56ef84a] - - @ai-sdk/provider-utils@0.0.4 - -## 0.0.7 - -### Patch Changes - -- 25f3350: ai/core: add support for getting raw response headers. -- Updated dependencies - - @ai-sdk/provider@0.0.2 - - @ai-sdk/provider-utils@0.0.3 - -## 0.0.6 - -### Patch Changes - -- eb150a6: ai/core: remove scaling of setting values (breaking change). If you were using the temperature, frequency penalty, or presence penalty settings, you need to update the providers and adjust the setting values. -- Updated dependencies [eb150a6] - - @ai-sdk/provider-utils@0.0.2 - - @ai-sdk/provider@0.0.1 - -## 0.0.5 - -### Patch Changes - -- c6fc35b: Add custom header support. - -## 0.0.4 - -### Patch Changes - -- ab60b18: Simplified model construction by directly calling provider functions. Add create... functions to create provider instances. - -## 0.0.3 - -### Patch Changes - -- 587240b: Standardize providers to offer .chat() method - -## 0.0.2 - -### Patch Changes - -- 2bff460: Fix build for release. - -## 0.0.1 - -### Patch Changes - -- 7b8791d: Rename baseUrl to baseURL. Automatically remove trailing slashes. -- Updated dependencies [7b8791d] - - @ai-sdk/provider-utils@0.0.1 diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/LICENSE deleted file mode 100644 index 6c16c29f4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2023 Vercel, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/README.md deleted file mode 100644 index 3d25ab811..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# AI SDK - Anthropic Provider - -The **[Anthropic provider](https://ai-sdk.dev/providers/ai-sdk-providers/anthropic)** for the [AI SDK](https://ai-sdk.dev/docs) contains language model support for the [Anthropic Messages API](https://docs.anthropic.com/claude/reference/messages_post). - -## Setup - -The Anthropic provider is available in the `@ai-sdk/anthropic` module. You can install it with - -```bash -npm i @ai-sdk/anthropic -``` - -## Skill for Coding Agents - -If you use coding agents such as Claude Code or Cursor, we highly recommend adding the AI SDK skill to your repository: - -```shell -npx skills add vercel/ai -``` - -## Provider Instance - -You can import the default provider instance `anthropic` from `@ai-sdk/anthropic`: - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -``` - -## Example - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: anthropic('claude-3-haiku-20240307'), - prompt: 'Write a vegetarian lasagna recipe for 4 people.', -}); -``` - -## Documentation - -Please check out the **[Anthropic provider documentation](https://ai-sdk.dev/providers/ai-sdk-providers/anthropic)** for more information. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/docs/05-anthropic.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/docs/05-anthropic.mdx deleted file mode 100644 index bef2b7a3f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/docs/05-anthropic.mdx +++ /dev/null @@ -1,1368 +0,0 @@ ---- -title: Anthropic -description: Learn how to use the Anthropic provider for the AI SDK. ---- - -# Anthropic Provider - -The [Anthropic](https://www.anthropic.com/) provider contains language model support for the [Anthropic Messages API](https://docs.anthropic.com/claude/reference/messages_post). - -## Setup - -The Anthropic provider is available in the `@ai-sdk/anthropic` module. You can install it with - - - - - - - - - - - - - - - - - -## Provider Instance - -You can import the default provider instance `anthropic` from `@ai-sdk/anthropic`: - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -``` - -If you need a customized setup, you can import `createAnthropic` from `@ai-sdk/anthropic` and create a provider instance with your settings: - -```ts -import { createAnthropic } from '@ai-sdk/anthropic'; - -const anthropic = createAnthropic({ - // custom settings -}); -``` - -You can use the following optional settings to customize the Anthropic provider instance: - -- **baseURL** _string_ - - Use a different URL prefix for API calls, e.g. to use proxy servers. - The default prefix is `https://api.anthropic.com/v1`. - -- **apiKey** _string_ - - API key that is being sent using the `x-api-key` header. - It defaults to the `ANTHROPIC_API_KEY` environment variable. - Only one of `apiKey` or `authToken` is required. - -- **authToken** _string_ - - Auth token that is being sent using the `Authorization: Bearer` header. - It defaults to the `ANTHROPIC_AUTH_TOKEN` environment variable. - Only one of `apiKey` or `authToken` is required. - -- **headers** _Record<string,string>_ - - Custom headers to include in the requests. - -- **fetch** _(input: RequestInfo, init?: RequestInit) => Promise<Response>_ - - Custom [fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch) implementation. - Defaults to the global `fetch` function. - You can use it as a middleware to intercept requests, - or to provide a custom fetch implementation for e.g. testing. - -## Language Models - -You can create models that call the [Anthropic Messages API](https://docs.anthropic.com/claude/reference/messages_post) using the provider instance. -The first argument is the model id, e.g. `claude-3-haiku-20240307`. -Some models have multi-modal capabilities. - -```ts -const model = anthropic('claude-3-haiku-20240307'); -``` - -You can also use the following aliases for model creation: - -- `anthropic.languageModel('claude-3-haiku-20240307')` - Creates a language model -- `anthropic.chat('claude-3-haiku-20240307')` - Alias for `languageModel` -- `anthropic.messages('claude-3-haiku-20240307')` - Alias for `languageModel` - -You can use Anthropic language models to generate text with the `generateText` function: - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: anthropic('claude-3-haiku-20240307'), - prompt: 'Write a vegetarian lasagna recipe for 4 people.', -}); -``` - -Anthropic language models can also be used in the `streamText` function -and support structured data generation with [`Output`](/docs/reference/ai-sdk-core/output) -(see [AI SDK Core](/docs/ai-sdk-core)). - -The following optional provider options are available for Anthropic models: - -- `disableParallelToolUse` _boolean_ - - Optional. Disables the use of parallel tool calls. Defaults to `false`. - - When set to `true`, the model will only call one tool at a time instead of potentially calling multiple tools in parallel. - -- `sendReasoning` _boolean_ - - Optional. Include reasoning content in requests sent to the model. Defaults to `true`. - - If you are experiencing issues with the model handling requests involving - reasoning content, you can set this to `false` to omit them from the request. - -- `effort` _"high" | "medium" | "low"_ - - Optional. See [Effort section](#effort) for more details. - -- `speed` _"fast" | "standard"_ - - Optional. See [Fast Mode section](#fast-mode) for more details. - -- `thinking` _object_ - - Optional. See [Reasoning section](#reasoning) for more details. - -- `toolStreaming` _boolean_ - - Whether to enable tool streaming (and structured output streaming). Default to `true`. - -- `structuredOutputMode` _"outputFormat" | "jsonTool" | "auto"_ - - Determines how structured outputs are generated. Optional. - - - `"outputFormat"`: Use the `output_format` parameter to specify the structured output format. - - `"jsonTool"`: Use a special `"json"` tool to specify the structured output format. - - `"auto"`: Use `"outputFormat"` when supported, otherwise fall back to `"jsonTool"` (default). - -- `metadata` _object_ - - Optional. Metadata to include with the request. See the [Anthropic API documentation](https://platform.claude.com/docs/en/api/messages/create) for details. - - - `userId` _string_ - An external identifier for the end-user. Should be a UUID, hash, or other opaque identifier. Must not contain PII. - -### Structured Outputs and Tool Input Streaming - -Tool call streaming is enabled by default. You can opt out by setting the -`toolStreaming` provider option to `false`. - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -import { streamText, tool } from 'ai'; -import { z } from 'zod'; - -const result = streamText({ - model: anthropic('claude-sonnet-4-20250514'), - tools: { - writeFile: tool({ - description: 'Write content to a file', - inputSchema: z.object({ - path: z.string(), - content: z.string(), - }), - execute: async ({ path, content }) => { - // Implementation - return { success: true }; - }, - }), - }, - prompt: 'Write a short story to story.txt', -}); -``` - -### Effort - -Anthropic introduced an `effort` option with `claude-opus-4-5` that affects thinking, text responses, and function calls. Effort defaults to `high` and you can set it to `medium` or `low` to save tokens and to lower time-to-last-token latency (TTLT). - -```ts highlight="8-10" -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const { text, usage } = await generateText({ - model: anthropic('claude-opus-4-20250514'), - prompt: 'How many people will live in the world in 2040?', - providerOptions: { - anthropic: { - effort: 'low', - } satisfies AnthropicLanguageModelOptions, - }, -}); - -console.log(text); // resulting text -console.log(usage); // token usage -``` - -### Fast Mode - -Anthropic supports a [`speed` option](https://code.claude.com/docs/en/fast-mode) for `claude-opus-4-6` that enables faster inference with approximately 2.5x faster output token speeds. - -```ts highlight="8-10" -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: anthropic('claude-opus-4-6'), - prompt: 'Write a short poem about the sea.', - providerOptions: { - anthropic: { - speed: 'fast', - } satisfies AnthropicLanguageModelOptions, - }, -}); -``` - -The `speed` option accepts `'fast'` or `'standard'` (default behavior). - -### Reasoning - -Anthropic models support extended thinking, where Claude shows its reasoning process before providing a final answer. - -#### Adaptive Thinking - -For newer models (`claude-sonnet-4-6`, `claude-opus-4-6`, and later), use adaptive thinking. -Claude automatically determines how much reasoning to use based on the complexity of the prompt. - -```ts highlight="4,8-10" -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const { text, reasoningText, reasoning } = await generateText({ - model: anthropic('claude-opus-4-6'), - prompt: 'How many people will live in the world in 2040?', - providerOptions: { - anthropic: { - thinking: { type: 'adaptive' }, - } satisfies AnthropicLanguageModelOptions, - }, -}); - -console.log(reasoningText); // reasoning text -console.log(reasoning); // reasoning details including redacted reasoning -console.log(text); // text response -``` - -You can combine adaptive thinking with the `effort` option to control how much reasoning Claude uses: - -```ts highlight="6-8" -const { text } = await generateText({ - model: anthropic('claude-opus-4-6'), - prompt: 'Invent a new holiday and describe its traditions.', - providerOptions: { - anthropic: { - thinking: { type: 'adaptive' }, - effort: 'max', // 'low' | 'medium' | 'high' | 'max' - } satisfies AnthropicLanguageModelOptions, - }, -}); -``` - -#### Budget-Based Thinking - -For earlier models (`claude-opus-4-20250514`, `claude-sonnet-4-20250514`, `claude-sonnet-4-5-20250929`), -use `type: 'enabled'` with an explicit token budget: - -```ts highlight="4,8-10" -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const { text, reasoningText, reasoning } = await generateText({ - model: anthropic('claude-sonnet-4-5-20250929'), - prompt: 'How many people will live in the world in 2040?', - providerOptions: { - anthropic: { - thinking: { type: 'enabled', budgetTokens: 12000 }, - } satisfies AnthropicLanguageModelOptions, - }, -}); - -console.log(reasoningText); // reasoning text -console.log(reasoning); // reasoning details including redacted reasoning -console.log(text); // text response -``` - -See [AI SDK UI: Chatbot](/docs/ai-sdk-ui/chatbot#reasoning) for more details -on how to integrate reasoning into your chatbot. - -### Context Management - -Anthropic's Context Management feature allows you to automatically manage conversation context by clearing tool uses or thinking content when certain conditions are met. This helps optimize token usage and manage long conversations more efficiently. - -You can configure context management using the `contextManagement` provider option: - -```ts highlight="7-20" -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: anthropic('claude-sonnet-4-5-20250929'), - prompt: 'Continue our conversation...', - providerOptions: { - anthropic: { - contextManagement: { - edits: [ - { - type: 'clear_tool_uses_20250919', - trigger: { type: 'input_tokens', value: 10000 }, - keep: { type: 'tool_uses', value: 5 }, - clearAtLeast: { type: 'input_tokens', value: 1000 }, - clearToolInputs: true, - excludeTools: ['important_tool'], - }, - ], - }, - } satisfies AnthropicLanguageModelOptions, - }, -}); - -// Check what was cleared -console.log(result.providerMetadata?.anthropic?.contextManagement); -``` - -#### Context Editing - -Context editing strategies selectively remove specific content types from earlier in the conversation to reduce token usage without losing the overall conversation flow. - -##### Clear Tool Uses - -The `clear_tool_uses_20250919` edit type removes old tool call/result pairs from the conversation history: - -- **trigger** - Condition that triggers the clearing (e.g., `{ type: 'input_tokens', value: 10000 }` or `{ type: 'tool_uses', value: 10 }`) -- **keep** - How many recent tool uses to preserve (e.g., `{ type: 'tool_uses', value: 5 }`) -- **clearAtLeast** - Minimum amount to clear (e.g., `{ type: 'input_tokens', value: 1000 }`) -- **clearToolInputs** - Whether to clear tool input parameters (boolean) -- **excludeTools** - Array of tool names to never clear - -##### Clear Thinking - -The `clear_thinking_20251015` edit type removes thinking/reasoning blocks from earlier turns, keeping only the most recent ones: - -- **keep** - How many recent thinking turns to preserve (e.g., `{ type: 'thinking_turns', value: 2 }`) or `'all'` to keep everything - -```ts -const result = await generateText({ - model: anthropic('claude-opus-4-20250514'), - prompt: 'Continue reasoning...', - providerOptions: { - anthropic: { - thinking: { type: 'enabled', budgetTokens: 12000 }, - contextManagement: { - edits: [ - { - type: 'clear_thinking_20251015', - keep: { type: 'thinking_turns', value: 2 }, - }, - ], - }, - } satisfies AnthropicLanguageModelOptions, - }, -}); -``` - -#### Compaction - -The `compact_20260112` edit type automatically summarizes earlier conversation context when token limits are reached. This is useful for long-running conversations where you want to preserve the essence of earlier exchanges while staying within token limits. - -```ts highlight="7-19" -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { streamText } from 'ai'; - -const result = streamText({ - model: anthropic('claude-opus-4-6'), - messages: conversationHistory, - providerOptions: { - anthropic: { - contextManagement: { - edits: [ - { - type: 'compact_20260112', - trigger: { - type: 'input_tokens', - value: 50000, // trigger compaction when input exceeds 50k tokens - }, - instructions: - 'Summarize the conversation concisely, preserving key decisions and context.', - pauseAfterCompaction: false, - }, - ], - }, - } satisfies AnthropicLanguageModelOptions, - }, -}); -``` - -**Configuration:** - -- **trigger** - Condition that triggers compaction (e.g., `{ type: 'input_tokens', value: 50000 }`) -- **instructions** - Custom instructions for how the model should summarize the conversation. Use this to guide the compaction summary towards specific aspects of the conversation you want to preserve. -- **pauseAfterCompaction** - When `true`, the model will pause after generating the compaction summary, allowing you to inspect or process it before continuing. Defaults to `false`. - -When compaction occurs, the model generates a summary of the earlier context. This summary appears as a text block with special provider metadata. - -##### Detecting Compaction in Streams - -When using `streamText`, you can detect compaction summaries by checking the `providerMetadata` on `text-start` events: - -```ts -for await (const part of result.fullStream) { - switch (part.type) { - case 'text-start': { - const isCompaction = - part.providerMetadata?.anthropic?.type === 'compaction'; - if (isCompaction) { - console.log('[COMPACTION SUMMARY START]'); - } - break; - } - case 'text-delta': { - process.stdout.write(part.text); - break; - } - } -} -``` - -##### Compaction in UI Applications - -When using `useChat` or other UI hooks, compaction summaries appear as regular text parts with `providerMetadata`. You can style them differently in your UI: - -```tsx -{ - message.parts.map((part, index) => { - if (part.type === 'text') { - const isCompaction = - (part.providerMetadata?.anthropic as { type?: string } | undefined) - ?.type === 'compaction'; - - if (isCompaction) { - return ( -

- [Compaction Summary] -
{part.text}
-
- ); - } - return
{part.text}
; - } - }); -} -``` - -#### Applied Edits Metadata - -After generation, you can check which edits were applied in the provider metadata: - -```ts -const metadata = result.providerMetadata?.anthropic?.contextManagement; - -if (metadata?.appliedEdits) { - metadata.appliedEdits.forEach(edit => { - if (edit.type === 'clear_tool_uses_20250919') { - console.log(`Cleared ${edit.clearedToolUses} tool uses`); - console.log(`Freed ${edit.clearedInputTokens} tokens`); - } else if (edit.type === 'clear_thinking_20251015') { - console.log(`Cleared ${edit.clearedThinkingTurns} thinking turns`); - console.log(`Freed ${edit.clearedInputTokens} tokens`); - } else if (edit.type === 'compact_20260112') { - console.log('Compaction was applied'); - } - }); -} -``` - -For more details, see [Anthropic's Context Management documentation](https://docs.anthropic.com/en/docs/build-with-claude/context-management). - -### Cache Control - -In the messages and message parts, you can use the `providerOptions` property to set cache control breakpoints. -You need to set the `anthropic` property in the `providerOptions` object to `{ cacheControl: { type: 'ephemeral' } }` to set a cache control breakpoint. - -The cache creation input tokens are then returned in the `providerMetadata` object -for `generateText`, again under the `anthropic` property. -When you use `streamText`, the response contains a promise -that resolves to the metadata. Alternatively you can receive it in the -`onFinish` callback. - -```ts highlight="8,18-20,29-30" -import { anthropic } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const errorMessage = '... long error message ...'; - -const result = await generateText({ - model: anthropic('claude-sonnet-4-5'), - messages: [ - { - role: 'user', - content: [ - { type: 'text', text: 'You are a JavaScript expert.' }, - { - type: 'text', - text: `Error message: ${errorMessage}`, - providerOptions: { - anthropic: { cacheControl: { type: 'ephemeral' } }, - }, - }, - { type: 'text', text: 'Explain the error message.' }, - ], - }, - ], -}); - -console.log(result.text); -console.log(result.providerMetadata?.anthropic); -// e.g. { cacheCreationInputTokens: 2118 } -``` - -You can also use cache control on system messages by providing multiple system messages at the head of your messages array: - -```ts highlight="3,7-9" -const result = await generateText({ - model: anthropic('claude-sonnet-4-5'), - messages: [ - { - role: 'system', - content: 'Cached system message part', - providerOptions: { - anthropic: { cacheControl: { type: 'ephemeral' } }, - }, - }, - { - role: 'system', - content: 'Uncached system message part', - }, - { - role: 'user', - content: 'User prompt', - }, - ], -}); -``` - -Cache control for tools: - -```ts -const result = await generateText({ - model: anthropic('claude-haiku-4-5'), - tools: { - cityAttractions: tool({ - inputSchema: z.object({ city: z.string() }), - providerOptions: { - anthropic: { - cacheControl: { type: 'ephemeral' }, - }, - }, - }), - }, - messages: [ - { - role: 'user', - content: 'User prompt', - }, - ], -}); -``` - -#### Longer cache TTL - -Anthropic also supports a longer 1-hour cache duration. - -Here's an example: - -```ts -const result = await generateText({ - model: anthropic('claude-haiku-4-5'), - messages: [ - { - role: 'user', - content: [ - { - type: 'text', - text: 'Long cached message', - providerOptions: { - anthropic: { - cacheControl: { type: 'ephemeral', ttl: '1h' }, - }, - }, - }, - ], - }, - ], -}); -``` - -#### Limitations - -The minimum cacheable prompt length is: - -- 4096 tokens for Claude Opus 4.5 -- 1024 tokens for Claude Opus 4.1, Claude Opus 4, Claude Sonnet 4.5, Claude Sonnet 4, Claude Sonnet 3.7, and Claude Opus 3 -- 4096 tokens for Claude Haiku 4.5 -- 2048 tokens for Claude Haiku 3.5 and Claude Haiku 3 - -Shorter prompts cannot be cached, even if marked with `cacheControl`. Any requests to cache fewer than this number of tokens will be processed without caching. - -For more on prompt caching with Anthropic, see [Anthropic's Cache Control documentation](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching). - - - Because the `UIMessage` type (used by AI SDK UI hooks like `useChat`) does not - support the `providerOptions` property, you can use `convertToModelMessages` - first before passing the messages to functions like `generateText` or - `streamText`. For more details on `providerOptions` usage, see - [here](/docs/foundations/prompts#provider-options). - - -### Bash Tool - -The Bash Tool allows running bash commands. Here's how to create and use it: - -```ts -const bashTool = anthropic.tools.bash_20250124({ - execute: async ({ command, restart }) => { - // Implement your bash command execution logic here - // Return the result of the command execution - }, -}); -``` - -Parameters: - -- `command` (string): The bash command to run. Required unless the tool is being restarted. -- `restart` (boolean, optional): Specifying true will restart this tool. - - - Two versions are available: `bash_20250124` (recommended) and `bash_20241022`. - Only certain Claude versions are supported. - - -### Memory Tool - -The [Memory Tool](https://docs.claude.com/en/docs/agents-and-tools/tool-use/memory-tool) allows Claude to use a local memory, e.g. in the filesystem. -Here's how to create it: - -```ts -const memory = anthropic.tools.memory_20250818({ - execute: async action => { - // Implement your memory command execution logic here - // Return the result of the command execution - }, -}); -``` - -Only certain Claude versions are supported. - -### Text Editor Tool - -The Text Editor Tool provides functionality for viewing and editing text files. - -```ts -const tools = { - str_replace_based_edit_tool: anthropic.tools.textEditor_20250728({ - maxCharacters: 10000, // optional - async execute({ command, path, old_str, new_str, insert_text }) { - // ... - }, - }), -} satisfies ToolSet; -``` - - - Different models support different versions of the tool: - -- `textEditor_20250728` - For Claude Sonnet 4, Opus 4, and Opus 4.1 (recommended) -- `textEditor_20250124` - For Claude Sonnet 3.7 -- `textEditor_20241022` - For Claude Sonnet 3.5 - -Note: `textEditor_20250429` is deprecated. Use `textEditor_20250728` instead. - - - -Parameters: - -- `command` ('view' | 'create' | 'str_replace' | 'insert' | 'undo_edit'): The command to run. Note: `undo_edit` is only available in Claude 3.5 Sonnet and earlier models. -- `path` (string): Absolute path to file or directory, e.g. `/repo/file.py` or `/repo`. -- `file_text` (string, optional): Required for `create` command, with the content of the file to be created. -- `insert_line` (number, optional): Required for `insert` command. The line number after which to insert the new string. -- `new_str` (string, optional): New string for `str_replace` command. -- `insert_text` (string, optional): Required for `insert` command, containing the text to insert. -- `old_str` (string, optional): Required for `str_replace` command, containing the string to replace. -- `view_range` (number[], optional): Optional for `view` command to specify line range to show. - -### Computer Tool - -The Computer Tool enables control of keyboard and mouse actions on a computer: - -```ts -const computerTool = anthropic.tools.computer_20251124({ - displayWidthPx: 1920, - displayHeightPx: 1080, - displayNumber: 0, // Optional, for X11 environments - enableZoom: true, // Optional, enables the zoom action - - execute: async ({ action, coordinate, text, region }) => { - // Implement your computer control logic here - // Return the result of the action - - // Example code: - switch (action) { - case 'screenshot': { - // multipart result: - return { - type: 'image', - data: fs - .readFileSync('./data/screenshot-editor.png') - .toString('base64'), - }; - } - case 'zoom': { - // region is [x1, y1, x2, y2] defining the area to zoom into - return { - type: 'image', - data: fs.readFileSync('./data/zoomed-region.png').toString('base64'), - }; - } - default: { - console.log('Action:', action); - console.log('Coordinate:', coordinate); - console.log('Text:', text); - return `executed ${action}`; - } - } - }, - - // map to tool result content for LLM consumption: - toModelOutput({ output }) { - return typeof output === 'string' - ? [{ type: 'text', text: output }] - : [{ type: 'image', data: output.data, mediaType: 'image/png' }]; - }, -}); -``` - - - Use `computer_20251124` for Claude Opus 4.5 which supports the zoom action. - Use `computer_20250124` for Claude Sonnet 4.5, Haiku 4.5, Opus 4.1, Sonnet 4, - Opus 4, and Sonnet 3.7. - - -Parameters: - -- `action` ('key' | 'type' | 'mouse_move' | 'left_click' | 'left_click_drag' | 'right_click' | 'middle_click' | 'double_click' | 'screenshot' | 'cursor_position' | 'zoom'): The action to perform. The `zoom` action is only available with `computer_20251124`. -- `coordinate` (number[], optional): Required for `mouse_move` and `left_click_drag` actions. Specifies the (x, y) coordinates. -- `text` (string, optional): Required for `type` and `key` actions. -- `region` (number[], optional): Required for `zoom` action. Specifies `[x1, y1, x2, y2]` coordinates for the area to inspect. -- `displayWidthPx` (number): The width of the display in pixels. -- `displayHeightPx` (number): The height of the display in pixels. -- `displayNumber` (number, optional): The display number for X11 environments. -- `enableZoom` (boolean, optional): Enable the zoom action. Only available with `computer_20251124`. Default: `false`. - -### Web Search Tool - -Anthropic provides a provider-defined web search tool that gives Claude direct access to real-time web content, allowing it to answer questions with up-to-date information beyond its knowledge cutoff. - -You can enable web search using the provider-defined web search tool: - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const webSearchTool = anthropic.tools.webSearch_20250305({ - maxUses: 5, -}); - -const result = await generateText({ - model: anthropic('claude-opus-4-20250514'), - prompt: 'What are the latest developments in AI?', - tools: { - web_search: webSearchTool, - }, -}); -``` - - - Web search must be enabled in your organization's [Console - settings](https://console.anthropic.com/settings/privacy). - - -#### Configuration Options - -The web search tool supports several configuration options: - -- **maxUses** _number_ - - Maximum number of web searches Claude can perform during the conversation. - -- **allowedDomains** _string[]_ - - Optional list of domains that Claude is allowed to search. If provided, searches will be restricted to these domains. - -- **blockedDomains** _string[]_ - - Optional list of domains that Claude should avoid when searching. - -- **userLocation** _object_ - - Optional user location information to provide geographically relevant search results. - -```ts -const webSearchTool = anthropic.tools.webSearch_20250305({ - maxUses: 3, - allowedDomains: ['techcrunch.com', 'wired.com'], - blockedDomains: ['example-spam-site.com'], - userLocation: { - type: 'approximate', - country: 'US', - region: 'California', - city: 'San Francisco', - timezone: 'America/Los_Angeles', - }, -}); - -const result = await generateText({ - model: anthropic('claude-opus-4-20250514'), - prompt: 'Find local news about technology', - tools: { - web_search: webSearchTool, - }, -}); -``` - -### Web Fetch Tool - -Anthropic provides a provider-defined web fetch tool that allows Claude to retrieve content from specific URLs. This is useful when you want Claude to analyze or reference content from a particular webpage or document. - -You can enable web fetch using the provider-defined web fetch tool: - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: anthropic('claude-sonnet-4-0'), - prompt: - 'What is this page about? https://en.wikipedia.org/wiki/Maglemosian_culture', - tools: { - web_fetch: anthropic.tools.webFetch_20250910({ maxUses: 1 }), - }, -}); -``` - -### Tool Search - -Anthropic provides provider-defined tool search tools that enable Claude to work with hundreds or thousands of tools by dynamically discovering and loading them on-demand. Instead of loading all tool definitions into the context window upfront, Claude searches your tool catalog and loads only the tools it needs. - -There are two variants: - -- **BM25 Search** - Uses natural language queries to find tools -- **Regex Search** - Uses regex patterns (Python `re.search()` syntax) to find tools - -#### Basic Usage - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -import { generateText, tool } from 'ai'; -import { z } from 'zod'; - -const result = await generateText({ - model: anthropic('claude-sonnet-4-5'), - prompt: 'What is the weather in San Francisco?', - tools: { - toolSearch: anthropic.tools.toolSearchBm25_20251119(), - - get_weather: tool({ - description: 'Get the current weather at a specific location', - inputSchema: z.object({ - location: z.string().describe('The city and state'), - }), - execute: async ({ location }) => ({ - location, - temperature: 72, - condition: 'Sunny', - }), - // Defer tool here - Claude discovers these via the tool search tool - providerOptions: { - anthropic: { deferLoading: true }, - }, - }), - }, -}); -``` - -#### Using Regex Search - -For more precise tool matching, you can use the regex variant: - -```ts -const result = await generateText({ - model: anthropic('claude-sonnet-4-5'), - prompt: 'Get the weather data', - tools: { - toolSearch: anthropic.tools.toolSearchRegex_20251119(), - // ... deferred tools - }, -}); -``` - -Claude will construct regex patterns like `weather|temperature|forecast` to find matching tools. - -#### Custom Tool Search - -You can implement your own tool search logic (e.g., using embeddings or semantic search) by returning `tool-reference` content blocks via `toModelOutput`: - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -import { generateText, tool } from 'ai'; -import { z } from 'zod'; - -const result = await generateText({ - model: anthropic('claude-sonnet-4-5'), - prompt: 'What is the weather in San Francisco?', - tools: { - // Custom search tool - searchTools: tool({ - description: 'Search for tools by keyword', - inputSchema: z.object({ query: z.string() }), - execute: async ({ query }) => { - // Your custom search logic (embeddings, fuzzy match, etc.) - const allTools = ['get_weather', 'get_forecast', 'get_temperature']; - return allTools.filter(name => name.includes(query.toLowerCase())); - }, - toModelOutput: ({ output }) => ({ - type: 'content', - value: (output as string[]).map(toolName => ({ - type: 'custom' as const, - providerOptions: { - anthropic: { - type: 'tool-reference', - toolName, - }, - }, - })), - }), - }), - - // Deferred tools - get_weather: tool({ - description: 'Get the current weather', - inputSchema: z.object({ location: z.string() }), - execute: async ({ location }) => ({ location, temperature: 72 }), - providerOptions: { - anthropic: { deferLoading: true }, - }, - }), - }, -}); -``` - -This sends `tool_reference` blocks to Anthropic, which loads the corresponding deferred tool schemas into Claude's context. - -### MCP Connectors - -Anthropic supports connecting to [MCP servers](https://docs.claude.com/en/docs/agents-and-tools/mcp-connector) as part of their execution. - -You can enable this feature with the `mcpServers` provider option: - -```ts -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: anthropic('claude-sonnet-4-5'), - prompt: `Call the echo tool with "hello world". what does it respond with back?`, - providerOptions: { - anthropic: { - mcpServers: [ - { - type: 'url', - name: 'echo', - url: 'https://echo.mcp.inevitable.fyi/mcp', - // optional: authorization token - authorizationToken: mcpAuthToken, - // optional: tool configuration - toolConfiguration: { - enabled: true, - allowedTools: ['echo'], - }, - }, - ], - } satisfies AnthropicLanguageModelOptions, - }, -}); -``` - -The tool calls and results are dynamic, i.e. the input and output schemas are not known. - -#### Configuration Options - -The web fetch tool supports several configuration options: - -- **maxUses** _number_ - - The maxUses parameter limits the number of web fetches performed. - -- **allowedDomains** _string[]_ - - Only fetch from these domains. - -- **blockedDomains** _string[]_ - - Never fetch from these domains. - -- **citations** _object_ - - Unlike web search where citations are always enabled, citations are optional for web fetch. Set `"citations": {"enabled": true}` to enable Claude to cite specific passages from fetched documents. - -- **maxContentTokens** _number_ - - The maxContentTokens parameter limits the amount of content that will be included in the context. - -#### Error Handling - -Web search errors are handled differently depending on whether you're using streaming or non-streaming: - -**Non-streaming (`generateText`):** -Web search errors throw exceptions that you can catch: - -```ts -try { - const result = await generateText({ - model: anthropic('claude-opus-4-20250514'), - prompt: 'Search for something', - tools: { - web_search: webSearchTool, - }, - }); -} catch (error) { - if (error.message.includes('Web search failed')) { - console.log('Search error:', error.message); - // Handle search error appropriately - } -} -``` - -**Streaming (`streamText`):** -Web search errors are delivered as error parts in the stream: - -```ts -const result = await streamText({ - model: anthropic('claude-opus-4-20250514'), - prompt: 'Search for something', - tools: { - web_search: webSearchTool, - }, -}); - -for await (const part of result.textStream) { - if (part.type === 'error') { - console.log('Search error:', part.error); - // Handle search error appropriately - } -} -``` - -## Code Execution - -Anthropic provides a provider-defined code execution tool that gives Claude direct access to a real Python environment allowing it to execute code to inform its responses. - -You can enable code execution using the provider-defined code execution tool: - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const codeExecutionTool = anthropic.tools.codeExecution_20260120(); - -const result = await generateText({ - model: anthropic('claude-opus-4-20250514'), - prompt: - 'Calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]', - tools: { - code_execution: codeExecutionTool, - }, -}); -``` - - - Three versions are available: `codeExecution_20260120` (recommended, does not - require a beta header, supports Claude Opus 4.6, Sonnet 4.6, Sonnet 4.5, and - Opus 4.5), `codeExecution_20250825` (supports Python and Bash with enhanced - file operations), and `codeExecution_20250522` (supports Bash only). - - -#### Error Handling - -Code execution errors are handled differently depending on whether you're using streaming or non-streaming: - -**Non-streaming (`generateText`):** -Code execution errors are delivered as tool result parts in the response: - -```ts -const result = await generateText({ - model: anthropic('claude-opus-4-20250514'), - prompt: 'Execute some Python script', - tools: { - code_execution: codeExecutionTool, - }, -}); - -const toolErrors = result.content?.filter( - content => content.type === 'tool-error', -); - -toolErrors?.forEach(error => { - console.error('Tool execution error:', { - toolName: error.toolName, - toolCallId: error.toolCallId, - error: error.error, - }); -}); -``` - -**Streaming (`streamText`):** -Code execution errors are delivered as error parts in the stream: - -```ts -const result = await streamText({ - model: anthropic('claude-opus-4-20250514'), - prompt: 'Execute some Python script', - tools: { - code_execution: codeExecutionTool, - }, -}); -for await (const part of result.textStream) { - if (part.type === 'error') { - console.log('Code execution error:', part.error); - // Handle code execution error appropriately - } -} -``` - -### Programmatic Tool Calling - -[Programmatic Tool Calling](https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/programmatic-tool-calling) allows Claude to write code that calls your tools programmatically within a code execution container, rather than requiring round trips through the model for each tool invocation. This reduces latency for multi-tool workflows and decreases token consumption. - -To enable programmatic tool calling, use the `allowedCallers` provider option on tools that you want to be callable from within code execution: - -```ts highlight="13-17" -import { - anthropic, - forwardAnthropicContainerIdFromLastStep, -} from '@ai-sdk/anthropic'; -import { generateText, tool, stepCountIs } from 'ai'; -import { z } from 'zod'; - -const result = await generateText({ - model: anthropic('claude-sonnet-4-5'), - stopWhen: stepCountIs(10), - prompt: - 'Get the weather for Tokyo, Sydney, and London, then calculate the average temperature.', - tools: { - code_execution: anthropic.tools.codeExecution_20260120(), - - getWeather: tool({ - description: 'Get current weather data for a city.', - inputSchema: z.object({ - city: z.string().describe('Name of the city'), - }), - execute: async ({ city }) => { - // Your weather API implementation - return { temp: 22, condition: 'Sunny' }; - }, - // Enable this tool to be called from within code execution - providerOptions: { - anthropic: { - allowedCallers: ['code_execution_20260120'], - }, - }, - }), - }, - - // Propagate container ID between steps for code execution continuity - prepareStep: forwardAnthropicContainerIdFromLastStep, -}); -``` - -In this flow: - -1. Claude writes Python code that calls your `getWeather` tool multiple times in parallel -2. The SDK automatically executes your tool and returns results to the code execution container -3. Claude processes the results in code and generates the final response - - - Programmatic tool calling requires `claude-sonnet-4-6`, `claude-sonnet-4-5`, - `claude-opus-4-6`, or `claude-opus-4-5` models and uses the - `code_execution_20260120` or `code_execution_20250825` tool. - - -#### Container Persistence - -When using programmatic tool calling across multiple steps, you need to preserve the container ID between steps using `prepareStep`. You can use the `forwardAnthropicContainerIdFromLastStep` helper function to do this automatically. The container ID is available in `providerMetadata.anthropic.container.id` after each step completes. - -## Agent Skills - -[Anthropic Agent Skills](https://docs.claude.com/en/docs/agents-and-tools/agent-skills/overview) enable Claude to perform specialized tasks like document processing (PPTX, DOCX, PDF, XLSX) and data analysis. Skills run in a sandboxed container and require the code execution tool to be enabled. - -### Using Built-in Skills - -Anthropic provides several built-in skills: - -- **pptx** - Create and edit PowerPoint presentations -- **docx** - Create and edit Word documents -- **pdf** - Process and analyze PDF files -- **xlsx** - Work with Excel spreadsheets - -To use skills, you need to: - -1. Enable the code execution tool -2. Specify the container with skills in `providerOptions` - -```ts highlight="4,9-17,19-23" -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: anthropic('claude-sonnet-4-5'), - tools: { - code_execution: anthropic.tools.codeExecution_20260120(), - }, - prompt: 'Create a presentation about renewable energy with 5 slides', - providerOptions: { - anthropic: { - container: { - skills: [ - { - type: 'anthropic', - skillId: 'pptx', - version: 'latest', // optional - }, - ], - }, - } satisfies AnthropicLanguageModelOptions, - }, -}); -``` - -### Custom Skills - -You can also use custom skills by specifying `type: 'custom'`: - -```ts highlight="9-11" -const result = await generateText({ - model: anthropic('claude-sonnet-4-5'), - tools: { - code_execution: anthropic.tools.codeExecution_20260120(), - }, - prompt: 'Use my custom skill to process this data', - providerOptions: { - anthropic: { - container: { - skills: [ - { - type: 'custom', - skillId: 'my-custom-skill-id', - version: '1.0', // optional - }, - ], - }, - } satisfies AnthropicLanguageModelOptions, - }, -}); -``` - - - Skills use progressive context loading and execute within a sandboxed - container with code execution capabilities. - - -### PDF support - -Anthropic Claude models support reading PDF files. -You can pass PDF files as part of the message content using the `file` type: - -Option 1: URL-based PDF document - -```ts -const result = await generateText({ - model: anthropic('claude-sonnet-4-5'), - messages: [ - { - role: 'user', - content: [ - { - type: 'text', - text: 'What is an embedding model according to this document?', - }, - { - type: 'file', - data: new URL( - 'https://github.com/vercel/ai/blob/main/examples/ai-functions/data/ai.pdf?raw=true', - ), - mimeType: 'application/pdf', - }, - ], - }, - ], -}); -``` - -Option 2: Base64-encoded PDF document - -```ts -const result = await generateText({ - model: anthropic('claude-sonnet-4-5'), - messages: [ - { - role: 'user', - content: [ - { - type: 'text', - text: 'What is an embedding model according to this document?', - }, - { - type: 'file', - data: fs.readFileSync('./data/ai.pdf'), - mediaType: 'application/pdf', - }, - ], - }, - ], -}); -``` - -The model will have access to the contents of the PDF file and -respond to questions about it. -The PDF file should be passed using the `data` field, -and the `mediaType` should be set to `'application/pdf'`. - -### Model Capabilities - -| Model | Image Input | Object Generation | Tool Usage | Computer Use | Web Search | Tool Search | Compaction | -| ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | -| `claude-opus-4-6` | | | | | | | | -| `claude-sonnet-4-6` | | | | | | | | -| `claude-opus-4-5` | | | | | | | | -| `claude-haiku-4-5` | | | | | | | | -| `claude-sonnet-4-5` | | | | | | | | -| `claude-opus-4-1` | | | | | | | | -| `claude-opus-4-0` | | | | | | | | -| `claude-sonnet-4-0` | | | | | | | | - - - The table above lists popular models. Please see the [Anthropic - docs](https://docs.anthropic.com/en/docs/about-claude/models) for a full list - of available models. The table above lists popular models. You can also pass - any available provider model ID as a string if needed. - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/internal.d.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/internal.d.ts deleted file mode 100644 index be034cd88..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/internal.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/internal'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/package.json deleted file mode 100644 index 19c717b55..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/package.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "@ai-sdk/anthropic", - "version": "3.0.64", - "license": "Apache-2.0", - "sideEffects": false, - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", - "files": [ - "dist/**/*", - "docs/**/*", - "src", - "!src/**/*.test.ts", - "!src/**/*.test-d.ts", - "!src/**/__snapshots__", - "!src/**/__fixtures__", - "CHANGELOG.md", - "README.md", - "internal.d.ts" - ], - "directories": { - "doc": "./docs" - }, - "exports": { - "./package.json": "./package.json", - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" - }, - "./internal": { - "types": "./dist/internal/index.d.ts", - "import": "./dist/internal/index.mjs", - "module": "./dist/internal/index.mjs", - "require": "./dist/internal/index.js" - } - }, - "dependencies": { - "@ai-sdk/provider": "3.0.8", - "@ai-sdk/provider-utils": "4.0.21" - }, - "devDependencies": { - "@types/node": "20.17.24", - "tsup": "^8", - "typescript": "5.8.3", - "zod": "3.25.76", - "@ai-sdk/test-server": "1.0.3", - "@vercel/ai-tsconfig": "0.0.0" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public" - }, - "homepage": "https://ai-sdk.dev/docs", - "repository": { - "type": "git", - "url": "git+https://github.com/vercel/ai.git" - }, - "bugs": { - "url": "https://github.com/vercel/ai/issues" - }, - "keywords": [ - "ai" - ], - "scripts": { - "build": "pnpm clean && tsup --tsconfig tsconfig.build.json", - "build:watch": "pnpm clean && tsup --watch --tsconfig tsconfig.build.json", - "clean": "del-cli dist docs *.tsbuildinfo", - "type-check": "tsc --build", - "test": "pnpm test:node && pnpm test:edge", - "test:update": "pnpm test:node -u", - "test:watch": "vitest --config vitest.node.config.js", - "test:edge": "vitest --config vitest.edge.config.js --run", - "test:node": "vitest --config vitest.node.config.js --run" - } -} \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-error.ts deleted file mode 100644 index e44740c2a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-error.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { - createJsonErrorResponseHandler, - InferSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const anthropicErrorDataSchema = lazySchema(() => - zodSchema( - z.object({ - type: z.literal('error'), - error: z.object({ - type: z.string(), - message: z.string(), - }), - }), - ), -); - -export type AnthropicErrorData = InferSchema; - -export const anthropicFailedResponseHandler = createJsonErrorResponseHandler({ - errorSchema: anthropicErrorDataSchema, - errorToMessage: data => data.error.message, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-message-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-message-metadata.ts deleted file mode 100644 index d58b08c5c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-message-metadata.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { JSONObject } from '@ai-sdk/provider'; - -/** - * Represents a single iteration in the usage breakdown. - * When compaction occurs, the API returns an iterations array showing - * usage for each sampling iteration (compaction + message). - */ -export interface AnthropicUsageIteration { - type: 'compaction' | 'message'; - - /** - * Number of input tokens consumed in this iteration. - */ - inputTokens: number; - - /** - * Number of output tokens generated in this iteration. - */ - outputTokens: number; -} - -export interface AnthropicMessageMetadata { - usage: JSONObject; - // TODO remove cacheCreationInputTokens in AI SDK 6 - // (use value in usage object instead) - cacheCreationInputTokens: number | null; - stopSequence: string | null; - - /** - * Usage breakdown by iteration when compaction is triggered. - * - * When compaction occurs, this array contains usage for each sampling iteration. - * The first iteration is typically the compaction step, followed by the main - * message iteration. - */ - iterations: AnthropicUsageIteration[] | null; - - /** - * Information about the container used in this request. - * - * This will be non-null if a container tool (e.g., code execution) was used. - * Information about the container used in the request (for the code execution tool). - */ - container: { - /** - * The time at which the container will expire (RFC3339 timestamp). - */ - expiresAt: string; - - /** - * Identifier for the container used in this request. - */ - id: string; - - /** - * Skills loaded in the container. - */ - skills: Array<{ - /** - * Type of skill: either 'anthropic' (built-in) or 'custom' (user-defined). - */ - type: 'anthropic' | 'custom'; - - /** - * Skill ID (1-64 characters). - */ - skillId: string; - - /** - * Skill version or 'latest' for most recent version (1-64 characters). - */ - version: string; - }> | null; - } | null; - - /** - * Context management response. - * - * Information about context management strategies applied during the request. - */ - contextManagement: { - /** - * List of context management edits that were applied. - * Each item in the array is a specific type of context management edit. - */ - appliedEdits: Array< - /** - * Represents an edit where a certain number of tool uses and input tokens were cleared. - */ - | { - /** - * The type of context management edit applied. - * Possible value: 'clear_tool_uses_20250919' - */ - type: 'clear_tool_uses_20250919'; - - /** - * Number of tool uses that were cleared by this edit. - * Minimum: 0 - */ - clearedToolUses: number; - - /** - * Number of input tokens cleared by this edit. - * Minimum: 0 - */ - clearedInputTokens: number; - } - /** - * Represents an edit where a certain number of thinking turns and input tokens were cleared. - */ - | { - /** - * The type of context management edit applied. - * Possible value: 'clear_thinking_20251015' - */ - type: 'clear_thinking_20251015'; - - /** - * Number of thinking turns that were cleared by this edit. - * Minimum: 0 - */ - clearedThinkingTurns: number; - - /** - * Number of input tokens cleared by this edit. - * Minimum: 0 - */ - clearedInputTokens: number; - } - /** - * Represents a compaction edit where the conversation context was summarized. - */ - | { - /** - * The type of context management edit applied. - * Possible value: 'compact_20260112' - */ - type: 'compact_20260112'; - } - >; - } | null; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-messages-api.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-messages-api.ts deleted file mode 100644 index e0e3058f7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-messages-api.ts +++ /dev/null @@ -1,1344 +0,0 @@ -import { JSONSchema7 } from '@ai-sdk/provider'; -import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export type AnthropicMessagesPrompt = { - system: Array | undefined; - messages: AnthropicMessage[]; -}; - -export type AnthropicMessage = AnthropicUserMessage | AnthropicAssistantMessage; - -export type AnthropicCacheControl = { - type: 'ephemeral'; - ttl?: '5m' | '1h'; -}; - -export interface AnthropicUserMessage { - role: 'user'; - content: Array< - | AnthropicTextContent - | AnthropicImageContent - | AnthropicDocumentContent - | AnthropicToolResultContent - >; -} - -export interface AnthropicAssistantMessage { - role: 'assistant'; - content: Array< - | AnthropicTextContent - | AnthropicThinkingContent - | AnthropicRedactedThinkingContent - | AnthropicToolCallContent - | AnthropicServerToolUseContent - | AnthropicCodeExecutionToolResultContent - | AnthropicWebFetchToolResultContent - | AnthropicWebSearchToolResultContent - | AnthropicToolSearchToolResultContent - | AnthropicBashCodeExecutionToolResultContent - | AnthropicTextEditorCodeExecutionToolResultContent - | AnthropicMcpToolUseContent - | AnthropicMcpToolResultContent - | AnthropicCompactionContent - >; -} - -export interface AnthropicCompactionContent { - type: 'compaction'; - content: string; - cache_control?: AnthropicCacheControl; -} - -export interface AnthropicTextContent { - type: 'text'; - text: string; - cache_control: AnthropicCacheControl | undefined; -} - -export interface AnthropicThinkingContent { - type: 'thinking'; - thinking: string; - signature: string; - // Note: thinking blocks cannot be directly cached with cache_control. - // They are cached implicitly when appearing in previous assistant turns. - cache_control?: never; -} - -export interface AnthropicRedactedThinkingContent { - type: 'redacted_thinking'; - data: string; - // Note: redacted thinking blocks cannot be directly cached with cache_control. - // They are cached implicitly when appearing in previous assistant turns. - cache_control?: never; -} - -type AnthropicContentSource = - | { - type: 'base64'; - media_type: string; - data: string; - } - | { - type: 'url'; - url: string; - } - | { - type: 'text'; - media_type: 'text/plain'; - data: string; - }; - -export interface AnthropicImageContent { - type: 'image'; - source: AnthropicContentSource; - cache_control: AnthropicCacheControl | undefined; -} - -export interface AnthropicDocumentContent { - type: 'document'; - source: AnthropicContentSource; - title?: string; - context?: string; - citations?: { enabled: boolean }; - cache_control: AnthropicCacheControl | undefined; -} - -/** - * The caller information for programmatic tool calling. - * Present when a tool is called from within code execution. - */ -export type AnthropicToolCallCaller = - | { - type: 'code_execution_20250825'; - tool_id: string; - } - | { - type: 'code_execution_20260120'; - tool_id: string; - } - | { - type: 'direct'; - }; - -export interface AnthropicToolCallContent { - type: 'tool_use'; - id: string; - name: string; - input: unknown; - /** - * Present when this tool call was triggered by a server-executed tool - * (e.g., code execution calling a user-defined tool programmatically). - */ - caller?: AnthropicToolCallCaller; - cache_control: AnthropicCacheControl | undefined; -} - -export interface AnthropicServerToolUseContent { - type: 'server_tool_use'; - id: string; - name: - | 'web_fetch' - | 'web_search' - // code execution 20250522: - | 'code_execution' - // code execution 20250825: - | 'bash_code_execution' - | 'text_editor_code_execution' - // tool search: - | 'tool_search_tool_regex' - | 'tool_search_tool_bm25'; - input: unknown; - cache_control: AnthropicCacheControl | undefined; -} - -// Nested content types for tool results (without cache_control) -// Sub-content blocks cannot be cached directly according to Anthropic docs -type AnthropicNestedTextContent = Omit< - AnthropicTextContent, - 'cache_control' -> & { - cache_control?: never; -}; - -type AnthropicNestedImageContent = Omit< - AnthropicImageContent, - 'cache_control' -> & { - cache_control?: never; -}; - -type AnthropicNestedDocumentContent = Omit< - AnthropicDocumentContent, - 'cache_control' -> & { - cache_control?: never; -}; - -export interface AnthropicToolReferenceContent { - type: 'tool_reference'; - tool_name: string; -} - -export interface AnthropicToolResultContent { - type: 'tool_result'; - tool_use_id: string; - content: - | string - | Array< - | AnthropicNestedTextContent - | AnthropicNestedImageContent - | AnthropicNestedDocumentContent - | AnthropicToolReferenceContent - >; - is_error: boolean | undefined; - cache_control: AnthropicCacheControl | undefined; -} - -export interface AnthropicWebSearchToolResultContent { - type: 'web_search_tool_result'; - tool_use_id: string; - content: Array<{ - url: string; - title: string | null; - page_age: string | null; - encrypted_content: string; - type: string; - }>; - cache_control: AnthropicCacheControl | undefined; -} - -export interface AnthropicToolSearchToolResultContent { - type: 'tool_search_tool_result'; - tool_use_id: string; - content: - | { - type: 'tool_search_tool_search_result'; - tool_references: Array<{ - type: 'tool_reference'; - tool_name: string; - }>; - } - | { - type: 'tool_search_tool_result_error'; - error_code: string; - }; - cache_control: AnthropicCacheControl | undefined; -} - -// code execution results for code_execution_20250522 tool: -export interface AnthropicCodeExecutionToolResultContent { - type: 'code_execution_tool_result'; - tool_use_id: string; - content: - | { - type: 'code_execution_result'; - stdout: string; - stderr: string; - return_code: number; - content: Array<{ type: 'code_execution_output'; file_id: string }>; - } - | { - type: 'encrypted_code_execution_result'; - encrypted_stdout: string; - stderr: string; - return_code: number; - content: Array<{ type: 'code_execution_output'; file_id: string }>; - } - | { - type: 'code_execution_tool_result_error'; - error_code: string; - }; - cache_control: AnthropicCacheControl | undefined; -} - -// text editor code execution results for code_execution_20250825 tool: -export interface AnthropicTextEditorCodeExecutionToolResultContent { - type: 'text_editor_code_execution_tool_result'; - tool_use_id: string; - content: - | { - type: 'text_editor_code_execution_tool_result_error'; - error_code: string; - } - | { - type: 'text_editor_code_execution_create_result'; - is_file_update: boolean; - } - | { - type: 'text_editor_code_execution_view_result'; - content: string; - file_type: string; - num_lines: number | null; - start_line: number | null; - total_lines: number | null; - } - | { - type: 'text_editor_code_execution_str_replace_result'; - lines: string[] | null; - new_lines: number | null; - new_start: number | null; - old_lines: number | null; - old_start: number | null; - }; - cache_control: AnthropicCacheControl | undefined; -} - -// bash code execution results for code_execution_20250825 tool: -export interface AnthropicBashCodeExecutionToolResultContent { - type: 'bash_code_execution_tool_result'; - tool_use_id: string; - content: - | { - type: 'bash_code_execution_result'; - stdout: string; - stderr: string; - return_code: number; - content: { - type: 'bash_code_execution_output'; - file_id: string; - }[]; - } - | { - type: 'bash_code_execution_tool_result_error'; - error_code: string; - }; - cache_control: AnthropicCacheControl | undefined; -} - -export interface AnthropicWebFetchToolResultContent { - type: 'web_fetch_tool_result'; - tool_use_id: string; - content: - | { - type: 'web_fetch_result'; - url: string; - retrieved_at: string | null; - content: { - type: 'document'; - title: string | null; - citations?: { enabled: boolean }; - source: - | { type: 'base64'; media_type: 'application/pdf'; data: string } - | { type: 'text'; media_type: 'text/plain'; data: string }; - }; - } - | { - type: 'web_fetch_tool_result_error'; - error_code: string; - }; - cache_control: AnthropicCacheControl | undefined; -} -export interface AnthropicMcpToolUseContent { - type: 'mcp_tool_use'; - id: string; - name: string; - server_name: string; - input: unknown; - cache_control: AnthropicCacheControl | undefined; -} - -export interface AnthropicMcpToolResultContent { - type: 'mcp_tool_result'; - tool_use_id: string; - is_error: boolean; - content: string | Array<{ type: 'text'; text: string }>; - cache_control: AnthropicCacheControl | undefined; -} - -export type AnthropicTool = - | { - name: string; - description: string | undefined; - input_schema: JSONSchema7; - cache_control: AnthropicCacheControl | undefined; - eager_input_streaming?: boolean; - strict?: boolean; - /** - * When true, this tool is deferred and will only be loaded when - * discovered via the tool search tool. - */ - defer_loading?: boolean; - /** - * Programmatic tool calling: specifies which server-executed tools - * are allowed to call this tool. When set, only the specified callers - * can invoke this tool programmatically. - * - * @example ['code_execution_20250825'] - */ - allowed_callers?: Array< - 'direct' | 'code_execution_20250825' | 'code_execution_20260120' - >; - } - | { - type: 'code_execution_20250522'; - name: string; - cache_control: AnthropicCacheControl | undefined; - } - | { - type: 'code_execution_20250825'; - name: string; - } - | { - type: 'code_execution_20260120'; - name: string; - } - | { - name: string; - type: 'computer_20250124' | 'computer_20241022'; - display_width_px: number; - display_height_px: number; - display_number: number; - cache_control: AnthropicCacheControl | undefined; - } - | { - name: string; - type: 'computer_20251124'; - display_width_px: number; - display_height_px: number; - display_number: number; - enable_zoom?: boolean; - cache_control: AnthropicCacheControl | undefined; - } - | { - name: string; - type: - | 'text_editor_20250124' - | 'text_editor_20241022' - | 'text_editor_20250429'; - cache_control: AnthropicCacheControl | undefined; - } - | { - name: string; - type: 'text_editor_20250728'; - max_characters?: number; - cache_control: AnthropicCacheControl | undefined; - } - | { - name: string; - type: 'bash_20250124' | 'bash_20241022'; - cache_control: AnthropicCacheControl | undefined; - } - | { - name: string; - type: 'memory_20250818'; - } - | { - type: 'web_fetch_20250910' | 'web_fetch_20260209'; - name: string; - max_uses?: number; - allowed_domains?: string[]; - blocked_domains?: string[]; - citations?: { enabled: boolean }; - max_content_tokens?: number; - cache_control: AnthropicCacheControl | undefined; - } - | { - type: 'web_search_20250305' | 'web_search_20260209'; - name: string; - max_uses?: number; - allowed_domains?: string[]; - blocked_domains?: string[]; - user_location?: { - type: 'approximate'; - city?: string; - region?: string; - country?: string; - timezone?: string; - }; - cache_control: AnthropicCacheControl | undefined; - } - | { - type: 'tool_search_tool_regex_20251119'; - name: string; - } - | { - type: 'tool_search_tool_bm25_20251119'; - name: string; - }; - -export type AnthropicSpeed = 'fast' | 'standard'; - -export type AnthropicToolChoice = - | { type: 'auto' | 'any'; disable_parallel_tool_use?: boolean } - | { type: 'tool'; name: string; disable_parallel_tool_use?: boolean }; - -export type AnthropicContainer = { - id?: string | null; - skills?: Array<{ - type: 'anthropic' | 'custom'; - skill_id: string; - version?: string; - }> | null; -}; - -export type AnthropicInputTokensTrigger = { - type: 'input_tokens'; - value: number; -}; - -export type AnthropicToolUsesTrigger = { - type: 'tool_uses'; - value: number; -}; - -export type AnthropicContextManagementTrigger = - | AnthropicInputTokensTrigger - | AnthropicToolUsesTrigger; - -export type AnthropicClearToolUsesEdit = { - type: 'clear_tool_uses_20250919'; - trigger?: AnthropicContextManagementTrigger; - keep?: { - type: 'tool_uses'; - value: number; - }; - clear_at_least?: { - type: 'input_tokens'; - value: number; - }; - clear_tool_inputs?: boolean; - exclude_tools?: string[]; -}; - -export type AnthropicClearThinkingBlockEdit = { - type: 'clear_thinking_20251015'; - keep?: 'all' | { type: 'thinking_turns'; value: number }; -}; - -export type AnthropicCompactEdit = { - type: 'compact_20260112'; - trigger?: AnthropicInputTokensTrigger; - pause_after_compaction?: boolean; - instructions?: string; -}; - -export type AnthropicContextManagementEdit = - | AnthropicClearToolUsesEdit - | AnthropicClearThinkingBlockEdit - | AnthropicCompactEdit; - -export type AnthropicContextManagementConfig = { - edits: AnthropicContextManagementEdit[]; -}; - -export type AnthropicResponseClearToolUsesEdit = { - type: 'clear_tool_uses_20250919'; - cleared_tool_uses: number; - cleared_input_tokens: number; -}; - -export type AnthropicResponseClearThinkingBlockEdit = { - type: 'clear_thinking_20251015'; - cleared_thinking_turns: number; - cleared_input_tokens: number; -}; - -export type AnthropicResponseCompactEdit = { - type: 'compact_20260112'; -}; - -export type AnthropicResponseContextManagementEdit = - | AnthropicResponseClearToolUsesEdit - | AnthropicResponseClearThinkingBlockEdit - | AnthropicResponseCompactEdit; - -export type AnthropicResponseContextManagement = { - applied_edits: AnthropicResponseContextManagementEdit[]; -}; - -// limited version of the schema, focussed on what is needed for the implementation -// this approach limits breakages when the API changes and increases efficiency -export const anthropicMessagesResponseSchema = lazySchema(() => - zodSchema( - z.object({ - type: z.literal('message'), - id: z.string().nullish(), - model: z.string().nullish(), - content: z.array( - z.discriminatedUnion('type', [ - z.object({ - type: z.literal('text'), - text: z.string(), - citations: z - .array( - z.discriminatedUnion('type', [ - z.object({ - type: z.literal('web_search_result_location'), - cited_text: z.string(), - url: z.string(), - title: z.string(), - encrypted_index: z.string(), - }), - z.object({ - type: z.literal('page_location'), - cited_text: z.string(), - document_index: z.number(), - document_title: z.string().nullable(), - start_page_number: z.number(), - end_page_number: z.number(), - }), - z.object({ - type: z.literal('char_location'), - cited_text: z.string(), - document_index: z.number(), - document_title: z.string().nullable(), - start_char_index: z.number(), - end_char_index: z.number(), - }), - ]), - ) - .optional(), - }), - z.object({ - type: z.literal('thinking'), - thinking: z.string(), - signature: z.string(), - }), - z.object({ - type: z.literal('redacted_thinking'), - data: z.string(), - }), - z.object({ - type: z.literal('compaction'), - content: z.string(), - }), - z.object({ - type: z.literal('tool_use'), - id: z.string(), - name: z.string(), - input: z.unknown(), - // Programmatic tool calling: caller info when triggered from code execution - caller: z - .union([ - z.object({ - type: z.literal('code_execution_20250825'), - tool_id: z.string(), - }), - z.object({ - type: z.literal('code_execution_20260120'), - tool_id: z.string(), - }), - z.object({ - type: z.literal('direct'), - }), - ]) - .optional(), - }), - z.object({ - type: z.literal('server_tool_use'), - id: z.string(), - name: z.string(), - input: z.record(z.string(), z.unknown()).nullish(), - caller: z - .union([ - z.object({ - type: z.literal('code_execution_20260120'), - tool_id: z.string(), - }), - z.object({ - type: z.literal('direct'), - }), - ]) - .optional(), - }), - z.object({ - type: z.literal('mcp_tool_use'), - id: z.string(), - name: z.string(), - input: z.unknown(), - server_name: z.string(), - }), - z.object({ - type: z.literal('mcp_tool_result'), - tool_use_id: z.string(), - is_error: z.boolean(), - content: z.array( - z.union([ - z.string(), - z.object({ type: z.literal('text'), text: z.string() }), - ]), - ), - }), - z.object({ - type: z.literal('web_fetch_tool_result'), - tool_use_id: z.string(), - content: z.union([ - z.object({ - type: z.literal('web_fetch_result'), - url: z.string(), - retrieved_at: z.string(), - content: z.object({ - type: z.literal('document'), - title: z.string().nullable(), - citations: z.object({ enabled: z.boolean() }).optional(), - source: z.union([ - z.object({ - type: z.literal('base64'), - media_type: z.literal('application/pdf'), - data: z.string(), - }), - z.object({ - type: z.literal('text'), - media_type: z.literal('text/plain'), - data: z.string(), - }), - ]), - }), - }), - z.object({ - type: z.literal('web_fetch_tool_result_error'), - error_code: z.string(), - }), - ]), - }), - z.object({ - type: z.literal('web_search_tool_result'), - tool_use_id: z.string(), - content: z.union([ - z.array( - z.object({ - type: z.literal('web_search_result'), - url: z.string(), - title: z.string(), - encrypted_content: z.string(), - page_age: z.string().nullish(), - }), - ), - z.object({ - type: z.literal('web_search_tool_result_error'), - error_code: z.string(), - }), - ]), - }), - // code execution results for code_execution_20250522 tool: - z.object({ - type: z.literal('code_execution_tool_result'), - tool_use_id: z.string(), - content: z.union([ - z.object({ - type: z.literal('code_execution_result'), - stdout: z.string(), - stderr: z.string(), - return_code: z.number(), - content: z - .array( - z.object({ - type: z.literal('code_execution_output'), - file_id: z.string(), - }), - ) - .optional() - .default([]), - }), - z.object({ - type: z.literal('encrypted_code_execution_result'), - encrypted_stdout: z.string(), - stderr: z.string(), - return_code: z.number(), - content: z - .array( - z.object({ - type: z.literal('code_execution_output'), - file_id: z.string(), - }), - ) - .optional() - .default([]), - }), - z.object({ - type: z.literal('code_execution_tool_result_error'), - error_code: z.string(), - }), - ]), - }), - // bash code execution results for code_execution_20250825 tool: - z.object({ - type: z.literal('bash_code_execution_tool_result'), - tool_use_id: z.string(), - content: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('bash_code_execution_result'), - content: z.array( - z.object({ - type: z.literal('bash_code_execution_output'), - file_id: z.string(), - }), - ), - stdout: z.string(), - stderr: z.string(), - return_code: z.number(), - }), - z.object({ - type: z.literal('bash_code_execution_tool_result_error'), - error_code: z.string(), - }), - ]), - }), - // text editor code execution results for code_execution_20250825 tool: - z.object({ - type: z.literal('text_editor_code_execution_tool_result'), - tool_use_id: z.string(), - content: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('text_editor_code_execution_tool_result_error'), - error_code: z.string(), - }), - z.object({ - type: z.literal('text_editor_code_execution_view_result'), - content: z.string(), - file_type: z.string(), - num_lines: z.number().nullable(), - start_line: z.number().nullable(), - total_lines: z.number().nullable(), - }), - z.object({ - type: z.literal('text_editor_code_execution_create_result'), - is_file_update: z.boolean(), - }), - z.object({ - type: z.literal( - 'text_editor_code_execution_str_replace_result', - ), - lines: z.array(z.string()).nullable(), - new_lines: z.number().nullable(), - new_start: z.number().nullable(), - old_lines: z.number().nullable(), - old_start: z.number().nullable(), - }), - ]), - }), - // tool search tool results for tool_search_tool_regex_20251119 and tool_search_tool_bm25_20251119: - z.object({ - type: z.literal('tool_search_tool_result'), - tool_use_id: z.string(), - content: z.union([ - z.object({ - type: z.literal('tool_search_tool_search_result'), - tool_references: z.array( - z.object({ - type: z.literal('tool_reference'), - tool_name: z.string(), - }), - ), - }), - z.object({ - type: z.literal('tool_search_tool_result_error'), - error_code: z.string(), - }), - ]), - }), - ]), - ), - stop_reason: z.string().nullish(), - stop_sequence: z.string().nullish(), - usage: z.looseObject({ - input_tokens: z.number(), - output_tokens: z.number(), - cache_creation_input_tokens: z.number().nullish(), - cache_read_input_tokens: z.number().nullish(), - iterations: z - .array( - z.object({ - type: z.union([z.literal('compaction'), z.literal('message')]), - input_tokens: z.number(), - output_tokens: z.number(), - }), - ) - .nullish(), - }), - container: z - .object({ - expires_at: z.string(), - id: z.string(), - skills: z - .array( - z.object({ - type: z.union([z.literal('anthropic'), z.literal('custom')]), - skill_id: z.string(), - version: z.string(), - }), - ) - .nullish(), - }) - .nullish(), - context_management: z - .object({ - applied_edits: z.array( - z.union([ - z.object({ - type: z.literal('clear_tool_uses_20250919'), - cleared_tool_uses: z.number(), - cleared_input_tokens: z.number(), - }), - z.object({ - type: z.literal('clear_thinking_20251015'), - cleared_thinking_turns: z.number(), - cleared_input_tokens: z.number(), - }), - z.object({ - type: z.literal('compact_20260112'), - }), - ]), - ), - }) - .nullish(), - }), - ), -); - -// limited version of the schema, focused on what is needed for the implementation -// this approach limits breakages when the API changes and increases efficiency -export const anthropicMessagesChunkSchema = lazySchema(() => - zodSchema( - z.discriminatedUnion('type', [ - z.object({ - type: z.literal('message_start'), - message: z.object({ - id: z.string().nullish(), - model: z.string().nullish(), - role: z.string().nullish(), - usage: z.looseObject({ - input_tokens: z.number(), - cache_creation_input_tokens: z.number().nullish(), - cache_read_input_tokens: z.number().nullish(), - }), - // Programmatic tool calling: content may be pre-populated for deferred tool calls - content: z - .array( - z.discriminatedUnion('type', [ - z.object({ - type: z.literal('tool_use'), - id: z.string(), - name: z.string(), - input: z.unknown(), - caller: z - .union([ - z.object({ - type: z.literal('code_execution_20250825'), - tool_id: z.string(), - }), - z.object({ - type: z.literal('code_execution_20260120'), - tool_id: z.string(), - }), - z.object({ - type: z.literal('direct'), - }), - ]) - .optional(), - }), - ]), - ) - .nullish(), - stop_reason: z.string().nullish(), - container: z - .object({ - expires_at: z.string(), - id: z.string(), - }) - .nullish(), - }), - }), - z.object({ - type: z.literal('content_block_start'), - index: z.number(), - content_block: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('text'), - text: z.string(), - }), - z.object({ - type: z.literal('thinking'), - thinking: z.string(), - }), - z.object({ - type: z.literal('tool_use'), - id: z.string(), - name: z.string(), - // Programmatic tool calling: input may be present directly for deferred tool calls - input: z.record(z.string(), z.unknown()).optional(), - // Programmatic tool calling: caller info when triggered from code execution - caller: z - .union([ - z.object({ - type: z.literal('code_execution_20250825'), - tool_id: z.string(), - }), - z.object({ - type: z.literal('code_execution_20260120'), - tool_id: z.string(), - }), - z.object({ - type: z.literal('direct'), - }), - ]) - .optional(), - }), - z.object({ - type: z.literal('redacted_thinking'), - data: z.string(), - }), - z.object({ - type: z.literal('compaction'), - content: z.string().nullish(), - }), - z.object({ - type: z.literal('server_tool_use'), - id: z.string(), - name: z.string(), - input: z.record(z.string(), z.unknown()).nullish(), - caller: z - .union([ - z.object({ - type: z.literal('code_execution_20260120'), - tool_id: z.string(), - }), - z.object({ - type: z.literal('direct'), - }), - ]) - .optional(), - }), - z.object({ - type: z.literal('mcp_tool_use'), - id: z.string(), - name: z.string(), - input: z.unknown(), - server_name: z.string(), - }), - z.object({ - type: z.literal('mcp_tool_result'), - tool_use_id: z.string(), - is_error: z.boolean(), - content: z.array( - z.union([ - z.string(), - z.object({ type: z.literal('text'), text: z.string() }), - ]), - ), - }), - z.object({ - type: z.literal('web_fetch_tool_result'), - tool_use_id: z.string(), - content: z.union([ - z.object({ - type: z.literal('web_fetch_result'), - url: z.string(), - retrieved_at: z.string(), - content: z.object({ - type: z.literal('document'), - title: z.string().nullable(), - citations: z.object({ enabled: z.boolean() }).optional(), - source: z.union([ - z.object({ - type: z.literal('base64'), - media_type: z.literal('application/pdf'), - data: z.string(), - }), - z.object({ - type: z.literal('text'), - media_type: z.literal('text/plain'), - data: z.string(), - }), - ]), - }), - }), - z.object({ - type: z.literal('web_fetch_tool_result_error'), - error_code: z.string(), - }), - ]), - }), - z.object({ - type: z.literal('web_search_tool_result'), - tool_use_id: z.string(), - content: z.union([ - z.array( - z.object({ - type: z.literal('web_search_result'), - url: z.string(), - title: z.string(), - encrypted_content: z.string(), - page_age: z.string().nullish(), - }), - ), - z.object({ - type: z.literal('web_search_tool_result_error'), - error_code: z.string(), - }), - ]), - }), - // code execution results for code_execution_20250522 tool: - z.object({ - type: z.literal('code_execution_tool_result'), - tool_use_id: z.string(), - content: z.union([ - z.object({ - type: z.literal('code_execution_result'), - stdout: z.string(), - stderr: z.string(), - return_code: z.number(), - content: z - .array( - z.object({ - type: z.literal('code_execution_output'), - file_id: z.string(), - }), - ) - .optional() - .default([]), - }), - z.object({ - type: z.literal('encrypted_code_execution_result'), - encrypted_stdout: z.string(), - stderr: z.string(), - return_code: z.number(), - content: z - .array( - z.object({ - type: z.literal('code_execution_output'), - file_id: z.string(), - }), - ) - .optional() - .default([]), - }), - z.object({ - type: z.literal('code_execution_tool_result_error'), - error_code: z.string(), - }), - ]), - }), - // bash code execution results for code_execution_20250825 tool: - z.object({ - type: z.literal('bash_code_execution_tool_result'), - tool_use_id: z.string(), - content: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('bash_code_execution_result'), - content: z.array( - z.object({ - type: z.literal('bash_code_execution_output'), - file_id: z.string(), - }), - ), - stdout: z.string(), - stderr: z.string(), - return_code: z.number(), - }), - z.object({ - type: z.literal('bash_code_execution_tool_result_error'), - error_code: z.string(), - }), - ]), - }), - // text editor code execution results for code_execution_20250825 tool: - z.object({ - type: z.literal('text_editor_code_execution_tool_result'), - tool_use_id: z.string(), - content: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('text_editor_code_execution_tool_result_error'), - error_code: z.string(), - }), - z.object({ - type: z.literal('text_editor_code_execution_view_result'), - content: z.string(), - file_type: z.string(), - num_lines: z.number().nullable(), - start_line: z.number().nullable(), - total_lines: z.number().nullable(), - }), - z.object({ - type: z.literal('text_editor_code_execution_create_result'), - is_file_update: z.boolean(), - }), - z.object({ - type: z.literal( - 'text_editor_code_execution_str_replace_result', - ), - lines: z.array(z.string()).nullable(), - new_lines: z.number().nullable(), - new_start: z.number().nullable(), - old_lines: z.number().nullable(), - old_start: z.number().nullable(), - }), - ]), - }), - // tool search tool results for tool_search_tool_regex_20251119 and tool_search_tool_bm25_20251119: - z.object({ - type: z.literal('tool_search_tool_result'), - tool_use_id: z.string(), - content: z.union([ - z.object({ - type: z.literal('tool_search_tool_search_result'), - tool_references: z.array( - z.object({ - type: z.literal('tool_reference'), - tool_name: z.string(), - }), - ), - }), - z.object({ - type: z.literal('tool_search_tool_result_error'), - error_code: z.string(), - }), - ]), - }), - ]), - }), - z.object({ - type: z.literal('content_block_delta'), - index: z.number(), - delta: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('input_json_delta'), - partial_json: z.string(), - }), - z.object({ - type: z.literal('text_delta'), - text: z.string(), - }), - z.object({ - type: z.literal('thinking_delta'), - thinking: z.string(), - }), - z.object({ - type: z.literal('signature_delta'), - signature: z.string(), - }), - z.object({ - type: z.literal('compaction_delta'), - content: z.string().nullish(), - }), - z.object({ - type: z.literal('citations_delta'), - citation: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('web_search_result_location'), - cited_text: z.string(), - url: z.string(), - title: z.string(), - encrypted_index: z.string(), - }), - z.object({ - type: z.literal('page_location'), - cited_text: z.string(), - document_index: z.number(), - document_title: z.string().nullable(), - start_page_number: z.number(), - end_page_number: z.number(), - }), - z.object({ - type: z.literal('char_location'), - cited_text: z.string(), - document_index: z.number(), - document_title: z.string().nullable(), - start_char_index: z.number(), - end_char_index: z.number(), - }), - ]), - }), - ]), - }), - z.object({ - type: z.literal('content_block_stop'), - index: z.number(), - }), - z.object({ - type: z.literal('error'), - error: z.object({ - type: z.string(), - message: z.string(), - }), - }), - z.object({ - type: z.literal('message_delta'), - delta: z.object({ - stop_reason: z.string().nullish(), - stop_sequence: z.string().nullish(), - container: z - .object({ - expires_at: z.string(), - id: z.string(), - skills: z - .array( - z.object({ - type: z.union([ - z.literal('anthropic'), - z.literal('custom'), - ]), - skill_id: z.string(), - version: z.string(), - }), - ) - .nullish(), - }) - .nullish(), - }), - usage: z.looseObject({ - input_tokens: z.number().nullish(), - output_tokens: z.number(), - cache_creation_input_tokens: z.number().nullish(), - cache_read_input_tokens: z.number().nullish(), - iterations: z - .array( - z.object({ - type: z.union([z.literal('compaction'), z.literal('message')]), - input_tokens: z.number(), - output_tokens: z.number(), - }), - ) - .nullish(), - }), - context_management: z - .object({ - applied_edits: z.array( - z.union([ - z.object({ - type: z.literal('clear_tool_uses_20250919'), - cleared_tool_uses: z.number(), - cleared_input_tokens: z.number(), - }), - z.object({ - type: z.literal('clear_thinking_20251015'), - cleared_thinking_turns: z.number(), - cleared_input_tokens: z.number(), - }), - z.object({ - type: z.literal('compact_20260112'), - }), - ]), - ), - }) - .nullish(), - }), - z.object({ - type: z.literal('message_stop'), - }), - z.object({ - type: z.literal('ping'), - }), - ]), - ), -); - -export const anthropicReasoningMetadataSchema = lazySchema(() => - zodSchema( - z.object({ - signature: z.string().optional(), - redactedData: z.string().optional(), - }), - ), -); - -export type AnthropicReasoningMetadata = InferSchema< - typeof anthropicReasoningMetadataSchema ->; - -export type Citation = NonNullable< - (InferSchema['content'][number] & { - type: 'text'; - })['citations'] ->[number]; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-messages-language-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-messages-language-model.ts deleted file mode 100644 index 5a736b0ac..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-messages-language-model.ts +++ /dev/null @@ -1,2392 +0,0 @@ -import { - APICallError, - JSONObject, - LanguageModelV3, - LanguageModelV3CallOptions, - LanguageModelV3Content, - LanguageModelV3FinishReason, - LanguageModelV3FunctionTool, - LanguageModelV3GenerateResult, - LanguageModelV3Prompt, - LanguageModelV3Source, - LanguageModelV3StreamPart, - LanguageModelV3StreamResult, - LanguageModelV3ToolCall, - SharedV3ProviderMetadata, - SharedV3Warning, -} from '@ai-sdk/provider'; -import { - combineHeaders, - createEventSourceResponseHandler, - createJsonResponseHandler, - createToolNameMapping, - FetchFunction, - generateId, - InferSchema, - parseProviderOptions, - ParseResult, - postJsonToApi, - Resolvable, - resolve, -} from '@ai-sdk/provider-utils'; -import { anthropicFailedResponseHandler } from './anthropic-error'; -import { AnthropicMessageMetadata } from './anthropic-message-metadata'; -import { - AnthropicContainer, - anthropicMessagesChunkSchema, - anthropicMessagesResponseSchema, - AnthropicReasoningMetadata, - AnthropicResponseContextManagement, - AnthropicTool, - Citation, -} from './anthropic-messages-api'; -import { - AnthropicMessagesModelId, - anthropicLanguageModelOptions, -} from './anthropic-messages-options'; -import { prepareTools } from './anthropic-prepare-tools'; -import { - AnthropicMessagesUsage, - convertAnthropicMessagesUsage, -} from './convert-anthropic-messages-usage'; -import { convertToAnthropicMessagesPrompt } from './convert-to-anthropic-messages-prompt'; -import { CacheControlValidator } from './get-cache-control'; -import { mapAnthropicStopReason } from './map-anthropic-stop-reason'; - -function createCitationSource( - citation: Citation, - citationDocuments: Array<{ - title: string; - filename?: string; - mediaType: string; - }>, - generateId: () => string, -): LanguageModelV3Source | undefined { - if (citation.type === 'web_search_result_location') { - return { - type: 'source' as const, - sourceType: 'url' as const, - id: generateId(), - url: citation.url, - title: citation.title, - providerMetadata: { - anthropic: { - citedText: citation.cited_text, - encryptedIndex: citation.encrypted_index, - }, - } satisfies SharedV3ProviderMetadata, - }; - } - - if (citation.type !== 'page_location' && citation.type !== 'char_location') { - return; - } - - const documentInfo = citationDocuments[citation.document_index]; - - if (!documentInfo) { - return; - } - - return { - type: 'source' as const, - sourceType: 'document' as const, - id: generateId(), - mediaType: documentInfo.mediaType, - title: citation.document_title ?? documentInfo.title, - filename: documentInfo.filename, - providerMetadata: { - anthropic: - citation.type === 'page_location' - ? { - citedText: citation.cited_text, - startPageNumber: citation.start_page_number, - endPageNumber: citation.end_page_number, - } - : { - citedText: citation.cited_text, - startCharIndex: citation.start_char_index, - endCharIndex: citation.end_char_index, - }, - } satisfies SharedV3ProviderMetadata, - }; -} - -type AnthropicMessagesConfig = { - provider: string; - baseURL: string; - headers: Resolvable>; - fetch?: FetchFunction; - buildRequestUrl?: (baseURL: string, isStreaming: boolean) => string; - transformRequestBody?: ( - args: Record, - betas: Set, - ) => Record; - supportedUrls?: () => LanguageModelV3['supportedUrls']; - generateId?: () => string; - - /** - * When false, the model will use JSON tool fallback for structured outputs. - */ - supportsNativeStructuredOutput?: boolean; - - /** - * When false, `strict` on tool definitions will be ignored and a warning emitted. - * Defaults to true. - */ - supportsStrictTools?: boolean; -}; - -export class AnthropicMessagesLanguageModel implements LanguageModelV3 { - readonly specificationVersion = 'v3'; - - readonly modelId: AnthropicMessagesModelId; - - private readonly config: AnthropicMessagesConfig; - private readonly generateId: () => string; - - constructor( - modelId: AnthropicMessagesModelId, - config: AnthropicMessagesConfig, - ) { - this.modelId = modelId; - this.config = config; - this.generateId = config.generateId ?? generateId; - } - - supportsUrl(url: URL): boolean { - return url.protocol === 'https:'; - } - - get provider(): string { - return this.config.provider; - } - - /** - * Extracts the dynamic provider name from the config.provider string. - * e.g., 'my-custom-anthropic.messages' -> 'my-custom-anthropic' - */ - private get providerOptionsName(): string { - const provider = this.config.provider; - const dotIndex = provider.indexOf('.'); - return dotIndex === -1 ? provider : provider.substring(0, dotIndex); - } - - get supportedUrls() { - return this.config.supportedUrls?.() ?? {}; - } - - private async getArgs({ - userSuppliedBetas, - prompt, - maxOutputTokens, - temperature, - topP, - topK, - frequencyPenalty, - presencePenalty, - stopSequences, - responseFormat, - seed, - tools, - toolChoice, - providerOptions, - stream, - }: LanguageModelV3CallOptions & { - stream: boolean; - userSuppliedBetas: Set; - }) { - const warnings: SharedV3Warning[] = []; - - if (frequencyPenalty != null) { - warnings.push({ type: 'unsupported', feature: 'frequencyPenalty' }); - } - - if (presencePenalty != null) { - warnings.push({ type: 'unsupported', feature: 'presencePenalty' }); - } - - if (seed != null) { - warnings.push({ type: 'unsupported', feature: 'seed' }); - } - - if (temperature != null && temperature > 1) { - warnings.push({ - type: 'unsupported', - feature: 'temperature', - details: `${temperature} exceeds anthropic maximum of 1.0. clamped to 1.0`, - }); - temperature = 1; - } else if (temperature != null && temperature < 0) { - warnings.push({ - type: 'unsupported', - feature: 'temperature', - details: `${temperature} is below anthropic minimum of 0. clamped to 0`, - }); - temperature = 0; - } - - if (responseFormat?.type === 'json') { - if (responseFormat.schema == null) { - warnings.push({ - type: 'unsupported', - feature: 'responseFormat', - details: - 'JSON response format requires a schema. ' + - 'The response format is ignored.', - }); - } - } - - const providerOptionsName = this.providerOptionsName; - - // Parse provider options from both canonical 'anthropic' key and custom key - const canonicalOptions = await parseProviderOptions({ - provider: 'anthropic', - providerOptions, - schema: anthropicLanguageModelOptions, - }); - - const customProviderOptions = - providerOptionsName !== 'anthropic' - ? await parseProviderOptions({ - provider: providerOptionsName, - providerOptions, - schema: anthropicLanguageModelOptions, - }) - : null; - - // Track if custom key was explicitly used - const usedCustomProviderKey = customProviderOptions != null; - - // Merge options - const anthropicOptions = Object.assign( - {}, - canonicalOptions ?? {}, - customProviderOptions ?? {}, - ); - - const { - maxOutputTokens: maxOutputTokensForModel, - supportsStructuredOutput: modelSupportsStructuredOutput, - isKnownModel, - } = getModelCapabilities(this.modelId); - - const supportsStructuredOutput = - (this.config.supportsNativeStructuredOutput ?? true) && - modelSupportsStructuredOutput; - - const supportsStrictTools = - (this.config.supportsStrictTools ?? true) && - modelSupportsStructuredOutput; - - const structureOutputMode = - anthropicOptions?.structuredOutputMode ?? 'auto'; - const useStructuredOutput = - structureOutputMode === 'outputFormat' || - (structureOutputMode === 'auto' && supportsStructuredOutput); - - const jsonResponseTool: LanguageModelV3FunctionTool | undefined = - responseFormat?.type === 'json' && - responseFormat.schema != null && - !useStructuredOutput - ? { - type: 'function', - name: 'json', - description: 'Respond with a JSON object.', - inputSchema: responseFormat.schema, - } - : undefined; - - const contextManagement = anthropicOptions?.contextManagement; - - // Create a shared cache control validator to track breakpoints across tools and messages - const cacheControlValidator = new CacheControlValidator(); - - const toolNameMapping = createToolNameMapping({ - tools, - providerToolNames: { - 'anthropic.code_execution_20250522': 'code_execution', - 'anthropic.code_execution_20250825': 'code_execution', - 'anthropic.code_execution_20260120': 'code_execution', - 'anthropic.computer_20241022': 'computer', - 'anthropic.computer_20250124': 'computer', - 'anthropic.text_editor_20241022': 'str_replace_editor', - 'anthropic.text_editor_20250124': 'str_replace_editor', - 'anthropic.text_editor_20250429': 'str_replace_based_edit_tool', - 'anthropic.text_editor_20250728': 'str_replace_based_edit_tool', - 'anthropic.bash_20241022': 'bash', - 'anthropic.bash_20250124': 'bash', - 'anthropic.memory_20250818': 'memory', - 'anthropic.web_search_20250305': 'web_search', - 'anthropic.web_search_20260209': 'web_search', - 'anthropic.web_fetch_20250910': 'web_fetch', - 'anthropic.web_fetch_20260209': 'web_fetch', - 'anthropic.tool_search_regex_20251119': 'tool_search_tool_regex', - 'anthropic.tool_search_bm25_20251119': 'tool_search_tool_bm25', - }, - }); - - const { prompt: messagesPrompt, betas } = - await convertToAnthropicMessagesPrompt({ - prompt, - sendReasoning: anthropicOptions?.sendReasoning ?? true, - warnings, - cacheControlValidator, - toolNameMapping, - }); - - const thinkingType = anthropicOptions?.thinking?.type; - const isThinking = - thinkingType === 'enabled' || thinkingType === 'adaptive'; - let thinkingBudget = - thinkingType === 'enabled' - ? anthropicOptions?.thinking?.budgetTokens - : undefined; - - const maxTokens = maxOutputTokens ?? maxOutputTokensForModel; - - const baseArgs = { - // model id: - model: this.modelId, - - // standardized settings: - max_tokens: maxTokens, - temperature, - top_k: topK, - top_p: topP, - stop_sequences: stopSequences, - - // provider specific settings: - ...(isThinking && { - thinking: { - type: thinkingType, - ...(thinkingBudget != null && { budget_tokens: thinkingBudget }), - }, - }), - ...((anthropicOptions?.effort || - (useStructuredOutput && - responseFormat?.type === 'json' && - responseFormat.schema != null)) && { - output_config: { - ...(anthropicOptions?.effort && { - effort: anthropicOptions.effort, - }), - ...(useStructuredOutput && - responseFormat?.type === 'json' && - responseFormat.schema != null && { - format: { - type: 'json_schema', - schema: responseFormat.schema, - }, - }), - }, - }), - ...(anthropicOptions?.speed && { - speed: anthropicOptions.speed, - }), - ...(anthropicOptions?.cacheControl && { - cache_control: anthropicOptions.cacheControl, - }), - ...(anthropicOptions?.metadata?.userId != null && { - metadata: { user_id: anthropicOptions.metadata.userId }, - }), - - // mcp servers: - ...(anthropicOptions?.mcpServers && - anthropicOptions.mcpServers.length > 0 && { - mcp_servers: anthropicOptions.mcpServers.map(server => ({ - type: server.type, - name: server.name, - url: server.url, - authorization_token: server.authorizationToken, - tool_configuration: server.toolConfiguration - ? { - allowed_tools: server.toolConfiguration.allowedTools, - enabled: server.toolConfiguration.enabled, - } - : undefined, - })), - }), - - // container: For programmatic tool calling (just an ID string) or agent skills (object with id and skills) - ...(anthropicOptions?.container && { - container: - anthropicOptions.container.skills && - anthropicOptions.container.skills.length > 0 - ? // Object format when skills are provided (agent skills feature) - ({ - id: anthropicOptions.container.id, - skills: anthropicOptions.container.skills.map(skill => ({ - type: skill.type, - skill_id: skill.skillId, - version: skill.version, - })), - } satisfies AnthropicContainer) - : // String format for container ID only (programmatic tool calling) - anthropicOptions.container.id, - }), - - // prompt: - system: messagesPrompt.system, - messages: messagesPrompt.messages, - - ...(contextManagement && { - context_management: { - edits: contextManagement.edits - .map(edit => { - const strategy = edit.type; - switch (strategy) { - case 'clear_tool_uses_20250919': - return { - type: edit.type, - ...(edit.trigger !== undefined && { - trigger: edit.trigger, - }), - ...(edit.keep !== undefined && { keep: edit.keep }), - ...(edit.clearAtLeast !== undefined && { - clear_at_least: edit.clearAtLeast, - }), - ...(edit.clearToolInputs !== undefined && { - clear_tool_inputs: edit.clearToolInputs, - }), - ...(edit.excludeTools !== undefined && { - exclude_tools: edit.excludeTools, - }), - }; - - case 'clear_thinking_20251015': - return { - type: edit.type, - ...(edit.keep !== undefined && { keep: edit.keep }), - }; - - case 'compact_20260112': - return { - type: edit.type, - ...(edit.trigger !== undefined && { - trigger: edit.trigger, - }), - ...(edit.pauseAfterCompaction !== undefined && { - pause_after_compaction: edit.pauseAfterCompaction, - }), - ...(edit.instructions !== undefined && { - instructions: edit.instructions, - }), - }; - - default: - warnings.push({ - type: 'other', - message: `Unknown context management strategy: ${strategy}`, - }); - return undefined; - } - }) - .filter(edit => edit !== undefined), - }, - }), - }; - - if (isThinking) { - if (thinkingType === 'enabled' && thinkingBudget == null) { - warnings.push({ - type: 'compatibility', - feature: 'extended thinking', - details: - 'thinking budget is required when thinking is enabled. using default budget of 1024 tokens.', - }); - - baseArgs.thinking = { - type: 'enabled', - budget_tokens: 1024, - }; - - thinkingBudget = 1024; - } - - if (baseArgs.temperature != null) { - baseArgs.temperature = undefined; - warnings.push({ - type: 'unsupported', - feature: 'temperature', - details: 'temperature is not supported when thinking is enabled', - }); - } - - if (topK != null) { - baseArgs.top_k = undefined; - warnings.push({ - type: 'unsupported', - feature: 'topK', - details: 'topK is not supported when thinking is enabled', - }); - } - - if (topP != null) { - baseArgs.top_p = undefined; - warnings.push({ - type: 'unsupported', - feature: 'topP', - details: 'topP is not supported when thinking is enabled', - }); - } - - // adjust max tokens to account for thinking: - baseArgs.max_tokens = maxTokens + (thinkingBudget ?? 0); - } else { - // Only check temperature/topP mutual exclusivity when thinking is not enabled - if (topP != null && temperature != null) { - warnings.push({ - type: 'unsupported', - feature: 'topP', - details: `topP is not supported when temperature is set. topP is ignored.`, - }); - baseArgs.top_p = undefined; - } - } - - // limit to max output tokens for known models to enable model switching without breaking it: - if (isKnownModel && baseArgs.max_tokens > maxOutputTokensForModel) { - // only warn if max output tokens is provided as input: - if (maxOutputTokens != null) { - warnings.push({ - type: 'unsupported', - feature: 'maxOutputTokens', - details: - `${baseArgs.max_tokens} (maxOutputTokens + thinkingBudget) is greater than ${this.modelId} ${maxOutputTokensForModel} max output tokens. ` + - `The max output tokens have been limited to ${maxOutputTokensForModel}.`, - }); - } - baseArgs.max_tokens = maxOutputTokensForModel; - } - - if ( - anthropicOptions?.mcpServers && - anthropicOptions.mcpServers.length > 0 - ) { - betas.add('mcp-client-2025-04-04'); - } - - if (contextManagement) { - betas.add('context-management-2025-06-27'); - - // Add compaction beta if compact edit is present - if (contextManagement.edits.some(e => e.type === 'compact_20260112')) { - betas.add('compact-2026-01-12'); - } - } - - if ( - anthropicOptions?.container && - anthropicOptions.container.skills && - anthropicOptions.container.skills.length > 0 - ) { - betas.add('code-execution-2025-08-25'); - betas.add('skills-2025-10-02'); - betas.add('files-api-2025-04-14'); - - if ( - !tools?.some( - tool => - tool.type === 'provider' && - (tool.id === 'anthropic.code_execution_20250825' || - tool.id === 'anthropic.code_execution_20260120'), - ) - ) { - warnings.push({ - type: 'other', - message: 'code execution tool is required when using skills', - }); - } - } - - if (anthropicOptions?.effort) { - betas.add('effort-2025-11-24'); - } - - if (anthropicOptions?.speed === 'fast') { - betas.add('fast-mode-2026-02-01'); - } - - // only when streaming: enable fine-grained tool streaming - if (stream && (anthropicOptions?.toolStreaming ?? true)) { - betas.add('fine-grained-tool-streaming-2025-05-14'); - } - - const { - tools: anthropicTools, - toolChoice: anthropicToolChoice, - toolWarnings, - betas: toolsBetas, - } = await prepareTools( - jsonResponseTool != null - ? { - tools: [...(tools ?? []), jsonResponseTool], - toolChoice: { type: 'required' }, - disableParallelToolUse: true, - cacheControlValidator, - supportsStructuredOutput: false, - supportsStrictTools, - } - : { - tools: tools ?? [], - toolChoice, - disableParallelToolUse: anthropicOptions?.disableParallelToolUse, - cacheControlValidator, - supportsStructuredOutput, - supportsStrictTools, - }, - ); - - // Extract cache control warnings once at the end - const cacheWarnings = cacheControlValidator.getWarnings(); - - return { - args: { - ...baseArgs, - tools: anthropicTools, - tool_choice: anthropicToolChoice, - stream: stream === true ? true : undefined, // do not send when not streaming - }, - warnings: [...warnings, ...toolWarnings, ...cacheWarnings], - betas: new Set([ - ...betas, - ...toolsBetas, - ...userSuppliedBetas, - ...(anthropicOptions?.anthropicBeta ?? []), - ]), - usesJsonResponseTool: jsonResponseTool != null, - toolNameMapping, - providerOptionsName, - usedCustomProviderKey, - }; - } - - private async getHeaders({ - betas, - headers, - }: { - betas: Set; - headers: Record | undefined; - }) { - return combineHeaders( - await resolve(this.config.headers), - headers, - betas.size > 0 ? { 'anthropic-beta': Array.from(betas).join(',') } : {}, - ); - } - - private async getBetasFromHeaders( - requestHeaders: Record | undefined, - ) { - const configHeaders = await resolve(this.config.headers); - - const configBetaHeader = configHeaders['anthropic-beta'] ?? ''; - const requestBetaHeader = requestHeaders?.['anthropic-beta'] ?? ''; - - return new Set( - [ - ...configBetaHeader.toLowerCase().split(','), - ...requestBetaHeader.toLowerCase().split(','), - ] - .map(beta => beta.trim()) - .filter(beta => beta !== ''), - ); - } - - private buildRequestUrl(isStreaming: boolean): string { - return ( - this.config.buildRequestUrl?.(this.config.baseURL, isStreaming) ?? - `${this.config.baseURL}/messages` - ); - } - - private transformRequestBody( - args: Record, - betas: Set, - ): Record { - return this.config.transformRequestBody?.(args, betas) ?? args; - } - - private extractCitationDocuments(prompt: LanguageModelV3Prompt): Array<{ - title: string; - filename?: string; - mediaType: string; - }> { - const isCitationPart = (part: { - type: string; - mediaType?: string; - providerOptions?: { anthropic?: { citations?: { enabled?: boolean } } }; - }) => { - if (part.type !== 'file') { - return false; - } - - if ( - part.mediaType !== 'application/pdf' && - part.mediaType !== 'text/plain' - ) { - return false; - } - - const anthropic = part.providerOptions?.anthropic; - const citationsConfig = anthropic?.citations as - | { enabled?: boolean } - | undefined; - return citationsConfig?.enabled ?? false; - }; - - return prompt - .filter(message => message.role === 'user') - .flatMap(message => message.content) - .filter(isCitationPart) - .map(part => { - // TypeScript knows this is a file part due to our filter - const filePart = part as Extract; - return { - title: filePart.filename ?? 'Untitled Document', - filename: filePart.filename, - mediaType: filePart.mediaType, - }; - }); - } - - async doGenerate( - options: LanguageModelV3CallOptions, - ): Promise { - const { - args, - warnings, - betas, - usesJsonResponseTool, - toolNameMapping, - providerOptionsName, - usedCustomProviderKey, - } = await this.getArgs({ - ...options, - stream: false, - userSuppliedBetas: await this.getBetasFromHeaders(options.headers), - }); - - // Extract citation documents for response processing - const citationDocuments = [ - ...this.extractCitationDocuments(options.prompt), - ]; - - const markCodeExecutionDynamic = hasWebTool20260209WithoutCodeExecution( - args.tools, - ); - - const { - responseHeaders, - value: response, - rawValue: rawResponse, - } = await postJsonToApi({ - url: this.buildRequestUrl(false), - headers: await this.getHeaders({ betas, headers: options.headers }), - body: this.transformRequestBody(args, betas), - failedResponseHandler: anthropicFailedResponseHandler, - successfulResponseHandler: createJsonResponseHandler( - anthropicMessagesResponseSchema, - ), - abortSignal: options.abortSignal, - fetch: this.config.fetch, - }); - - const content: Array = []; - const mcpToolCalls: Record = {}; - const serverToolCalls: Record = {}; // tool_use_id -> provider tool name - let isJsonResponseFromTool = false; - - // map response content to content array - for (const part of response.content) { - switch (part.type) { - case 'text': { - if (!usesJsonResponseTool) { - content.push({ type: 'text', text: part.text }); - - // Process citations if present - if (part.citations) { - for (const citation of part.citations) { - const source = createCitationSource( - citation, - citationDocuments, - this.generateId, - ); - - if (source) { - content.push(source); - } - } - } - } - break; - } - case 'thinking': { - content.push({ - type: 'reasoning', - text: part.thinking, - providerMetadata: { - anthropic: { - signature: part.signature, - } satisfies AnthropicReasoningMetadata, - }, - }); - break; - } - case 'redacted_thinking': { - content.push({ - type: 'reasoning', - text: '', - providerMetadata: { - anthropic: { - redactedData: part.data, - } satisfies AnthropicReasoningMetadata, - }, - }); - break; - } - case 'compaction': { - content.push({ - type: 'text', - text: part.content, - providerMetadata: { - anthropic: { - type: 'compaction', - }, - }, - }); - break; - } - case 'tool_use': { - const isJsonResponseTool = - usesJsonResponseTool && part.name === 'json'; - - if (isJsonResponseTool) { - isJsonResponseFromTool = true; - - // when a json response tool is used, the tool call becomes the text: - content.push({ - type: 'text', - text: JSON.stringify(part.input), - }); - } else { - const caller = part.caller; - const callerInfo = caller - ? { - type: caller.type, - toolId: 'tool_id' in caller ? caller.tool_id : undefined, - } - : undefined; - - content.push({ - type: 'tool-call', - toolCallId: part.id, - toolName: part.name, - input: JSON.stringify(part.input), - ...(callerInfo && { - providerMetadata: { - anthropic: { - caller: callerInfo, - }, - }, - }), - }); - } - - break; - } - case 'server_tool_use': { - // code execution 20250825 needs mapping: - if ( - part.name === 'text_editor_code_execution' || - part.name === 'bash_code_execution' - ) { - content.push({ - type: 'tool-call', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName('code_execution'), - input: JSON.stringify({ type: part.name, ...part.input }), - providerExecuted: true, - }); - } else if ( - part.name === 'web_search' || - part.name === 'code_execution' || - part.name === 'web_fetch' - ) { - // For code_execution, inject 'programmatic-tool-call' type when input has { code } format - const inputToSerialize = - part.name === 'code_execution' && - part.input != null && - typeof part.input === 'object' && - 'code' in part.input && - !('type' in part.input) - ? { type: 'programmatic-tool-call', ...part.input } - : part.input; - - content.push({ - type: 'tool-call', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName(part.name), - input: JSON.stringify(inputToSerialize), - providerExecuted: true, - // We want this 'code_execution' tool call to be allowed even if the tool is not explicitly provided. - // Since the validation generally bypasses dynamic tools, we mark this specific tool as dynamic. - ...(markCodeExecutionDynamic && part.name === 'code_execution' - ? { dynamic: true } - : {}), - }); - } else if ( - part.name === 'tool_search_tool_regex' || - part.name === 'tool_search_tool_bm25' - ) { - serverToolCalls[part.id] = part.name; - content.push({ - type: 'tool-call', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName(part.name), - input: JSON.stringify(part.input), - providerExecuted: true, - }); - } - - break; - } - case 'mcp_tool_use': { - mcpToolCalls[part.id] = { - type: 'tool-call', - toolCallId: part.id, - toolName: part.name, - input: JSON.stringify(part.input), - providerExecuted: true, - dynamic: true, - providerMetadata: { - anthropic: { - type: 'mcp-tool-use', - serverName: part.server_name, - }, - }, - }; - content.push(mcpToolCalls[part.id]); - break; - } - case 'mcp_tool_result': { - content.push({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: mcpToolCalls[part.tool_use_id].toolName, - isError: part.is_error, - result: part.content, - dynamic: true, - providerMetadata: mcpToolCalls[part.tool_use_id].providerMetadata, - }); - break; - } - case 'web_fetch_tool_result': { - if (part.content.type === 'web_fetch_result') { - citationDocuments.push({ - title: part.content.content.title ?? part.content.url, - mediaType: part.content.content.source.media_type, - }); - content.push({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName('web_fetch'), - result: { - type: 'web_fetch_result', - url: part.content.url, - retrievedAt: part.content.retrieved_at, - content: { - type: part.content.content.type, - title: part.content.content.title, - citations: part.content.content.citations, - source: { - type: part.content.content.source.type, - mediaType: part.content.content.source.media_type, - data: part.content.content.source.data, - }, - }, - }, - }); - } else if (part.content.type === 'web_fetch_tool_result_error') { - content.push({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName('web_fetch'), - isError: true, - result: { - type: 'web_fetch_tool_result_error', - errorCode: part.content.error_code, - }, - }); - } - break; - } - case 'web_search_tool_result': { - if (Array.isArray(part.content)) { - content.push({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName('web_search'), - result: part.content.map(result => ({ - url: result.url, - title: result.title, - pageAge: result.page_age ?? null, - encryptedContent: result.encrypted_content, - type: result.type, - })), - }); - - for (const result of part.content) { - content.push({ - type: 'source', - sourceType: 'url', - id: this.generateId(), - url: result.url, - title: result.title, - providerMetadata: { - anthropic: { - pageAge: result.page_age ?? null, - }, - }, - }); - } - } else { - content.push({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName('web_search'), - isError: true, - result: { - type: 'web_search_tool_result_error', - errorCode: part.content.error_code, - }, - }); - } - break; - } - - // code execution 20250522: - case 'code_execution_tool_result': { - if (part.content.type === 'code_execution_result') { - content.push({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName('code_execution'), - result: { - type: part.content.type, - stdout: part.content.stdout, - stderr: part.content.stderr, - return_code: part.content.return_code, - content: part.content.content ?? [], - }, - }); - } else if (part.content.type === 'encrypted_code_execution_result') { - content.push({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName('code_execution'), - result: { - type: part.content.type, - encrypted_stdout: part.content.encrypted_stdout, - stderr: part.content.stderr, - return_code: part.content.return_code, - content: part.content.content ?? [], - }, - }); - } else if (part.content.type === 'code_execution_tool_result_error') { - content.push({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName('code_execution'), - isError: true, - result: { - type: 'code_execution_tool_result_error', - errorCode: part.content.error_code, - }, - }); - } - break; - } - - // code execution 20250825: - case 'bash_code_execution_tool_result': - case 'text_editor_code_execution_tool_result': { - content.push({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName('code_execution'), - result: part.content, - }); - break; - } - - // tool search tool results: - case 'tool_search_tool_result': { - let providerToolName = serverToolCalls[part.tool_use_id]; - - if (providerToolName == null) { - const bm25CustomName = toolNameMapping.toCustomToolName( - 'tool_search_tool_bm25', - ); - const regexCustomName = toolNameMapping.toCustomToolName( - 'tool_search_tool_regex', - ); - - if (bm25CustomName !== 'tool_search_tool_bm25') { - providerToolName = 'tool_search_tool_bm25'; - } else if (regexCustomName !== 'tool_search_tool_regex') { - providerToolName = 'tool_search_tool_regex'; - } else { - providerToolName = 'tool_search_tool_regex'; - } - } - - if (part.content.type === 'tool_search_tool_search_result') { - content.push({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName(providerToolName), - result: part.content.tool_references.map(ref => ({ - type: ref.type, - toolName: ref.tool_name, - })), - }); - } else { - content.push({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName(providerToolName), - isError: true, - result: { - type: 'tool_search_tool_result_error', - errorCode: part.content.error_code, - }, - }); - } - break; - } - } - } - - return { - content, - finishReason: { - unified: mapAnthropicStopReason({ - finishReason: response.stop_reason, - isJsonResponseFromTool, - }), - raw: response.stop_reason ?? undefined, - }, - usage: convertAnthropicMessagesUsage({ usage: response.usage }), - request: { body: args }, - response: { - id: response.id ?? undefined, - modelId: response.model ?? undefined, - headers: responseHeaders, - body: rawResponse, - }, - warnings, - providerMetadata: (() => { - const anthropicMetadata = { - usage: response.usage as JSONObject, - cacheCreationInputTokens: - response.usage.cache_creation_input_tokens ?? null, - stopSequence: response.stop_sequence ?? null, - - iterations: response.usage.iterations - ? response.usage.iterations.map(iter => ({ - type: iter.type, - inputTokens: iter.input_tokens, - outputTokens: iter.output_tokens, - })) - : null, - container: response.container - ? { - expiresAt: response.container.expires_at, - id: response.container.id, - skills: - response.container.skills?.map(skill => ({ - type: skill.type, - skillId: skill.skill_id, - version: skill.version, - })) ?? null, - } - : null, - contextManagement: - mapAnthropicResponseContextManagement( - response.context_management, - ) ?? null, - } satisfies AnthropicMessageMetadata; - - const providerMetadata: SharedV3ProviderMetadata = { - anthropic: anthropicMetadata, - }; - - if (usedCustomProviderKey && providerOptionsName !== 'anthropic') { - providerMetadata[providerOptionsName] = anthropicMetadata; - } - - return providerMetadata; - })(), - }; - } - - async doStream( - options: LanguageModelV3CallOptions, - ): Promise { - const { - args: body, - warnings, - betas, - usesJsonResponseTool, - toolNameMapping, - providerOptionsName, - usedCustomProviderKey, - } = await this.getArgs({ - ...options, - stream: true, - userSuppliedBetas: await this.getBetasFromHeaders(options.headers), - }); - - // Extract citation documents for response processing - const citationDocuments = [ - ...this.extractCitationDocuments(options.prompt), - ]; - - const markCodeExecutionDynamic = hasWebTool20260209WithoutCodeExecution( - body.tools, - ); - - const url = this.buildRequestUrl(true); - const { responseHeaders, value: response } = await postJsonToApi({ - url, - headers: await this.getHeaders({ betas, headers: options.headers }), - body: this.transformRequestBody(body, betas), - failedResponseHandler: anthropicFailedResponseHandler, - successfulResponseHandler: createEventSourceResponseHandler( - anthropicMessagesChunkSchema, - ), - abortSignal: options.abortSignal, - fetch: this.config.fetch, - }); - - let finishReason: LanguageModelV3FinishReason = { - unified: 'other', - raw: undefined, - }; - const usage: AnthropicMessagesUsage = { - input_tokens: 0, - output_tokens: 0, - cache_creation_input_tokens: 0, - cache_read_input_tokens: 0, - iterations: null, - }; - - const contentBlocks: Record< - number, - | { - type: 'tool-call'; - toolCallId: string; - toolName: string; - input: string; - providerExecuted?: boolean; - firstDelta: boolean; - providerToolName?: string; - caller?: { - type: - | 'code_execution_20250825' - | 'code_execution_20260120' - | 'direct'; - toolId?: string; - }; - } - | { type: 'text' | 'reasoning' } - > = {}; - const mcpToolCalls: Record = {}; - const serverToolCalls: Record = {}; // tool_use_id -> provider tool name - - let contextManagement: - | AnthropicMessageMetadata['contextManagement'] - | null = null; - let rawUsage: JSONObject | undefined = undefined; - let cacheCreationInputTokens: number | null = null; - let stopSequence: string | null = null; - let container: AnthropicMessageMetadata['container'] | null = null; - let isJsonResponseFromTool = false; - - let blockType: - | 'text' - | 'thinking' - | 'tool_use' - | 'redacted_thinking' - | 'server_tool_use' - | 'web_fetch_tool_result' - | 'web_search_tool_result' - | 'code_execution_tool_result' - | 'text_editor_code_execution_tool_result' - | 'bash_code_execution_tool_result' - | 'tool_search_tool_result' - | 'mcp_tool_use' - | 'mcp_tool_result' - | 'compaction' - | undefined = undefined; - - const generateId = this.generateId; - - const transformedStream = response.pipeThrough( - new TransformStream< - ParseResult>, - LanguageModelV3StreamPart - >({ - start(controller) { - controller.enqueue({ type: 'stream-start', warnings }); - }, - - transform(chunk, controller) { - if (options.includeRawChunks) { - controller.enqueue({ type: 'raw', rawValue: chunk.rawValue }); - } - - if (!chunk.success) { - controller.enqueue({ type: 'error', error: chunk.error }); - return; - } - - const value = chunk.value; - - switch (value.type) { - case 'ping': { - return; // ignored - } - - case 'content_block_start': { - const part = value.content_block; - const contentBlockType = part.type; - blockType = contentBlockType; - - switch (contentBlockType) { - case 'text': { - // when a json response tool is used, the tool call is returned as text, - // so we ignore the text content: - if (usesJsonResponseTool) { - return; - } - - contentBlocks[value.index] = { type: 'text' }; - controller.enqueue({ - type: 'text-start', - id: String(value.index), - }); - return; - } - - case 'thinking': { - contentBlocks[value.index] = { type: 'reasoning' }; - controller.enqueue({ - type: 'reasoning-start', - id: String(value.index), - }); - return; - } - - case 'redacted_thinking': { - contentBlocks[value.index] = { type: 'reasoning' }; - controller.enqueue({ - type: 'reasoning-start', - id: String(value.index), - providerMetadata: { - anthropic: { - redactedData: part.data, - } satisfies AnthropicReasoningMetadata, - }, - }); - return; - } - - case 'compaction': { - contentBlocks[value.index] = { type: 'text' }; - controller.enqueue({ - type: 'text-start', - id: String(value.index), - providerMetadata: { - anthropic: { - type: 'compaction', - }, - }, - }); - return; - } - - case 'tool_use': { - const isJsonResponseTool = - usesJsonResponseTool && part.name === 'json'; - - if (isJsonResponseTool) { - isJsonResponseFromTool = true; - - contentBlocks[value.index] = { type: 'text' }; - - controller.enqueue({ - type: 'text-start', - id: String(value.index), - }); - } else { - // Extract caller info for type-safe access - const caller = part.caller; - const callerInfo = caller - ? { - type: caller.type, - toolId: - 'tool_id' in caller ? caller.tool_id : undefined, - } - : undefined; - - // Programmatic tool calling: for deferred tool calls from code_execution, - // input may be present directly in content_block_start. - // Only use if non-empty (empty {} means input comes via deltas) - const hasNonEmptyInput = - part.input && Object.keys(part.input).length > 0; - const initialInput = hasNonEmptyInput - ? JSON.stringify(part.input) - : ''; - - contentBlocks[value.index] = { - type: 'tool-call', - toolCallId: part.id, - toolName: part.name, - input: initialInput, - firstDelta: initialInput.length === 0, - ...(callerInfo && { caller: callerInfo }), - }; - - controller.enqueue({ - type: 'tool-input-start', - id: part.id, - toolName: part.name, - }); - } - return; - } - - case 'server_tool_use': { - if ( - [ - 'web_fetch', - 'web_search', - // code execution 20250825: - 'code_execution', - // code execution 20250825 text editor: - 'text_editor_code_execution', - // code execution 20250825 bash: - 'bash_code_execution', - ].includes(part.name) - ) { - // map tool names for the code execution 20250825 tool: - const providerToolName = - part.name === 'text_editor_code_execution' || - part.name === 'bash_code_execution' - ? 'code_execution' - : part.name; - - const customToolName = - toolNameMapping.toCustomToolName(providerToolName); - - // Tools like 'web_fetch_20260209' provide input data here. - // Other tools like 'code_execution_20260120' provide input data via deltas. - // So we only use this if it's non-empty to avoid conflicts. - const finalInput = - part.input != null && - typeof part.input === 'object' && - Object.keys(part.input).length > 0 - ? JSON.stringify(part.input) - : ''; - - contentBlocks[value.index] = { - type: 'tool-call', - toolCallId: part.id, - toolName: customToolName, - input: finalInput, - providerExecuted: true, - ...(markCodeExecutionDynamic && - providerToolName === 'code_execution' - ? { dynamic: true } - : {}), - firstDelta: true, - providerToolName: part.name, - }; - - controller.enqueue({ - type: 'tool-input-start', - id: part.id, - toolName: customToolName, - providerExecuted: true, - ...(markCodeExecutionDynamic && - providerToolName === 'code_execution' - ? { dynamic: true } - : {}), - }); - } else if ( - part.name === 'tool_search_tool_regex' || - part.name === 'tool_search_tool_bm25' - ) { - serverToolCalls[part.id] = part.name; - const customToolName = toolNameMapping.toCustomToolName( - part.name, - ); - - contentBlocks[value.index] = { - type: 'tool-call', - toolCallId: part.id, - toolName: customToolName, - input: '', - providerExecuted: true, - firstDelta: true, - providerToolName: part.name, - }; - - controller.enqueue({ - type: 'tool-input-start', - id: part.id, - toolName: customToolName, - providerExecuted: true, - }); - } - - return; - } - - case 'web_fetch_tool_result': { - if (part.content.type === 'web_fetch_result') { - citationDocuments.push({ - title: part.content.content.title ?? part.content.url, - mediaType: part.content.content.source.media_type, - }); - controller.enqueue({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName('web_fetch'), - result: { - type: 'web_fetch_result', - url: part.content.url, - retrievedAt: part.content.retrieved_at, - content: { - type: part.content.content.type, - title: part.content.content.title, - citations: part.content.content.citations, - source: { - type: part.content.content.source.type, - mediaType: part.content.content.source.media_type, - data: part.content.content.source.data, - }, - }, - }, - }); - } else if ( - part.content.type === 'web_fetch_tool_result_error' - ) { - controller.enqueue({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName('web_fetch'), - isError: true, - result: { - type: 'web_fetch_tool_result_error', - errorCode: part.content.error_code, - }, - }); - } - - return; - } - - case 'web_search_tool_result': { - if (Array.isArray(part.content)) { - controller.enqueue({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName('web_search'), - result: part.content.map(result => ({ - url: result.url, - title: result.title, - pageAge: result.page_age ?? null, - encryptedContent: result.encrypted_content, - type: result.type, - })), - }); - - for (const result of part.content) { - controller.enqueue({ - type: 'source', - sourceType: 'url', - id: generateId(), - url: result.url, - title: result.title, - providerMetadata: { - anthropic: { - pageAge: result.page_age ?? null, - }, - }, - }); - } - } else { - controller.enqueue({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: toolNameMapping.toCustomToolName('web_search'), - isError: true, - result: { - type: 'web_search_tool_result_error', - errorCode: part.content.error_code, - }, - }); - } - return; - } - - // code execution 20250522: - case 'code_execution_tool_result': { - if (part.content.type === 'code_execution_result') { - controller.enqueue({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: - toolNameMapping.toCustomToolName('code_execution'), - result: { - type: part.content.type, - stdout: part.content.stdout, - stderr: part.content.stderr, - return_code: part.content.return_code, - content: part.content.content ?? [], - }, - }); - } else if ( - part.content.type === 'encrypted_code_execution_result' - ) { - controller.enqueue({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: - toolNameMapping.toCustomToolName('code_execution'), - result: { - type: part.content.type, - encrypted_stdout: part.content.encrypted_stdout, - stderr: part.content.stderr, - return_code: part.content.return_code, - content: part.content.content ?? [], - }, - }); - } else if ( - part.content.type === 'code_execution_tool_result_error' - ) { - controller.enqueue({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: - toolNameMapping.toCustomToolName('code_execution'), - isError: true, - result: { - type: 'code_execution_tool_result_error', - errorCode: part.content.error_code, - }, - }); - } - - return; - } - - // code execution 20250825: - case 'bash_code_execution_tool_result': - case 'text_editor_code_execution_tool_result': { - controller.enqueue({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: - toolNameMapping.toCustomToolName('code_execution'), - result: part.content, - }); - return; - } - - // tool search tool results: - case 'tool_search_tool_result': { - let providerToolName = serverToolCalls[part.tool_use_id]; - - if (providerToolName == null) { - const bm25CustomName = toolNameMapping.toCustomToolName( - 'tool_search_tool_bm25', - ); - const regexCustomName = toolNameMapping.toCustomToolName( - 'tool_search_tool_regex', - ); - - if (bm25CustomName !== 'tool_search_tool_bm25') { - providerToolName = 'tool_search_tool_bm25'; - } else if (regexCustomName !== 'tool_search_tool_regex') { - providerToolName = 'tool_search_tool_regex'; - } else { - providerToolName = 'tool_search_tool_regex'; - } - } - - if (part.content.type === 'tool_search_tool_search_result') { - controller.enqueue({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: - toolNameMapping.toCustomToolName(providerToolName), - result: part.content.tool_references.map(ref => ({ - type: ref.type, - toolName: ref.tool_name, - })), - }); - } else { - controller.enqueue({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: - toolNameMapping.toCustomToolName(providerToolName), - isError: true, - result: { - type: 'tool_search_tool_result_error', - errorCode: part.content.error_code, - }, - }); - } - return; - } - - case 'mcp_tool_use': { - mcpToolCalls[part.id] = { - type: 'tool-call', - toolCallId: part.id, - toolName: part.name, - input: JSON.stringify(part.input), - providerExecuted: true, - dynamic: true, - providerMetadata: { - anthropic: { - type: 'mcp-tool-use', - serverName: part.server_name, - }, - }, - }; - controller.enqueue(mcpToolCalls[part.id]); - return; - } - - case 'mcp_tool_result': { - controller.enqueue({ - type: 'tool-result', - toolCallId: part.tool_use_id, - toolName: mcpToolCalls[part.tool_use_id].toolName, - isError: part.is_error, - result: part.content, - dynamic: true, - providerMetadata: - mcpToolCalls[part.tool_use_id].providerMetadata, - }); - return; - } - - default: { - const _exhaustiveCheck: never = contentBlockType; - throw new Error( - `Unsupported content block type: ${_exhaustiveCheck}`, - ); - } - } - } - - case 'content_block_stop': { - // when finishing a tool call block, send the full tool call: - if (contentBlocks[value.index] != null) { - const contentBlock = contentBlocks[value.index]; - - switch (contentBlock.type) { - case 'text': { - controller.enqueue({ - type: 'text-end', - id: String(value.index), - }); - break; - } - - case 'reasoning': { - controller.enqueue({ - type: 'reasoning-end', - id: String(value.index), - }); - break; - } - - case 'tool-call': - // when a json response tool is used, the tool call is returned as text, - // so we ignore the tool call content: - const isJsonResponseTool = - usesJsonResponseTool && contentBlock.toolName === 'json'; - - if (!isJsonResponseTool) { - controller.enqueue({ - type: 'tool-input-end', - id: contentBlock.toolCallId, - }); - - // For code_execution, inject 'programmatic-tool-call' type - // when input has { code } format (programmatic tool calling) - let finalInput = - contentBlock.input === '' ? '{}' : contentBlock.input; - if (contentBlock.providerToolName === 'code_execution') { - try { - const parsed = JSON.parse(finalInput); - if ( - parsed != null && - typeof parsed === 'object' && - 'code' in parsed && - !('type' in parsed) - ) { - finalInput = JSON.stringify({ - type: 'programmatic-tool-call', - ...parsed, - }); - } - } catch { - // ignore parse errors, use original input - } - } - - controller.enqueue({ - type: 'tool-call', - toolCallId: contentBlock.toolCallId, - toolName: contentBlock.toolName, - input: finalInput, - providerExecuted: contentBlock.providerExecuted, - ...(markCodeExecutionDynamic && - contentBlock.providerToolName === 'code_execution' - ? { dynamic: true } - : {}), - ...(contentBlock.caller && { - providerMetadata: { - anthropic: { - caller: contentBlock.caller, - }, - }, - }), - }); - } - break; - } - - delete contentBlocks[value.index]; - } - - blockType = undefined; // reset block type - - return; - } - - case 'content_block_delta': { - const deltaType = value.delta.type; - - switch (deltaType) { - case 'text_delta': { - // when a json response tool is used, the tool call is returned as text, - // so we ignore the text content: - if (usesJsonResponseTool) { - return; // excluding the text-start will also exclude the text-end - } - - controller.enqueue({ - type: 'text-delta', - id: String(value.index), - delta: value.delta.text, - }); - - return; - } - - case 'thinking_delta': { - controller.enqueue({ - type: 'reasoning-delta', - id: String(value.index), - delta: value.delta.thinking, - }); - - return; - } - - case 'signature_delta': { - // signature are only supported on thinking blocks: - if (blockType === 'thinking') { - controller.enqueue({ - type: 'reasoning-delta', - id: String(value.index), - delta: '', - providerMetadata: { - anthropic: { - signature: value.delta.signature, - } satisfies AnthropicReasoningMetadata, - }, - }); - } - - return; - } - - case 'compaction_delta': { - if (value.delta.content != null) { - controller.enqueue({ - type: 'text-delta', - id: String(value.index), - delta: value.delta.content, - }); - } - - return; - } - - case 'input_json_delta': { - const contentBlock = contentBlocks[value.index]; - let delta = value.delta.partial_json; - - // skip empty deltas to enable replacing the first character - // in the code execution 20250825 tool. - if (delta.length === 0) { - return; - } - - if (isJsonResponseFromTool) { - if (contentBlock?.type !== 'text') { - return; // exclude reasoning - } - - controller.enqueue({ - type: 'text-delta', - id: String(value.index), - delta, - }); - } else { - if (contentBlock?.type !== 'tool-call') { - return; - } - - // for the code execution 20250825, we need to add - // the type to the delta and change the tool name. - if ( - contentBlock.firstDelta && - (contentBlock.providerToolName === - 'bash_code_execution' || - contentBlock.providerToolName === - 'text_editor_code_execution') - ) { - delta = `{"type": "${contentBlock.providerToolName}",${delta.substring(1)}`; - } - - controller.enqueue({ - type: 'tool-input-delta', - id: contentBlock.toolCallId, - delta, - }); - - contentBlock.input += delta; - contentBlock.firstDelta = false; - } - - return; - } - - case 'citations_delta': { - const citation = value.delta.citation; - const source = createCitationSource( - citation, - citationDocuments, - generateId, - ); - - if (source) { - controller.enqueue(source); - } - - return; - } - - default: { - const _exhaustiveCheck: never = deltaType; - throw new Error( - `Unsupported delta type: ${_exhaustiveCheck}`, - ); - } - } - } - - case 'message_start': { - usage.input_tokens = value.message.usage.input_tokens; - usage.cache_read_input_tokens = - value.message.usage.cache_read_input_tokens ?? 0; - usage.cache_creation_input_tokens = - value.message.usage.cache_creation_input_tokens ?? 0; - - rawUsage = { - ...(value.message.usage as JSONObject), - }; - - cacheCreationInputTokens = - value.message.usage.cache_creation_input_tokens ?? null; - - if (value.message.container != null) { - container = { - expiresAt: value.message.container.expires_at, - id: value.message.container.id, - skills: null, - }; - } - - if (value.message.stop_reason != null) { - finishReason = { - unified: mapAnthropicStopReason({ - finishReason: value.message.stop_reason, - isJsonResponseFromTool, - }), - raw: value.message.stop_reason, - }; - } - - controller.enqueue({ - type: 'response-metadata', - id: value.message.id ?? undefined, - modelId: value.message.model ?? undefined, - }); - - // Programmatic tool calling: process pre-populated content blocks - // (for deferred tool calls, content may be in message_start) - if (value.message.content != null) { - for ( - let contentIndex = 0; - contentIndex < value.message.content.length; - contentIndex++ - ) { - const part = value.message.content[contentIndex]; - if (part.type === 'tool_use') { - const caller = part.caller; - const callerInfo = caller - ? { - type: caller.type, - toolId: - 'tool_id' in caller ? caller.tool_id : undefined, - } - : undefined; - - controller.enqueue({ - type: 'tool-input-start', - id: part.id, - toolName: part.name, - }); - - const inputStr = JSON.stringify(part.input ?? {}); - controller.enqueue({ - type: 'tool-input-delta', - id: part.id, - delta: inputStr, - }); - - controller.enqueue({ - type: 'tool-input-end', - id: part.id, - }); - - controller.enqueue({ - type: 'tool-call', - toolCallId: part.id, - toolName: part.name, - input: inputStr, - ...(callerInfo && { - providerMetadata: { - anthropic: { - caller: callerInfo, - }, - }, - }), - }); - } - } - } - - return; - } - - case 'message_delta': { - if ( - value.usage.input_tokens != null && - usage.input_tokens !== value.usage.input_tokens - ) { - usage.input_tokens = value.usage.input_tokens; - } - usage.output_tokens = value.usage.output_tokens; - - if (value.usage.cache_read_input_tokens != null) { - usage.cache_read_input_tokens = - value.usage.cache_read_input_tokens; - } - if (value.usage.cache_creation_input_tokens != null) { - usage.cache_creation_input_tokens = - value.usage.cache_creation_input_tokens; - cacheCreationInputTokens = - value.usage.cache_creation_input_tokens; - } - if (value.usage.iterations != null) { - usage.iterations = value.usage.iterations; - } - - finishReason = { - unified: mapAnthropicStopReason({ - finishReason: value.delta.stop_reason, - isJsonResponseFromTool, - }), - raw: value.delta.stop_reason ?? undefined, - }; - - stopSequence = value.delta.stop_sequence ?? null; - container = - value.delta.container != null - ? { - expiresAt: value.delta.container.expires_at, - id: value.delta.container.id, - skills: - value.delta.container.skills?.map(skill => ({ - type: skill.type, - skillId: skill.skill_id, - version: skill.version, - })) ?? null, - } - : null; - - if (value.context_management) { - contextManagement = mapAnthropicResponseContextManagement( - value.context_management, - ); - } - - rawUsage = { - ...rawUsage, - ...(value.usage as JSONObject), - }; - - return; - } - - case 'message_stop': { - const anthropicMetadata = { - usage: (rawUsage as JSONObject) ?? null, - cacheCreationInputTokens, - stopSequence, - iterations: usage.iterations - ? usage.iterations.map(iter => ({ - type: iter.type, - inputTokens: iter.input_tokens, - outputTokens: iter.output_tokens, - })) - : null, - container, - contextManagement, - } satisfies AnthropicMessageMetadata; - - const providerMetadata: SharedV3ProviderMetadata = { - anthropic: anthropicMetadata, - }; - - if ( - usedCustomProviderKey && - providerOptionsName !== 'anthropic' - ) { - providerMetadata[providerOptionsName] = anthropicMetadata; - } - - controller.enqueue({ - type: 'finish', - finishReason, - usage: convertAnthropicMessagesUsage({ usage, rawUsage }), - providerMetadata, - }); - return; - } - - case 'error': { - controller.enqueue({ type: 'error', error: value.error }); - return; - } - - default: { - const _exhaustiveCheck: never = value; - throw new Error(`Unsupported chunk type: ${_exhaustiveCheck}`); - } - } - }, - }), - ); - - // The first chunk needs to be pulled immediately to check if it is an error - const [streamForFirstChunk, streamForConsumer] = transformedStream.tee(); - - const firstChunkReader = streamForFirstChunk.getReader(); - try { - await firstChunkReader.read(); // streamStart comes first, ignored - - let result = await firstChunkReader.read(); - - // when raw chunks are enabled, the first chunk is a raw chunk, so we need to read the next chunk - if (result.value?.type === 'raw') { - result = await firstChunkReader.read(); - } - - // The Anthropic API returns 200 responses when there are overloaded errors. - // We handle the case where the first chunk is an error here and transform - // it into an APICallError. - if (result.value?.type === 'error') { - const error = result.value.error as { message: string; type: string }; - - throw new APICallError({ - message: error.message, - url, - requestBodyValues: body, - statusCode: error.type === 'overloaded_error' ? 529 : 500, - responseHeaders, - responseBody: JSON.stringify(error), - isRetryable: error.type === 'overloaded_error', - }); - } - } finally { - firstChunkReader.cancel().catch(() => {}); - firstChunkReader.releaseLock(); - } - - return { - stream: streamForConsumer, - request: { body }, - response: { headers: responseHeaders }, - }; - } -} - -/** - * Returns the capabilities of a Claude model that are used for defaults and feature selection. - * - * @see https://docs.claude.com/en/docs/about-claude/models/overview#model-comparison-table - * @see https://platform.claude.com/docs/en/build-with-claude/structured-outputs - */ -function getModelCapabilities(modelId: string): { - maxOutputTokens: number; - supportsStructuredOutput: boolean; - isKnownModel: boolean; -} { - if ( - modelId.includes('claude-sonnet-4-6') || - modelId.includes('claude-opus-4-6') - ) { - return { - maxOutputTokens: 128000, - supportsStructuredOutput: true, - isKnownModel: true, - }; - } else if ( - modelId.includes('claude-sonnet-4-5') || - modelId.includes('claude-opus-4-5') || - modelId.includes('claude-haiku-4-5') - ) { - return { - maxOutputTokens: 64000, - supportsStructuredOutput: true, - isKnownModel: true, - }; - } else if (modelId.includes('claude-opus-4-1')) { - return { - maxOutputTokens: 32000, - supportsStructuredOutput: true, - isKnownModel: true, - }; - } else if (modelId.includes('claude-sonnet-4-')) { - return { - maxOutputTokens: 64000, - supportsStructuredOutput: false, - isKnownModel: true, - }; - } else if (modelId.includes('claude-opus-4-')) { - return { - maxOutputTokens: 32000, - supportsStructuredOutput: false, - isKnownModel: true, - }; - } else if (modelId.includes('claude-3-haiku')) { - return { - maxOutputTokens: 4096, - supportsStructuredOutput: false, - isKnownModel: true, - }; - } else { - return { - maxOutputTokens: 4096, - supportsStructuredOutput: false, - isKnownModel: false, - }; - } -} - -function hasWebTool20260209WithoutCodeExecution( - tools: AnthropicTool[] | undefined, -): boolean { - if (!tools) { - return false; - } - let hasWebTool20260209 = false; - let hasCodeExecutionTool = false; - for (const tool of tools) { - if ( - 'type' in tool && - (tool.type === 'web_fetch_20260209' || - tool.type === 'web_search_20260209') - ) { - hasWebTool20260209 = true; - continue; - } - if (tool.name === 'code_execution') { - hasCodeExecutionTool = true; - break; - } - } - return hasWebTool20260209 && !hasCodeExecutionTool; -} - -function mapAnthropicResponseContextManagement( - contextManagement: AnthropicResponseContextManagement | null | undefined, -): AnthropicMessageMetadata['contextManagement'] | null { - return contextManagement - ? { - appliedEdits: contextManagement.applied_edits - .map(edit => { - const strategy = edit.type; - - switch (strategy) { - case 'clear_tool_uses_20250919': - return { - type: edit.type, - clearedToolUses: edit.cleared_tool_uses, - clearedInputTokens: edit.cleared_input_tokens, - }; - - case 'clear_thinking_20251015': - return { - type: edit.type, - clearedThinkingTurns: edit.cleared_thinking_turns, - clearedInputTokens: edit.cleared_input_tokens, - }; - - case 'compact_20260112': - return { - type: edit.type, - }; - } - }) - .filter(edit => edit !== undefined), - } - : null; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-messages-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-messages-options.ts deleted file mode 100644 index 34e7530e0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-messages-options.ts +++ /dev/null @@ -1,263 +0,0 @@ -import { z } from 'zod/v4'; - -// https://docs.claude.com/en/docs/about-claude/models/overview -export type AnthropicMessagesModelId = - | 'claude-3-haiku-20240307' - | 'claude-haiku-4-5-20251001' - | 'claude-haiku-4-5' - | 'claude-opus-4-0' - | 'claude-opus-4-20250514' - | 'claude-opus-4-1-20250805' - | 'claude-opus-4-1' - | 'claude-opus-4-5' - | 'claude-opus-4-5-20251101' - | 'claude-sonnet-4-0' - | 'claude-sonnet-4-20250514' - | 'claude-sonnet-4-5-20250929' - | 'claude-sonnet-4-5' - | 'claude-sonnet-4-6' - | 'claude-opus-4-6' - | (string & {}); - -/** - * Anthropic file part provider options for document-specific features. - * These options apply to individual file parts (documents). - */ -export const anthropicFilePartProviderOptions = z.object({ - /** - * Citation configuration for this document. - * When enabled, this document will generate citations in the response. - */ - citations: z - .object({ - /** - * Enable citations for this document - */ - enabled: z.boolean(), - }) - .optional(), - - /** - * Custom title for the document. - * If not provided, the filename will be used. - */ - title: z.string().optional(), - - /** - * Context about the document that will be passed to the model - * but not used towards cited content. - * Useful for storing document metadata as text or stringified JSON. - */ - context: z.string().optional(), -}); - -export type AnthropicFilePartProviderOptions = z.infer< - typeof anthropicFilePartProviderOptions ->; - -export const anthropicLanguageModelOptions = z.object({ - /** - * Whether to send reasoning to the model. - * - * This allows you to deactivate reasoning inputs for models that do not support them. - */ - sendReasoning: z.boolean().optional(), - - /** - * Determines how structured outputs are generated. - * - * - `outputFormat`: Use the `output_config.format` parameter to specify the structured output format. - * - `jsonTool`: Use a special 'json' tool to specify the structured output format. - * - `auto`: Use 'outputFormat' when supported, otherwise use 'jsonTool' (default). - */ - structuredOutputMode: z.enum(['outputFormat', 'jsonTool', 'auto']).optional(), - - /** - * Configuration for enabling Claude's extended thinking. - * - * When enabled, responses include thinking content blocks showing Claude's thinking process before the final answer. - * Requires a minimum budget of 1,024 tokens and counts towards the `max_tokens` limit. - */ - thinking: z - .discriminatedUnion('type', [ - z.object({ - /** for Sonnet 4.6, Opus 4.6, and newer models */ - type: z.literal('adaptive'), - }), - z.object({ - /** for models before Opus 4.6, except Sonnet 4.6 still supports it */ - type: z.literal('enabled'), - budgetTokens: z.number().optional(), - }), - z.object({ - type: z.literal('disabled'), - }), - ]) - .optional(), - - /** - * Whether to disable parallel function calling during tool use. Default is false. - * When set to true, Claude will use at most one tool per response. - */ - disableParallelToolUse: z.boolean().optional(), - - /** - * Cache control settings for this message. - * See https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching - */ - cacheControl: z - .object({ - type: z.literal('ephemeral'), - ttl: z.union([z.literal('5m'), z.literal('1h')]).optional(), - }) - .optional(), - - /** - * Metadata to include with the request. - * - * See https://platform.claude.com/docs/en/api/messages/create for details. - */ - metadata: z - .object({ - /** - * An external identifier for the user associated with the request. - * - * Should be a UUID, hash value, or other opaque identifier. - * Must not contain PII (name, email, phone number, etc.). - */ - userId: z.string().optional(), - }) - .optional(), - - /** - * MCP servers to be utilized in this request. - */ - mcpServers: z - .array( - z.object({ - type: z.literal('url'), - name: z.string(), - url: z.string(), - authorizationToken: z.string().nullish(), - toolConfiguration: z - .object({ - enabled: z.boolean().nullish(), - allowedTools: z.array(z.string()).nullish(), - }) - .nullish(), - }), - ) - .optional(), - - /** - * Agent Skills configuration. Skills enable Claude to perform specialized tasks - * like document processing (PPTX, DOCX, PDF, XLSX) and data analysis. - * Requires code execution tool to be enabled. - */ - container: z - .object({ - id: z.string().optional(), - skills: z - .array( - z.object({ - type: z.union([z.literal('anthropic'), z.literal('custom')]), - skillId: z.string(), - version: z.string().optional(), - }), - ) - .optional(), - }) - .optional(), - - /** - * Whether to enable tool streaming (and structured output streaming). - * - * When set to false, the model will return all tool calls and results - * at once after a delay. - * - * @default true - */ - toolStreaming: z.boolean().optional(), - - /** - * @default 'high' - */ - effort: z.enum(['low', 'medium', 'high', 'max']).optional(), - - /** - * Enable fast mode for faster inference (2.5x faster output token speeds). - * Only supported with claude-opus-4-6. - */ - speed: z.enum(['fast', 'standard']).optional(), - - /** - * A set of beta features to enable. - * Allow a provider to receive the full `betas` set if it needs it. - */ - anthropicBeta: z.array(z.string()).optional(), - - contextManagement: z - .object({ - edits: z.array( - z.discriminatedUnion('type', [ - z.object({ - type: z.literal('clear_tool_uses_20250919'), - trigger: z - .discriminatedUnion('type', [ - z.object({ - type: z.literal('input_tokens'), - value: z.number(), - }), - z.object({ - type: z.literal('tool_uses'), - value: z.number(), - }), - ]) - .optional(), - keep: z - .object({ - type: z.literal('tool_uses'), - value: z.number(), - }) - .optional(), - clearAtLeast: z - .object({ - type: z.literal('input_tokens'), - value: z.number(), - }) - .optional(), - clearToolInputs: z.boolean().optional(), - excludeTools: z.array(z.string()).optional(), - }), - z.object({ - type: z.literal('clear_thinking_20251015'), - keep: z - .union([ - z.literal('all'), - z.object({ - type: z.literal('thinking_turns'), - value: z.number(), - }), - ]) - .optional(), - }), - z.object({ - type: z.literal('compact_20260112'), - trigger: z - .object({ - type: z.literal('input_tokens'), - value: z.number(), - }) - .optional(), - pauseAfterCompaction: z.boolean().optional(), - instructions: z.string().optional(), - }), - ]), - ), - }) - .optional(), -}); - -export type AnthropicLanguageModelOptions = z.infer< - typeof anthropicLanguageModelOptions ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-prepare-tools.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-prepare-tools.ts deleted file mode 100644 index 2e82aabdb..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-prepare-tools.ts +++ /dev/null @@ -1,416 +0,0 @@ -import { - LanguageModelV3CallOptions, - SharedV3Warning, - UnsupportedFunctionalityError, -} from '@ai-sdk/provider'; -import { AnthropicTool, AnthropicToolChoice } from './anthropic-messages-api'; -import { CacheControlValidator } from './get-cache-control'; -import { textEditor_20250728ArgsSchema } from './tool/text-editor_20250728'; -import { webSearch_20260209ArgsSchema } from './tool/web-search_20260209'; -import { webSearch_20250305ArgsSchema } from './tool/web-search_20250305'; -import { webFetch_20260209ArgsSchema } from './tool/web-fetch-20260209'; -import { webFetch_20250910ArgsSchema } from './tool/web-fetch-20250910'; -import { validateTypes } from '@ai-sdk/provider-utils'; - -export interface AnthropicToolOptions { - deferLoading?: boolean; - allowedCallers?: Array< - 'direct' | 'code_execution_20250825' | 'code_execution_20260120' - >; - eagerInputStreaming?: boolean; -} - -export async function prepareTools({ - tools, - toolChoice, - disableParallelToolUse, - cacheControlValidator, - supportsStructuredOutput, - supportsStrictTools, -}: { - tools: LanguageModelV3CallOptions['tools']; - toolChoice: LanguageModelV3CallOptions['toolChoice'] | undefined; - disableParallelToolUse?: boolean; - cacheControlValidator?: CacheControlValidator; - - /** - * Whether the model supports native structured output response format. - */ - supportsStructuredOutput: boolean; - - /** - * Whether the model supports strict mode on tool definitions. - */ - supportsStrictTools: boolean; -}): Promise<{ - tools: Array | undefined; - toolChoice: AnthropicToolChoice | undefined; - toolWarnings: SharedV3Warning[]; - betas: Set; -}> { - // when the tools array is empty, change it to undefined to prevent errors: - tools = tools?.length ? tools : undefined; - - const toolWarnings: SharedV3Warning[] = []; - const betas = new Set(); - const validator = cacheControlValidator || new CacheControlValidator(); - - if (tools == null) { - return { tools: undefined, toolChoice: undefined, toolWarnings, betas }; - } - - const anthropicTools: AnthropicTool[] = []; - - for (const tool of tools) { - switch (tool.type) { - case 'function': { - const cacheControl = validator.getCacheControl(tool.providerOptions, { - type: 'tool definition', - canCache: true, - }); - - // Read Anthropic-specific provider options - const anthropicOptions = tool.providerOptions?.anthropic as - | AnthropicToolOptions - | undefined; - // eager_input_streaming is only supported on custom (function) tools - const eagerInputStreaming = anthropicOptions?.eagerInputStreaming; - const deferLoading = anthropicOptions?.deferLoading; - const allowedCallers = anthropicOptions?.allowedCallers; - - if (!supportsStrictTools && tool.strict != null) { - toolWarnings.push({ - type: 'unsupported', - feature: 'strict', - details: `Tool '${tool.name}' has strict: ${tool.strict}, but strict mode is not supported by this provider. The strict property will be ignored.`, - }); - } - - anthropicTools.push({ - name: tool.name, - description: tool.description, - input_schema: tool.inputSchema, - cache_control: cacheControl, - ...(eagerInputStreaming ? { eager_input_streaming: true } : {}), - ...(supportsStrictTools === true && tool.strict != null - ? { strict: tool.strict } - : {}), - ...(deferLoading != null ? { defer_loading: deferLoading } : {}), - ...(allowedCallers != null - ? { allowed_callers: allowedCallers } - : {}), - ...(tool.inputExamples != null - ? { - input_examples: tool.inputExamples.map( - example => example.input, - ), - } - : {}), - }); - - if (supportsStructuredOutput === true) { - betas.add('structured-outputs-2025-11-13'); - } - - if (tool.inputExamples != null || allowedCallers != null) { - betas.add('advanced-tool-use-2025-11-20'); - } - - break; - } - - case 'provider': { - // Note: Provider-defined tools don't currently support providerOptions in the SDK, - // so cache_control cannot be set on them. The Anthropic API supports caching all tools, - // but the SDK would need to be updated to expose providerOptions on provider-defined tools. - switch (tool.id) { - case 'anthropic.code_execution_20250522': { - betas.add('code-execution-2025-05-22'); - anthropicTools.push({ - type: 'code_execution_20250522', - name: 'code_execution', - cache_control: undefined, - }); - break; - } - case 'anthropic.code_execution_20250825': { - betas.add('code-execution-2025-08-25'); - anthropicTools.push({ - type: 'code_execution_20250825', - name: 'code_execution', - }); - break; - } - case 'anthropic.code_execution_20260120': { - anthropicTools.push({ - type: 'code_execution_20260120', - name: 'code_execution', - }); - break; - } - case 'anthropic.computer_20250124': { - betas.add('computer-use-2025-01-24'); - anthropicTools.push({ - name: 'computer', - type: 'computer_20250124', - display_width_px: tool.args.displayWidthPx as number, - display_height_px: tool.args.displayHeightPx as number, - display_number: tool.args.displayNumber as number, - cache_control: undefined, - }); - break; - } - case 'anthropic.computer_20251124': { - betas.add('computer-use-2025-11-24'); - anthropicTools.push({ - name: 'computer', - type: 'computer_20251124', - display_width_px: tool.args.displayWidthPx as number, - display_height_px: tool.args.displayHeightPx as number, - display_number: tool.args.displayNumber as number, - enable_zoom: tool.args.enableZoom as boolean, - cache_control: undefined, - }); - break; - } - case 'anthropic.computer_20241022': { - betas.add('computer-use-2024-10-22'); - anthropicTools.push({ - name: 'computer', - type: 'computer_20241022', - display_width_px: tool.args.displayWidthPx as number, - display_height_px: tool.args.displayHeightPx as number, - display_number: tool.args.displayNumber as number, - cache_control: undefined, - }); - break; - } - case 'anthropic.text_editor_20250124': { - betas.add('computer-use-2025-01-24'); - anthropicTools.push({ - name: 'str_replace_editor', - type: 'text_editor_20250124', - cache_control: undefined, - }); - break; - } - case 'anthropic.text_editor_20241022': { - betas.add('computer-use-2024-10-22'); - anthropicTools.push({ - name: 'str_replace_editor', - type: 'text_editor_20241022', - cache_control: undefined, - }); - break; - } - case 'anthropic.text_editor_20250429': { - betas.add('computer-use-2025-01-24'); - anthropicTools.push({ - name: 'str_replace_based_edit_tool', - type: 'text_editor_20250429', - cache_control: undefined, - }); - break; - } - case 'anthropic.text_editor_20250728': { - const args = await validateTypes({ - value: tool.args, - schema: textEditor_20250728ArgsSchema, - }); - anthropicTools.push({ - name: 'str_replace_based_edit_tool', - type: 'text_editor_20250728', - max_characters: args.maxCharacters, - cache_control: undefined, - }); - break; - } - case 'anthropic.bash_20250124': { - betas.add('computer-use-2025-01-24'); - anthropicTools.push({ - name: 'bash', - type: 'bash_20250124', - cache_control: undefined, - }); - break; - } - case 'anthropic.bash_20241022': { - betas.add('computer-use-2024-10-22'); - anthropicTools.push({ - name: 'bash', - type: 'bash_20241022', - cache_control: undefined, - }); - break; - } - case 'anthropic.memory_20250818': { - betas.add('context-management-2025-06-27'); - anthropicTools.push({ - name: 'memory', - type: 'memory_20250818', - }); - break; - } - case 'anthropic.web_fetch_20250910': { - betas.add('web-fetch-2025-09-10'); - const args = await validateTypes({ - value: tool.args, - schema: webFetch_20250910ArgsSchema, - }); - anthropicTools.push({ - type: 'web_fetch_20250910', - name: 'web_fetch', - max_uses: args.maxUses, - allowed_domains: args.allowedDomains, - blocked_domains: args.blockedDomains, - citations: args.citations, - max_content_tokens: args.maxContentTokens, - cache_control: undefined, - }); - break; - } - case 'anthropic.web_fetch_20260209': { - betas.add('code-execution-web-tools-2026-02-09'); - const args = await validateTypes({ - value: tool.args, - schema: webFetch_20260209ArgsSchema, - }); - anthropicTools.push({ - type: 'web_fetch_20260209', - name: 'web_fetch', - max_uses: args.maxUses, - allowed_domains: args.allowedDomains, - blocked_domains: args.blockedDomains, - citations: args.citations, - max_content_tokens: args.maxContentTokens, - cache_control: undefined, - }); - break; - } - case 'anthropic.web_search_20250305': { - const args = await validateTypes({ - value: tool.args, - schema: webSearch_20250305ArgsSchema, - }); - anthropicTools.push({ - type: 'web_search_20250305', - name: 'web_search', - max_uses: args.maxUses, - allowed_domains: args.allowedDomains, - blocked_domains: args.blockedDomains, - user_location: args.userLocation, - cache_control: undefined, - }); - break; - } - case 'anthropic.web_search_20260209': { - betas.add('code-execution-web-tools-2026-02-09'); - const args = await validateTypes({ - value: tool.args, - schema: webSearch_20260209ArgsSchema, - }); - anthropicTools.push({ - type: 'web_search_20260209', - name: 'web_search', - max_uses: args.maxUses, - allowed_domains: args.allowedDomains, - blocked_domains: args.blockedDomains, - user_location: args.userLocation, - cache_control: undefined, - }); - break; - } - - case 'anthropic.tool_search_regex_20251119': { - anthropicTools.push({ - type: 'tool_search_tool_regex_20251119', - name: 'tool_search_tool_regex', - }); - break; - } - - case 'anthropic.tool_search_bm25_20251119': { - anthropicTools.push({ - type: 'tool_search_tool_bm25_20251119', - name: 'tool_search_tool_bm25', - }); - break; - } - - default: { - toolWarnings.push({ - type: 'unsupported', - feature: `provider-defined tool ${tool.id}`, - }); - break; - } - } - break; - } - - default: { - toolWarnings.push({ - type: 'unsupported', - feature: `tool ${tool}`, - }); - break; - } - } - } - - if (toolChoice == null) { - return { - tools: anthropicTools, - toolChoice: disableParallelToolUse - ? { type: 'auto', disable_parallel_tool_use: disableParallelToolUse } - : undefined, - toolWarnings, - betas, - }; - } - - const type = toolChoice.type; - - switch (type) { - case 'auto': - return { - tools: anthropicTools, - toolChoice: { - type: 'auto', - disable_parallel_tool_use: disableParallelToolUse, - }, - toolWarnings, - betas, - }; - case 'required': - return { - tools: anthropicTools, - toolChoice: { - type: 'any', - disable_parallel_tool_use: disableParallelToolUse, - }, - toolWarnings, - betas, - }; - case 'none': - // Anthropic does not support 'none' tool choice, so we remove the tools: - return { tools: undefined, toolChoice: undefined, toolWarnings, betas }; - case 'tool': - return { - tools: anthropicTools, - toolChoice: { - type: 'tool', - name: toolChoice.toolName, - disable_parallel_tool_use: disableParallelToolUse, - }, - toolWarnings, - betas, - }; - default: { - const _exhaustiveCheck: never = type; - throw new UnsupportedFunctionalityError({ - functionality: `tool choice type: ${_exhaustiveCheck}`, - }); - } - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-provider.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-provider.ts deleted file mode 100644 index f77cc3d9f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-provider.ts +++ /dev/null @@ -1,177 +0,0 @@ -import { - InvalidArgumentError, - LanguageModelV3, - NoSuchModelError, - ProviderV3, -} from '@ai-sdk/provider'; -import { - FetchFunction, - generateId, - loadApiKey, - loadOptionalSetting, - withoutTrailingSlash, - withUserAgentSuffix, -} from '@ai-sdk/provider-utils'; -import { VERSION } from './version'; -import { AnthropicMessagesLanguageModel } from './anthropic-messages-language-model'; -import { AnthropicMessagesModelId } from './anthropic-messages-options'; -import { anthropicTools } from './anthropic-tools'; - -export interface AnthropicProvider extends ProviderV3 { - /** - * Creates a model for text generation. - */ - (modelId: AnthropicMessagesModelId): LanguageModelV3; - - /** - * Creates a model for text generation. - */ - languageModel(modelId: AnthropicMessagesModelId): LanguageModelV3; - - chat(modelId: AnthropicMessagesModelId): LanguageModelV3; - - messages(modelId: AnthropicMessagesModelId): LanguageModelV3; - - /** - * @deprecated Use `embeddingModel` instead. - */ - textEmbeddingModel(modelId: string): never; - - /** - * Anthropic-specific computer use tool. - */ - tools: typeof anthropicTools; -} - -export interface AnthropicProviderSettings { - /** - * Use a different URL prefix for API calls, e.g. to use proxy servers. - * The default prefix is `https://api.anthropic.com/v1`. - */ - baseURL?: string; - - /** - * API key that is being send using the `x-api-key` header. - * It defaults to the `ANTHROPIC_API_KEY` environment variable. - * Only one of `apiKey` or `authToken` is required. - */ - apiKey?: string; - - /** - * Auth token that is being sent using the `Authorization: Bearer` header. - * It defaults to the `ANTHROPIC_AUTH_TOKEN` environment variable. - * Only one of `apiKey` or `authToken` is required. - */ - authToken?: string; - - /** - * Custom headers to include in the requests. - */ - headers?: Record; - - /** - * Custom fetch implementation. You can use it as a middleware to intercept requests, - * or to provide a custom fetch implementation for e.g. testing. - */ - fetch?: FetchFunction; - - generateId?: () => string; - - /** - * Custom provider name - * Defaults to 'anthropic.messages'. - */ - name?: string; -} - -/** - * Create an Anthropic provider instance. - */ -export function createAnthropic( - options: AnthropicProviderSettings = {}, -): AnthropicProvider { - const baseURL = - withoutTrailingSlash( - loadOptionalSetting({ - settingValue: options.baseURL, - environmentVariableName: 'ANTHROPIC_BASE_URL', - }), - ) ?? 'https://api.anthropic.com/v1'; - - const providerName = options.name ?? 'anthropic.messages'; - - // Only error if both are explicitly provided in options - if (options.apiKey && options.authToken) { - throw new InvalidArgumentError({ - argument: 'apiKey/authToken', - message: - 'Both apiKey and authToken were provided. Please use only one authentication method.', - }); - } - - const getHeaders = () => { - const authHeaders: Record = options.authToken - ? { Authorization: `Bearer ${options.authToken}` } - : { - 'x-api-key': loadApiKey({ - apiKey: options.apiKey, - environmentVariableName: 'ANTHROPIC_API_KEY', - description: 'Anthropic', - }), - }; - - return withUserAgentSuffix( - { - 'anthropic-version': '2023-06-01', - ...authHeaders, - ...options.headers, - }, - `ai-sdk/anthropic/${VERSION}`, - ); - }; - - const createChatModel = (modelId: AnthropicMessagesModelId) => - new AnthropicMessagesLanguageModel(modelId, { - provider: providerName, - baseURL, - headers: getHeaders, - fetch: options.fetch, - generateId: options.generateId ?? generateId, - supportedUrls: () => ({ - 'image/*': [/^https?:\/\/.*$/], - 'application/pdf': [/^https?:\/\/.*$/], - }), - }); - - const provider = function (modelId: AnthropicMessagesModelId) { - if (new.target) { - throw new Error( - 'The Anthropic model function cannot be called with the new keyword.', - ); - } - - return createChatModel(modelId); - }; - - provider.specificationVersion = 'v3' as const; - provider.languageModel = createChatModel; - provider.chat = createChatModel; - provider.messages = createChatModel; - - provider.embeddingModel = (modelId: string) => { - throw new NoSuchModelError({ modelId, modelType: 'embeddingModel' }); - }; - provider.textEmbeddingModel = provider.embeddingModel; - provider.imageModel = (modelId: string) => { - throw new NoSuchModelError({ modelId, modelType: 'imageModel' }); - }; - - provider.tools = anthropicTools; - - return provider; -} - -/** - * Default Anthropic provider instance. - */ -export const anthropic = createAnthropic(); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-tools.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-tools.ts deleted file mode 100644 index d3f62d812..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/anthropic-tools.ts +++ /dev/null @@ -1,238 +0,0 @@ -import { bash_20241022 } from './tool/bash_20241022'; -import { bash_20250124 } from './tool/bash_20250124'; -import { codeExecution_20250522 } from './tool/code-execution_20250522'; -import { codeExecution_20250825 } from './tool/code-execution_20250825'; -import { codeExecution_20260120 } from './tool/code-execution_20260120'; -import { computer_20241022 } from './tool/computer_20241022'; -import { computer_20250124 } from './tool/computer_20250124'; -import { computer_20251124 } from './tool/computer_20251124'; -import { memory_20250818 } from './tool/memory_20250818'; -import { textEditor_20241022 } from './tool/text-editor_20241022'; -import { textEditor_20250124 } from './tool/text-editor_20250124'; -import { textEditor_20250429 } from './tool/text-editor_20250429'; -import { textEditor_20250728 } from './tool/text-editor_20250728'; -import { toolSearchBm25_20251119 } from './tool/tool-search-bm25_20251119'; -import { toolSearchRegex_20251119 } from './tool/tool-search-regex_20251119'; -import { webFetch_20260209 } from './tool/web-fetch-20260209'; -import { webFetch_20250910 } from './tool/web-fetch-20250910'; -import { webSearch_20260209 } from './tool/web-search_20260209'; -import { webSearch_20250305 } from './tool/web-search_20250305'; - -export const anthropicTools = { - /** - * The bash tool enables Claude to execute shell commands in a persistent bash session, - * allowing system operations, script execution, and command-line automation. - * - * Image results are supported. - */ - bash_20241022, - - /** - * The bash tool enables Claude to execute shell commands in a persistent bash session, - * allowing system operations, script execution, and command-line automation. - * - * Image results are supported. - */ - bash_20250124, - - /** - * Claude can analyze data, create visualizations, perform complex calculations, - * run system commands, create and edit files, and process uploaded files directly within - * the API conversation. - * - * The code execution tool allows Claude to run Bash commands and manipulate files, - * including writing code, in a secure, sandboxed environment. - */ - codeExecution_20250522, - - /** - * Claude can analyze data, create visualizations, perform complex calculations, - * run system commands, create and edit files, and process uploaded files directly within - * the API conversation. - * - * The code execution tool allows Claude to run both Python and Bash commands and manipulate files, - * including writing code, in a secure, sandboxed environment. - * - * This is the latest version with enhanced Bash support and file operations. - */ - codeExecution_20250825, - - /** - * Claude can analyze data, create visualizations, perform complex calculations, - * run system commands, create and edit files, and process uploaded files directly within - * the API conversation. - * - * The code execution tool allows Claude to run both Python and Bash commands and manipulate files, - * including writing code, in a secure, sandboxed environment. - * - * This is the recommended version. Does not require a beta header. - * - * Supported models: Claude Opus 4.6, Sonnet 4.6, Sonnet 4.5, Opus 4.5 - */ - codeExecution_20260120, - - /** - * Claude can interact with computer environments through the computer use tool, which - * provides screenshot capabilities and mouse/keyboard control for autonomous desktop interaction. - * - * Image results are supported. - * - * @param displayWidthPx - The width of the display being controlled by the model in pixels. - * @param displayHeightPx - The height of the display being controlled by the model in pixels. - * @param displayNumber - The display number to control (only relevant for X11 environments). If specified, the tool will be provided a display number in the tool definition. - */ - computer_20241022, - - /** - * Claude can interact with computer environments through the computer use tool, which - * provides screenshot capabilities and mouse/keyboard control for autonomous desktop interaction. - * - * Image results are supported. - * - * @param displayWidthPx - The width of the display being controlled by the model in pixels. - * @param displayHeightPx - The height of the display being controlled by the model in pixels. - * @param displayNumber - The display number to control (only relevant for X11 environments). If specified, the tool will be provided a display number in the tool definition. - */ - computer_20250124, - - /** - * Claude can interact with computer environments through the computer use tool, which - * provides screenshot capabilities and mouse/keyboard control for autonomous desktop interaction. - * - * This version adds the zoom action for detailed screen region inspection. - * - * Image results are supported. - * - * Supported models: Claude Opus 4.5 - * - * @param displayWidthPx - The width of the display being controlled by the model in pixels. - * @param displayHeightPx - The height of the display being controlled by the model in pixels. - * @param displayNumber - The display number to control (only relevant for X11 environments). If specified, the tool will be provided a display number in the tool definition. - * @param enableZoom - Enable zoom action. Set to true to allow Claude to zoom into specific screen regions. Default: false. - */ - computer_20251124, - - /** - * The memory tool enables Claude to store and retrieve information across conversations through a memory file directory. - * Claude can create, read, update, and delete files that persist between sessions, - * allowing it to build knowledge over time without keeping everything in the context window. - * The memory tool operates client-side—you control where and how the data is stored through your own infrastructure. - * - * Supported models: Claude Sonnet 4.5, Claude Sonnet 4, Claude Opus 4.1, Claude Opus 4. - */ - memory_20250818, - - /** - * Claude can use an Anthropic-defined text editor tool to view and modify text files, - * helping you debug, fix, and improve your code or other text documents. This allows Claude - * to directly interact with your files, providing hands-on assistance rather than just suggesting changes. - * - * Supported models: Claude Sonnet 3.5 - */ - textEditor_20241022, - - /** - * Claude can use an Anthropic-defined text editor tool to view and modify text files, - * helping you debug, fix, and improve your code or other text documents. This allows Claude - * to directly interact with your files, providing hands-on assistance rather than just suggesting changes. - * - * Supported models: Claude Sonnet 3.7 - */ - textEditor_20250124, - - /** - * Claude can use an Anthropic-defined text editor tool to view and modify text files, - * helping you debug, fix, and improve your code or other text documents. This allows Claude - * to directly interact with your files, providing hands-on assistance rather than just suggesting changes. - * - * Note: This version does not support the "undo_edit" command. - * - * @deprecated Use textEditor_20250728 instead - */ - textEditor_20250429, - - /** - * Claude can use an Anthropic-defined text editor tool to view and modify text files, - * helping you debug, fix, and improve your code or other text documents. This allows Claude - * to directly interact with your files, providing hands-on assistance rather than just suggesting changes. - * - * Note: This version does not support the "undo_edit" command and adds optional max_characters parameter. - * - * Supported models: Claude Sonnet 4, Opus 4, and Opus 4.1 - * - * @param maxCharacters - Optional maximum number of characters to view in the file - */ - textEditor_20250728, - - /** - * Creates a web fetch tool that gives Claude direct access to real-time web content. - * - * @param maxUses - The max_uses parameter limits the number of web fetches performed - * @param allowedDomains - Only fetch from these domains - * @param blockedDomains - Never fetch from these domains - * @param citations - Unlike web search where citations are always enabled, citations are optional for web fetch. Set "citations": {"enabled": true} to enable Claude to cite specific passages from fetched documents. - * @param maxContentTokens - The max_content_tokens parameter limits the amount of content that will be included in the context. - */ - webFetch_20250910, - - /** - * Creates a web fetch tool that gives Claude direct access to real-time web content. - * - * @param maxUses - The max_uses parameter limits the number of web fetches performed - * @param allowedDomains - Only fetch from these domains - * @param blockedDomains - Never fetch from these domains - * @param citations - Unlike web search where citations are always enabled, citations are optional for web fetch. Set "citations": {"enabled": true} to enable Claude to cite specific passages from fetched documents. - * @param maxContentTokens - The max_content_tokens parameter limits the amount of content that will be included in the context. - */ - webFetch_20260209, - - /** - * Creates a web search tool that gives Claude direct access to real-time web content. - * - * @param maxUses - Maximum number of web searches Claude can perform during the conversation. - * @param allowedDomains - Optional list of domains that Claude is allowed to search. - * @param blockedDomains - Optional list of domains that Claude should avoid when searching. - * @param userLocation - Optional user location information to provide geographically relevant search results. - */ - webSearch_20250305, - - /** - * Creates a web search tool that gives Claude direct access to real-time web content. - * - * @param maxUses - Maximum number of web searches Claude can perform during the conversation. - * @param allowedDomains - Optional list of domains that Claude is allowed to search. - * @param blockedDomains - Optional list of domains that Claude should avoid when searching. - * @param userLocation - Optional user location information to provide geographically relevant search results. - */ - webSearch_20260209, - - /** - * Creates a tool search tool that uses regex patterns to find tools. - * - * The tool search tool enables Claude to work with hundreds or thousands of tools - * by dynamically discovering and loading them on-demand. Instead of loading all - * tool definitions into the context window upfront, Claude searches your tool - * catalog and loads only the tools it needs. - * - * Use `providerOptions: { anthropic: { deferLoading: true } }` on other tools - * to mark them for deferred loading. - * - * Supported models: Claude Opus 4.5, Claude Sonnet 4.5 - */ - toolSearchRegex_20251119, - - /** - * Creates a tool search tool that uses BM25 (natural language) to find tools. - * - * The tool search tool enables Claude to work with hundreds or thousands of tools - * by dynamically discovering and loading them on-demand. Instead of loading all - * tool definitions into the context window upfront, Claude searches your tool - * catalog and loads only the tools it needs. - * - * Use `providerOptions: { anthropic: { deferLoading: true } }` on other tools - * to mark them for deferred loading. - * - * Supported models: Claude Opus 4.5, Claude Sonnet 4.5 - */ - toolSearchBm25_20251119, -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/convert-anthropic-messages-usage.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/convert-anthropic-messages-usage.ts deleted file mode 100644 index 679629448..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/convert-anthropic-messages-usage.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { JSONObject, LanguageModelV3Usage } from '@ai-sdk/provider'; - -/** - * Represents a single iteration in the usage breakdown. - * When compaction occurs, the API returns an iterations array showing - * usage for each sampling iteration (compaction + message). - */ -export type AnthropicUsageIteration = { - type: 'compaction' | 'message'; - input_tokens: number; - output_tokens: number; -}; - -export type AnthropicMessagesUsage = { - input_tokens: number; - output_tokens: number; - cache_creation_input_tokens?: number | null; - cache_read_input_tokens?: number | null; - /** - * When compaction is triggered, this array contains usage for each - * sampling iteration. The top-level input_tokens and output_tokens - * do NOT include compaction iteration usage - to get total tokens - * consumed and billed, sum across all entries in this array. - */ - iterations?: AnthropicUsageIteration[] | null; -}; - -export function convertAnthropicMessagesUsage({ - usage, - rawUsage, -}: { - usage: AnthropicMessagesUsage; - rawUsage?: JSONObject; -}): LanguageModelV3Usage { - const cacheCreationTokens = usage.cache_creation_input_tokens ?? 0; - const cacheReadTokens = usage.cache_read_input_tokens ?? 0; - - // When iterations is present (compaction occurred), sum across all iterations - // to get the true total tokens consumed/billed. The top-level input_tokens - // and output_tokens exclude compaction iteration usage. - let inputTokens: number; - let outputTokens: number; - - if (usage.iterations && usage.iterations.length > 0) { - const totals = usage.iterations.reduce( - (acc, iter) => ({ - input: acc.input + iter.input_tokens, - output: acc.output + iter.output_tokens, - }), - { input: 0, output: 0 }, - ); - inputTokens = totals.input; - outputTokens = totals.output; - } else { - inputTokens = usage.input_tokens; - outputTokens = usage.output_tokens; - } - - return { - inputTokens: { - total: inputTokens + cacheCreationTokens + cacheReadTokens, - noCache: inputTokens, - cacheRead: cacheReadTokens, - cacheWrite: cacheCreationTokens, - }, - outputTokens: { - total: outputTokens, - text: undefined, - reasoning: undefined, - }, - raw: rawUsage ?? usage, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/convert-to-anthropic-messages-prompt.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/convert-to-anthropic-messages-prompt.ts deleted file mode 100644 index 610ad1cb5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/convert-to-anthropic-messages-prompt.ts +++ /dev/null @@ -1,1119 +0,0 @@ -import { - SharedV3Warning, - LanguageModelV3DataContent, - LanguageModelV3Message, - LanguageModelV3Prompt, - SharedV3ProviderMetadata, - UnsupportedFunctionalityError, -} from '@ai-sdk/provider'; -import { - convertBase64ToUint8Array, - convertToBase64, - parseProviderOptions, - validateTypes, - isNonNullable, - ToolNameMapping, -} from '@ai-sdk/provider-utils'; -import { - AnthropicAssistantMessage, - AnthropicMessagesPrompt, - anthropicReasoningMetadataSchema, - AnthropicToolResultContent, - AnthropicUserMessage, - AnthropicWebFetchToolResultContent, -} from './anthropic-messages-api'; -import { anthropicFilePartProviderOptions } from './anthropic-messages-options'; -import { CacheControlValidator } from './get-cache-control'; -import { codeExecution_20250522OutputSchema } from './tool/code-execution_20250522'; -import { codeExecution_20250825OutputSchema } from './tool/code-execution_20250825'; -import { codeExecution_20260120OutputSchema } from './tool/code-execution_20260120'; -import { toolSearchRegex_20251119OutputSchema as toolSearchOutputSchema } from './tool/tool-search-regex_20251119'; -import { webFetch_20250910OutputSchema } from './tool/web-fetch-20250910'; -import { webSearch_20250305OutputSchema } from './tool/web-search_20250305'; - -function convertToString(data: LanguageModelV3DataContent): string { - if (typeof data === 'string') { - return new TextDecoder().decode(convertBase64ToUint8Array(data)); - } - - if (data instanceof Uint8Array) { - return new TextDecoder().decode(data); - } - - if (data instanceof URL) { - throw new UnsupportedFunctionalityError({ - functionality: 'URL-based text documents are not supported for citations', - }); - } - - throw new UnsupportedFunctionalityError({ - functionality: `unsupported data type for text documents: ${typeof data}`, - }); -} - -/** - * Checks if data is a URL (either a URL object or a URL string). - */ -function isUrlData( - data: LanguageModelV3DataContent, -): data is URL | (string & { __brand: 'url-string' }) { - return data instanceof URL || isUrlString(data); -} - -function isUrlString(data: LanguageModelV3DataContent): boolean { - return typeof data === 'string' && /^https?:\/\//i.test(data); -} - -function getUrlString(data: LanguageModelV3DataContent): string { - return data instanceof URL ? data.toString() : (data as string); -} - -export async function convertToAnthropicMessagesPrompt({ - prompt, - sendReasoning, - warnings, - cacheControlValidator, - toolNameMapping, -}: { - prompt: LanguageModelV3Prompt; - sendReasoning: boolean; - warnings: SharedV3Warning[]; - cacheControlValidator?: CacheControlValidator; - toolNameMapping: ToolNameMapping; -}): Promise<{ - prompt: AnthropicMessagesPrompt; - betas: Set; -}> { - const betas = new Set(); - const blocks = groupIntoBlocks(prompt); - const validator = cacheControlValidator || new CacheControlValidator(); - - let system: AnthropicMessagesPrompt['system'] = undefined; - const messages: AnthropicMessagesPrompt['messages'] = []; - - async function shouldEnableCitations( - providerMetadata: SharedV3ProviderMetadata | undefined, - ): Promise { - const anthropicOptions = await parseProviderOptions({ - provider: 'anthropic', - providerOptions: providerMetadata, - schema: anthropicFilePartProviderOptions, - }); - - return anthropicOptions?.citations?.enabled ?? false; - } - - async function getDocumentMetadata( - providerMetadata: SharedV3ProviderMetadata | undefined, - ): Promise<{ title?: string; context?: string }> { - const anthropicOptions = await parseProviderOptions({ - provider: 'anthropic', - providerOptions: providerMetadata, - schema: anthropicFilePartProviderOptions, - }); - - return { - title: anthropicOptions?.title, - context: anthropicOptions?.context, - }; - } - - for (let i = 0; i < blocks.length; i++) { - const block = blocks[i]; - const isLastBlock = i === blocks.length - 1; - const type = block.type; - - switch (type) { - case 'system': { - if (system != null) { - throw new UnsupportedFunctionalityError({ - functionality: - 'Multiple system messages that are separated by user/assistant messages', - }); - } - - system = block.messages.map(({ content, providerOptions }) => ({ - type: 'text', - text: content, - cache_control: validator.getCacheControl(providerOptions, { - type: 'system message', - canCache: true, - }), - })); - - break; - } - - case 'user': { - // combines all user and tool messages in this block into a single message: - const anthropicContent: AnthropicUserMessage['content'] = []; - - for (const message of block.messages) { - const { role, content } = message; - switch (role) { - case 'user': { - for (let j = 0; j < content.length; j++) { - const part = content[j]; - - // cache control: first add cache control from part. - // for the last part of a message, - // check also if the message has cache control. - const isLastPart = j === content.length - 1; - - const cacheControl = - validator.getCacheControl(part.providerOptions, { - type: 'user message part', - canCache: true, - }) ?? - (isLastPart - ? validator.getCacheControl(message.providerOptions, { - type: 'user message', - canCache: true, - }) - : undefined); - - switch (part.type) { - case 'text': { - anthropicContent.push({ - type: 'text', - text: part.text, - cache_control: cacheControl, - }); - break; - } - - case 'file': { - if (part.mediaType.startsWith('image/')) { - anthropicContent.push({ - type: 'image', - source: isUrlData(part.data) - ? { - type: 'url', - url: getUrlString(part.data), - } - : { - type: 'base64', - media_type: - part.mediaType === 'image/*' - ? 'image/jpeg' - : part.mediaType, - data: convertToBase64(part.data), - }, - cache_control: cacheControl, - }); - } else if (part.mediaType === 'application/pdf') { - betas.add('pdfs-2024-09-25'); - - const enableCitations = await shouldEnableCitations( - part.providerOptions, - ); - - const metadata = await getDocumentMetadata( - part.providerOptions, - ); - - anthropicContent.push({ - type: 'document', - source: isUrlData(part.data) - ? { - type: 'url', - url: getUrlString(part.data), - } - : { - type: 'base64', - media_type: 'application/pdf', - data: convertToBase64(part.data), - }, - title: metadata.title ?? part.filename, - ...(metadata.context && { context: metadata.context }), - ...(enableCitations && { - citations: { enabled: true }, - }), - cache_control: cacheControl, - }); - } else if (part.mediaType === 'text/plain') { - const enableCitations = await shouldEnableCitations( - part.providerOptions, - ); - - const metadata = await getDocumentMetadata( - part.providerOptions, - ); - - anthropicContent.push({ - type: 'document', - source: isUrlData(part.data) - ? { - type: 'url', - url: getUrlString(part.data), - } - : { - type: 'text', - media_type: 'text/plain', - data: convertToString(part.data), - }, - title: metadata.title ?? part.filename, - ...(metadata.context && { context: metadata.context }), - ...(enableCitations && { - citations: { enabled: true }, - }), - cache_control: cacheControl, - }); - } else { - throw new UnsupportedFunctionalityError({ - functionality: `media type: ${part.mediaType}`, - }); - } - - break; - } - } - } - - break; - } - case 'tool': { - for (let i = 0; i < content.length; i++) { - const part = content[i]; - - if (part.type === 'tool-approval-response') { - continue; - } - - // cache control: first add cache control from part. - // for the last part of a message, - // check also if the message has cache control. - const isLastPart = i === content.length - 1; - - const cacheControl = - validator.getCacheControl(part.providerOptions, { - type: 'tool result part', - canCache: true, - }) ?? - (isLastPart - ? validator.getCacheControl(message.providerOptions, { - type: 'tool result message', - canCache: true, - }) - : undefined); - - const output = part.output; - let contentValue: AnthropicToolResultContent['content']; - switch (output.type) { - case 'content': - contentValue = output.value - .map(contentPart => { - switch (contentPart.type) { - case 'text': - return { - type: 'text' as const, - text: contentPart.text, - }; - case 'image-data': { - return { - type: 'image' as const, - source: { - type: 'base64' as const, - media_type: contentPart.mediaType, - data: contentPart.data, - }, - }; - } - case 'image-url': { - return { - type: 'image' as const, - source: { - type: 'url' as const, - url: contentPart.url, - }, - }; - } - case 'file-url': { - return { - type: 'document' as const, - source: { - type: 'url' as const, - url: contentPart.url, - }, - }; - } - case 'file-data': { - if (contentPart.mediaType === 'application/pdf') { - betas.add('pdfs-2024-09-25'); - return { - type: 'document' as const, - source: { - type: 'base64' as const, - media_type: contentPart.mediaType, - data: contentPart.data, - }, - }; - } - - warnings.push({ - type: 'other', - message: `unsupported tool content part type: ${contentPart.type} with media type: ${contentPart.mediaType}`, - }); - - return undefined; - } - case 'custom': { - const anthropicOptions = contentPart.providerOptions - ?.anthropic as - | { type: string; toolName?: string } - | undefined; - if (anthropicOptions?.type === 'tool-reference') { - return { - type: 'tool_reference' as const, - tool_name: anthropicOptions.toolName!, - }; - } - warnings.push({ - type: 'other', - message: `unsupported custom tool content part`, - }); - return undefined; - } - default: { - warnings.push({ - type: 'other', - message: `unsupported tool content part type: ${contentPart.type}`, - }); - - return undefined; - } - } - }) - .filter(isNonNullable); - break; - case 'text': - case 'error-text': - contentValue = output.value; - break; - case 'execution-denied': - contentValue = output.reason ?? 'Tool execution denied.'; - break; - case 'json': - case 'error-json': - default: - contentValue = JSON.stringify(output.value); - break; - } - - anthropicContent.push({ - type: 'tool_result', - tool_use_id: part.toolCallId, - content: contentValue, - is_error: - output.type === 'error-text' || output.type === 'error-json' - ? true - : undefined, - cache_control: cacheControl, - }); - } - - break; - } - default: { - const _exhaustiveCheck: never = role; - throw new Error(`Unsupported role: ${_exhaustiveCheck}`); - } - } - } - - messages.push({ role: 'user', content: anthropicContent }); - - break; - } - - case 'assistant': { - // combines multiple assistant messages in this block into a single message: - const anthropicContent: AnthropicAssistantMessage['content'] = []; - - const mcpToolUseIds = new Set(); - - for (let j = 0; j < block.messages.length; j++) { - const message = block.messages[j]; - const isLastMessage = j === block.messages.length - 1; - const { content } = message; - - for (let k = 0; k < content.length; k++) { - const part = content[k]; - const isLastContentPart = k === content.length - 1; - - // cache control: first add cache control from part. - // for the last part of a message, - // check also if the message has cache control. - const cacheControl = - validator.getCacheControl(part.providerOptions, { - type: 'assistant message part', - canCache: true, - }) ?? - (isLastContentPart - ? validator.getCacheControl(message.providerOptions, { - type: 'assistant message', - canCache: true, - }) - : undefined); - - switch (part.type) { - case 'text': { - // Check if this is a compaction block (via providerMetadata) - const textMetadata = part.providerOptions?.anthropic as - | { type?: string } - | undefined; - - if (textMetadata?.type === 'compaction') { - anthropicContent.push({ - type: 'compaction', - content: part.text, - cache_control: cacheControl, - }); - } else { - anthropicContent.push({ - type: 'text', - text: - // trim the last text part if it's the last message in the block - // because Anthropic does not allow trailing whitespace - // in pre-filled assistant responses - isLastBlock && isLastMessage && isLastContentPart - ? part.text.trim() - : part.text, - - cache_control: cacheControl, - }); - } - break; - } - - case 'reasoning': { - if (sendReasoning) { - const reasoningMetadata = await parseProviderOptions({ - provider: 'anthropic', - providerOptions: part.providerOptions, - schema: anthropicReasoningMetadataSchema, - }); - - if (reasoningMetadata != null) { - if (reasoningMetadata.signature != null) { - // Note: thinking blocks cannot have cache_control directly - // They are cached implicitly when in previous assistant turns - // Validate to provide helpful error message - validator.getCacheControl(part.providerOptions, { - type: 'thinking block', - canCache: false, - }); - anthropicContent.push({ - type: 'thinking', - thinking: part.text, - signature: reasoningMetadata.signature, - }); - } else if (reasoningMetadata.redactedData != null) { - // Note: redacted thinking blocks cannot have cache_control directly - // They are cached implicitly when in previous assistant turns - // Validate to provide helpful error message - validator.getCacheControl(part.providerOptions, { - type: 'redacted thinking block', - canCache: false, - }); - anthropicContent.push({ - type: 'redacted_thinking', - data: reasoningMetadata.redactedData, - }); - } else { - warnings.push({ - type: 'other', - message: 'unsupported reasoning metadata', - }); - } - } else { - warnings.push({ - type: 'other', - message: 'unsupported reasoning metadata', - }); - } - } else { - warnings.push({ - type: 'other', - message: - 'sending reasoning content is disabled for this model', - }); - } - break; - } - - case 'tool-call': { - if (part.providerExecuted) { - const providerToolName = toolNameMapping.toProviderToolName( - part.toolName, - ); - const isMcpToolUse = - part.providerOptions?.anthropic?.type === 'mcp-tool-use'; - - if (isMcpToolUse) { - mcpToolUseIds.add(part.toolCallId); - - const serverName = - part.providerOptions?.anthropic?.serverName; - - if (serverName == null || typeof serverName !== 'string') { - warnings.push({ - type: 'other', - message: - 'mcp tool use server name is required and must be a string', - }); - break; - } - - anthropicContent.push({ - type: 'mcp_tool_use', - id: part.toolCallId, - name: part.toolName, - input: part.input, - server_name: serverName, - cache_control: cacheControl, - }); - } else if ( - // code execution 20250825: - providerToolName === 'code_execution' && - part.input != null && - typeof part.input === 'object' && - 'type' in part.input && - typeof part.input.type === 'string' && - (part.input.type === 'bash_code_execution' || - part.input.type === 'text_editor_code_execution') - ) { - anthropicContent.push({ - type: 'server_tool_use', - id: part.toolCallId, - name: part.input.type, // map back to subtool name - input: part.input, - cache_control: cacheControl, - }); - } else if ( - // code execution 20250825 programmatic tool calling: - // Strip the fake 'programmatic-tool-call' type before sending to Anthropic - providerToolName === 'code_execution' && - part.input != null && - typeof part.input === 'object' && - 'type' in part.input && - part.input.type === 'programmatic-tool-call' - ) { - const { type: _, ...inputWithoutType } = part.input as { - type: string; - code: string; - }; - anthropicContent.push({ - type: 'server_tool_use', - id: part.toolCallId, - name: 'code_execution', - input: inputWithoutType, - cache_control: cacheControl, - }); - } else { - if ( - providerToolName === 'code_execution' || // code execution 20250522 - providerToolName === 'web_fetch' || - providerToolName === 'web_search' - ) { - anthropicContent.push({ - type: 'server_tool_use', - id: part.toolCallId, - name: providerToolName, - input: part.input, - cache_control: cacheControl, - }); - } else if ( - providerToolName === 'tool_search_tool_regex' || - providerToolName === 'tool_search_tool_bm25' - ) { - anthropicContent.push({ - type: 'server_tool_use', - id: part.toolCallId, - name: providerToolName, - input: part.input, - cache_control: cacheControl, - }); - } else { - warnings.push({ - type: 'other', - message: `provider executed tool call for tool ${part.toolName} is not supported`, - }); - } - } - - break; - } - - // Extract caller info from provider options for programmatic tool calling - const callerOptions = part.providerOptions?.anthropic as - | { caller?: { type: string; toolId?: string } } - | undefined; - const caller = callerOptions?.caller - ? (callerOptions.caller.type === 'code_execution_20250825' || - callerOptions.caller.type === - 'code_execution_20260120') && - callerOptions.caller.toolId - ? { - type: callerOptions.caller.type as - | 'code_execution_20250825' - | 'code_execution_20260120', - tool_id: callerOptions.caller.toolId, - } - : callerOptions.caller.type === 'direct' - ? { type: 'direct' as const } - : undefined - : undefined; - - anthropicContent.push({ - type: 'tool_use', - id: part.toolCallId, - name: part.toolName, - input: part.input, - ...(caller && { caller }), - cache_control: cacheControl, - }); - break; - } - - case 'tool-result': { - const providerToolName = toolNameMapping.toProviderToolName( - part.toolName, - ); - - if (mcpToolUseIds.has(part.toolCallId)) { - const output = part.output; - - if (output.type !== 'json' && output.type !== 'error-json') { - warnings.push({ - type: 'other', - message: `provider executed tool result output type ${output.type} for tool ${part.toolName} is not supported`, - }); - - break; - } - - anthropicContent.push({ - type: 'mcp_tool_result', - tool_use_id: part.toolCallId, - is_error: output.type === 'error-json', - content: output.value as unknown as - | string - | Array<{ type: 'text'; text: string }>, - cache_control: cacheControl, - }); - } else if (providerToolName === 'code_execution') { - const output = part.output; - - // Handle error types for code_execution tools (e.g., from programmatic tool calling) - if ( - output.type === 'error-text' || - output.type === 'error-json' - ) { - let errorInfo: { type?: string; errorCode?: string } = {}; - try { - if (typeof output.value === 'string') { - errorInfo = JSON.parse(output.value); - } else if ( - typeof output.value === 'object' && - output.value !== null - ) { - errorInfo = output.value as typeof errorInfo; - } - } catch {} - - if (errorInfo.type === 'code_execution_tool_result_error') { - anthropicContent.push({ - type: 'code_execution_tool_result', - tool_use_id: part.toolCallId, - content: { - type: 'code_execution_tool_result_error' as const, - error_code: errorInfo.errorCode ?? 'unknown', - }, - cache_control: cacheControl, - }); - } else { - anthropicContent.push({ - type: 'bash_code_execution_tool_result', - tool_use_id: part.toolCallId, - cache_control: cacheControl, - content: { - type: 'bash_code_execution_tool_result_error' as const, - error_code: errorInfo.errorCode ?? 'unknown', - }, - }); - } - break; - } - - if (output.type !== 'json') { - warnings.push({ - type: 'other', - message: `provider executed tool result output type ${output.type} for tool ${part.toolName} is not supported`, - }); - - break; - } - - if ( - output.value == null || - typeof output.value !== 'object' || - !('type' in output.value) || - typeof output.value.type !== 'string' - ) { - warnings.push({ - type: 'other', - message: `provider executed tool result output value is not a valid code execution result for tool ${part.toolName}`, - }); - break; - } - - // to distinguish between code execution 20250522, 20250825, - // and encrypted results (from web_fetch_20260209/web_search_20260209 injection), - // we check the type property in output.value - if (output.value.type === 'code_execution_result') { - // code execution 20250522 - const codeExecutionOutput = await validateTypes({ - value: output.value, - schema: codeExecution_20250522OutputSchema, - }); - - anthropicContent.push({ - type: 'code_execution_tool_result', - tool_use_id: part.toolCallId, - content: { - type: codeExecutionOutput.type, - stdout: codeExecutionOutput.stdout, - stderr: codeExecutionOutput.stderr, - return_code: codeExecutionOutput.return_code, - content: codeExecutionOutput.content ?? [], - }, - cache_control: cacheControl, - }); - } else if ( - output.value.type === 'encrypted_code_execution_result' - ) { - // code execution 20260120 encrypted result - const codeExecutionOutput = await validateTypes({ - value: output.value, - schema: codeExecution_20260120OutputSchema, - }); - - if ( - codeExecutionOutput.type === - 'encrypted_code_execution_result' - ) { - anthropicContent.push({ - type: 'code_execution_tool_result', - tool_use_id: part.toolCallId, - content: { - type: codeExecutionOutput.type, - encrypted_stdout: - codeExecutionOutput.encrypted_stdout, - stderr: codeExecutionOutput.stderr, - return_code: codeExecutionOutput.return_code, - content: codeExecutionOutput.content ?? [], - }, - cache_control: cacheControl, - }); - } - } else { - // code execution 20250825 - const codeExecutionOutput = await validateTypes({ - value: output.value, - schema: codeExecution_20250825OutputSchema, - }); - - if (codeExecutionOutput.type === 'code_execution_result') { - anthropicContent.push({ - type: 'code_execution_tool_result', - tool_use_id: part.toolCallId, - content: { - type: codeExecutionOutput.type, - stdout: codeExecutionOutput.stdout, - stderr: codeExecutionOutput.stderr, - return_code: codeExecutionOutput.return_code, - content: codeExecutionOutput.content ?? [], - }, - cache_control: cacheControl, - }); - } else if ( - codeExecutionOutput.type === - 'bash_code_execution_result' || - codeExecutionOutput.type === - 'bash_code_execution_tool_result_error' - ) { - anthropicContent.push({ - type: 'bash_code_execution_tool_result', - tool_use_id: part.toolCallId, - cache_control: cacheControl, - content: codeExecutionOutput, - }); - } else { - anthropicContent.push({ - type: 'text_editor_code_execution_tool_result', - tool_use_id: part.toolCallId, - cache_control: cacheControl, - content: codeExecutionOutput, - }); - } - } - break; - } - - if (providerToolName === 'web_fetch') { - const output = part.output; - - if (output.type === 'error-json') { - let errorValue: { errorCode?: string } = {}; - try { - if (typeof output.value === 'string') { - errorValue = JSON.parse(output.value); - } else if ( - typeof output.value === 'object' && - output.value !== null - ) { - errorValue = output.value as typeof errorValue; - } - } catch { - // If parsing fails, treat the value as-is - const extractedErrorCode = ( - output.value as Record - )?.errorCode; - errorValue = { - errorCode: - typeof extractedErrorCode === 'string' - ? extractedErrorCode - : 'unavailable', - }; - } - - anthropicContent.push({ - type: 'web_fetch_tool_result', - tool_use_id: part.toolCallId, - content: { - type: 'web_fetch_tool_result_error', - error_code: errorValue.errorCode ?? 'unavailable', - }, - cache_control: cacheControl, - }); - - break; - } - - if (output.type !== 'json') { - warnings.push({ - type: 'other', - message: `provider executed tool result output type ${output.type} for tool ${part.toolName} is not supported`, - }); - - break; - } - - // ideally we'd switch schema based on the tool version (e.g. - // web_fetch_20260209 vs web_fetch_20250910), but since both - // versions share an identical output schema, we use one here. - const webFetchOutput = await validateTypes({ - value: output.value, - schema: webFetch_20250910OutputSchema, - }); - - anthropicContent.push({ - type: 'web_fetch_tool_result', - tool_use_id: part.toolCallId, - content: { - type: 'web_fetch_result', - url: webFetchOutput.url, - retrieved_at: webFetchOutput.retrievedAt, - content: { - type: 'document', - title: webFetchOutput.content.title, - citations: webFetchOutput.content.citations, - source: { - type: webFetchOutput.content.source.type, - media_type: webFetchOutput.content.source.mediaType, - data: webFetchOutput.content.source.data, - } as Extract< - AnthropicWebFetchToolResultContent['content'], - { type: 'web_fetch_result' } - >['content']['source'], - }, - }, - cache_control: cacheControl, - }); - - break; - } - - if (providerToolName === 'web_search') { - const output = part.output; - - if (output.type !== 'json') { - warnings.push({ - type: 'other', - message: `provider executed tool result output type ${output.type} for tool ${part.toolName} is not supported`, - }); - - break; - } - - // ideally we'd switch schema based on the tool version (e.g. - // web_search_20260209 vs web_search_20250305), but since both - // versions share an identical output schema, we use one here. - const webSearchOutput = await validateTypes({ - value: output.value, - schema: webSearch_20250305OutputSchema, - }); - - anthropicContent.push({ - type: 'web_search_tool_result', - tool_use_id: part.toolCallId, - content: webSearchOutput.map(result => ({ - url: result.url, - title: result.title, - page_age: result.pageAge, - encrypted_content: result.encryptedContent, - type: result.type, - })), - cache_control: cacheControl, - }); - - break; - } - - if ( - providerToolName === 'tool_search_tool_regex' || - providerToolName === 'tool_search_tool_bm25' - ) { - const output = part.output; - - if (output.type !== 'json') { - warnings.push({ - type: 'other', - message: `provider executed tool result output type ${output.type} for tool ${part.toolName} is not supported`, - }); - - break; - } - - const toolSearchOutput = await validateTypes({ - value: output.value, - schema: toolSearchOutputSchema, - }); - - // Convert tool references back to API format - const toolReferences = toolSearchOutput.map(ref => ({ - type: 'tool_reference' as const, - tool_name: ref.toolName, - })); - - anthropicContent.push({ - type: 'tool_search_tool_result', - tool_use_id: part.toolCallId, - content: { - type: 'tool_search_tool_search_result', - tool_references: toolReferences, - }, - cache_control: cacheControl, - }); - - break; - } - - warnings.push({ - type: 'other', - message: `provider executed tool result for tool ${part.toolName} is not supported`, - }); - - break; - } - } - } - } - - messages.push({ role: 'assistant', content: anthropicContent }); - - break; - } - - default: { - const _exhaustiveCheck: never = type; - throw new Error(`content type: ${_exhaustiveCheck}`); - } - } - } - - return { - prompt: { system, messages }, - betas, - }; -} - -type SystemBlock = { - type: 'system'; - messages: Array; -}; -type AssistantBlock = { - type: 'assistant'; - messages: Array; -}; -type UserBlock = { - type: 'user'; - messages: Array; -}; - -function groupIntoBlocks( - prompt: LanguageModelV3Prompt, -): Array { - const blocks: Array = []; - let currentBlock: SystemBlock | AssistantBlock | UserBlock | undefined = - undefined; - - for (const message of prompt) { - const { role } = message; - switch (role) { - case 'system': { - if (currentBlock?.type !== 'system') { - currentBlock = { type: 'system', messages: [] }; - blocks.push(currentBlock); - } - - currentBlock.messages.push(message); - break; - } - case 'assistant': { - if (currentBlock?.type !== 'assistant') { - currentBlock = { type: 'assistant', messages: [] }; - blocks.push(currentBlock); - } - - currentBlock.messages.push(message); - break; - } - case 'user': { - if (currentBlock?.type !== 'user') { - currentBlock = { type: 'user', messages: [] }; - blocks.push(currentBlock); - } - - currentBlock.messages.push(message); - break; - } - case 'tool': { - if (currentBlock?.type !== 'user') { - currentBlock = { type: 'user', messages: [] }; - blocks.push(currentBlock); - } - - currentBlock.messages.push(message); - break; - } - default: { - const _exhaustiveCheck: never = role; - throw new Error(`Unsupported role: ${_exhaustiveCheck}`); - } - } - } - - return blocks; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/forward-anthropic-container-id-from-last-step.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/forward-anthropic-container-id-from-last-step.ts deleted file mode 100644 index c2b356be6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/forward-anthropic-container-id-from-last-step.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { JSONObject } from '@ai-sdk/provider'; -import { AnthropicMessageMetadata } from './anthropic-message-metadata'; - -/** - * Sets the Anthropic container ID in the provider options based on - * any previous step's provider metadata. - * - * Searches backwards through steps to find the most recent container ID. - * You can use this function in `prepareStep` to forward the container ID between steps. - */ -export function forwardAnthropicContainerIdFromLastStep({ - steps, -}: { - steps: Array<{ - providerMetadata?: Record; - }>; -}): undefined | { providerOptions?: Record } { - // Search backwards through steps to find the most recent container ID - for (let i = steps.length - 1; i >= 0; i--) { - const containerId = ( - steps[i].providerMetadata?.anthropic as - | AnthropicMessageMetadata - | undefined - )?.container?.id; - - if (containerId) { - return { - providerOptions: { - anthropic: { - container: { id: containerId }, - }, - }, - }; - } - } - - return undefined; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/get-cache-control.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/get-cache-control.ts deleted file mode 100644 index 2c3018d83..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/get-cache-control.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { SharedV3Warning, SharedV3ProviderMetadata } from '@ai-sdk/provider'; -import { AnthropicCacheControl } from './anthropic-messages-api'; - -// Anthropic allows a maximum of 4 cache breakpoints per request -const MAX_CACHE_BREAKPOINTS = 4; - -// Helper function to extract cache_control from provider metadata -// Allows both cacheControl and cache_control for flexibility -function getCacheControl( - providerMetadata: SharedV3ProviderMetadata | undefined, -): AnthropicCacheControl | undefined { - const anthropic = providerMetadata?.anthropic; - - // allow both cacheControl and cache_control: - const cacheControlValue = anthropic?.cacheControl ?? anthropic?.cache_control; - - // Pass through value assuming it is of the correct type. - // The Anthropic API will validate the value. - return cacheControlValue as AnthropicCacheControl | undefined; -} - -export class CacheControlValidator { - private breakpointCount = 0; - private warnings: SharedV3Warning[] = []; - - getCacheControl( - providerMetadata: SharedV3ProviderMetadata | undefined, - context: { type: string; canCache: boolean }, - ): AnthropicCacheControl | undefined { - const cacheControlValue = getCacheControl(providerMetadata); - - if (!cacheControlValue) { - return undefined; - } - - // Validate that cache_control is allowed in this context - if (!context.canCache) { - this.warnings.push({ - type: 'unsupported', - feature: 'cache_control on non-cacheable context', - details: `cache_control cannot be set on ${context.type}. It will be ignored.`, - }); - return undefined; - } - - // Validate cache breakpoint limit - this.breakpointCount++; - if (this.breakpointCount > MAX_CACHE_BREAKPOINTS) { - this.warnings.push({ - type: 'unsupported', - feature: 'cacheControl breakpoint limit', - details: `Maximum ${MAX_CACHE_BREAKPOINTS} cache breakpoints exceeded (found ${this.breakpointCount}). This breakpoint will be ignored.`, - }); - return undefined; - } - - return cacheControlValue; - } - - getWarnings(): SharedV3Warning[] { - return this.warnings; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/index.ts deleted file mode 100644 index bb57c24a6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -export type { - AnthropicMessageMetadata, - AnthropicUsageIteration, -} from './anthropic-message-metadata'; -export type { - AnthropicLanguageModelOptions, - /** @deprecated Use `AnthropicLanguageModelOptions` instead. */ - AnthropicLanguageModelOptions as AnthropicProviderOptions, -} from './anthropic-messages-options'; -export type { AnthropicToolOptions } from './anthropic-prepare-tools'; -export { anthropic, createAnthropic } from './anthropic-provider'; -export type { - AnthropicProvider, - AnthropicProviderSettings, -} from './anthropic-provider'; -export { forwardAnthropicContainerIdFromLastStep } from './forward-anthropic-container-id-from-last-step'; -export { VERSION } from './version'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/internal/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/internal/index.ts deleted file mode 100644 index 42804b235..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/internal/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { AnthropicMessagesLanguageModel } from '../anthropic-messages-language-model'; -export { anthropicTools } from '../anthropic-tools'; -export type { AnthropicMessagesModelId } from '../anthropic-messages-options'; -export { prepareTools } from '../anthropic-prepare-tools'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/map-anthropic-stop-reason.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/map-anthropic-stop-reason.ts deleted file mode 100644 index 990690413..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/map-anthropic-stop-reason.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LanguageModelV3FinishReason } from '@ai-sdk/provider'; - -/** - * @see https://docs.anthropic.com/en/api/messages#response-stop-reason - */ -export function mapAnthropicStopReason({ - finishReason, - isJsonResponseFromTool, -}: { - finishReason: string | null | undefined; - isJsonResponseFromTool?: boolean; -}): LanguageModelV3FinishReason['unified'] { - switch (finishReason) { - case 'pause_turn': - case 'end_turn': - case 'stop_sequence': - return 'stop'; - case 'refusal': - return 'content-filter'; - case 'tool_use': - return isJsonResponseFromTool ? 'stop' : 'tool-calls'; - case 'max_tokens': - case 'model_context_window_exceeded': - return 'length'; - case 'compaction': - return 'other'; - default: - return 'other'; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/bash_20241022.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/bash_20241022.ts deleted file mode 100644 index 74c0fd61f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/bash_20241022.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { - createProviderToolFactory, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -const bash_20241022InputSchema = lazySchema(() => - zodSchema( - z.object({ - command: z.string(), - restart: z.boolean().optional(), - }), - ), -); - -export const bash_20241022 = createProviderToolFactory< - { - /** - * The bash command to run. Required unless the tool is being restarted. - */ - command: string; - - /** - * Specifying true will restart this tool. Otherwise, leave this unspecified. - */ - restart?: boolean; - }, - {} ->({ - id: 'anthropic.bash_20241022', - inputSchema: bash_20241022InputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/bash_20250124.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/bash_20250124.ts deleted file mode 100644 index 901d6ff50..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/bash_20250124.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { - createProviderToolFactory, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -const bash_20250124InputSchema = lazySchema(() => - zodSchema( - z.object({ - command: z.string(), - restart: z.boolean().optional(), - }), - ), -); - -export const bash_20250124 = createProviderToolFactory< - { - /** - * The bash command to run. Required unless the tool is being restarted. - */ - command: string; - - /** - * Specifying true will restart this tool. Otherwise, leave this unspecified. - */ - restart?: boolean; - }, - {} ->({ - id: 'anthropic.bash_20250124', - inputSchema: bash_20250124InputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/code-execution_20250522.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/code-execution_20250522.ts deleted file mode 100644 index 5d92aef0c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/code-execution_20250522.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const codeExecution_20250522OutputSchema = lazySchema(() => - zodSchema( - z.object({ - type: z.literal('code_execution_result'), - stdout: z.string(), - stderr: z.string(), - return_code: z.number(), - content: z - .array( - z.object({ - type: z.literal('code_execution_output'), - file_id: z.string(), - }), - ) - .optional() - .default([]), - }), - ), -); - -const codeExecution_20250522InputSchema = lazySchema(() => - zodSchema( - z.object({ - code: z.string(), - }), - ), -); - -const factory = createProviderToolFactoryWithOutputSchema< - { - /** - * The Python code to execute. - */ - code: string; - }, - { - type: 'code_execution_result'; - stdout: string; - stderr: string; - return_code: number; - content: Array<{ type: 'code_execution_output'; file_id: string }>; - }, - {} ->({ - id: 'anthropic.code_execution_20250522', - inputSchema: codeExecution_20250522InputSchema, - outputSchema: codeExecution_20250522OutputSchema, -}); - -export const codeExecution_20250522 = ( - args: Parameters[0] = {}, -) => { - return factory(args); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/code-execution_20250825.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/code-execution_20250825.ts deleted file mode 100644 index 30a21e73c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/code-execution_20250825.ts +++ /dev/null @@ -1,281 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const codeExecution_20250825OutputSchema = lazySchema(() => - zodSchema( - z.discriminatedUnion('type', [ - z.object({ - type: z.literal('code_execution_result'), - stdout: z.string(), - stderr: z.string(), - return_code: z.number(), - content: z - .array( - z.object({ - type: z.literal('code_execution_output'), - file_id: z.string(), - }), - ) - .optional() - .default([]), - }), - z.object({ - type: z.literal('bash_code_execution_result'), - content: z.array( - z.object({ - type: z.literal('bash_code_execution_output'), - file_id: z.string(), - }), - ), - stdout: z.string(), - stderr: z.string(), - return_code: z.number(), - }), - z.object({ - type: z.literal('bash_code_execution_tool_result_error'), - error_code: z.string(), - }), - z.object({ - type: z.literal('text_editor_code_execution_tool_result_error'), - error_code: z.string(), - }), - z.object({ - type: z.literal('text_editor_code_execution_view_result'), - content: z.string(), - file_type: z.string(), - num_lines: z.number().nullable(), - start_line: z.number().nullable(), - total_lines: z.number().nullable(), - }), - z.object({ - type: z.literal('text_editor_code_execution_create_result'), - is_file_update: z.boolean(), - }), - z.object({ - type: z.literal('text_editor_code_execution_str_replace_result'), - lines: z.array(z.string()).nullable(), - new_lines: z.number().nullable(), - new_start: z.number().nullable(), - old_lines: z.number().nullable(), - old_start: z.number().nullable(), - }), - ]), - ), -); - -export const codeExecution_20250825InputSchema = lazySchema(() => - zodSchema( - z.discriminatedUnion('type', [ - // Programmatic tool calling format (mapped from { code } by AI SDK) - z.object({ - type: z.literal('programmatic-tool-call'), - code: z.string(), - }), - z.object({ - type: z.literal('bash_code_execution'), - command: z.string(), - }), - z.discriminatedUnion('command', [ - z.object({ - type: z.literal('text_editor_code_execution'), - command: z.literal('view'), - path: z.string(), - }), - z.object({ - type: z.literal('text_editor_code_execution'), - command: z.literal('create'), - path: z.string(), - file_text: z.string().nullish(), - }), - z.object({ - type: z.literal('text_editor_code_execution'), - command: z.literal('str_replace'), - path: z.string(), - old_str: z.string(), - new_str: z.string(), - }), - ]), - ]), - ), -); - -const factory = createProviderToolFactoryWithOutputSchema< - | { - type: 'programmatic-tool-call'; - /** - * Programmatic tool calling: Python code to execute when code_execution - * is used with allowedCallers to trigger client-executed tools. - */ - code: string; - } - | { - type: 'bash_code_execution'; - - /** - * Shell command to execute. - */ - command: string; - } - | { - type: 'text_editor_code_execution'; - command: 'view'; - - /** - * The path to the file to view. - */ - path: string; - } - | { - type: 'text_editor_code_execution'; - command: 'create'; - - /** - * The path to the file to edit. - */ - path: string; - - /** - * The text of the file to edit. - */ - file_text?: string | null; - } - | { - type: 'text_editor_code_execution'; - command: 'str_replace'; - - /** - * The path to the file to edit. - */ - path: string; - - /** - * The string to replace. - */ - old_str: string; - - /** - * The new string to replace the old string with. - */ - new_str: string; - }, - | { - /** - * Programmatic tool calling result: returned when code_execution runs code - * that calls client-executed tools via allowedCallers. - */ - type: 'code_execution_result'; - - /** - * Output from successful execution - */ - stdout: string; - - /** - * Error messages if execution fails - */ - stderr: string; - - /** - * 0 for success, non-zero for failure - */ - return_code: number; - - /** - * Output file Id list - */ - content: Array<{ type: 'code_execution_output'; file_id: string }>; - } - | { - type: 'bash_code_execution_result'; - - /** - * Output file Id list - */ - content: Array<{ - type: 'bash_code_execution_output'; - file_id: string; - }>; - - /** - * Output from successful execution - */ - stdout: string; - - /** - * Error messages if execution fails - */ - stderr: string; - - /** - * 0 for success, non-zero for failure - */ - return_code: number; - } - | { - type: 'bash_code_execution_tool_result_error'; - - /** - * Available options: invalid_tool_input, unavailable, too_many_requests, - * execution_time_exceeded, output_file_too_large. - */ - error_code: string; - } - | { - type: 'text_editor_code_execution_tool_result_error'; - - /** - * Available options: invalid_tool_input, unavailable, too_many_requests, - * execution_time_exceeded, file_not_found. - */ - error_code: string; - } - | { - type: 'text_editor_code_execution_view_result'; - - content: string; - - /** - * The type of the file. Available options: text, image, pdf. - */ - file_type: string; - - num_lines: number | null; - start_line: number | null; - total_lines: number | null; - } - | { - type: 'text_editor_code_execution_create_result'; - - is_file_update: boolean; - } - | { - type: 'text_editor_code_execution_str_replace_result'; - - lines: string[] | null; - new_lines: number | null; - new_start: number | null; - old_lines: number | null; - old_start: number | null; - }, - { - // no arguments - } ->({ - id: 'anthropic.code_execution_20250825', - inputSchema: codeExecution_20250825InputSchema, - outputSchema: codeExecution_20250825OutputSchema, - // Programmatic tool calling: tool results may be deferred to a later turn - // when code execution triggers a client-executed tool that needs to be - // resolved before the code execution result can be returned. - supportsDeferredResults: true, -}); - -export const codeExecution_20250825 = ( - args: Parameters[0] = {}, -) => { - return factory(args); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/code-execution_20260120.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/code-execution_20260120.ts deleted file mode 100644 index cfa2e32fa..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/code-execution_20260120.ts +++ /dev/null @@ -1,315 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const codeExecution_20260120OutputSchema = lazySchema(() => - zodSchema( - z.discriminatedUnion('type', [ - z.object({ - type: z.literal('code_execution_result'), - stdout: z.string(), - stderr: z.string(), - return_code: z.number(), - content: z - .array( - z.object({ - type: z.literal('code_execution_output'), - file_id: z.string(), - }), - ) - .optional() - .default([]), - }), - z.object({ - type: z.literal('encrypted_code_execution_result'), - encrypted_stdout: z.string(), - stderr: z.string(), - return_code: z.number(), - content: z - .array( - z.object({ - type: z.literal('code_execution_output'), - file_id: z.string(), - }), - ) - .optional() - .default([]), - }), - z.object({ - type: z.literal('bash_code_execution_result'), - content: z.array( - z.object({ - type: z.literal('bash_code_execution_output'), - file_id: z.string(), - }), - ), - stdout: z.string(), - stderr: z.string(), - return_code: z.number(), - }), - z.object({ - type: z.literal('bash_code_execution_tool_result_error'), - error_code: z.string(), - }), - z.object({ - type: z.literal('text_editor_code_execution_tool_result_error'), - error_code: z.string(), - }), - z.object({ - type: z.literal('text_editor_code_execution_view_result'), - content: z.string(), - file_type: z.string(), - num_lines: z.number().nullable(), - start_line: z.number().nullable(), - total_lines: z.number().nullable(), - }), - z.object({ - type: z.literal('text_editor_code_execution_create_result'), - is_file_update: z.boolean(), - }), - z.object({ - type: z.literal('text_editor_code_execution_str_replace_result'), - lines: z.array(z.string()).nullable(), - new_lines: z.number().nullable(), - new_start: z.number().nullable(), - old_lines: z.number().nullable(), - old_start: z.number().nullable(), - }), - ]), - ), -); - -export const codeExecution_20260120InputSchema = lazySchema(() => - zodSchema( - z.discriminatedUnion('type', [ - z.object({ - type: z.literal('programmatic-tool-call'), - code: z.string(), - }), - z.object({ - type: z.literal('bash_code_execution'), - command: z.string(), - }), - z.discriminatedUnion('command', [ - z.object({ - type: z.literal('text_editor_code_execution'), - command: z.literal('view'), - path: z.string(), - }), - z.object({ - type: z.literal('text_editor_code_execution'), - command: z.literal('create'), - path: z.string(), - file_text: z.string().nullish(), - }), - z.object({ - type: z.literal('text_editor_code_execution'), - command: z.literal('str_replace'), - path: z.string(), - old_str: z.string(), - new_str: z.string(), - }), - ]), - ]), - ), -); - -const factory = createProviderToolFactoryWithOutputSchema< - | { - type: 'programmatic-tool-call'; - /** - * Programmatic tool calling: Python code to execute when code_execution - * is used with allowedCallers to trigger client-executed tools. - */ - code: string; - } - | { - type: 'bash_code_execution'; - - /** - * Shell command to execute. - */ - command: string; - } - | { - type: 'text_editor_code_execution'; - command: 'view'; - - /** - * The path to the file to view. - */ - path: string; - } - | { - type: 'text_editor_code_execution'; - command: 'create'; - - /** - * The path to the file to edit. - */ - path: string; - - /** - * The text of the file to edit. - */ - file_text?: string | null; - } - | { - type: 'text_editor_code_execution'; - command: 'str_replace'; - - /** - * The path to the file to edit. - */ - path: string; - - /** - * The string to replace. - */ - old_str: string; - - /** - * The new string to replace the old string with. - */ - new_str: string; - }, - | { - /** - * Programmatic tool calling result: returned when code_execution runs code - * that calls client-executed tools via allowedCallers. - */ - type: 'code_execution_result'; - - /** - * Output from successful execution - */ - stdout: string; - - /** - * Error messages if execution fails - */ - stderr: string; - - /** - * 0 for success, non-zero for failure - */ - return_code: number; - - /** - * Output file Id list - */ - content: Array<{ type: 'code_execution_output'; file_id: string }>; - } - | { - type: 'encrypted_code_execution_result'; - - /** - * Encrypted output from successful execution - */ - encrypted_stdout: string; - - /** - * Error messages if execution fails - */ - stderr: string; - - /** - * 0 for success, non-zero for failure - */ - return_code: number; - - /** - * Output file Id list - */ - content: Array<{ type: 'code_execution_output'; file_id: string }>; - } - | { - type: 'bash_code_execution_result'; - - /** - * Output file Id list - */ - content: Array<{ - type: 'bash_code_execution_output'; - file_id: string; - }>; - - /** - * Output from successful execution - */ - stdout: string; - - /** - * Error messages if execution fails - */ - stderr: string; - - /** - * 0 for success, non-zero for failure - */ - return_code: number; - } - | { - type: 'bash_code_execution_tool_result_error'; - - /** - * Available options: invalid_tool_input, unavailable, too_many_requests, - * execution_time_exceeded, output_file_too_large. - */ - error_code: string; - } - | { - type: 'text_editor_code_execution_tool_result_error'; - - /** - * Available options: invalid_tool_input, unavailable, too_many_requests, - * execution_time_exceeded, file_not_found. - */ - error_code: string; - } - | { - type: 'text_editor_code_execution_view_result'; - - content: string; - - /** - * The type of the file. Available options: text, image, pdf. - */ - file_type: string; - - num_lines: number | null; - start_line: number | null; - total_lines: number | null; - } - | { - type: 'text_editor_code_execution_create_result'; - - is_file_update: boolean; - } - | { - type: 'text_editor_code_execution_str_replace_result'; - - lines: string[] | null; - new_lines: number | null; - new_start: number | null; - old_lines: number | null; - old_start: number | null; - }, - { - // no arguments - } ->({ - id: 'anthropic.code_execution_20260120', - inputSchema: codeExecution_20260120InputSchema, - outputSchema: codeExecution_20260120OutputSchema, - supportsDeferredResults: true, -}); - -export const codeExecution_20260120 = ( - args: Parameters[0] = {}, -) => { - return factory(args); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/computer_20241022.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/computer_20241022.ts deleted file mode 100644 index de7b99f69..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/computer_20241022.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { - createProviderToolFactory, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -const computer_20241022InputSchema = lazySchema(() => - zodSchema( - z.object({ - action: z.enum([ - 'key', - 'type', - 'mouse_move', - 'left_click', - 'left_click_drag', - 'right_click', - 'middle_click', - 'double_click', - 'screenshot', - 'cursor_position', - ]), - coordinate: z.array(z.number().int()).optional(), - text: z.string().optional(), - }), - ), -); - -export const computer_20241022 = createProviderToolFactory< - { - /** - * The action to perform. The available actions are: - * - `key`: Press a key or key-combination on the keyboard. - * - This supports xdotool's `key` syntax. - * - Examples: "a", "Return", "alt+Tab", "ctrl+s", "Up", "KP_0" (for the numpad 0 key). - * - `type`: Type a string of text on the keyboard. - * - `cursor_position`: Get the current (x, y) pixel coordinate of the cursor on the screen. - * - `mouse_move`: Move the cursor to a specified (x, y) pixel coordinate on the screen. - * - `left_click`: Click the left mouse button. - * - `left_click_drag`: Click and drag the cursor to a specified (x, y) pixel coordinate on the screen. - * - `right_click`: Click the right mouse button. - * - `middle_click`: Click the middle mouse button. - * - `double_click`: Double-click the left mouse button. - * - `screenshot`: Take a screenshot of the screen. - */ - action: - | 'key' - | 'type' - | 'mouse_move' - | 'left_click' - | 'left_click_drag' - | 'right_click' - | 'middle_click' - | 'double_click' - | 'screenshot' - | 'cursor_position'; - - /** - * (x, y): The x (pixels from the left edge) and y (pixels from the top edge) coordinates to move the mouse to. Required only by `action=mouse_move` and `action=left_click_drag`. - */ - coordinate?: number[]; - - /** - * Required only by `action=type` and `action=key`. - */ - text?: string; - }, - { - /** - * The width of the display being controlled by the model in pixels. - */ - displayWidthPx: number; - - /** - * The height of the display being controlled by the model in pixels. - */ - displayHeightPx: number; - - /** - * The display number to control (only relevant for X11 environments). If specified, the tool will be provided a display number in the tool definition. - */ - displayNumber?: number; - } ->({ - id: 'anthropic.computer_20241022', - inputSchema: computer_20241022InputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/computer_20250124.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/computer_20250124.ts deleted file mode 100644 index 2a111d231..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/computer_20250124.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { - createProviderToolFactory, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -const computer_20250124InputSchema = lazySchema(() => - zodSchema( - z.object({ - action: z.enum([ - 'key', - 'hold_key', - 'type', - 'cursor_position', - 'mouse_move', - 'left_mouse_down', - 'left_mouse_up', - 'left_click', - 'left_click_drag', - 'right_click', - 'middle_click', - 'double_click', - 'triple_click', - 'scroll', - 'wait', - 'screenshot', - ]), - coordinate: z.tuple([z.number().int(), z.number().int()]).optional(), - duration: z.number().optional(), - scroll_amount: z.number().optional(), - scroll_direction: z.enum(['up', 'down', 'left', 'right']).optional(), - start_coordinate: z - .tuple([z.number().int(), z.number().int()]) - .optional(), - text: z.string().optional(), - }), - ), -); - -export const computer_20250124 = createProviderToolFactory< - { - /** - * - `key`: Press a key or key-combination on the keyboard. - * - This supports xdotool's `key` syntax. - * - Examples: "a", "Return", "alt+Tab", "ctrl+s", "Up", "KP_0" (for the numpad 0 key). - * - `hold_key`: Hold down a key or multiple keys for a specified duration (in seconds). Supports the same syntax as `key`. - * - `type`: Type a string of text on the keyboard. - * - `cursor_position`: Get the current (x, y) pixel coordinate of the cursor on the screen. - * - `mouse_move`: Move the cursor to a specified (x, y) pixel coordinate on the screen. - * - `left_mouse_down`: Press the left mouse button. - * - `left_mouse_up`: Release the left mouse button. - * - `left_click`: Click the left mouse button at the specified (x, y) pixel coordinate on the screen. You can also include a key combination to hold down while clicking using the `text` parameter. - * - `left_click_drag`: Click and drag the cursor from `start_coordinate` to a specified (x, y) pixel coordinate on the screen. - * - `right_click`: Click the right mouse button at the specified (x, y) pixel coordinate on the screen. - * - `middle_click`: Click the middle mouse button at the specified (x, y) pixel coordinate on the screen. - * - `double_click`: Double-click the left mouse button at the specified (x, y) pixel coordinate on the screen. - * - `triple_click`: Triple-click the left mouse button at the specified (x, y) pixel coordinate on the screen. - * - `scroll`: Scroll the screen in a specified direction by a specified amount of clicks of the scroll wheel, at the specified (x, y) pixel coordinate. DO NOT use PageUp/PageDown to scroll. - * - `wait`: Wait for a specified duration (in seconds). - * - `screenshot`: Take a screenshot of the screen. - */ - action: - | 'key' - | 'hold_key' - | 'type' - | 'cursor_position' - | 'mouse_move' - | 'left_mouse_down' - | 'left_mouse_up' - | 'left_click' - | 'left_click_drag' - | 'right_click' - | 'middle_click' - | 'double_click' - | 'triple_click' - | 'scroll' - | 'wait' - | 'screenshot'; - - /** - * (x, y): The x (pixels from the left edge) and y (pixels from the top edge) coordinates to move the mouse to. Required only by `action=mouse_move` and `action=left_click_drag`. - */ - coordinate?: [number, number]; - - /** - * The duration to hold the key down for. Required only by `action=hold_key` and `action=wait`. - */ - duration?: number; - - /** - * The number of 'clicks' to scroll. Required only by `action=scroll`. - */ - scroll_amount?: number; - - /** - * The direction to scroll the screen. Required only by `action=scroll`. - */ - scroll_direction?: 'up' | 'down' | 'left' | 'right'; - - /** - * (x, y): The x (pixels from the left edge) and y (pixels from the top edge) coordinates to start the drag from. Required only by `action=left_click_drag`. - */ - start_coordinate?: [number, number]; - - /** - * Required only by `action=type`, `action=key`, and `action=hold_key`. Can also be used by click or scroll actions to hold down keys while clicking or scrolling. - */ - text?: string; - }, - { - /** - * The width of the display being controlled by the model in pixels. - */ - displayWidthPx: number; - - /** - * The height of the display being controlled by the model in pixels. - */ - displayHeightPx: number; - - /** - * The display number to control (only relevant for X11 environments). If specified, the tool will be provided a display number in the tool definition. - */ - displayNumber?: number; - } ->({ - id: 'anthropic.computer_20250124', - inputSchema: computer_20250124InputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/computer_20251124.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/computer_20251124.ts deleted file mode 100644 index 9c7b397f8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/computer_20251124.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { - createProviderToolFactory, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -const computer_20251124InputSchema = lazySchema(() => - zodSchema( - z.object({ - action: z.enum([ - 'key', - 'hold_key', - 'type', - 'cursor_position', - 'mouse_move', - 'left_mouse_down', - 'left_mouse_up', - 'left_click', - 'left_click_drag', - 'right_click', - 'middle_click', - 'double_click', - 'triple_click', - 'scroll', - 'wait', - 'screenshot', - 'zoom', - ]), - coordinate: z.tuple([z.number().int(), z.number().int()]).optional(), - duration: z.number().optional(), - region: z - .tuple([ - z.number().int(), - z.number().int(), - z.number().int(), - z.number().int(), - ]) - .optional(), - scroll_amount: z.number().optional(), - scroll_direction: z.enum(['up', 'down', 'left', 'right']).optional(), - start_coordinate: z - .tuple([z.number().int(), z.number().int()]) - .optional(), - text: z.string().optional(), - }), - ), -); - -export const computer_20251124 = createProviderToolFactory< - { - /** - * - `key`: Press a key or key-combination on the keyboard. - * - This supports xdotool's `key` syntax. - * - Examples: "a", "Return", "alt+Tab", "ctrl+s", "Up", "KP_0" (for the numpad 0 key). - * - `hold_key`: Hold down a key or multiple keys for a specified duration (in seconds). Supports the same syntax as `key`. - * - `type`: Type a string of text on the keyboard. - * - `cursor_position`: Get the current (x, y) pixel coordinate of the cursor on the screen. - * - `mouse_move`: Move the cursor to a specified (x, y) pixel coordinate on the screen. - * - `left_mouse_down`: Press the left mouse button. - * - `left_mouse_up`: Release the left mouse button. - * - `left_click`: Click the left mouse button at the specified (x, y) pixel coordinate on the screen. You can also include a key combination to hold down while clicking using the `text` parameter. - * - `left_click_drag`: Click and drag the cursor from `start_coordinate` to a specified (x, y) pixel coordinate on the screen. - * - `right_click`: Click the right mouse button at the specified (x, y) pixel coordinate on the screen. - * - `middle_click`: Click the middle mouse button at the specified (x, y) pixel coordinate on the screen. - * - `double_click`: Double-click the left mouse button at the specified (x, y) pixel coordinate on the screen. - * - `triple_click`: Triple-click the left mouse button at the specified (x, y) pixel coordinate on the screen. - * - `scroll`: Scroll the screen in a specified direction by a specified amount of clicks of the scroll wheel, at the specified (x, y) pixel coordinate. DO NOT use PageUp/PageDown to scroll. - * - `wait`: Wait for a specified duration (in seconds). - * - `screenshot`: Take a screenshot of the screen. - * - `zoom`: View a specific region of the screen at full resolution. Requires `enableZoom: true` in tool definition. Takes a `region` parameter with coordinates `[x1, y1, x2, y2]` defining top-left and bottom-right corners of the area to inspect. - */ - action: - | 'key' - | 'hold_key' - | 'type' - | 'cursor_position' - | 'mouse_move' - | 'left_mouse_down' - | 'left_mouse_up' - | 'left_click' - | 'left_click_drag' - | 'right_click' - | 'middle_click' - | 'double_click' - | 'triple_click' - | 'scroll' - | 'wait' - | 'screenshot' - | 'zoom'; - - /** - * (x, y): The x (pixels from the left edge) and y (pixels from the top edge) coordinates to move the mouse to. Required only by `action=mouse_move` and `action=left_click_drag`. - */ - coordinate?: [number, number]; - - /** - * The duration to hold the key down for. Required only by `action=hold_key` and `action=wait`. - */ - duration?: number; - - /** - * [x1, y1, x2, y2]: The coordinates defining the region to zoom into. x1, y1 is the top-left corner and x2, y2 is the bottom-right corner. Required only by `action=zoom`. - */ - region?: [number, number, number, number]; - - /** - * The number of 'clicks' to scroll. Required only by `action=scroll`. - */ - scroll_amount?: number; - - /** - * The direction to scroll the screen. Required only by `action=scroll`. - */ - scroll_direction?: 'up' | 'down' | 'left' | 'right'; - - /** - * (x, y): The x (pixels from the left edge) and y (pixels from the top edge) coordinates to start the drag from. Required only by `action=left_click_drag`. - */ - start_coordinate?: [number, number]; - - /** - * Required only by `action=type`, `action=key`, and `action=hold_key`. Can also be used by click or scroll actions to hold down keys while clicking or scrolling. - */ - text?: string; - }, - { - /** - * The width of the display being controlled by the model in pixels. - */ - displayWidthPx: number; - - /** - * The height of the display being controlled by the model in pixels. - */ - displayHeightPx: number; - - /** - * The display number to control (only relevant for X11 environments). If specified, the tool will be provided a display number in the tool definition. - */ - displayNumber?: number; - - /** - * Enable zoom action. Set to true to allow Claude to zoom into specific screen regions. Default: false. - */ - enableZoom?: boolean; - } ->({ - id: 'anthropic.computer_20251124', - inputSchema: computer_20251124InputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/memory_20250818.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/memory_20250818.ts deleted file mode 100644 index f4a103028..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/memory_20250818.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { - createProviderToolFactory, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -const memory_20250818InputSchema = lazySchema(() => - zodSchema( - z.discriminatedUnion('command', [ - z.object({ - command: z.literal('view'), - path: z.string(), - view_range: z.tuple([z.number(), z.number()]).optional(), - }), - z.object({ - command: z.literal('create'), - path: z.string(), - file_text: z.string(), - }), - z.object({ - command: z.literal('str_replace'), - path: z.string(), - old_str: z.string(), - new_str: z.string(), - }), - z.object({ - command: z.literal('insert'), - path: z.string(), - insert_line: z.number(), - insert_text: z.string(), - }), - z.object({ - command: z.literal('delete'), - path: z.string(), - }), - z.object({ - command: z.literal('rename'), - old_path: z.string(), - new_path: z.string(), - }), - ]), - ), -); - -export const memory_20250818 = createProviderToolFactory< - | { command: 'view'; path: string; view_range?: [number, number] } - | { command: 'create'; path: string; file_text: string } - | { command: 'str_replace'; path: string; old_str: string; new_str: string } - | { - command: 'insert'; - path: string; - insert_line: number; - insert_text: string; - } - | { command: 'delete'; path: string } - | { command: 'rename'; old_path: string; new_path: string }, - {} ->({ - id: 'anthropic.memory_20250818', - inputSchema: memory_20250818InputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/text-editor_20241022.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/text-editor_20241022.ts deleted file mode 100644 index 7263d7673..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/text-editor_20241022.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { - createProviderToolFactory, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -const textEditor_20241022InputSchema = lazySchema(() => - zodSchema( - z.object({ - command: z.enum(['view', 'create', 'str_replace', 'insert', 'undo_edit']), - path: z.string(), - file_text: z.string().optional(), - insert_line: z.number().int().optional(), - new_str: z.string().optional(), - insert_text: z.string().optional(), - old_str: z.string().optional(), - view_range: z.array(z.number().int()).optional(), - }), - ), -); - -export const textEditor_20241022 = createProviderToolFactory< - { - /** - * The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`, `undo_edit`. - */ - command: 'view' | 'create' | 'str_replace' | 'insert' | 'undo_edit'; - - /** - * Absolute path to file or directory, e.g. `/repo/file.py` or `/repo`. - */ - path: string; - - /** - * Required parameter of `create` command, with the content of the file to be created. - */ - file_text?: string; - - /** - * Required parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`. - */ - insert_line?: number; - - /** - * Optional parameter of `str_replace` command containing the new string (if not given, no string will be added). - */ - new_str?: string; - - /** - * Required parameter of `insert` command containing the text to insert. - */ - insert_text?: string; - - /** - * Required parameter of `str_replace` command containing the string in `path` to replace. - */ - old_str?: string; - - /** - * Optional parameter of `view` command when `path` points to a file. If none is given, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file. - */ - view_range?: number[]; - }, - {} ->({ - id: 'anthropic.text_editor_20241022', - inputSchema: textEditor_20241022InputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/text-editor_20250124.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/text-editor_20250124.ts deleted file mode 100644 index 9dfb9dbfd..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/text-editor_20250124.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { - createProviderToolFactory, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -const textEditor_20250124InputSchema = lazySchema(() => - zodSchema( - z.object({ - command: z.enum(['view', 'create', 'str_replace', 'insert', 'undo_edit']), - path: z.string(), - file_text: z.string().optional(), - insert_line: z.number().int().optional(), - new_str: z.string().optional(), - insert_text: z.string().optional(), - old_str: z.string().optional(), - view_range: z.array(z.number().int()).optional(), - }), - ), -); - -export const textEditor_20250124 = createProviderToolFactory< - { - /** - * The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`, `undo_edit`. - */ - command: 'view' | 'create' | 'str_replace' | 'insert' | 'undo_edit'; - - /** - * Absolute path to file or directory, e.g. `/repo/file.py` or `/repo`. - */ - path: string; - - /** - * Required parameter of `create` command, with the content of the file to be created. - */ - file_text?: string; - - /** - * Required parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`. - */ - insert_line?: number; - - /** - * Optional parameter of `str_replace` command containing the new string (if not given, no string will be added). - */ - new_str?: string; - - /** - * Required parameter of `insert` command containing the text to insert. - */ - insert_text?: string; - - /** - * Required parameter of `str_replace` command containing the string in `path` to replace. - */ - old_str?: string; - - /** - * Optional parameter of `view` command when `path` points to a file. If none is given, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file. - */ - view_range?: number[]; - }, - {} ->({ - id: 'anthropic.text_editor_20250124', - inputSchema: textEditor_20250124InputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/text-editor_20250429.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/text-editor_20250429.ts deleted file mode 100644 index 86e468ea2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/text-editor_20250429.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { - createProviderToolFactory, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -const textEditor_20250429InputSchema = lazySchema(() => - zodSchema( - z.object({ - command: z.enum(['view', 'create', 'str_replace', 'insert']), - path: z.string(), - file_text: z.string().optional(), - insert_line: z.number().int().optional(), - new_str: z.string().optional(), - insert_text: z.string().optional(), - old_str: z.string().optional(), - view_range: z.array(z.number().int()).optional(), - }), - ), -); - -export const textEditor_20250429 = createProviderToolFactory< - { - /** - * The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`. - * Note: `undo_edit` is not supported in Claude 4 models. - */ - command: 'view' | 'create' | 'str_replace' | 'insert'; - - /** - * Absolute path to file or directory, e.g. `/repo/file.py` or `/repo`. - */ - path: string; - - /** - * Required parameter of `create` command, with the content of the file to be created. - */ - file_text?: string; - - /** - * Required parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`. - */ - insert_line?: number; - - /** - * Optional parameter of `str_replace` command containing the new string (if not given, no string will be added). - */ - new_str?: string; - - /** - * Required parameter of `insert` command containing the text to insert. - */ - insert_text?: string; - - /** - * Required parameter of `str_replace` command containing the string in `path` to replace. - */ - old_str?: string; - - /** - * Optional parameter of `view` command when `path` points to a file. If none is given, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file. - */ - view_range?: number[]; - }, - {} ->({ - id: 'anthropic.text_editor_20250429', - inputSchema: textEditor_20250429InputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/text-editor_20250728.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/text-editor_20250728.ts deleted file mode 100644 index 10c820ec0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/text-editor_20250728.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { createProviderToolFactory } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import { lazySchema, zodSchema } from '@ai-sdk/provider-utils'; - -export const textEditor_20250728ArgsSchema = lazySchema(() => - zodSchema( - z.object({ - maxCharacters: z.number().optional(), - }), - ), -); - -const textEditor_20250728InputSchema = lazySchema(() => - zodSchema( - z.object({ - command: z.enum(['view', 'create', 'str_replace', 'insert']), - path: z.string(), - file_text: z.string().optional(), - insert_line: z.number().int().optional(), - new_str: z.string().optional(), - insert_text: z.string().optional(), - old_str: z.string().optional(), - view_range: z.array(z.number().int()).optional(), - }), - ), -); - -const factory = createProviderToolFactory< - { - /** - * The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`. - * Note: `undo_edit` is not supported in Claude 4 models. - */ - command: 'view' | 'create' | 'str_replace' | 'insert'; - - /** - * Absolute path to file or directory, e.g. `/repo/file.py` or `/repo`. - */ - path: string; - - /** - * Required parameter of `create` command, with the content of the file to be created. - */ - file_text?: string; - - /** - * Required parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`. - */ - insert_line?: number; - - /** - * Optional parameter of `str_replace` command containing the new string (if not given, no string will be added). - */ - new_str?: string; - - /** - * Required parameter of `insert` command containing the text to insert. - */ - insert_text?: string; - - /** - * Required parameter of `str_replace` command containing the string in `path` to replace. - */ - old_str?: string; - - /** - * Optional parameter of `view` command when `path` points to a file. If none is given, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file. - */ - view_range?: number[]; - }, - { - /** - * Optional parameter to control truncation when viewing large files. Only compatible with text_editor_20250728 and later versions. - */ - maxCharacters?: number; - } ->({ - id: 'anthropic.text_editor_20250728', - inputSchema: textEditor_20250728InputSchema, -}); - -export const textEditor_20250728 = ( - args: Parameters[0] = {}, // default -) => { - return factory(args); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/tool-search-bm25_20251119.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/tool-search-bm25_20251119.ts deleted file mode 100644 index fa1a081c4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/tool-search-bm25_20251119.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -/** - * Output schema for tool search results - returns tool references - * that are automatically expanded into full tool definitions by the API. - */ -export const toolSearchBm25_20251119OutputSchema = lazySchema(() => - zodSchema( - z.array( - z.object({ - type: z.literal('tool_reference'), - toolName: z.string(), - }), - ), - ), -); - -/** - * Input schema for BM25-based tool search. - * Claude uses natural language queries to search for tools. - */ -const toolSearchBm25_20251119InputSchema = lazySchema(() => - zodSchema( - z.object({ - /** - * A natural language query to search for tools. - * Claude will use BM25 text search to find relevant tools. - */ - query: z.string(), - /** - * Maximum number of tools to return. Optional. - */ - limit: z.number().optional(), - }), - ), -); - -const factory = createProviderToolFactoryWithOutputSchema< - { - /** - * A natural language query to search for tools. - * Claude will use BM25 text search to find relevant tools. - */ - query: string; - /** - * Maximum number of tools to return. Optional. - */ - limit?: number; - }, - Array<{ - type: 'tool_reference'; - /** - * The name of the discovered tool. - */ - toolName: string; - }>, - {} ->({ - id: 'anthropic.tool_search_bm25_20251119', - inputSchema: toolSearchBm25_20251119InputSchema, - outputSchema: toolSearchBm25_20251119OutputSchema, - supportsDeferredResults: true, -}); - -/** - * Creates a tool search tool that uses BM25 (natural language) to find tools. - * - * The tool search tool enables Claude to work with hundreds or thousands of tools - * by dynamically discovering and loading them on-demand. Instead of loading all - * tool definitions into the context window upfront, Claude searches your tool - * catalog and loads only the tools it needs. - * - * When Claude uses this tool, it uses natural language queries (NOT regex patterns) - * to search for tools using BM25 text search. - * - * **Important**: This tool should never have `deferLoading: true` in providerOptions. - * - * @example - * ```ts - * import { anthropicTools } from '@ai-sdk/anthropic'; - * - * const tools = { - * toolSearch: anthropicTools.toolSearchBm25_20251119(), - * // Other tools with deferLoading... - * }; - * ``` - * - * @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-search-tool - */ -export const toolSearchBm25_20251119 = ( - args: Parameters[0] = {}, -) => { - return factory(args); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/tool-search-regex_20251119.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/tool-search-regex_20251119.ts deleted file mode 100644 index dacda51c7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/tool-search-regex_20251119.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -/** - * Output schema for tool search results - returns tool references - * that are automatically expanded into full tool definitions by the API. - */ -export const toolSearchRegex_20251119OutputSchema = lazySchema(() => - zodSchema( - z.array( - z.object({ - type: z.literal('tool_reference'), - toolName: z.string(), - }), - ), - ), -); - -/** - * Input schema for regex-based tool search. - * Claude constructs regex patterns using Python's re.search() syntax. - */ -const toolSearchRegex_20251119InputSchema = lazySchema(() => - zodSchema( - z.object({ - /** - * A regex pattern to search for tools. - * Uses Python re.search() syntax. Maximum 200 characters. - * - * Examples: - * - "weather" - matches tool names/descriptions containing "weather" - * - "get_.*_data" - matches tools like get_user_data, get_weather_data - * - "database.*query|query.*database" - OR patterns for flexibility - * - "(?i)slack" - case-insensitive search - */ - pattern: z.string(), - /** - * Maximum number of tools to return. Optional. - */ - limit: z.number().optional(), - }), - ), -); - -const factory = createProviderToolFactoryWithOutputSchema< - { - /** - * A regex pattern to search for tools. - * Uses Python re.search() syntax. Maximum 200 characters. - * - * Examples: - * - "weather" - matches tool names/descriptions containing "weather" - * - "get_.*_data" - matches tools like get_user_data, get_weather_data - * - "database.*query|query.*database" - OR patterns for flexibility - * - "(?i)slack" - case-insensitive search - */ - pattern: string; - /** - * Maximum number of tools to return. Optional. - */ - limit?: number; - }, - Array<{ - type: 'tool_reference'; - /** - * The name of the discovered tool. - */ - toolName: string; - }>, - {} ->({ - id: 'anthropic.tool_search_regex_20251119', - inputSchema: toolSearchRegex_20251119InputSchema, - outputSchema: toolSearchRegex_20251119OutputSchema, - supportsDeferredResults: true, -}); - -/** - * Creates a tool search tool that uses regex patterns to find tools. - * - * The tool search tool enables Claude to work with hundreds or thousands of tools - * by dynamically discovering and loading them on-demand. Instead of loading all - * tool definitions into the context window upfront, Claude searches your tool - * catalog and loads only the tools it needs. - * - * When Claude uses this tool, it constructs regex patterns using Python's - * re.search() syntax (NOT natural language queries). - * - * **Important**: This tool should never have `deferLoading: true` in providerOptions. - * - * @example - * ```ts - * import { anthropicTools } from '@ai-sdk/anthropic'; - * - * const tools = { - * toolSearch: anthropicTools.toolSearchRegex_20251119(), - * // Other tools with deferLoading... - * }; - * ``` - * - * @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-search-tool - */ -export const toolSearchRegex_20251119 = ( - args: Parameters[0] = {}, -) => { - return factory(args); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/web-fetch-20250910.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/web-fetch-20250910.ts deleted file mode 100644 index de8d33eed..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/web-fetch-20250910.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const webFetch_20250910ArgsSchema = lazySchema(() => - zodSchema( - z.object({ - maxUses: z.number().optional(), - allowedDomains: z.array(z.string()).optional(), - blockedDomains: z.array(z.string()).optional(), - citations: z.object({ enabled: z.boolean() }).optional(), - maxContentTokens: z.number().optional(), - }), - ), -); - -export const webFetch_20250910OutputSchema = lazySchema(() => - zodSchema( - z.object({ - type: z.literal('web_fetch_result'), - url: z.string(), - content: z.object({ - type: z.literal('document'), - title: z.string().nullable(), - citations: z.object({ enabled: z.boolean() }).optional(), - source: z.union([ - z.object({ - type: z.literal('base64'), - mediaType: z.literal('application/pdf'), - data: z.string(), - }), - z.object({ - type: z.literal('text'), - mediaType: z.literal('text/plain'), - data: z.string(), - }), - ]), - }), - retrievedAt: z.string().nullable(), - }), - ), -); - -const webFetch_20250910InputSchema = lazySchema(() => - zodSchema( - z.object({ - url: z.string(), - }), - ), -); - -const factory = createProviderToolFactoryWithOutputSchema< - { - /** - * The URL to fetch. - */ - url: string; - }, - { - type: 'web_fetch_result'; - - /** - * Fetched content URL - */ - url: string; - - /** - * Fetched content. - */ - content: { - type: 'document'; - - /** - * Title of the document - */ - title: string | null; - - /** - * Citation configuration for the document - */ - citations?: { enabled: boolean }; - - source: - | { - type: 'base64'; - mediaType: 'application/pdf'; - data: string; - } - | { - type: 'text'; - mediaType: 'text/plain'; - data: string; - }; - }; - - /** - * ISO 8601 timestamp when the content was retrieved - */ - retrievedAt: string | null; - }, - { - /** - * The maxUses parameter limits the number of web fetches performed - */ - maxUses?: number; - - /** - * Only fetch from these domains - */ - allowedDomains?: string[]; - - /** - * Never fetch from these domains - */ - blockedDomains?: string[]; - - /** - * Unlike web search where citations are always enabled, citations are optional for - * web fetch. Set "citations": {"enabled": true} to enable Claude to cite specific passages - * from fetched documents. - */ - citations?: { - enabled: boolean; - }; - - /** - * The maxContentTokens parameter limits the amount of content that will be included in the context. - */ - maxContentTokens?: number; - } ->({ - id: 'anthropic.web_fetch_20250910', - inputSchema: webFetch_20250910InputSchema, - outputSchema: webFetch_20250910OutputSchema, - supportsDeferredResults: true, -}); - -export const webFetch_20250910 = ( - args: Parameters[0] = {}, // default -) => { - return factory(args); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/web-fetch-20260209.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/web-fetch-20260209.ts deleted file mode 100644 index 80a208653..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/web-fetch-20260209.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const webFetch_20260209ArgsSchema = lazySchema(() => - zodSchema( - z.object({ - maxUses: z.number().optional(), - allowedDomains: z.array(z.string()).optional(), - blockedDomains: z.array(z.string()).optional(), - citations: z.object({ enabled: z.boolean() }).optional(), - maxContentTokens: z.number().optional(), - }), - ), -); - -export const webFetch_20260209OutputSchema = lazySchema(() => - zodSchema( - z.object({ - type: z.literal('web_fetch_result'), - url: z.string(), - content: z.object({ - type: z.literal('document'), - title: z.string().nullable(), - citations: z.object({ enabled: z.boolean() }).optional(), - source: z.union([ - z.object({ - type: z.literal('base64'), - mediaType: z.literal('application/pdf'), - data: z.string(), - }), - z.object({ - type: z.literal('text'), - mediaType: z.literal('text/plain'), - data: z.string(), - }), - ]), - }), - retrievedAt: z.string().nullable(), - }), - ), -); - -const webFetch_20260209InputSchema = lazySchema(() => - zodSchema( - z.object({ - url: z.string(), - }), - ), -); - -const factory = createProviderToolFactoryWithOutputSchema< - { - /** - * The URL to fetch. - */ - url: string; - }, - { - type: 'web_fetch_result'; - - /** - * Fetched content URL - */ - url: string; - - /** - * Fetched content. - */ - content: { - type: 'document'; - - /** - * Title of the document - */ - title: string | null; - - /** - * Citation configuration for the document - */ - citations?: { enabled: boolean }; - - source: - | { - type: 'base64'; - mediaType: 'application/pdf'; - data: string; - } - | { - type: 'text'; - mediaType: 'text/plain'; - data: string; - }; - }; - - /** - * ISO 8601 timestamp when the content was retrieved - */ - retrievedAt: string | null; - }, - { - /** - * The maxUses parameter limits the number of web fetches performed - */ - maxUses?: number; - - /** - * Only fetch from these domains - */ - allowedDomains?: string[]; - - /** - * Never fetch from these domains - */ - blockedDomains?: string[]; - - /** - * Unlike web search where citations are always enabled, citations are optional for - * web fetch. Set "citations": {"enabled": true} to enable Claude to cite specific passages - * from fetched documents. - */ - citations?: { - enabled: boolean; - }; - - /** - * The maxContentTokens parameter limits the amount of content that will be included in the context. - */ - maxContentTokens?: number; - } ->({ - id: 'anthropic.web_fetch_20260209', - inputSchema: webFetch_20260209InputSchema, - outputSchema: webFetch_20260209OutputSchema, - supportsDeferredResults: true, -}); - -export const webFetch_20260209 = ( - args: Parameters[0] = {}, // default -) => { - return factory(args); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/web-search_20250305.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/web-search_20250305.ts deleted file mode 100644 index b83f764e9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/web-search_20250305.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const webSearch_20250305ArgsSchema = lazySchema(() => - zodSchema( - z.object({ - maxUses: z.number().optional(), - allowedDomains: z.array(z.string()).optional(), - blockedDomains: z.array(z.string()).optional(), - userLocation: z - .object({ - type: z.literal('approximate'), - city: z.string().optional(), - region: z.string().optional(), - country: z.string().optional(), - timezone: z.string().optional(), - }) - .optional(), - }), - ), -); - -export const webSearch_20250305OutputSchema = lazySchema(() => - zodSchema( - z.array( - z.object({ - url: z.string(), - title: z.string().nullable(), - pageAge: z.string().nullable(), - encryptedContent: z.string(), - type: z.literal('web_search_result'), - }), - ), - ), -); - -const webSearch_20250305InputSchema = lazySchema(() => - zodSchema( - z.object({ - query: z.string(), - }), - ), -); - -const factory = createProviderToolFactoryWithOutputSchema< - { - /** - * The search query to execute. - */ - query: string; - }, - Array<{ - type: 'web_search_result'; - - /** - * The URL of the source page. - */ - url: string; - - /** - * The title of the source page. - */ - title: string | null; - - /** - * When the site was last updated - */ - pageAge: string | null; - - /** - * Encrypted content that must be passed back in multi-turn conversations for citations - */ - encryptedContent: string; - }>, - { - /** - * Maximum number of web searches Claude can perform during the conversation. - */ - maxUses?: number; - - /** - * Optional list of domains that Claude is allowed to search. - */ - allowedDomains?: string[]; - - /** - * Optional list of domains that Claude should avoid when searching. - */ - blockedDomains?: string[]; - - /** - * Optional user location information to provide geographically relevant search results. - */ - userLocation?: { - /** - * The type of location (must be approximate) - */ - type: 'approximate'; - - /** - * The city name - */ - city?: string; - - /** - * The region or state - */ - region?: string; - - /** - * The country - */ - country?: string; - - /** - * The IANA timezone ID. - */ - timezone?: string; - }; - } ->({ - id: 'anthropic.web_search_20250305', - inputSchema: webSearch_20250305InputSchema, - outputSchema: webSearch_20250305OutputSchema, - supportsDeferredResults: true, -}); - -export const webSearch_20250305 = ( - args: Parameters[0] = {}, // default -) => { - return factory(args); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/web-search_20260209.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/web-search_20260209.ts deleted file mode 100644 index a34ae31ac..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/tool/web-search_20260209.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const webSearch_20260209ArgsSchema = lazySchema(() => - zodSchema( - z.object({ - maxUses: z.number().optional(), - allowedDomains: z.array(z.string()).optional(), - blockedDomains: z.array(z.string()).optional(), - userLocation: z - .object({ - type: z.literal('approximate'), - city: z.string().optional(), - region: z.string().optional(), - country: z.string().optional(), - timezone: z.string().optional(), - }) - .optional(), - }), - ), -); - -export const webSearch_20260209OutputSchema = lazySchema(() => - zodSchema( - z.array( - z.object({ - url: z.string(), - title: z.string().nullable(), - pageAge: z.string().nullable(), - encryptedContent: z.string(), - type: z.literal('web_search_result'), - }), - ), - ), -); - -const webSearch_20260209InputSchema = lazySchema(() => - zodSchema( - z.object({ - query: z.string(), - }), - ), -); - -const factory = createProviderToolFactoryWithOutputSchema< - { - /** - * The search query to execute. - */ - query: string; - }, - Array<{ - type: 'web_search_result'; - - /** - * The URL of the source page. - */ - url: string; - - /** - * The title of the source page. - */ - title: string | null; - - /** - * When the site was last updated - */ - pageAge: string | null; - - /** - * Encrypted content that must be passed back in multi-turn conversations for citations - */ - encryptedContent: string; - }>, - { - /** - * Maximum number of web searches Claude can perform during the conversation. - */ - maxUses?: number; - - /** - * Optional list of domains that Claude is allowed to search. - */ - allowedDomains?: string[]; - - /** - * Optional list of domains that Claude should avoid when searching. - */ - blockedDomains?: string[]; - - /** - * Optional user location information to provide geographically relevant search results. - */ - userLocation?: { - /** - * The type of location (must be approximate) - */ - type: 'approximate'; - - /** - * The city name - */ - city?: string; - - /** - * The region or state - */ - region?: string; - - /** - * The country - */ - country?: string; - - /** - * The IANA timezone ID. - */ - timezone?: string; - }; - } ->({ - id: 'anthropic.web_search_20260209', - inputSchema: webSearch_20260209InputSchema, - outputSchema: webSearch_20260209OutputSchema, - supportsDeferredResults: true, -}); - -export const webSearch_20260209 = ( - args: Parameters[0] = {}, // default -) => { - return factory(args); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/version.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/version.ts deleted file mode 100644 index 7a35d46f5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/anthropic/src/version.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Version string of this package injected at build time. -declare const __PACKAGE_VERSION__: string | undefined; -export const VERSION: string = - typeof __PACKAGE_VERSION__ !== 'undefined' - ? __PACKAGE_VERSION__ - : '0.0.0-test'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/CHANGELOG.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/CHANGELOG.md deleted file mode 100644 index 72d7a68c0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/CHANGELOG.md +++ /dev/null @@ -1,1718 +0,0 @@ -# @ai-sdk/gateway - -## 3.0.80 - -### Patch Changes - -- 0db5cd8: Backport: chore(provider/gateway): update gateway model settings files - -## 3.0.79 - -### Patch Changes - -- 3caa544: chore(provider/xai): update Grok 4.20 model IDs to their non-beta versions - -## 3.0.78 - -### Patch Changes - -- 763e178: Backport: chore(provider/gateway): update gateway model settings files - -## 3.0.77 - -### Patch Changes - -- d99eb91: Backport: chore(provider/gateway): update gateway model settings files -- 055cd68: fix: publish v6 to latest npm dist tag -- Updated dependencies [055cd68] - - @ai-sdk/provider-utils@4.0.21 - -## 3.0.76 - -### Patch Changes - -- 25af909: Backport: chore(provider/gateway): update gateway model settings files - -## 3.0.75 - -### Patch Changes - -- f95e0c0: Backport: chore(provider/gateway): update gateway model settings files - -## 3.0.74 - -### Patch Changes - -- 7324b56: Backport: chore(provider/gateway): update gateway model settings files - -## 3.0.73 - -### Patch Changes - -- ac0c407: Backport: chore(provider/gateway): update gateway model settings files -- e748159: Backport: chore(provider/gateway): update gateway model settings files - -## 3.0.72 - -### Patch Changes - -- 5ffb1ad: feat(provider/google): add `gemini-embedding-2-preview` and fix multimodal embedding support with `embedMany` -- f5bf0c6: Backport: chore(provider/gateway): update gateway model settings files - -## 3.0.71 - -### Patch Changes - -- 55ccbe2: chore(provider/xai): remove obsolete Grok 2 models now that they are shut down in their API - -## 3.0.70 - -### Patch Changes - -- ca0b430: chore(provider/gateway): update gateway model settings files - -## 3.0.69 - -### Patch Changes - -- efdaefc: chore(provider/gateway): update gateway model settings files - -## 3.0.68 - -### Patch Changes - -- Updated dependencies [64ac0fd] - - @ai-sdk/provider-utils@4.0.20 - -## 3.0.67 - -### Patch Changes - -- 2589004: feat(provider/openai): add GPT-5.4 model support - -## 3.0.66 - -### Patch Changes - -- Updated dependencies [ad4cfc2] - - @ai-sdk/provider-utils@4.0.19 - -## 3.0.65 - -### Patch Changes - -- Updated dependencies [824b295] - - @ai-sdk/provider-utils@4.0.18 - -## 3.0.64 - -### Patch Changes - -- db3d4ca: chore(provider/gateway): update gateway model settings files - -## 3.0.63 - -### Patch Changes - -- 1b01ec1: feat(gateway): add providerTimeouts to provider options -- 8df8e11: chore(provider/gateway): update gateway model settings files - -## 3.0.62 - -### Patch Changes - -- 10bec50: feat(provider/google): add `gemini-3.1-flash-lite-preview` - -## 3.0.61 - -### Patch Changes - -- Updated dependencies [08336f1] - - @ai-sdk/provider-utils@4.0.17 - -## 3.0.60 - -### Patch Changes - -- 29e9f4d: chore(provider/gateway): update gateway model settings files - -## 3.0.59 - -### Patch Changes - -- Updated dependencies [58bc42d] - - @ai-sdk/provider-utils@4.0.16 - -## 3.0.58 - -### Patch Changes - -- 1330f2f: chore(provider/gateway): update gateway model settings files - -## 3.0.57 - -### Patch Changes - -- ba63bc2: chore(provider/gateway): update gateway model settings files - -## 3.0.56 - -### Patch Changes - -- 45f0a7f: feat(provider/google): add support for gemini-3.1-flash-image-preview - -## 3.0.55 - -### Patch Changes - -- e8172b6: feat (provider/gateway): pass through project id when available for o11y - -## 3.0.54 - -### Patch Changes - -- 0c9395b: feat(provider/openai): add `gpt-5.3-codex` - -## 3.0.53 - -### Patch Changes - -- 73b7e09: feat (provider/gateway): add SSE support for video generation with heartbeat keep-alive - -## 3.0.52 - -### Patch Changes - -- 363fa44: chore(provider/gateway): update gateway model settings files - -## 3.0.51 - -### Patch Changes - -- 765b013: feat(provider/google): add support for `gemini-3.1-pro-preview` - -## 3.0.50 - -### Patch Changes - -- a433cd3: chore(provider/gateway): update gateway model settings files - -## 3.0.49 - -### Patch Changes - -- 5f693c8: chore(provider/gateway): update gateway model settings files - -## 3.0.48 - -### Patch Changes - -- 2a1c664: feat(provider/anthropic): add support for new Claude Sonnet 4.6 model - -## 3.0.47 - -### Patch Changes - -- 6bbd05b: chore(provider/gateway): update gateway model settings files - -## 3.0.46 - -### Patch Changes - -- f75f18c: chore(provider/gateway): update gateway model settings files - -## 3.0.45 - -### Patch Changes - -- e858654: fix (provider/gateway): Fixed error handling in Gateway models by making asGatewayError async in both image and video model implementations. - -## 3.0.44 - -### Patch Changes - -- Updated dependencies [4024a3a] - - @ai-sdk/provider-utils@4.0.15 - -## 3.0.43 - -### Patch Changes - -- b424e50: chore(provider/gateway): update gateway model settings files - -## 3.0.42 - -### Patch Changes - -- 1819bc1: fix (provider/gateway): add missing warning types for video response parsing - -## 3.0.41 - -### Patch Changes - -- 99fbed8: feat: normalize provider specific model options type names and ensure they are exported - -## 3.0.40 - -### Patch Changes - -- a2208a2: fix (provider/gateway): added custom error class and message for client side timeouts - -## 3.0.39 - -### Patch Changes - -- eea5d30: fix: image generation via Gateway warning schema mismatch - -## 3.0.38 - -### Patch Changes - -- 70028ab: feat: report image generation usage info in Gateway - -## 3.0.37 - -### Patch Changes - -- Updated dependencies [7168375] - - @ai-sdk/provider@3.0.8 - - @ai-sdk/provider-utils@4.0.14 - -## 3.0.36 - -### Patch Changes - -- 9892c58: feat(anthropic): add support for Opus 4.6 - -## 3.0.35 - -### Patch Changes - -- 8e2eaac: chore(provider/gateway): update gateway model settings files - -## 3.0.34 - -### Patch Changes - -- 4867635: feat (provider/gateway): add video generation support - -## 3.0.33 - -### Patch Changes - -- ae30443: fix(google): remove shut down `gemini-2.5-flash-image-preview` - -## 3.0.32 - -### Patch Changes - -- Updated dependencies [53f6731] - - @ai-sdk/provider@3.0.7 - - @ai-sdk/provider-utils@4.0.13 - -## 3.0.31 - -### Patch Changes - -- Updated dependencies [96936e5] - - @ai-sdk/provider-utils@4.0.12 - -## 3.0.30 - -### Patch Changes - -- 1a74972: chore(provider/gateway): update gateway model settings files - -## 3.0.29 - -### Patch Changes - -- Updated dependencies [2810850] - - @ai-sdk/provider-utils@4.0.11 - - @ai-sdk/provider@3.0.6 - -## 3.0.28 - -### Patch Changes - -- 1524271: chore: add skill information to README files - -## 3.0.27 - -### Patch Changes - -- 0acff64: feat (provider/gateway): add parallel search tool - -## 3.0.26 - -### Patch Changes - -- a8be296: chore(provider/gateway): update gateway model settings files - -## 3.0.25 - -### Patch Changes - -- 15a78c7: chore(provider/gateway): update gateway model settings files - -## 3.0.24 - -### Patch Changes - -- Updated dependencies [462ad00] - - @ai-sdk/provider-utils@4.0.10 - -## 3.0.23 - -### Patch Changes - -- cbf1704: chore(provider/gateway): update gateway model settings files - -## 3.0.22 - -### Patch Changes - -- 4de5a1d: chore: excluded tests from src folder in npm package -- Updated dependencies [4de5a1d] - - @ai-sdk/provider@3.0.5 - - @ai-sdk/provider-utils@4.0.9 - -## 3.0.21 - -### Patch Changes - -- 2b8369d: chore: add docs to package dist - -## 3.0.20 - -### Patch Changes - -- 8dc54db: chore: add src folders to package bundle - -## 3.0.19 - -### Patch Changes - -- c60fdd8: Inline fullMessage variable in GatewayError constructor - -## 3.0.18 - -### Patch Changes - -- 7af4eb4: chore(provider/gateway): update gateway model settings files - -## 3.0.17 - -### Patch Changes - -- 66d78d5: chore(provider/gateway): update gateway model settings files - -## 3.0.16 - -### Patch Changes - -- Updated dependencies [5c090e7] - - @ai-sdk/provider@3.0.4 - - @ai-sdk/provider-utils@4.0.8 - -## 3.0.15 - -### Patch Changes - -- Updated dependencies [46f46e4] - - @ai-sdk/provider-utils@4.0.7 - -## 3.0.14 - -### Patch Changes - -- Updated dependencies [1b11dcb] - - @ai-sdk/provider-utils@4.0.6 - - @ai-sdk/provider@3.0.3 - -## 3.0.13 - -### Patch Changes - -- 92b339b: feat (provider/gateway): add'l perplexity search tool params - -## 3.0.12 - -### Patch Changes - -- Updated dependencies [34d1c8a] - - @ai-sdk/provider-utils@4.0.5 - -## 3.0.11 - -### Patch Changes - -- 891a60a: feat (provider/gateway): add provider-defined perplexity search - -## 3.0.10 - -### Patch Changes - -- 2696fd2: chore(provider/gateway): Update gateway model settings files - -## 3.0.9 - -### Patch Changes - -- Updated dependencies [d937c8f] - - @ai-sdk/provider@3.0.2 - - @ai-sdk/provider-utils@4.0.4 - -## 3.0.8 - -### Patch Changes - -- 8ec1984: fix(gateway): bump `@vercel/oidc` to 3.1.0 - -## 3.0.7 - -### Patch Changes - -- Updated dependencies [0b429d4] - - @ai-sdk/provider-utils@4.0.3 - -## 3.0.6 - -### Patch Changes - -- 74c0157: feat (provider/gateway): support image editing - -## 3.0.5 - -### Patch Changes - -- 7ee2d12: chore (provider/gateway): bump specification version header to reflect v3 - -## 3.0.4 - -### Patch Changes - -- 863d34f: fix: trigger release to update `@latest` -- Updated dependencies [863d34f] - - @ai-sdk/provider@3.0.1 - - @ai-sdk/provider-utils@4.0.2 - -## 3.0.3 - -### Patch Changes - -- 1dad057: fix(gateway): add error handling for oidc refresh - -## 3.0.2 - -### Patch Changes - -- Updated dependencies [29264a3] - - @ai-sdk/provider-utils@4.0.1 - -## 3.0.1 - -### Patch Changes - -- c0c8a0e: Add zai/glm-4.7 model support - -## 3.0.0 - -### Major Changes - -- 387980f: fix: major version bump for AI SDK v6 - -## 2.0.0 - -### Major Changes - -- dee8b05: ai SDK 6 beta -- 2f8b0c8: fix(gateway): bump `@vercel/oidc` to latest - -### Minor Changes - -- 78928cb: release: start 5.1 beta - -### Patch Changes - -- 0c3b58b: fix(provider): add specificationVersion to ProviderV3 -- ea9ca31: feat(provider/gateway): Add new xAI models -- 5dd4c6a: fix(provider/gateway): Fix Gateway image model provider options not passing through -- 5d21222: feat(provider/gateway): Add gpt-5-codex to Gateway model string autocomplete -- 0adc679: feat(provider): shared spec v3 -- 7294355: feat (provider/gateway): update route path version and embed format -- e8694af: feat(provider/gateway): Server-side image request splitting -- 8d9e8ad: chore(provider): remove generics from EmbeddingModelV3 - - Before - - ```ts - model.textEmbeddingModel("my-model-id"); - ``` - - After - - ```ts - model.embeddingModel("my-model-id"); - ``` - -- aaf5ebf: feat(provider/gateway): Add new Qwen models to Gateway model string autocomplete -- 95f65c2: chore: use import \* from zod/v4 -- c823faf: feat(provider/gateway): Add new Gemini preview models to Gateway model string autocomplete -- 2b6a848: feat (provider/gateway): add models provider option for model routing -- 0c4822d: feat: `EmbeddingModelV3` -- 34ee8d0: feat (provider/gateway): add support for request-scoped byok -- 1890317: feat (provider/gateway): improve auth error messages -- 636e614: feat(provider/gateway): Add DeepSeek V3.2 Exp to Gateway language model settings -- 7ccb36f: feat(provider/gateway): Add LongCat Thinking model to Gateway autocomplete -- ed329cb: feat: `Provider-V3` -- 5f66123: chore(provider/gateway): Update gateway language model settings -- 1cad0ab: feat: add provider version to user-agent header -- bca7e61: feat(provider/gateway): Change default maxImagesPerCall per-provider -- 8dac895: feat: `LanguageModelV3` -- 3e83633: add getCredits() gateway method -- 1d8ea2c: feat(provider/gateway): Add GPT-5 pro to Gateway model string autocomplete -- ef62178: feat(gateway): oidc refresh with `@vercel/oidc` -- 0a2ff8a: feat (provider/gateway): add user and tags provider options -- ee71658: feat (provider/gateway): add zero data retention provider option -- 457318b: chore(provider,ai): switch to SharedV3Warning and unified warnings -- 9061dc0: feat: image editing -- 7d73922: feat(provider/gateway): Add MiniMax M2 to Gateway autocomplete -- e6bfe91: feat(provider/gateway): Update DeepSeek model string autocomplete -- acc14d8: feat (provider/gateway): add 'only' to provider options -- f83903d: getCredits style improvements -- 0e29b8b: chore(provider/gateway): lazy schema loading -- 366f50b: chore(provider): add deprecated textEmbeddingModel and textEmbedding aliases -- cdd0bc2: feat (provider/gateway): add intellect-3 model id -- 96322b7: feat(provider/gateway): Add GPT OSS Safeguard 20B to Gateway model string autocomplete -- 4616b86: chore: update zod peer depenedency version -- 2d166e4: feat(provider/gateway): add support for image models -- 6c766ef: feat(provider/gateway): Add DeepSeek V3.1 Terminus to Gateway autocomplete -- 7b1b1b1: fix(provider/gateway): add "react-native" as export condition for browser behavior - - This avoids the use of native Node APIs in bundles created for React Native / Expo apps - -- 3782645: bump `@vercel/oidc` to 3.0.5 -- f18ef7f: feat(openai): add gpt-5.2 models -- 1425df5: feat(provider/gateway): Add Imagen 4 Ultra Generate to model string autocomplete list -- 9f6149e: feat(provider/gateway): Add Sonnet 4.5 to Gateway model string autocomplete -- cc5170d: feat(provider/gateway): update gateway model string autocomplete -- a90dca6: feat(provider/gateway): Add zAI GLM 4.6 to Gateway language model settings -- b1624f0: feat (provider/gateway): add trinity-mini model id -- cbf52cd: feat: expose raw finish reason -- 870297d: feat(google): gemini-3-flash -- f0b2157: fix: revert zod import change -- Updated dependencies - - @ai-sdk/provider@3.0.0 - - @ai-sdk/provider-utils@4.0.0 - -## 2.0.0-beta.93 - -### Patch Changes - -- 7294355: feat (provider/gateway): update route path version and embed format - -## 2.0.0-beta.92 - -### Patch Changes - -- Updated dependencies [475189e] - - @ai-sdk/provider@3.0.0-beta.32 - - @ai-sdk/provider-utils@4.0.0-beta.59 - -## 2.0.0-beta.91 - -### Patch Changes - -- Updated dependencies [2625a04] - - @ai-sdk/provider@3.0.0-beta.31 - - @ai-sdk/provider-utils@4.0.0-beta.58 - -## 2.0.0-beta.90 - -### Patch Changes - -- cbf52cd: feat: expose raw finish reason -- Updated dependencies [cbf52cd] - - @ai-sdk/provider@3.0.0-beta.30 - - @ai-sdk/provider-utils@4.0.0-beta.57 - -## 2.0.0-beta.89 - -### Patch Changes - -- Updated dependencies [9549c9e] - - @ai-sdk/provider@3.0.0-beta.29 - - @ai-sdk/provider-utils@4.0.0-beta.56 - -## 2.0.0-beta.88 - -### Patch Changes - -- Updated dependencies [50b70d6] - - @ai-sdk/provider-utils@4.0.0-beta.55 - -## 2.0.0-beta.87 - -### Patch Changes - -- ee71658: feat (provider/gateway): add zero data retention provider option - -## 2.0.0-beta.86 - -### Patch Changes - -- 9061dc0: feat: image editing -- Updated dependencies [9061dc0] - - @ai-sdk/provider-utils@4.0.0-beta.54 - - @ai-sdk/provider@3.0.0-beta.28 - -## 2.0.0-beta.85 - -### Patch Changes - -- 870297d: feat(google): gemini-3-flash - -## 2.0.0-beta.84 - -### Patch Changes - -- 366f50b: chore(provider): add deprecated textEmbeddingModel and textEmbedding aliases -- Updated dependencies [366f50b] - - @ai-sdk/provider@3.0.0-beta.27 - - @ai-sdk/provider-utils@4.0.0-beta.53 - -## 2.0.0-beta.83 - -### Patch Changes - -- Updated dependencies [763d04a] - - @ai-sdk/provider-utils@4.0.0-beta.52 - -## 2.0.0-beta.82 - -### Patch Changes - -- Updated dependencies [c1efac4] - - @ai-sdk/provider-utils@4.0.0-beta.51 - -## 2.0.0-beta.81 - -### Patch Changes - -- Updated dependencies [32223c8] - - @ai-sdk/provider-utils@4.0.0-beta.50 - -## 2.0.0-beta.80 - -### Patch Changes - -- Updated dependencies [83e5744] - - @ai-sdk/provider-utils@4.0.0-beta.49 - -## 2.0.0-beta.79 - -### Patch Changes - -- Updated dependencies [960ec8f] - - @ai-sdk/provider-utils@4.0.0-beta.48 - -## 2.0.0-beta.78 - -### Patch Changes - -- f18ef7f: feat(openai): add gpt-5.2 models - -## 2.0.0-beta.77 - -### Patch Changes - -- Updated dependencies [e9e157f] - - @ai-sdk/provider-utils@4.0.0-beta.47 - -## 2.0.0-beta.76 - -### Patch Changes - -- 34ee8d0: feat (provider/gateway): add support for request-scoped byok - -## 2.0.0-beta.75 - -### Patch Changes - -- Updated dependencies [81e29ab] - - @ai-sdk/provider-utils@4.0.0-beta.46 - -## 2.0.0-beta.74 - -### Patch Changes - -- Updated dependencies [3bd2689] - - @ai-sdk/provider@3.0.0-beta.26 - - @ai-sdk/provider-utils@4.0.0-beta.45 - -## 2.0.0-beta.73 - -### Patch Changes - -- Updated dependencies [53f3368] - - @ai-sdk/provider@3.0.0-beta.25 - - @ai-sdk/provider-utils@4.0.0-beta.44 - -## 2.0.0-beta.72 - -### Patch Changes - -- Updated dependencies [dce03c4] - - @ai-sdk/provider-utils@4.0.0-beta.43 - - @ai-sdk/provider@3.0.0-beta.24 - -## 2.0.0-beta.71 - -### Patch Changes - -- Updated dependencies [3ed5519] - - @ai-sdk/provider-utils@4.0.0-beta.42 - -## 2.0.0-beta.70 - -### Patch Changes - -- Updated dependencies [1bd7d32] - - @ai-sdk/provider-utils@4.0.0-beta.41 - - @ai-sdk/provider@3.0.0-beta.23 - -## 2.0.0-beta.69 - -### Patch Changes - -- b1624f0: feat (provider/gateway): add trinity-mini model id - -## 2.0.0-beta.68 - -### Patch Changes - -- Updated dependencies [544d4e8] - - @ai-sdk/provider-utils@4.0.0-beta.40 - - @ai-sdk/provider@3.0.0-beta.22 - -## 2.0.0-beta.67 - -### Patch Changes - -- Updated dependencies [954c356] - - @ai-sdk/provider-utils@4.0.0-beta.39 - - @ai-sdk/provider@3.0.0-beta.21 - -## 2.0.0-beta.66 - -### Patch Changes - -- Updated dependencies [03849b0] - - @ai-sdk/provider-utils@4.0.0-beta.38 - -## 2.0.0-beta.65 - -### Patch Changes - -- cdd0bc2: feat (provider/gateway): add intellect-3 model id - -## 2.0.0-beta.64 - -### Patch Changes - -- 457318b: chore(provider,ai): switch to SharedV3Warning and unified warnings -- Updated dependencies [457318b] - - @ai-sdk/provider@3.0.0-beta.20 - - @ai-sdk/provider-utils@4.0.0-beta.37 - -## 2.0.0-beta.63 - -### Patch Changes - -- 8d9e8ad: chore(provider): remove generics from EmbeddingModelV3 - - Before - - ```ts - model.textEmbeddingModel("my-model-id"); - ``` - - After - - ```ts - model.embeddingModel("my-model-id"); - ``` - -- Updated dependencies [8d9e8ad] - - @ai-sdk/provider@3.0.0-beta.19 - - @ai-sdk/provider-utils@4.0.0-beta.36 - -## 2.0.0-beta.62 - -### Patch Changes - -- Updated dependencies [10d819b] - - @ai-sdk/provider@3.0.0-beta.18 - - @ai-sdk/provider-utils@4.0.0-beta.35 - -## 2.0.0-beta.61 - -### Patch Changes - -- e8694af: feat(provider/gateway): Server-side image request splitting - -## 2.0.0-beta.60 - -### Patch Changes - -- Updated dependencies [db913bd] - - @ai-sdk/provider@3.0.0-beta.17 - - @ai-sdk/provider-utils@4.0.0-beta.34 - -## 2.0.0-beta.59 - -### Patch Changes - -- 5dd4c6a: fix(provider/gateway): Fix Gateway image model provider options not passing through - -## 2.0.0-beta.58 - -### Patch Changes - -- 1425df5: feat(provider/gateway): Add Imagen 4 Ultra Generate to model string autocomplete list - -## 2.0.0-beta.57 - -### Patch Changes - -- bca7e61: feat(provider/gateway): Change default maxImagesPerCall per-provider - -## 2.0.0-beta.56 - -### Patch Changes - -- 2d166e4: feat(provider/gateway): add support for image models - -## 2.0.0-beta.55 - -### Patch Changes - -- cc5170d: feat(provider/gateway): update gateway model string autocomplete - -## 2.0.0-beta.54 - -### Patch Changes - -- 5f66123: chore(provider/gateway): Update gateway language model settings - -## 2.0.0-beta.53 - -### Patch Changes - -- 3782645: bump `@vercel/oidc` to 3.0.5 - -## 2.0.0-beta.52 - -### Patch Changes - -- Updated dependencies [b681d7d] - - @ai-sdk/provider@3.0.0-beta.16 - - @ai-sdk/provider-utils@4.0.0-beta.33 - -## 2.0.0-beta.51 - -### Patch Changes - -- Updated dependencies [32d8dbb] - - @ai-sdk/provider-utils@4.0.0-beta.32 - -## 2.0.0-beta.50 - -### Patch Changes - -- Updated dependencies [bb36798] - - @ai-sdk/provider@3.0.0-beta.15 - - @ai-sdk/provider-utils@4.0.0-beta.31 - -## 2.0.0-beta.49 - -### Patch Changes - -- Updated dependencies [4f16c37] - - @ai-sdk/provider-utils@4.0.0-beta.30 - -## 2.0.0-beta.48 - -### Patch Changes - -- Updated dependencies [af3780b] - - @ai-sdk/provider@3.0.0-beta.14 - - @ai-sdk/provider-utils@4.0.0-beta.29 - -## 2.0.0-beta.47 - -### Patch Changes - -- 96322b7: feat(provider/gateway): Add GPT OSS Safeguard 20B to Gateway model string autocomplete - -## 2.0.0-beta.46 - -### Patch Changes - -- Updated dependencies [016b111] - - @ai-sdk/provider-utils@4.0.0-beta.28 - -## 2.0.0-beta.45 - -### Patch Changes - -- Updated dependencies [37c58a0] - - @ai-sdk/provider@3.0.0-beta.13 - - @ai-sdk/provider-utils@4.0.0-beta.27 - -## 2.0.0-beta.44 - -### Patch Changes - -- 7d73922: feat(provider/gateway): Add MiniMax M2 to Gateway autocomplete - -## 2.0.0-beta.43 - -### Patch Changes - -- Updated dependencies [d1bdadb] - - @ai-sdk/provider@3.0.0-beta.12 - - @ai-sdk/provider-utils@4.0.0-beta.26 - -## 2.0.0-beta.42 - -### Patch Changes - -- Updated dependencies [4c44a5b] - - @ai-sdk/provider@3.0.0-beta.11 - - @ai-sdk/provider-utils@4.0.0-beta.25 - -## 2.0.0-beta.41 - -### Patch Changes - -- 0c3b58b: fix(provider): add specificationVersion to ProviderV3 -- Updated dependencies [0c3b58b] - - @ai-sdk/provider@3.0.0-beta.10 - - @ai-sdk/provider-utils@4.0.0-beta.24 - -## 2.0.0-beta.40 - -### Patch Changes - -- Updated dependencies [a755db5] - - @ai-sdk/provider@3.0.0-beta.9 - - @ai-sdk/provider-utils@4.0.0-beta.23 - -## 2.0.0-beta.39 - -### Patch Changes - -- Updated dependencies [58920e0] - - @ai-sdk/provider-utils@4.0.0-beta.22 - -## 2.0.0-beta.38 - -### Patch Changes - -- Updated dependencies [293a6b7] - - @ai-sdk/provider-utils@4.0.0-beta.21 - -## 2.0.0-beta.37 - -### Patch Changes - -- 2b6a848: feat (provider/gateway): add models provider option for model routing - -## 2.0.0-beta.36 - -### Patch Changes - -- Updated dependencies [fca786b] - - @ai-sdk/provider-utils@4.0.0-beta.20 - -## 2.0.0-beta.35 - -### Patch Changes - -- Updated dependencies [3794514] - - @ai-sdk/provider-utils@4.0.0-beta.19 - - @ai-sdk/provider@3.0.0-beta.8 - -## 2.0.0-beta.34 - -### Major Changes - -- 2f8b0c8: fix(gateway): bump `@vercel/oidc` to latest - -## 2.0.0-beta.33 - -### Patch Changes - -- 1890317: feat (provider/gateway): improve auth error messages - -## 2.0.0-beta.32 - -### Patch Changes - -- Updated dependencies [81d4308] - - @ai-sdk/provider@3.0.0-beta.7 - - @ai-sdk/provider-utils@4.0.0-beta.18 - -## 2.0.0-beta.31 - -### Patch Changes - -- Updated dependencies [703459a] - - @ai-sdk/provider-utils@4.0.0-beta.17 - -## 2.0.0-beta.30 - -### Patch Changes - -- 0a2ff8a: feat (provider/gateway): add user and tags provider options - -## 2.0.0-beta.29 - -### Patch Changes - -- Updated dependencies [6306603] - - @ai-sdk/provider-utils@4.0.0-beta.16 - -## 2.0.0-beta.28 - -### Patch Changes - -- f0b2157: fix: revert zod import change -- Updated dependencies [f0b2157] - - @ai-sdk/provider-utils@4.0.0-beta.15 - -## 2.0.0-beta.27 - -### Patch Changes - -- Updated dependencies [3b1d015] - - @ai-sdk/provider-utils@4.0.0-beta.14 - -## 2.0.0-beta.26 - -### Patch Changes - -- Updated dependencies [d116b4b] - - @ai-sdk/provider-utils@4.0.0-beta.13 - -## 2.0.0-beta.25 - -### Patch Changes - -- Updated dependencies [7e32fea] - - @ai-sdk/provider-utils@4.0.0-beta.12 - -## 2.0.0-beta.24 - -### Patch Changes - -- 0e29b8b: chore(provider/gateway): lazy schema loading - -## 2.0.0-beta.23 - -### Patch Changes - -- acc14d8: feat (provider/gateway): add 'only' to provider options - -## 2.0.0-beta.22 - -### Patch Changes - -- 95f65c2: chore: use import \* from zod/v4 -- Updated dependencies - - @ai-sdk/provider-utils@4.0.0-beta.11 - -## 2.0.0-beta.21 - -### Patch Changes - -- 7b1b1b1: fix(provider/gateway): add "react-native" as export condition for browser behavior - - This avoids the use of native Node APIs in bundles created for React Native / Expo apps - -## 2.0.0-beta.20 - -### Major Changes - -- dee8b05: ai SDK 6 beta - -### Patch Changes - -- Updated dependencies [dee8b05] - - @ai-sdk/provider@3.0.0-beta.6 - - @ai-sdk/provider-utils@4.0.0-beta.10 - -## 1.1.0-beta.19 - -### Patch Changes - -- Updated dependencies [521c537] - - @ai-sdk/provider-utils@3.1.0-beta.9 - -## 1.1.0-beta.18 - -### Patch Changes - -- Updated dependencies [e06565c] - - @ai-sdk/provider-utils@3.1.0-beta.8 - -## 1.1.0-beta.17 - -### Patch Changes - -- 1d8ea2c: feat(provider/gateway): Add GPT-5 pro to Gateway model string autocomplete - -## 1.1.0-beta.16 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.1.0-beta.5 - - @ai-sdk/provider-utils@3.1.0-beta.7 - -## 1.1.0-beta.15 - -### Patch Changes - -- ef62178: feat(gateway): oidc refresh with `@vercel/oidc` - -## 1.1.0-beta.14 - -### Patch Changes - -- a90dca6: feat(provider/gateway): Add zAI GLM 4.6 to Gateway language model settings - -## 1.1.0-beta.13 - -### Patch Changes - -- 0adc679: feat(provider): shared spec v3 -- Updated dependencies - - @ai-sdk/provider-utils@3.1.0-beta.6 - - @ai-sdk/provider@2.1.0-beta.4 - -## 1.1.0-beta.12 - -### Patch Changes - -- e6bfe91: feat(provider/gateway): Update DeepSeek model string autocomplete - -## 1.1.0-beta.11 - -### Patch Changes - -- 636e614: feat(provider/gateway): Add DeepSeek V3.2 Exp to Gateway language model settings - -## 1.1.0-beta.10 - -### Patch Changes - -- 9f6149e: feat(provider/gateway): Add Sonnet 4.5 to Gateway model string autocomplete - -## 1.1.0-beta.9 - -### Patch Changes - -- 8dac895: feat: `LanguageModelV3` -- Updated dependencies [8dac895] - - @ai-sdk/provider-utils@3.1.0-beta.5 - - @ai-sdk/provider@2.1.0-beta.3 - -## 1.1.0-beta.8 - -### Patch Changes - -- c823faf: feat(provider/gateway): Add new Gemini preview models to Gateway model string autocomplete - -## 1.1.0-beta.7 - -### Patch Changes - -- 4616b86: chore: update zod peer depenedency version -- Updated dependencies [4616b86] - - @ai-sdk/provider-utils@3.1.0-beta.4 - -## 1.1.0-beta.6 - -### Patch Changes - -- aaf5ebf: feat(provider/gateway): Add new Qwen models to Gateway model string autocomplete -- ed329cb: feat: `Provider-V3` -- Updated dependencies - - @ai-sdk/provider@2.1.0-beta.2 - - @ai-sdk/provider-utils@3.1.0-beta.3 - -## 1.1.0-beta.5 - -### Patch Changes - -- 5d21222: feat(provider/gateway): Add gpt-5-codex to Gateway model string autocomplete -- 0c4822d: feat: `EmbeddingModelV3` -- 1cad0ab: feat: add provider version to user-agent header -- Updated dependencies [0c4822d] - - @ai-sdk/provider@2.1.0-beta.1 - - @ai-sdk/provider-utils@3.1.0-beta.2 - -## 1.1.0-beta.4 - -### Patch Changes - -- 7ccb36f: feat(provider/gateway): Add LongCat Thinking model to Gateway autocomplete -- 6c766ef: feat(provider/gateway): Add DeepSeek V3.1 Terminus to Gateway autocomplete - -## 1.1.0-beta.3 - -### Patch Changes - -- ea9ca31: feat(provider/gateway): Add new xAI models - -## 1.1.0-beta.2 - -### Patch Changes - -- 3e83633: add getCredits() gateway method -- f83903d: getCredits style improvements - -## 1.1.0-beta.1 - -### Patch Changes - -- Updated dependencies [cbb1d35] - - @ai-sdk/provider-utils@3.1.0-beta.1 - -## 1.1.0-beta.0 - -### Minor Changes - -- 78928cb: release: start 5.1 beta - -### Patch Changes - -- Updated dependencies [78928cb] - - @ai-sdk/provider@2.1.0-beta.0 - - @ai-sdk/provider-utils@3.1.0-beta.0 - -## 1.0.23 - -### Patch Changes - -- f49f924: feat (provider/gateway): add qwen3 next model ids - -## 1.0.22 - -### Patch Changes - -- Updated dependencies [0294b58] - - @ai-sdk/provider-utils@3.0.9 - -## 1.0.21 - -### Patch Changes - -- 4ee3719: feat(provider/gateway): Add Meituan LongCat Flash Chat to autocomplete - -## 1.0.20 - -### Patch Changes - -- 350a328: feat(provider/gateway): Add stealth models to Gateway autocomplete - -## 1.0.19 - -### Patch Changes - -- 034287f: feat (provider/gateway): add qwen3-max model id -- dee1afe: feat(provider/gateway): Fix embeddings `providerOptions` - -## 1.0.18 - -### Patch Changes - -- 5d59a8c: feat (provider/gateway): add moonshotai/kimi-k2-0905 model id - -## 1.0.17 - -### Patch Changes - -- b6005cd: feat(provider/gateway): Add Voyage embedding models - -## 1.0.16 - -### Patch Changes - -- Updated dependencies [99964ed] - - @ai-sdk/provider-utils@3.0.8 - -## 1.0.15 - -### Patch Changes - -- 980633d: feat(provider/gateway): Add xAI Grok Code Fast 1 -- 1c5b88d: feat (provider/gateway): add new model ids - -## 1.0.14 - -### Patch Changes - -- Updated dependencies [886e7cd] - - @ai-sdk/provider-utils@3.0.7 - -## 1.0.13 - -### Patch Changes - -- c9994f9: feat(provider/gateway): Add cache pricing fields to model metadata -- Updated dependencies [1b5a3d3] - - @ai-sdk/provider-utils@3.0.6 - -## 1.0.12 - -### Patch Changes - -- 50e2029: feat (provider/gateway): add deepseek v3.1 thinking model id -- b8478f0: feat (provider/gateway): add mistral medium model id - -## 1.0.11 - -### Patch Changes - -- 926259f: feat(provider/gateway): Expose model type in model spec -- c000f96: feat(provider/gateway): Add DeepSeek V3.1 - -## 1.0.10 - -### Patch Changes - -- Updated dependencies [0857788] - - @ai-sdk/provider-utils@3.0.5 - -## 1.0.9 - -### Patch Changes - -- 8b96f99: feat(provider/gateway): Add DeepSeek v3.1 Base - -## 1.0.8 - -### Patch Changes - -- Updated dependencies [68751f9] - - @ai-sdk/provider-utils@3.0.4 - -## 1.0.7 - -### Patch Changes - -- 28a4006: feat (provider/gateway): add gemini-2.5-flash-lite model id - -## 1.0.6 - -### Patch Changes - -- eefa730: refactor(provider/gateway): Make claude-sonnet-4 and similar the primary model slug for Anthropic v4 models -- Updated dependencies - - @ai-sdk/provider-utils@3.0.3 - -## 1.0.5 - -### Patch Changes - -- cf7b2ad: feat(provider/gateway): Add GLM-4.5V -- Updated dependencies [38ac190] - - @ai-sdk/provider-utils@3.0.2 - -## 1.0.4 - -### Patch Changes - -- 35f93ce: feat (provider/gateway): add new model ids - -## 1.0.3 - -### Patch Changes - -- 893aed6: feat (provider/gateway): add anthropic claude 4.1 opus model id - -## 1.0.2 - -### Patch Changes - -- 444df49: feat (provider/gateway): update model ids - -## 1.0.1 - -### Patch Changes - -- 028fb9c: refactor(provider/gateway): Cleanup old gateway-embedding-options file -- 6331826: feat(provider/gateway): Hide Cohere embedding models with no pricing info -- Updated dependencies [90d212f] - - @ai-sdk/provider-utils@3.0.1 - -## 1.0.0 - -### Patch Changes - -- 9e16bfd: feat (provider/gateway): update model ids -- 0477a13: feat (provider/gateway): Add OpenAI embedding support -- 26b6dd0: feat (providers/gateway): include deployment and request id -- 30ab1de: feat (provider/gateway): add grok-4 model id -- e2aceaf: feat: add raw chunk support -- 97fedf9: feat (providers/gateway): include description and pricing info in model list -- c91586a: chore (providers/gateway): update language model ids -- 3cbcbb7: feat (providers/gateway): share common gateway error transform logic -- fedb55e: feat (provider/gateway): add z.ai and glm-4.5 models -- 6c2c708: feat (providers/gateway): initial gateway provider -- 721775e: feat(provider/gateway): Generate new Gateway embedding model settings file -- 70ebead: feat (provider/gateway): add qwen3 coder model id -- f3639fa: feat (providers/gateway): improve oidc api key client auth flow -- 8bd3624: feat (provider/gateway): update model ids to include vercel -- c145d62: feat (providers/gateway): add createGateway shorthand alias for createGatewayProvider -- f77bc38: chore (providers/gateway): update language model ids -- 989ac75: chore (providers/gateway): update chat model ids -- 7742ba3: feat (providers/gateway): add gateway error types with error detail -- c190907: fix (provider/gateway): use zod v4 -- d1a034f: feature: using Zod 4 for internal stuff -- d454e4b: fix (providers/gateway): fix timestamp error when streaming objects -- cf1e00e: feat (provider/gateway): add devstral model id -- cc21603: feat (provider/gateway): Add AI Gateway provider options (ordering) -- 205077b: fix: improve Zod compatibility -- e001ea1: fix (provider/gateway): remove unnecessary 'x-' prefix on auth method header -- 27deb4d: feat (provider/gateway): Add providerMetadata to embeddings response -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0 - - @ai-sdk/provider@2.0.0 - -## 1.0.0-beta.19 - -### Patch Changes - -- 721775e: feat(provider/gateway): Generate new Gateway embedding model settings file -- Updated dependencies [88a8ee5] - - @ai-sdk/provider-utils@3.0.0-beta.10 - -## 1.0.0-beta.18 - -### Patch Changes - -- 27deb4d: feat (provider/gateway): Add providerMetadata to embeddings response -- Updated dependencies [27deb4d] - - @ai-sdk/provider@2.0.0-beta.2 - - @ai-sdk/provider-utils@3.0.0-beta.9 - -## 1.0.0-beta.17 - -### Patch Changes - -- Updated dependencies [dd5fd43] - - @ai-sdk/provider-utils@3.0.0-beta.8 - -## 1.0.0-beta.16 - -### Patch Changes - -- fedb55e: feat (provider/gateway): add z.ai and glm-4.5 models - -## 1.0.0-beta.15 - -### Patch Changes - -- Updated dependencies [e7fcc86] - - @ai-sdk/provider-utils@3.0.0-beta.7 - -## 1.0.0-beta.14 - -### Patch Changes - -- Updated dependencies [ac34802] - - @ai-sdk/provider-utils@3.0.0-beta.6 - -## 1.0.0-beta.13 - -### Patch Changes - -- 0477a13: feat (provider/gateway): Add OpenAI embedding support -- cf1e00e: feat (provider/gateway): add devstral model id -- cc21603: feat (provider/gateway): Add AI Gateway provider options (ordering) - -## 1.0.0-beta.12 - -### Patch Changes - -- 70ebead: feat (provider/gateway): add qwen3 coder model id - -## 1.0.0-beta.11 - -### Patch Changes - -- 8bd3624: feat (provider/gateway): update model ids to include vercel -- e001ea1: fix (provider/gateway): remove unnecessary 'x-' prefix on auth method header - -## 1.0.0-beta.10 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-beta.5 - -## 1.0.0-beta.9 - -### Patch Changes - -- 205077b: fix: improve Zod compatibility -- Updated dependencies [205077b] - - @ai-sdk/provider-utils@3.0.0-beta.4 - -## 1.0.0-beta.8 - -### Patch Changes - -- Updated dependencies [05d2819] - - @ai-sdk/provider-utils@3.0.0-beta.3 - -## 1.0.0-beta.7 - -### Patch Changes - -- c190907: fix (provider/gateway): use zod v4 - -## 1.0.0-beta.6 - -### Patch Changes - -- 9e16bfd: feat (provider/gateway): update model ids - -## 1.0.0-beta.5 - -### Patch Changes - -- 30ab1de: feat (provider/gateway): add grok-4 model id - -## 1.0.0-beta.4 - -### Patch Changes - -- 97fedf9: feat (providers/gateway): include description and pricing info in model list - -## 1.0.0-beta.3 - -### Patch Changes - -- f3639fa: feat (providers/gateway): improve oidc api key client auth flow -- d454e4b: fix (providers/gateway): fix timestamp error when streaming objects - -## 1.0.0-beta.2 - -### Patch Changes - -- c91586a: chore (providers/gateway): update language model ids -- d1a034f: feature: using Zod 4 for internal stuff -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-beta.2 - -## 1.0.0-beta.1 - -### Patch Changes - -- f77bc38: chore (providers/gateway): update language model ids -- Updated dependencies - - @ai-sdk/provider@2.0.0-beta.1 - - @ai-sdk/provider-utils@3.0.0-beta.1 - -## 1.0.0-alpha.15 - -### Patch Changes - -- c145d62: feat (providers/gateway): add createGateway shorthand alias for createGatewayProvider -- Updated dependencies - - @ai-sdk/provider@2.0.0-alpha.15 - - @ai-sdk/provider-utils@3.0.0-alpha.15 - -## 1.0.0-alpha.14 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-alpha.14 - - @ai-sdk/provider-utils@3.0.0-alpha.14 - -## 1.0.0-alpha.13 - -### Patch Changes - -- Updated dependencies [68ecf2f] - - @ai-sdk/provider@2.0.0-alpha.13 - - @ai-sdk/provider-utils@3.0.0-alpha.13 - -## 1.0.0-alpha.12 - -### Patch Changes - -- e2aceaf: feat: add raw chunk support -- Updated dependencies [e2aceaf] - - @ai-sdk/provider@2.0.0-alpha.12 - - @ai-sdk/provider-utils@3.0.0-alpha.12 - -## 1.0.0-alpha.11 - -### Patch Changes - -- Updated dependencies [c1e6647] - - @ai-sdk/provider@2.0.0-alpha.11 - - @ai-sdk/provider-utils@3.0.0-alpha.11 - -## 1.0.0-alpha.10 - -### Patch Changes - -- Updated dependencies [c4df419] - - @ai-sdk/provider@2.0.0-alpha.10 - - @ai-sdk/provider-utils@3.0.0-alpha.10 - -## 1.0.0-alpha.9 - -### Patch Changes - -- 26b6dd0: feat (providers/gateway): include deployment and request id -- Updated dependencies [811dff3] - - @ai-sdk/provider@2.0.0-alpha.9 - - @ai-sdk/provider-utils@3.0.0-alpha.9 - -## 1.0.0-alpha.8 - -### Patch Changes - -- 3cbcbb7: feat (providers/gateway): share common gateway error transform logic -- 989ac75: chore (providers/gateway): update chat model ids -- 7742ba3: feat (providers/gateway): add gateway error types with error detail -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-alpha.8 - - @ai-sdk/provider@2.0.0-alpha.8 - -## 1.0.0-alpha.7 - -### Patch Changes - -- Updated dependencies [5c56081] - - @ai-sdk/provider@2.0.0-alpha.7 - - @ai-sdk/provider-utils@3.0.0-alpha.7 - -## 1.0.0-alpha.6 - -### Patch Changes - -- 6c2c708: feat (providers/gateway): initial gateway provider -- Updated dependencies [0d2c085] - - @ai-sdk/provider@2.0.0-alpha.6 - - @ai-sdk/provider-utils@3.0.0-alpha.6 diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/LICENSE deleted file mode 100644 index 6c16c29f4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2023 Vercel, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/README.md deleted file mode 100644 index 579a96c3d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# AI SDK - Gateway Provider - -The Gateway provider for the [AI SDK](https://ai-sdk.dev/docs) allows the use of a wide variety of AI models and providers. - -## Setup - -The Gateway provider is available in the `@ai-sdk/gateway` module. You can install it with - -```bash -npm i @ai-sdk/gateway -``` - -## Skill for Coding Agents - -If you use coding agents such as Claude Code or Cursor, we highly recommend adding the AI SDK skill to your repository: - -```shell -npx skills add vercel/ai -``` - -## Provider Instance - -You can import the default provider instance `gateway` from `@ai-sdk/gateway`: - -```ts -import { gateway } from '@ai-sdk/gateway'; -``` - -## Example - -```ts -import { gateway } from '@ai-sdk/gateway'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: gateway('xai/grok-3-beta'), - prompt: - 'Tell me about the history of the San Francisco Mission-style burrito.', -}); -``` - -## Documentation - -Please check out the [AI SDK documentation](https://ai-sdk.dev/docs) for more information. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/docs/00-ai-gateway.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/docs/00-ai-gateway.mdx deleted file mode 100644 index 822e2b69e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/docs/00-ai-gateway.mdx +++ /dev/null @@ -1,742 +0,0 @@ ---- -title: AI Gateway -description: Learn how to use the AI Gateway provider with the AI SDK. ---- - -# AI Gateway Provider - -The [AI Gateway](https://vercel.com/docs/ai-gateway) provider connects you to models from multiple AI providers through a single interface. Instead of integrating with each provider separately, you can access OpenAI, Anthropic, Google, Meta, xAI, and other providers and their models. - -## Features - -- Access models from multiple providers without having to install additional provider modules/dependencies -- Use the same code structure across different AI providers -- Switch between models and providers easily -- Automatic authentication when deployed on Vercel -- View pricing information across providers -- Observability for AI model usage through the Vercel dashboard - -## Setup - -The Vercel AI Gateway provider is part of the AI SDK. - -## Basic Usage - -For most use cases, you can use the AI Gateway directly with a model string: - -```ts -// use plain model string with global provider -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: 'openai/gpt-5', - prompt: 'Hello world', -}); -``` - -```ts -// use provider instance (requires version 5.0.36 or later) -import { generateText, gateway } from 'ai'; - -const { text } = await generateText({ - model: gateway('openai/gpt-5'), - prompt: 'Hello world', -}); -``` - -The AI SDK automatically uses the AI Gateway when you pass a model string in the `creator/model-name` format. - -## Provider Instance - - - The `gateway` provider instance is available from the `ai` package in version - 5.0.36 and later. - - -You can also import the default provider instance `gateway` from `ai`: - -```ts -import { gateway } from 'ai'; -``` - -You may want to create a custom provider instance when you need to: - -- Set custom configuration options (API key, base URL, headers) -- Use the provider in a [provider registry](/docs/ai-sdk-core/provider-management) -- Wrap the provider with [middleware](/docs/ai-sdk-core/middleware) -- Use different settings for different parts of your application - -To create a custom provider instance, import `createGateway` from `ai`: - -```ts -import { createGateway } from 'ai'; - -const gateway = createGateway({ - apiKey: process.env.AI_GATEWAY_API_KEY ?? '', -}); -``` - -You can use the following optional settings to customize the AI Gateway provider instance: - -- **baseURL** _string_ - - Use a different URL prefix for API calls. The default prefix is `https://ai-gateway.vercel.sh/v3/ai`. - -- **apiKey** _string_ - - API key that is being sent using the `Authorization` header. It defaults to - the `AI_GATEWAY_API_KEY` environment variable. - -- **headers** _Record<string,string>_ - - Custom headers to include in the requests. - -- **fetch** _(input: RequestInfo, init?: RequestInit) => Promise<Response>_ - - Custom [fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch) implementation. - Defaults to the global `fetch` function. - You can use it as a middleware to intercept requests, - or to provide a custom fetch implementation for e.g. testing. - -- **metadataCacheRefreshMillis** _number_ - - How frequently to refresh the metadata cache in milliseconds. Defaults to 5 minutes (300,000ms). - -## Authentication - -The Gateway provider supports two authentication methods: - -### API Key Authentication - -Set your API key via environment variable: - -```bash -AI_GATEWAY_API_KEY=your_api_key_here -``` - -Or pass it directly to the provider: - -```ts -import { createGateway } from 'ai'; - -const gateway = createGateway({ - apiKey: 'your_api_key_here', -}); -``` - -### OIDC Authentication (Vercel Deployments) - -When deployed to Vercel, the AI Gateway provider supports authenticating using [OIDC (OpenID Connect) -tokens](https://vercel.com/docs/oidc) without API Keys. - -#### How OIDC Authentication Works - -1. **In Production/Preview Deployments**: - - - OIDC authentication is automatically handled - - No manual configuration needed - - Tokens are automatically obtained and refreshed - -2. **In Local Development**: - - First, install and authenticate with the [Vercel CLI](https://vercel.com/docs/cli) - - Run `vercel env pull` to download your project's OIDC token locally - - For automatic token management: - - Use `vercel dev` to start your development server - this will handle token refreshing automatically - - For manual token management: - - If not using `vercel dev`, note that OIDC tokens expire after 12 hours - - You'll need to run `vercel env pull` again to refresh the token before it expires - - - If an API Key is present (either passed directly or via environment), it will - always be used, even if invalid. - - -Read more about using OIDC tokens in the [Vercel AI Gateway docs](https://vercel.com/docs/ai-gateway#using-the-ai-gateway-with-a-vercel-oidc-token). - -## Bring Your Own Key (BYOK) - -You can connect your own provider credentials to use with Vercel AI Gateway. This lets you use your existing provider accounts and access private resources. - -To set up BYOK, add your provider credentials in your Vercel team's AI Gateway settings. Once configured, AI Gateway automatically uses your credentials. No code changes are needed. - -Learn more in the [BYOK documentation](https://vercel.com/docs/ai-gateway/byok). - -## Language Models - -You can create language models using a provider instance. The first argument is the model ID in the format `creator/model-name`: - -```ts -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: 'openai/gpt-5', - prompt: 'Explain quantum computing in simple terms', -}); -``` - -AI Gateway language models can also be used in the `streamText` function and support structured data generation with [`Output`](/docs/reference/ai-sdk-core/output) (see [AI SDK Core](/docs/ai-sdk-core)). - -## Available Models - -The AI Gateway supports models from OpenAI, Anthropic, Google, Meta, xAI, Mistral, DeepSeek, Amazon Bedrock, Cohere, Perplexity, Alibaba, and other providers. - -For the complete list of available models, see the [AI Gateway documentation](https://vercel.com/docs/ai-gateway). - -## Dynamic Model Discovery - -You can discover available models programmatically: - -```ts -import { gateway, generateText } from 'ai'; - -const availableModels = await gateway.getAvailableModels(); - -// List all available models -availableModels.models.forEach(model => { - console.log(`${model.id}: ${model.name}`); - if (model.description) { - console.log(` Description: ${model.description}`); - } - if (model.pricing) { - console.log(` Input: $${model.pricing.input}/token`); - console.log(` Output: $${model.pricing.output}/token`); - if (model.pricing.cachedInputTokens) { - console.log( - ` Cached input (read): $${model.pricing.cachedInputTokens}/token`, - ); - } - if (model.pricing.cacheCreationInputTokens) { - console.log( - ` Cache creation (write): $${model.pricing.cacheCreationInputTokens}/token`, - ); - } - } -}); - -// Use any discovered model with plain string -const { text } = await generateText({ - model: availableModels.models[0].id, // e.g., 'openai/gpt-4o' - prompt: 'Hello world', -}); -``` - -## Credit Usage - -You can check your team's current credit balance and usage: - -```ts -import { gateway } from 'ai'; - -const credits = await gateway.getCredits(); - -console.log(`Team balance: ${credits.balance} credits`); -console.log(`Team total used: ${credits.total_used} credits`); -``` - -The `getCredits()` method returns your team's credit information based on the authenticated API key or OIDC token: - -- **balance** _number_ - Your team's current available credit balance -- **total_used** _number_ - Total credits consumed by your team - -## Examples - -### Basic Text Generation - -```ts -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: 'anthropic/claude-sonnet-4', - prompt: 'Write a haiku about programming', -}); - -console.log(text); -``` - -### Streaming - -```ts -import { streamText } from 'ai'; - -const { textStream } = await streamText({ - model: 'openai/gpt-5', - prompt: 'Explain the benefits of serverless architecture', -}); - -for await (const textPart of textStream) { - process.stdout.write(textPart); -} -``` - -### Tool Usage - -```ts -import { generateText, tool } from 'ai'; -import { z } from 'zod'; - -const { text } = await generateText({ - model: 'xai/grok-4', - prompt: 'What is the weather like in San Francisco?', - tools: { - getWeather: tool({ - description: 'Get the current weather for a location', - parameters: z.object({ - location: z.string().describe('The location to get weather for'), - }), - execute: async ({ location }) => { - // Your weather API call here - return `It's sunny in ${location}`; - }, - }), - }, -}); -``` - -### Provider-Executed Tools - -Some providers offer tools that are executed by the provider itself, such as [OpenAI's web search tool](/providers/ai-sdk-providers/openai#web-search-tool). To use these tools through AI Gateway, import the provider to access the tool definitions: - -```ts -import { generateText, stepCountIs } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const result = await generateText({ - model: 'openai/gpt-5-mini', - prompt: 'What is the Vercel AI Gateway?', - stopWhen: stepCountIs(10), - tools: { - web_search: openai.tools.webSearch({}), - }, -}); - -console.dir(result.text); -``` - - - Some provider-executed tools require account-specific configuration (such as - Claude Agent Skills) and may not work through AI Gateway. To use these tools, - you must bring your own key (BYOK) directly to the provider. - - -### Gateway Tools - -The AI Gateway provider includes built-in tools that are executed by the gateway itself. These tools can be used with any model through the gateway. - -#### Perplexity Search - -The Perplexity Search tool enables models to search the web using [Perplexity's search API](https://docs.perplexity.ai/guides/search-quickstart). This tool is executed by the AI Gateway and returns web search results that the model can use to provide up-to-date information. - -```ts -import { gateway, generateText } from 'ai'; - -const result = await generateText({ - model: 'openai/gpt-5-nano', - prompt: 'Search for news about AI regulations in January 2025.', - tools: { - perplexity_search: gateway.tools.perplexitySearch(), - }, -}); - -console.log(result.text); -console.log('Tool calls:', JSON.stringify(result.toolCalls, null, 2)); -console.log('Tool results:', JSON.stringify(result.toolResults, null, 2)); -``` - -You can also configure the search with optional parameters: - -```ts -import { gateway, generateText } from 'ai'; - -const result = await generateText({ - model: 'openai/gpt-5-nano', - prompt: - 'Search for news about AI regulations from the first week of January 2025.', - tools: { - perplexity_search: gateway.tools.perplexitySearch({ - maxResults: 5, - searchLanguageFilter: ['en'], - country: 'US', - searchDomainFilter: ['reuters.com', 'bbc.com', 'nytimes.com'], - }), - }, -}); - -console.log(result.text); -console.log('Tool calls:', JSON.stringify(result.toolCalls, null, 2)); -console.log('Tool results:', JSON.stringify(result.toolResults, null, 2)); -``` - -The Perplexity Search tool supports the following optional configuration options: - -- **maxResults** _number_ - - The maximum number of search results to return (1-20, default: 10). - -- **maxTokensPerPage** _number_ - - The maximum number of tokens to extract per search result page (256-2048, default: 2048). - -- **maxTokens** _number_ - - The maximum total tokens across all search results (default: 25000, max: 1000000). - -- **searchLanguageFilter** _string[]_ - - Filter search results by language using ISO 639-1 language codes (e.g., `['en']` for English, `['en', 'es']` for English and Spanish). - -- **country** _string_ - - Filter search results by country using ISO 3166-1 alpha-2 country codes (e.g., `'US'` for United States, `'GB'` for United Kingdom). - -- **searchDomainFilter** _string[]_ - - Limit search results to specific domains (e.g., `['reuters.com', 'bbc.com']`). This is useful for restricting results to trusted sources. - -- **searchRecencyFilter** _'day' | 'week' | 'month' | 'year'_ - - Filter search results by relative time period. Useful for always getting recent results (e.g., 'week' for results from the last week). - -The tool works with both `generateText` and `streamText`: - -```ts -import { gateway, streamText } from 'ai'; - -const result = streamText({ - model: 'openai/gpt-5-nano', - prompt: 'Search for the latest news about AI regulations.', - tools: { - perplexity_search: gateway.tools.perplexitySearch(), - }, -}); - -for await (const part of result.fullStream) { - switch (part.type) { - case 'text-delta': - process.stdout.write(part.text); - break; - case 'tool-call': - console.log('\nTool call:', JSON.stringify(part, null, 2)); - break; - case 'tool-result': - console.log('\nTool result:', JSON.stringify(part, null, 2)); - break; - } -} -``` - -#### Parallel Search - -The Parallel Search tool enables models to search the web using [Parallel AI's Search API](https://docs.parallel.ai/api-reference/search-beta/search). This tool is optimized for LLM consumption, returning relevant excerpts from web pages that can replace multiple keyword searches with a single call. - -```ts -import { gateway, generateText } from 'ai'; - -const result = await generateText({ - model: 'openai/gpt-5-nano', - prompt: 'Research the latest developments in quantum computing.', - tools: { - parallel_search: gateway.tools.parallelSearch(), - }, -}); - -console.log(result.text); -console.log('Tool calls:', JSON.stringify(result.toolCalls, null, 2)); -console.log('Tool results:', JSON.stringify(result.toolResults, null, 2)); -``` - -You can also configure the search with optional parameters: - -```ts -import { gateway, generateText } from 'ai'; - -const result = await generateText({ - model: 'openai/gpt-5-nano', - prompt: 'Find detailed information about TypeScript 5.0 features.', - tools: { - parallel_search: gateway.tools.parallelSearch({ - mode: 'agentic', - maxResults: 5, - sourcePolicy: { - includeDomains: ['typescriptlang.org', 'github.com'], - }, - excerpts: { - maxCharsPerResult: 8000, - }, - }), - }, -}); - -console.log(result.text); -console.log('Tool calls:', JSON.stringify(result.toolCalls, null, 2)); -console.log('Tool results:', JSON.stringify(result.toolResults, null, 2)); -``` - -The Parallel Search tool supports the following optional configuration options: - -- **mode** _'one-shot' | 'agentic'_ - - Mode preset for different use cases: - - - `'one-shot'` - Comprehensive results with longer excerpts for single-response answers (default) - - `'agentic'` - Concise, token-efficient results optimized for multi-step agentic workflows - -- **maxResults** _number_ - - Maximum number of results to return (1-20). Defaults to 10 if not specified. - -- **sourcePolicy** _object_ - - Source policy for controlling which domains to include/exclude: - - - `includeDomains` - List of domains to include in search results - - `excludeDomains` - List of domains to exclude from search results - - `afterDate` - Only include results published after this date (ISO 8601 format) - -- **excerpts** _object_ - - Excerpt configuration for controlling result length: - - - `maxCharsPerResult` - Maximum characters per result - - `maxCharsTotal` - Maximum total characters across all results - -- **fetchPolicy** _object_ - - Fetch policy for controlling content freshness: - - - `maxAgeSeconds` - Maximum age in seconds for cached content (set to 0 for always fresh) - -The tool works with both `generateText` and `streamText`: - -```ts -import { gateway, streamText } from 'ai'; - -const result = streamText({ - model: 'openai/gpt-5-nano', - prompt: 'Research the latest AI safety guidelines.', - tools: { - parallel_search: gateway.tools.parallelSearch(), - }, -}); - -for await (const part of result.fullStream) { - switch (part.type) { - case 'text-delta': - process.stdout.write(part.text); - break; - case 'tool-call': - console.log('\nTool call:', JSON.stringify(part, null, 2)); - break; - case 'tool-result': - console.log('\nTool result:', JSON.stringify(part, null, 2)); - break; - } -} -``` - -### Usage Tracking with User and Tags - -Track usage per end-user and categorize requests with tags: - -```ts -import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: 'openai/gpt-5', - prompt: 'Summarize this document...', - providerOptions: { - gateway: { - user: 'user-abc-123', // Track usage for this specific end-user - tags: ['document-summary', 'premium-feature'], // Categorize for reporting - } satisfies GatewayLanguageModelOptions, - }, -}); -``` - -This allows you to: - -- View usage and costs broken down by end-user in your analytics -- Filter and analyze spending by feature or use case using tags -- Track which users or features are driving the most AI usage - -## Provider Options - -The AI Gateway provider accepts provider options that control routing behavior and provider-specific configurations. - -### Gateway Provider Options - -You can use the `gateway` key in `providerOptions` to control how AI Gateway routes requests: - -```ts -import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: 'anthropic/claude-sonnet-4', - prompt: 'Explain quantum computing', - providerOptions: { - gateway: { - order: ['vertex', 'anthropic'], // Try Vertex AI first, then Anthropic - only: ['vertex', 'anthropic'], // Only use these providers - } satisfies GatewayLanguageModelOptions, - }, -}); -``` - -The following gateway provider options are available: - -- **order** _string[]_ - - Specifies the sequence of providers to attempt when routing requests. The gateway will try providers in the order specified. If a provider fails or is unavailable, it will move to the next provider in the list. - - Example: `order: ['bedrock', 'anthropic']` will attempt Amazon Bedrock first, then fall back to Anthropic. - -- **only** _string[]_ - - Restricts routing to only the specified providers. When set, the gateway will never route to providers not in this list, even if they would otherwise be available. - - Example: `only: ['anthropic', 'vertex']` will only allow routing to Anthropic or Vertex AI. - -- **models** _string[]_ - - Specifies fallback models to use when the primary model fails or is unavailable. The gateway will try the primary model first (specified in the `model` parameter), then try each model in this array in order until one succeeds. - - Example: `models: ['openai/gpt-5-nano', 'gemini-2.0-flash']` will try the fallback models in order if the primary model fails. - -- **user** _string_ - - Optional identifier for the end user on whose behalf the request is being made. This is used for spend tracking and attribution purposes, allowing you to track usage per end-user in your application. - - Example: `user: 'user-123'` will associate this request with end-user ID "user-123" in usage reports. - -- **tags** _string[]_ - - Optional array of tags for categorizing and filtering usage in reports. Useful for tracking spend by feature, prompt version, or any other dimension relevant to your application. - - Example: `tags: ['chat', 'v2']` will tag this request with "chat" and "v2" for filtering in usage analytics. - -- **byok** _Record<string, Array<Record<string, unknown>>>_ - - Request-scoped BYOK (Bring Your Own Key) credentials to use for this request. When provided, any cached BYOK credentials configured in the gateway system are not considered. Requests may still fall back to use system credentials if the provided credentials fail. - - Each provider can have multiple credentials (tried in order). The structure is a record where keys are provider slugs and values are arrays of credential objects. - - Examples: - - - Single provider: `byok: { 'anthropic': [{ apiKey: 'sk-ant-...' }] }` - - Multiple credentials: `byok: { 'vertex': [{ project: 'proj-1', googleCredentials: { privateKey: '...', clientEmail: '...' } }, { project: 'proj-2', googleCredentials: { privateKey: '...', clientEmail: '...' } }] }` - - Multiple providers: `byok: { 'anthropic': [{ apiKey: '...' }], 'bedrock': [{ accessKeyId: '...', secretAccessKey: '...' }] }` - -- **zeroDataRetention** _boolean_ - - Restricts routing requests to providers that have zero data retention policies. - -- **providerTimeouts** _object_ - - Per-provider timeouts for BYOK credentials in milliseconds. Controls how long to wait for a provider to start responding before falling back to the next available provider. - - Example: `providerTimeouts: { byok: { openai: 5000, anthropic: 2000 } }` - - For full details, see [Provider Timeouts](https://vercel.com/docs/ai-gateway/models-and-providers/provider-timeouts). - -You can combine these options to have fine-grained control over routing and tracking: - -```ts -import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: 'anthropic/claude-sonnet-4', - prompt: 'Write a haiku about programming', - providerOptions: { - gateway: { - order: ['vertex'], // Prefer Vertex AI - only: ['anthropic', 'vertex'], // Only allow these providers - } satisfies GatewayLanguageModelOptions, - }, -}); -``` - -#### Model Fallbacks Example - -The `models` option enables automatic fallback to alternative models when the primary model fails: - -```ts -import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: 'openai/gpt-4o', // Primary model - prompt: 'Write a TypeScript haiku', - providerOptions: { - gateway: { - models: ['openai/gpt-5-nano', 'gemini-2.0-flash'], // Fallback models - } satisfies GatewayLanguageModelOptions, - }, -}); - -// This will: -// 1. Try openai/gpt-4o first -// 2. If it fails, try openai/gpt-5-nano -// 3. If that fails, try gemini-2.0-flash -// 4. Return the result from the first model that succeeds -``` - -#### Zero Data Retention Example - -Set `zeroDataRetention` to true to ensure requests are only routed to providers -that have zero data retention policies. When `zeroDataRetention` is `false` or not -specified, there is no enforcement of restricting routing. - -```ts -import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: 'anthropic/claude-sonnet-4.5', - prompt: 'Analyze this sensitive document...', - providerOptions: { - gateway: { - zeroDataRetention: true, - } satisfies GatewayLanguageModelOptions, - }, -}); -``` - -### Provider-Specific Options - -When using provider-specific options through AI Gateway, use the actual provider name (e.g. `anthropic`, `openai`, not `gateway`) as the key: - -```ts -import type { AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: 'anthropic/claude-sonnet-4', - prompt: 'Explain quantum computing', - providerOptions: { - gateway: { - order: ['vertex', 'anthropic'], - } satisfies GatewayLanguageModelOptions, - anthropic: { - thinking: { type: 'enabled', budgetTokens: 12000 }, - } satisfies AnthropicLanguageModelOptions, - }, -}); -``` - -This works with any provider supported by AI Gateway. Each provider has its own set of options - see the individual [provider documentation pages](/providers/ai-sdk-providers) for details on provider-specific options. - -### Available Providers - -AI Gateway supports routing to 20+ providers. - -For a complete list of available providers and their slugs, see the [AI Gateway documentation](https://vercel.com/docs/ai-gateway/provider-options#available-providers). - -## Model Capabilities - -Model capabilities depend on the specific provider and model you're using. For detailed capability information, see: - -- [AI Gateway provider options](https://vercel.com/docs/ai-gateway/provider-options#available-providers) for an overview of available providers -- Individual [AI SDK provider pages](/providers/ai-sdk-providers) for specific model capabilities and features diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/package.json deleted file mode 100644 index 66da58a04..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/package.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "name": "@ai-sdk/gateway", - "private": false, - "version": "3.0.80", - "license": "Apache-2.0", - "sideEffects": false, - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", - "files": [ - "dist/**/*", - "docs/**/*", - "src", - "!src/**/*.test.ts", - "!src/**/*.test-d.ts", - "!src/**/__snapshots__", - "!src/**/__fixtures__", - "CHANGELOG.md", - "README.md" - ], - "directories": { - "doc": "./docs" - }, - "exports": { - "./package.json": "./package.json", - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" - } - }, - "dependencies": { - "@vercel/oidc": "3.1.0", - "@ai-sdk/provider": "3.0.8", - "@ai-sdk/provider-utils": "4.0.21" - }, - "devDependencies": { - "@types/node": "18.15.11", - "tsup": "^8", - "tsx": "4.19.2", - "typescript": "5.8.3", - "zod": "3.25.76", - "@ai-sdk/test-server": "1.0.3", - "@vercel/ai-tsconfig": "0.0.0" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public" - }, - "homepage": "https://ai-sdk.dev/docs", - "repository": { - "type": "git", - "url": "git+https://github.com/vercel/ai.git" - }, - "bugs": { - "url": "https://github.com/vercel/ai/issues" - }, - "keywords": [ - "ai" - ], - "scripts": { - "build": "pnpm clean && tsup --tsconfig tsconfig.build.json", - "build:watch": "pnpm clean && tsup --watch", - "clean": "del-cli dist docs *.tsbuildinfo", - "generate-model-settings": "tsx scripts/generate-model-settings.ts", - "type-check": "tsc --build", - "test": "pnpm test:node && pnpm test:edge", - "test:update": "pnpm test:node -u", - "test:watch": "vitest --config vitest.node.config.js", - "test:edge": "vitest --config vitest.edge.config.js --run", - "test:node": "vitest --config vitest.node.config.js --run" - } -} \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/as-gateway-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/as-gateway-error.ts deleted file mode 100644 index 07ae080ef..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/as-gateway-error.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { APICallError } from '@ai-sdk/provider'; -import { extractApiCallResponse, GatewayError } from '.'; -import { createGatewayErrorFromResponse } from './create-gateway-error'; -import { GatewayTimeoutError } from './gateway-timeout-error'; - -/** - * Checks if an error is a timeout error from undici. - * Only checks undici-specific error codes to avoid false positives. - */ -function isTimeoutError(error: unknown): boolean { - if (!(error instanceof Error)) { - return false; - } - - // Check for undici-specific timeout error codes - const errorCode = (error as any).code; - if (typeof errorCode === 'string') { - const undiciTimeoutCodes = [ - 'UND_ERR_HEADERS_TIMEOUT', - 'UND_ERR_BODY_TIMEOUT', - 'UND_ERR_CONNECT_TIMEOUT', - ]; - return undiciTimeoutCodes.includes(errorCode); - } - - return false; -} - -export async function asGatewayError( - error: unknown, - authMethod?: 'api-key' | 'oidc', -) { - if (GatewayError.isInstance(error)) { - return error; - } - - // Check if this is a timeout error (or has a timeout error in the cause chain) - if (isTimeoutError(error)) { - return GatewayTimeoutError.createTimeoutError({ - originalMessage: error instanceof Error ? error.message : 'Unknown error', - cause: error, - }); - } - - // Check if this is an APICallError caused by a timeout - if (APICallError.isInstance(error)) { - // Check if the cause is a timeout error - if (error.cause && isTimeoutError(error.cause)) { - return GatewayTimeoutError.createTimeoutError({ - originalMessage: error.message, - cause: error, - }); - } - - return await createGatewayErrorFromResponse({ - response: extractApiCallResponse(error), - statusCode: error.statusCode ?? 500, - defaultMessage: 'Gateway request failed', - cause: error, - authMethod, - }); - } - - return await createGatewayErrorFromResponse({ - response: {}, - statusCode: 500, - defaultMessage: - error instanceof Error - ? `Gateway request failed: ${error.message}` - : 'Unknown Gateway error', - cause: error, - authMethod, - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/create-gateway-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/create-gateway-error.ts deleted file mode 100644 index 68a827de1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/create-gateway-error.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { z } from 'zod/v4'; -import type { GatewayError } from './gateway-error'; -import { GatewayAuthenticationError } from './gateway-authentication-error'; -import { GatewayInvalidRequestError } from './gateway-invalid-request-error'; -import { GatewayRateLimitError } from './gateway-rate-limit-error'; -import { - GatewayModelNotFoundError, - modelNotFoundParamSchema, -} from './gateway-model-not-found-error'; -import { GatewayInternalServerError } from './gateway-internal-server-error'; -import { GatewayResponseError } from './gateway-response-error'; -import { - InferSchema, - lazySchema, - safeValidateTypes, - validateTypes, - zodSchema, -} from '@ai-sdk/provider-utils'; - -export async function createGatewayErrorFromResponse({ - response, - statusCode, - defaultMessage = 'Gateway request failed', - cause, - authMethod, -}: { - response: unknown; - statusCode: number; - defaultMessage?: string; - cause?: unknown; - authMethod?: 'api-key' | 'oidc'; -}): Promise { - const parseResult = await safeValidateTypes({ - value: response, - schema: gatewayErrorResponseSchema, - }); - - if (!parseResult.success) { - // Try to extract generationId even if validation failed - const rawGenerationId = - typeof response === 'object' && - response !== null && - 'generationId' in response - ? (response as { generationId?: string }).generationId - : undefined; - - return new GatewayResponseError({ - message: `Invalid error response format: ${defaultMessage}`, - statusCode, - response, - validationError: parseResult.error, - cause, - generationId: rawGenerationId, - }); - } - - const validatedResponse: GatewayErrorResponse = parseResult.value; - const errorType = validatedResponse.error.type; - const message = validatedResponse.error.message; - const generationId = validatedResponse.generationId ?? undefined; - - switch (errorType) { - case 'authentication_error': - return GatewayAuthenticationError.createContextualError({ - apiKeyProvided: authMethod === 'api-key', - oidcTokenProvided: authMethod === 'oidc', - statusCode, - cause, - generationId, - }); - case 'invalid_request_error': - return new GatewayInvalidRequestError({ - message, - statusCode, - cause, - generationId, - }); - case 'rate_limit_exceeded': - return new GatewayRateLimitError({ - message, - statusCode, - cause, - generationId, - }); - case 'model_not_found': { - const modelResult = await safeValidateTypes({ - value: validatedResponse.error.param, - schema: modelNotFoundParamSchema, - }); - - return new GatewayModelNotFoundError({ - message, - statusCode, - modelId: modelResult.success ? modelResult.value.modelId : undefined, - cause, - generationId, - }); - } - case 'internal_server_error': - return new GatewayInternalServerError({ - message, - statusCode, - cause, - generationId, - }); - default: - return new GatewayInternalServerError({ - message, - statusCode, - cause, - generationId, - }); - } -} - -const gatewayErrorResponseSchema = lazySchema(() => - zodSchema( - z.object({ - error: z.object({ - message: z.string(), - type: z.string().nullish(), - param: z.unknown().nullish(), - code: z.union([z.string(), z.number()]).nullish(), - }), - generationId: z.string().nullish(), - }), - ), -); - -export type GatewayErrorResponse = InferSchema< - typeof gatewayErrorResponseSchema ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/extract-api-call-response.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/extract-api-call-response.ts deleted file mode 100644 index e99662aac..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/extract-api-call-response.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { APICallError } from '@ai-sdk/provider'; - -export function extractApiCallResponse(error: APICallError): unknown { - if (error.data !== undefined) { - return error.data; - } - if (error.responseBody != null) { - try { - return JSON.parse(error.responseBody); - } catch { - return error.responseBody; - } - } - return {}; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-authentication-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-authentication-error.ts deleted file mode 100644 index f62136104..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-authentication-error.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { GatewayError } from './gateway-error'; - -const name = 'GatewayAuthenticationError'; -const marker = `vercel.ai.gateway.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Authentication failed - invalid API key or OIDC token - */ -export class GatewayAuthenticationError extends GatewayError { - private readonly [symbol] = true; // used in isInstance - - readonly name = name; - readonly type = 'authentication_error'; - - constructor({ - message = 'Authentication failed', - statusCode = 401, - cause, - generationId, - }: { - message?: string; - statusCode?: number; - cause?: unknown; - generationId?: string; - } = {}) { - super({ message, statusCode, cause, generationId }); - } - - static isInstance(error: unknown): error is GatewayAuthenticationError { - return GatewayError.hasMarker(error) && symbol in error; - } - - /** - * Creates a contextual error message when authentication fails - */ - static createContextualError({ - apiKeyProvided, - oidcTokenProvided, - message = 'Authentication failed', - statusCode = 401, - cause, - generationId, - }: { - apiKeyProvided: boolean; - oidcTokenProvided: boolean; - message?: string; - statusCode?: number; - cause?: unknown; - generationId?: string; - }): GatewayAuthenticationError { - let contextualMessage: string; - - if (apiKeyProvided) { - contextualMessage = `AI Gateway authentication failed: Invalid API key. - -Create a new API key: https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai%2Fapi-keys - -Provide via 'apiKey' option or 'AI_GATEWAY_API_KEY' environment variable.`; - } else if (oidcTokenProvided) { - contextualMessage = `AI Gateway authentication failed: Invalid OIDC token. - -Run 'npx vercel link' to link your project, then 'vc env pull' to fetch the token. - -Alternatively, use an API key: https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai%2Fapi-keys`; - } else { - contextualMessage = `AI Gateway authentication failed: No authentication provided. - -Option 1 - API key: -Create an API key: https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai%2Fapi-keys -Provide via 'apiKey' option or 'AI_GATEWAY_API_KEY' environment variable. - -Option 2 - OIDC token: -Run 'npx vercel link' to link your project, then 'vc env pull' to fetch the token.`; - } - - return new GatewayAuthenticationError({ - message: contextualMessage, - statusCode, - cause, - generationId, - }); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-error.ts deleted file mode 100644 index 669dcc294..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-error.ts +++ /dev/null @@ -1,47 +0,0 @@ -const marker = 'vercel.ai.gateway.error'; -const symbol = Symbol.for(marker); - -export abstract class GatewayError extends Error { - private readonly [symbol] = true; // used in isInstance - - abstract readonly name: string; - abstract readonly type: string; - readonly statusCode: number; - readonly cause?: unknown; - readonly generationId?: string; - - constructor({ - message, - statusCode = 500, - cause, - generationId, - }: { - message: string; - statusCode?: number; - cause?: unknown; - generationId?: string; - }) { - super(generationId ? `${message} [${generationId}]` : message); - this.statusCode = statusCode; - this.cause = cause; - this.generationId = generationId; - } - - /** - * Checks if the given error is a Gateway Error. - * @param {unknown} error - The error to check. - * @returns {boolean} True if the error is a Gateway Error, false otherwise. - */ - static isInstance(error: unknown): error is GatewayError { - return GatewayError.hasMarker(error); - } - - static hasMarker(error: unknown): error is GatewayError { - return ( - typeof error === 'object' && - error !== null && - symbol in error && - (error as any)[symbol] === true - ); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-internal-server-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-internal-server-error.ts deleted file mode 100644 index 4b2e99909..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-internal-server-error.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { GatewayError } from './gateway-error'; - -const name = 'GatewayInternalServerError'; -const marker = `vercel.ai.gateway.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Internal server error from the Gateway - */ -export class GatewayInternalServerError extends GatewayError { - private readonly [symbol] = true; // used in isInstance - - readonly name = name; - readonly type = 'internal_server_error'; - - constructor({ - message = 'Internal server error', - statusCode = 500, - cause, - generationId, - }: { - message?: string; - statusCode?: number; - cause?: unknown; - generationId?: string; - } = {}) { - super({ message, statusCode, cause, generationId }); - } - - static isInstance(error: unknown): error is GatewayInternalServerError { - return GatewayError.hasMarker(error) && symbol in error; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-invalid-request-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-invalid-request-error.ts deleted file mode 100644 index c7ec507e9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-invalid-request-error.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { GatewayError } from './gateway-error'; - -const name = 'GatewayInvalidRequestError'; -const marker = `vercel.ai.gateway.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Invalid request - missing headers, malformed data, etc. - */ -export class GatewayInvalidRequestError extends GatewayError { - private readonly [symbol] = true; // used in isInstance - - readonly name = name; - readonly type = 'invalid_request_error'; - - constructor({ - message = 'Invalid request', - statusCode = 400, - cause, - generationId, - }: { - message?: string; - statusCode?: number; - cause?: unknown; - generationId?: string; - } = {}) { - super({ message, statusCode, cause, generationId }); - } - - static isInstance(error: unknown): error is GatewayInvalidRequestError { - return GatewayError.hasMarker(error) && symbol in error; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-model-not-found-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-model-not-found-error.ts deleted file mode 100644 index 6f23fda81..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-model-not-found-error.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { z } from 'zod/v4'; -import { GatewayError } from './gateway-error'; -import { lazySchema, zodSchema } from '@ai-sdk/provider-utils'; - -const name = 'GatewayModelNotFoundError'; -const marker = `vercel.ai.gateway.error.${name}`; -const symbol = Symbol.for(marker); - -export const modelNotFoundParamSchema = lazySchema(() => - zodSchema( - z.object({ - modelId: z.string(), - }), - ), -); - -/** - * Model not found or not available - */ -export class GatewayModelNotFoundError extends GatewayError { - private readonly [symbol] = true; // used in isInstance - - readonly name = name; - readonly type = 'model_not_found'; - readonly modelId?: string; - - constructor({ - message = 'Model not found', - statusCode = 404, - modelId, - cause, - generationId, - }: { - message?: string; - statusCode?: number; - modelId?: string; - cause?: unknown; - generationId?: string; - } = {}) { - super({ message, statusCode, cause, generationId }); - this.modelId = modelId; - } - - static isInstance(error: unknown): error is GatewayModelNotFoundError { - return GatewayError.hasMarker(error) && symbol in error; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-rate-limit-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-rate-limit-error.ts deleted file mode 100644 index 09867eead..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-rate-limit-error.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { GatewayError } from './gateway-error'; - -const name = 'GatewayRateLimitError'; -const marker = `vercel.ai.gateway.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Rate limit exceeded. - */ -export class GatewayRateLimitError extends GatewayError { - private readonly [symbol] = true; // used in isInstance - - readonly name = name; - readonly type = 'rate_limit_exceeded'; - - constructor({ - message = 'Rate limit exceeded', - statusCode = 429, - cause, - generationId, - }: { - message?: string; - statusCode?: number; - cause?: unknown; - generationId?: string; - } = {}) { - super({ message, statusCode, cause, generationId }); - } - - static isInstance(error: unknown): error is GatewayRateLimitError { - return GatewayError.hasMarker(error) && symbol in error; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-response-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-response-error.ts deleted file mode 100644 index 7bc05d7c7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-response-error.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { TypeValidationError } from '@ai-sdk/provider'; -import { GatewayError } from './gateway-error'; - -const name = 'GatewayResponseError'; -const marker = `vercel.ai.gateway.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Gateway response parsing error - */ -export class GatewayResponseError extends GatewayError { - private readonly [symbol] = true; // used in isInstance - - readonly name = name; - readonly type = 'response_error'; - readonly response?: unknown; - readonly validationError?: TypeValidationError; - - constructor({ - message = 'Invalid response from Gateway', - statusCode = 502, - response, - validationError, - cause, - generationId, - }: { - message?: string; - statusCode?: number; - response?: unknown; - validationError?: TypeValidationError; - cause?: unknown; - generationId?: string; - } = {}) { - super({ message, statusCode, cause, generationId }); - this.response = response; - this.validationError = validationError; - } - - static isInstance(error: unknown): error is GatewayResponseError { - return GatewayError.hasMarker(error) && symbol in error; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-timeout-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-timeout-error.ts deleted file mode 100644 index d99df6293..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/gateway-timeout-error.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { GatewayError } from './gateway-error'; - -const name = 'GatewayTimeoutError'; -const marker = `vercel.ai.gateway.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Client request timed out before receiving a response. - */ -export class GatewayTimeoutError extends GatewayError { - private readonly [symbol] = true; // used in isInstance - - readonly name = name; - readonly type = 'timeout_error'; - - constructor({ - message = 'Request timed out', - statusCode = 408, - cause, - generationId, - }: { - message?: string; - statusCode?: number; - cause?: unknown; - generationId?: string; - } = {}) { - super({ message, statusCode, cause, generationId }); - } - - static isInstance(error: unknown): error is GatewayTimeoutError { - return GatewayError.hasMarker(error) && symbol in error; - } - - /** - * Creates a helpful timeout error message with troubleshooting guidance - */ - static createTimeoutError({ - originalMessage, - statusCode = 408, - cause, - generationId, - }: { - originalMessage: string; - statusCode?: number; - cause?: unknown; - generationId?: string; - }): GatewayTimeoutError { - const message = `Gateway request timed out: ${originalMessage} - - This is a client-side timeout. To resolve this, increase your timeout configuration: https://vercel.com/docs/ai-gateway/capabilities/video-generation#extending-timeouts-for-node.js`; - - return new GatewayTimeoutError({ - message, - statusCode, - cause, - generationId, - }); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/index.ts deleted file mode 100644 index e5d8f7f7e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -export { asGatewayError } from './as-gateway-error'; -export { - createGatewayErrorFromResponse, - type GatewayErrorResponse, -} from './create-gateway-error'; -export { extractApiCallResponse } from './extract-api-call-response'; -export { GatewayError } from './gateway-error'; -export { GatewayAuthenticationError } from './gateway-authentication-error'; -export { GatewayInternalServerError } from './gateway-internal-server-error'; -export { GatewayInvalidRequestError } from './gateway-invalid-request-error'; -export { - GatewayModelNotFoundError, - modelNotFoundParamSchema, -} from './gateway-model-not-found-error'; -export { GatewayRateLimitError } from './gateway-rate-limit-error'; -export { GatewayResponseError } from './gateway-response-error'; -export { GatewayTimeoutError } from './gateway-timeout-error'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/parse-auth-method.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/parse-auth-method.ts deleted file mode 100644 index 3efe41a6f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/errors/parse-auth-method.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { z } from 'zod/v4'; -import { - lazySchema, - safeValidateTypes, - zodSchema, -} from '@ai-sdk/provider-utils'; - -export const GATEWAY_AUTH_METHOD_HEADER = 'ai-gateway-auth-method' as const; - -export async function parseAuthMethod( - headers: Record, -) { - const result = await safeValidateTypes({ - value: headers[GATEWAY_AUTH_METHOD_HEADER], - schema: gatewayAuthMethodSchema, - }); - - return result.success ? result.value : undefined; -} - -const gatewayAuthMethodSchema = lazySchema(() => - zodSchema(z.union([z.literal('api-key'), z.literal('oidc')])), -); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-config.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-config.ts deleted file mode 100644 index 3edf37da6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { FetchFunction, Resolvable } from '@ai-sdk/provider-utils'; - -export type GatewayConfig = { - baseURL: string; - headers: () => Resolvable>; - fetch?: FetchFunction; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-embedding-model-settings.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-embedding-model-settings.ts deleted file mode 100644 index 70d8384e8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-embedding-model-settings.ts +++ /dev/null @@ -1,26 +0,0 @@ -export type GatewayEmbeddingModelId = - | 'alibaba/qwen3-embedding-0.6b' - | 'alibaba/qwen3-embedding-4b' - | 'alibaba/qwen3-embedding-8b' - | 'amazon/titan-embed-text-v2' - | 'cohere/embed-v4.0' - | 'google/gemini-embedding-001' - | 'google/gemini-embedding-2' - | 'google/text-embedding-005' - | 'google/text-multilingual-embedding-002' - | 'mistral/codestral-embed' - | 'mistral/mistral-embed' - | 'openai/text-embedding-3-large' - | 'openai/text-embedding-3-small' - | 'openai/text-embedding-ada-002' - | 'voyage/voyage-3-large' - | 'voyage/voyage-3.5' - | 'voyage/voyage-3.5-lite' - | 'voyage/voyage-4' - | 'voyage/voyage-4-large' - | 'voyage/voyage-4-lite' - | 'voyage/voyage-code-2' - | 'voyage/voyage-code-3' - | 'voyage/voyage-finance-2' - | 'voyage/voyage-law-2' - | (string & {}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-embedding-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-embedding-model.ts deleted file mode 100644 index 80c9ee1d4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-embedding-model.ts +++ /dev/null @@ -1,109 +0,0 @@ -import type { - EmbeddingModelV3, - SharedV3ProviderMetadata, -} from '@ai-sdk/provider'; -import { - combineHeaders, - createJsonErrorResponseHandler, - createJsonResponseHandler, - lazySchema, - postJsonToApi, - resolve, - zodSchema, - type Resolvable, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import { asGatewayError } from './errors'; -import { parseAuthMethod } from './errors/parse-auth-method'; -import type { GatewayConfig } from './gateway-config'; - -export class GatewayEmbeddingModel implements EmbeddingModelV3 { - readonly specificationVersion = 'v3'; - readonly maxEmbeddingsPerCall = 2048; - readonly supportsParallelCalls = true; - - constructor( - readonly modelId: string, - private readonly config: GatewayConfig & { - provider: string; - o11yHeaders: Resolvable>; - }, - ) {} - - get provider(): string { - return this.config.provider; - } - - async doEmbed({ - values, - headers, - abortSignal, - providerOptions, - }: Parameters[0]): Promise< - Awaited> - > { - const resolvedHeaders = await resolve(this.config.headers()); - try { - const { - responseHeaders, - value: responseBody, - rawValue, - } = await postJsonToApi({ - url: this.getUrl(), - headers: combineHeaders( - resolvedHeaders, - headers ?? {}, - this.getModelConfigHeaders(), - await resolve(this.config.o11yHeaders), - ), - body: { - values, - ...(providerOptions ? { providerOptions } : {}), - }, - successfulResponseHandler: createJsonResponseHandler( - gatewayEmbeddingResponseSchema, - ), - failedResponseHandler: createJsonErrorResponseHandler({ - errorSchema: z.any(), - errorToMessage: data => data, - }), - ...(abortSignal && { abortSignal }), - fetch: this.config.fetch, - }); - - return { - embeddings: responseBody.embeddings, - usage: responseBody.usage ?? undefined, - providerMetadata: - responseBody.providerMetadata as unknown as SharedV3ProviderMetadata, - response: { headers: responseHeaders, body: rawValue }, - warnings: [], - }; - } catch (error) { - throw await asGatewayError(error, await parseAuthMethod(resolvedHeaders)); - } - } - - private getUrl() { - return `${this.config.baseURL}/embedding-model`; - } - - private getModelConfigHeaders() { - return { - 'ai-embedding-model-specification-version': '3', - 'ai-model-id': this.modelId, - }; - } -} - -const gatewayEmbeddingResponseSchema = lazySchema(() => - zodSchema( - z.object({ - embeddings: z.array(z.array(z.number())), - usage: z.object({ tokens: z.number() }).nullish(), - providerMetadata: z - .record(z.string(), z.record(z.string(), z.unknown())) - .optional(), - }), - ), -); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-fetch-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-fetch-metadata.ts deleted file mode 100644 index 44f8c3c3d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-fetch-metadata.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { - createJsonErrorResponseHandler, - createJsonResponseHandler, - getFromApi, - lazySchema, - resolve, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import { asGatewayError } from './errors'; -import type { GatewayConfig } from './gateway-config'; -import type { GatewayLanguageModelEntry } from './gateway-model-entry'; - -type GatewayFetchMetadataConfig = GatewayConfig; - -export interface GatewayFetchMetadataResponse { - models: GatewayLanguageModelEntry[]; -} - -export interface GatewayCreditsResponse { - /** The remaining gateway credit balance available for API usage */ - balance: string; - /** The total amount of gateway credits that have been consumed */ - totalUsed: string; -} - -export class GatewayFetchMetadata { - constructor(private readonly config: GatewayFetchMetadataConfig) {} - - async getAvailableModels(): Promise { - try { - const { value } = await getFromApi({ - url: `${this.config.baseURL}/config`, - headers: await resolve(this.config.headers()), - successfulResponseHandler: createJsonResponseHandler( - gatewayAvailableModelsResponseSchema, - ), - failedResponseHandler: createJsonErrorResponseHandler({ - errorSchema: z.any(), - errorToMessage: data => data, - }), - fetch: this.config.fetch, - }); - - return value; - } catch (error) { - throw await asGatewayError(error); - } - } - - async getCredits(): Promise { - try { - const baseUrl = new URL(this.config.baseURL); - - const { value } = await getFromApi({ - url: `${baseUrl.origin}/v1/credits`, - headers: await resolve(this.config.headers()), - successfulResponseHandler: createJsonResponseHandler( - gatewayCreditsResponseSchema, - ), - failedResponseHandler: createJsonErrorResponseHandler({ - errorSchema: z.any(), - errorToMessage: data => data, - }), - fetch: this.config.fetch, - }); - - return value; - } catch (error) { - throw await asGatewayError(error); - } - } -} - -const gatewayAvailableModelsResponseSchema = lazySchema(() => - zodSchema( - z.object({ - models: z.array( - z.object({ - id: z.string(), - name: z.string(), - description: z.string().nullish(), - pricing: z - .object({ - input: z.string(), - output: z.string(), - input_cache_read: z.string().nullish(), - input_cache_write: z.string().nullish(), - }) - .transform( - ({ input, output, input_cache_read, input_cache_write }) => ({ - input, - output, - ...(input_cache_read - ? { cachedInputTokens: input_cache_read } - : {}), - ...(input_cache_write - ? { cacheCreationInputTokens: input_cache_write } - : {}), - }), - ) - .nullish(), - specification: z.object({ - specificationVersion: z.literal('v3'), - provider: z.string(), - modelId: z.string(), - }), - modelType: z - .enum(['embedding', 'image', 'language', 'video']) - .nullish(), - }), - ), - }), - ), -); - -const gatewayCreditsResponseSchema = lazySchema(() => - zodSchema( - z - .object({ - balance: z.string(), - total_used: z.string(), - }) - .transform(({ balance, total_used }) => ({ - balance, - totalUsed: total_used, - })), - ), -); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-image-model-settings.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-image-model-settings.ts deleted file mode 100644 index f48bff9d8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-image-model-settings.ts +++ /dev/null @@ -1,25 +0,0 @@ -export type GatewayImageModelId = - | 'bfl/flux-2-flex' - | 'bfl/flux-2-klein-4b' - | 'bfl/flux-2-klein-9b' - | 'bfl/flux-2-max' - | 'bfl/flux-2-pro' - | 'bfl/flux-kontext-max' - | 'bfl/flux-kontext-pro' - | 'bfl/flux-pro-1.0-fill' - | 'bfl/flux-pro-1.1' - | 'bfl/flux-pro-1.1-ultra' - | 'google/imagen-4.0-fast-generate-001' - | 'google/imagen-4.0-generate-001' - | 'google/imagen-4.0-ultra-generate-001' - | 'openai/gpt-image-1' - | 'openai/gpt-image-1-mini' - | 'openai/gpt-image-1.5' - | 'prodia/flux-fast-schnell' - | 'recraft/recraft-v2' - | 'recraft/recraft-v3' - | 'recraft/recraft-v4' - | 'recraft/recraft-v4-pro' - | 'xai/grok-imagine-image' - | 'xai/grok-imagine-image-pro' - | (string & {}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-image-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-image-model.ts deleted file mode 100644 index 44b698875..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-image-model.ts +++ /dev/null @@ -1,169 +0,0 @@ -import type { - ImageModelV3, - ImageModelV3File, - ImageModelV3ProviderMetadata, -} from '@ai-sdk/provider'; -import { - combineHeaders, - convertUint8ArrayToBase64, - createJsonResponseHandler, - createJsonErrorResponseHandler, - postJsonToApi, - resolve, - type Resolvable, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import type { GatewayConfig } from './gateway-config'; -import { asGatewayError } from './errors'; -import { parseAuthMethod } from './errors/parse-auth-method'; - -export class GatewayImageModel implements ImageModelV3 { - readonly specificationVersion = 'v3' as const; - // Set a very large number to prevent client-side splitting of requests - readonly maxImagesPerCall = Number.MAX_SAFE_INTEGER; - - constructor( - readonly modelId: string, - private readonly config: GatewayConfig & { - provider: string; - o11yHeaders: Resolvable>; - }, - ) {} - - get provider(): string { - return this.config.provider; - } - - async doGenerate({ - prompt, - n, - size, - aspectRatio, - seed, - files, - mask, - providerOptions, - headers, - abortSignal, - }: Parameters[0]): Promise< - Awaited> - > { - const resolvedHeaders = await resolve(this.config.headers()); - try { - const { - responseHeaders, - value: responseBody, - rawValue, - } = await postJsonToApi({ - url: this.getUrl(), - headers: combineHeaders( - resolvedHeaders, - headers ?? {}, - this.getModelConfigHeaders(), - await resolve(this.config.o11yHeaders), - ), - body: { - prompt, - n, - ...(size && { size }), - ...(aspectRatio && { aspectRatio }), - ...(seed && { seed }), - ...(providerOptions && { providerOptions }), - ...(files && { - files: files.map(file => maybeEncodeImageFile(file)), - }), - ...(mask && { mask: maybeEncodeImageFile(mask) }), - }, - successfulResponseHandler: createJsonResponseHandler( - gatewayImageResponseSchema, - ), - failedResponseHandler: createJsonErrorResponseHandler({ - errorSchema: z.any(), - errorToMessage: data => data, - }), - ...(abortSignal && { abortSignal }), - fetch: this.config.fetch, - }); - - return { - images: responseBody.images, // Always base64 strings from server - warnings: responseBody.warnings ?? [], - providerMetadata: - responseBody.providerMetadata as ImageModelV3ProviderMetadata, - response: { - timestamp: new Date(), - modelId: this.modelId, - headers: responseHeaders, - }, - ...(responseBody.usage != null && { - usage: { - inputTokens: responseBody.usage.inputTokens ?? undefined, - outputTokens: responseBody.usage.outputTokens ?? undefined, - totalTokens: responseBody.usage.totalTokens ?? undefined, - }, - }), - }; - } catch (error) { - throw await asGatewayError(error, await parseAuthMethod(resolvedHeaders)); - } - } - - private getUrl() { - return `${this.config.baseURL}/image-model`; - } - - private getModelConfigHeaders() { - return { - 'ai-image-model-specification-version': '3', - 'ai-model-id': this.modelId, - }; - } -} - -function maybeEncodeImageFile(file: ImageModelV3File) { - if (file.type === 'file' && file.data instanceof Uint8Array) { - return { - ...file, - data: convertUint8ArrayToBase64(file.data), - }; - } - return file; -} - -const providerMetadataEntrySchema = z - .object({ - images: z.array(z.unknown()).optional(), - }) - .catchall(z.unknown()); - -const gatewayImageWarningSchema = z.discriminatedUnion('type', [ - z.object({ - type: z.literal('unsupported'), - feature: z.string(), - details: z.string().optional(), - }), - z.object({ - type: z.literal('compatibility'), - feature: z.string(), - details: z.string().optional(), - }), - z.object({ - type: z.literal('other'), - message: z.string(), - }), -]); - -const gatewayImageUsageSchema = z.object({ - inputTokens: z.number().nullish(), - outputTokens: z.number().nullish(), - totalTokens: z.number().nullish(), -}); - -const gatewayImageResponseSchema = z.object({ - images: z.array(z.string()), // Always base64 strings over the wire - warnings: z.array(gatewayImageWarningSchema).optional(), - providerMetadata: z - .record(z.string(), providerMetadataEntrySchema) - .optional(), - usage: gatewayImageUsageSchema.optional(), -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-language-model-settings.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-language-model-settings.ts deleted file mode 100644 index 06bf147c4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-language-model-settings.ts +++ /dev/null @@ -1,183 +0,0 @@ -export type GatewayModelId = - | 'alibaba/qwen-3-14b' - | 'alibaba/qwen-3-235b' - | 'alibaba/qwen-3-30b' - | 'alibaba/qwen-3-32b' - | 'alibaba/qwen3-235b-a22b-thinking' - | 'alibaba/qwen3-coder' - | 'alibaba/qwen3-coder-30b-a3b' - | 'alibaba/qwen3-coder-next' - | 'alibaba/qwen3-coder-plus' - | 'alibaba/qwen3-max' - | 'alibaba/qwen3-max-preview' - | 'alibaba/qwen3-max-thinking' - | 'alibaba/qwen3-next-80b-a3b-instruct' - | 'alibaba/qwen3-next-80b-a3b-thinking' - | 'alibaba/qwen3-vl-instruct' - | 'alibaba/qwen3-vl-thinking' - | 'alibaba/qwen3.5-flash' - | 'alibaba/qwen3.5-plus' - | 'amazon/nova-2-lite' - | 'amazon/nova-lite' - | 'amazon/nova-micro' - | 'amazon/nova-pro' - | 'anthropic/claude-3-haiku' - | 'anthropic/claude-3-opus' - | 'anthropic/claude-3.5-haiku' - | 'anthropic/claude-3.5-sonnet' - | 'anthropic/claude-3.5-sonnet-20240620' - | 'anthropic/claude-3.7-sonnet' - | 'anthropic/claude-haiku-4.5' - | 'anthropic/claude-opus-4' - | 'anthropic/claude-opus-4.1' - | 'anthropic/claude-opus-4.5' - | 'anthropic/claude-opus-4.6' - | 'anthropic/claude-sonnet-4' - | 'anthropic/claude-sonnet-4.5' - | 'anthropic/claude-sonnet-4.6' - | 'arcee-ai/trinity-large-preview' - | 'arcee-ai/trinity-mini' - | 'bytedance/seed-1.6' - | 'bytedance/seed-1.8' - | 'cohere/command-a' - | 'deepseek/deepseek-r1' - | 'deepseek/deepseek-v3' - | 'deepseek/deepseek-v3.1' - | 'deepseek/deepseek-v3.1-terminus' - | 'deepseek/deepseek-v3.2' - | 'deepseek/deepseek-v3.2-thinking' - | 'google/gemini-2.0-flash' - | 'google/gemini-2.0-flash-lite' - | 'google/gemini-2.5-flash' - | 'google/gemini-2.5-flash-image' - | 'google/gemini-2.5-flash-lite' - | 'google/gemini-2.5-pro' - | 'google/gemini-3-flash' - | 'google/gemini-3-pro-image' - | 'google/gemini-3-pro-preview' - | 'google/gemini-3.1-flash-image-preview' - | 'google/gemini-3.1-flash-lite-preview' - | 'google/gemini-3.1-pro-preview' - | 'inception/mercury-2' - | 'inception/mercury-coder-small' - | 'kwaipilot/kat-coder-pro-v1' - | 'meituan/longcat-flash-chat' - | 'meituan/longcat-flash-thinking' - | 'meituan/longcat-flash-thinking-2601' - | 'meta/llama-3.1-70b' - | 'meta/llama-3.1-8b' - | 'meta/llama-3.2-11b' - | 'meta/llama-3.2-1b' - | 'meta/llama-3.2-3b' - | 'meta/llama-3.2-90b' - | 'meta/llama-3.3-70b' - | 'meta/llama-4-maverick' - | 'meta/llama-4-scout' - | 'minimax/minimax-m2' - | 'minimax/minimax-m2.1' - | 'minimax/minimax-m2.1-lightning' - | 'minimax/minimax-m2.5' - | 'minimax/minimax-m2.5-highspeed' - | 'minimax/minimax-m2.7' - | 'minimax/minimax-m2.7-highspeed' - | 'mistral/codestral' - | 'mistral/devstral-2' - | 'mistral/devstral-small' - | 'mistral/devstral-small-2' - | 'mistral/magistral-medium' - | 'mistral/magistral-small' - | 'mistral/ministral-14b' - | 'mistral/ministral-3b' - | 'mistral/ministral-8b' - | 'mistral/mistral-large-3' - | 'mistral/mistral-medium' - | 'mistral/mistral-nemo' - | 'mistral/mistral-small' - | 'mistral/mixtral-8x22b-instruct' - | 'mistral/pixtral-12b' - | 'mistral/pixtral-large' - | 'moonshotai/kimi-k2' - | 'moonshotai/kimi-k2-0905' - | 'moonshotai/kimi-k2-thinking' - | 'moonshotai/kimi-k2-thinking-turbo' - | 'moonshotai/kimi-k2-turbo' - | 'moonshotai/kimi-k2.5' - | 'morph/morph-v3-fast' - | 'morph/morph-v3-large' - | 'nvidia/nemotron-3-nano-30b-a3b' - | 'nvidia/nemotron-nano-12b-v2-vl' - | 'nvidia/nemotron-nano-9b-v2' - | 'openai/gpt-3.5-turbo' - | 'openai/gpt-3.5-turbo-instruct' - | 'openai/gpt-4-turbo' - | 'openai/gpt-4.1' - | 'openai/gpt-4.1-mini' - | 'openai/gpt-4.1-nano' - | 'openai/gpt-4o' - | 'openai/gpt-4o-mini' - | 'openai/gpt-4o-mini-search-preview' - | 'openai/gpt-5' - | 'openai/gpt-5-chat' - | 'openai/gpt-5-codex' - | 'openai/gpt-5-mini' - | 'openai/gpt-5-nano' - | 'openai/gpt-5-pro' - | 'openai/gpt-5.1-codex' - | 'openai/gpt-5.1-codex-max' - | 'openai/gpt-5.1-codex-mini' - | 'openai/gpt-5.1-instant' - | 'openai/gpt-5.1-thinking' - | 'openai/gpt-5.2' - | 'openai/gpt-5.2-chat' - | 'openai/gpt-5.2-codex' - | 'openai/gpt-5.2-pro' - | 'openai/gpt-5.3-chat' - | 'openai/gpt-5.3-codex' - | 'openai/gpt-5.4' - | 'openai/gpt-5.4-mini' - | 'openai/gpt-5.4-nano' - | 'openai/gpt-5.4-pro' - | 'openai/gpt-oss-120b' - | 'openai/gpt-oss-20b' - | 'openai/gpt-oss-safeguard-20b' - | 'openai/o1' - | 'openai/o3' - | 'openai/o3-deep-research' - | 'openai/o3-mini' - | 'openai/o3-pro' - | 'openai/o4-mini' - | 'perplexity/sonar' - | 'perplexity/sonar-pro' - | 'perplexity/sonar-reasoning-pro' - | 'prime-intellect/intellect-3' - | 'xai/grok-2-vision' - | 'xai/grok-3' - | 'xai/grok-3-fast' - | 'xai/grok-3-mini' - | 'xai/grok-3-mini-fast' - | 'xai/grok-4' - | 'xai/grok-4-fast-non-reasoning' - | 'xai/grok-4-fast-reasoning' - | 'xai/grok-4.1-fast-non-reasoning' - | 'xai/grok-4.1-fast-reasoning' - | 'xai/grok-4.20-multi-agent' - | 'xai/grok-4.20-multi-agent-beta' - | 'xai/grok-4.20-non-reasoning' - | 'xai/grok-4.20-non-reasoning-beta' - | 'xai/grok-4.20-reasoning' - | 'xai/grok-4.20-reasoning-beta' - | 'xai/grok-code-fast-1' - | 'xiaomi/mimo-v2-flash' - | 'xiaomi/mimo-v2-pro' - | 'zai/glm-4.5' - | 'zai/glm-4.5-air' - | 'zai/glm-4.5v' - | 'zai/glm-4.6' - | 'zai/glm-4.6v' - | 'zai/glm-4.6v-flash' - | 'zai/glm-4.7' - | 'zai/glm-4.7-flash' - | 'zai/glm-4.7-flashx' - | 'zai/glm-5' - | 'zai/glm-5-turbo' - | (string & {}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-language-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-language-model.ts deleted file mode 100644 index 8bce6153f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-language-model.ts +++ /dev/null @@ -1,212 +0,0 @@ -import type { - LanguageModelV3, - LanguageModelV3CallOptions, - SharedV3Warning, - LanguageModelV3FilePart, - LanguageModelV3StreamPart, - LanguageModelV3GenerateResult, - LanguageModelV3StreamResult, -} from '@ai-sdk/provider'; -import { - combineHeaders, - createEventSourceResponseHandler, - createJsonErrorResponseHandler, - createJsonResponseHandler, - postJsonToApi, - resolve, - type ParseResult, - type Resolvable, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import type { GatewayConfig } from './gateway-config'; -import type { GatewayModelId } from './gateway-language-model-settings'; -import { asGatewayError } from './errors'; -import { parseAuthMethod } from './errors/parse-auth-method'; - -type GatewayChatConfig = GatewayConfig & { - provider: string; - o11yHeaders: Resolvable>; -}; - -export class GatewayLanguageModel implements LanguageModelV3 { - readonly specificationVersion = 'v3'; - readonly supportedUrls = { '*/*': [/.*/] }; - - constructor( - readonly modelId: GatewayModelId, - private readonly config: GatewayChatConfig, - ) {} - - get provider(): string { - return this.config.provider; - } - - private async getArgs(options: LanguageModelV3CallOptions) { - const { abortSignal: _abortSignal, ...optionsWithoutSignal } = options; - - return { - args: this.maybeEncodeFileParts(optionsWithoutSignal), - warnings: [], - }; - } - - async doGenerate( - options: LanguageModelV3CallOptions, - ): Promise { - const { args, warnings } = await this.getArgs(options); - const { abortSignal } = options; - - const resolvedHeaders = await resolve(this.config.headers()); - - try { - const { - responseHeaders, - value: responseBody, - rawValue: rawResponse, - } = await postJsonToApi({ - url: this.getUrl(), - headers: combineHeaders( - resolvedHeaders, - options.headers, - this.getModelConfigHeaders(this.modelId, false), - await resolve(this.config.o11yHeaders), - ), - body: args, - successfulResponseHandler: createJsonResponseHandler(z.any()), - failedResponseHandler: createJsonErrorResponseHandler({ - errorSchema: z.any(), - errorToMessage: data => data, - }), - ...(abortSignal && { abortSignal }), - fetch: this.config.fetch, - }); - - return { - ...responseBody, - request: { body: args }, - response: { headers: responseHeaders, body: rawResponse }, - warnings, - }; - } catch (error) { - throw await asGatewayError(error, await parseAuthMethod(resolvedHeaders)); - } - } - - async doStream( - options: LanguageModelV3CallOptions, - ): Promise { - const { args, warnings } = await this.getArgs(options); - const { abortSignal } = options; - - const resolvedHeaders = await resolve(this.config.headers()); - - try { - const { value: response, responseHeaders } = await postJsonToApi({ - url: this.getUrl(), - headers: combineHeaders( - resolvedHeaders, - options.headers, - this.getModelConfigHeaders(this.modelId, true), - await resolve(this.config.o11yHeaders), - ), - body: args, - successfulResponseHandler: createEventSourceResponseHandler(z.any()), - failedResponseHandler: createJsonErrorResponseHandler({ - errorSchema: z.any(), - errorToMessage: data => data, - }), - ...(abortSignal && { abortSignal }), - fetch: this.config.fetch, - }); - - return { - stream: response.pipeThrough( - new TransformStream< - ParseResult, - LanguageModelV3StreamPart - >({ - start(controller) { - if (warnings.length > 0) { - controller.enqueue({ type: 'stream-start', warnings }); - } - }, - transform(chunk, controller) { - if (chunk.success) { - const streamPart = chunk.value; - - // Handle raw chunks: if this is a raw chunk from the gateway API, - // only emit it if includeRawChunks is true - if (streamPart.type === 'raw' && !options.includeRawChunks) { - return; // Skip raw chunks if not requested - } - - if ( - streamPart.type === 'response-metadata' && - streamPart.timestamp && - typeof streamPart.timestamp === 'string' - ) { - streamPart.timestamp = new Date(streamPart.timestamp); - } - - controller.enqueue(streamPart); - } else { - controller.error( - (chunk as { success: false; error: unknown }).error, - ); - } - }, - }), - ), - request: { body: args }, - response: { headers: responseHeaders }, - }; - } catch (error) { - throw await asGatewayError(error, await parseAuthMethod(resolvedHeaders)); - } - } - - private isFilePart(part: unknown) { - return ( - part && typeof part === 'object' && 'type' in part && part.type === 'file' - ); - } - - /** - * Encodes file parts in the prompt to base64. Mutates the passed options - * instance directly to avoid copying the file data. - * @param options - The options to encode. - * @returns The options with the file parts encoded. - */ - private maybeEncodeFileParts(options: LanguageModelV3CallOptions) { - for (const message of options.prompt) { - for (const part of message.content) { - if (this.isFilePart(part)) { - const filePart = part as LanguageModelV3FilePart; - // If the file part is a URL it will get cleanly converted to a string. - // If it's a binary file attachment we convert it to a data url. - // In either case, server-side we should only ever see URLs as strings. - if (filePart.data instanceof Uint8Array) { - const buffer = Uint8Array.from(filePart.data); - const base64Data = Buffer.from(buffer).toString('base64'); - filePart.data = new URL( - `data:${filePart.mediaType || 'application/octet-stream'};base64,${base64Data}`, - ); - } - } - } - } - return options; - } - - private getUrl() { - return `${this.config.baseURL}/language-model`; - } - - private getModelConfigHeaders(modelId: string, streaming: boolean) { - return { - 'ai-language-model-specification-version': '3', - 'ai-language-model-id': modelId, - 'ai-language-model-streaming': String(streaming), - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-model-entry.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-model-entry.ts deleted file mode 100644 index bd69757cc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-model-entry.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { LanguageModelV3 } from '@ai-sdk/provider'; - -export interface GatewayLanguageModelEntry { - /** - * The model id used by the remote provider in model settings and for specifying the - * intended model for text generation. - */ - id: string; - - /** - * The display name of the model for presentation in user-facing contexts. - */ - name: string; - - /** - * Optional description of the model. - */ - description?: string | null; - - /** - * Optional pricing information for the model. - */ - pricing?: { - /** - * Cost per input token in USD. - */ - input: string; - /** - * Cost per output token in USD. - */ - output: string; - /** - * Cost per cached input token in USD. - * Only present for providers/models that support prompt caching. - */ - cachedInputTokens?: string; - /** - * Cost per input token to create/write cache entries in USD. - * Only present for providers/models that support prompt caching. - */ - cacheCreationInputTokens?: string; - } | null; - - /** - * Additional AI SDK language model specifications for the model. - */ - specification: GatewayLanguageModelSpecification; - - /** - * Optional field to differentiate between model types. - */ - modelType?: 'language' | 'embedding' | 'image' | 'video' | null; -} - -export type GatewayLanguageModelSpecification = Pick< - LanguageModelV3, - 'specificationVersion' | 'provider' | 'modelId' ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-provider-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-provider-options.ts deleted file mode 100644 index 54d653f03..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-provider-options.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -// https://vercel.com/docs/ai-gateway/provider-options -const gatewayLanguageModelOptions = lazySchema(() => - zodSchema( - z.object({ - /** - * Array of provider slugs that are the only ones allowed to be used. - * - * Example: `['azure', 'openai']` will only allow Azure and OpenAI to be used. - */ - only: z.array(z.string()).optional(), - /** - * Array of provider slugs that specifies the sequence in which providers should be attempted. - * - * Example: `['bedrock', 'anthropic']` will try Amazon Bedrock first, then Anthropic as fallback. - */ - order: z.array(z.string()).optional(), - /** - * The unique identifier for the end user on behalf of whom the request was made. - * - * Used for spend tracking and attribution purposes. - */ - user: z.string().optional(), - /** - * User-specified tags for use in reporting and filtering usage. - * - * For example, spend tracking reporting by feature or prompt version. - * - * Example: `['chat', 'v2']` - */ - tags: z.array(z.string()).optional(), - /** - * Array of model slugs specifying fallback models to use in order. - * - * Example: `['openai/gpt-5-nano', 'zai/glm-4.6']` will try `openai/gpt-5-nano` first, then `zai/glm-4.6` as fallback. - */ - models: z.array(z.string()).optional(), - /** - * Request-scoped BYOK credentials to use instead of cached credentials. - * - * When provided, cached BYOK credentials are ignored entirely. - * - * Each provider can have multiple credentials (tried in order). - * - * Examples: - * - Simple: `{ 'anthropic': [{ apiKey: 'sk-ant-...' }] }` - * - Multiple: `{ 'vertex': [{ projectId: 'proj-1', privateKey: '...' }, { projectId: 'proj-2', privateKey: '...' }] }` - * - Multi-provider: `{ 'anthropic': [{ apiKey: '...' }], 'bedrock': [{ accessKeyId: '...', secretAccessKey: '...' }] }` - */ - byok: z - .record(z.string(), z.array(z.record(z.string(), z.unknown()))) - .optional(), - /** - * Whether to filter by only providers that state they have zero data - * retention with Vercel AI Gateway. When enabled, only providers that - * have agreements with Vercel AI Gateway for zero data retention will be - * used. - */ - zeroDataRetention: z.boolean().optional(), - /** - * Per-provider timeouts for BYOK credentials in milliseconds. - * Controls how long to wait for a provider to start responding - * before falling back to the next available provider. - * - * Example: `{ byok: { openai: 5000, anthropic: 2000 } }` - */ - providerTimeouts: z - .object({ - byok: z.record(z.string(), z.number().int().min(1000)).optional(), - }) - .optional(), - }), - ), -); - -export type GatewayLanguageModelOptions = InferSchema< - typeof gatewayLanguageModelOptions ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-provider.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-provider.ts deleted file mode 100644 index 9b2a5f246..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-provider.ts +++ /dev/null @@ -1,329 +0,0 @@ -import { - loadOptionalSetting, - withoutTrailingSlash, - type FetchFunction, -} from '@ai-sdk/provider-utils'; -import { asGatewayError, GatewayAuthenticationError } from './errors'; -import { - GATEWAY_AUTH_METHOD_HEADER, - parseAuthMethod, -} from './errors/parse-auth-method'; -import { - GatewayFetchMetadata, - type GatewayFetchMetadataResponse, - type GatewayCreditsResponse, -} from './gateway-fetch-metadata'; -import { GatewayLanguageModel } from './gateway-language-model'; -import { GatewayEmbeddingModel } from './gateway-embedding-model'; -import { GatewayImageModel } from './gateway-image-model'; -import { GatewayVideoModel } from './gateway-video-model'; -import type { GatewayEmbeddingModelId } from './gateway-embedding-model-settings'; -import type { GatewayImageModelId } from './gateway-image-model-settings'; -import type { GatewayVideoModelId } from './gateway-video-model-settings'; -import { gatewayTools } from './gateway-tools'; -import { getVercelOidcToken, getVercelRequestId } from './vercel-environment'; -import type { GatewayModelId } from './gateway-language-model-settings'; -import type { - LanguageModelV3, - EmbeddingModelV3, - ImageModelV3, - Experimental_VideoModelV3, - ProviderV3, -} from '@ai-sdk/provider'; -import { withUserAgentSuffix } from '@ai-sdk/provider-utils'; -import { VERSION } from './version'; - -export interface GatewayProvider extends ProviderV3 { - (modelId: GatewayModelId): LanguageModelV3; - - /** - * Creates a model for text generation. - */ - chat(modelId: GatewayModelId): LanguageModelV3; - - /** - * Creates a model for text generation. - */ - languageModel(modelId: GatewayModelId): LanguageModelV3; - - /** - * Returns available providers and models for use with the remote provider. - */ - getAvailableModels(): Promise; - - /** - * Returns credit information for the authenticated user. - */ - getCredits(): Promise; - - /** - * Creates a model for generating text embeddings. - */ - embedding(modelId: GatewayEmbeddingModelId): EmbeddingModelV3; - - /** - * Creates a model for generating text embeddings. - */ - embeddingModel(modelId: GatewayEmbeddingModelId): EmbeddingModelV3; - - /** - * @deprecated Use `embeddingModel` instead. - */ - textEmbeddingModel(modelId: GatewayEmbeddingModelId): EmbeddingModelV3; - - /** - * Creates a model for generating images. - */ - image(modelId: GatewayImageModelId): ImageModelV3; - - /** - * Creates a model for generating images. - */ - imageModel(modelId: GatewayImageModelId): ImageModelV3; - - /** - * Creates a model for generating videos. - */ - video(modelId: GatewayVideoModelId): Experimental_VideoModelV3; - - /** - * Creates a model for generating videos. - */ - videoModel(modelId: GatewayVideoModelId): Experimental_VideoModelV3; - - /** - * Gateway-specific tools executed server-side. - */ - tools: typeof gatewayTools; -} - -export interface GatewayProviderSettings { - /** - * The base URL prefix for API calls. Defaults to `https://ai-gateway.vercel.sh/v1/ai`. - */ - baseURL?: string; - - /** - * API key that is being sent using the `Authorization` header. - */ - apiKey?: string; - - /** - * Custom headers to include in the requests. - */ - headers?: Record; - - /** - * Custom fetch implementation. You can use it as a middleware to intercept requests, - * or to provide a custom fetch implementation for e.g. testing. - */ - fetch?: FetchFunction; - - /** - * How frequently to refresh the metadata cache in milliseconds. - */ - metadataCacheRefreshMillis?: number; - - /** - * @internal For testing purposes only - */ - _internal?: { - currentDate?: () => Date; - }; -} - -const AI_GATEWAY_PROTOCOL_VERSION = '0.0.1'; - -/** - * Create a remote provider instance. - */ -export function createGatewayProvider( - options: GatewayProviderSettings = {}, -): GatewayProvider { - let pendingMetadata: Promise | null = null; - let metadataCache: GatewayFetchMetadataResponse | null = null; - const cacheRefreshMillis = - options.metadataCacheRefreshMillis ?? 1000 * 60 * 5; - let lastFetchTime = 0; - - const baseURL = - withoutTrailingSlash(options.baseURL) ?? - 'https://ai-gateway.vercel.sh/v3/ai'; - - const getHeaders = async () => { - try { - const auth = await getGatewayAuthToken(options); - return withUserAgentSuffix( - { - Authorization: `Bearer ${auth.token}`, - 'ai-gateway-protocol-version': AI_GATEWAY_PROTOCOL_VERSION, - [GATEWAY_AUTH_METHOD_HEADER]: auth.authMethod, - ...options.headers, - }, - `ai-sdk/gateway/${VERSION}`, - ); - } catch (error) { - throw GatewayAuthenticationError.createContextualError({ - apiKeyProvided: false, - oidcTokenProvided: false, - statusCode: 401, - cause: error, - }); - } - }; - - const createO11yHeaders = () => { - const deploymentId = loadOptionalSetting({ - settingValue: undefined, - environmentVariableName: 'VERCEL_DEPLOYMENT_ID', - }); - const environment = loadOptionalSetting({ - settingValue: undefined, - environmentVariableName: 'VERCEL_ENV', - }); - const region = loadOptionalSetting({ - settingValue: undefined, - environmentVariableName: 'VERCEL_REGION', - }); - const projectId = loadOptionalSetting({ - settingValue: undefined, - environmentVariableName: 'VERCEL_PROJECT_ID', - }); - - return async () => { - const requestId = await getVercelRequestId(); - return { - ...(deploymentId && { 'ai-o11y-deployment-id': deploymentId }), - ...(environment && { 'ai-o11y-environment': environment }), - ...(region && { 'ai-o11y-region': region }), - ...(requestId && { 'ai-o11y-request-id': requestId }), - ...(projectId && { 'ai-o11y-project-id': projectId }), - }; - }; - }; - - const createLanguageModel = (modelId: GatewayModelId) => { - return new GatewayLanguageModel(modelId, { - provider: 'gateway', - baseURL, - headers: getHeaders, - fetch: options.fetch, - o11yHeaders: createO11yHeaders(), - }); - }; - - const getAvailableModels = async () => { - const now = options._internal?.currentDate?.().getTime() ?? Date.now(); - if (!pendingMetadata || now - lastFetchTime > cacheRefreshMillis) { - lastFetchTime = now; - - pendingMetadata = new GatewayFetchMetadata({ - baseURL, - headers: getHeaders, - fetch: options.fetch, - }) - .getAvailableModels() - .then(metadata => { - metadataCache = metadata; - return metadata; - }) - .catch(async (error: unknown) => { - throw await asGatewayError( - error, - await parseAuthMethod(await getHeaders()), - ); - }); - } - - return metadataCache ? Promise.resolve(metadataCache) : pendingMetadata; - }; - - const getCredits = async () => { - return new GatewayFetchMetadata({ - baseURL, - headers: getHeaders, - fetch: options.fetch, - }) - .getCredits() - .catch(async (error: unknown) => { - throw await asGatewayError( - error, - await parseAuthMethod(await getHeaders()), - ); - }); - }; - - const provider = function (modelId: GatewayModelId) { - if (new.target) { - throw new Error( - 'The Gateway Provider model function cannot be called with the new keyword.', - ); - } - - return createLanguageModel(modelId); - }; - - provider.specificationVersion = 'v3' as const; - provider.getAvailableModels = getAvailableModels; - provider.getCredits = getCredits; - provider.imageModel = (modelId: GatewayImageModelId) => { - return new GatewayImageModel(modelId, { - provider: 'gateway', - baseURL, - headers: getHeaders, - fetch: options.fetch, - o11yHeaders: createO11yHeaders(), - }); - }; - provider.languageModel = createLanguageModel; - const createEmbeddingModel = (modelId: GatewayEmbeddingModelId) => { - return new GatewayEmbeddingModel(modelId, { - provider: 'gateway', - baseURL, - headers: getHeaders, - fetch: options.fetch, - o11yHeaders: createO11yHeaders(), - }); - }; - provider.embeddingModel = createEmbeddingModel; - provider.textEmbeddingModel = createEmbeddingModel; - provider.videoModel = (modelId: GatewayVideoModelId) => { - return new GatewayVideoModel(modelId, { - provider: 'gateway', - baseURL, - headers: getHeaders, - fetch: options.fetch, - o11yHeaders: createO11yHeaders(), - }); - }; - provider.chat = provider.languageModel; - provider.embedding = provider.embeddingModel; - provider.image = provider.imageModel; - provider.video = provider.videoModel; - provider.tools = gatewayTools; - return provider; -} - -export const gateway = createGatewayProvider(); - -export async function getGatewayAuthToken( - options: GatewayProviderSettings, -): Promise<{ token: string; authMethod: 'api-key' | 'oidc' }> { - const apiKey = loadOptionalSetting({ - settingValue: options.apiKey, - environmentVariableName: 'AI_GATEWAY_API_KEY', - }); - - if (apiKey) { - return { - token: apiKey, - authMethod: 'api-key', - }; - } - - const oidcToken = await getVercelOidcToken(); - return { - token: oidcToken, - authMethod: 'oidc', - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-tools.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-tools.ts deleted file mode 100644 index 8d57b71f4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-tools.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { parallelSearch } from './tool/parallel-search'; -import { perplexitySearch } from './tool/perplexity-search'; - -/** - * Gateway-specific provider-defined tools. - */ -export const gatewayTools = { - /** - * Search the web using Parallel AI's Search API for LLM-optimized excerpts. - * - * Takes a natural language objective and returns relevant excerpts, - * replacing multiple keyword searches with a single call for broad - * or complex queries. Supports different search types for depth vs - * breadth tradeoffs. - */ - parallelSearch, - - /** - * Search the web using Perplexity's Search API for real-time information, - * news, research papers, and articles. - * - * Provides ranked search results with advanced filtering options including - * domain, language, date range, and recency filters. - */ - perplexitySearch, -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-video-model-settings.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-video-model-settings.ts deleted file mode 100644 index c14fdd1d5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-video-model-settings.ts +++ /dev/null @@ -1,25 +0,0 @@ -export type GatewayVideoModelId = - | 'alibaba/wan-v2.5-t2v-preview' - | 'alibaba/wan-v2.6-i2v' - | 'alibaba/wan-v2.6-i2v-flash' - | 'alibaba/wan-v2.6-r2v' - | 'alibaba/wan-v2.6-r2v-flash' - | 'alibaba/wan-v2.6-t2v' - | 'bytedance/seedance-v1.0-lite-i2v' - | 'bytedance/seedance-v1.0-lite-t2v' - | 'bytedance/seedance-v1.0-pro' - | 'bytedance/seedance-v1.0-pro-fast' - | 'bytedance/seedance-v1.5-pro' - | 'google/veo-3.0-fast-generate-001' - | 'google/veo-3.0-generate-001' - | 'google/veo-3.1-fast-generate-001' - | 'google/veo-3.1-generate-001' - | 'klingai/kling-v2.5-turbo-i2v' - | 'klingai/kling-v2.5-turbo-t2v' - | 'klingai/kling-v2.6-i2v' - | 'klingai/kling-v2.6-motion-control' - | 'klingai/kling-v2.6-t2v' - | 'klingai/kling-v3.0-i2v' - | 'klingai/kling-v3.0-t2v' - | 'xai/grok-imagine-video' - | (string & {}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-video-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-video-model.ts deleted file mode 100644 index e97162009..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/gateway-video-model.ts +++ /dev/null @@ -1,259 +0,0 @@ -import type { - Experimental_VideoModelV3, - Experimental_VideoModelV3CallOptions, - Experimental_VideoModelV3File, - Experimental_VideoModelV3VideoData, - SharedV3ProviderMetadata, - SharedV3Warning, -} from '@ai-sdk/provider'; -import { APICallError } from '@ai-sdk/provider'; -import { - combineHeaders, - convertUint8ArrayToBase64, - createJsonErrorResponseHandler, - parseJsonEventStream, - postJsonToApi, - resolve, - type Resolvable, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import type { GatewayConfig } from './gateway-config'; -import { asGatewayError } from './errors'; -import { parseAuthMethod } from './errors/parse-auth-method'; - -export class GatewayVideoModel implements Experimental_VideoModelV3 { - readonly specificationVersion = 'v3' as const; - // Set a very large number to prevent client-side splitting of requests - readonly maxVideosPerCall = Number.MAX_SAFE_INTEGER; - - constructor( - readonly modelId: string, - private readonly config: GatewayConfig & { - provider: string; - o11yHeaders: Resolvable>; - }, - ) {} - - get provider(): string { - return this.config.provider; - } - - async doGenerate({ - prompt, - n, - aspectRatio, - resolution, - duration, - fps, - seed, - image, - providerOptions, - headers, - abortSignal, - }: Experimental_VideoModelV3CallOptions): Promise<{ - videos: Array; - warnings: Array; - providerMetadata?: SharedV3ProviderMetadata; - response: { - timestamp: Date; - modelId: string; - headers: Record | undefined; - }; - }> { - const resolvedHeaders = await resolve(this.config.headers()); - try { - const { responseHeaders, value: responseBody } = await postJsonToApi({ - url: this.getUrl(), - headers: combineHeaders( - resolvedHeaders, - headers ?? {}, - this.getModelConfigHeaders(), - await resolve(this.config.o11yHeaders), - { accept: 'text/event-stream' }, - ), - body: { - prompt, - n, - ...(aspectRatio && { aspectRatio }), - ...(resolution && { resolution }), - ...(duration && { duration }), - ...(fps && { fps }), - ...(seed && { seed }), - ...(providerOptions && { providerOptions }), - ...(image && { image: maybeEncodeVideoFile(image) }), - }, - successfulResponseHandler: async ({ - response, - url, - requestBodyValues, - }: { - url: string; - requestBodyValues: unknown; - response: Response; - }) => { - if (response.body == null) { - throw new APICallError({ - message: 'SSE response body is empty', - url, - requestBodyValues, - statusCode: response.status, - }); - } - - const eventStream = parseJsonEventStream({ - stream: response.body, - schema: gatewayVideoEventSchema, - }); - - const reader = eventStream.getReader(); - const { done, value: parseResult } = await reader.read(); - reader.releaseLock(); - - if (done || !parseResult) { - throw new APICallError({ - message: 'SSE stream ended without a data event', - url, - requestBodyValues, - statusCode: response.status, - }); - } - - if (!parseResult.success) { - throw new APICallError({ - message: 'Failed to parse video SSE event', - cause: parseResult.error, - url, - requestBodyValues, - statusCode: response.status, - }); - } - - const event = parseResult.value; - - if (event.type === 'error') { - throw new APICallError({ - message: event.message, - statusCode: event.statusCode, - url, - requestBodyValues, - responseHeaders: Object.fromEntries([...response.headers]), - responseBody: JSON.stringify(event), - data: { - error: { - message: event.message, - type: event.errorType, - param: event.param, - }, - }, - }); - } - - // event.type === 'result' - return { - value: { - videos: event.videos, - warnings: event.warnings, - providerMetadata: event.providerMetadata, - }, - responseHeaders: Object.fromEntries([...response.headers]), - }; - }, - failedResponseHandler: createJsonErrorResponseHandler({ - errorSchema: z.any(), - errorToMessage: data => data, - }), - ...(abortSignal && { abortSignal }), - fetch: this.config.fetch, - }); - - return { - videos: responseBody.videos, - warnings: responseBody.warnings ?? [], - providerMetadata: - responseBody.providerMetadata as SharedV3ProviderMetadata, - response: { - timestamp: new Date(), - modelId: this.modelId, - headers: responseHeaders, - }, - }; - } catch (error) { - throw await asGatewayError(error, await parseAuthMethod(resolvedHeaders)); - } - } - - private getUrl() { - return `${this.config.baseURL}/video-model`; - } - - private getModelConfigHeaders() { - return { - 'ai-video-model-specification-version': '3', - 'ai-model-id': this.modelId, - }; - } -} - -function maybeEncodeVideoFile(file: Experimental_VideoModelV3File) { - if (file.type === 'file' && file.data instanceof Uint8Array) { - return { - ...file, - data: convertUint8ArrayToBase64(file.data), - }; - } - return file; -} - -const providerMetadataEntrySchema = z - .object({ - videos: z.array(z.unknown()).optional(), - }) - .catchall(z.unknown()); - -const gatewayVideoDataSchema = z.union([ - z.object({ - type: z.literal('url'), - url: z.string(), - mediaType: z.string(), - }), - z.object({ - type: z.literal('base64'), - data: z.string(), - mediaType: z.string(), - }), -]); - -const gatewayVideoWarningSchema = z.discriminatedUnion('type', [ - z.object({ - type: z.literal('unsupported'), - feature: z.string(), - details: z.string().optional(), - }), - z.object({ - type: z.literal('compatibility'), - feature: z.string(), - details: z.string().optional(), - }), - z.object({ - type: z.literal('other'), - message: z.string(), - }), -]); - -const gatewayVideoEventSchema = z.discriminatedUnion('type', [ - z.object({ - type: z.literal('result'), - videos: z.array(gatewayVideoDataSchema), - warnings: z.array(gatewayVideoWarningSchema).optional(), - providerMetadata: z - .record(z.string(), providerMetadataEntrySchema) - .optional(), - }), - z.object({ - type: z.literal('error'), - message: z.string(), - errorType: z.string(), - statusCode: z.number(), - param: z.unknown().nullable(), - }), -]); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/index.ts deleted file mode 100644 index 61acc34ac..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -export type { GatewayModelId } from './gateway-language-model-settings'; -export type { GatewayVideoModelId } from './gateway-video-model-settings'; -export type { - GatewayLanguageModelEntry, - GatewayLanguageModelSpecification, -} from './gateway-model-entry'; -export type { GatewayCreditsResponse } from './gateway-fetch-metadata'; -export type { GatewayLanguageModelEntry as GatewayModelEntry } from './gateway-model-entry'; -export { - createGatewayProvider, - createGatewayProvider as createGateway, - gateway, -} from './gateway-provider'; -export type { - GatewayProvider, - GatewayProviderSettings, -} from './gateway-provider'; -export type { - GatewayLanguageModelOptions, - /** @deprecated Use `GatewayLanguageModelOptions` instead. */ - GatewayLanguageModelOptions as GatewayProviderOptions, -} from './gateway-provider-options'; -export { - GatewayError, - GatewayAuthenticationError, - GatewayInvalidRequestError, - GatewayRateLimitError, - GatewayModelNotFoundError, - GatewayInternalServerError, - GatewayResponseError, -} from './errors'; -export type { GatewayErrorResponse } from './errors'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/tool/parallel-search.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/tool/parallel-search.ts deleted file mode 100644 index e8f81a772..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/tool/parallel-search.ts +++ /dev/null @@ -1,295 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod'; - -export interface ParallelSearchSourcePolicy { - /** - * List of domains to include in search results. - * Example: ['wikipedia.org', 'nature.com'] - */ - includeDomains?: string[]; - - /** - * List of domains to exclude from search results. - * Example: ['reddit.com', 'twitter.com'] - */ - excludeDomains?: string[]; - - /** - * Only include results published after this date (ISO 8601 format). - * Example: '2024-01-01' - */ - afterDate?: string; -} - -export interface ParallelSearchExcerpts { - /** - * Maximum characters per result. - */ - maxCharsPerResult?: number; - - /** - * Maximum total characters across all results. - */ - maxCharsTotal?: number; -} - -export interface ParallelSearchFetchPolicy { - /** - * Maximum age in seconds for cached content. - * Set to 0 to always fetch fresh content. - */ - maxAgeSeconds?: number; -} - -export interface ParallelSearchConfig { - /** - * Mode preset for different use cases: - * - "one-shot": Comprehensive results with longer excerpts for single-response answers (default) - * - "agentic": Concise, token-efficient results for multi-step agentic workflows - */ - mode?: 'one-shot' | 'agentic'; - - /** - * Default maximum number of results to return (1-20). - * Defaults to 10 if not specified. - */ - maxResults?: number; - - /** - * Default source policy for controlling which domains to include/exclude. - */ - sourcePolicy?: ParallelSearchSourcePolicy; - - /** - * Default excerpt configuration for controlling result length. - */ - excerpts?: ParallelSearchExcerpts; - - /** - * Default fetch policy for controlling content freshness. - */ - fetchPolicy?: ParallelSearchFetchPolicy; -} - -export interface ParallelSearchResult { - /** URL of the search result */ - url: string; - /** Title of the search result */ - title: string; - /** Extracted text excerpt/content from the page */ - excerpt: string; - /** Publication date of the content (may be null) */ - publishDate?: string | null; - /** Relevance score for the result */ - relevanceScore?: number; -} - -export interface ParallelSearchResponse { - /** Unique identifier for this search request */ - searchId: string; - /** Array of search results */ - results: ParallelSearchResult[]; -} - -export interface ParallelSearchError { - /** Error type */ - error: - | 'api_error' - | 'rate_limit' - | 'timeout' - | 'invalid_input' - | 'configuration_error' - | 'unknown'; - /** HTTP status code if applicable */ - statusCode?: number; - /** Human-readable error message */ - message: string; -} - -export interface ParallelSearchInput { - /** - * Natural-language description of the web research goal. - * Include source or freshness guidance and broader context from the task. - * Maximum 5000 characters. - */ - objective: string; - - /** - * Optional search queries to supplement the objective. - * Maximum 200 characters per query. - */ - search_queries?: string[]; - - /** - * Mode preset for different use cases: - * - "one-shot": Comprehensive results with longer excerpts - * - "agentic": Concise, token-efficient results for multi-step workflows - */ - mode?: 'one-shot' | 'agentic'; - - /** - * Maximum number of results to return (1-20). - * Defaults to 10 if not specified. - */ - max_results?: number; - - /** - * Source policy for controlling which domains to include/exclude. - */ - source_policy?: { - include_domains?: string[]; - exclude_domains?: string[]; - after_date?: string; - }; - - /** - * Excerpt configuration for controlling result length. - */ - excerpts?: { - max_chars_per_result?: number; - max_chars_total?: number; - }; - - /** - * Fetch policy for controlling content freshness. - */ - fetch_policy?: { - max_age_seconds?: number; - }; -} - -export type ParallelSearchOutput = ParallelSearchResponse | ParallelSearchError; - -const parallelSearchInputSchema = lazySchema(() => - zodSchema( - z.object({ - objective: z - .string() - .describe( - 'Natural-language description of the web research goal, including source or freshness guidance and broader context from the task. Maximum 5000 characters.', - ), - - search_queries: z - .array(z.string()) - .optional() - .describe( - 'Optional search queries to supplement the objective. Maximum 200 characters per query.', - ), - - mode: z - .enum(['one-shot', 'agentic']) - .optional() - .describe( - 'Mode preset: "one-shot" for comprehensive results with longer excerpts (default), "agentic" for concise, token-efficient results for multi-step workflows.', - ), - - max_results: z - .number() - .optional() - .describe( - 'Maximum number of results to return (1-20). Defaults to 10 if not specified.', - ), - - source_policy: z - .object({ - include_domains: z - .array(z.string()) - .optional() - .describe('List of domains to include in search results.'), - exclude_domains: z - .array(z.string()) - .optional() - .describe('List of domains to exclude from search results.'), - after_date: z - .string() - .optional() - .describe( - 'Only include results published after this date (ISO 8601 format).', - ), - }) - .optional() - .describe( - 'Source policy for controlling which domains to include/exclude and freshness.', - ), - - excerpts: z - .object({ - max_chars_per_result: z - .number() - .optional() - .describe('Maximum characters per result.'), - max_chars_total: z - .number() - .optional() - .describe('Maximum total characters across all results.'), - }) - .optional() - .describe('Excerpt configuration for controlling result length.'), - - fetch_policy: z - .object({ - max_age_seconds: z - .number() - .optional() - .describe( - 'Maximum age in seconds for cached content. Set to 0 to always fetch fresh content.', - ), - }) - .optional() - .describe('Fetch policy for controlling content freshness.'), - }), - ), -); - -const parallelSearchOutputSchema = lazySchema(() => - zodSchema( - z.union([ - // Success response - z.object({ - searchId: z.string(), - results: z.array( - z.object({ - url: z.string(), - title: z.string(), - excerpt: z.string(), - publishDate: z.string().nullable().optional(), - relevanceScore: z.number().optional(), - }), - ), - }), - // Error response - z.object({ - error: z.enum([ - 'api_error', - 'rate_limit', - 'timeout', - 'invalid_input', - 'configuration_error', - 'unknown', - ]), - statusCode: z.number().optional(), - message: z.string(), - }), - ]), - ), -); - -export const parallelSearchToolFactory = - createProviderToolFactoryWithOutputSchema< - ParallelSearchInput, - ParallelSearchOutput, - ParallelSearchConfig - >({ - id: 'gateway.parallel_search', - inputSchema: parallelSearchInputSchema, - outputSchema: parallelSearchOutputSchema, - }); - -export const parallelSearch = ( - config: ParallelSearchConfig = {}, -): ReturnType => - parallelSearchToolFactory(config); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/tool/perplexity-search.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/tool/perplexity-search.ts deleted file mode 100644 index e315e4255..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/tool/perplexity-search.ts +++ /dev/null @@ -1,294 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod'; - -export interface PerplexitySearchConfig { - /** - * Default maximum number of search results to return (1-20, default: 10). - */ - maxResults?: number; - - /** - * Default maximum tokens to extract per search result page (256-2048, default: 2048). - */ - maxTokensPerPage?: number; - - /** - * Default maximum total tokens across all search results (default: 25000, max: 1000000). - */ - maxTokens?: number; - - /** - * Default two-letter ISO 3166-1 alpha-2 country code for regional search results. - * Examples: 'US', 'GB', 'FR' - */ - country?: string; - - /** - * Default list of domains to include or exclude from search results (max 20). - * To include: ['nature.com', 'science.org'] - * To exclude: ['-example.com', '-spam.net'] - */ - searchDomainFilter?: string[]; - - /** - * Default list of ISO 639-1 language codes to filter results (max 10, lowercase). - * Examples: ['en', 'fr', 'de'] - */ - searchLanguageFilter?: string[]; - - /** - * Default recency filter for results. - * Cannot be combined with searchAfterDate/searchBeforeDate at runtime. - */ - searchRecencyFilter?: 'day' | 'week' | 'month' | 'year'; -} - -export interface PerplexitySearchResult { - /** Title of the search result */ - title: string; - /** URL of the search result */ - url: string; - /** Text snippet/preview of the content */ - snippet: string; - /** Publication date of the content */ - date?: string; - /** Last updated date of the content */ - lastUpdated?: string; -} - -export interface PerplexitySearchResponse { - /** Array of search results */ - results: PerplexitySearchResult[]; - /** Unique identifier for this search request */ - id: string; -} - -export interface PerplexitySearchError { - /** Error type */ - error: 'api_error' | 'rate_limit' | 'timeout' | 'invalid_input' | 'unknown'; - /** HTTP status code if applicable */ - statusCode?: number; - /** Human-readable error message */ - message: string; -} - -export interface PerplexitySearchInput { - /** - * Search query (string) or multiple queries (array of up to 5 strings). - * Multi-query searches return combined results from all queries. - */ - query: string | string[]; - - /** - * Maximum number of search results to return (1-20, default: 10). - */ - max_results?: number; - - /** - * Maximum number of tokens to extract per search result page (256-2048, default: 2048). - */ - max_tokens_per_page?: number; - - /** - * Maximum total tokens across all search results (default: 25000, max: 1000000). - */ - max_tokens?: number; - - /** - * Two-letter ISO 3166-1 alpha-2 country code for regional search results. - * Examples: 'US', 'GB', 'FR' - */ - country?: string; - - /** - * List of domains to include or exclude from search results (max 20). - * To include: ['nature.com', 'science.org'] - * To exclude: ['-example.com', '-spam.net'] - */ - search_domain_filter?: string[]; - - /** - * List of ISO 639-1 language codes to filter results (max 10, lowercase). - * Examples: ['en', 'fr', 'de'] - */ - search_language_filter?: string[]; - - /** - * Include only results published after this date. - * Format: 'MM/DD/YYYY' (e.g., '3/1/2025') - * Cannot be used with search_recency_filter. - */ - search_after_date?: string; - - /** - * Include only results published before this date. - * Format: 'MM/DD/YYYY' (e.g., '3/15/2025') - * Cannot be used with search_recency_filter. - */ - search_before_date?: string; - - /** - * Include only results last updated after this date. - * Format: 'MM/DD/YYYY' (e.g., '3/1/2025') - * Cannot be used with search_recency_filter. - */ - last_updated_after_filter?: string; - - /** - * Include only results last updated before this date. - * Format: 'MM/DD/YYYY' (e.g., '3/15/2025') - * Cannot be used with search_recency_filter. - */ - last_updated_before_filter?: string; - - /** - * Filter results by relative time period. - * Cannot be used with search_after_date or search_before_date. - */ - search_recency_filter?: 'day' | 'week' | 'month' | 'year'; -} - -export type PerplexitySearchOutput = - | PerplexitySearchResponse - | PerplexitySearchError; - -const perplexitySearchInputSchema = lazySchema(() => - zodSchema( - z.object({ - query: z - .union([z.string(), z.array(z.string())]) - .describe( - 'Search query (string) or multiple queries (array of up to 5 strings). Multi-query searches return combined results from all queries.', - ), - - max_results: z - .number() - .optional() - .describe( - 'Maximum number of search results to return (1-20, default: 10)', - ), - - max_tokens_per_page: z - .number() - .optional() - .describe( - 'Maximum number of tokens to extract per search result page (256-2048, default: 2048)', - ), - - max_tokens: z - .number() - .optional() - .describe( - 'Maximum total tokens across all search results (default: 25000, max: 1000000)', - ), - - country: z - .string() - .optional() - .describe( - "Two-letter ISO 3166-1 alpha-2 country code for regional search results (e.g., 'US', 'GB', 'FR')", - ), - - search_domain_filter: z - .array(z.string()) - .optional() - .describe( - "List of domains to include or exclude from search results (max 20). To include: ['nature.com', 'science.org']. To exclude: ['-example.com', '-spam.net']", - ), - - search_language_filter: z - .array(z.string()) - .optional() - .describe( - "List of ISO 639-1 language codes to filter results (max 10, lowercase). Examples: ['en', 'fr', 'de']", - ), - - search_after_date: z - .string() - .optional() - .describe( - "Include only results published after this date. Format: 'MM/DD/YYYY' (e.g., '3/1/2025'). Cannot be used with search_recency_filter.", - ), - - search_before_date: z - .string() - .optional() - .describe( - "Include only results published before this date. Format: 'MM/DD/YYYY' (e.g., '3/15/2025'). Cannot be used with search_recency_filter.", - ), - - last_updated_after_filter: z - .string() - .optional() - .describe( - "Include only results last updated after this date. Format: 'MM/DD/YYYY' (e.g., '3/1/2025'). Cannot be used with search_recency_filter.", - ), - - last_updated_before_filter: z - .string() - .optional() - .describe( - "Include only results last updated before this date. Format: 'MM/DD/YYYY' (e.g., '3/15/2025'). Cannot be used with search_recency_filter.", - ), - - search_recency_filter: z - .enum(['day', 'week', 'month', 'year']) - .optional() - .describe( - 'Filter results by relative time period. Cannot be used with search_after_date or search_before_date.', - ), - }), - ), -); - -const perplexitySearchOutputSchema = lazySchema(() => - zodSchema( - z.union([ - // Success response - z.object({ - results: z.array( - z.object({ - title: z.string(), - url: z.string(), - snippet: z.string(), - date: z.string().optional(), - lastUpdated: z.string().optional(), - }), - ), - id: z.string(), - }), - // Error response - z.object({ - error: z.enum([ - 'api_error', - 'rate_limit', - 'timeout', - 'invalid_input', - 'unknown', - ]), - statusCode: z.number().optional(), - message: z.string(), - }), - ]), - ), -); - -export const perplexitySearchToolFactory = - createProviderToolFactoryWithOutputSchema< - PerplexitySearchInput, - PerplexitySearchOutput, - PerplexitySearchConfig - >({ - id: 'gateway.perplexity_search', - inputSchema: perplexitySearchInputSchema, - outputSchema: perplexitySearchOutputSchema, - }); - -export const perplexitySearch = ( - config: PerplexitySearchConfig = {}, -): ReturnType => - perplexitySearchToolFactory(config); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/vercel-environment.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/vercel-environment.ts deleted file mode 100644 index 3ed597eb9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/vercel-environment.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { getContext } from '@vercel/oidc'; -export { getVercelOidcToken } from '@vercel/oidc'; - -export async function getVercelRequestId(): Promise { - return getContext().headers?.['x-vercel-id']; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/version.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/version.ts deleted file mode 100644 index 7a35d46f5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/gateway/src/version.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Version string of this package injected at build time. -declare const __PACKAGE_VERSION__: string | undefined; -export const VERSION: string = - typeof __PACKAGE_VERSION__ !== 'undefined' - ? __PACKAGE_VERSION__ - : '0.0.0-test'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/CHANGELOG.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/CHANGELOG.md deleted file mode 100644 index f76b3a5bd..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/CHANGELOG.md +++ /dev/null @@ -1,3149 +0,0 @@ -# @ai-sdk/openai - -## 3.0.48 - -### Patch Changes - -- 9c548de: Add `gpt-5.4-mini`, `gpt-5.4-mini-2026-03-17`, `gpt-5.4-nano`, and `gpt-5.4-nano-2026-03-17` models. -- bcb04df: fix(openai): preserve raw finish reason for failed responses stream events - - Handle `response.failed` chunks in Responses API streaming so `finishReason.raw` is preserved from `incomplete_details.reason` (e.g. `max_output_tokens`), and map failed-without-reason cases to unified `error` instead of `other`. - -## 3.0.47 - -### Patch Changes - -- 055cd68: fix: publish v6 to latest npm dist tag -- Updated dependencies [055cd68] - - @ai-sdk/provider-utils@4.0.21 - -## 3.0.46 - -### Patch Changes - -- 75fc0e7: feat(openai): add new tool search tool - -## 3.0.45 - -### Patch Changes - -- 023088c: feat(provider/openai): add `gpt-5.3-chat-latest` - -## 3.0.44 - -### Patch Changes - -- f4a734a: fix(provider/openai): drop reasoning parts without encrypted content when store: false - -## 3.0.43 - -### Patch Changes - -- Updated dependencies [64ac0fd] - - @ai-sdk/provider-utils@4.0.20 - -## 3.0.42 - -### Patch Changes - -- 2589004: feat(provider/openai): add GPT-5.4 model support - -## 3.0.41 - -### Patch Changes - -- Updated dependencies [ad4cfc2] - - @ai-sdk/provider-utils@4.0.19 - -## 3.0.40 - -### Patch Changes - -- Updated dependencies [824b295] - - @ai-sdk/provider-utils@4.0.18 - -## 3.0.39 - -### Patch Changes - -- Updated dependencies [08336f1] - - @ai-sdk/provider-utils@4.0.17 - -## 3.0.38 - -### Patch Changes - -- 64a8fae: chore: remove obsolete model IDs for Anthropic, Google, OpenAI, xAI - -## 3.0.37 - -### Patch Changes - -- 58bc42d: feat(provider/openai): support custom tools with alias mapping -- Updated dependencies [58bc42d] - - @ai-sdk/provider-utils@4.0.16 - -## 3.0.36 - -### Patch Changes - -- 53bdfa5: fix(openai): allow null/undefined type in streaming tool call deltas - - Azure AI Foundry and Mistral deployed on Azure omit the `type` field in - streaming tool_calls deltas. The chat stream parser now accepts a missing - `type` field (treating it as `"function"`) instead of throwing - `InvalidResponseDataError: Expected 'function' type.` - - Fixes #12770 - -## 3.0.35 - -### Patch Changes - -- 5e18272: fix(openai): include reasoning parts without itemId when encrypted_content is present - - When `providerOptions.openai.itemId` is absent on a reasoning content part, - the converter now uses `encrypted_content` as a fallback instead of silently - skipping the part with a warning. The OpenAI Responses API accepts reasoning - items without an `id` when `encrypted_content` is supplied, enabling - multi-turn reasoning even when item IDs are stripped from provider options. - - Also makes the `id` field optional on the `OpenAIResponsesReasoning` type to - reflect that the API does not require it. - - Fixes #12853 - -## 3.0.34 - -### Patch Changes - -- 66a374c: Support `phase` parameter on Responses API message items. The `phase` field (`'commentary'` or `'final_answer'`) is returned by models like `gpt-5.3-codex` on assistant message output items and must be preserved when sending follow-up requests. The phase value is available in `providerMetadata.openai.phase` on text parts and is automatically included on assistant messages sent back to the API. - -## 3.0.33 - -### Patch Changes - -- 624e651: Added missing model IDs to OpenAIChatModelId, OpenAIResponsesModelId, OpenAIImageModelId, OpenAISpeechModelId, OpenAITranscriptionModelId, and OpenAICompletionModelId types for better autocomplete support. - -## 3.0.32 - -### Patch Changes - -- 0c9395b: feat(provider/openai): add `gpt-5.3-codex` - -## 3.0.31 - -### Patch Changes - -- d5f7312: fix(openai): change web search tool action to be optional - -## 3.0.30 - -### Patch Changes - -- ff12133: feat(provider/openai): support native skills and hosted shell - -## 3.0.29 - -### Patch Changes - -- e2ee705: feat: differentiate text vs image input tokens - -## 3.0.28 - -### Patch Changes - -- Updated dependencies [4024a3a] - - @ai-sdk/provider-utils@4.0.15 - -## 3.0.27 - -### Patch Changes - -- 99fbed8: feat: normalize provider specific model options type names and ensure they are exported - -## 3.0.26 - -### Patch Changes - -- Updated dependencies [7168375] - - @ai-sdk/provider@3.0.8 - - @ai-sdk/provider-utils@4.0.14 - -## 3.0.25 - -### Patch Changes - -- Updated dependencies [53f6731] - - @ai-sdk/provider@3.0.7 - - @ai-sdk/provider-utils@4.0.13 - -## 3.0.24 - -### Patch Changes - -- Updated dependencies [96936e5] - - @ai-sdk/provider-utils@4.0.12 - -## 3.0.23 - -### Patch Changes - -- Updated dependencies [2810850] - - @ai-sdk/provider-utils@4.0.11 - - @ai-sdk/provider@3.0.6 - -## 3.0.22 - -### Patch Changes - -- 1524271: chore: add skill information to README files - -## 3.0.21 - -### Patch Changes - -- 2c70b90: chore: update provider docs - -## 3.0.20 - -### Patch Changes - -- Updated dependencies [462ad00] - - @ai-sdk/provider-utils@4.0.10 - -## 3.0.19 - -### Patch Changes - -- 04c89b1: Provide Responses API providerMetadata types at the message / reasoning level. - - - Export the following types for use in client code: - - `OpenaiResponsesProviderMetadata` - - `OpenaiResponsesReasoningProviderMetadata` - - `AzureResponsesProviderMetadata` - - `AzureResponsesReasoningProviderMetadata` - -## 3.0.18 - -### Patch Changes - -- 4de5a1d: chore: excluded tests from src folder in npm package -- Updated dependencies [4de5a1d] - - @ai-sdk/provider@3.0.5 - - @ai-sdk/provider-utils@4.0.9 - -## 3.0.17 - -### Patch Changes - -- 4218f86: fix(openai): preserve tool id for apply patch tool - -## 3.0.16 - -### Patch Changes - -- 2b8369d: chore: add docs to package dist - -## 3.0.15 - -### Patch Changes - -- 8dc54db: chore: add src folders to package bundle - -## 3.0.14 - -### Patch Changes - -- d21d016: feat(openai): add o4-mini model to OpenAIChatModelId type - -## 3.0.13 - -### Patch Changes - -- 000fa96: fix(openai): filter duplicate items when passing conversationID - -## 3.0.12 - -### Patch Changes - -- Updated dependencies [5c090e7] - - @ai-sdk/provider@3.0.4 - - @ai-sdk/provider-utils@4.0.8 - -## 3.0.11 - -### Patch Changes - -- Updated dependencies [46f46e4] - - @ai-sdk/provider-utils@4.0.7 - -## 3.0.10 - -### Patch Changes - -- Updated dependencies [1b11dcb] - - @ai-sdk/provider-utils@4.0.6 - - @ai-sdk/provider@3.0.3 - -## 3.0.9 - -### Patch Changes - -- Updated dependencies [34d1c8a] - - @ai-sdk/provider-utils@4.0.5 - -## 3.0.8 - -### Patch Changes - -- 330bd92: Fix Responses `code_interpreter` annotations and add typed providerMetadata - - - Align Responses API `code_interpreter` annotation types with the official spec. - - Add tests to ensure the overlapping parts of the Zod schemas used by `doGenerate` and `doStream` stay in sync. - - Export the following types for use in client code: - - `OpenaiResponsesTextProviderMetadata` - - `OpenaiResponsesSourceDocumentProviderMetadata` - - `AzureResponsesTextProviderMetadata` - - `AzureResponsesSourceDocumentProviderMetadata` - -## 3.0.7 - -### Patch Changes - -- 89202fb: fix(openai/azure): passing response_format correctly - -## 3.0.6 - -### Patch Changes - -- dc87517: Fix handling of `image-url` tool result content type in OpenAI Responses API conversion - -## 3.0.5 - -### Patch Changes - -- Updated dependencies [d937c8f] - - @ai-sdk/provider@3.0.2 - - @ai-sdk/provider-utils@4.0.4 - -## 3.0.4 - -### Patch Changes - -- Updated dependencies [0b429d4] - - @ai-sdk/provider-utils@4.0.3 - -## 3.0.3 - -### Patch Changes - -- 55cd1a4: fix(azure): allow 'azure' as a key for providerOptions - -## 3.0.2 - -### Patch Changes - -- 863d34f: fix: trigger release to update `@latest` -- Updated dependencies [863d34f] - - @ai-sdk/provider@3.0.1 - - @ai-sdk/provider-utils@4.0.2 - -## 3.0.1 - -### Patch Changes - -- 29264a3: feat: add MCP tool approval -- Updated dependencies [29264a3] - - @ai-sdk/provider-utils@4.0.1 - -## 3.0.0 - -### Major Changes - -- dee8b05: ai SDK 6 beta - -### Minor Changes - -- 78928cb: release: start 5.1 beta - -### Patch Changes - -- 0c3b58b: fix(provider): add specificationVersion to ProviderV3 -- 4920119: fix the "incomplete_details" key from nullable to nullish for openai compatibility -- 0adc679: feat(provider): shared spec v3 -- 92c6241: feat(openai): additional settings for file search tool -- 88fc415: feat(openai): add the new provider 'apply_patch' tool -- 817e601: fix(openai); fix url_citation schema in chat api -- dae2185: fix(openai): extract meta data from first chunk that contains any -- 046aa3b: feat(provider): speech model v3 spec -- f1277fe: feat(provider/openai): send assistant text and tool call parts as reference ids when store: true -- 8d9e8ad: chore(provider): remove generics from EmbeddingModelV3 - - Before - - ```ts - model.textEmbeddingModel("my-model-id"); - ``` - - After - - ```ts - model.embeddingModel("my-model-id"); - ``` - -- 60f4775: fix: remove code for unsuported o1-mini and o1-preview models -- 9a51b92: support OPENAI_BASE_URL env -- d64ece9: enables image_generation capabilities in the Azure provider through the Responses API. -- 2625a04: feat(openai); update spec for mcp approval -- 2e86082: feat(provider/openai): `OpenAIChatLanguageModelOptions` type - - ```ts - import { openai, type OpenAIChatLanguageModelOptions } from "@ai-sdk/openai"; - import { generateText } from "ai"; - - await generateText({ - model: openai.chat("gpt-4o"), - prompt: "Invent a new holiday and describe its traditions.", - providerOptions: { - openai: { - user: "user-123", - } satisfies OpenAIChatLanguageModelOptions, - }, - }); - ``` - -- 0877683: feat(provider/openai): support conversations api -- d0f1baf: feat(openai): Add support for 'promptCacheRetention: 24h' for gpt5.1 series -- 831b6cc: feat(openai): adding provider mcp tool for openai -- 95f65c2: chore: use import \* from zod/v4 -- edc5548: feat(provider/openai): automatically add reasoning.encrypted_content include when store = false -- 954c356: feat(openai): allow custom names for provider-defined tools -- 544d4e8: chore(specification): rename v3 provider defined tool to provider tool -- 77f2b20: enables code_interpreter and file_search capabilities in the Azure provider through the Responses API -- 0c4822d: feat: `EmbeddingModelV3` -- 73d9883: chore(openai): enable strict json by default -- d2039d7: feat(provider/openai): add GPT 5.1 Codex Max to OpenAI Responses model IDs list -- 88edc28: feat (provider/openai): include more image generation response metadata -- e8109d3: feat: tool execution approval -- ed329cb: feat: `Provider-V3` -- 3bd2689: feat: extended token usage -- 1cad0ab: feat: add provider version to user-agent header -- e85fa2f: feat(openai): add sources in web-search actions -- 423ba08: Set the annotations from the Responses API to doStream -- 401f561: fix(provider/openai): fix web search tool input types -- 4122d2a: feat(provider/openai): add gpt-5-codex model id -- 0153bfa: fix(openai): fix parameter exclusion logic -- 8dac895: feat: `LanguageModelV3` -- 304222e: Add streaming support for apply_patch partial diffs. -- 23f132b: fix: error schema for Responses API -- 1d0de66: refactoring(provider/openai): simplify code -- 000e87b: fix(provider/openai): add providerExecuted flag to tool start chunks -- 2c0a758: chore(openai): add JSDoc to responses options -- 1b982e6: feat(openai): preserve file_id when converting file citations -- b82987c: feat(openai): support openai code-interpreter annotations -- 457318b: chore(provider,ai): switch to SharedV3Warning and unified warnings -- b681d7d: feat: expose usage tokens for 'generateImage' function -- 79b4e46: feat(openai): add 'gpt-5.1' modelID -- 3997a42: feat(provider/openai): local shell tool -- 348fd10: fix(openai): treat unknown models as reasoning -- 9061dc0: feat: image editing -- fe49278: feat(provider/openai): only send item references for reasoning when store: true -- cb4d238: The built in Code Interpreter tool input code is streamed in `tool-input-` chunks. -- 357cfd7: feat(provider/openai): add new model IDs `gpt-image-1-mini`, `gpt-5-pro`, `gpt-5-pro-2025-10-06` -- 38a4035: added support for external_web_access parameter on web_search tool -- 40d5419: feat(openai): add `o3-deep-research` and `o4-mini-deep-research` models -- 366f50b: chore(provider): add deprecated textEmbeddingModel and textEmbedding aliases -- 2b0caef: feat(provider/openai): preview image generation results -- b60d2e2: fix(openai): allow open_page action type url to be nullish -- fd47df5: fix(openai): revised_prompt sometimes returns null, causing errors -- 4616b86: chore: update zod peer depenedency version -- 7756857: fix(provider/openai): add truncation parameter support for Responses API -- cad6445: feat(openai); adding OpenAI's new shell tool -- 64aa48f: Azure OpenAI enabled web-search-preview -- 0b9fdd5: fix(provider/openai): end reasoning parts earlier -- 61c52dc: feat (provider/openai): add gpt-image-1.5 model support -- ef739fa: fix(openai): refactor apply-patch tool -- 3220329: fix openai responses input: process all provider tool outputs (shell/apply_patch) so parallel tool results aren’t dropped and apply_patch outputs are forwarded. -- d270a5d: chore(openai): update tests for apply-patch tool to use snapshots -- f18ef7f: feat(openai): add gpt-5.2 models -- 21e20c0: feat(provider): transcription model v3 spec -- 522f6b8: feat: `ImageModelV3` -- 484aa93: Add 'default' as service tier -- 88574c1: Change `isReasoningModel` detection from blocklist to allowlist and add override option -- 68c6187: feat(provider/openai): support file and image tool results -- 3794514: feat: flexible tool output content support -- cbf52cd: feat: expose raw finish reason -- 10c1322: fix: moved dependency `@ai-sdk/test-server` to devDependencies -- 5648ec0: Add GPT-5.2 support for non-reasoning parameters (temperature, topP, logProbs) when reasoningEffort is none. -- 78f813e: fix(openai): allow temperature etc setting when reasoning effort is none for gpt-5.1 -- 40dc7fa: fix(openai): change find action type to find_in_page action type -- 0273b74: fix(openai): add support for sources type 'api' -- 5bf101a: feat(provider/openai): add support for OpenAI xhigh reasoning effort -- 1bd7d32: feat: tool-specific strict mode -- d86b52f: distinguish between OpenAI and Azure in Responses API providerMetadata -- 95f65c2: chore: load zod schemas lazily -- 59561f8: fix(openai); fix url_citation schema in chat api -- Updated dependencies - - @ai-sdk/provider@3.0.0 - - @ai-sdk/provider-utils@4.0.0 - -## 3.0.0-beta.112 - -### Patch Changes - -- Updated dependencies [475189e] - - @ai-sdk/provider@3.0.0-beta.32 - - @ai-sdk/provider-utils@4.0.0-beta.59 - -## 3.0.0-beta.111 - -### Patch Changes - -- 304222e: Add streaming support for apply_patch partial diffs. - -## 3.0.0-beta.110 - -### Patch Changes - -- 2625a04: feat(openai); update spec for mcp approval -- Updated dependencies [2625a04] - - @ai-sdk/provider@3.0.0-beta.31 - - @ai-sdk/provider-utils@4.0.0-beta.58 - -## 3.0.0-beta.109 - -### Patch Changes - -- cbf52cd: feat: expose raw finish reason -- Updated dependencies [cbf52cd] - - @ai-sdk/provider@3.0.0-beta.30 - - @ai-sdk/provider-utils@4.0.0-beta.57 - -## 3.0.0-beta.108 - -### Patch Changes - -- Updated dependencies [9549c9e] - - @ai-sdk/provider@3.0.0-beta.29 - - @ai-sdk/provider-utils@4.0.0-beta.56 - -## 3.0.0-beta.107 - -### Patch Changes - -- Updated dependencies [50b70d6] - - @ai-sdk/provider-utils@4.0.0-beta.55 - -## 3.0.0-beta.106 - -### Patch Changes - -- 9061dc0: feat: image editing -- Updated dependencies [9061dc0] - - @ai-sdk/provider-utils@4.0.0-beta.54 - - @ai-sdk/provider@3.0.0-beta.28 - -## 3.0.0-beta.105 - -### Patch Changes - -- 88574c1: Change `isReasoningModel` detection from blocklist to allowlist and add override option - -## 3.0.0-beta.104 - -### Patch Changes - -- 61c52dc: feat (provider/openai): add gpt-image-1.5 model support - -## 3.0.0-beta.103 - -### Patch Changes - -- 366f50b: chore(provider): add deprecated textEmbeddingModel and textEmbedding aliases -- Updated dependencies [366f50b] - - @ai-sdk/provider@3.0.0-beta.27 - - @ai-sdk/provider-utils@4.0.0-beta.53 - -## 3.0.0-beta.102 - -### Patch Changes - -- Updated dependencies [763d04a] - - @ai-sdk/provider-utils@4.0.0-beta.52 - -## 3.0.0-beta.101 - -### Patch Changes - -- 3220329: fix openai responses input: process all provider tool outputs (shell/apply_patch) so parallel tool results aren’t dropped and apply_patch outputs are forwarded. -- 5648ec0: Add GPT-5.2 support for non-reasoning parameters (temperature, topP, logProbs) when reasoningEffort is none. - -## 3.0.0-beta.100 - -### Patch Changes - -- Updated dependencies [c1efac4] - - @ai-sdk/provider-utils@4.0.0-beta.51 - -## 3.0.0-beta.99 - -### Patch Changes - -- Updated dependencies [32223c8] - - @ai-sdk/provider-utils@4.0.0-beta.50 - -## 3.0.0-beta.98 - -### Patch Changes - -- Updated dependencies [83e5744] - - @ai-sdk/provider-utils@4.0.0-beta.49 - -## 3.0.0-beta.97 - -### Patch Changes - -- Updated dependencies [960ec8f] - - @ai-sdk/provider-utils@4.0.0-beta.48 - -## 3.0.0-beta.96 - -### Patch Changes - -- 817e601: fix(openai); fix url_citation schema in chat api -- 59561f8: fix(openai); fix url_citation schema in chat api - -## 3.0.0-beta.95 - -### Patch Changes - -- 40dc7fa: fix(openai): change find action type to find_in_page action type - -## 3.0.0-beta.94 - -### Patch Changes - -- f18ef7f: feat(openai): add gpt-5.2 models - -## 3.0.0-beta.93 - -### Patch Changes - -- d2039d7: feat(provider/openai): add GPT 5.1 Codex Max to OpenAI Responses model IDs list - -## 3.0.0-beta.92 - -### Patch Changes - -- 5bf101a: feat(provider/openai): add support for OpenAI xhigh reasoning effort - -## 3.0.0-beta.91 - -### Patch Changes - -- Updated dependencies [e9e157f] - - @ai-sdk/provider-utils@4.0.0-beta.47 - -## 3.0.0-beta.90 - -### Patch Changes - -- Updated dependencies [81e29ab] - - @ai-sdk/provider-utils@4.0.0-beta.46 - -## 3.0.0-beta.89 - -### Patch Changes - -- 3bd2689: feat: extended token usage -- Updated dependencies [3bd2689] - - @ai-sdk/provider@3.0.0-beta.26 - - @ai-sdk/provider-utils@4.0.0-beta.45 - -## 3.0.0-beta.88 - -### Patch Changes - -- 92c6241: feat(openai): additional settings for file search tool - -## 3.0.0-beta.87 - -### Patch Changes - -- Updated dependencies [53f3368] - - @ai-sdk/provider@3.0.0-beta.25 - - @ai-sdk/provider-utils@4.0.0-beta.44 - -## 3.0.0-beta.86 - -### Patch Changes - -- 0153bfa: fix(openai): fix parameter exclusion logic - -## 3.0.0-beta.85 - -### Patch Changes - -- 78f813e: fix(openai): allow temperature etc setting when reasoning effort is none for gpt-5.1 - -## 3.0.0-beta.84 - -### Patch Changes - -- Updated dependencies [dce03c4] - - @ai-sdk/provider-utils@4.0.0-beta.43 - - @ai-sdk/provider@3.0.0-beta.24 - -## 3.0.0-beta.83 - -### Patch Changes - -- ef739fa: fix(openai): refactor apply-patch tool - -## 3.0.0-beta.82 - -### Patch Changes - -- Updated dependencies [3ed5519] - - @ai-sdk/provider-utils@4.0.0-beta.42 - -## 3.0.0-beta.81 - -### Patch Changes - -- cad6445: feat(openai); adding OpenAI's new shell tool - -## 3.0.0-beta.80 - -### Patch Changes - -- b60d2e2: fix(openai): allow open_page action type url to be nullish - -## 3.0.0-beta.79 - -### Patch Changes - -- 1bd7d32: feat: tool-specific strict mode -- Updated dependencies [1bd7d32] - - @ai-sdk/provider-utils@4.0.0-beta.41 - - @ai-sdk/provider@3.0.0-beta.23 - -## 3.0.0-beta.78 - -### Patch Changes - -- 2c0a758: chore(openai): add JSDoc to responses options - -## 3.0.0-beta.77 - -### Patch Changes - -- d270a5d: chore(openai): update tests for apply-patch tool to use snapshots - -## 3.0.0-beta.76 - -### Patch Changes - -- 88edc28: feat (provider/openai): include more image generation response metadata - -## 3.0.0-beta.75 - -### Patch Changes - -- 73d9883: chore(openai): enable strict json by default - -## 3.0.0-beta.74 - -### Patch Changes - -- 88fc415: feat(openai): add the new provider 'apply_patch' tool - -## 3.0.0-beta.73 - -### Patch Changes - -- 544d4e8: chore(specification): rename v3 provider defined tool to provider tool -- Updated dependencies [544d4e8] - - @ai-sdk/provider-utils@4.0.0-beta.40 - - @ai-sdk/provider@3.0.0-beta.22 - -## 3.0.0-beta.72 - -### Patch Changes - -- 954c356: feat(openai): allow custom names for provider-defined tools -- Updated dependencies [954c356] - - @ai-sdk/provider-utils@4.0.0-beta.39 - - @ai-sdk/provider@3.0.0-beta.21 - -## 3.0.0-beta.71 - -### Patch Changes - -- Updated dependencies [03849b0] - - @ai-sdk/provider-utils@4.0.0-beta.38 - -## 3.0.0-beta.70 - -### Patch Changes - -- 457318b: chore(provider,ai): switch to SharedV3Warning and unified warnings -- Updated dependencies [457318b] - - @ai-sdk/provider@3.0.0-beta.20 - - @ai-sdk/provider-utils@4.0.0-beta.37 - -## 3.0.0-beta.69 - -### Patch Changes - -- 1d0de66: refactoring(provider/openai): simplify code - -## 3.0.0-beta.68 - -### Patch Changes - -- 8d9e8ad: chore(provider): remove generics from EmbeddingModelV3 - - Before - - ```ts - model.textEmbeddingModel("my-model-id"); - ``` - - After - - ```ts - model.embeddingModel("my-model-id"); - ``` - -- Updated dependencies [8d9e8ad] - - @ai-sdk/provider@3.0.0-beta.19 - - @ai-sdk/provider-utils@4.0.0-beta.36 - -## 3.0.0-beta.67 - -### Patch Changes - -- Updated dependencies [10d819b] - - @ai-sdk/provider@3.0.0-beta.18 - - @ai-sdk/provider-utils@4.0.0-beta.35 - -## 3.0.0-beta.66 - -### Patch Changes - -- d86b52f: distinguish between OpenAI and Azure in Responses API providerMetadata - -## 3.0.0-beta.65 - -### Patch Changes - -- 38a4035: added support for external_web_access parameter on web_search tool - -## 3.0.0-beta.64 - -### Patch Changes - -- Updated dependencies [db913bd] - - @ai-sdk/provider@3.0.0-beta.17 - - @ai-sdk/provider-utils@4.0.0-beta.34 - -## 3.0.0-beta.63 - -### Patch Changes - -- 423ba08: Set the annotations from the Responses API to doStream - -## 3.0.0-beta.62 - -### Patch Changes - -- 64aa48f: Azure OpenAI enabled web-search-preview - -## 3.0.0-beta.61 - -### Patch Changes - -- 23f132b: fix: error schema for Responses API - -## 3.0.0-beta.60 - -### Patch Changes - -- 0877683: feat(provider/openai): support conversations api - -## 3.0.0-beta.59 - -### Patch Changes - -- d0f1baf: feat(openai): Add support for 'promptCacheRetention: 24h' for gpt5.1 series - -## 3.0.0-beta.58 - -### Patch Changes - -- 79b4e46: feat(openai): add 'gpt-5.1' modelID - -## 3.0.0-beta.57 - -### Patch Changes - -- b681d7d: feat: expose usage tokens for 'generateImage' function -- Updated dependencies [b681d7d] - - @ai-sdk/provider@3.0.0-beta.16 - - @ai-sdk/provider-utils@4.0.0-beta.33 - -## 3.0.0-beta.56 - -### Patch Changes - -- Updated dependencies [32d8dbb] - - @ai-sdk/provider-utils@4.0.0-beta.32 - -## 3.0.0-beta.55 - -### Patch Changes - -- 831b6cc: feat(openai): adding provider mcp tool for openai - -## 3.0.0-beta.54 - -### Patch Changes - -- 40d5419: feat(openai): add `o3-deep-research` and `o4-mini-deep-research` models - -## 3.0.0-beta.53 - -### Patch Changes - -- dae2185: fix(openai): extract meta data from first chunk that contains any - -## 3.0.0-beta.52 - -### Patch Changes - -- 348fd10: fix(openai): treat unknown models as reasoning - -## 3.0.0-beta.51 - -### Patch Changes - -- b82987c: feat(openai): support openai code-interpreter annotations - -## 3.0.0-beta.50 - -### Patch Changes - -- Updated dependencies [bb36798] - - @ai-sdk/provider@3.0.0-beta.15 - - @ai-sdk/provider-utils@4.0.0-beta.31 - -## 3.0.0-beta.49 - -### Patch Changes - -- 0273b74: fix(openai): add support for sources type 'api' - -## 3.0.0-beta.48 - -### Patch Changes - -- 60f4775: fix: remove code for unsuported o1-mini and o1-preview models - -## 3.0.0-beta.47 - -### Patch Changes - -- Updated dependencies [4f16c37] - - @ai-sdk/provider-utils@4.0.0-beta.30 - -## 3.0.0-beta.46 - -### Patch Changes - -- Updated dependencies [af3780b] - - @ai-sdk/provider@3.0.0-beta.14 - - @ai-sdk/provider-utils@4.0.0-beta.29 - -## 3.0.0-beta.45 - -### Patch Changes - -- fd47df5: fix(openai): revised_prompt sometimes returns null, causing errors - -## 3.0.0-beta.44 - -### Patch Changes - -- Updated dependencies [016b111] - - @ai-sdk/provider-utils@4.0.0-beta.28 - -## 3.0.0-beta.43 - -### Patch Changes - -- Updated dependencies [37c58a0] - - @ai-sdk/provider@3.0.0-beta.13 - - @ai-sdk/provider-utils@4.0.0-beta.27 - -## 3.0.0-beta.42 - -### Patch Changes - -- Updated dependencies [d1bdadb] - - @ai-sdk/provider@3.0.0-beta.12 - - @ai-sdk/provider-utils@4.0.0-beta.26 - -## 3.0.0-beta.41 - -### Patch Changes - -- Updated dependencies [4c44a5b] - - @ai-sdk/provider@3.0.0-beta.11 - - @ai-sdk/provider-utils@4.0.0-beta.25 - -## 3.0.0-beta.40 - -### Patch Changes - -- 1b982e6: feat(openai): preserve file_id when converting file citations - -## 3.0.0-beta.39 - -### Patch Changes - -- 0c3b58b: fix(provider): add specificationVersion to ProviderV3 -- Updated dependencies [0c3b58b] - - @ai-sdk/provider@3.0.0-beta.10 - - @ai-sdk/provider-utils@4.0.0-beta.24 - -## 3.0.0-beta.38 - -### Patch Changes - -- Updated dependencies [a755db5] - - @ai-sdk/provider@3.0.0-beta.9 - - @ai-sdk/provider-utils@4.0.0-beta.23 - -## 3.0.0-beta.37 - -### Patch Changes - -- e85fa2f: feat(openai): add sources in web-search actions - -## 3.0.0-beta.36 - -### Patch Changes - -- Updated dependencies [58920e0] - - @ai-sdk/provider-utils@4.0.0-beta.22 - -## 3.0.0-beta.35 - -### Patch Changes - -- Updated dependencies [293a6b7] - - @ai-sdk/provider-utils@4.0.0-beta.21 - -## 3.0.0-beta.34 - -### Patch Changes - -- Updated dependencies [fca786b] - - @ai-sdk/provider-utils@4.0.0-beta.20 - -## 3.0.0-beta.33 - -### Patch Changes - -- 7756857: fix(provider/openai): add truncation parameter support for Responses API - -## 3.0.0-beta.32 - -### Patch Changes - -- 3794514: feat: flexible tool output content support -- Updated dependencies [3794514] - - @ai-sdk/provider-utils@4.0.0-beta.19 - - @ai-sdk/provider@3.0.0-beta.8 - -## 3.0.0-beta.31 - -### Patch Changes - -- Updated dependencies [81d4308] - - @ai-sdk/provider@3.0.0-beta.7 - - @ai-sdk/provider-utils@4.0.0-beta.18 - -## 3.0.0-beta.30 - -### Patch Changes - -- Updated dependencies [703459a] - - @ai-sdk/provider-utils@4.0.0-beta.17 - -## 3.0.0-beta.29 - -### Patch Changes - -- 0b9fdd5: fix(provider/openai): end reasoning parts earlier - -## 3.0.0-beta.28 - -### Patch Changes - -- 401f561: fix(provider/openai): fix web search tool input types - -## 3.0.0-beta.27 - -### Patch Changes - -- f1277fe: feat(provider/openai): send assistant text and tool call parts as reference ids when store: true - -## 3.0.0-beta.26 - -### Patch Changes - -- edc5548: feat(provider/openai): automatically add reasoning.encrypted_content include when store = false - -## 3.0.0-beta.25 - -### Patch Changes - -- Updated dependencies [6306603] - - @ai-sdk/provider-utils@4.0.0-beta.16 - -## 3.0.0-beta.24 - -### Patch Changes - -- Updated dependencies [f0b2157] - - @ai-sdk/provider-utils@4.0.0-beta.15 - -## 3.0.0-beta.23 - -### Patch Changes - -- Updated dependencies [3b1d015] - - @ai-sdk/provider-utils@4.0.0-beta.14 - -## 3.0.0-beta.22 - -### Patch Changes - -- Updated dependencies [d116b4b] - - @ai-sdk/provider-utils@4.0.0-beta.13 - -## 3.0.0-beta.21 - -### Patch Changes - -- Updated dependencies [7e32fea] - - @ai-sdk/provider-utils@4.0.0-beta.12 - -## 3.0.0-beta.20 - -### Patch Changes - -- 68c6187: feat(provider/openai): support file and image tool results - -## 3.0.0-beta.19 - -### Patch Changes - -- 484aa93: Add 'default' as service tier - -## 3.0.0-beta.18 - -### Patch Changes - -- 95f65c2: chore: use import \* from zod/v4 -- 95f65c2: chore: load zod schemas lazily -- Updated dependencies - - @ai-sdk/provider-utils@4.0.0-beta.11 - -## 3.0.0-beta.17 - -### Major Changes - -- dee8b05: ai SDK 6 beta - -### Patch Changes - -- Updated dependencies [dee8b05] - - @ai-sdk/provider@3.0.0-beta.6 - - @ai-sdk/provider-utils@4.0.0-beta.10 - -## 2.1.0-beta.16 - -### Patch Changes - -- Updated dependencies [521c537] - - @ai-sdk/provider-utils@3.1.0-beta.9 - -## 2.1.0-beta.15 - -### Patch Changes - -- Updated dependencies [e06565c] - - @ai-sdk/provider-utils@3.1.0-beta.8 - -## 2.1.0-beta.14 - -### Patch Changes - -- 000e87b: fix(provider/openai): add providerExecuted flag to tool start chunks - -## 2.1.0-beta.13 - -### Patch Changes - -- 357cfd7: feat(provider/openai): add new model IDs `gpt-image-1-mini`, `gpt-5-pro`, `gpt-5-pro-2025-10-06` - -## 2.1.0-beta.12 - -### Patch Changes - -- 046aa3b: feat(provider): speech model v3 spec -- e8109d3: feat: tool execution approval -- 21e20c0: feat(provider): transcription model v3 spec -- Updated dependencies - - @ai-sdk/provider@2.1.0-beta.5 - - @ai-sdk/provider-utils@3.1.0-beta.7 - -## 2.1.0-beta.11 - -### Patch Changes - -- 0adc679: feat(provider): shared spec v3 -- 2b0caef: feat(provider/openai): preview image generation results -- Updated dependencies - - @ai-sdk/provider-utils@3.1.0-beta.6 - - @ai-sdk/provider@2.1.0-beta.4 - -## 2.1.0-beta.10 - -### Patch Changes - -- d64ece9: enables image_generation capabilities in the Azure provider through the Responses API. - -## 2.1.0-beta.9 - -### Patch Changes - -- 9a51b92: support OPENAI_BASE_URL env - -## 2.1.0-beta.8 - -### Patch Changes - -- 4122d2a: feat(provider/openai): add gpt-5-codex model id -- 3997a42: feat(provider/openai): local shell tool -- cb4d238: The built in Code Interpreter tool input code is streamed in `tool-input-` chunks. - -## 2.1.0-beta.7 - -### Patch Changes - -- 77f2b20: enables code_interpreter and file_search capabilities in the Azure provider through the Responses API -- 8dac895: feat: `LanguageModelV3` -- 10c1322: fix: moved dependency `@ai-sdk/test-server` to devDependencies -- Updated dependencies [8dac895] - - @ai-sdk/provider-utils@3.1.0-beta.5 - - @ai-sdk/provider@2.1.0-beta.3 - -## 2.1.0-beta.6 - -### Patch Changes - -- fe49278: feat(provider/openai): only send item references for reasoning when store: true - -## 2.1.0-beta.5 - -### Patch Changes - -- 4616b86: chore: update zod peer depenedency version -- Updated dependencies [4616b86] - - @ai-sdk/provider-utils@3.1.0-beta.4 - -## 2.1.0-beta.4 - -### Patch Changes - -- ed329cb: feat: `Provider-V3` -- 522f6b8: feat: `ImageModelV3` -- Updated dependencies - - @ai-sdk/provider@2.1.0-beta.2 - - @ai-sdk/provider-utils@3.1.0-beta.3 - -## 2.1.0-beta.3 - -### Patch Changes - -- 2e86082: feat(provider/openai): `OpenAIChatLanguageModelOptions` type - - ```ts - import { openai, type OpenAIChatLanguageModelOptions } from "@ai-sdk/openai"; - import { generateText } from "ai"; - - await generateText({ - model: openai.chat("gpt-4o"), - prompt: "Invent a new holiday and describe its traditions.", - providerOptions: { - openai: { - user: "user-123", - } satisfies OpenAIChatLanguageModelOptions, - }, - }); - ``` - -## 2.1.0-beta.2 - -### Patch Changes - -- 4920119: fix the "incomplete_details" key from nullable to nullish for openai compatibility -- 0c4822d: feat: `EmbeddingModelV3` -- 1cad0ab: feat: add provider version to user-agent header -- Updated dependencies [0c4822d] - - @ai-sdk/provider@2.1.0-beta.1 - - @ai-sdk/provider-utils@3.1.0-beta.2 - -## 2.1.0-beta.1 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/test-server@1.0.0-beta.0 - - @ai-sdk/provider-utils@3.1.0-beta.1 - -## 2.1.0-beta.0 - -### Minor Changes - -- 78928cb: release: start 5.1 beta - -### Patch Changes - -- Updated dependencies [78928cb] - - @ai-sdk/provider@2.1.0-beta.0 - - @ai-sdk/provider-utils@3.1.0-beta.0 - -## 2.0.32 - -### Patch Changes - -- 1cf857d: fix(provider/openai): remove provider-executed tools from chat completions model -- 01de47f: feat(provider/openai): rework file search tool - -## 2.0.31 - -### Patch Changes - -- bb94467: feat(provider/openai): add maxToolCalls provider option -- 4a2b70e: feat(provider/openai): send item references for provider-executed tool results -- 643711d: feat (provider/openai): provider defined image generation tool support - -## 2.0.30 - -### Patch Changes - -- Updated dependencies [0294b58] - - @ai-sdk/provider-utils@3.0.9 - -## 2.0.29 - -### Patch Changes - -- 4235eb3: feat(provider/openai): code interpreter tool calls and results - -## 2.0.28 - -### Patch Changes - -- 4c2bb77: fix (provider/openai): send sources action as include -- 561e8b0: fix (provider/openai): fix code interpreter tool in doGenerate - -## 2.0.27 - -### Patch Changes - -- 2338c79: feat (provider/openai): add jsdoc for openai tools - -## 2.0.26 - -### Patch Changes - -- 5819aec: fix (provider/openai): only send tool calls finish reason for tools that are not provider-executed -- af8c6bb: feat (provider/openai): add web_search tool - -## 2.0.25 - -### Patch Changes - -- fb45ade: fix timestamp granularities support for openai transcription - -## 2.0.24 - -### Patch Changes - -- ad57512: fix(provider/openai): safe practice to include filename and fileExtension to avoid `experimental_transcribe` fails with valid Buffer -- Updated dependencies [99964ed] - - @ai-sdk/provider-utils@3.0.8 - -## 2.0.23 - -### Patch Changes - -- a9a61b7: Add serviceTier to provider metadata for OpenAI responses - -## 2.0.22 - -### Patch Changes - -- 0e272ae: fix(provider/openai): make file_citation annotation fields optional for responses api compatibility -- Updated dependencies [886e7cd] - - @ai-sdk/provider-utils@3.0.7 - -## 2.0.21 - -### Patch Changes - -- d18856a: fix(provider/openai): support websearch tool results without query property -- 15271d6: fix(provider/openai): do not set `response_format` to `verbose_json` if model is `gpt-4o-transcribe` or `gpt-4o-mini-transcribe` - - These two models do not support it: - https://platform.openai.com/docs/api-reference/audio/createTranscription#audio_createtranscription-response_format - -- Updated dependencies [1b5a3d3] - - @ai-sdk/provider-utils@3.0.6 - -## 2.0.20 - -### Patch Changes - -- 974de40: fix(provider/ai): do not set `.providerMetadata.openai.logprobs` to an array of empty arrays when using `streamText()` - -## 2.0.19 - -### Patch Changes - -- Updated dependencies [0857788] - - @ai-sdk/provider-utils@3.0.5 - -## 2.0.18 - -### Patch Changes - -- 5e47d00: Support Responses API input_file file_url passthrough for PDFs. - - This adds: - - - file_url variant to OpenAIResponses user content - - PDF URL mapping to input_file with file_url in Responses converter - - PDF URL support in supportedUrls to avoid auto-download - -## 2.0.17 - -### Patch Changes - -- 70bb696: fix(provider/openai): correct web search tool input - -## 2.0.16 - -### Patch Changes - -- Updated dependencies [68751f9] - - @ai-sdk/provider-utils@3.0.4 - -## 2.0.15 - -### Patch Changes - -- a4bef93: feat(provider/openai): expose web search queries in responses api -- 6ed34cb: refactor(openai): consolidate model config into `getResponsesModelConfig()` - - https://github.com/vercel/ai/pull/8038 - -## 2.0.14 - -### Patch Changes - -- 7f47105: fix(provider/openai): support file_citation annotations in responses api - -## 2.0.13 - -### Patch Changes - -- ddc9d99: Implements `logprobs` for OpenAI `providerOptions` and `providerMetaData` in `OpenAIResponsesLanguageModel` - - You can now set `providerOptions.openai.logprobs` when using `generateText()` and retrieve logprobs from the response via `result.providerMetadata?.openai` - -## 2.0.12 - -### Patch Changes - -- ec336a1: feat(provider/openai): add response_format to be supported by default -- 2935ec7: fix(provider/openai): exclude gpt-5-chat from reasoning model -- Updated dependencies - - @ai-sdk/provider-utils@3.0.3 - -## 2.0.11 - -### Patch Changes - -- 097b452: feat(openai, azure): add configurable file ID prefixes for Responses API - - - Added `fileIdPrefixes` option to OpenAI Responses API configuration - - Azure OpenAI now supports `assistant-` prefixed file IDs (replacing previous `file-` prefix support) - - OpenAI maintains backward compatibility with default `file-` prefix - - File ID detection is disabled when `fileIdPrefixes` is undefined, gracefully falling back to base64 processing - -- 87cf954: feat(provider/openai): add support for prompt_cache_key -- a3d98a9: feat(provider/openai): add support for safety_identifier -- 110d167: fix(openai): add missing file_search_call handlers in responses streaming -- 8d3c747: chore(openai): remove deprecated GPT-4.5-preview models and improve autocomplete control -- Updated dependencies [38ac190] - - @ai-sdk/provider-utils@3.0.2 - -## 2.0.10 - -### Patch Changes - -- a274b01: refactor(provider/openai): restructure files -- b48e0ff: feat(provider/openai): add code interpreter tool (responses api) - -## 2.0.9 - -### Patch Changes - -- 8f8a521: fix(providers): use convertToBase64 for Uint8Array image parts to produce valid data URLs; keep mediaType normalization and URL passthrough - -## 2.0.8 - -### Patch Changes - -- 57fb959: feat(openai): add verbosity parameter support for chat api -- 2a3fbe6: allow `minimal` in `reasoningEffort` for openai chat - -## 2.0.7 - -### Patch Changes - -- 4738f18: feat(openai): add flex processing support for gpt-5 models -- 013d747: feat(openai): add verbosity parameter support for responses api -- 35feee8: feat(openai): add priority processing support for gpt-5 models - -## 2.0.6 - -### Patch Changes - -- ad2255f: chore(docs): added gpt 5 models + removed deprecated models -- 64bcb66: feat(provider/openai): models ids on chat -- 1d42ff2: feat(provider/openai): models ids - -## 2.0.5 - -### Patch Changes - -- 6753a2e: feat(examples): add gpt-5 model examples and e2e tests -- 6cba06a: feat (provider/openai): add reasoning model config - -## 2.0.4 - -### Patch Changes - -- c9e0f52: Files from the OpenAI Files API are now supported, mirroring functionality of OpenAI Chat and Responses API, respectively. Also, the AI SDK supports URLs for PDFs in the responses API the same way it did for completions. - -## 2.0.3 - -### Patch Changes - -- Updated dependencies [90d212f] - - @ai-sdk/provider-utils@3.0.1 - -## 2.0.2 - -### Patch Changes - -- 63e2016: fix(openai): missing url citations from web search tools - -## 2.0.1 - -### Patch Changes - -- bc45e29: feat(openai): add file_search_call support to responses api - -## 2.0.0 - -### Major Changes - -- d5f588f: AI SDK 5 -- cc62234: chore (provider/openai): switch default to openai responses api -- 516be5b: ### Move Image Model Settings into generate options - - Image Models no longer have settings. Instead, `maxImagesPerCall` can be passed directly to `generateImage()`. All other image settings can be passed to `providerOptions[provider]`. - - Before - - ```js - await generateImage({ - model: luma.image("photon-flash-1", { - maxImagesPerCall: 5, - pollIntervalMillis: 500, - }), - prompt, - n: 10, - }); - ``` - - After - - ```js - await generateImage({ - model: luma.image("photon-flash-1"), - prompt, - n: 10, - maxImagesPerCall: 5, - providerOptions: { - luma: { pollIntervalMillis: 5 }, - }, - }); - ``` - - Pull Request: https://github.com/vercel/ai/pull/6180 - -- efc3a62: fix (provider/openai): default strict mode to false - -### Patch Changes - -- 948b755: chore(providers/openai): convert to providerOptions -- d63bcbc: feat (provider/openai): o4 updates for responses api -- 3bd3c0b: chore(providers/openai): update embedding model to use providerOptions -- 5d959e7: refactor: updated openai + anthropic tool use server side -- 0eee6a8: Fix streaming and reconstruction of reasoning summary parts -- 177526b: chore(providers/openai-transcription): switch to providerOptions -- 2f542fa: Add reasoning-part-finish parts for reasoning models in the responses API -- c15dfbf: feat (providers/openai): add gpt-image-1 model id to image settings -- 3b1ea10: adding support for gpt-4o-search-preview and handling unsupported parameters -- e2aceaf: feat: add raw chunk support -- d2af019: feat (providers/openai): add gpt-4.1 models -- eb173f1: chore (providers): remove model shorthand deprecation warnings -- 209256d: Add missing file_search tool support to OpenAI Responses API -- faea29f: fix (provider/openai): multi-step reasoning with text -- 7032dc5: feat(openai): add priority processing service tier support -- 870c5c0: feat (providers/openai): add o3 and o4-mini models -- db72adc: chore(providers/openai): update completion model to use providerOptions -- a166433: feat: add transcription with experimental_transcribe -- 26735b5: chore(embedding-model): add v2 interface -- 443d8ec: feat(embedding-model-v2): add response body field -- 8d12da5: feat(provider/openai): add serviceTier option for flex processing -- 9bf7291: chore(providers/openai): enable structuredOutputs by default & switch to provider option -- d521cda: feat(openai): add file_search filters and update field names -- 66962ed: fix(packages): export node10 compatible types -- 442be08: fix: propagate openai transcription fixes -- 0059ee2: fix(openai): update file_search fields to match API changes -- 8493141: feat (providers/openai): add support for reasoning summaries -- 9301f86: refactor (image-model): rename `ImageModelV1` to `ImageModelV2` -- 0a87932: core (ai): change transcription model mimeType to mediaType -- 8aa9e20: feat: add speech with experimental_generateSpeech -- 4617fab: chore(embedding-models): remove remaining settings -- b5a0e32: fix (provider/openai): correct default for chat model strict mode -- 136819b: chore(providers/openai): re-introduce logprobs as providerMetadata -- 52ce942: chore(providers/openai): remove & enable strict compatibility by default -- db64cbe: fix (provider/openai): multi-step reasoning with tool calls -- b3c3450: feat (provider/openai): add support for encrypted_reasoning to responses api -- 48249c4: Do not warn if empty text is the first part of a reasoning sequence -- c7d3b2e: fix (provider/openai): push first reasoning chunk in output item added event -- ad2a3d5: feat(provider/openai): add missing reasoning models to responses API -- 9943464: feat(openai): add file_search_call.results support to include parameter -- 0fa7414: chore (provider/openai): standardize on itemId in provider metadata -- 9bd5ab5: feat (provider): add providerMetadata to ImageModelV2 interface (#5977) - - The `experimental_generateImage` method from the `ai` package now returnes revised prompts for OpenAI's image models. - - ```js - const prompt = "Santa Claus driving a Cadillac"; - - const { providerMetadata } = await experimental_generateImage({ - model: openai.image("dall-e-3"), - prompt, - }); - - const revisedPrompt = providerMetadata.openai.images[0]?.revisedPrompt; - - console.log({ - prompt, - revisedPrompt, - }); - ``` - -- fa758ea: feat(provider/openai): add o3 & o4-mini with developer systemMessageMode -- d1a034f: feature: using Zod 4 for internal stuff -- fd65bc6: chore(embedding-model-v2): rename rawResponse to response -- e497698: fix (provider/openai): handle responses api errors -- 928fadf: fix(providers/openai): logprobs for stream alongside completion model -- 0a87932: fix (provider/openai): increase transcription model resilience -- 5147e6e: chore(openai): remove simulateStreaming -- 06bac05: fix (openai): structure output for responses model -- 205077b: fix: improve Zod compatibility -- c2b92cc: chore(openai): remove legacy function calling -- 284353f: fix(providers/openai): zod parse error with function -- 6f231db: fix(providers): always use optional instead of mix of nullish for providerOptions -- f10304b: feat(tool-calling): don't require the user to have to pass parameters -- 4af5233: Fix PDF file parts when passed as a string url or Uint8Array -- 7df7a25: feat (providers/openai): support gpt-image-1 image generation -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0 - - @ai-sdk/provider@2.0.0 - -## 2.0.0-beta.16 - -### Patch Changes - -- Updated dependencies [88a8ee5] - - @ai-sdk/provider-utils@3.0.0-beta.10 - -## 2.0.0-beta.15 - -### Patch Changes - -- 9943464: feat(openai): add file_search_call.results support to include parameter -- Updated dependencies [27deb4d] - - @ai-sdk/provider@2.0.0-beta.2 - - @ai-sdk/provider-utils@3.0.0-beta.9 - -## 2.0.0-beta.14 - -### Patch Changes - -- eb173f1: chore (providers): remove model shorthand deprecation warnings -- 7032dc5: feat(openai): add priority processing service tier support -- Updated dependencies [dd5fd43] - - @ai-sdk/provider-utils@3.0.0-beta.8 - -## 2.0.0-beta.13 - -### Patch Changes - -- Updated dependencies [e7fcc86] - - @ai-sdk/provider-utils@3.0.0-beta.7 - -## 2.0.0-beta.12 - -### Patch Changes - -- d521cda: feat(openai): add file_search filters and update field names -- 0059ee2: fix(openai): update file_search fields to match API changes -- Updated dependencies [ac34802] - - @ai-sdk/provider-utils@3.0.0-beta.6 - -## 2.0.0-beta.11 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-beta.5 - -## 2.0.0-beta.10 - -### Patch Changes - -- 0fa7414: chore (provider/openai): standardize on itemId in provider metadata -- 205077b: fix: improve Zod compatibility -- Updated dependencies [205077b] - - @ai-sdk/provider-utils@3.0.0-beta.4 - -## 2.0.0-beta.9 - -### Patch Changes - -- faea29f: fix (provider/openai): multi-step reasoning with text - -## 2.0.0-beta.8 - -### Patch Changes - -- db64cbe: fix (provider/openai): multi-step reasoning with tool calls -- Updated dependencies [05d2819] - - @ai-sdk/provider-utils@3.0.0-beta.3 - -## 2.0.0-beta.7 - -### Patch Changes - -- 209256d: Add missing file_search tool support to OpenAI Responses API - -## 2.0.0-beta.6 - -### Patch Changes - -- 0eee6a8: Fix streaming and reconstruction of reasoning summary parts -- b5a0e32: fix (provider/openai): correct default for chat model strict mode -- c7d3b2e: fix (provider/openai): push first reasoning chunk in output item added event - -## 2.0.0-beta.5 - -### Patch Changes - -- 48249c4: Do not warn if empty text is the first part of a reasoning sequence -- e497698: fix (provider/openai): handle responses api errors - -## 2.0.0-beta.4 - -### Patch Changes - -- b3c3450: feat (provider/openai): add support for encrypted_reasoning to responses api -- ad2a3d5: feat(provider/openai): add missing reasoning models to responses API - -## 2.0.0-beta.3 - -### Major Changes - -- efc3a62: fix (provider/openai): default strict mode to false - -## 2.0.0-beta.2 - -### Patch Changes - -- d1a034f: feature: using Zod 4 for internal stuff -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-beta.2 - -## 2.0.0-beta.1 - -### Major Changes - -- cc62234: chore (provider/openai): switch default to openai responses api - -### Patch Changes - -- 5d959e7: refactor: updated openai + anthropic tool use server side -- Updated dependencies - - @ai-sdk/provider@2.0.0-beta.1 - - @ai-sdk/provider-utils@3.0.0-beta.1 - -## 2.0.0-alpha.15 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-alpha.15 - - @ai-sdk/provider-utils@3.0.0-alpha.15 - -## 2.0.0-alpha.14 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-alpha.14 - - @ai-sdk/provider-utils@3.0.0-alpha.14 - -## 2.0.0-alpha.13 - -### Patch Changes - -- Updated dependencies [68ecf2f] - - @ai-sdk/provider@2.0.0-alpha.13 - - @ai-sdk/provider-utils@3.0.0-alpha.13 - -## 2.0.0-alpha.12 - -### Patch Changes - -- 2f542fa: Add reasoning-part-finish parts for reasoning models in the responses API -- e2aceaf: feat: add raw chunk support -- Updated dependencies [e2aceaf] - - @ai-sdk/provider@2.0.0-alpha.12 - - @ai-sdk/provider-utils@3.0.0-alpha.12 - -## 2.0.0-alpha.11 - -### Patch Changes - -- 8d12da5: feat(provider/openai): add serviceTier option for flex processing -- Updated dependencies [c1e6647] - - @ai-sdk/provider@2.0.0-alpha.11 - - @ai-sdk/provider-utils@3.0.0-alpha.11 - -## 2.0.0-alpha.10 - -### Patch Changes - -- Updated dependencies [c4df419] - - @ai-sdk/provider@2.0.0-alpha.10 - - @ai-sdk/provider-utils@3.0.0-alpha.10 - -## 2.0.0-alpha.9 - -### Patch Changes - -- Updated dependencies [811dff3] - - @ai-sdk/provider@2.0.0-alpha.9 - - @ai-sdk/provider-utils@3.0.0-alpha.9 - -## 2.0.0-alpha.8 - -### Patch Changes - -- 4af5233: Fix PDF file parts when passed as a string url or Uint8Array -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-alpha.8 - - @ai-sdk/provider@2.0.0-alpha.8 - -## 2.0.0-alpha.7 - -### Patch Changes - -- Updated dependencies [5c56081] - - @ai-sdk/provider@2.0.0-alpha.7 - - @ai-sdk/provider-utils@3.0.0-alpha.7 - -## 2.0.0-alpha.6 - -### Patch Changes - -- Updated dependencies [0d2c085] - - @ai-sdk/provider@2.0.0-alpha.6 - - @ai-sdk/provider-utils@3.0.0-alpha.6 - -## 2.0.0-alpha.4 - -### Patch Changes - -- Updated dependencies [dc714f3] - - @ai-sdk/provider@2.0.0-alpha.4 - - @ai-sdk/provider-utils@3.0.0-alpha.4 - -## 2.0.0-alpha.3 - -### Patch Changes - -- Updated dependencies [6b98118] - - @ai-sdk/provider@2.0.0-alpha.3 - - @ai-sdk/provider-utils@3.0.0-alpha.3 - -## 2.0.0-alpha.2 - -### Patch Changes - -- Updated dependencies [26535e0] - - @ai-sdk/provider@2.0.0-alpha.2 - - @ai-sdk/provider-utils@3.0.0-alpha.2 - -## 2.0.0-alpha.1 - -### Patch Changes - -- Updated dependencies [3f2f00c] - - @ai-sdk/provider@2.0.0-alpha.1 - - @ai-sdk/provider-utils@3.0.0-alpha.1 - -## 2.0.0-canary.20 - -### Patch Changes - -- Updated dependencies [faf8446] - - @ai-sdk/provider-utils@3.0.0-canary.19 - -## 2.0.0-canary.19 - -### Patch Changes - -- Updated dependencies [40acf9b] - - @ai-sdk/provider-utils@3.0.0-canary.18 - -## 2.0.0-canary.18 - -### Major Changes - -- 516be5b: ### Move Image Model Settings into generate options - - Image Models no longer have settings. Instead, `maxImagesPerCall` can be passed directly to `generateImage()`. All other image settings can be passed to `providerOptions[provider]`. - - Before - - ```js - await generateImage({ - model: luma.image("photon-flash-1", { - maxImagesPerCall: 5, - pollIntervalMillis: 500, - }), - prompt, - n: 10, - }); - ``` - - After - - ```js - await generateImage({ - model: luma.image("photon-flash-1"), - prompt, - n: 10, - maxImagesPerCall: 5, - providerOptions: { - luma: { pollIntervalMillis: 5 }, - }, - }); - ``` - - Pull Request: https://github.com/vercel/ai/pull/6180 - -### Patch Changes - -- Updated dependencies [ea7a7c9] - - @ai-sdk/provider-utils@3.0.0-canary.17 - -## 2.0.0-canary.17 - -### Patch Changes - -- 52ce942: chore(providers/openai): remove & enable strict compatibility by default -- Updated dependencies [87b828f] - - @ai-sdk/provider-utils@3.0.0-canary.16 - -## 2.0.0-canary.16 - -### Patch Changes - -- 928fadf: fix(providers/openai): logprobs for stream alongside completion model -- 6f231db: fix(providers): always use optional instead of mix of nullish for providerOptions -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.15 - - @ai-sdk/provider@2.0.0-canary.14 - -## 2.0.0-canary.15 - -### Patch Changes - -- 136819b: chore(providers/openai): re-introduce logprobs as providerMetadata -- 9bd5ab5: feat (provider): add providerMetadata to ImageModelV2 interface (#5977) - - The `experimental_generateImage` method from the `ai` package now returnes revised prompts for OpenAI's image models. - - ```js - const prompt = "Santa Claus driving a Cadillac"; - - const { providerMetadata } = await experimental_generateImage({ - model: openai.image("dall-e-3"), - prompt, - }); - - const revisedPrompt = providerMetadata.openai.images[0]?.revisedPrompt; - - console.log({ - prompt, - revisedPrompt, - }); - ``` - -- 284353f: fix(providers/openai): zod parse error with function -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.14 - - @ai-sdk/provider@2.0.0-canary.13 - -## 2.0.0-canary.14 - -### Patch Changes - -- fa758ea: feat(provider/openai): add o3 & o4-mini with developer systemMessageMode -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.12 - - @ai-sdk/provider-utils@3.0.0-canary.13 - -## 2.0.0-canary.13 - -### Patch Changes - -- 177526b: chore(providers/openai-transcription): switch to providerOptions -- c15dfbf: feat (providers/openai): add gpt-image-1 model id to image settings -- 9bf7291: chore(providers/openai): enable structuredOutputs by default & switch to provider option -- 4617fab: chore(embedding-models): remove remaining settings -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.11 - - @ai-sdk/provider-utils@3.0.0-canary.12 - -## 2.0.0-canary.12 - -### Patch Changes - -- db72adc: chore(providers/openai): update completion model to use providerOptions -- 66962ed: fix(packages): export node10 compatible types -- 9301f86: refactor (image-model): rename `ImageModelV1` to `ImageModelV2` -- 7df7a25: feat (providers/openai): support gpt-image-1 image generation -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.11 - - @ai-sdk/provider@2.0.0-canary.10 - -## 2.0.0-canary.11 - -### Patch Changes - -- 8493141: feat (providers/openai): add support for reasoning summaries -- Updated dependencies [e86be6f] - - @ai-sdk/provider@2.0.0-canary.9 - - @ai-sdk/provider-utils@3.0.0-canary.10 - -## 2.0.0-canary.10 - -### Patch Changes - -- 3bd3c0b: chore(providers/openai): update embedding model to use providerOptions -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.8 - - @ai-sdk/provider-utils@3.0.0-canary.9 - -## 2.0.0-canary.9 - -### Patch Changes - -- d63bcbc: feat (provider/openai): o4 updates for responses api -- d2af019: feat (providers/openai): add gpt-4.1 models -- 870c5c0: feat (providers/openai): add o3 and o4-mini models -- 06bac05: fix (openai): structure output for responses model - -## 2.0.0-canary.8 - -### Patch Changes - -- 8aa9e20: feat: add speech with experimental_generateSpeech -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.8 - - @ai-sdk/provider@2.0.0-canary.7 - -## 2.0.0-canary.7 - -### Patch Changes - -- 26735b5: chore(embedding-model): add v2 interface -- 443d8ec: feat(embedding-model-v2): add response body field -- fd65bc6: chore(embedding-model-v2): rename rawResponse to response -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.6 - - @ai-sdk/provider-utils@3.0.0-canary.7 - -## 2.0.0-canary.6 - -### Patch Changes - -- 948b755: chore(providers/openai): convert to providerOptions -- 3b1ea10: adding support for gpt-4o-search-preview and handling unsupported parameters -- 442be08: fix: propagate openai transcription fixes -- 5147e6e: chore(openai): remove simulateStreaming -- c2b92cc: chore(openai): remove legacy function calling -- f10304b: feat(tool-calling): don't require the user to have to pass parameters -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.5 - - @ai-sdk/provider-utils@3.0.0-canary.6 - -## 2.0.0-canary.5 - -### Patch Changes - -- Updated dependencies [6f6bb89] - - @ai-sdk/provider@2.0.0-canary.4 - - @ai-sdk/provider-utils@3.0.0-canary.5 - -## 2.0.0-canary.4 - -### Patch Changes - -- Updated dependencies [d1a1aa1] - - @ai-sdk/provider@2.0.0-canary.3 - - @ai-sdk/provider-utils@3.0.0-canary.4 - -## 2.0.0-canary.3 - -### Patch Changes - -- a166433: feat: add transcription with experimental_transcribe -- 0a87932: core (ai): change transcription model mimeType to mediaType -- 0a87932: fix (provider/openai): increase transcription model resilience -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.3 - - @ai-sdk/provider@2.0.0-canary.2 - -## 2.0.0-canary.2 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.1 - - @ai-sdk/provider-utils@3.0.0-canary.2 - -## 2.0.0-canary.1 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.1 - -## 2.0.0-canary.0 - -### Major Changes - -- d5f588f: AI SDK 5 - -### Patch Changes - -- Updated dependencies [d5f588f] - - @ai-sdk/provider-utils@3.0.0-canary.0 - - @ai-sdk/provider@2.0.0-canary.0 - -## 1.3.6 - -### Patch Changes - -- Updated dependencies [28be004] - - @ai-sdk/provider-utils@2.2.3 - -## 1.3.5 - -### Patch Changes - -- 52ed95f: fix (provider/openai): force web search tool -- Updated dependencies [b01120e] - - @ai-sdk/provider-utils@2.2.2 - -## 1.3.4 - -### Patch Changes - -- b520dba: feat (provider/openai): add chatgpt-4o-latest model - -## 1.3.3 - -### Patch Changes - -- 24befd8: feat (provider/openai): add instructions to providerOptions - -## 1.3.2 - -### Patch Changes - -- db15028: feat (provider/openai): expose type for validating OpenAI responses provider options - -## 1.3.1 - -### Patch Changes - -- Updated dependencies [f10f0fa] - - @ai-sdk/provider-utils@2.2.1 - -## 1.3.0 - -### Minor Changes - -- 5bc638d: AI SDK 4.2 - -### Patch Changes - -- Updated dependencies [5bc638d] - - @ai-sdk/provider@1.1.0 - - @ai-sdk/provider-utils@2.2.0 - -## 1.2.8 - -### Patch Changes - -- 9f4f1bc: feat (provider/openai): pdf support for chat language models - -## 1.2.7 - -### Patch Changes - -- Updated dependencies [d0c4659] - - @ai-sdk/provider-utils@2.1.15 - -## 1.2.6 - -### Patch Changes - -- Updated dependencies [0bd5bc6] - - @ai-sdk/provider@1.0.12 - - @ai-sdk/provider-utils@2.1.14 - -## 1.2.5 - -### Patch Changes - -- 2e1101a: feat (provider/openai): pdf input support -- Updated dependencies [2e1101a] - - @ai-sdk/provider@1.0.11 - - @ai-sdk/provider-utils@2.1.13 - -## 1.2.4 - -### Patch Changes - -- 523f128: feat (provider/openai): add strictSchemas option to responses model - -## 1.2.3 - -### Patch Changes - -- Updated dependencies [1531959] - - @ai-sdk/provider-utils@2.1.12 - -## 1.2.2 - -### Patch Changes - -- e3a389e: feat (provider/openai): support responses api - -## 1.2.1 - -### Patch Changes - -- e1d3d42: feat (ai): expose raw response body in generateText and generateObject -- Updated dependencies [e1d3d42] - - @ai-sdk/provider@1.0.10 - - @ai-sdk/provider-utils@2.1.11 - -## 1.2.0 - -### Minor Changes - -- ede6d1b: feat (provider/azure): Add Azure image model support - -## 1.1.15 - -### Patch Changes - -- d8216f8: feat (provider/openai): add gpt-4.5-preview to model id set - -## 1.1.14 - -### Patch Changes - -- Updated dependencies [ddf9740] - - @ai-sdk/provider@1.0.9 - - @ai-sdk/provider-utils@2.1.10 - -## 1.1.13 - -### Patch Changes - -- Updated dependencies [2761f06] - - @ai-sdk/provider@1.0.8 - - @ai-sdk/provider-utils@2.1.9 - -## 1.1.12 - -### Patch Changes - -- ea159cb: chore (provider/openai): remove default streaming simulation for o1 - -## 1.1.11 - -### Patch Changes - -- Updated dependencies [2e898b4] - - @ai-sdk/provider-utils@2.1.8 - -## 1.1.10 - -### Patch Changes - -- Updated dependencies [3ff4ef8] - - @ai-sdk/provider-utils@2.1.7 - -## 1.1.9 - -### Patch Changes - -- c55b81a: fix (provider/openai): fix o3-mini streaming - -## 1.1.8 - -### Patch Changes - -- 161be90: fix (provider/openai): fix model id typo - -## 1.1.7 - -### Patch Changes - -- 0a2f026: feat (provider/openai): add o3-mini - -## 1.1.6 - -### Patch Changes - -- d89c3b9: feat (provider): add image model support to provider specification -- Updated dependencies [d89c3b9] - - @ai-sdk/provider@1.0.7 - - @ai-sdk/provider-utils@2.1.6 - -## 1.1.5 - -### Patch Changes - -- Updated dependencies [3a602ca] - - @ai-sdk/provider-utils@2.1.5 - -## 1.1.4 - -### Patch Changes - -- Updated dependencies [066206e] - - @ai-sdk/provider-utils@2.1.4 - -## 1.1.3 - -### Patch Changes - -- Updated dependencies [39e5c1f] - - @ai-sdk/provider-utils@2.1.3 - -## 1.1.2 - -### Patch Changes - -- 3a58a2e: feat (ai/core): throw NoImageGeneratedError from generateImage when no predictions are returned. -- Updated dependencies - - @ai-sdk/provider-utils@2.1.2 - - @ai-sdk/provider@1.0.6 - -## 1.1.1 - -### Patch Changes - -- e7a9ec9: feat (provider-utils): include raw value in json parse results -- Updated dependencies - - @ai-sdk/provider-utils@2.1.1 - - @ai-sdk/provider@1.0.5 - -## 1.1.0 - -### Minor Changes - -- 62ba5ad: release: AI SDK 4.1 - -### Patch Changes - -- Updated dependencies [62ba5ad] - - @ai-sdk/provider-utils@2.1.0 - -## 1.0.20 - -### Patch Changes - -- Updated dependencies [00114c5] - - @ai-sdk/provider-utils@2.0.8 - -## 1.0.19 - -### Patch Changes - -- 218d001: feat (provider): Add maxImagesPerCall setting to all image providers. - -## 1.0.18 - -### Patch Changes - -- fe816e4: fix (provider/openai): streamObject with o1 - -## 1.0.17 - -### Patch Changes - -- ba62cf2: feat (provider/openai): automatically map maxTokens to max_completion_tokens for reasoning models -- 3c3fae8: fix (provider/openai): add o1-mini-2024-09-12 and o1-preview-2024-09-12 configurations - -## 1.0.16 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@2.0.7 - -## 1.0.15 - -### Patch Changes - -- f8c6acb: feat (provider/openai): automatically simulate streaming for reasoning models -- d0041f7: feat (provider/openai): improved system message support for reasoning models -- 4d2f97b: feat (provider/openai): improve automatic setting removal for reasoning models - -## 1.0.14 - -### Patch Changes - -- 19a2ce7: feat (ai/core): add aspectRatio and seed options to generateImage -- 6337688: feat: change image generation errors to warnings -- Updated dependencies - - @ai-sdk/provider@1.0.4 - - @ai-sdk/provider-utils@2.0.6 - -## 1.0.13 - -### Patch Changes - -- b19aa82: feat (provider/openai): add predicted outputs token usage - -## 1.0.12 - -### Patch Changes - -- a4241ff: feat (provider/openai): add o3 reasoning model support - -## 1.0.11 - -### Patch Changes - -- 5ed5e45: chore (config): Use ts-library.json tsconfig for no-UI libs. -- Updated dependencies [5ed5e45] - - @ai-sdk/provider-utils@2.0.5 - - @ai-sdk/provider@1.0.3 - -## 1.0.10 - -### Patch Changes - -- d4fad4e: fix (provider/openai): fix reasoning model detection - -## 1.0.9 - -### Patch Changes - -- 3fab0fb: feat (provider/openai): support reasoning_effort setting -- e956eed: feat (provider/openai): update model list and add o1 -- 6faab13: feat (provider/openai): simulated streaming setting - -## 1.0.8 - -### Patch Changes - -- 09a9cab: feat (ai/core): add experimental generateImage function -- Updated dependencies [09a9cab] - - @ai-sdk/provider@1.0.2 - - @ai-sdk/provider-utils@2.0.4 - -## 1.0.7 - -### Patch Changes - -- Updated dependencies [0984f0b] - - @ai-sdk/provider-utils@2.0.3 - -## 1.0.6 - -### Patch Changes - -- a9a19cb: fix (provider/openai,groq): prevent sending duplicate tool calls - -## 1.0.5 - -### Patch Changes - -- fc18132: feat (ai/core): experimental output for generateText - -## 1.0.4 - -### Patch Changes - -- Updated dependencies [b446ae5] - - @ai-sdk/provider@1.0.1 - - @ai-sdk/provider-utils@2.0.2 - -## 1.0.3 - -### Patch Changes - -- b748dfb: feat (providers): update model lists - -## 1.0.2 - -### Patch Changes - -- Updated dependencies [c3ab5de] - - @ai-sdk/provider-utils@2.0.1 - -## 1.0.1 - -### Patch Changes - -- 5e6419a: feat (provider/openai): support streaming for reasoning models - -## 1.0.0 - -### Major Changes - -- 66060f7: chore (release): bump major version to 4.0 -- 79644e9: chore (provider/openai): remove OpenAI facade -- 0d3d3f5: chore (providers): remove baseUrl option - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@2.0.0 - - @ai-sdk/provider@1.0.0 - -## 1.0.0-canary.3 - -### Patch Changes - -- Updated dependencies [8426f55] - - @ai-sdk/provider-utils@2.0.0-canary.3 - -## 1.0.0-canary.2 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@2.0.0-canary.2 - -## 1.0.0-canary.1 - -### Major Changes - -- 79644e9: chore (provider/openai): remove OpenAI facade -- 0d3d3f5: chore (providers): remove baseUrl option - -### Patch Changes - -- Updated dependencies [b1da952] - - @ai-sdk/provider-utils@2.0.0-canary.1 - -## 1.0.0-canary.0 - -### Major Changes - -- 66060f7: chore (release): bump major version to 4.0 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@2.0.0-canary.0 - - @ai-sdk/provider@1.0.0-canary.0 - -## 0.0.72 - -### Patch Changes - -- 0bc4115: feat (provider/openai): support predicted outputs - -## 0.0.71 - -### Patch Changes - -- 54a3a59: fix (provider/openai): support object-json mode without schema - -## 0.0.70 - -### Patch Changes - -- 3b1b69a: feat: provider-defined tools -- Updated dependencies - - @ai-sdk/provider-utils@1.0.22 - - @ai-sdk/provider@0.0.26 - -## 0.0.69 - -### Patch Changes - -- b9b0d7b: feat (ai): access raw request body -- Updated dependencies [b9b0d7b] - - @ai-sdk/provider@0.0.25 - - @ai-sdk/provider-utils@1.0.21 - -## 0.0.68 - -### Patch Changes - -- 741ca51: feat (provider/openai): support mp3 and wav audio inputs - -## 0.0.67 - -### Patch Changes - -- 39fccee: feat (provider/openai): provider name can be changed for 3rd party openai compatible providers - -## 0.0.66 - -### Patch Changes - -- 3f29c10: feat (provider/openai): support metadata field for distillation - -## 0.0.65 - -### Patch Changes - -- e8aed44: Add OpenAI cached prompt tokens to experimental_providerMetadata for generateText and streamText - -## 0.0.64 - -### Patch Changes - -- 5aa576d: feat (provider/openai): support store parameter for distillation - -## 0.0.63 - -### Patch Changes - -- Updated dependencies [d595d0d] - - @ai-sdk/provider@0.0.24 - - @ai-sdk/provider-utils@1.0.20 - -## 0.0.62 - -### Patch Changes - -- 7efa867: feat (provider/openai): simulated streaming for reasoning models - -## 0.0.61 - -### Patch Changes - -- 8132a60: feat (provider/openai): support reasoning token usage and max_completion_tokens - -## 0.0.60 - -### Patch Changes - -- Updated dependencies [273f696] - - @ai-sdk/provider-utils@1.0.19 - -## 0.0.59 - -### Patch Changes - -- a0991ec: feat (provider/openai): add o1-preview and o1-mini models - -## 0.0.58 - -### Patch Changes - -- e0c36bd: feat (provider/openai): support image detail - -## 0.0.57 - -### Patch Changes - -- d1aaeae: feat (provider/openai): support ai sdk image download - -## 0.0.56 - -### Patch Changes - -- 03313cd: feat (ai): expose response id, response model, response timestamp in telemetry and api -- Updated dependencies - - @ai-sdk/provider-utils@1.0.18 - - @ai-sdk/provider@0.0.23 - -## 0.0.55 - -### Patch Changes - -- 28cbf2e: fix (provider/openai): support tool call deltas when arguments are sent in the first chunk - -## 0.0.54 - -### Patch Changes - -- 26515cb: feat (ai/provider): introduce ProviderV1 specification -- Updated dependencies [26515cb] - - @ai-sdk/provider@0.0.22 - - @ai-sdk/provider-utils@1.0.17 - -## 0.0.53 - -### Patch Changes - -- Updated dependencies [09f895f] - - @ai-sdk/provider-utils@1.0.16 - -## 0.0.52 - -### Patch Changes - -- d5b6a15: feat (provider/openai): support partial usage information - -## 0.0.51 - -### Patch Changes - -- Updated dependencies [d67fa9c] - - @ai-sdk/provider-utils@1.0.15 - -## 0.0.50 - -### Patch Changes - -- Updated dependencies [f2c025e] - - @ai-sdk/provider@0.0.21 - - @ai-sdk/provider-utils@1.0.14 - -## 0.0.49 - -### Patch Changes - -- f42d9bd: fix (provider/openai): support OpenRouter streaming errors - -## 0.0.48 - -### Patch Changes - -- Updated dependencies [6ac355e] - - @ai-sdk/provider@0.0.20 - - @ai-sdk/provider-utils@1.0.13 - -## 0.0.47 - -### Patch Changes - -- 4ffbaee: fix (provider/openai): fix strict flag for structured outputs with tools -- dd712ac: fix: use FetchFunction type to prevent self-reference -- Updated dependencies [dd712ac] - - @ai-sdk/provider-utils@1.0.12 - -## 0.0.46 - -### Patch Changes - -- 89b18ca: fix (ai/provider): send finish reason 'unknown' by default -- Updated dependencies [dd4a0f5] - - @ai-sdk/provider@0.0.19 - - @ai-sdk/provider-utils@1.0.11 - -## 0.0.45 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@1.0.10 - - @ai-sdk/provider@0.0.18 - -## 0.0.44 - -### Patch Changes - -- 029af4c: feat (ai/core): support schema name & description in generateObject & streamObject -- Updated dependencies [029af4c] - - @ai-sdk/provider@0.0.17 - - @ai-sdk/provider-utils@1.0.9 - -## 0.0.43 - -### Patch Changes - -- d58517b: feat (ai/openai): structured outputs -- c0a73ee: feat (provider/openai): add gpt-4o-2024-08-06 to list of supported models -- Updated dependencies [d58517b] - - @ai-sdk/provider@0.0.16 - - @ai-sdk/provider-utils@1.0.8 - -## 0.0.42 - -### Patch Changes - -- Updated dependencies [96aed25] - - @ai-sdk/provider@0.0.15 - - @ai-sdk/provider-utils@1.0.7 - -## 0.0.41 - -### Patch Changes - -- 7a2eb27: feat (provider/openai): make role nullish to enhance provider support -- Updated dependencies - - @ai-sdk/provider-utils@1.0.6 - -## 0.0.40 - -### Patch Changes - -- Updated dependencies [a8d1c9e9] - - @ai-sdk/provider-utils@1.0.5 - - @ai-sdk/provider@0.0.14 - -## 0.0.39 - -### Patch Changes - -- Updated dependencies [4f88248f] - - @ai-sdk/provider-utils@1.0.4 - -## 0.0.38 - -### Patch Changes - -- 2b9da0f0: feat (core): support stopSequences setting. -- 909b9d27: feat (ai/openai): Support legacy function calls -- a5b58845: feat (core): support topK setting -- 4aa8deb3: feat (provider): support responseFormat setting in provider api -- 13b27ec6: chore (ai/core): remove grammar mode -- Updated dependencies - - @ai-sdk/provider@0.0.13 - - @ai-sdk/provider-utils@1.0.3 - -## 0.0.37 - -### Patch Changes - -- 89947fc5: chore (provider/openai): update model list for type-ahead support - -## 0.0.36 - -### Patch Changes - -- b7290943: feat (ai/core): add token usage to embed and embedMany -- Updated dependencies [b7290943] - - @ai-sdk/provider@0.0.12 - - @ai-sdk/provider-utils@1.0.2 - -## 0.0.35 - -### Patch Changes - -- Updated dependencies [d481729f] - - @ai-sdk/provider-utils@1.0.1 - -## 0.0.34 - -### Patch Changes - -- 5edc6110: feat (ai/core): add custom request header support -- Updated dependencies - - @ai-sdk/provider@0.0.11 - - @ai-sdk/provider-utils@1.0.0 - -## 0.0.33 - -### Patch Changes - -- Updated dependencies [02f6a088] - - @ai-sdk/provider-utils@0.0.16 - -## 0.0.32 - -### Patch Changes - -- 1b37b8b9: fix (@ai-sdk/openai): only send logprobs settings when logprobs are requested - -## 0.0.31 - -### Patch Changes - -- eba071dd: feat (@ai-sdk/azure): add azure openai completion support -- 1ea890fe: feat (@ai-sdk/azure): add azure openai completion support - -## 0.0.30 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@0.0.15 - -## 0.0.29 - -### Patch Changes - -- 4728c37f: feat (core): add text embedding model support to provider registry -- 7910ae84: feat (providers): support custom fetch implementations -- Updated dependencies [7910ae84] - - @ai-sdk/provider-utils@0.0.14 - -## 0.0.28 - -### Patch Changes - -- f9db8fd6: feat (@ai-sdk/openai): add parallelToolCalls setting - -## 0.0.27 - -### Patch Changes - -- fc9552ec: fix (@ai-sdk/azure): allow for nullish delta - -## 0.0.26 - -### Patch Changes - -- 7530f861: fix (@ai-sdk/openai): add internal dist to bundle - -## 0.0.25 - -### Patch Changes - -- 8b1362a7: chore (@ai-sdk/openai): expose models under /internal for reuse in other providers - -## 0.0.24 - -### Patch Changes - -- 0e78960c: fix (@ai-sdk/openai): make function name and arguments nullish - -## 0.0.23 - -### Patch Changes - -- a68fe74a: fix (@ai-sdk/openai): allow null tool_calls value. - -## 0.0.22 - -### Patch Changes - -- Updated dependencies [102ca22f] - - @ai-sdk/provider@0.0.10 - - @ai-sdk/provider-utils@0.0.13 - -## 0.0.21 - -### Patch Changes - -- fca7d026: feat (provider/openai): support streaming tool calls that are sent in one chunk -- Updated dependencies - - @ai-sdk/provider@0.0.9 - - @ai-sdk/provider-utils@0.0.12 - -## 0.0.20 - -### Patch Changes - -- a1d08f3e: fix (provider/openai): handle error chunks when streaming - -## 0.0.19 - -### Patch Changes - -- beb8b739: fix (provider/openai): return unknown finish reasons as unknown - -## 0.0.18 - -### Patch Changes - -- fb42e760: feat (provider/openai): send user message content as text when possible - -## 0.0.17 - -### Patch Changes - -- f39c0dd2: feat (provider): implement toolChoice support -- Updated dependencies [f39c0dd2] - - @ai-sdk/provider@0.0.8 - - @ai-sdk/provider-utils@0.0.11 - -## 0.0.16 - -### Patch Changes - -- 2b18fa11: fix (provider/openai): remove object type validation - -## 0.0.15 - -### Patch Changes - -- 24683b72: fix (providers): Zod is required dependency -- Updated dependencies [8e780288] - - @ai-sdk/provider@0.0.7 - - @ai-sdk/provider-utils@0.0.10 - -## 0.0.14 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@0.0.6 - - @ai-sdk/provider-utils@0.0.9 - -## 0.0.13 - -### Patch Changes - -- 4e3c922: fix (provider/openai): introduce compatibility mode in which "stream_options" are not sent - -## 0.0.12 - -### Patch Changes - -- 6f48839: feat (provider/openai): add gpt-4o to the list of supported models -- 1009594: feat (provider/openai): set stream_options/include_usage to true when streaming -- 0f6bc4e: feat (ai/core): add embed function -- Updated dependencies [0f6bc4e] - - @ai-sdk/provider@0.0.5 - - @ai-sdk/provider-utils@0.0.8 - -## 0.0.11 - -### Patch Changes - -- Updated dependencies [325ca55] - - @ai-sdk/provider@0.0.4 - - @ai-sdk/provider-utils@0.0.7 - -## 0.0.10 - -### Patch Changes - -- Updated dependencies [276f22b] - - @ai-sdk/provider-utils@0.0.6 - -## 0.0.9 - -### Patch Changes - -- Updated dependencies [41d5736] - - @ai-sdk/provider@0.0.3 - - @ai-sdk/provider-utils@0.0.5 - -## 0.0.8 - -### Patch Changes - -- Updated dependencies [56ef84a] - - @ai-sdk/provider-utils@0.0.4 - -## 0.0.7 - -### Patch Changes - -- 0833e19: Allow optional content to support Fireworks function calling. - -## 0.0.6 - -### Patch Changes - -- d6431ae: ai/core: add logprobs support (thanks @SamStenner for the contribution) -- 25f3350: ai/core: add support for getting raw response headers. -- Updated dependencies - - @ai-sdk/provider@0.0.2 - - @ai-sdk/provider-utils@0.0.3 - -## 0.0.5 - -### Patch Changes - -- eb150a6: ai/core: remove scaling of setting values (breaking change). If you were using the temperature, frequency penalty, or presence penalty settings, you need to update the providers and adjust the setting values. -- Updated dependencies [eb150a6] - - @ai-sdk/provider-utils@0.0.2 - - @ai-sdk/provider@0.0.1 - -## 0.0.4 - -### Patch Changes - -- c6fc35b: Add custom header and OpenAI project support. - -## 0.0.3 - -### Patch Changes - -- ab60b18: Simplified model construction by directly calling provider functions. Add create... functions to create provider instances. - -## 0.0.2 - -### Patch Changes - -- 2bff460: Fix build for release. - -## 0.0.1 - -### Patch Changes - -- 7b8791d: Support streams with 'chat.completion' objects. -- 7b8791d: Rename baseUrl to baseURL. Automatically remove trailing slashes. -- Updated dependencies [7b8791d] - - @ai-sdk/provider-utils@0.0.1 diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/LICENSE deleted file mode 100644 index 6c16c29f4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2023 Vercel, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/README.md deleted file mode 100644 index 8e027b8c4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# AI SDK - OpenAI Provider - -The **[OpenAI provider](https://ai-sdk.dev/providers/ai-sdk-providers/openai)** for the [AI SDK](https://ai-sdk.dev/docs) -contains language model support for the OpenAI chat and completion APIs and embedding model support for the OpenAI embeddings API. - -## Setup - -The OpenAI provider is available in the `@ai-sdk/openai` module. You can install it with - -```bash -npm i @ai-sdk/openai -``` - -## Skill for Coding Agents - -If you use coding agents such as Claude Code or Cursor, we highly recommend adding the AI SDK skill to your repository: - -```shell -npx skills add vercel/ai -``` - -## Provider Instance - -You can import the default provider instance `openai` from `@ai-sdk/openai`: - -```ts -import { openai } from '@ai-sdk/openai'; -``` - -## Example - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: openai('gpt-5-mini'), - prompt: 'Write a vegetarian lasagna recipe for 4 people.', -}); -``` - -## Documentation - -Please check out the **[OpenAI provider documentation](https://ai-sdk.dev/providers/ai-sdk-providers/openai)** for more information. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/docs/03-openai.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/docs/03-openai.mdx deleted file mode 100644 index bc673dcf1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/docs/03-openai.mdx +++ /dev/null @@ -1,2540 +0,0 @@ ---- -title: OpenAI -description: Learn how to use the OpenAI provider for the AI SDK. ---- - -# OpenAI Provider - -The [OpenAI](https://openai.com/) provider contains language model support for the OpenAI responses, chat, and completion APIs, as well as embedding model support for the OpenAI embeddings API. - -## Setup - -The OpenAI provider is available in the `@ai-sdk/openai` module. You can install it with - - - - - - - - - - - - - - - - - -## Provider Instance - -You can import the default provider instance `openai` from `@ai-sdk/openai`: - -```ts -import { openai } from '@ai-sdk/openai'; -``` - -If you need a customized setup, you can import `createOpenAI` from `@ai-sdk/openai` and create a provider instance with your settings: - -```ts -import { createOpenAI } from '@ai-sdk/openai'; - -const openai = createOpenAI({ - // custom settings, e.g. - headers: { - 'header-name': 'header-value', - }, -}); -``` - -You can use the following optional settings to customize the OpenAI provider instance: - -- **baseURL** _string_ - - Use a different URL prefix for API calls, e.g. to use proxy servers. - The default prefix is `https://api.openai.com/v1`. - -- **apiKey** _string_ - - API key that is being sent using the `Authorization` header. - It defaults to the `OPENAI_API_KEY` environment variable. - -- **name** _string_ - - The provider name. You can set this when using OpenAI compatible providers - to change the model provider property. Defaults to `openai`. - -- **organization** _string_ - - OpenAI Organization. - -- **project** _string_ - - OpenAI project. - -- **headers** _Record<string,string>_ - - Custom headers to include in the requests. - -- **fetch** _(input: RequestInfo, init?: RequestInit) => Promise<Response>_ - - Custom [fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch) implementation. - Defaults to the global `fetch` function. - You can use it as a middleware to intercept requests, - or to provide a custom fetch implementation for e.g. testing. - -## Language Models - -The OpenAI provider instance is a function that you can invoke to create a language model: - -```ts -const model = openai('gpt-5'); -``` - -It automatically selects the correct API based on the model id. -You can also pass additional settings in the second argument: - -```ts -const model = openai('gpt-5', { - // additional settings -}); -``` - -The available options depend on the API that's automatically chosen for the model (see below). -If you want to explicitly select a specific model API, you can use `.responses`, `.chat`, or `.completion`. - - - Since AI SDK 5, the OpenAI responses API is called by default (unless you - specify e.g. 'openai.chat') - - -### Example - -You can use OpenAI language models to generate text with the `generateText` function: - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: openai('gpt-5'), - prompt: 'Write a vegetarian lasagna recipe for 4 people.', -}); -``` - -OpenAI language models can also be used in the `streamText` function -and support structured data generation with [`Output`](/docs/reference/ai-sdk-core/output) -(see [AI SDK Core](/docs/ai-sdk-core)). - -### Responses Models - -You can use the OpenAI responses API with the `openai(modelId)` or `openai.responses(modelId)` factory methods. It is the default API that is used by the OpenAI provider (since AI SDK 5). - -```ts -const model = openai('gpt-5'); -``` - -Further configuration can be done using OpenAI provider options. -You can validate the provider options using the `OpenAILanguageModelResponsesOptions` type. - -```ts -import { openai, OpenAILanguageModelResponsesOptions } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5'), // or openai.responses('gpt-5') - providerOptions: { - openai: { - parallelToolCalls: false, - store: false, - user: 'user_123', - // ... - } satisfies OpenAILanguageModelResponsesOptions, - }, - // ... -}); -``` - -The following provider options are available: - -- **parallelToolCalls** _boolean_ - Whether to use parallel tool calls. Defaults to `true`. - -- **store** _boolean_ - - Whether to store the generation. Defaults to `true`. - -- **maxToolCalls** _integer_ - The maximum number of total calls to built-in tools that can be processed in a response. - This maximum number applies across all built-in tool calls, not per individual tool. - Any further attempts to call a tool by the model will be ignored. - -- **metadata** _Record<string, string>_ - Additional metadata to store with the generation. - -- **conversation** _string_ - The ID of the OpenAI Conversation to continue. - You must create a conversation first via the [OpenAI API](https://platform.openai.com/docs/api-reference/conversations/create). - Cannot be used in conjunction with `previousResponseId`. - Defaults to `undefined`. - -- **previousResponseId** _string_ - The ID of the previous response. You can use it to continue a conversation. Defaults to `undefined`. - -- **instructions** _string_ - Instructions for the model. - They can be used to change the system or developer message when continuing a conversation using the `previousResponseId` option. - Defaults to `undefined`. - -- **logprobs** _boolean | number_ - Return the log probabilities of the tokens. Including logprobs will increase the response size and can slow down response times. However, it can be useful to better understand how the model is behaving. Setting to `true` returns the log probabilities of the tokens that were generated. Setting to a number (1-20) returns the log probabilities of the top n tokens that were generated. - -- **user** _string_ - A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. Defaults to `undefined`. - -- **reasoningEffort** _'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh'_ - Reasoning effort for reasoning models. Defaults to `medium`. If you use `providerOptions` to set the `reasoningEffort` option, this model setting will be ignored. - - - The 'none' type for `reasoningEffort` is only available for OpenAI's GPT-5.1 - models. Also, the 'xhigh' type for `reasoningEffort` is only available for - OpenAI's GPT-5.1-Codex-Max model. Setting `reasoningEffort` to 'none' or - 'xhigh' with unsupported models will result in an error. - - -- **reasoningSummary** _'auto' | 'detailed'_ - Controls whether the model returns its reasoning process. Set to `'auto'` for a condensed summary, `'detailed'` for more comprehensive reasoning. Defaults to `undefined` (no reasoning summaries). When enabled, reasoning summaries appear in the stream as events with type `'reasoning'` and in non-streaming responses within the `reasoning` field. - -- **strictJsonSchema** _boolean_ - Whether to use strict JSON schema validation. Defaults to `true`. - - - OpenAI structured outputs have several - [limitations](https://openai.com/index/introducing-structured-outputs-in-the-api), - in particular around the [supported - schemas](https://platform.openai.com/docs/guides/structured-outputs/supported-schemas), - and are therefore opt-in. For example, optional schema properties are not - supported. You need to change Zod `.nullish()` and `.optional()` to - `.nullable()`. - - -- **serviceTier** _'auto' | 'flex' | 'priority' | 'default'_ - Service tier for the request. Set to 'flex' for 50% cheaper processing - at the cost of increased latency (available for o3, o4-mini, and gpt-5 models). - Set to 'priority' for faster processing with Enterprise access (available for gpt-4, gpt-5, gpt-5-mini, o3, o4-mini; gpt-5-nano is not supported). - - Defaults to 'auto'. - -- **textVerbosity** _'low' | 'medium' | 'high'_ - Controls the verbosity of the model's response. Lower values result in more concise responses, - while higher values result in more verbose responses. Defaults to `'medium'`. - -- **include** _Array<string>_ - Specifies additional content to include in the response. Supported values: - `['file_search_call.results']` for including file search results in responses. - `['message.output_text.logprobs']` for logprobs. - Defaults to `undefined`. - -- **truncation** _string_ - The truncation strategy to use for the model response. - - - Auto: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - - disabled (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. - -- **promptCacheKey** _string_ - A cache key for manual prompt caching control. Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. - -- **promptCacheRetention** _'in_memory' | '24h'_ - The retention policy for the prompt cache. Set to `'24h'` to enable extended prompt caching, which keeps cached prefixes active for up to 24 hours. Defaults to `'in_memory'` for standard prompt caching. Note: `'24h'` is currently only available for the 5.1 series of models. - -- **safetyIdentifier** _string_ - A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user. - -- **systemMessageMode** _'system' | 'developer' | 'remove'_ - Controls the role of the system message when making requests. By default (when omitted), for models that support reasoning the `system` message is automatically converted to a `developer` message. Setting `systemMessageMode` to `system` passes the system message as a system-level instruction; `developer` passes it as a developer message; `remove` omits the system message from the request. - -- **forceReasoning** _boolean_ - Force treating this model as a reasoning model. This is useful for "stealth" reasoning models (e.g. via a custom baseURL) where the model ID is not recognized by the SDK's allowlist. When enabled, the SDK applies reasoning-model parameter compatibility rules and defaults `systemMessageMode` to `developer` unless overridden. - -The OpenAI responses provider also returns provider-specific metadata: - -For Responses models, you can type this metadata using `OpenaiResponsesProviderMetadata`: - -```ts -import { openai, type OpenaiResponsesProviderMetadata } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5'), -}); - -const providerMetadata = result.providerMetadata as - | OpenaiResponsesProviderMetadata - | undefined; - -const { responseId, logprobs, serviceTier } = providerMetadata?.openai ?? {}; - -// responseId can be used to continue a conversation (previousResponseId). -console.log(responseId); -``` - -The following OpenAI-specific metadata may be returned: - -- **responseId** _string | null | undefined_ - The ID of the response. Can be used to continue a conversation. -- **logprobs** _(optional)_ - Log probabilities of output tokens (when enabled). -- **serviceTier** _(optional)_ - Service tier information returned by the API. - -#### Reasoning Output - -For reasoning models like `gpt-5`, you can enable reasoning summaries to see the model's thought process. Different models support different summarizers—for example, `o4-mini` supports detailed summaries. Set `reasoningSummary: "auto"` to automatically receive the richest level available. - -```ts highlight="8-9,16" -import { - openai, - type OpenAILanguageModelResponsesOptions, -} from '@ai-sdk/openai'; -import { streamText } from 'ai'; - -const result = streamText({ - model: openai('gpt-5'), - prompt: 'Tell me about the Mission burrito debate in San Francisco.', - providerOptions: { - openai: { - reasoningSummary: 'detailed', // 'auto' for condensed or 'detailed' for comprehensive - } satisfies OpenAILanguageModelResponsesOptions, - }, -}); - -for await (const part of result.fullStream) { - if (part.type === 'reasoning') { - console.log(`Reasoning: ${part.textDelta}`); - } else if (part.type === 'text-delta') { - process.stdout.write(part.textDelta); - } -} -``` - -For non-streaming calls with `generateText`, the reasoning summaries are available in the `reasoning` field of the response: - -```ts highlight="8-9,13" -import { - openai, - type OpenAILanguageModelResponsesOptions, -} from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5'), - prompt: 'Tell me about the Mission burrito debate in San Francisco.', - providerOptions: { - openai: { - reasoningSummary: 'auto', - } satisfies OpenAILanguageModelResponsesOptions, - }, -}); -console.log('Reasoning:', result.reasoning); -``` - -Learn more about reasoning summaries in the [OpenAI documentation](https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries). - -#### WebSocket Transport - -OpenAI's [WebSocket API](https://developers.openai.com/api/docs/guides/websocket-mode) keeps a persistent connection open, which can significantly -reduce Time-to-First-Byte (TTFB) in agentic workflows with many tool calls. -After the initial connection, subsequent requests skip TCP/TLS/HTTP negotiation entirely. - -The [`ai-sdk-openai-websocket-fetch`](https://www.npmjs.com/package/ai-sdk-openai-websocket-fetch) -package provides a drop-in `fetch` replacement that routes streaming requests -through a persistent WebSocket connection. - - - - - - - - - - - - - - - - -Pass the WebSocket fetch to `createOpenAI` via the `fetch` option: - -```ts highlight="2,6-7,15" -import { createOpenAI } from '@ai-sdk/openai'; -import { createWebSocketFetch } from 'ai-sdk-openai-websocket-fetch'; -import { streamText } from 'ai'; - -// Create a WebSocket-backed fetch instance -const wsFetch = createWebSocketFetch(); -const openai = createOpenAI({ fetch: wsFetch }); - -const result = streamText({ - model: openai('gpt-4.1-mini'), - prompt: 'Hello!', - tools: { - // ... - }, - onFinish: () => wsFetch.close(), // close the WebSocket when done -}); -``` - -The first request will be slower because it must establish the WebSocket connection -(DNS + TCP + TLS + WebSocket upgrade). After that, subsequent steps in a -multi-step tool-calling loop reuse the open connection, resulting in lower TTFB -per step. - - - The WebSocket transport only routes streaming requests to the OpenAI Responses - API (`POST /responses` with `stream: true`) through the WebSocket. All other - requests (non-streaming, embeddings, etc.) fall through to the standard - `fetch` implementation. - - -You can see a live side-by-side comparison of HTTP vs WebSocket streaming performance -in the [demo app](https://github.com/vercel-labs/ai-sdk-openai-websocket). - -#### Verbosity Control - -You can control the length and detail of model responses using the `textVerbosity` parameter: - -```ts -import { - openai, - type OpenAILanguageModelResponsesOptions, -} from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5-mini'), - prompt: 'Write a poem about a boy and his first pet dog.', - providerOptions: { - openai: { - textVerbosity: 'low', // 'low' for concise, 'medium' (default), or 'high' for verbose - } satisfies OpenAILanguageModelResponsesOptions, - }, -}); -``` - -The `textVerbosity` parameter scales output length without changing the underlying prompt: - -- `'low'`: Produces terse, minimal responses -- `'medium'`: Balanced detail (default) -- `'high'`: Verbose responses with comprehensive detail - -#### Web Search Tool - -The OpenAI responses API supports web search through the `openai.tools.webSearch` tool. - -```ts -const result = await generateText({ - model: openai('gpt-5'), - prompt: 'What happened in San Francisco last week?', - tools: { - web_search: openai.tools.webSearch({ - // optional configuration: - externalWebAccess: true, - searchContextSize: 'high', - userLocation: { - type: 'approximate', - city: 'San Francisco', - region: 'California', - }, - filters: { - allowedDomains: ['sfchronicle.com', 'sfgate.com'], - }, - }), - }, - // Force web search tool (optional): - toolChoice: { type: 'tool', toolName: 'web_search' }, -}); - -// URL sources directly from `results` -const sources = result.sources; - -// Or access sources from tool results -for (const toolResult of result.toolResults) { - if (toolResult.toolName === 'web_search') { - console.log('Query:', toolResult.output.action.query); - console.log('Sources:', toolResult.output.sources); - // `sources` is an array of object: { type: 'url', url: string } - } -} -``` - -The web search tool supports the following configuration options: - -- **externalWebAccess** _boolean_ - Whether to use external web access for fetching live content. Defaults to `true`. -- **searchContextSize** _'low' | 'medium' | 'high'_ - Controls the amount of context used for the search. Higher values provide more comprehensive results but may have higher latency and cost. -- **userLocation** - Optional location information to provide geographically relevant results. Includes `type` (always `'approximate'`), `country`, `city`, `region`, and `timezone`. -- **filters** - Optional filter configuration to restrict search results. - - **allowedDomains** _string[]_ - Array of allowed domains for the search. Subdomains of the provided domains are automatically included. - -For detailed information on configuration options see the [OpenAI Web Search Tool documentation](https://platform.openai.com/docs/guides/tools-web-search?api-mode=responses). - -#### File Search Tool - -The OpenAI responses API supports file search through the `openai.tools.fileSearch` tool. - -You can force the use of the file search tool by setting the `toolChoice` parameter to `{ type: 'tool', toolName: 'file_search' }`. - -```ts -const result = await generateText({ - model: openai('gpt-5'), - prompt: 'What does the document say about user authentication?', - tools: { - file_search: openai.tools.fileSearch({ - vectorStoreIds: ['vs_123'], - // configuration below is optional: - maxNumResults: 5, - filters: { - key: 'author', - type: 'eq', - value: 'Jane Smith', - }, - ranking: { - ranker: 'auto', - scoreThreshold: 0.5, - }, - }), - }, - providerOptions: { - openai: { - // optional: include results - include: ['file_search_call.results'], - } satisfies OpenAILanguageModelResponsesOptions, - }, -}); -``` - -The file search tool supports filtering with both comparison and compound filters: - -**Comparison filters** - Filter by a single attribute: - -- `eq` - Equal to -- `ne` - Not equal to -- `gt` - Greater than -- `gte` - Greater than or equal to -- `lt` - Less than -- `lte` - Less than or equal to -- `in` - Value is in array -- `nin` - Value is not in array - -```ts -// Single comparison filter -filters: { key: 'year', type: 'gte', value: 2023 } - -// Filter with array values -filters: { key: 'status', type: 'in', value: ['published', 'reviewed'] } -``` - -**Compound filters** - Combine multiple filters with `and` or `or`: - -```ts -// Compound filter with AND -filters: { - type: 'and', - filters: [ - { key: 'author', type: 'eq', value: 'Jane Smith' }, - { key: 'year', type: 'gte', value: 2023 }, - ], -} - -// Compound filter with OR -filters: { - type: 'or', - filters: [ - { key: 'department', type: 'eq', value: 'Engineering' }, - { key: 'department', type: 'eq', value: 'Research' }, - ], -} -``` - -#### Image Generation Tool - -OpenAI's Responses API supports multi-modal image generation as a provider-defined tool. -Availability is restricted to specific models (for example, `gpt-5` variants). - -You can use the image tool with either `generateText` or `streamText`: - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5'), - prompt: - 'Generate an image of an echidna swimming across the Mozambique channel.', - tools: { - image_generation: openai.tools.imageGeneration({ outputFormat: 'webp' }), - }, -}); - -for (const toolResult of result.staticToolResults) { - if (toolResult.toolName === 'image_generation') { - const base64Image = toolResult.output.result; - } -} -``` - -```ts -import { openai } from '@ai-sdk/openai'; -import { streamText } from 'ai'; - -const result = streamText({ - model: openai('gpt-5'), - prompt: - 'Generate an image of an echidna swimming across the Mozambique channel.', - tools: { - image_generation: openai.tools.imageGeneration({ - outputFormat: 'webp', - quality: 'low', - }), - }, -}); - -for await (const part of result.fullStream) { - if (part.type == 'tool-result' && !part.dynamic) { - const base64Image = part.output.result; - } -} -``` - - - When you set `store: false`, then previously generated images will not be - accessible by the model. We recommend using the image generation tool without - setting `store: false`. - - -For complete details on model availability, image quality controls, supported sizes, and tool-specific parameters, -refer to the OpenAI documentation: - -- Image generation overview and models: [OpenAI Image Generation](https://platform.openai.com/docs/guides/image-generation) -- Image generation tool parameters (background, size, quality, format, etc.): [Image Generation Tool Options](https://platform.openai.com/docs/guides/tools-image-generation#tool-options) - -#### Code Interpreter Tool - -The OpenAI responses API supports the code interpreter tool through the `openai.tools.codeInterpreter` tool. -This allows models to write and execute Python code. - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5'), - prompt: 'Write and run Python code to calculate the factorial of 10', - tools: { - code_interpreter: openai.tools.codeInterpreter({ - // optional configuration: - container: { - fileIds: ['file-123', 'file-456'], // optional file IDs to make available - }, - }), - }, -}); -``` - -The code interpreter tool can be configured with: - -- **container**: Either a container ID string or an object with `fileIds` to specify uploaded files that should be available to the code interpreter - - - When working with files generated by the Code Interpreter, reference - information can be obtained from both [annotations in Text - Parts](#typed-providermetadata-in-text-parts) and [`providerMetadata` in - Source Document Parts](#typed-providermetadata-in-source-document-parts). - - -#### MCP Tool - -The OpenAI responses API supports connecting to [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers through the `openai.tools.mcp` tool. This allows models to call tools exposed by remote MCP servers or service connectors. - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5'), - prompt: 'Search the web for the latest news about AI developments', - tools: { - mcp: openai.tools.mcp({ - serverLabel: 'web-search', - serverUrl: 'https://mcp.exa.ai/mcp', - serverDescription: 'A web-search API for AI agents', - }), - }, -}); -``` - -The MCP tool can be configured with: - -- **serverLabel** _string_ (required) - - A label to identify the MCP server. This label is used in tool calls to distinguish between multiple MCP servers. - -- **serverUrl** _string_ (required if `connectorId` is not provided) - - The URL for the MCP server. Either `serverUrl` or `connectorId` must be provided. - -- **connectorId** _string_ (required if `serverUrl` is not provided) - - Identifier for a service connector. Either `serverUrl` or `connectorId` must be provided. - -- **serverDescription** _string_ (optional) - - Optional description of the MCP server that helps the model understand its purpose. - -- **allowedTools** _string[] | object_ (optional) - - Controls which tools from the MCP server are available. Can be: - - - An array of tool names: `['tool1', 'tool2']` - - An object with filters: - ```ts - { - readOnly: true, // Only allow read-only tools - toolNames: ['tool1', 'tool2'] // Specific tool names - } - ``` - -- **authorization** _string_ (optional) - - OAuth access token for authenticating with the MCP server or connector. - -- **headers** _Record<string, string>_ (optional) - - Optional HTTP headers to include in requests to the MCP server. - -- **requireApproval** _'always' | 'never' | object_ (optional) - - Controls which MCP tool calls require user approval before execution. Can be: - - - `'always'`: All MCP tool calls require approval - - `'never'`: No MCP tool calls require approval (default) - - An object with filters: - ```ts - { - never: { - toolNames: ['safe_tool', 'another_safe_tool']; // Skip approval for these tools - } - } - ``` - - When approval is required, the model will return a `tool-approval-request` content part that you can use to prompt the user for approval. See [Human in the Loop](/cookbook/next/human-in-the-loop) for more details on implementing approval workflows. - - - When `requireApproval` is not set, tool calls are approved by default. Be sure - to connect to only trusted MCP servers, who you trust to share your data with. - - - - The OpenAI MCP tool is different from the general MCP client approach - documented in [MCP Tools](/docs/ai-sdk-core/mcp-tools). The OpenAI MCP tool is - a built-in provider-defined tool that allows OpenAI models to directly connect - to MCP servers, while the general MCP client requires you to convert MCP tools - to AI SDK tools first. - - -#### Local Shell Tool - -The OpenAI responses API support the local shell tool for Codex models through the `openai.tools.localShell` tool. -Local shell is a tool that allows agents to run shell commands locally on a machine you or the user provides. - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai.responses('gpt-5-codex'), - tools: { - local_shell: openai.tools.localShell({ - execute: async ({ action }) => { - // ... your implementation, e.g. sandbox access ... - return { output: stdout }; - }, - }), - }, - prompt: 'List the files in my home directory.', - stopWhen: stepCountIs(2), -}); -``` - -#### Shell Tool - -The OpenAI Responses API supports the shell tool through the `openai.tools.shell` tool. -The shell tool allows running bash commands and interacting with a command line. -The model proposes shell commands; your integration executes them and returns the outputs. - - - Running arbitrary shell commands can be dangerous. Always sandbox execution or - add strict allow-/deny-lists before forwarding a command to the system shell. - - -The shell tool supports three environment modes that control where commands are executed: - -##### Local Execution (default) - -When no `environment` is specified (or `type: 'local'` is used), commands are executed locally via your `execute` callback: - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5.2'), - tools: { - shell: openai.tools.shell({ - execute: async ({ action }) => { - // ... your implementation, e.g. sandbox access ... - return { output: results }; - }, - }), - }, - prompt: 'List the files in the current directory and show disk usage.', -}); -``` - -##### Hosted Container (auto) - -Set `environment.type` to `'containerAuto'` to run commands in an OpenAI-hosted container. No `execute` callback is needed — OpenAI handles execution server-side: - -```ts -const result = await generateText({ - model: openai('gpt-5.2'), - tools: { - shell: openai.tools.shell({ - environment: { - type: 'containerAuto', - // optional configuration: - memoryLimit: '4g', - fileIds: ['file-abc123'], - networkPolicy: { - type: 'allowlist', - allowedDomains: ['example.com'], - }, - }, - }), - }, - prompt: 'Install numpy and compute the eigenvalues of a 3x3 matrix.', -}); -``` - -The `containerAuto` environment supports: - -- **fileIds** _string[]_ - File IDs to make available in the container -- **memoryLimit** _'1g' | '4g' | '16g' | '64g'_ - Memory limit for the container -- **networkPolicy** - Network access policy: - - `{ type: 'disabled' }` — no network access - - `{ type: 'allowlist', allowedDomains: string[], domainSecrets?: Array<{ domain, name, value }> }` — allow specific domains with optional secrets - -##### Existing Container Reference - -Set `environment.type` to `'containerReference'` to use an existing container by ID: - -```ts -const result = await generateText({ - model: openai('gpt-5.2'), - tools: { - shell: openai.tools.shell({ - environment: { - type: 'containerReference', - containerId: 'cntr_abc123', - }, - }), - }, - prompt: 'Check the status of running processes.', -}); -``` - -##### Execute Callback - -For local execution (default or `type: 'local'`), your execute function must return an output array with results for each command: - -- **stdout** _string_ - Standard output from the command -- **stderr** _string_ - Standard error from the command -- **outcome** - Either `{ type: 'timeout' }` or `{ type: 'exit', exitCode: number }` - -##### Skills - -[Skills](https://platform.openai.com/docs/guides/tools-skills) are versioned bundles of files with a `SKILL.md` manifest that extend the shell tool's capabilities. They can be attached to both `containerAuto` and `local` environments. - -**Container skills** support two formats — by reference (for skills uploaded to OpenAI) or inline (as a base64-encoded zip): - -```ts -const result = await generateText({ - model: openai('gpt-5.2'), - tools: { - shell: openai.tools.shell({ - environment: { - type: 'containerAuto', - skills: [ - // By reference: - { type: 'skillReference', skillId: 'skill_abc123' }, - // Or inline: - { - type: 'inline', - name: 'my-skill', - description: 'What this skill does', - source: { - type: 'base64', - mediaType: 'application/zip', - data: readFileSync('./my-skill.zip').toString('base64'), - }, - }, - ], - }, - }), - }, - prompt: 'Use the skill to solve this problem.', -}); -``` - -**Local skills** point to a directory on disk containing a `SKILL.md` file: - -```ts -const result = await generateText({ - model: openai('gpt-5.2'), - tools: { - shell: openai.tools.shell({ - execute: async ({ action }) => { - // ... your local execution implementation ... - return { output: results }; - }, - environment: { - type: 'local', - skills: [ - { - name: 'my-skill', - description: 'What this skill does', - path: resolve('path/to/skill-directory'), - }, - ], - }, - }), - }, - prompt: 'Use the skill to solve this problem.', - stopWhen: stepCountIs(5), -}); -``` - -For more details on creating skills, see the [OpenAI Skills documentation](https://platform.openai.com/docs/guides/tools-skills). - -#### Apply Patch Tool - -The OpenAI Responses API supports the apply patch tool for GPT-5.1 models through the `openai.tools.applyPatch` tool. -The apply patch tool lets the model create, update, and delete files in your codebase using structured diffs. -Instead of just suggesting edits, the model emits patch operations that your application applies and reports back on, -enabling iterative, multi-step code editing workflows. - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText, stepCountIs } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5.1'), - tools: { - apply_patch: openai.tools.applyPatch({ - execute: async ({ callId, operation }) => { - // ... your implementation for applying the diffs. - }, - }), - }, - prompt: 'Create a python file that calculates the factorial of a number', - stopWhen: stepCountIs(5), -}); -``` - -Your execute function must return: - -- **status** _'completed' | 'failed'_ - Whether the patch was applied successfully -- **output** _string_ (optional) - Human-readable log text (e.g., results or error messages) - -#### Tool Search - -Tool search allows the model to dynamically search for and load tools into context as needed, -rather than loading all tool definitions up front. This can reduce token usage, cost, and latency -when you have many tools. Mark the tools you want to make searchable with `deferLoading: true` -in their `providerOptions`. - -There are two execution modes: - -- **Server-executed (hosted):** OpenAI searches across the deferred tools declared in the request and returns the loaded subset in the same response. No extra round-trip is needed. -- **Client-executed:** The model emits a `tool_search_call`, your application performs the lookup, and you return the matching tools via the `execute` callback. - -##### Server-Executed (Hosted) Tool Search - -Use hosted tool search when the candidate tools are already known at request time. -Add `openai.tools.toolSearch()` with no arguments and mark your tools with `deferLoading: true`: - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText, tool, stepCountIs } from 'ai'; -import { z } from 'zod'; - -const result = await generateText({ - model: openai.responses('gpt-5.4'), - prompt: 'What is the weather in San Francisco?', - stopWhen: stepCountIs(10), - tools: { - toolSearch: openai.tools.toolSearch(), - - get_weather: tool({ - description: 'Get the current weather at a specific location', - inputSchema: z.object({ - location: z.string(), - unit: z.enum(['celsius', 'fahrenheit']), - }), - execute: async ({ location, unit }) => ({ - location, - temperature: unit === 'celsius' ? 18 : 64, - }), - providerOptions: { - openai: { deferLoading: true }, - }, - }), - - search_files: tool({ - description: 'Search through files in the workspace', - inputSchema: z.object({ query: z.string() }), - execute: async ({ query }) => ({ - results: [`Found 3 files matching "${query}"`], - }), - providerOptions: { - openai: { deferLoading: true }, - }, - }), - }, -}); -``` - -In hosted mode, the model internally searches the deferred tools, loads the relevant ones, and -proceeds to call them — all within a single response. The `tool_search_call` and -`tool_search_output` items appear in the response with `execution: 'server'` and `call_id: null`. - -##### Client-Executed Tool Search - -Use client-executed tool search when tool discovery depends on runtime state — for example, -tools that vary per tenant, project, or external system. Pass `execution: 'client'` along with -a `description`, `parameters` schema, and an `execute` callback: - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText, tool, stepCountIs } from 'ai'; -import { z } from 'zod'; - -const result = await generateText({ - model: openai.responses('gpt-5.4'), - prompt: 'What is the weather in San Francisco?', - stopWhen: stepCountIs(10), - tools: { - toolSearch: openai.tools.toolSearch({ - execution: 'client', - description: 'Search for available tools based on what the user needs.', - parameters: { - type: 'object', - properties: { - goal: { - type: 'string', - description: 'What the user is trying to accomplish', - }, - }, - required: ['goal'], - additionalProperties: false, - }, - execute: async ({ arguments: args }) => { - // Your custom tool discovery logic here. - // Return the tools that match the search goal. - return { - tools: [ - { - type: 'function', - name: 'get_weather', - description: 'Get the current weather at a specific location', - deferLoading: true, - parameters: { - type: 'object', - properties: { - location: { type: 'string' }, - }, - required: ['location'], - additionalProperties: false, - }, - }, - ], - }; - }, - }), - - get_weather: tool({ - description: 'Get the current weather at a specific location', - inputSchema: z.object({ location: z.string() }), - execute: async ({ location }) => ({ - location, - temperature: 64, - condition: 'Partly cloudy', - }), - providerOptions: { - openai: { deferLoading: true }, - }, - }), - }, -}); -``` - -In client mode, the flow spans two steps: - -1. **Step 1:** The model emits a `tool_search_call` with `execution: 'client'` and a non-null `call_id`. The SDK calls your `execute` callback with the search arguments. Your callback returns the discovered tools. -2. **Step 2:** The SDK sends the `tool_search_output` (with the matching `call_id`) back to the model. The model can now call the loaded tools as normal function calls. - -For more details, see the [OpenAI Tool Search documentation](https://platform.openai.com/docs/guides/tools-tool-search). - -#### Custom Tool - -The OpenAI Responses API supports -[custom tools](https://developers.openai.com/api/docs/guides/function-calling/#custom-tools) -through the `openai.tools.customTool` tool. -Custom tools return a raw string instead of JSON, optionally constrained to a grammar -(regex or Lark syntax). This makes them useful for generating structured text like -SQL queries, code snippets, or any output that must match a specific pattern. - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText, stepCountIs } from 'ai'; - -const result = await generateText({ - model: openai.responses('gpt-5.2-codex'), - tools: { - write_sql: openai.tools.customTool({ - name: 'write_sql', - description: 'Write a SQL SELECT query to answer the user question.', - format: { - type: 'grammar', - syntax: 'regex', - definition: 'SELECT .+', - }, - execute: async input => { - // input is a raw string matching the grammar, e.g. "SELECT * FROM users WHERE age > 25" - const rows = await db.query(input); - return JSON.stringify(rows); - }, - }), - }, - toolChoice: 'required', - prompt: 'Write a SQL query to get all users older than 25.', - stopWhen: stepCountIs(3), -}); -``` - -Custom tools also work with `streamText`: - -```ts -import { openai } from '@ai-sdk/openai'; -import { streamText } from 'ai'; - -const result = streamText({ - model: openai.responses('gpt-5.2-codex'), - tools: { - write_sql: openai.tools.customTool({ - name: 'write_sql', - description: 'Write a SQL SELECT query to answer the user question.', - format: { - type: 'grammar', - syntax: 'regex', - definition: 'SELECT .+', - }, - }), - }, - toolChoice: 'required', - prompt: 'Write a SQL query to get all users older than 25.', -}); - -for await (const chunk of result.fullStream) { - if (chunk.type === 'tool-call') { - console.log(`Tool: ${chunk.toolName}`); - console.log(`Input: ${chunk.input}`); - } -} -``` - -The custom tool can be configured with: - -- **name** _string_ (required) - The name of the custom tool. Used to identify the tool in tool calls. -- **description** _string_ (optional) - A description of what the tool does, to help the model understand when to use it. -- **format** _object_ (optional) - The output format constraint. Omit for unconstrained text output. - - **type** _'grammar' | 'text'_ - The format type. Use `'grammar'` for constrained output or `'text'` for explicit unconstrained text. - - **syntax** _'regex' | 'lark'_ - (grammar only) The grammar syntax. Use `'regex'` for regular expression patterns or `'lark'` for [Lark parser grammar](https://lark-parser.readthedocs.io/). - - **definition** _string_ - (grammar only) The grammar definition string (a regex pattern or Lark grammar). -- **execute** _function_ (optional) - An async function that receives the raw string input and returns a string result. Enables multi-turn tool calling. - -#### Image Inputs - -The OpenAI Responses API supports Image inputs for appropriate models. -You can pass Image files as part of the message content using the 'image' type: - -```ts -const result = await generateText({ - model: openai('gpt-5'), - messages: [ - { - role: 'user', - content: [ - { - type: 'text', - text: 'Please describe the image.', - }, - { - type: 'image', - image: readFileSync('./data/image.png'), - }, - ], - }, - ], -}); -``` - -The model will have access to the image and will respond to questions about it. -The image should be passed using the `image` field. - -You can also pass a file-id from the OpenAI Files API. - -```ts -{ - type: 'image', - image: 'file-8EFBcWHsQxZV7YGezBC1fq' -} -``` - -You can also pass the URL of an image. - -```ts -{ - type: 'image', - image: 'https://sample.edu/image.png', -} -``` - -#### PDF Inputs - -The OpenAI Responses API supports reading PDF files. -You can pass PDF files as part of the message content using the `file` type: - -```ts -const result = await generateText({ - model: openai('gpt-5'), - messages: [ - { - role: 'user', - content: [ - { - type: 'text', - text: 'What is an embedding model?', - }, - { - type: 'file', - data: readFileSync('./data/ai.pdf'), - mediaType: 'application/pdf', - filename: 'ai.pdf', // optional - }, - ], - }, - ], -}); -``` - -You can also pass a file-id from the OpenAI Files API. - -```ts -{ - type: 'file', - data: 'file-8EFBcWHsQxZV7YGezBC1fq', - mediaType: 'application/pdf', -} -``` - -You can also pass the URL of a pdf. - -```ts -{ - type: 'file', - data: 'https://sample.edu/example.pdf', - mediaType: 'application/pdf', - filename: 'ai.pdf', // optional -} -``` - -The model will have access to the contents of the PDF file and -respond to questions about it. -The PDF file should be passed using the `data` field, -and the `mediaType` should be set to `'application/pdf'`. - -#### Structured Outputs - -The OpenAI Responses API supports structured outputs. You can use `generateText` or `streamText` with [`Output`](/docs/reference/ai-sdk-core/output) to enforce structured outputs. - -```ts -const result = await generateText({ - model: openai('gpt-4.1'), - output: Output.object({ - schema: z.object({ - recipe: z.object({ - name: z.string(), - ingredients: z.array( - z.object({ - name: z.string(), - amount: z.string(), - }), - ), - steps: z.array(z.string()), - }), - }), - }), - prompt: 'Generate a lasagna recipe.', -}); -``` - -#### Typed providerMetadata in Text Parts - -When using the OpenAI Responses API, the SDK attaches OpenAI-specific metadata to output parts via `providerMetadata`. - -This metadata can be used on the client side for tasks such as rendering citations or downloading files generated by the Code Interpreter. -To enable type-safe handling of this metadata, the AI SDK exports dedicated TypeScript types. - -For text parts, when `part.type === 'text'`, the `providerMetadata` is provided in the form of `OpenaiResponsesTextProviderMetadata`. - -This metadata includes the following fields: - -- `itemId` - The ID of the output item in the Responses API. -- `annotations` (optional) - An array of annotation objects generated by the model. - If no annotations are present, this property itself may be omitted (`undefined`). - - Each element in `annotations` is a discriminated union with a required `type` field. Supported types include, for example: - - - `url_citation` - - `file_citation` - - `container_file_citation` - - `file_path` - - These annotations directly correspond to the annotation objects defined by the Responses API and can be used for inline reference rendering or output analysis. - For details, see the official OpenAI documentation: - [Responses API – output text annotations](https://platform.openai.com/docs/api-reference/responses/object?lang=javascript#responses-object-output-output_message-content-output_text-annotations). - -```ts -import { - openai, - type OpenaiResponsesTextProviderMetadata, -} from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-4.1-mini'), - prompt: - 'Create a program that generates five random numbers between 1 and 100 with two decimal places, and show me the execution results. Also save the result to a file.', - tools: { - code_interpreter: openai.tools.codeInterpreter(), - web_search: openai.tools.webSearch(), - file_search: openai.tools.fileSearch({ vectorStoreIds: ['vs_1234'] }), // requires a configured vector store - }, -}); - -for (const part of result.content) { - if (part.type === 'text') { - const providerMetadata = part.providerMetadata as - | OpenaiResponsesTextProviderMetadata - | undefined; - if (!providerMetadata) continue; - const { itemId: _itemId, annotations } = providerMetadata.openai; - - if (!annotations) continue; - for (const annotation of annotations) { - switch (annotation.type) { - case 'url_citation': - // url_citation is returned from web_search and provides: - // properties: type, url, title, start_index and end_index - break; - case 'file_citation': - // file_citation is returned from file_search and provides: - // properties: type, file_id, filename and index - break; - case 'container_file_citation': - // container_file_citation is returned from code_interpreter and provides: - // properties: type, container_id, file_id, filename, start_index and end_index - break; - case 'file_path': - // file_path provides: - // properties: type, file_id and index - break; - default: { - const _exhaustiveCheck: never = annotation; - throw new Error( - `Unhandled annotation: ${JSON.stringify(_exhaustiveCheck)}`, - ); - } - } - } - } -} -``` - - - When implementing file downloads for files generated by the Code Interpreter, - the `container_id` and `file_id` available in `providerMetadata` can be used - to retrieve the file content. For details, see the [Retrieve container file - content](https://platform.openai.com/docs/api-reference/container-files/retrieveContainerFileContent) - API. - - -#### Typed providerMetadata in Reasoning Parts - -When using the OpenAI Responses API, reasoning output parts can include provider metadata. -To handle this metadata in a type-safe way, use `OpenaiResponsesReasoningProviderMetadata`. - -For reasoning parts, when `part.type === 'reasoning'`, the `providerMetadata` is provided in the form of `OpenaiResponsesReasoningProviderMetadata`. - -This metadata includes the following fields: - -- `itemId` - The ID of the reasoning item in the Responses API. -- `reasoningEncryptedContent` (optional) - Encrypted reasoning content (only returned when requested via `include: ['reasoning.encrypted_content']`). - -```ts -import { - openai, - type OpenaiResponsesReasoningProviderMetadata, - type OpenAILanguageModelResponsesOptions, -} from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5'), - prompt: 'How many "r"s are in the word "strawberry"?', - providerOptions: { - openai: { - store: false, - include: ['reasoning.encrypted_content'], - } satisfies OpenAILanguageModelResponsesOptions, - }, -}); - -for (const part of result.content) { - if (part.type === 'reasoning') { - const providerMetadata = part.providerMetadata as - | OpenaiResponsesReasoningProviderMetadata - | undefined; - - const { itemId, reasoningEncryptedContent } = - providerMetadata?.openai ?? {}; - console.log(itemId, reasoningEncryptedContent); - } -} -``` - -#### Typed providerMetadata in Source Document Parts - -For source document parts, when `part.type === 'source'` and `sourceType === 'document'`, the `providerMetadata` is provided as `OpenaiResponsesSourceDocumentProviderMetadata`. - -This metadata is also a discriminated union with a required `type` field. Supported types include: - -- `file_citation` -- `container_file_citation` -- `file_path` - -Each type includes the identifiers required to work with the referenced resource, such as `fileId` and `containerId`. - -```ts -import { - openai, - type OpenaiResponsesSourceDocumentProviderMetadata, -} from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-4.1-mini'), - prompt: - 'Create a program that generates five random numbers between 1 and 100 with two decimal places, and show me the execution results. Also save the result to a file.', - tools: { - code_interpreter: openai.tools.codeInterpreter(), - web_search: openai.tools.webSearch(), - file_search: openai.tools.fileSearch({ vectorStoreIds: ['vs_1234'] }), // requires a configured vector store - }, -}); - -for (const part of result.content) { - if (part.type === 'source') { - if (part.sourceType === 'document') { - const providerMetadata = part.providerMetadata as - | OpenaiResponsesSourceDocumentProviderMetadata - | undefined; - if (!providerMetadata) continue; - const annotation = providerMetadata.openai; - switch (annotation.type) { - case 'file_citation': - // file_citation is returned from file_search and provides: - // properties: type, fileId and index - // The filename can be accessed via part.filename. - break; - case 'container_file_citation': - // container_file_citation is returned from code_interpreter and provides: - // properties: type, containerId and fileId - // The filename can be accessed via part.filename. - break; - case 'file_path': - // file_path provides: - // properties: type, fileId and index - break; - default: { - const _exhaustiveCheck: never = annotation; - throw new Error( - `Unhandled annotation: ${JSON.stringify(_exhaustiveCheck)}`, - ); - } - } - } - } -} -``` - - - Annotations in text parts follow the OpenAI Responses API specification and - therefore use snake_case properties (e.g. `file_id`, `container_id`). In - contrast, `providerMetadata` for source document parts is normalized by the - SDK to camelCase (e.g. `fileId`, `containerId`). Fields that depend on the - original text content, such as `start_index` and `end_index`, are omitted, as - are fields like `filename` that are directly available on the source object. - - -### Chat Models - -You can create models that call the [OpenAI chat API](https://platform.openai.com/docs/api-reference/chat) using the `.chat()` factory method. -The first argument is the model id, e.g. `gpt-4`. -The OpenAI chat models support tool calls and some have multi-modal capabilities. - -```ts -const model = openai.chat('gpt-5'); -``` - -OpenAI chat models support also some model specific provider options that are not part of the [standard call settings](/docs/ai-sdk-core/settings). -You can pass them in the `providerOptions` argument: - -```ts -import { openai, type OpenAILanguageModelChatOptions } from '@ai-sdk/openai'; - -const model = openai.chat('gpt-5'); - -await generateText({ - model, - providerOptions: { - openai: { - logitBias: { - // optional likelihood for specific tokens - '50256': -100, - }, - user: 'test-user', // optional unique user identifier - } satisfies OpenAILanguageModelChatOptions, - }, -}); -``` - -The following optional provider options are available for OpenAI chat models: - -- **logitBias** _Record<number, number>_ - - Modifies the likelihood of specified tokens appearing in the completion. - - Accepts a JSON object that maps tokens (specified by their token ID in - the GPT tokenizer) to an associated bias value from -100 to 100. You - can use this tokenizer tool to convert text to token IDs. Mathematically, - the bias is added to the logits generated by the model prior to sampling. - The exact effect will vary per model, but values between -1 and 1 should - decrease or increase likelihood of selection; values like -100 or 100 - should result in a ban or exclusive selection of the relevant token. - - As an example, you can pass `{"50256": -100}` to prevent the token from being generated. - -- **logprobs** _boolean | number_ - - Return the log probabilities of the tokens. Including logprobs will increase - the response size and can slow down response times. However, it can - be useful to better understand how the model is behaving. - - Setting to true will return the log probabilities of the tokens that - were generated. - - Setting to a number will return the log probabilities of the top n - tokens that were generated. - -- **parallelToolCalls** _boolean_ - - Whether to enable parallel function calling during tool use. Defaults to `true`. - -- **user** _string_ - - A unique identifier representing your end-user, which can help OpenAI to - monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids). - -- **reasoningEffort** _'minimal' | 'low' | 'medium' | 'high' | 'xhigh'_ - - Reasoning effort for reasoning models. Defaults to `medium`. If you use - `providerOptions` to set the `reasoningEffort` option, this - model setting will be ignored. - -- **maxCompletionTokens** _number_ - - Maximum number of completion tokens to generate. Useful for reasoning models. - -- **store** _boolean_ - - Whether to enable persistence in Responses API. - -- **metadata** _Record<string, string>_ - - Metadata to associate with the request. - -- **prediction** _Record<string, any>_ - - Parameters for prediction mode. - -- **serviceTier** _'auto' | 'flex' | 'priority' | 'default'_ - - Service tier for the request. Set to 'flex' for 50% cheaper processing - at the cost of increased latency (available for o3, o4-mini, and gpt-5 models). - Set to 'priority' for faster processing with Enterprise access (available for gpt-4, gpt-5, gpt-5-mini, o3, o4-mini; gpt-5-nano is not supported). - - Defaults to 'auto'. - -- **strictJsonSchema** _boolean_ - - Whether to use strict JSON schema validation. - Defaults to `true`. - -- **textVerbosity** _'low' | 'medium' | 'high'_ - - Controls the verbosity of the model's responses. Lower values will result in more concise responses, while higher values will result in more verbose responses. - -- **promptCacheKey** _string_ - - A cache key for manual prompt caching control. Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. - -- **promptCacheRetention** _'in_memory' | '24h'_ - - The retention policy for the prompt cache. Set to `'24h'` to enable extended prompt caching, which keeps cached prefixes active for up to 24 hours. Defaults to `'in_memory'` for standard prompt caching. Note: `'24h'` is currently only available for the 5.1 series of models. - -- **safetyIdentifier** _string_ - - A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user. - -- **systemMessageMode** _'system' | 'developer' | 'remove'_ - - Override the system message mode for this model. If not specified, the mode is automatically determined based on the model. `system` uses the 'system' role for system messages (default for most models); `developer` uses the 'developer' role (used by reasoning models); `remove` removes system messages entirely. - -- **forceReasoning** _boolean_ - - Force treating this model as a reasoning model. This is useful for "stealth" reasoning models (e.g. via a custom baseURL) where the model ID is not recognized by the SDK's allowlist. When enabled, the SDK applies reasoning-model parameter compatibility rules and defaults `systemMessageMode` to `developer` unless overridden. - -#### Reasoning - -OpenAI has introduced the `o1`,`o3`, and `o4` series of [reasoning models](https://platform.openai.com/docs/guides/reasoning). -Currently, `o4-mini`, `o3`, `o3-mini`, and `o1` are available via both the chat and responses APIs. The -model `gpt-5.1-codex-mini` is available only via the [responses API](#responses-models). - -Reasoning models currently only generate text, have several limitations, and are only supported using `generateText` and `streamText`. - -They support additional settings and response metadata: - -- You can use `providerOptions` to set - - - the `reasoningEffort` option (or alternatively the `reasoningEffort` model setting), which determines the amount of reasoning the model performs. - -- You can use response `providerMetadata` to access the number of reasoning tokens that the model generated. - -```ts highlight="4,7-11,17" -import { openai, type OpenAILanguageModelChatOptions } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const { text, usage, providerMetadata } = await generateText({ - model: openai.chat('gpt-5'), - prompt: 'Invent a new holiday and describe its traditions.', - providerOptions: { - openai: { - reasoningEffort: 'low', - } satisfies OpenAILanguageModelChatOptions, - }, -}); - -console.log(text); -console.log('Usage:', { - ...usage, - reasoningTokens: providerMetadata?.openai?.reasoningTokens, -}); -``` - - - System messages are automatically converted to OpenAI developer messages for - reasoning models when supported. - - -- You can control how system messages are handled by providerOptions `systemMessageMode`: - - - `developer`: treat the prompt as a developer message (default for reasoning models). - - `system`: keep the system message as a system-level instruction. - - `remove`: remove the system message from the messages. - -```ts highlight="12" -import { openai, type OpenAILanguageModelChatOptions } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai.chat('gpt-5'), - messages: [ - { role: 'system', content: 'You are a helpful assistant.' }, - { role: 'user', content: 'Tell me a joke.' }, - ], - providerOptions: { - openai: { - systemMessageMode: 'system', - } satisfies OpenAILanguageModelChatOptions, - }, -}); -``` - - - Reasoning models require additional runtime inference to complete their - reasoning phase before generating a response. This introduces longer latency - compared to other models. - - - - `maxOutputTokens` is automatically mapped to `max_completion_tokens` for - reasoning models. - - -#### Strict Structured Outputs - -Strict structured outputs are enabled by default. -You can disable them by setting the `strictJsonSchema` option to `false`. - -```ts highlight="7" -import { openai, OpenAILanguageModelChatOptions } from '@ai-sdk/openai'; -import { generateText, Output } from 'ai'; -import { z } from 'zod'; - -const result = await generateText({ - model: openai.chat('gpt-4o-2024-08-06'), - providerOptions: { - openai: { - strictJsonSchema: false, - } satisfies OpenAILanguageModelChatOptions, - }, - output: Output.object({ - schema: z.object({ - name: z.string(), - ingredients: z.array( - z.object({ - name: z.string(), - amount: z.string(), - }), - ), - steps: z.array(z.string()), - }), - schemaName: 'recipe', - schemaDescription: 'A recipe for lasagna.', - }), - prompt: 'Generate a lasagna recipe.', -}); - -console.log(JSON.stringify(result.output, null, 2)); -``` - - - OpenAI structured outputs have several - [limitations](https://openai.com/index/introducing-structured-outputs-in-the-api), - in particular around the [supported schemas](https://platform.openai.com/docs/guides/structured-outputs/supported-schemas), - and are therefore opt-in. - -For example, optional schema properties are not supported. -You need to change Zod `.nullish()` and `.optional()` to `.nullable()`. - - - -#### Logprobs - -OpenAI provides logprobs information for completion/chat models. -You can access it in the `providerMetadata` object. - -```ts highlight="11" -import { openai, type OpenAILanguageModelChatOptions } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai.chat('gpt-5'), - prompt: 'Write a vegetarian lasagna recipe for 4 people.', - providerOptions: { - openai: { - // this can also be a number, - // refer to logprobs provider options section for more - logprobs: true, - } satisfies OpenAILanguageModelChatOptions, - }, -}); - -const openaiMetadata = (await result.providerMetadata)?.openai; - -const logprobs = openaiMetadata?.logprobs; -``` - -#### Image Support - -The OpenAI Chat API supports Image inputs for appropriate models. -You can pass Image files as part of the message content using the 'image' type: - -```ts -const result = await generateText({ - model: openai.chat('gpt-5'), - messages: [ - { - role: 'user', - content: [ - { - type: 'text', - text: 'Please describe the image.', - }, - { - type: 'image', - image: readFileSync('./data/image.png'), - }, - ], - }, - ], -}); -``` - -The model will have access to the image and will respond to questions about it. -The image should be passed using the `image` field. - -You can also pass the URL of an image. - -```ts -{ - type: 'image', - image: 'https://sample.edu/image.png', -} -``` - -#### PDF support - -The OpenAI Chat API supports reading PDF files. -You can pass PDF files as part of the message content using the `file` type: - -```ts -const result = await generateText({ - model: openai.chat('gpt-5'), - messages: [ - { - role: 'user', - content: [ - { - type: 'text', - text: 'What is an embedding model?', - }, - { - type: 'file', - data: readFileSync('./data/ai.pdf'), - mediaType: 'application/pdf', - filename: 'ai.pdf', // optional - }, - ], - }, - ], -}); -``` - -The model will have access to the contents of the PDF file and -respond to questions about it. -The PDF file should be passed using the `data` field, -and the `mediaType` should be set to `'application/pdf'`. - -You can also pass a file-id from the OpenAI Files API. - -```ts -{ - type: 'file', - data: 'file-8EFBcWHsQxZV7YGezBC1fq', - mediaType: 'application/pdf', -} -``` - -You can also pass the URL of a PDF. - -```ts -{ - type: 'file', - data: 'https://sample.edu/example.pdf', - mediaType: 'application/pdf', - filename: 'ai.pdf', // optional -} -``` - -#### Predicted Outputs - -OpenAI supports [predicted outputs](https://platform.openai.com/docs/guides/latency-optimization#use-predicted-outputs) for `gpt-4o` and `gpt-4o-mini`. -Predicted outputs help you reduce latency by allowing you to specify a base text that the model should modify. -You can enable predicted outputs by adding the `prediction` option to the `providerOptions.openai` object: - -```ts highlight="15-18" -const result = streamText({ - model: openai.chat('gpt-5'), - messages: [ - { - role: 'user', - content: 'Replace the Username property with an Email property.', - }, - { - role: 'user', - content: existingCode, - }, - ], - providerOptions: { - openai: { - prediction: { - type: 'content', - content: existingCode, - }, - } satisfies OpenAILanguageModelChatOptions, - }, -}); -``` - -OpenAI provides usage information for predicted outputs (`acceptedPredictionTokens` and `rejectedPredictionTokens`). -You can access it in the `providerMetadata` object. - -```ts highlight="11" -const openaiMetadata = (await result.providerMetadata)?.openai; - -const acceptedPredictionTokens = openaiMetadata?.acceptedPredictionTokens; -const rejectedPredictionTokens = openaiMetadata?.rejectedPredictionTokens; -``` - - - OpenAI Predicted Outputs have several - [limitations](https://platform.openai.com/docs/guides/predicted-outputs#limitations), - e.g. unsupported API parameters and no tool calling support. - - -#### Image Detail - -You can use the `openai` provider option to set the [image input detail](https://platform.openai.com/docs/guides/images-vision?api-mode=responses#specify-image-input-detail-level) to `high`, `low`, or `auto`: - -```ts highlight="13-16" -const result = await generateText({ - model: openai.chat('gpt-5'), - messages: [ - { - role: 'user', - content: [ - { type: 'text', text: 'Describe the image in detail.' }, - { - type: 'image', - image: - 'https://github.com/vercel/ai/blob/main/examples/ai-functions/data/comic-cat.png?raw=true', - - // OpenAI specific options - image detail: - providerOptions: { - openai: { imageDetail: 'low' }, - }, - }, - ], - }, - ], -}); -``` - - - Because the `UIMessage` type (used by AI SDK UI hooks like `useChat`) does not - support the `providerOptions` property, you can use `convertToModelMessages` - first before passing the messages to functions like `generateText` or - `streamText`. For more details on `providerOptions` usage, see - [here](/docs/foundations/prompts#provider-options). - - -#### Distillation - -OpenAI supports model distillation for some models. -If you want to store a generation for use in the distillation process, you can add the `store` option to the `providerOptions.openai` object. -This will save the generation to the OpenAI platform for later use in distillation. - -```typescript highlight="9-16" -import { openai, type OpenAILanguageModelChatOptions } from '@ai-sdk/openai'; -import { generateText } from 'ai'; -import 'dotenv/config'; - -async function main() { - const { text, usage } = await generateText({ - model: openai.chat('gpt-4o-mini'), - prompt: 'Who worked on the original macintosh?', - providerOptions: { - openai: { - store: true, - metadata: { - custom: 'value', - }, - } satisfies OpenAILanguageModelChatOptions, - }, - }); - - console.log(text); - console.log(); - console.log('Usage:', usage); -} - -main().catch(console.error); -``` - -#### Prompt Caching - -OpenAI has introduced [Prompt Caching](https://platform.openai.com/docs/guides/prompt-caching) for supported models -including `gpt-4o` and `gpt-4o-mini`. - -- Prompt caching is automatically enabled for these models, when the prompt is 1024 tokens or longer. It does - not need to be explicitly enabled. -- You can use response `providerMetadata` to access the number of prompt tokens that were a cache hit. -- Note that caching behavior is dependent on load on OpenAI's infrastructure. Prompt prefixes generally remain in the - cache following 5-10 minutes of inactivity before they are evicted, but during off-peak periods they may persist for up - to an hour. - -```ts highlight="11" -import { openai } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const { text, usage, providerMetadata } = await generateText({ - model: openai.chat('gpt-4o-mini'), - prompt: `A 1024-token or longer prompt...`, -}); - -console.log(`usage:`, { - ...usage, - cachedPromptTokens: providerMetadata?.openai?.cachedPromptTokens, -}); -``` - -To improve cache hit rates, you can manually control caching using the `promptCacheKey` option: - -```ts highlight="7-11" -import { openai, type OpenAILanguageModelChatOptions } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const { text, usage, providerMetadata } = await generateText({ - model: openai.chat('gpt-5'), - prompt: `A 1024-token or longer prompt...`, - providerOptions: { - openai: { - promptCacheKey: 'my-custom-cache-key-123', - } satisfies OpenAILanguageModelChatOptions, - }, -}); - -console.log(`usage:`, { - ...usage, - cachedPromptTokens: providerMetadata?.openai?.cachedPromptTokens, -}); -``` - -For GPT-5.1 models, you can enable extended prompt caching that keeps cached prefixes active for up to 24 hours: - -```ts highlight="7-12" -import { openai, type OpenAILanguageModelChatOptions } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const { text, usage, providerMetadata } = await generateText({ - model: openai.chat('gpt-5.1'), - prompt: `A 1024-token or longer prompt...`, - providerOptions: { - openai: { - promptCacheKey: 'my-custom-cache-key-123', - promptCacheRetention: '24h', // Extended caching for GPT-5.1 - } satisfies OpenAILanguageModelChatOptions, - }, -}); - -console.log(`usage:`, { - ...usage, - cachedPromptTokens: providerMetadata?.openai?.cachedPromptTokens, -}); -``` - -#### Audio Input - -With the `gpt-4o-audio-preview` model, you can pass audio files to the model. - - - The `gpt-4o-audio-preview` model is currently in preview and requires at least - some audio inputs. It will not work with non-audio data. - - -```ts highlight="12-14" -import { openai } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai.chat('gpt-4o-audio-preview'), - messages: [ - { - role: 'user', - content: [ - { type: 'text', text: 'What is the audio saying?' }, - { - type: 'file', - mediaType: 'audio/mpeg', - data: readFileSync('./data/galileo.mp3'), - }, - ], - }, - ], -}); -``` - -### Completion Models - -You can create models that call the [OpenAI completions API](https://platform.openai.com/docs/api-reference/completions) using the `.completion()` factory method. -The first argument is the model id. -Currently only `gpt-3.5-turbo-instruct` is supported. - -```ts -const model = openai.completion('gpt-3.5-turbo-instruct'); -``` - -OpenAI completion models support also some model specific settings that are not part of the [standard call settings](/docs/ai-sdk-core/settings). -You can pass them as an options argument: - -```ts -const model = openai.completion('gpt-3.5-turbo-instruct'); - -await model.doGenerate({ - providerOptions: { - openai: { - echo: true, // optional, echo the prompt in addition to the completion - logitBias: { - // optional likelihood for specific tokens - '50256': -100, - }, - suffix: 'some text', // optional suffix that comes after a completion of inserted text - user: 'test-user', // optional unique user identifier - } satisfies OpenAILanguageModelCompletionOptions, - }, -}); -``` - -The following optional provider options are available for OpenAI completion models: - -- **echo**: _boolean_ - - Echo back the prompt in addition to the completion. - -- **logitBias** _Record<number, number>_ - - Modifies the likelihood of specified tokens appearing in the completion. - - Accepts a JSON object that maps tokens (specified by their token ID in - the GPT tokenizer) to an associated bias value from -100 to 100. You - can use this tokenizer tool to convert text to token IDs. Mathematically, - the bias is added to the logits generated by the model prior to sampling. - The exact effect will vary per model, but values between -1 and 1 should - decrease or increase likelihood of selection; values like -100 or 100 - should result in a ban or exclusive selection of the relevant token. - - As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> - token from being generated. - -- **logprobs** _boolean | number_ - - Return the log probabilities of the tokens. Including logprobs will increase - the response size and can slow down response times. However, it can - be useful to better understand how the model is behaving. - - Setting to true will return the log probabilities of the tokens that - were generated. - - Setting to a number will return the log probabilities of the top n - tokens that were generated. - -- **suffix** _string_ - - The suffix that comes after a completion of inserted text. - -- **user** _string_ - - A unique identifier representing your end-user, which can help OpenAI to - monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids). - -### Model Capabilities - -| Model | Image Input | Audio Input | Object Generation | Tool Usage | -| --------------------- | ------------------- | ------------------- | ------------------- | ------------------- | -| `gpt-5.4-pro` | | | | | -| `gpt-5.4` | | | | | -| `gpt-5.4-mini` | | | | | -| `gpt-5.4-nano` | | | | | -| `gpt-5.3-chat-latest` | | | | | -| `gpt-5.2-pro` | | | | | -| `gpt-5.2-chat-latest` | | | | | -| `gpt-5.2` | | | | | -| `gpt-5.1-codex-mini` | | | | | -| `gpt-5.1-codex` | | | | | -| `gpt-5.1-chat-latest` | | | | | -| `gpt-5.1` | | | | | -| `gpt-5-pro` | | | | | -| `gpt-5` | | | | | -| `gpt-5-mini` | | | | | -| `gpt-5-nano` | | | | | -| `gpt-5-codex` | | | | | -| `gpt-5-chat-latest` | | | | | -| `gpt-4.1` | | | | | -| `gpt-4.1-mini` | | | | | -| `gpt-4.1-nano` | | | | | -| `gpt-4o` | | | | | -| `gpt-4o-mini` | | | | | - - - The table above lists popular models. Please see the [OpenAI - docs](https://platform.openai.com/docs/models) for a full list of available - models. The table above lists popular models. You can also pass any available - provider model ID as a string if needed. - - -## Embedding Models - -You can create models that call the [OpenAI embeddings API](https://platform.openai.com/docs/api-reference/embeddings) -using the `.embedding()` factory method. - -```ts -const model = openai.embedding('text-embedding-3-large'); -``` - -OpenAI embedding models support several additional provider options. -You can pass them as an options argument: - -```ts -import { openai, type OpenAIEmbeddingModelOptions } from '@ai-sdk/openai'; -import { embed } from 'ai'; - -const { embedding } = await embed({ - model: openai.embedding('text-embedding-3-large'), - value: 'sunny day at the beach', - providerOptions: { - openai: { - dimensions: 512, // optional, number of dimensions for the embedding - user: 'test-user', // optional unique user identifier - } satisfies OpenAIEmbeddingModelOptions, - }, -}); -``` - -The following optional provider options are available for OpenAI embedding models: - -- **dimensions**: _number_ - - The number of dimensions the resulting output embeddings should have. - Only supported in text-embedding-3 and later models. - -- **user** _string_ - - A unique identifier representing your end-user, which can help OpenAI to - monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids). - -### Model Capabilities - -| Model | Default Dimensions | Custom Dimensions | -| ------------------------ | ------------------ | ------------------- | -| `text-embedding-3-large` | 3072 | | -| `text-embedding-3-small` | 1536 | | -| `text-embedding-ada-002` | 1536 | | - -## Image Models - -You can create models that call the [OpenAI image generation API](https://platform.openai.com/docs/api-reference/images) -using the `.image()` factory method. - -```ts -const model = openai.image('dall-e-3'); -``` - - - Dall-E models do not support the `aspectRatio` parameter. Use the `size` - parameter instead. - - -### Image Editing - -OpenAI's `gpt-image-1` model supports powerful image editing capabilities. Pass input images via `prompt.images` to transform, combine, or edit existing images. - -#### Basic Image Editing - -Transform an existing image using text prompts: - -```ts -const imageBuffer = readFileSync('./input-image.png'); - -const { images } = await generateImage({ - model: openai.image('gpt-image-1'), - prompt: { - text: 'Turn the cat into a dog but retain the style of the original image', - images: [imageBuffer], - }, -}); -``` - -#### Inpainting with Mask - -Edit specific parts of an image using a mask. Transparent areas in the mask indicate where the image should be edited: - -```ts -const image = readFileSync('./input-image.png'); -const mask = readFileSync('./mask.png'); // Transparent areas = edit regions - -const { images } = await generateImage({ - model: openai.image('gpt-image-1'), - prompt: { - text: 'A sunlit indoor lounge area with a pool containing a flamingo', - images: [image], - mask: mask, - }, -}); -``` - -#### Background Removal - -Remove the background from an image by setting `background` to `transparent`: - -```ts -const imageBuffer = readFileSync('./input-image.png'); - -const { images } = await generateImage({ - model: openai.image('gpt-image-1'), - prompt: { - text: 'do not change anything', - images: [imageBuffer], - }, - providerOptions: { - openai: { - background: 'transparent', - output_format: 'png', - }, - }, -}); -``` - -#### Multi-Image Combining - -Combine multiple reference images into a single output. `gpt-image-1` supports up to 16 input images: - -```ts -const cat = readFileSync('./cat.png'); -const dog = readFileSync('./dog.png'); -const owl = readFileSync('./owl.png'); -const bear = readFileSync('./bear.png'); - -const { images } = await generateImage({ - model: openai.image('gpt-image-1'), - prompt: { - text: 'Combine these animals into a group photo, retaining the original style', - images: [cat, dog, owl, bear], - }, -}); -``` - - - Input images can be provided as `Buffer`, `ArrayBuffer`, `Uint8Array`, or - base64-encoded strings. For `gpt-image-1`, each image should be a `png`, - `webp`, or `jpg` file less than 50MB. - - -### Model Capabilities - -| Model | Sizes | -| ------------------ | ------------------------------- | -| `gpt-image-1.5` | 1024x1024, 1536x1024, 1024x1536 | -| `gpt-image-1-mini` | 1024x1024, 1536x1024, 1024x1536 | -| `gpt-image-1` | 1024x1024, 1536x1024, 1024x1536 | -| `dall-e-3` | 1024x1024, 1792x1024, 1024x1792 | -| `dall-e-2` | 256x256, 512x512, 1024x1024 | - -You can pass optional `providerOptions` to the image model. These are prone to change by OpenAI and are model dependent. For example, the `gpt-image-1` model supports the `quality` option: - -```ts -const { image, providerMetadata } = await generateImage({ - model: openai.image('gpt-image-1.5'), - prompt: 'A salamander at sunrise in a forest pond in the Seychelles.', - providerOptions: { - openai: { quality: 'high' }, - }, -}); -``` - -For more on `generateImage()` see [Image Generation](/docs/ai-sdk-core/image-generation). - -OpenAI's image models return additional metadata in the response that can be -accessed via `providerMetadata.openai`. The following OpenAI-specific metadata -is available: - -- **images** _Array<object>_ - - Array of image-specific metadata. Each image object may contain: - - - `revisedPrompt` _string_ - The revised prompt that was actually used to generate the image (OpenAI may modify your prompt for safety or clarity) - - `created` _number_ - The Unix timestamp (in seconds) of when the image was created - - `size` _string_ - The size of the generated image. One of `1024x1024`, `1024x1536`, or `1536x1024` - - `quality` _string_ - The quality of the generated image. One of `low`, `medium`, or `high` - - `background` _string_ - The background parameter used for the image generation. Either `transparent` or `opaque` - - `outputFormat` _string_ - The output format of the generated image. One of `png`, `webp`, or `jpeg` - -For more information on the available OpenAI image model options, see the [OpenAI API reference](https://platform.openai.com/docs/api-reference/images/create). - -## Transcription Models - -You can create models that call the [OpenAI transcription API](https://platform.openai.com/docs/api-reference/audio/transcribe) -using the `.transcription()` factory method. - -The first argument is the model id e.g. `whisper-1`. - -```ts -const model = openai.transcription('whisper-1'); -``` - -You can also pass additional provider-specific options using the `providerOptions` argument. For example, supplying the input language in ISO-639-1 (e.g. `en`) format will improve accuracy and latency. - -```ts highlight="6" -import { experimental_transcribe as transcribe } from 'ai'; -import { openai, type OpenAITranscriptionModelOptions } from '@ai-sdk/openai'; - -const result = await transcribe({ - model: openai.transcription('whisper-1'), - audio: new Uint8Array([1, 2, 3, 4]), - providerOptions: { - openai: { language: 'en' } satisfies OpenAITranscriptionModelOptions, - }, -}); -``` - -To get word-level timestamps, specify the granularity: - -```ts highlight="8-9" -import { experimental_transcribe as transcribe } from 'ai'; -import { openai, type OpenAITranscriptionModelOptions } from '@ai-sdk/openai'; - -const result = await transcribe({ - model: openai.transcription('whisper-1'), - audio: new Uint8Array([1, 2, 3, 4]), - providerOptions: { - openai: { - //timestampGranularities: ['word'], - timestampGranularities: ['segment'], - } satisfies OpenAITranscriptionModelOptions, - }, -}); - -// Access word-level timestamps -console.log(result.segments); // Array of segments with startSecond/endSecond -``` - -The following provider options are available: - -- **timestampGranularities** _string[]_ - The granularity of the timestamps in the transcription. - Defaults to `['segment']`. - Possible values are `['word']`, `['segment']`, and `['word', 'segment']`. - Note: There is no additional latency for segment timestamps, but generating word timestamps incurs additional latency. - -- **language** _string_ - The language of the input audio. Supplying the input language in ISO-639-1 format (e.g. 'en') will improve accuracy and latency. - Optional. - -- **prompt** _string_ - An optional text to guide the model's style or continue a previous audio segment. The prompt should match the audio language. - Optional. - -- **temperature** _number_ - The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit. - Defaults to 0. - Optional. - -- **include** _string[]_ - Additional information to include in the transcription response. - -### Model Capabilities - -| Model | Transcription | Duration | Segments | Language | -| ------------------------ | ------------------- | ------------------- | ------------------- | ------------------- | -| `whisper-1` | | | | | -| `gpt-4o-mini-transcribe` | | | | | -| `gpt-4o-transcribe` | | | | | - -## Speech Models - -You can create models that call the [OpenAI speech API](https://platform.openai.com/docs/api-reference/audio/speech) -using the `.speech()` factory method. - -The first argument is the model id e.g. `tts-1`. - -```ts -const model = openai.speech('tts-1'); -``` - -The `voice` argument can be set to one of OpenAI's available voices: `alloy`, `ash`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, or `shimmer`. - -```ts highlight="6" -import { experimental_generateSpeech as generateSpeech } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const result = await generateSpeech({ - model: openai.speech('tts-1'), - text: 'Hello, world!', - voice: 'alloy', // OpenAI voice ID -}); -``` - -You can also pass additional provider-specific options using the `providerOptions` argument: - -```ts highlight="7-9" -import { experimental_generateSpeech as generateSpeech } from 'ai'; -import { openai, type OpenAISpeechModelOptions } from '@ai-sdk/openai'; - -const result = await generateSpeech({ - model: openai.speech('tts-1'), - text: 'Hello, world!', - voice: 'alloy', - providerOptions: { - openai: { - speed: 1.2, - } satisfies OpenAISpeechModelOptions, - }, -}); -``` - -- **instructions** _string_ - Control the voice of your generated audio with additional instructions e.g. "Speak in a slow and steady tone". - Does not work with `tts-1` or `tts-1-hd`. - Optional. - -- **speed** _number_ - The speed of the generated audio. - Select a value from 0.25 to 4.0. - Defaults to 1.0. - Optional. - -### Model Capabilities - -| Model | Instructions | -| ----------------- | ------------------- | -| `tts-1` | | -| `tts-1-hd` | | -| `gpt-4o-mini-tts` | | diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/internal.d.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/internal.d.ts deleted file mode 100644 index be034cd88..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/internal.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/internal'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/package.json deleted file mode 100644 index 79bd3f868..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/package.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "@ai-sdk/openai", - "version": "3.0.48", - "license": "Apache-2.0", - "sideEffects": false, - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", - "files": [ - "dist/**/*", - "docs/**/*", - "src", - "!src/**/*.test.ts", - "!src/**/*.test-d.ts", - "!src/**/__snapshots__", - "!src/**/__fixtures__", - "CHANGELOG.md", - "README.md", - "internal.d.ts" - ], - "directories": { - "doc": "./docs" - }, - "exports": { - "./package.json": "./package.json", - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" - }, - "./internal": { - "types": "./dist/internal/index.d.ts", - "import": "./dist/internal/index.mjs", - "module": "./dist/internal/index.mjs", - "require": "./dist/internal/index.js" - } - }, - "dependencies": { - "@ai-sdk/provider": "3.0.8", - "@ai-sdk/provider-utils": "4.0.21" - }, - "devDependencies": { - "@types/node": "20.17.24", - "tsup": "^8", - "typescript": "5.8.3", - "zod": "3.25.76", - "@vercel/ai-tsconfig": "0.0.0", - "@ai-sdk/test-server": "1.0.3" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public" - }, - "homepage": "https://ai-sdk.dev/docs", - "repository": { - "type": "git", - "url": "git+https://github.com/vercel/ai.git" - }, - "bugs": { - "url": "https://github.com/vercel/ai/issues" - }, - "keywords": [ - "ai" - ], - "scripts": { - "build": "pnpm clean && tsup --tsconfig tsconfig.build.json", - "build:watch": "pnpm clean && tsup --watch", - "clean": "del-cli dist docs *.tsbuildinfo", - "type-check": "tsc --build", - "test": "pnpm test:node && pnpm test:edge", - "test:update": "pnpm test:node -u", - "test:watch": "vitest --config vitest.node.config.js", - "test:edge": "vitest --config vitest.edge.config.js --run", - "test:node": "vitest --config vitest.node.config.js --run" - } -} \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/convert-openai-chat-usage.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/convert-openai-chat-usage.ts deleted file mode 100644 index 9e62acd1b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/convert-openai-chat-usage.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { LanguageModelV3Usage } from '@ai-sdk/provider'; - -export type OpenAIChatUsage = { - prompt_tokens?: number | null; - completion_tokens?: number | null; - total_tokens?: number | null; - prompt_tokens_details?: { - cached_tokens?: number | null; - } | null; - completion_tokens_details?: { - reasoning_tokens?: number | null; - accepted_prediction_tokens?: number | null; - rejected_prediction_tokens?: number | null; - } | null; -}; - -export function convertOpenAIChatUsage( - usage: OpenAIChatUsage | undefined | null, -): LanguageModelV3Usage { - if (usage == null) { - return { - inputTokens: { - total: undefined, - noCache: undefined, - cacheRead: undefined, - cacheWrite: undefined, - }, - outputTokens: { - total: undefined, - text: undefined, - reasoning: undefined, - }, - raw: undefined, - }; - } - - const promptTokens = usage.prompt_tokens ?? 0; - const completionTokens = usage.completion_tokens ?? 0; - const cachedTokens = usage.prompt_tokens_details?.cached_tokens ?? 0; - const reasoningTokens = - usage.completion_tokens_details?.reasoning_tokens ?? 0; - - return { - inputTokens: { - total: promptTokens, - noCache: promptTokens - cachedTokens, - cacheRead: cachedTokens, - cacheWrite: undefined, - }, - outputTokens: { - total: completionTokens, - text: completionTokens - reasoningTokens, - reasoning: reasoningTokens, - }, - raw: usage, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/convert-to-openai-chat-messages.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/convert-to-openai-chat-messages.ts deleted file mode 100644 index d6c520b73..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/convert-to-openai-chat-messages.ts +++ /dev/null @@ -1,225 +0,0 @@ -import { - SharedV3Warning, - LanguageModelV3Prompt, - UnsupportedFunctionalityError, -} from '@ai-sdk/provider'; -import { OpenAIChatPrompt } from './openai-chat-prompt'; -import { convertToBase64 } from '@ai-sdk/provider-utils'; - -export function convertToOpenAIChatMessages({ - prompt, - systemMessageMode = 'system', -}: { - prompt: LanguageModelV3Prompt; - systemMessageMode?: 'system' | 'developer' | 'remove'; -}): { - messages: OpenAIChatPrompt; - warnings: Array; -} { - const messages: OpenAIChatPrompt = []; - const warnings: Array = []; - - for (const { role, content } of prompt) { - switch (role) { - case 'system': { - switch (systemMessageMode) { - case 'system': { - messages.push({ role: 'system', content }); - break; - } - case 'developer': { - messages.push({ role: 'developer', content }); - break; - } - case 'remove': { - warnings.push({ - type: 'other', - message: 'system messages are removed for this model', - }); - break; - } - default: { - const _exhaustiveCheck: never = systemMessageMode; - throw new Error( - `Unsupported system message mode: ${_exhaustiveCheck}`, - ); - } - } - break; - } - - case 'user': { - if (content.length === 1 && content[0].type === 'text') { - messages.push({ role: 'user', content: content[0].text }); - break; - } - - messages.push({ - role: 'user', - content: content.map((part, index) => { - switch (part.type) { - case 'text': { - return { type: 'text', text: part.text }; - } - case 'file': { - if (part.mediaType.startsWith('image/')) { - const mediaType = - part.mediaType === 'image/*' - ? 'image/jpeg' - : part.mediaType; - - return { - type: 'image_url', - image_url: { - url: - part.data instanceof URL - ? part.data.toString() - : `data:${mediaType};base64,${convertToBase64(part.data)}`, - - // OpenAI specific extension: image detail - detail: part.providerOptions?.openai?.imageDetail, - }, - }; - } else if (part.mediaType.startsWith('audio/')) { - if (part.data instanceof URL) { - throw new UnsupportedFunctionalityError({ - functionality: 'audio file parts with URLs', - }); - } - - switch (part.mediaType) { - case 'audio/wav': { - return { - type: 'input_audio', - input_audio: { - data: convertToBase64(part.data), - format: 'wav', - }, - }; - } - case 'audio/mp3': - case 'audio/mpeg': { - return { - type: 'input_audio', - input_audio: { - data: convertToBase64(part.data), - format: 'mp3', - }, - }; - } - - default: { - throw new UnsupportedFunctionalityError({ - functionality: `audio content parts with media type ${part.mediaType}`, - }); - } - } - } else if (part.mediaType === 'application/pdf') { - if (part.data instanceof URL) { - throw new UnsupportedFunctionalityError({ - functionality: 'PDF file parts with URLs', - }); - } - - return { - type: 'file', - file: - typeof part.data === 'string' && - part.data.startsWith('file-') - ? { file_id: part.data } - : { - filename: part.filename ?? `part-${index}.pdf`, - file_data: `data:application/pdf;base64,${convertToBase64(part.data)}`, - }, - }; - } else { - throw new UnsupportedFunctionalityError({ - functionality: `file part media type ${part.mediaType}`, - }); - } - } - } - }), - }); - - break; - } - - case 'assistant': { - let text = ''; - const toolCalls: Array<{ - id: string; - type: 'function'; - function: { name: string; arguments: string }; - }> = []; - - for (const part of content) { - switch (part.type) { - case 'text': { - text += part.text; - break; - } - case 'tool-call': { - toolCalls.push({ - id: part.toolCallId, - type: 'function', - function: { - name: part.toolName, - arguments: JSON.stringify(part.input), - }, - }); - break; - } - } - } - - messages.push({ - role: 'assistant', - content: text, - tool_calls: toolCalls.length > 0 ? toolCalls : undefined, - }); - - break; - } - - case 'tool': { - for (const toolResponse of content) { - if (toolResponse.type === 'tool-approval-response') { - continue; - } - const output = toolResponse.output; - - let contentValue: string; - switch (output.type) { - case 'text': - case 'error-text': - contentValue = output.value; - break; - case 'execution-denied': - contentValue = output.reason ?? 'Tool execution denied.'; - break; - case 'content': - case 'json': - case 'error-json': - contentValue = JSON.stringify(output.value); - break; - } - - messages.push({ - role: 'tool', - tool_call_id: toolResponse.toolCallId, - content: contentValue, - }); - } - break; - } - - default: { - const _exhaustiveCheck: never = role; - throw new Error(`Unsupported role: ${_exhaustiveCheck}`); - } - } - } - - return { messages, warnings }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/get-response-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/get-response-metadata.ts deleted file mode 100644 index 7c6ca41fd..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/get-response-metadata.ts +++ /dev/null @@ -1,15 +0,0 @@ -export function getResponseMetadata({ - id, - model, - created, -}: { - id?: string | undefined | null; - created?: number | undefined | null; - model?: string | undefined | null; -}) { - return { - id: id ?? undefined, - modelId: model ?? undefined, - timestamp: created ? new Date(created * 1000) : undefined, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/map-openai-finish-reason.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/map-openai-finish-reason.ts deleted file mode 100644 index f3005bb8d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/map-openai-finish-reason.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { LanguageModelV3FinishReason } from '@ai-sdk/provider'; - -export function mapOpenAIFinishReason( - finishReason: string | null | undefined, -): LanguageModelV3FinishReason['unified'] { - switch (finishReason) { - case 'stop': - return 'stop'; - case 'length': - return 'length'; - case 'content_filter': - return 'content-filter'; - case 'function_call': - case 'tool_calls': - return 'tool-calls'; - default: - return 'other'; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-api.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-api.ts deleted file mode 100644 index 7b634112a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-api.ts +++ /dev/null @@ -1,198 +0,0 @@ -import { JSONSchema7 } from '@ai-sdk/provider'; -import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import { openaiErrorDataSchema } from '../openai-error'; - -export interface OpenAIChatFunctionTool { - type: 'function'; - function: { - name: string; - description: string | undefined; - parameters: JSONSchema7; - strict?: boolean; - }; -} - -export type OpenAIChatToolChoice = - | 'auto' - | 'none' - | 'required' - | { type: 'function'; function: { name: string } }; - -// limited version of the schema, focussed on what is needed for the implementation -// this approach limits breakages when the API changes and increases efficiency -export const openaiChatResponseSchema = lazySchema(() => - zodSchema( - z.object({ - id: z.string().nullish(), - created: z.number().nullish(), - model: z.string().nullish(), - choices: z.array( - z.object({ - message: z.object({ - role: z.literal('assistant').nullish(), - content: z.string().nullish(), - tool_calls: z - .array( - z.object({ - id: z.string().nullish(), - type: z.literal('function'), - function: z.object({ - name: z.string(), - arguments: z.string(), - }), - }), - ) - .nullish(), - annotations: z - .array( - z.object({ - type: z.literal('url_citation'), - url_citation: z.object({ - start_index: z.number(), - end_index: z.number(), - url: z.string(), - title: z.string(), - }), - }), - ) - .nullish(), - }), - index: z.number(), - logprobs: z - .object({ - content: z - .array( - z.object({ - token: z.string(), - logprob: z.number(), - top_logprobs: z.array( - z.object({ - token: z.string(), - logprob: z.number(), - }), - ), - }), - ) - .nullish(), - }) - .nullish(), - finish_reason: z.string().nullish(), - }), - ), - usage: z - .object({ - prompt_tokens: z.number().nullish(), - completion_tokens: z.number().nullish(), - total_tokens: z.number().nullish(), - prompt_tokens_details: z - .object({ - cached_tokens: z.number().nullish(), - }) - .nullish(), - completion_tokens_details: z - .object({ - reasoning_tokens: z.number().nullish(), - accepted_prediction_tokens: z.number().nullish(), - rejected_prediction_tokens: z.number().nullish(), - }) - .nullish(), - }) - .nullish(), - }), - ), -); - -// limited version of the schema, focussed on what is needed for the implementation -// this approach limits breakages when the API changes and increases efficiency -export const openaiChatChunkSchema = lazySchema(() => - zodSchema( - z.union([ - z.object({ - id: z.string().nullish(), - created: z.number().nullish(), - model: z.string().nullish(), - choices: z.array( - z.object({ - delta: z - .object({ - role: z.enum(['assistant']).nullish(), - content: z.string().nullish(), - tool_calls: z - .array( - z.object({ - index: z.number(), - id: z.string().nullish(), - type: z.literal('function').nullish(), - function: z.object({ - name: z.string().nullish(), - arguments: z.string().nullish(), - }), - }), - ) - .nullish(), - annotations: z - .array( - z.object({ - type: z.literal('url_citation'), - url_citation: z.object({ - start_index: z.number(), - end_index: z.number(), - url: z.string(), - title: z.string(), - }), - }), - ) - .nullish(), - }) - .nullish(), - logprobs: z - .object({ - content: z - .array( - z.object({ - token: z.string(), - logprob: z.number(), - top_logprobs: z.array( - z.object({ - token: z.string(), - logprob: z.number(), - }), - ), - }), - ) - .nullish(), - }) - .nullish(), - finish_reason: z.string().nullish(), - index: z.number(), - }), - ), - usage: z - .object({ - prompt_tokens: z.number().nullish(), - completion_tokens: z.number().nullish(), - total_tokens: z.number().nullish(), - prompt_tokens_details: z - .object({ - cached_tokens: z.number().nullish(), - }) - .nullish(), - completion_tokens_details: z - .object({ - reasoning_tokens: z.number().nullish(), - accepted_prediction_tokens: z.number().nullish(), - rejected_prediction_tokens: z.number().nullish(), - }) - .nullish(), - }) - .nullish(), - }), - openaiErrorDataSchema, - ]), - ), -); - -export type OpenAIChatResponse = InferSchema; - -export type OpenAIChatChunk = InferSchema; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-language-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-language-model.ts deleted file mode 100644 index 96077d47c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-language-model.ts +++ /dev/null @@ -1,703 +0,0 @@ -import { - InvalidResponseDataError, - LanguageModelV3, - LanguageModelV3CallOptions, - LanguageModelV3Content, - LanguageModelV3FinishReason, - LanguageModelV3GenerateResult, - LanguageModelV3StreamPart, - LanguageModelV3StreamResult, - SharedV3ProviderMetadata, - SharedV3Warning, -} from '@ai-sdk/provider'; -import { - FetchFunction, - ParseResult, - combineHeaders, - createEventSourceResponseHandler, - createJsonResponseHandler, - generateId, - isParsableJson, - parseProviderOptions, - postJsonToApi, -} from '@ai-sdk/provider-utils'; -import { openaiFailedResponseHandler } from '../openai-error'; -import { getOpenAILanguageModelCapabilities } from '../openai-language-model-capabilities'; -import { - OpenAIChatUsage, - convertOpenAIChatUsage, -} from './convert-openai-chat-usage'; -import { convertToOpenAIChatMessages } from './convert-to-openai-chat-messages'; -import { getResponseMetadata } from './get-response-metadata'; -import { mapOpenAIFinishReason } from './map-openai-finish-reason'; -import { - OpenAIChatChunk, - openaiChatChunkSchema, - openaiChatResponseSchema, -} from './openai-chat-api'; -import { - OpenAIChatModelId, - openaiLanguageModelChatOptions, -} from './openai-chat-options'; -import { prepareChatTools } from './openai-chat-prepare-tools'; - -type OpenAIChatConfig = { - provider: string; - headers: () => Record; - url: (options: { modelId: string; path: string }) => string; - fetch?: FetchFunction; -}; - -export class OpenAIChatLanguageModel implements LanguageModelV3 { - readonly specificationVersion = 'v3'; - - readonly modelId: OpenAIChatModelId; - - readonly supportedUrls = { - 'image/*': [/^https?:\/\/.*$/], - }; - - private readonly config: OpenAIChatConfig; - - constructor(modelId: OpenAIChatModelId, config: OpenAIChatConfig) { - this.modelId = modelId; - this.config = config; - } - - get provider(): string { - return this.config.provider; - } - - private async getArgs({ - prompt, - maxOutputTokens, - temperature, - topP, - topK, - frequencyPenalty, - presencePenalty, - stopSequences, - responseFormat, - seed, - tools, - toolChoice, - providerOptions, - }: LanguageModelV3CallOptions) { - const warnings: SharedV3Warning[] = []; - - // Parse provider options - const openaiOptions = - (await parseProviderOptions({ - provider: 'openai', - providerOptions, - schema: openaiLanguageModelChatOptions, - })) ?? {}; - - const modelCapabilities = getOpenAILanguageModelCapabilities(this.modelId); - const isReasoningModel = - openaiOptions.forceReasoning ?? modelCapabilities.isReasoningModel; - - if (topK != null) { - warnings.push({ type: 'unsupported', feature: 'topK' }); - } - - const { messages, warnings: messageWarnings } = convertToOpenAIChatMessages( - { - prompt, - systemMessageMode: - openaiOptions.systemMessageMode ?? - (isReasoningModel - ? 'developer' - : modelCapabilities.systemMessageMode), - }, - ); - - warnings.push(...messageWarnings); - - const strictJsonSchema = openaiOptions.strictJsonSchema ?? true; - - const baseArgs = { - // model id: - model: this.modelId, - - // model specific settings: - logit_bias: openaiOptions.logitBias, - logprobs: - openaiOptions.logprobs === true || - typeof openaiOptions.logprobs === 'number' - ? true - : undefined, - top_logprobs: - typeof openaiOptions.logprobs === 'number' - ? openaiOptions.logprobs - : typeof openaiOptions.logprobs === 'boolean' - ? openaiOptions.logprobs - ? 0 - : undefined - : undefined, - user: openaiOptions.user, - parallel_tool_calls: openaiOptions.parallelToolCalls, - - // standardized settings: - max_tokens: maxOutputTokens, - temperature, - top_p: topP, - frequency_penalty: frequencyPenalty, - presence_penalty: presencePenalty, - response_format: - responseFormat?.type === 'json' - ? responseFormat.schema != null - ? { - type: 'json_schema', - json_schema: { - schema: responseFormat.schema, - strict: strictJsonSchema, - name: responseFormat.name ?? 'response', - description: responseFormat.description, - }, - } - : { type: 'json_object' } - : undefined, - stop: stopSequences, - seed, - verbosity: openaiOptions.textVerbosity, - - // openai specific settings: - // TODO AI SDK 6: remove, we auto-map maxOutputTokens now - max_completion_tokens: openaiOptions.maxCompletionTokens, - store: openaiOptions.store, - metadata: openaiOptions.metadata, - prediction: openaiOptions.prediction, - reasoning_effort: openaiOptions.reasoningEffort, - service_tier: openaiOptions.serviceTier, - prompt_cache_key: openaiOptions.promptCacheKey, - prompt_cache_retention: openaiOptions.promptCacheRetention, - safety_identifier: openaiOptions.safetyIdentifier, - - // messages: - messages, - }; - - // remove unsupported settings for reasoning models - // see https://platform.openai.com/docs/guides/reasoning#limitations - if (isReasoningModel) { - // when reasoning effort is none, gpt-5.1 models allow temperature, topP, logprobs - // https://platform.openai.com/docs/guides/latest-model#gpt-5-1-parameter-compatibility - if ( - openaiOptions.reasoningEffort !== 'none' || - !modelCapabilities.supportsNonReasoningParameters - ) { - if (baseArgs.temperature != null) { - baseArgs.temperature = undefined; - warnings.push({ - type: 'unsupported', - feature: 'temperature', - details: 'temperature is not supported for reasoning models', - }); - } - if (baseArgs.top_p != null) { - baseArgs.top_p = undefined; - warnings.push({ - type: 'unsupported', - feature: 'topP', - details: 'topP is not supported for reasoning models', - }); - } - if (baseArgs.logprobs != null) { - baseArgs.logprobs = undefined; - warnings.push({ - type: 'other', - message: 'logprobs is not supported for reasoning models', - }); - } - } - - if (baseArgs.frequency_penalty != null) { - baseArgs.frequency_penalty = undefined; - warnings.push({ - type: 'unsupported', - feature: 'frequencyPenalty', - details: 'frequencyPenalty is not supported for reasoning models', - }); - } - if (baseArgs.presence_penalty != null) { - baseArgs.presence_penalty = undefined; - warnings.push({ - type: 'unsupported', - feature: 'presencePenalty', - details: 'presencePenalty is not supported for reasoning models', - }); - } - if (baseArgs.logit_bias != null) { - baseArgs.logit_bias = undefined; - warnings.push({ - type: 'other', - message: 'logitBias is not supported for reasoning models', - }); - } - - if (baseArgs.top_logprobs != null) { - baseArgs.top_logprobs = undefined; - warnings.push({ - type: 'other', - message: 'topLogprobs is not supported for reasoning models', - }); - } - - // reasoning models use max_completion_tokens instead of max_tokens: - if (baseArgs.max_tokens != null) { - if (baseArgs.max_completion_tokens == null) { - baseArgs.max_completion_tokens = baseArgs.max_tokens; - } - baseArgs.max_tokens = undefined; - } - } else if ( - this.modelId.startsWith('gpt-4o-search-preview') || - this.modelId.startsWith('gpt-4o-mini-search-preview') - ) { - if (baseArgs.temperature != null) { - baseArgs.temperature = undefined; - warnings.push({ - type: 'unsupported', - feature: 'temperature', - details: - 'temperature is not supported for the search preview models and has been removed.', - }); - } - } - - // Validate flex processing support - if ( - openaiOptions.serviceTier === 'flex' && - !modelCapabilities.supportsFlexProcessing - ) { - warnings.push({ - type: 'unsupported', - feature: 'serviceTier', - details: - 'flex processing is only available for o3, o4-mini, and gpt-5 models', - }); - baseArgs.service_tier = undefined; - } - - // Validate priority processing support - if ( - openaiOptions.serviceTier === 'priority' && - !modelCapabilities.supportsPriorityProcessing - ) { - warnings.push({ - type: 'unsupported', - feature: 'serviceTier', - details: - 'priority processing is only available for supported models (gpt-4, gpt-5, gpt-5-mini, o3, o4-mini) and requires Enterprise access. gpt-5-nano is not supported', - }); - baseArgs.service_tier = undefined; - } - - const { - tools: openaiTools, - toolChoice: openaiToolChoice, - toolWarnings, - } = prepareChatTools({ - tools, - toolChoice, - }); - - return { - args: { - ...baseArgs, - tools: openaiTools, - tool_choice: openaiToolChoice, - }, - warnings: [...warnings, ...toolWarnings], - }; - } - - async doGenerate( - options: LanguageModelV3CallOptions, - ): Promise { - const { args: body, warnings } = await this.getArgs(options); - - const { - responseHeaders, - value: response, - rawValue: rawResponse, - } = await postJsonToApi({ - url: this.config.url({ - path: '/chat/completions', - modelId: this.modelId, - }), - headers: combineHeaders(this.config.headers(), options.headers), - body, - failedResponseHandler: openaiFailedResponseHandler, - successfulResponseHandler: createJsonResponseHandler( - openaiChatResponseSchema, - ), - abortSignal: options.abortSignal, - fetch: this.config.fetch, - }); - - const choice = response.choices[0]; - const content: Array = []; - - // text content: - const text = choice.message.content; - if (text != null && text.length > 0) { - content.push({ type: 'text', text }); - } - - // tool calls: - for (const toolCall of choice.message.tool_calls ?? []) { - content.push({ - type: 'tool-call' as const, - toolCallId: toolCall.id ?? generateId(), - toolName: toolCall.function.name, - input: toolCall.function.arguments!, - }); - } - - // annotations/citations: - for (const annotation of choice.message.annotations ?? []) { - content.push({ - type: 'source', - sourceType: 'url', - id: generateId(), - url: annotation.url_citation.url, - title: annotation.url_citation.title, - }); - } - - // provider metadata: - const completionTokenDetails = response.usage?.completion_tokens_details; - const promptTokenDetails = response.usage?.prompt_tokens_details; - const providerMetadata: SharedV3ProviderMetadata = { openai: {} }; - if (completionTokenDetails?.accepted_prediction_tokens != null) { - providerMetadata.openai.acceptedPredictionTokens = - completionTokenDetails?.accepted_prediction_tokens; - } - if (completionTokenDetails?.rejected_prediction_tokens != null) { - providerMetadata.openai.rejectedPredictionTokens = - completionTokenDetails?.rejected_prediction_tokens; - } - if (choice.logprobs?.content != null) { - providerMetadata.openai.logprobs = choice.logprobs.content; - } - - return { - content, - finishReason: { - unified: mapOpenAIFinishReason(choice.finish_reason), - raw: choice.finish_reason ?? undefined, - }, - usage: convertOpenAIChatUsage(response.usage), - request: { body }, - response: { - ...getResponseMetadata(response), - headers: responseHeaders, - body: rawResponse, - }, - warnings, - providerMetadata, - }; - } - - async doStream( - options: LanguageModelV3CallOptions, - ): Promise { - const { args, warnings } = await this.getArgs(options); - - const body = { - ...args, - stream: true, - stream_options: { - include_usage: true, - }, - }; - - const { responseHeaders, value: response } = await postJsonToApi({ - url: this.config.url({ - path: '/chat/completions', - modelId: this.modelId, - }), - headers: combineHeaders(this.config.headers(), options.headers), - body, - failedResponseHandler: openaiFailedResponseHandler, - successfulResponseHandler: createEventSourceResponseHandler( - openaiChatChunkSchema, - ), - abortSignal: options.abortSignal, - fetch: this.config.fetch, - }); - - const toolCalls: Array<{ - id: string; - type: 'function'; - function: { - name: string; - arguments: string; - }; - hasFinished: boolean; - }> = []; - - let finishReason: LanguageModelV3FinishReason = { - unified: 'other', - raw: undefined, - }; - let usage: OpenAIChatUsage | undefined = undefined; - let metadataExtracted = false; - let isActiveText = false; - - const providerMetadata: SharedV3ProviderMetadata = { openai: {} }; - - return { - stream: response.pipeThrough( - new TransformStream< - ParseResult, - LanguageModelV3StreamPart - >({ - start(controller) { - controller.enqueue({ type: 'stream-start', warnings }); - }, - - transform(chunk, controller) { - if (options.includeRawChunks) { - controller.enqueue({ type: 'raw', rawValue: chunk.rawValue }); - } - - // handle failed chunk parsing / validation: - if (!chunk.success) { - finishReason = { unified: 'error', raw: undefined }; - controller.enqueue({ type: 'error', error: chunk.error }); - return; - } - - const value = chunk.value; - - // handle error chunks: - if ('error' in value) { - finishReason = { unified: 'error', raw: undefined }; - controller.enqueue({ type: 'error', error: value.error }); - return; - } - - // extract and emit response metadata once. Usually it comes in the first chunk. - // Azure may prepend a chunk with a `"prompt_filter_results"` key which does not contain other metadata, - // https://learn.microsoft.com/en-us/azure/ai-foundry/openai/concepts/content-filter-annotations?tabs=powershell - if (!metadataExtracted) { - const metadata = getResponseMetadata(value); - if (Object.values(metadata).some(Boolean)) { - metadataExtracted = true; - controller.enqueue({ - type: 'response-metadata', - ...getResponseMetadata(value), - }); - } - } - - if (value.usage != null) { - usage = value.usage; - - if ( - value.usage.completion_tokens_details - ?.accepted_prediction_tokens != null - ) { - providerMetadata.openai.acceptedPredictionTokens = - value.usage.completion_tokens_details?.accepted_prediction_tokens; - } - if ( - value.usage.completion_tokens_details - ?.rejected_prediction_tokens != null - ) { - providerMetadata.openai.rejectedPredictionTokens = - value.usage.completion_tokens_details?.rejected_prediction_tokens; - } - } - - const choice = value.choices[0]; - - if (choice?.finish_reason != null) { - finishReason = { - unified: mapOpenAIFinishReason(choice.finish_reason), - raw: choice.finish_reason, - }; - } - - if (choice?.logprobs?.content != null) { - providerMetadata.openai.logprobs = choice.logprobs.content; - } - - if (choice?.delta == null) { - return; - } - - const delta = choice.delta; - - if (delta.content != null) { - if (!isActiveText) { - controller.enqueue({ type: 'text-start', id: '0' }); - isActiveText = true; - } - - controller.enqueue({ - type: 'text-delta', - id: '0', - delta: delta.content, - }); - } - - if (delta.tool_calls != null) { - for (const toolCallDelta of delta.tool_calls) { - const index = toolCallDelta.index; - - // Tool call start. OpenAI returns all information except the arguments in the first chunk. - if (toolCalls[index] == null) { - if ( - toolCallDelta.type != null && - toolCallDelta.type !== 'function' - ) { - throw new InvalidResponseDataError({ - data: toolCallDelta, - message: `Expected 'function' type.`, - }); - } - - if (toolCallDelta.id == null) { - throw new InvalidResponseDataError({ - data: toolCallDelta, - message: `Expected 'id' to be a string.`, - }); - } - - if (toolCallDelta.function?.name == null) { - throw new InvalidResponseDataError({ - data: toolCallDelta, - message: `Expected 'function.name' to be a string.`, - }); - } - - controller.enqueue({ - type: 'tool-input-start', - id: toolCallDelta.id, - toolName: toolCallDelta.function.name, - }); - - toolCalls[index] = { - id: toolCallDelta.id, - type: 'function', - function: { - name: toolCallDelta.function.name, - arguments: toolCallDelta.function.arguments ?? '', - }, - hasFinished: false, - }; - - const toolCall = toolCalls[index]; - - if ( - toolCall.function?.name != null && - toolCall.function?.arguments != null - ) { - // send delta if the argument text has already started: - if (toolCall.function.arguments.length > 0) { - controller.enqueue({ - type: 'tool-input-delta', - id: toolCall.id, - delta: toolCall.function.arguments, - }); - } - - // check if tool call is complete - // (some providers send the full tool call in one chunk): - if (isParsableJson(toolCall.function.arguments)) { - controller.enqueue({ - type: 'tool-input-end', - id: toolCall.id, - }); - - controller.enqueue({ - type: 'tool-call', - toolCallId: toolCall.id ?? generateId(), - toolName: toolCall.function.name, - input: toolCall.function.arguments, - }); - toolCall.hasFinished = true; - } - } - - continue; - } - - // existing tool call, merge if not finished - const toolCall = toolCalls[index]; - - if (toolCall.hasFinished) { - continue; - } - - if (toolCallDelta.function?.arguments != null) { - toolCall.function!.arguments += - toolCallDelta.function?.arguments ?? ''; - } - - // send delta - controller.enqueue({ - type: 'tool-input-delta', - id: toolCall.id, - delta: toolCallDelta.function.arguments ?? '', - }); - - // check if tool call is complete - if ( - toolCall.function?.name != null && - toolCall.function?.arguments != null && - isParsableJson(toolCall.function.arguments) - ) { - controller.enqueue({ - type: 'tool-input-end', - id: toolCall.id, - }); - - controller.enqueue({ - type: 'tool-call', - toolCallId: toolCall.id ?? generateId(), - toolName: toolCall.function.name, - input: toolCall.function.arguments, - }); - toolCall.hasFinished = true; - } - } - } - - // annotations/citations: - if (delta.annotations != null) { - for (const annotation of delta.annotations) { - controller.enqueue({ - type: 'source', - sourceType: 'url', - id: generateId(), - url: annotation.url_citation.url, - title: annotation.url_citation.title, - }); - } - } - }, - - flush(controller) { - if (isActiveText) { - controller.enqueue({ type: 'text-end', id: '0' }); - } - - controller.enqueue({ - type: 'finish', - finishReason, - usage: convertOpenAIChatUsage(usage), - ...(providerMetadata != null ? { providerMetadata } : {}), - }); - }, - }), - ), - request: { body }, - response: { headers: responseHeaders }, - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-options.ts deleted file mode 100644 index d876e62e8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-options.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -// https://platform.openai.com/docs/models -export type OpenAIChatModelId = - | 'o1' - | 'o1-2024-12-17' - | 'o3-mini' - | 'o3-mini-2025-01-31' - | 'o3' - | 'o3-2025-04-16' - | 'o4-mini' - | 'o4-mini-2025-04-16' - | 'gpt-4.1' - | 'gpt-4.1-2025-04-14' - | 'gpt-4.1-mini' - | 'gpt-4.1-mini-2025-04-14' - | 'gpt-4.1-nano' - | 'gpt-4.1-nano-2025-04-14' - | 'gpt-4o' - | 'gpt-4o-2024-05-13' - | 'gpt-4o-2024-08-06' - | 'gpt-4o-2024-11-20' - | 'gpt-4o-audio-preview' - | 'gpt-4o-audio-preview-2024-12-17' - | 'gpt-4o-audio-preview-2025-06-03' - | 'gpt-4o-mini' - | 'gpt-4o-mini-2024-07-18' - | 'gpt-4o-mini-audio-preview' - | 'gpt-4o-mini-audio-preview-2024-12-17' - | 'gpt-4o-search-preview' - | 'gpt-4o-search-preview-2025-03-11' - | 'gpt-4o-mini-search-preview' - | 'gpt-4o-mini-search-preview-2025-03-11' - | 'gpt-3.5-turbo-0125' - | 'gpt-3.5-turbo' - | 'gpt-3.5-turbo-1106' - | 'gpt-3.5-turbo-16k' - | 'gpt-5' - | 'gpt-5-2025-08-07' - | 'gpt-5-mini' - | 'gpt-5-mini-2025-08-07' - | 'gpt-5-nano' - | 'gpt-5-nano-2025-08-07' - | 'gpt-5-chat-latest' - | 'gpt-5.1' - | 'gpt-5.1-2025-11-13' - | 'gpt-5.1-chat-latest' - | 'gpt-5.2' - | 'gpt-5.2-2025-12-11' - | 'gpt-5.2-chat-latest' - | 'gpt-5.2-pro' - | 'gpt-5.2-pro-2025-12-11' - | 'gpt-5.3-chat-latest' - | 'gpt-5.4' - | 'gpt-5.4-2026-03-05' - | 'gpt-5.4-mini' - | 'gpt-5.4-mini-2026-03-17' - | 'gpt-5.4-nano' - | 'gpt-5.4-nano-2026-03-17' - | 'gpt-5.4-pro' - | 'gpt-5.4-pro-2026-03-05' - | (string & {}); - -export const openaiLanguageModelChatOptions = lazySchema(() => - zodSchema( - z.object({ - /** - * Modify the likelihood of specified tokens appearing in the completion. - * - * Accepts a JSON object that maps tokens (specified by their token ID in - * the GPT tokenizer) to an associated bias value from -100 to 100. - */ - logitBias: z.record(z.coerce.number(), z.number()).optional(), - - /** - * Return the log probabilities of the tokens. - * - * Setting to true will return the log probabilities of the tokens that - * were generated. - * - * Setting to a number will return the log probabilities of the top n - * tokens that were generated. - */ - logprobs: z.union([z.boolean(), z.number()]).optional(), - - /** - * Whether to enable parallel function calling during tool use. Default to true. - */ - parallelToolCalls: z.boolean().optional(), - - /** - * A unique identifier representing your end-user, which can help OpenAI to - * monitor and detect abuse. - */ - user: z.string().optional(), - - /** - * Reasoning effort for reasoning models. Defaults to `medium`. - */ - reasoningEffort: z - .enum(['none', 'minimal', 'low', 'medium', 'high', 'xhigh']) - .optional(), - - /** - * Maximum number of completion tokens to generate. Useful for reasoning models. - */ - maxCompletionTokens: z.number().optional(), - - /** - * Whether to enable persistence in responses API. - */ - store: z.boolean().optional(), - - /** - * Metadata to associate with the request. - */ - metadata: z.record(z.string().max(64), z.string().max(512)).optional(), - - /** - * Parameters for prediction mode. - */ - prediction: z.record(z.string(), z.any()).optional(), - - /** - * Service tier for the request. - * - 'auto': Default service tier. The request will be processed with the service tier configured in the - * Project settings. Unless otherwise configured, the Project will use 'default'. - * - 'flex': 50% cheaper processing at the cost of increased latency. Only available for o3 and o4-mini models. - * - 'priority': Higher-speed processing with predictably low latency at premium cost. Available for Enterprise customers. - * - 'default': The request will be processed with the standard pricing and performance for the selected model. - * - * @default 'auto' - */ - serviceTier: z.enum(['auto', 'flex', 'priority', 'default']).optional(), - - /** - * Whether to use strict JSON schema validation. - * - * @default true - */ - strictJsonSchema: z.boolean().optional(), - - /** - * Controls the verbosity of the model's responses. - * Lower values will result in more concise responses, while higher values will result in more verbose responses. - */ - textVerbosity: z.enum(['low', 'medium', 'high']).optional(), - - /** - * A cache key for prompt caching. Allows manual control over prompt caching behavior. - * Useful for improving cache hit rates and working around automatic caching issues. - */ - promptCacheKey: z.string().optional(), - - /** - * The retention policy for the prompt cache. - * - 'in_memory': Default. Standard prompt caching behavior. - * - '24h': Extended prompt caching that keeps cached prefixes active for up to 24 hours. - * Currently only available for 5.1 series models. - * - * @default 'in_memory' - */ - promptCacheRetention: z.enum(['in_memory', '24h']).optional(), - - /** - * A stable identifier used to help detect users of your application - * that may be violating OpenAI's usage policies. The IDs should be a - * string that uniquely identifies each user. We recommend hashing their - * username or email address, in order to avoid sending us any identifying - * information. - */ - safetyIdentifier: z.string().optional(), - - /** - * Override the system message mode for this model. - * - 'system': Use the 'system' role for system messages (default for most models) - * - 'developer': Use the 'developer' role for system messages (used by reasoning models) - * - 'remove': Remove system messages entirely - * - * If not specified, the mode is automatically determined based on the model. - */ - systemMessageMode: z.enum(['system', 'developer', 'remove']).optional(), - - /** - * Force treating this model as a reasoning model. - * - * This is useful for "stealth" reasoning models (e.g. via a custom baseURL) - * where the model ID is not recognized by the SDK's allowlist. - * - * When enabled, the SDK applies reasoning-model parameter compatibility rules - * and defaults `systemMessageMode` to `developer` unless overridden. - */ - forceReasoning: z.boolean().optional(), - }), - ), -); - -export type OpenAILanguageModelChatOptions = InferSchema< - typeof openaiLanguageModelChatOptions ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-prepare-tools.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-prepare-tools.ts deleted file mode 100644 index 9080896fe..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-prepare-tools.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { - LanguageModelV3CallOptions, - SharedV3Warning, - UnsupportedFunctionalityError, -} from '@ai-sdk/provider'; -import { - OpenAIChatToolChoice, - OpenAIChatFunctionTool, -} from './openai-chat-api'; - -export function prepareChatTools({ - tools, - toolChoice, -}: { - tools: LanguageModelV3CallOptions['tools']; - toolChoice?: LanguageModelV3CallOptions['toolChoice']; -}): { - tools?: OpenAIChatFunctionTool[]; - toolChoice?: OpenAIChatToolChoice; - toolWarnings: Array; -} { - // when the tools array is empty, change it to undefined to prevent errors: - tools = tools?.length ? tools : undefined; - - const toolWarnings: SharedV3Warning[] = []; - - if (tools == null) { - return { tools: undefined, toolChoice: undefined, toolWarnings }; - } - - const openaiTools: OpenAIChatFunctionTool[] = []; - - for (const tool of tools) { - switch (tool.type) { - case 'function': - openaiTools.push({ - type: 'function', - function: { - name: tool.name, - description: tool.description, - parameters: tool.inputSchema, - ...(tool.strict != null ? { strict: tool.strict } : {}), - }, - }); - break; - default: - toolWarnings.push({ - type: 'unsupported', - feature: `tool type: ${tool.type}`, - }); - break; - } - } - - if (toolChoice == null) { - return { tools: openaiTools, toolChoice: undefined, toolWarnings }; - } - - const type = toolChoice.type; - - switch (type) { - case 'auto': - case 'none': - case 'required': - return { tools: openaiTools, toolChoice: type, toolWarnings }; - case 'tool': - return { - tools: openaiTools, - toolChoice: { - type: 'function', - function: { - name: toolChoice.toolName, - }, - }, - toolWarnings, - }; - default: { - const _exhaustiveCheck: never = type; - throw new UnsupportedFunctionalityError({ - functionality: `tool choice type: ${_exhaustiveCheck}`, - }); - } - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-prompt.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-prompt.ts deleted file mode 100644 index 379530416..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/chat/openai-chat-prompt.ts +++ /dev/null @@ -1,70 +0,0 @@ -export type OpenAIChatPrompt = Array; - -export type ChatCompletionMessage = - | ChatCompletionSystemMessage - | ChatCompletionDeveloperMessage - | ChatCompletionUserMessage - | ChatCompletionAssistantMessage - | ChatCompletionToolMessage; - -export interface ChatCompletionSystemMessage { - role: 'system'; - content: string; -} - -export interface ChatCompletionDeveloperMessage { - role: 'developer'; - content: string; -} - -export interface ChatCompletionUserMessage { - role: 'user'; - content: string | Array; -} - -export type ChatCompletionContentPart = - | ChatCompletionContentPartText - | ChatCompletionContentPartImage - | ChatCompletionContentPartInputAudio - | ChatCompletionContentPartFile; - -export interface ChatCompletionContentPartText { - type: 'text'; - text: string; -} - -export interface ChatCompletionContentPartImage { - type: 'image_url'; - image_url: { url: string }; -} - -export interface ChatCompletionContentPartInputAudio { - type: 'input_audio'; - input_audio: { data: string; format: 'wav' | 'mp3' }; -} - -export interface ChatCompletionContentPartFile { - type: 'file'; - file: { filename: string; file_data: string } | { file_id: string }; -} - -export interface ChatCompletionAssistantMessage { - role: 'assistant'; - content?: string | null; - tool_calls?: Array; -} - -export interface ChatCompletionMessageToolCall { - type: 'function'; - id: string; - function: { - arguments: string; - name: string; - }; -} - -export interface ChatCompletionToolMessage { - role: 'tool'; - content: string; - tool_call_id: string; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/convert-openai-completion-usage.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/convert-openai-completion-usage.ts deleted file mode 100644 index 3b4dc14df..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/convert-openai-completion-usage.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { LanguageModelV3Usage } from '@ai-sdk/provider'; - -export type OpenAICompletionUsage = { - prompt_tokens?: number | null; - completion_tokens?: number | null; - total_tokens?: number | null; -}; - -export function convertOpenAICompletionUsage( - usage: OpenAICompletionUsage | undefined | null, -): LanguageModelV3Usage { - if (usage == null) { - return { - inputTokens: { - total: undefined, - noCache: undefined, - cacheRead: undefined, - cacheWrite: undefined, - }, - outputTokens: { - total: undefined, - text: undefined, - reasoning: undefined, - }, - raw: undefined, - }; - } - - const promptTokens = usage.prompt_tokens ?? 0; - const completionTokens = usage.completion_tokens ?? 0; - - return { - inputTokens: { - total: usage.prompt_tokens ?? undefined, - noCache: promptTokens, - cacheRead: undefined, - cacheWrite: undefined, - }, - outputTokens: { - total: usage.completion_tokens ?? undefined, - text: completionTokens, - reasoning: undefined, - }, - raw: usage, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/convert-to-openai-completion-prompt.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/convert-to-openai-completion-prompt.ts deleted file mode 100644 index ed67f480d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/convert-to-openai-completion-prompt.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { - InvalidPromptError, - LanguageModelV3Prompt, - UnsupportedFunctionalityError, -} from '@ai-sdk/provider'; - -export function convertToOpenAICompletionPrompt({ - prompt, - user = 'user', - assistant = 'assistant', -}: { - prompt: LanguageModelV3Prompt; - user?: string; - assistant?: string; -}): { - prompt: string; - stopSequences?: string[]; -} { - // transform to a chat message format: - let text = ''; - - // if first message is a system message, add it to the text: - if (prompt[0].role === 'system') { - text += `${prompt[0].content}\n\n`; - prompt = prompt.slice(1); - } - - for (const { role, content } of prompt) { - switch (role) { - case 'system': { - throw new InvalidPromptError({ - message: 'Unexpected system message in prompt: ${content}', - prompt, - }); - } - - case 'user': { - const userMessage = content - .map(part => { - switch (part.type) { - case 'text': { - return part.text; - } - } - }) - .filter(Boolean) - .join(''); - - text += `${user}:\n${userMessage}\n\n`; - break; - } - - case 'assistant': { - const assistantMessage = content - .map(part => { - switch (part.type) { - case 'text': { - return part.text; - } - case 'tool-call': { - throw new UnsupportedFunctionalityError({ - functionality: 'tool-call messages', - }); - } - } - }) - .join(''); - - text += `${assistant}:\n${assistantMessage}\n\n`; - break; - } - - case 'tool': { - throw new UnsupportedFunctionalityError({ - functionality: 'tool messages', - }); - } - - default: { - const _exhaustiveCheck: never = role; - throw new Error(`Unsupported role: ${_exhaustiveCheck}`); - } - } - } - - // Assistant message prefix: - text += `${assistant}:\n`; - - return { - prompt: text, - stopSequences: [`\n${user}:`], - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/get-response-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/get-response-metadata.ts deleted file mode 100644 index bd358b23f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/get-response-metadata.ts +++ /dev/null @@ -1,15 +0,0 @@ -export function getResponseMetadata({ - id, - model, - created, -}: { - id?: string | undefined | null; - created?: number | undefined | null; - model?: string | undefined | null; -}) { - return { - id: id ?? undefined, - modelId: model ?? undefined, - timestamp: created != null ? new Date(created * 1000) : undefined, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/map-openai-finish-reason.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/map-openai-finish-reason.ts deleted file mode 100644 index f3005bb8d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/map-openai-finish-reason.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { LanguageModelV3FinishReason } from '@ai-sdk/provider'; - -export function mapOpenAIFinishReason( - finishReason: string | null | undefined, -): LanguageModelV3FinishReason['unified'] { - switch (finishReason) { - case 'stop': - return 'stop'; - case 'length': - return 'length'; - case 'content_filter': - return 'content-filter'; - case 'function_call': - case 'tool_calls': - return 'tool-calls'; - default: - return 'other'; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/openai-completion-api.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/openai-completion-api.ts deleted file mode 100644 index 312ab046c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/openai-completion-api.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { z } from 'zod/v4'; -import { openaiErrorDataSchema } from '../openai-error'; -import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils'; - -// limited version of the schema, focussed on what is needed for the implementation -// this approach limits breakages when the API changes and increases efficiency -export const openaiCompletionResponseSchema = lazySchema(() => - zodSchema( - z.object({ - id: z.string().nullish(), - created: z.number().nullish(), - model: z.string().nullish(), - choices: z.array( - z.object({ - text: z.string(), - finish_reason: z.string(), - logprobs: z - .object({ - tokens: z.array(z.string()), - token_logprobs: z.array(z.number()), - top_logprobs: z.array(z.record(z.string(), z.number())).nullish(), - }) - .nullish(), - }), - ), - usage: z - .object({ - prompt_tokens: z.number(), - completion_tokens: z.number(), - total_tokens: z.number(), - }) - .nullish(), - }), - ), -); - -// limited version of the schema, focussed on what is needed for the implementation -// this approach limits breakages when the API changes and increases efficiency -export const openaiCompletionChunkSchema = lazySchema(() => - zodSchema( - z.union([ - z.object({ - id: z.string().nullish(), - created: z.number().nullish(), - model: z.string().nullish(), - choices: z.array( - z.object({ - text: z.string(), - finish_reason: z.string().nullish(), - index: z.number(), - logprobs: z - .object({ - tokens: z.array(z.string()), - token_logprobs: z.array(z.number()), - top_logprobs: z - .array(z.record(z.string(), z.number())) - .nullish(), - }) - .nullish(), - }), - ), - usage: z - .object({ - prompt_tokens: z.number(), - completion_tokens: z.number(), - total_tokens: z.number(), - }) - .nullish(), - }), - openaiErrorDataSchema, - ]), - ), -); - -export type OpenAICompletionChunk = InferSchema< - typeof openaiCompletionChunkSchema ->; - -export type OpenAICompletionResponse = InferSchema< - typeof openaiCompletionResponseSchema ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/openai-completion-language-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/openai-completion-language-model.ts deleted file mode 100644 index 836b30634..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/openai-completion-language-model.ts +++ /dev/null @@ -1,336 +0,0 @@ -import { - LanguageModelV3, - LanguageModelV3CallOptions, - LanguageModelV3FinishReason, - LanguageModelV3GenerateResult, - LanguageModelV3StreamPart, - LanguageModelV3StreamResult, - SharedV3ProviderMetadata, - SharedV3Warning, -} from '@ai-sdk/provider'; -import { - combineHeaders, - createEventSourceResponseHandler, - createJsonResponseHandler, - FetchFunction, - parseProviderOptions, - ParseResult, - postJsonToApi, -} from '@ai-sdk/provider-utils'; -import { openaiFailedResponseHandler } from '../openai-error'; -import { - convertOpenAICompletionUsage, - OpenAICompletionUsage, -} from './convert-openai-completion-usage'; -import { convertToOpenAICompletionPrompt } from './convert-to-openai-completion-prompt'; -import { getResponseMetadata } from './get-response-metadata'; -import { mapOpenAIFinishReason } from './map-openai-finish-reason'; -import { - OpenAICompletionChunk, - openaiCompletionChunkSchema, - openaiCompletionResponseSchema, -} from './openai-completion-api'; -import { - OpenAICompletionModelId, - openaiLanguageModelCompletionOptions, -} from './openai-completion-options'; - -type OpenAICompletionConfig = { - provider: string; - headers: () => Record; - url: (options: { modelId: string; path: string }) => string; - fetch?: FetchFunction; -}; - -export class OpenAICompletionLanguageModel implements LanguageModelV3 { - readonly specificationVersion = 'v3'; - - readonly modelId: OpenAICompletionModelId; - - private readonly config: OpenAICompletionConfig; - - private get providerOptionsName(): string { - return this.config.provider.split('.')[0].trim(); - } - - constructor( - modelId: OpenAICompletionModelId, - config: OpenAICompletionConfig, - ) { - this.modelId = modelId; - this.config = config; - } - - get provider(): string { - return this.config.provider; - } - - readonly supportedUrls: Record = { - // No URLs are supported for completion models. - }; - - private async getArgs({ - prompt, - maxOutputTokens, - temperature, - topP, - topK, - frequencyPenalty, - presencePenalty, - stopSequences: userStopSequences, - responseFormat, - tools, - toolChoice, - seed, - providerOptions, - }: LanguageModelV3CallOptions) { - const warnings: SharedV3Warning[] = []; - - // Parse provider options - const openaiOptions = { - ...(await parseProviderOptions({ - provider: 'openai', - providerOptions, - schema: openaiLanguageModelCompletionOptions, - })), - ...(await parseProviderOptions({ - provider: this.providerOptionsName, - providerOptions, - schema: openaiLanguageModelCompletionOptions, - })), - }; - - if (topK != null) { - warnings.push({ type: 'unsupported', feature: 'topK' }); - } - - if (tools?.length) { - warnings.push({ type: 'unsupported', feature: 'tools' }); - } - - if (toolChoice != null) { - warnings.push({ type: 'unsupported', feature: 'toolChoice' }); - } - - if (responseFormat != null && responseFormat.type !== 'text') { - warnings.push({ - type: 'unsupported', - feature: 'responseFormat', - details: 'JSON response format is not supported.', - }); - } - - const { prompt: completionPrompt, stopSequences } = - convertToOpenAICompletionPrompt({ prompt }); - - const stop = [...(stopSequences ?? []), ...(userStopSequences ?? [])]; - - return { - args: { - // model id: - model: this.modelId, - - // model specific settings: - echo: openaiOptions.echo, - logit_bias: openaiOptions.logitBias, - logprobs: - openaiOptions?.logprobs === true - ? 0 - : openaiOptions?.logprobs === false - ? undefined - : openaiOptions?.logprobs, - suffix: openaiOptions.suffix, - user: openaiOptions.user, - - // standardized settings: - max_tokens: maxOutputTokens, - temperature, - top_p: topP, - frequency_penalty: frequencyPenalty, - presence_penalty: presencePenalty, - seed, - - // prompt: - prompt: completionPrompt, - - // stop sequences: - stop: stop.length > 0 ? stop : undefined, - }, - warnings, - }; - } - - async doGenerate( - options: LanguageModelV3CallOptions, - ): Promise { - const { args, warnings } = await this.getArgs(options); - - const { - responseHeaders, - value: response, - rawValue: rawResponse, - } = await postJsonToApi({ - url: this.config.url({ - path: '/completions', - modelId: this.modelId, - }), - headers: combineHeaders(this.config.headers(), options.headers), - body: args, - failedResponseHandler: openaiFailedResponseHandler, - successfulResponseHandler: createJsonResponseHandler( - openaiCompletionResponseSchema, - ), - abortSignal: options.abortSignal, - fetch: this.config.fetch, - }); - - const choice = response.choices[0]; - - const providerMetadata: SharedV3ProviderMetadata = { openai: {} }; - - if (choice.logprobs != null) { - providerMetadata.openai.logprobs = choice.logprobs; - } - - return { - content: [{ type: 'text', text: choice.text }], - usage: convertOpenAICompletionUsage(response.usage), - finishReason: { - unified: mapOpenAIFinishReason(choice.finish_reason), - raw: choice.finish_reason ?? undefined, - }, - request: { body: args }, - response: { - ...getResponseMetadata(response), - headers: responseHeaders, - body: rawResponse, - }, - providerMetadata, - warnings, - }; - } - - async doStream( - options: LanguageModelV3CallOptions, - ): Promise { - const { args, warnings } = await this.getArgs(options); - - const body = { - ...args, - stream: true, - - stream_options: { - include_usage: true, - }, - }; - - const { responseHeaders, value: response } = await postJsonToApi({ - url: this.config.url({ - path: '/completions', - modelId: this.modelId, - }), - headers: combineHeaders(this.config.headers(), options.headers), - body, - failedResponseHandler: openaiFailedResponseHandler, - successfulResponseHandler: createEventSourceResponseHandler( - openaiCompletionChunkSchema, - ), - abortSignal: options.abortSignal, - fetch: this.config.fetch, - }); - - let finishReason: LanguageModelV3FinishReason = { - unified: 'other', - raw: undefined, - }; - const providerMetadata: SharedV3ProviderMetadata = { openai: {} }; - let usage: OpenAICompletionUsage | undefined = undefined; - let isFirstChunk = true; - - return { - stream: response.pipeThrough( - new TransformStream< - ParseResult, - LanguageModelV3StreamPart - >({ - start(controller) { - controller.enqueue({ type: 'stream-start', warnings }); - }, - - transform(chunk, controller) { - if (options.includeRawChunks) { - controller.enqueue({ type: 'raw', rawValue: chunk.rawValue }); - } - - // handle failed chunk parsing / validation: - if (!chunk.success) { - finishReason = { unified: 'error', raw: undefined }; - controller.enqueue({ type: 'error', error: chunk.error }); - return; - } - - const value = chunk.value; - - // handle error chunks: - if ('error' in value) { - finishReason = { unified: 'error', raw: undefined }; - controller.enqueue({ type: 'error', error: value.error }); - return; - } - - if (isFirstChunk) { - isFirstChunk = false; - - controller.enqueue({ - type: 'response-metadata', - ...getResponseMetadata(value), - }); - - controller.enqueue({ type: 'text-start', id: '0' }); - } - - if (value.usage != null) { - usage = value.usage; - } - - const choice = value.choices[0]; - - if (choice?.finish_reason != null) { - finishReason = { - unified: mapOpenAIFinishReason(choice.finish_reason), - raw: choice.finish_reason, - }; - } - - if (choice?.logprobs != null) { - providerMetadata.openai.logprobs = choice.logprobs; - } - - if (choice?.text != null && choice.text.length > 0) { - controller.enqueue({ - type: 'text-delta', - id: '0', - delta: choice.text, - }); - } - }, - - flush(controller) { - if (!isFirstChunk) { - controller.enqueue({ type: 'text-end', id: '0' }); - } - - controller.enqueue({ - type: 'finish', - finishReason, - providerMetadata, - usage: convertOpenAICompletionUsage(usage), - }); - }, - }), - ), - request: { body }, - response: { headers: responseHeaders }, - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/openai-completion-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/openai-completion-options.ts deleted file mode 100644 index a936f3b39..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/completion/openai-completion-options.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -// https://platform.openai.com/docs/models -export type OpenAICompletionModelId = - | 'gpt-3.5-turbo-instruct' - | 'gpt-3.5-turbo-instruct-0914' - | (string & {}); - -export const openaiLanguageModelCompletionOptions = lazySchema(() => - zodSchema( - z.object({ - /** - * Echo back the prompt in addition to the completion. - */ - echo: z.boolean().optional(), - - /** - * Modify the likelihood of specified tokens appearing in the completion. - * - * Accepts a JSON object that maps tokens (specified by their token ID in - * the GPT tokenizer) to an associated bias value from -100 to 100. You - * can use this tokenizer tool to convert text to token IDs. Mathematically, - * the bias is added to the logits generated by the model prior to sampling. - * The exact effect will vary per model, but values between -1 and 1 should - * decrease or increase likelihood of selection; values like -100 or 100 - * should result in a ban or exclusive selection of the relevant token. - * - * As an example, you can pass {"50256": -100} to prevent the <|endoftext|> - * token from being generated. - */ - logitBias: z.record(z.string(), z.number()).optional(), - - /** - * The suffix that comes after a completion of inserted text. - */ - suffix: z.string().optional(), - - /** - * A unique identifier representing your end-user, which can help OpenAI to - * monitor and detect abuse. Learn more. - */ - user: z.string().optional(), - - /** - * Return the log probabilities of the tokens. Including logprobs will increase - * the response size and can slow down response times. However, it can - * be useful to better understand how the model is behaving. - * Setting to true will return the log probabilities of the tokens that - * were generated. - * Setting to a number will return the log probabilities of the top n - * tokens that were generated. - */ - logprobs: z.union([z.boolean(), z.number()]).optional(), - }), - ), -); - -export type OpenAILanguageModelCompletionOptions = InferSchema< - typeof openaiLanguageModelCompletionOptions ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/embedding/openai-embedding-api.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/embedding/openai-embedding-api.ts deleted file mode 100644 index 87ab6c106..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/embedding/openai-embedding-api.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -// minimal version of the schema, focussed on what is needed for the implementation -// this approach limits breakages when the API changes and increases efficiency -export const openaiTextEmbeddingResponseSchema = lazySchema(() => - zodSchema( - z.object({ - data: z.array(z.object({ embedding: z.array(z.number()) })), - usage: z.object({ prompt_tokens: z.number() }).nullish(), - }), - ), -); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/embedding/openai-embedding-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/embedding/openai-embedding-model.ts deleted file mode 100644 index a1e2c7615..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/embedding/openai-embedding-model.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { - EmbeddingModelV3, - TooManyEmbeddingValuesForCallError, -} from '@ai-sdk/provider'; -import { - combineHeaders, - createJsonResponseHandler, - parseProviderOptions, - postJsonToApi, -} from '@ai-sdk/provider-utils'; -import { OpenAIConfig } from '../openai-config'; -import { openaiFailedResponseHandler } from '../openai-error'; -import { - OpenAIEmbeddingModelId, - openaiEmbeddingModelOptions, -} from './openai-embedding-options'; -import { openaiTextEmbeddingResponseSchema } from './openai-embedding-api'; - -export class OpenAIEmbeddingModel implements EmbeddingModelV3 { - readonly specificationVersion = 'v3'; - readonly modelId: OpenAIEmbeddingModelId; - readonly maxEmbeddingsPerCall = 2048; - readonly supportsParallelCalls = true; - - private readonly config: OpenAIConfig; - - get provider(): string { - return this.config.provider; - } - - constructor(modelId: OpenAIEmbeddingModelId, config: OpenAIConfig) { - this.modelId = modelId; - this.config = config; - } - - async doEmbed({ - values, - headers, - abortSignal, - providerOptions, - }: Parameters[0]): Promise< - Awaited> - > { - if (values.length > this.maxEmbeddingsPerCall) { - throw new TooManyEmbeddingValuesForCallError({ - provider: this.provider, - modelId: this.modelId, - maxEmbeddingsPerCall: this.maxEmbeddingsPerCall, - values, - }); - } - - // Parse provider options - const openaiOptions = - (await parseProviderOptions({ - provider: 'openai', - providerOptions, - schema: openaiEmbeddingModelOptions, - })) ?? {}; - - const { - responseHeaders, - value: response, - rawValue, - } = await postJsonToApi({ - url: this.config.url({ - path: '/embeddings', - modelId: this.modelId, - }), - headers: combineHeaders(this.config.headers(), headers), - body: { - model: this.modelId, - input: values, - encoding_format: 'float', - dimensions: openaiOptions.dimensions, - user: openaiOptions.user, - }, - failedResponseHandler: openaiFailedResponseHandler, - successfulResponseHandler: createJsonResponseHandler( - openaiTextEmbeddingResponseSchema, - ), - abortSignal, - fetch: this.config.fetch, - }); - - return { - warnings: [], - embeddings: response.data.map(item => item.embedding), - usage: response.usage - ? { tokens: response.usage.prompt_tokens } - : undefined, - response: { headers: responseHeaders, body: rawValue }, - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/embedding/openai-embedding-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/embedding/openai-embedding-options.ts deleted file mode 100644 index 54d7ff077..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/embedding/openai-embedding-options.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export type OpenAIEmbeddingModelId = - | 'text-embedding-3-small' - | 'text-embedding-3-large' - | 'text-embedding-ada-002' - | (string & {}); - -export const openaiEmbeddingModelOptions = lazySchema(() => - zodSchema( - z.object({ - /** - * The number of dimensions the resulting output embeddings should have. - * Only supported in text-embedding-3 and later models. - */ - dimensions: z.number().optional(), - - /** - * A unique identifier representing your end-user, which can help OpenAI to - * monitor and detect abuse. Learn more. - */ - user: z.string().optional(), - }), - ), -); - -export type OpenAIEmbeddingModelOptions = InferSchema< - typeof openaiEmbeddingModelOptions ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/image/openai-image-api.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/image/openai-image-api.ts deleted file mode 100644 index de779ca46..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/image/openai-image-api.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -// minimal version of the schema, focused on what is needed for the implementation -// this approach limits breakages when the API changes and increases efficiency -export const openaiImageResponseSchema = lazySchema(() => - zodSchema( - z.object({ - created: z.number().nullish(), - data: z.array( - z.object({ - b64_json: z.string(), - revised_prompt: z.string().nullish(), - }), - ), - background: z.string().nullish(), - output_format: z.string().nullish(), - size: z.string().nullish(), - quality: z.string().nullish(), - usage: z - .object({ - input_tokens: z.number().nullish(), - output_tokens: z.number().nullish(), - total_tokens: z.number().nullish(), - input_tokens_details: z - .object({ - image_tokens: z.number().nullish(), - text_tokens: z.number().nullish(), - }) - .nullish(), - }) - .nullish(), - }), - ), -); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/image/openai-image-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/image/openai-image-model.ts deleted file mode 100644 index d456d6398..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/image/openai-image-model.ts +++ /dev/null @@ -1,349 +0,0 @@ -import { - ImageModelV3, - ImageModelV3File, - SharedV3Warning, -} from '@ai-sdk/provider'; -import { - combineHeaders, - convertBase64ToUint8Array, - convertToFormData, - createJsonResponseHandler, - downloadBlob, - postFormDataToApi, - postJsonToApi, -} from '@ai-sdk/provider-utils'; -import { OpenAIConfig } from '../openai-config'; -import { openaiFailedResponseHandler } from '../openai-error'; -import { openaiImageResponseSchema } from './openai-image-api'; -import { - OpenAIImageModelId, - hasDefaultResponseFormat, - modelMaxImagesPerCall, -} from './openai-image-options'; - -interface OpenAIImageModelConfig extends OpenAIConfig { - _internal?: { - currentDate?: () => Date; - }; -} - -export class OpenAIImageModel implements ImageModelV3 { - readonly specificationVersion = 'v3'; - - get maxImagesPerCall(): number { - return modelMaxImagesPerCall[this.modelId] ?? 1; - } - - get provider(): string { - return this.config.provider; - } - - constructor( - readonly modelId: OpenAIImageModelId, - private readonly config: OpenAIImageModelConfig, - ) {} - - async doGenerate({ - prompt, - files, - mask, - n, - size, - aspectRatio, - seed, - providerOptions, - headers, - abortSignal, - }: Parameters[0]): Promise< - Awaited> - > { - const warnings: Array = []; - - if (aspectRatio != null) { - warnings.push({ - type: 'unsupported', - feature: 'aspectRatio', - details: - 'This model does not support aspect ratio. Use `size` instead.', - }); - } - - if (seed != null) { - warnings.push({ type: 'unsupported', feature: 'seed' }); - } - - const currentDate = this.config._internal?.currentDate?.() ?? new Date(); - - if (files != null) { - const { value: response, responseHeaders } = await postFormDataToApi({ - url: this.config.url({ - path: '/images/edits', - modelId: this.modelId, - }), - headers: combineHeaders(this.config.headers(), headers), - formData: convertToFormData({ - model: this.modelId, - prompt, - image: await Promise.all( - files.map(file => - file.type === 'file' - ? new Blob( - [ - file.data instanceof Uint8Array - ? new Blob([file.data as BlobPart], { - type: file.mediaType, - }) - : new Blob([convertBase64ToUint8Array(file.data)], { - type: file.mediaType, - }), - ], - { type: file.mediaType }, - ) - : downloadBlob(file.url), - ), - ), - mask: mask != null ? await fileToBlob(mask) : undefined, - n, - size, - ...(providerOptions.openai ?? {}), - }), - failedResponseHandler: openaiFailedResponseHandler, - successfulResponseHandler: createJsonResponseHandler( - openaiImageResponseSchema, - ), - abortSignal, - fetch: this.config.fetch, - }); - - return { - images: response.data.map(item => item.b64_json), - warnings, - usage: - response.usage != null - ? { - inputTokens: response.usage.input_tokens ?? undefined, - outputTokens: response.usage.output_tokens ?? undefined, - totalTokens: response.usage.total_tokens ?? undefined, - } - : undefined, - response: { - timestamp: currentDate, - modelId: this.modelId, - headers: responseHeaders, - }, - providerMetadata: { - openai: { - images: response.data.map((item, index) => ({ - ...(item.revised_prompt - ? { revisedPrompt: item.revised_prompt } - : {}), - created: response.created ?? undefined, - size: response.size ?? undefined, - quality: response.quality ?? undefined, - background: response.background ?? undefined, - outputFormat: response.output_format ?? undefined, - ...distributeTokenDetails( - response.usage?.input_tokens_details, - index, - response.data.length, - ), - })), - }, - }, - }; - } - - const { value: response, responseHeaders } = await postJsonToApi({ - url: this.config.url({ - path: '/images/generations', - modelId: this.modelId, - }), - headers: combineHeaders(this.config.headers(), headers), - body: { - model: this.modelId, - prompt, - n, - size, - ...(providerOptions.openai ?? {}), - ...(!hasDefaultResponseFormat(this.modelId) - ? { response_format: 'b64_json' } - : {}), - }, - failedResponseHandler: openaiFailedResponseHandler, - successfulResponseHandler: createJsonResponseHandler( - openaiImageResponseSchema, - ), - abortSignal, - fetch: this.config.fetch, - }); - - return { - images: response.data.map(item => item.b64_json), - warnings, - usage: - response.usage != null - ? { - inputTokens: response.usage.input_tokens ?? undefined, - outputTokens: response.usage.output_tokens ?? undefined, - totalTokens: response.usage.total_tokens ?? undefined, - } - : undefined, - response: { - timestamp: currentDate, - modelId: this.modelId, - headers: responseHeaders, - }, - providerMetadata: { - openai: { - images: response.data.map((item, index) => ({ - ...(item.revised_prompt - ? { revisedPrompt: item.revised_prompt } - : {}), - created: response.created ?? undefined, - size: response.size ?? undefined, - quality: response.quality ?? undefined, - background: response.background ?? undefined, - outputFormat: response.output_format ?? undefined, - ...distributeTokenDetails( - response.usage?.input_tokens_details, - index, - response.data.length, - ), - })), - }, - }, - }; - } -} - -/** - * Distributes input token details evenly across images, with the remainder - * assigned to the last image so that summing across all entries gives the - * exact total. - */ -function distributeTokenDetails( - details: - | { image_tokens?: number | null; text_tokens?: number | null } - | null - | undefined, - index: number, - total: number, -): { imageTokens?: number; textTokens?: number } { - if (details == null) { - return {}; - } - - const result: { imageTokens?: number; textTokens?: number } = {}; - - if (details.image_tokens != null) { - const base = Math.floor(details.image_tokens / total); - const remainder = details.image_tokens - base * (total - 1); - result.imageTokens = index === total - 1 ? remainder : base; - } - - if (details.text_tokens != null) { - const base = Math.floor(details.text_tokens / total); - const remainder = details.text_tokens - base * (total - 1); - result.textTokens = index === total - 1 ? remainder : base; - } - - return result; -} - -type OpenAIImageEditInput = { - /** - * Allows to set transparency for the background of the generated image(s). - * This parameter is only supported for `gpt-image-1`. Must be one of - * `transparent`, `opaque` or `auto` (default value). When `auto` is used, the - * model will automatically determine the best background for the image. - * - * If `transparent`, the output format needs to support transparency, so it - * should be set to either `png` (default value) or `webp`. - * - */ - background?: 'transparent' | 'opaque' | 'auto'; - /** - * The image(s) to edit. Must be a supported image file or an array of images. - * - * For `gpt-image-1`, each image should be a `png`, `webp`, or `jpg` file less - * than 50MB. You can provide up to 16 images. - * - * For `dall-e-2`, you can only provide one image, and it should be a square - * `png` file less than 4MB. - * - */ - image: Blob | Blob[]; - input_fidelity?: ('high' | 'low') | null; - /** - * An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where `image` should be edited. If there are multiple images provided, the mask will be applied on the first image. Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`. - */ - mask?: Blob; - /** - * The model to use for image generation. Only `dall-e-2` and `gpt-image-1` are supported. Defaults to `dall-e-2` unless a parameter specific to `gpt-image-1` is used. - */ - model?: 'dall-e-2' | 'gpt-image-1' | 'gpt-image-1-mini' | (string & {}); - /** - * The number of images to generate. Must be between 1 and 10. - */ - n?: number; - /** - * The compression level (0-100%) for the generated images. This parameter - * is only supported for `gpt-image-1` with the `webp` or `jpeg` output - * formats, and defaults to 100. - * - */ - output_compression?: number; - /** - * The format in which the generated images are returned. This parameter is - * only supported for `gpt-image-1`. Must be one of `png`, `jpeg`, or `webp`. - * The default value is `png`. - * - */ - output_format?: 'png' | 'jpeg' | 'webp'; - partial_images?: number | null; - /** - * A text description of the desired image(s). The maximum length is 1000 characters for `dall-e-2`, and 32000 characters for `gpt-image-1`. - */ - prompt?: string; - /** - * The quality of the image that will be generated. `high`, `medium` and `low` are only supported for `gpt-image-1`. `dall-e-2` only supports `standard` quality. Defaults to `auto`. - * - */ - quality?: 'standard' | 'low' | 'medium' | 'high' | 'auto'; - /** - * The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter is only supported for `dall-e-2`, as `gpt-image-1` will always return base64-encoded images. - */ - response_format?: 'url' | 'b64_json'; - /** - * The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for `gpt-image-1`, and one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`. - */ - size?: `${number}x${number}`; - /** - * Edit the image in streaming mode. Defaults to `false`. See the - * [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. - * - */ - stream?: boolean; - /** - * A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). - * - */ - user?: string; -}; - -async function fileToBlob( - file: ImageModelV3File | undefined, -): Promise { - if (!file) return undefined; - - if (file.type === 'url') { - return downloadBlob(file.url); - } - - const data = - file.data instanceof Uint8Array - ? file.data - : convertBase64ToUint8Array(file.data); - - return new Blob([data as BlobPart], { type: file.mediaType }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/image/openai-image-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/image/openai-image-options.ts deleted file mode 100644 index 2ee92ea5e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/image/openai-image-options.ts +++ /dev/null @@ -1,31 +0,0 @@ -export type OpenAIImageModelId = - | 'dall-e-3' - | 'dall-e-2' - | 'gpt-image-1' - | 'gpt-image-1-mini' - | 'gpt-image-1.5' - | 'chatgpt-image-latest' - | (string & {}); - -// https://platform.openai.com/docs/guides/images -export const modelMaxImagesPerCall: Record = { - 'dall-e-3': 1, - 'dall-e-2': 10, - 'gpt-image-1': 10, - 'gpt-image-1-mini': 10, - 'gpt-image-1.5': 10, - 'chatgpt-image-latest': 10, -}; - -const defaultResponseFormatPrefixes = [ - 'chatgpt-image-', - 'gpt-image-1-mini', - 'gpt-image-1.5', - 'gpt-image-1', -]; - -export function hasDefaultResponseFormat(modelId: string): boolean { - return defaultResponseFormatPrefixes.some(prefix => - modelId.startsWith(prefix), - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/index.ts deleted file mode 100644 index 22e3ceed8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -export { createOpenAI, openai } from './openai-provider'; -export type { OpenAIProvider, OpenAIProviderSettings } from './openai-provider'; -export type { - OpenAILanguageModelResponsesOptions, - /** @deprecated Use `OpenAILanguageModelResponsesOptions` instead. */ - OpenAILanguageModelResponsesOptions as OpenAIResponsesProviderOptions, -} from './responses/openai-responses-options'; -export type { - OpenAILanguageModelChatOptions, - /** @deprecated Use `OpenAILanguageModelChatOptions` instead. */ - OpenAILanguageModelChatOptions as OpenAIChatLanguageModelOptions, -} from './chat/openai-chat-options'; -export type { OpenAILanguageModelCompletionOptions } from './completion/openai-completion-options'; -export type { OpenAIEmbeddingModelOptions } from './embedding/openai-embedding-options'; -export type { OpenAISpeechModelOptions } from './speech/openai-speech-options'; -export type { OpenAITranscriptionModelOptions } from './transcription/openai-transcription-options'; -export type { - OpenaiResponsesProviderMetadata, - OpenaiResponsesReasoningProviderMetadata, - OpenaiResponsesTextProviderMetadata, - OpenaiResponsesSourceDocumentProviderMetadata, -} from './responses/openai-responses-provider-metadata'; -export { VERSION } from './version'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/internal/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/internal/index.ts deleted file mode 100644 index 0a79d3f71..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/internal/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -export * from '../chat/openai-chat-language-model'; -export * from '../chat/openai-chat-options'; -export * from '../completion/openai-completion-language-model'; -export * from '../completion/openai-completion-options'; -export * from '../embedding/openai-embedding-model'; -export * from '../embedding/openai-embedding-options'; -export * from '../image/openai-image-model'; -export * from '../image/openai-image-options'; -export * from '../transcription/openai-transcription-model'; -export * from '../transcription/openai-transcription-options'; -export * from '../speech/openai-speech-model'; -export * from '../speech/openai-speech-options'; -export * from '../responses/openai-responses-language-model'; -export * from '../responses/openai-responses-provider-metadata'; -export * from '../tool/apply-patch'; -export * from '../tool/code-interpreter'; -export * from '../tool/file-search'; -export * from '../tool/image-generation'; -export * from '../tool/web-search-preview'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-config.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-config.ts deleted file mode 100644 index 6f41ff698..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { FetchFunction } from '@ai-sdk/provider-utils'; - -export type OpenAIConfig = { - provider: string; - url: (options: { modelId: string; path: string }) => string; - headers: () => Record; - fetch?: FetchFunction; - generateId?: () => string; - /** - * File ID prefixes used to identify file IDs in Responses API. - * When undefined, all file data is treated as base64 content. - * - * Examples: - * - OpenAI: ['file-'] for IDs like 'file-abc123' - * - Azure OpenAI: ['assistant-'] for IDs like 'assistant-abc123' - */ - fileIdPrefixes?: readonly string[]; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-error.ts deleted file mode 100644 index d8d59a515..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-error.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { z } from 'zod/v4'; -import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils'; - -export const openaiErrorDataSchema = z.object({ - error: z.object({ - message: z.string(), - - // The additional information below is handled loosely to support - // OpenAI-compatible providers that have slightly different error - // responses: - type: z.string().nullish(), - param: z.any().nullish(), - code: z.union([z.string(), z.number()]).nullish(), - }), -}); - -export type OpenAIErrorData = z.infer; - -export const openaiFailedResponseHandler = createJsonErrorResponseHandler({ - errorSchema: openaiErrorDataSchema, - errorToMessage: data => data.error.message, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-language-model-capabilities.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-language-model-capabilities.ts deleted file mode 100644 index 3d926d6ca..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-language-model-capabilities.ts +++ /dev/null @@ -1,55 +0,0 @@ -export type OpenAILanguageModelCapabilities = { - isReasoningModel: boolean; - systemMessageMode: 'remove' | 'system' | 'developer'; - supportsFlexProcessing: boolean; - supportsPriorityProcessing: boolean; - - /** - * Allow temperature, topP, logProbs when reasoningEffort is none. - */ - supportsNonReasoningParameters: boolean; -}; - -export function getOpenAILanguageModelCapabilities( - modelId: string, -): OpenAILanguageModelCapabilities { - const supportsFlexProcessing = - modelId.startsWith('o3') || - modelId.startsWith('o4-mini') || - (modelId.startsWith('gpt-5') && !modelId.startsWith('gpt-5-chat')); - - const supportsPriorityProcessing = - modelId.startsWith('gpt-4') || - (modelId.startsWith('gpt-5') && - !modelId.startsWith('gpt-5-nano') && - !modelId.startsWith('gpt-5-chat') && - !modelId.startsWith('gpt-5.4-nano')) || - modelId.startsWith('o3') || - modelId.startsWith('o4-mini'); - - // Use allowlist approach: only known reasoning models should use 'developer' role - // This prevents issues with fine-tuned models, third-party models, and custom models - const isReasoningModel = - modelId.startsWith('o1') || - modelId.startsWith('o3') || - modelId.startsWith('o4-mini') || - (modelId.startsWith('gpt-5') && !modelId.startsWith('gpt-5-chat')); - - // https://platform.openai.com/docs/guides/latest-model#gpt-5-1-parameter-compatibility - // GPT-5.1, GPT-5.2, and GPT-5.4 support temperature, topP, logProbs when reasoningEffort is none - const supportsNonReasoningParameters = - modelId.startsWith('gpt-5.1') || - modelId.startsWith('gpt-5.2') || - modelId.startsWith('gpt-5.3') || - modelId.startsWith('gpt-5.4'); - - const systemMessageMode = isReasoningModel ? 'developer' : 'system'; - - return { - supportsFlexProcessing, - supportsPriorityProcessing, - isReasoningModel, - systemMessageMode, - supportsNonReasoningParameters, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-provider.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-provider.ts deleted file mode 100644 index 1dd6d7609..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-provider.ts +++ /dev/null @@ -1,270 +0,0 @@ -import { - EmbeddingModelV3, - ImageModelV3, - LanguageModelV3, - ProviderV3, - SpeechModelV3, - TranscriptionModelV3, -} from '@ai-sdk/provider'; -import { - FetchFunction, - loadApiKey, - loadOptionalSetting, - withoutTrailingSlash, - withUserAgentSuffix, -} from '@ai-sdk/provider-utils'; -import { OpenAIChatLanguageModel } from './chat/openai-chat-language-model'; -import { OpenAIChatModelId } from './chat/openai-chat-options'; -import { OpenAICompletionLanguageModel } from './completion/openai-completion-language-model'; -import { OpenAICompletionModelId } from './completion/openai-completion-options'; -import { OpenAIEmbeddingModel } from './embedding/openai-embedding-model'; -import { OpenAIEmbeddingModelId } from './embedding/openai-embedding-options'; -import { OpenAIImageModel } from './image/openai-image-model'; -import { OpenAIImageModelId } from './image/openai-image-options'; -import { openaiTools } from './openai-tools'; -import { OpenAIResponsesLanguageModel } from './responses/openai-responses-language-model'; -import { OpenAIResponsesModelId } from './responses/openai-responses-options'; -import { OpenAISpeechModel } from './speech/openai-speech-model'; -import { OpenAISpeechModelId } from './speech/openai-speech-options'; -import { OpenAITranscriptionModel } from './transcription/openai-transcription-model'; -import { OpenAITranscriptionModelId } from './transcription/openai-transcription-options'; -import { VERSION } from './version'; - -export interface OpenAIProvider extends ProviderV3 { - (modelId: OpenAIResponsesModelId): LanguageModelV3; - - /** - * Creates an OpenAI model for text generation. - */ - languageModel(modelId: OpenAIResponsesModelId): LanguageModelV3; - - /** - * Creates an OpenAI chat model for text generation. - */ - chat(modelId: OpenAIChatModelId): LanguageModelV3; - - /** - * Creates an OpenAI responses API model for text generation. - */ - responses(modelId: OpenAIResponsesModelId): LanguageModelV3; - - /** - * Creates an OpenAI completion model for text generation. - */ - completion(modelId: OpenAICompletionModelId): LanguageModelV3; - - /** - * Creates a model for text embeddings. - */ - embedding(modelId: OpenAIEmbeddingModelId): EmbeddingModelV3; - - /** - * Creates a model for text embeddings. - */ - embeddingModel(modelId: OpenAIEmbeddingModelId): EmbeddingModelV3; - - /** - * @deprecated Use `embedding` instead. - */ - textEmbedding(modelId: OpenAIEmbeddingModelId): EmbeddingModelV3; - - /** - * @deprecated Use `embeddingModel` instead. - */ - textEmbeddingModel(modelId: OpenAIEmbeddingModelId): EmbeddingModelV3; - - /** - * Creates a model for image generation. - */ - image(modelId: OpenAIImageModelId): ImageModelV3; - - /** - * Creates a model for image generation. - */ - imageModel(modelId: OpenAIImageModelId): ImageModelV3; - - /** - * Creates a model for transcription. - */ - transcription(modelId: OpenAITranscriptionModelId): TranscriptionModelV3; - - /** - * Creates a model for speech generation. - */ - speech(modelId: OpenAISpeechModelId): SpeechModelV3; - - /** - * OpenAI-specific tools. - */ - tools: typeof openaiTools; -} - -export interface OpenAIProviderSettings { - /** - * Base URL for the OpenAI API calls. - */ - baseURL?: string; - - /** - * API key for authenticating requests. - */ - apiKey?: string; - - /** - * OpenAI Organization. - */ - organization?: string; - - /** - * OpenAI project. - */ - project?: string; - - /** - * Custom headers to include in the requests. - */ - headers?: Record; - - /** - * Provider name. Overrides the `openai` default name for 3rd party providers. - */ - name?: string; - - /** - * Custom fetch implementation. You can use it as a middleware to intercept requests, - * or to provide a custom fetch implementation for e.g. testing. - */ - fetch?: FetchFunction; -} - -/** - * Create an OpenAI provider instance. - */ -export function createOpenAI( - options: OpenAIProviderSettings = {}, -): OpenAIProvider { - const baseURL = - withoutTrailingSlash( - loadOptionalSetting({ - settingValue: options.baseURL, - environmentVariableName: 'OPENAI_BASE_URL', - }), - ) ?? 'https://api.openai.com/v1'; - - const providerName = options.name ?? 'openai'; - - const getHeaders = () => - withUserAgentSuffix( - { - Authorization: `Bearer ${loadApiKey({ - apiKey: options.apiKey, - environmentVariableName: 'OPENAI_API_KEY', - description: 'OpenAI', - })}`, - 'OpenAI-Organization': options.organization, - 'OpenAI-Project': options.project, - ...options.headers, - }, - `ai-sdk/openai/${VERSION}`, - ); - - const createChatModel = (modelId: OpenAIChatModelId) => - new OpenAIChatLanguageModel(modelId, { - provider: `${providerName}.chat`, - url: ({ path }) => `${baseURL}${path}`, - headers: getHeaders, - fetch: options.fetch, - }); - - const createCompletionModel = (modelId: OpenAICompletionModelId) => - new OpenAICompletionLanguageModel(modelId, { - provider: `${providerName}.completion`, - url: ({ path }) => `${baseURL}${path}`, - headers: getHeaders, - fetch: options.fetch, - }); - - const createEmbeddingModel = (modelId: OpenAIEmbeddingModelId) => - new OpenAIEmbeddingModel(modelId, { - provider: `${providerName}.embedding`, - url: ({ path }) => `${baseURL}${path}`, - headers: getHeaders, - fetch: options.fetch, - }); - - const createImageModel = (modelId: OpenAIImageModelId) => - new OpenAIImageModel(modelId, { - provider: `${providerName}.image`, - url: ({ path }) => `${baseURL}${path}`, - headers: getHeaders, - fetch: options.fetch, - }); - - const createTranscriptionModel = (modelId: OpenAITranscriptionModelId) => - new OpenAITranscriptionModel(modelId, { - provider: `${providerName}.transcription`, - url: ({ path }) => `${baseURL}${path}`, - headers: getHeaders, - fetch: options.fetch, - }); - - const createSpeechModel = (modelId: OpenAISpeechModelId) => - new OpenAISpeechModel(modelId, { - provider: `${providerName}.speech`, - url: ({ path }) => `${baseURL}${path}`, - headers: getHeaders, - fetch: options.fetch, - }); - - const createLanguageModel = (modelId: OpenAIResponsesModelId) => { - if (new.target) { - throw new Error( - 'The OpenAI model function cannot be called with the new keyword.', - ); - } - - return createResponsesModel(modelId); - }; - - const createResponsesModel = (modelId: OpenAIResponsesModelId) => { - return new OpenAIResponsesLanguageModel(modelId, { - provider: `${providerName}.responses`, - url: ({ path }) => `${baseURL}${path}`, - headers: getHeaders, - fetch: options.fetch, - fileIdPrefixes: ['file-'], - }); - }; - - const provider = function (modelId: OpenAIResponsesModelId) { - return createLanguageModel(modelId); - }; - - provider.specificationVersion = 'v3' as const; - provider.languageModel = createLanguageModel; - provider.chat = createChatModel; - provider.completion = createCompletionModel; - provider.responses = createResponsesModel; - provider.embedding = createEmbeddingModel; - provider.embeddingModel = createEmbeddingModel; - provider.textEmbedding = createEmbeddingModel; - provider.textEmbeddingModel = createEmbeddingModel; - - provider.image = createImageModel; - provider.imageModel = createImageModel; - - provider.transcription = createTranscriptionModel; - provider.transcriptionModel = createTranscriptionModel; - - provider.speech = createSpeechModel; - provider.speechModel = createSpeechModel; - - provider.tools = openaiTools; - - return provider as OpenAIProvider; -} - -/** - * Default OpenAI provider instance. - */ -export const openai = createOpenAI(); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-tools.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-tools.ts deleted file mode 100644 index c6192938b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/openai-tools.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { applyPatch } from './tool/apply-patch'; -import { codeInterpreter } from './tool/code-interpreter'; -import { customTool } from './tool/custom'; -import { fileSearch } from './tool/file-search'; -import { imageGeneration } from './tool/image-generation'; -import { localShell } from './tool/local-shell'; -import { shell } from './tool/shell'; -import { toolSearch } from './tool/tool-search'; -import { webSearch } from './tool/web-search'; -import { webSearchPreview } from './tool/web-search-preview'; -import { mcp } from './tool/mcp'; - -export const openaiTools = { - /** - * The apply_patch tool lets GPT-5.1 create, update, and delete files in your - * codebase using structured diffs. Instead of just suggesting edits, the model - * emits patch operations that your application applies and then reports back on, - * enabling iterative, multi-step code editing workflows. - * - */ - applyPatch, - - /** - * Custom tools let callers constrain model output to a grammar (regex or - * Lark syntax). The model returns a `custom_tool_call` output item whose - * `input` field is a string matching the specified grammar. - * - * @param name - The name of the custom tool. - * @param description - An optional description of the tool. - * @param format - The output format constraint (grammar type, syntax, and definition). - */ - customTool, - - /** - * The Code Interpreter tool allows models to write and run Python code in a - * sandboxed environment to solve complex problems in domains like data analysis, - * coding, and math. - * - * @param container - The container to use for the code interpreter. - */ - codeInterpreter, - - /** - * File search is a tool available in the Responses API. It enables models to - * retrieve information in a knowledge base of previously uploaded files through - * semantic and keyword search. - * - * @param vectorStoreIds - The vector store IDs to use for the file search. - * @param maxNumResults - The maximum number of results to return. - * @param ranking - The ranking options to use for the file search. - * @param filters - The filters to use for the file search. - */ - fileSearch, - - /** - * The image generation tool allows you to generate images using a text prompt, - * and optionally image inputs. It leverages the GPT Image model, - * and automatically optimizes text inputs for improved performance. - * - * @param background - Background type for the generated image. One of 'auto', 'opaque', or 'transparent'. - * @param inputFidelity - Input fidelity for the generated image. One of 'low' or 'high'. - * @param inputImageMask - Optional mask for inpainting. Contains fileId and/or imageUrl. - * @param model - The image generation model to use. Default: gpt-image-1. - * @param moderation - Moderation level for the generated image. Default: 'auto'. - * @param outputCompression - Compression level for the output image (0-100). - * @param outputFormat - The output format of the generated image. One of 'png', 'jpeg', or 'webp'. - * @param partialImages - Number of partial images to generate in streaming mode (0-3). - * @param quality - The quality of the generated image. One of 'auto', 'low', 'medium', or 'high'. - * @param size - The size of the generated image. One of 'auto', '1024x1024', '1024x1536', or '1536x1024'. - */ - imageGeneration, - - /** - * Local shell is a tool that allows agents to run shell commands locally - * on a machine you or the user provides. - * - * Supported models: `gpt-5-codex` - */ - localShell, - - /** - * The shell tool allows the model to interact with your local computer through - * a controlled command-line interface. The model proposes shell commands; your - * integration executes them and returns the outputs. - * - * Available through the Responses API for use with GPT-5.1. - * - * WARNING: Running arbitrary shell commands can be dangerous. Always sandbox - * execution or add strict allow-/deny-lists before forwarding a command to - * the system shell. - */ - shell, - - /** - * Web search allows models to access up-to-date information from the internet - * and provide answers with sourced citations. - * - * @param searchContextSize - The search context size to use for the web search. - * @param userLocation - The user location to use for the web search. - */ - webSearchPreview, - - /** - * Web search allows models to access up-to-date information from the internet - * and provide answers with sourced citations. - * - * @param filters - The filters to use for the web search. - * @param searchContextSize - The search context size to use for the web search. - * @param userLocation - The user location to use for the web search. - */ - webSearch, - - /** - * MCP (Model Context Protocol) allows models to call tools exposed by - * remote MCP servers or service connectors. - * - * @param serverLabel - Label to identify the MCP server. - * @param allowedTools - Allowed tool names or filter object. - * @param authorization - OAuth access token for the MCP server/connector. - * @param connectorId - Identifier for a service connector. - * @param headers - Optional headers to include in MCP requests. - * // param requireApproval - Approval policy ('always'|'never'|filter object). (Removed - always 'never') - * @param serverDescription - Optional description of the server. - * @param serverUrl - URL for the MCP server. - */ - mcp, - - /** - * Tool search allows the model to dynamically search for and load deferred - * tools into the model's context as needed. This helps reduce overall token - * usage, cost, and latency by only loading tools when the model needs them. - * - * To use tool search, mark functions or namespaces with `defer_loading: true` - * in the tools array. The model will use tool search to load these tools - * when it determines they are needed. - */ - toolSearch, -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/convert-openai-responses-usage.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/convert-openai-responses-usage.ts deleted file mode 100644 index b40b9dec6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/convert-openai-responses-usage.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { LanguageModelV3Usage } from '@ai-sdk/provider'; - -export type OpenAIResponsesUsage = { - input_tokens: number; - output_tokens: number; - input_tokens_details?: { - cached_tokens?: number | null; - } | null; - output_tokens_details?: { - reasoning_tokens?: number | null; - } | null; -}; - -export function convertOpenAIResponsesUsage( - usage: OpenAIResponsesUsage | undefined | null, -): LanguageModelV3Usage { - if (usage == null) { - return { - inputTokens: { - total: undefined, - noCache: undefined, - cacheRead: undefined, - cacheWrite: undefined, - }, - outputTokens: { - total: undefined, - text: undefined, - reasoning: undefined, - }, - raw: undefined, - }; - } - - const inputTokens = usage.input_tokens; - const outputTokens = usage.output_tokens; - const cachedTokens = usage.input_tokens_details?.cached_tokens ?? 0; - const reasoningTokens = usage.output_tokens_details?.reasoning_tokens ?? 0; - - return { - inputTokens: { - total: inputTokens, - noCache: inputTokens - cachedTokens, - cacheRead: cachedTokens, - cacheWrite: undefined, - }, - outputTokens: { - total: outputTokens, - text: outputTokens - reasoningTokens, - reasoning: reasoningTokens, - }, - raw: usage, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/convert-to-openai-responses-input.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/convert-to-openai-responses-input.ts deleted file mode 100644 index 712a403bd..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/convert-to-openai-responses-input.ts +++ /dev/null @@ -1,839 +0,0 @@ -import { - LanguageModelV3Prompt, - LanguageModelV3ToolApprovalResponsePart, - SharedV3Warning, - UnsupportedFunctionalityError, -} from '@ai-sdk/provider'; -import { - convertToBase64, - isNonNullable, - parseJSON, - parseProviderOptions, - ToolNameMapping, - validateTypes, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import { - applyPatchInputSchema, - applyPatchOutputSchema, -} from '../tool/apply-patch'; -import { - localShellInputSchema, - localShellOutputSchema, -} from '../tool/local-shell'; -import { shellInputSchema, shellOutputSchema } from '../tool/shell'; -import { - toolSearchInputSchema, - toolSearchOutputSchema, -} from '../tool/tool-search'; -import { - OpenAIResponsesCustomToolCallOutput, - OpenAIResponsesFunctionCallOutput, - OpenAIResponsesInput, - OpenAIResponsesReasoning, -} from './openai-responses-api'; - -/** - * Check if a string is a file ID based on the given prefixes - * Returns false if prefixes is undefined (disables file ID detection) - */ -function isFileId(data: string, prefixes?: readonly string[]): boolean { - if (!prefixes) return false; - return prefixes.some(prefix => data.startsWith(prefix)); -} - -export async function convertToOpenAIResponsesInput({ - prompt, - toolNameMapping, - systemMessageMode, - providerOptionsName, - fileIdPrefixes, - store, - hasConversation = false, - hasLocalShellTool = false, - hasShellTool = false, - hasApplyPatchTool = false, - customProviderToolNames, -}: { - prompt: LanguageModelV3Prompt; - toolNameMapping: ToolNameMapping; - systemMessageMode: 'system' | 'developer' | 'remove'; - providerOptionsName: string; - fileIdPrefixes?: readonly string[]; - store: boolean; - hasConversation?: boolean; // when true, skip assistant messages that already have item IDs - hasLocalShellTool?: boolean; - hasShellTool?: boolean; - hasApplyPatchTool?: boolean; - customProviderToolNames?: Set; -}): Promise<{ - input: OpenAIResponsesInput; - warnings: Array; -}> { - let input: OpenAIResponsesInput = []; - const warnings: Array = []; - const processedApprovalIds = new Set(); - - for (const { role, content } of prompt) { - switch (role) { - case 'system': { - switch (systemMessageMode) { - case 'system': { - input.push({ role: 'system', content }); - break; - } - case 'developer': { - input.push({ role: 'developer', content }); - break; - } - case 'remove': { - warnings.push({ - type: 'other', - message: 'system messages are removed for this model', - }); - break; - } - default: { - const _exhaustiveCheck: never = systemMessageMode; - throw new Error( - `Unsupported system message mode: ${_exhaustiveCheck}`, - ); - } - } - break; - } - - case 'user': { - input.push({ - role: 'user', - content: content.map((part, index) => { - switch (part.type) { - case 'text': { - return { type: 'input_text', text: part.text }; - } - case 'file': { - if (part.mediaType.startsWith('image/')) { - const mediaType = - part.mediaType === 'image/*' - ? 'image/jpeg' - : part.mediaType; - - return { - type: 'input_image', - ...(part.data instanceof URL - ? { image_url: part.data.toString() } - : typeof part.data === 'string' && - isFileId(part.data, fileIdPrefixes) - ? { file_id: part.data } - : { - image_url: `data:${mediaType};base64,${convertToBase64(part.data)}`, - }), - detail: - part.providerOptions?.[providerOptionsName]?.imageDetail, - }; - } else if (part.mediaType === 'application/pdf') { - if (part.data instanceof URL) { - return { - type: 'input_file', - file_url: part.data.toString(), - }; - } - return { - type: 'input_file', - ...(typeof part.data === 'string' && - isFileId(part.data, fileIdPrefixes) - ? { file_id: part.data } - : { - filename: part.filename ?? `part-${index}.pdf`, - file_data: `data:application/pdf;base64,${convertToBase64(part.data)}`, - }), - }; - } else { - throw new UnsupportedFunctionalityError({ - functionality: `file part media type ${part.mediaType}`, - }); - } - } - } - }), - }); - - break; - } - - case 'assistant': { - const reasoningMessages: Record = {}; - - for (const part of content) { - switch (part.type) { - case 'text': { - const providerOpts = part.providerOptions?.[providerOptionsName]; - const id = providerOpts?.itemId as string | undefined; - const phase = providerOpts?.phase as - | 'commentary' - | 'final_answer' - | null - | undefined; - - // when using conversation, skip items that already exist in the conversation context to avoid "Duplicate item found" errors - if (hasConversation && id != null) { - break; - } - - // item references reduce the payload size - if (store && id != null) { - input.push({ type: 'item_reference', id }); - break; - } - - input.push({ - role: 'assistant', - content: [{ type: 'output_text', text: part.text }], - id, - ...(phase != null && { phase }), - }); - - break; - } - case 'tool-call': { - const id = (part.providerOptions?.[providerOptionsName]?.itemId ?? - ( - part as { - providerMetadata?: { - [providerOptionsName]?: { itemId?: string }; - }; - } - ).providerMetadata?.[providerOptionsName]?.itemId) as - | string - | undefined; - - if (hasConversation && id != null) { - break; - } - - const resolvedToolName = toolNameMapping.toProviderToolName( - part.toolName, - ); - - if (resolvedToolName === 'tool_search') { - if (store && id != null) { - input.push({ type: 'item_reference', id }); - break; - } - - const parsedInput = - typeof part.input === 'string' - ? await parseJSON({ - text: part.input, - schema: toolSearchInputSchema, - }) - : await validateTypes({ - value: part.input, - schema: toolSearchInputSchema, - }); - - const execution = - parsedInput.call_id != null ? 'client' : 'server'; - - input.push({ - type: 'tool_search_call', - id: id ?? part.toolCallId, - execution, - call_id: parsedInput.call_id ?? null, - status: 'completed', - arguments: parsedInput.arguments, - }); - break; - } - - if (part.providerExecuted) { - if (store && id != null) { - input.push({ type: 'item_reference', id }); - } - break; - } - - if (store && id != null) { - input.push({ type: 'item_reference', id }); - break; - } - - if (hasLocalShellTool && resolvedToolName === 'local_shell') { - const parsedInput = await validateTypes({ - value: part.input, - schema: localShellInputSchema, - }); - input.push({ - type: 'local_shell_call', - call_id: part.toolCallId, - id: id!, - action: { - type: 'exec', - command: parsedInput.action.command, - timeout_ms: parsedInput.action.timeoutMs, - user: parsedInput.action.user, - working_directory: parsedInput.action.workingDirectory, - env: parsedInput.action.env, - }, - }); - - break; - } - - if (hasShellTool && resolvedToolName === 'shell') { - const parsedInput = await validateTypes({ - value: part.input, - schema: shellInputSchema, - }); - input.push({ - type: 'shell_call', - call_id: part.toolCallId, - id: id!, - status: 'completed', - action: { - commands: parsedInput.action.commands, - timeout_ms: parsedInput.action.timeoutMs, - max_output_length: parsedInput.action.maxOutputLength, - }, - }); - - break; - } - - if (hasApplyPatchTool && resolvedToolName === 'apply_patch') { - const parsedInput = await validateTypes({ - value: part.input, - schema: applyPatchInputSchema, - }); - input.push({ - type: 'apply_patch_call', - call_id: parsedInput.callId, - id: id!, - status: 'completed', - operation: parsedInput.operation, - }); - - break; - } - - if (customProviderToolNames?.has(resolvedToolName)) { - input.push({ - type: 'custom_tool_call', - call_id: part.toolCallId, - name: resolvedToolName, - input: - typeof part.input === 'string' - ? part.input - : JSON.stringify(part.input), - id, - }); - break; - } - - input.push({ - type: 'function_call', - call_id: part.toolCallId, - name: resolvedToolName, - arguments: JSON.stringify(part.input), - id, - }); - break; - } - - // assistant tool result parts are from provider-executed tools: - case 'tool-result': { - // Skip execution-denied results - these are synthetic results from denied - // approvals and have no corresponding item in OpenAI's store. - // Check both the direct type and if it was transformed to json with execution-denied inside - if ( - part.output.type === 'execution-denied' || - (part.output.type === 'json' && - typeof part.output.value === 'object' && - part.output.value != null && - 'type' in part.output.value && - part.output.value.type === 'execution-denied') - ) { - break; - } - - if (hasConversation) { - break; - } - - const resolvedResultToolName = toolNameMapping.toProviderToolName( - part.toolName, - ); - - if (resolvedResultToolName === 'tool_search') { - const itemId = - ( - part.providerOptions?.[providerOptionsName] as - | { itemId?: string } - | undefined - )?.itemId ?? part.toolCallId; - - if (store) { - input.push({ type: 'item_reference', id: itemId }); - } else if (part.output.type === 'json') { - const parsedOutput = await validateTypes({ - value: part.output.value, - schema: toolSearchOutputSchema, - }); - - input.push({ - type: 'tool_search_output', - id: itemId, - execution: 'server', - call_id: null, - status: 'completed', - tools: parsedOutput.tools, - }); - } - - break; - } - - /* - * Shell tool results are separate output items (shell_call_output) - * with their own item IDs distinct from the shell_call's item ID. - * Since the pipeline only preserves the shell_call's item ID in - * callProviderMetadata, we reconstruct the full shell_call_output - * instead of using an item_reference with the wrong ID. - */ - if (hasShellTool && resolvedResultToolName === 'shell') { - if (part.output.type === 'json') { - const parsedOutput = await validateTypes({ - value: part.output.value, - schema: shellOutputSchema, - }); - input.push({ - type: 'shell_call_output', - call_id: part.toolCallId, - output: parsedOutput.output.map(item => ({ - stdout: item.stdout, - stderr: item.stderr, - outcome: - item.outcome.type === 'timeout' - ? { type: 'timeout' as const } - : { - type: 'exit' as const, - exit_code: item.outcome.exitCode, - }, - })), - }); - } - break; - } - - if (store) { - const itemId = - ( - part.providerOptions?.[providerOptionsName] as - | { itemId?: string } - | undefined - )?.itemId ?? part.toolCallId; - input.push({ type: 'item_reference', id: itemId }); - } else { - warnings.push({ - type: 'other', - message: `Results for OpenAI tool ${part.toolName} are not sent to the API when store is false`, - }); - } - - break; - } - - case 'reasoning': { - const providerOptions = await parseProviderOptions({ - provider: providerOptionsName, - providerOptions: part.providerOptions, - schema: openaiResponsesReasoningProviderOptionsSchema, - }); - - const reasoningId = providerOptions?.itemId; - - if (hasConversation && reasoningId != null) { - break; - } - - if (reasoningId != null) { - const reasoningMessage = reasoningMessages[reasoningId]; - - if (store) { - // use item references to refer to reasoning (single reference) - // when the first part is encountered - if (reasoningMessage === undefined) { - input.push({ type: 'item_reference', id: reasoningId }); - - // store unused reasoning message to mark id as used - reasoningMessages[reasoningId] = { - type: 'reasoning', - id: reasoningId, - summary: [], - }; - } - } else { - const summaryParts: Array<{ - type: 'summary_text'; - text: string; - }> = []; - - if (part.text.length > 0) { - summaryParts.push({ - type: 'summary_text', - text: part.text, - }); - } else if (reasoningMessage !== undefined) { - warnings.push({ - type: 'other', - message: `Cannot append empty reasoning part to existing reasoning sequence. Skipping reasoning part: ${JSON.stringify(part)}.`, - }); - } - - if (reasoningMessage === undefined) { - reasoningMessages[reasoningId] = { - type: 'reasoning', - id: reasoningId, - encrypted_content: - providerOptions?.reasoningEncryptedContent, - summary: summaryParts, - }; - input.push(reasoningMessages[reasoningId]); - } else { - reasoningMessage.summary.push(...summaryParts); - - // updated encrypted content to enable setting it in the last summary part: - if (providerOptions?.reasoningEncryptedContent != null) { - reasoningMessage.encrypted_content = - providerOptions.reasoningEncryptedContent; - } - } - } - } else { - // No itemId — fall back to encrypted_content if available. - // The OpenAI Responses API accepts reasoning items without an - // id when encrypted_content is provided, enabling multi-turn - // reasoning even when server-side item persistence is not used - // or when itemId has been stripped from providerOptions. - const encryptedContent = - providerOptions?.reasoningEncryptedContent; - - if (encryptedContent != null) { - const summaryParts: Array<{ - type: 'summary_text'; - text: string; - }> = []; - if (part.text.length > 0) { - summaryParts.push({ - type: 'summary_text', - text: part.text, - }); - } - input.push({ - type: 'reasoning', - encrypted_content: encryptedContent, - summary: summaryParts, - }); - } else { - warnings.push({ - type: 'other', - message: `Non-OpenAI reasoning parts are not supported. Skipping reasoning part: ${JSON.stringify(part)}.`, - }); - } - } - break; - } - } - } - - break; - } - - case 'tool': { - for (const part of content) { - if (part.type === 'tool-approval-response') { - const approvalResponse = - part as LanguageModelV3ToolApprovalResponsePart; - - if (processedApprovalIds.has(approvalResponse.approvalId)) { - continue; - } - processedApprovalIds.add(approvalResponse.approvalId); - - if (store) { - input.push({ - type: 'item_reference', - id: approvalResponse.approvalId, - }); - } - - input.push({ - type: 'mcp_approval_response', - approval_request_id: approvalResponse.approvalId, - approve: approvalResponse.approved, - }); - continue; - } - - const output = part.output; - - // Skip execution-denied with approvalId - already handled via tool-approval-response - if (output.type === 'execution-denied') { - const approvalId = ( - output.providerOptions?.openai as { approvalId?: string } - )?.approvalId; - - if (approvalId) { - continue; - } - } - - const resolvedToolName = toolNameMapping.toProviderToolName( - part.toolName, - ); - - if (resolvedToolName === 'tool_search' && output.type === 'json') { - const parsedOutput = await validateTypes({ - value: output.value, - schema: toolSearchOutputSchema, - }); - - input.push({ - type: 'tool_search_output', - execution: 'client', - call_id: part.toolCallId, - status: 'completed', - tools: parsedOutput.tools, - }); - continue; - } - - if ( - hasLocalShellTool && - resolvedToolName === 'local_shell' && - output.type === 'json' - ) { - const parsedOutput = await validateTypes({ - value: output.value, - schema: localShellOutputSchema, - }); - - input.push({ - type: 'local_shell_call_output', - call_id: part.toolCallId, - output: parsedOutput.output, - }); - continue; - } - - if ( - hasShellTool && - resolvedToolName === 'shell' && - output.type === 'json' - ) { - const parsedOutput = await validateTypes({ - value: output.value, - schema: shellOutputSchema, - }); - - input.push({ - type: 'shell_call_output', - call_id: part.toolCallId, - output: parsedOutput.output.map(item => ({ - stdout: item.stdout, - stderr: item.stderr, - outcome: - item.outcome.type === 'timeout' - ? { type: 'timeout' as const } - : { - type: 'exit' as const, - exit_code: item.outcome.exitCode, - }, - })), - }); - continue; - } - - if ( - hasApplyPatchTool && - part.toolName === 'apply_patch' && - output.type === 'json' - ) { - const parsedOutput = await validateTypes({ - value: output.value, - schema: applyPatchOutputSchema, - }); - - input.push({ - type: 'apply_patch_call_output', - call_id: part.toolCallId, - status: parsedOutput.status, - output: parsedOutput.output, - }); - continue; - } - - if (customProviderToolNames?.has(resolvedToolName)) { - let outputValue: OpenAIResponsesCustomToolCallOutput['output']; - switch (output.type) { - case 'text': - case 'error-text': - outputValue = output.value; - break; - case 'execution-denied': - outputValue = output.reason ?? 'Tool execution denied.'; - break; - case 'json': - case 'error-json': - outputValue = JSON.stringify(output.value); - break; - case 'content': - outputValue = output.value - .map(item => { - switch (item.type) { - case 'text': - return { type: 'input_text' as const, text: item.text }; - case 'image-data': - return { - type: 'input_image' as const, - image_url: `data:${item.mediaType};base64,${item.data}`, - }; - case 'image-url': - return { - type: 'input_image' as const, - image_url: item.url, - }; - case 'file-data': - return { - type: 'input_file' as const, - filename: item.filename ?? 'data', - file_data: `data:${item.mediaType};base64,${item.data}`, - }; - default: - warnings.push({ - type: 'other', - message: `unsupported custom tool content part type: ${item.type}`, - }); - return undefined; - } - }) - .filter(isNonNullable); - break; - default: - outputValue = ''; - } - input.push({ - type: 'custom_tool_call_output', - call_id: part.toolCallId, - output: outputValue, - } satisfies OpenAIResponsesCustomToolCallOutput); - continue; - } - - let contentValue: OpenAIResponsesFunctionCallOutput['output']; - switch (output.type) { - case 'text': - case 'error-text': - contentValue = output.value; - break; - case 'execution-denied': - contentValue = output.reason ?? 'Tool execution denied.'; - break; - case 'json': - case 'error-json': - contentValue = JSON.stringify(output.value); - break; - case 'content': - contentValue = output.value - .map(item => { - switch (item.type) { - case 'text': { - return { type: 'input_text' as const, text: item.text }; - } - - case 'image-data': { - return { - type: 'input_image' as const, - image_url: `data:${item.mediaType};base64,${item.data}`, - }; - } - - case 'image-url': { - return { - type: 'input_image' as const, - image_url: item.url, - }; - } - - case 'file-data': { - return { - type: 'input_file' as const, - filename: item.filename ?? 'data', - file_data: `data:${item.mediaType};base64,${item.data}`, - }; - } - - default: { - warnings.push({ - type: 'other', - message: `unsupported tool content part type: ${item.type}`, - }); - return undefined; - } - } - }) - .filter(isNonNullable); - break; - } - - input.push({ - type: 'function_call_output', - call_id: part.toolCallId, - output: contentValue, - }); - } - - break; - } - - default: { - const _exhaustiveCheck: never = role; - throw new Error(`Unsupported role: ${_exhaustiveCheck}`); - } - } - } - - // when store is false, remove reasoning parts without encrypted content - if ( - !store && - input.some( - item => - 'type' in item && - item.type === 'reasoning' && - item.encrypted_content == null, - ) - ) { - warnings.push({ - type: 'other', - message: - 'Reasoning parts without encrypted content are not supported when store is false. Skipping reasoning parts.', - }); - input = input.filter( - item => - !('type' in item) || - item.type !== 'reasoning' || - item.encrypted_content != null, - ); - } - - return { input, warnings }; -} - -const openaiResponsesReasoningProviderOptionsSchema = z.object({ - itemId: z.string().nullish(), - reasoningEncryptedContent: z.string().nullish(), -}); - -export type OpenAIResponsesReasoningProviderOptions = z.infer< - typeof openaiResponsesReasoningProviderOptionsSchema ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/map-openai-responses-finish-reason.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/map-openai-responses-finish-reason.ts deleted file mode 100644 index f925d4992..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/map-openai-responses-finish-reason.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { LanguageModelV3FinishReason } from '@ai-sdk/provider'; - -export function mapOpenAIResponseFinishReason({ - finishReason, - hasFunctionCall, -}: { - finishReason: string | null | undefined; - // flag that checks if there have been client-side tool calls (not executed by openai) - hasFunctionCall: boolean; -}): LanguageModelV3FinishReason['unified'] { - switch (finishReason) { - case undefined: - case null: - return hasFunctionCall ? 'tool-calls' : 'stop'; - case 'max_output_tokens': - return 'length'; - case 'content_filter': - return 'content-filter'; - default: - return hasFunctionCall ? 'tool-calls' : 'other'; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-api.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-api.ts deleted file mode 100644 index 511b000ff..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-api.ts +++ /dev/null @@ -1,1371 +0,0 @@ -import { JSONObject, JSONSchema7, JSONValue } from '@ai-sdk/provider'; -import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -const jsonValueSchema: z.ZodType = z.lazy(() => - z.union([ - z.string(), - z.number(), - z.boolean(), - z.null(), - z.array(jsonValueSchema), - z.record(z.string(), jsonValueSchema.optional()), - ]), -); - -export type OpenAIResponsesInput = Array; - -export type OpenAIResponsesInputItem = - | OpenAIResponsesSystemMessage - | OpenAIResponsesUserMessage - | OpenAIResponsesAssistantMessage - | OpenAIResponsesFunctionCall - | OpenAIResponsesFunctionCallOutput - | OpenAIResponsesCustomToolCall - | OpenAIResponsesCustomToolCallOutput - | OpenAIResponsesMcpApprovalResponse - | OpenAIResponsesComputerCall - | OpenAIResponsesLocalShellCall - | OpenAIResponsesLocalShellCallOutput - | OpenAIResponsesShellCall - | OpenAIResponsesShellCallOutput - | OpenAIResponsesApplyPatchCall - | OpenAIResponsesApplyPatchCallOutput - | OpenAIResponsesToolSearchCall - | OpenAIResponsesToolSearchOutput - | OpenAIResponsesReasoning - | OpenAIResponsesItemReference; - -export type OpenAIResponsesIncludeValue = - | 'web_search_call.action.sources' - | 'code_interpreter_call.outputs' - | 'computer_call_output.output.image_url' - | 'file_search_call.results' - | 'message.input_image.image_url' - | 'message.output_text.logprobs' - | 'reasoning.encrypted_content'; - -export type OpenAIResponsesIncludeOptions = - | Array - | undefined - | null; - -export type OpenAIResponsesApplyPatchOperationDiffDeltaChunk = { - type: 'response.apply_patch_call_operation_diff.delta'; - item_id: string; - output_index: number; - delta: string; - obfuscation?: string | null; -}; - -export type OpenAIResponsesApplyPatchOperationDiffDoneChunk = { - type: 'response.apply_patch_call_operation_diff.done'; - item_id: string; - output_index: number; - diff: string; -}; - -export type OpenAIResponsesSystemMessage = { - role: 'system' | 'developer'; - content: string; -}; - -export type OpenAIResponsesUserMessage = { - role: 'user'; - content: Array< - | { type: 'input_text'; text: string } - | { type: 'input_image'; image_url: string } - | { type: 'input_image'; file_id: string } - | { type: 'input_file'; file_url: string } - | { type: 'input_file'; filename: string; file_data: string } - | { type: 'input_file'; file_id: string } - >; -}; - -export type OpenAIResponsesAssistantMessage = { - role: 'assistant'; - content: Array<{ type: 'output_text'; text: string }>; - id?: string; - phase?: 'commentary' | 'final_answer' | null; -}; - -export type OpenAIResponsesFunctionCall = { - type: 'function_call'; - call_id: string; - name: string; - arguments: string; - id?: string; -}; - -export type OpenAIResponsesFunctionCallOutput = { - type: 'function_call_output'; - call_id: string; - output: - | string - | Array< - | { type: 'input_text'; text: string } - | { type: 'input_image'; image_url: string } - | { type: 'input_file'; filename: string; file_data: string } - >; -}; - -export type OpenAIResponsesCustomToolCall = { - type: 'custom_tool_call'; - id?: string; - call_id: string; - name: string; - input: string; -}; - -export type OpenAIResponsesCustomToolCallOutput = { - type: 'custom_tool_call_output'; - call_id: string; - output: OpenAIResponsesFunctionCallOutput['output']; -}; - -export type OpenAIResponsesMcpApprovalResponse = { - type: 'mcp_approval_response'; - approval_request_id: string; - approve: boolean; -}; - -export type OpenAIResponsesComputerCall = { - type: 'computer_call'; - id: string; - status?: string; -}; - -export type OpenAIResponsesLocalShellCall = { - type: 'local_shell_call'; - id: string; - call_id: string; - action: { - type: 'exec'; - command: string[]; - timeout_ms?: number; - user?: string; - working_directory?: string; - env?: Record; - }; -}; - -export type OpenAIResponsesLocalShellCallOutput = { - type: 'local_shell_call_output'; - call_id: string; - output: string; -}; - -/** - * Official OpenAI API Specifications: https://platform.openai.com/docs/api-reference/responses/object#responses-object-output-shell_tool_call - */ -export type OpenAIResponsesShellCall = { - type: 'shell_call'; - id: string; - call_id: string; - status: 'in_progress' | 'completed' | 'incomplete'; - action: { - commands: string[]; - timeout_ms?: number; - max_output_length?: number; - }; -}; - -export type OpenAIResponsesShellCallOutput = { - type: 'shell_call_output'; - id?: string; - call_id: string; - status?: 'in_progress' | 'completed' | 'incomplete'; - max_output_length?: number | null; - output: Array<{ - stdout: string; - stderr: string; - outcome: { type: 'timeout' } | { type: 'exit'; exit_code: number }; - }>; -}; - -export type OpenAIResponsesApplyPatchCall = { - type: 'apply_patch_call'; - id?: string; - call_id: string; - status: 'in_progress' | 'completed'; - operation: - | { - type: 'create_file'; - path: string; - diff: string; - } - | { - type: 'delete_file'; - path: string; - } - | { - type: 'update_file'; - path: string; - diff: string; - }; -}; - -export type OpenAIResponsesApplyPatchCallOutput = { - type: 'apply_patch_call_output'; - call_id: string; - status: 'completed' | 'failed'; - output?: string; -}; - -export type OpenAIResponsesToolSearchCall = { - type: 'tool_search_call'; - id: string; - execution: 'server' | 'client'; - call_id: string | null; - status: 'in_progress' | 'completed' | 'incomplete'; - arguments: unknown; -}; - -export type OpenAIResponsesToolSearchOutput = { - type: 'tool_search_output'; - id?: string; - execution: 'server' | 'client'; - call_id: string | null; - status: 'in_progress' | 'completed' | 'incomplete'; - tools: Array; -}; - -export type OpenAIResponsesItemReference = { - type: 'item_reference'; - id: string; -}; - -/** - * A filter used to compare a specified attribute key to a given value using a defined comparison operation. - */ -export type OpenAIResponsesFileSearchToolComparisonFilter = { - /** - * The key to compare against the value. - */ - key: string; - - /** - * Specifies the comparison operator: eq, ne, gt, gte, lt, lte, in, nin. - */ - type: 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'nin'; - - /** - * The value to compare against the attribute key; supports string, number, boolean, or array of string types. - */ - value: string | number | boolean | string[]; -}; - -/** - * Combine multiple filters using and or or. - */ -export type OpenAIResponsesFileSearchToolCompoundFilter = { - /** - * Type of operation: and or or. - */ - type: 'and' | 'or'; - - /** - * Array of filters to combine. Items can be ComparisonFilter or CompoundFilter. - */ - filters: Array< - | OpenAIResponsesFileSearchToolComparisonFilter - | OpenAIResponsesFileSearchToolCompoundFilter - >; -}; - -export type OpenAIResponsesTool = - | { - type: 'function'; - name: string; - description: string | undefined; - parameters: JSONSchema7; - strict?: boolean; - defer_loading?: boolean; - } - | { - type: 'apply_patch'; - } - | { - type: 'web_search'; - external_web_access: boolean | undefined; - filters: { allowed_domains: string[] | undefined } | undefined; - search_context_size: 'low' | 'medium' | 'high' | undefined; - user_location: - | { - type: 'approximate'; - city?: string; - country?: string; - region?: string; - timezone?: string; - } - | undefined; - } - | { - type: 'web_search_preview'; - search_context_size: 'low' | 'medium' | 'high' | undefined; - user_location: - | { - type: 'approximate'; - city?: string; - country?: string; - region?: string; - timezone?: string; - } - | undefined; - } - | { - type: 'code_interpreter'; - container: string | { type: 'auto'; file_ids: string[] | undefined }; - } - | { - type: 'file_search'; - vector_store_ids: string[]; - max_num_results: number | undefined; - ranking_options: - | { ranker?: string; score_threshold?: number } - | undefined; - filters: - | OpenAIResponsesFileSearchToolComparisonFilter - | OpenAIResponsesFileSearchToolCompoundFilter - | undefined; - } - | { - type: 'image_generation'; - background: 'auto' | 'opaque' | 'transparent' | undefined; - input_fidelity: 'low' | 'high' | undefined; - input_image_mask: - | { - file_id: string | undefined; - image_url: string | undefined; - } - | undefined; - model: string | undefined; - moderation: 'auto' | undefined; - output_compression: number | undefined; - output_format: 'png' | 'jpeg' | 'webp' | undefined; - partial_images: number | undefined; - quality: 'auto' | 'low' | 'medium' | 'high' | undefined; - size: 'auto' | '1024x1024' | '1024x1536' | '1536x1024' | undefined; - } - - /** - * Official OpenAI API Specifications: https://platform.openai.com/docs/api-reference/responses/create#responses_create-tools-mcp_tool - */ - | { - type: 'mcp'; - server_label: string; - allowed_tools: - | string[] - | { - read_only?: boolean; - tool_names?: string[]; - } - | undefined; - authorization: string | undefined; - connector_id: string | undefined; - headers: Record | undefined; - require_approval: - | 'always' - | 'never' - | { - never?: { tool_names?: string[] }; - } - | undefined; - server_description: string | undefined; - server_url: string | undefined; - } - | { - type: 'custom'; - name: string; - description?: string; - format?: - | { - type: 'grammar'; - syntax: 'regex' | 'lark'; - definition: string; - } - | { - type: 'text'; - }; - } - | { - type: 'local_shell'; - } - | { - type: 'shell'; - environment?: - | { - type: 'container_auto'; - file_ids?: string[]; - memory_limit?: '1g' | '4g' | '16g' | '64g'; - network_policy?: - | { type: 'disabled' } - | { - type: 'allowlist'; - allowed_domains: string[]; - domain_secrets?: Array<{ - domain: string; - name: string; - value: string; - }>; - }; - skills?: Array< - | { - type: 'skill_reference'; - skill_id: string; - version?: string; - } - | { - type: 'inline'; - name: string; - description: string; - source: { - type: 'base64'; - media_type: 'application/zip'; - data: string; - }; - } - >; - } - | { - type: 'container_reference'; - container_id: string; - } - | { - type: 'local'; - skills?: Array<{ - name: string; - description: string; - path: string; - }>; - }; - } - | { - type: 'tool_search'; - execution?: 'server' | 'client'; - description?: string; - parameters?: Record; - }; - -export type OpenAIResponsesReasoning = { - type: 'reasoning'; - id?: string; - encrypted_content?: string | null; - summary: Array<{ - type: 'summary_text'; - text: string; - }>; -}; - -export const openaiResponsesChunkSchema = lazySchema(() => - zodSchema( - z.union([ - z.object({ - type: z.literal('response.output_text.delta'), - item_id: z.string(), - delta: z.string(), - logprobs: z - .array( - z.object({ - token: z.string(), - logprob: z.number(), - top_logprobs: z.array( - z.object({ - token: z.string(), - logprob: z.number(), - }), - ), - }), - ) - .nullish(), - }), - z.object({ - type: z.enum(['response.completed', 'response.incomplete']), - response: z.object({ - incomplete_details: z.object({ reason: z.string() }).nullish(), - usage: z.object({ - input_tokens: z.number(), - input_tokens_details: z - .object({ cached_tokens: z.number().nullish() }) - .nullish(), - output_tokens: z.number(), - output_tokens_details: z - .object({ reasoning_tokens: z.number().nullish() }) - .nullish(), - }), - service_tier: z.string().nullish(), - }), - }), - z.object({ - type: z.literal('response.failed'), - response: z.object({ - error: z - .object({ - code: z.string().nullish(), - message: z.string(), - }) - .nullish(), - incomplete_details: z.object({ reason: z.string() }).nullish(), - usage: z - .object({ - input_tokens: z.number(), - input_tokens_details: z - .object({ cached_tokens: z.number().nullish() }) - .nullish(), - output_tokens: z.number(), - output_tokens_details: z - .object({ reasoning_tokens: z.number().nullish() }) - .nullish(), - }) - .nullish(), - service_tier: z.string().nullish(), - }), - }), - z.object({ - type: z.literal('response.created'), - response: z.object({ - id: z.string(), - created_at: z.number(), - model: z.string(), - service_tier: z.string().nullish(), - }), - }), - z.object({ - type: z.literal('response.output_item.added'), - output_index: z.number(), - item: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('message'), - id: z.string(), - phase: z.enum(['commentary', 'final_answer']).nullish(), - }), - z.object({ - type: z.literal('reasoning'), - id: z.string(), - encrypted_content: z.string().nullish(), - }), - z.object({ - type: z.literal('function_call'), - id: z.string(), - call_id: z.string(), - name: z.string(), - arguments: z.string(), - }), - z.object({ - type: z.literal('web_search_call'), - id: z.string(), - status: z.string(), - }), - z.object({ - type: z.literal('computer_call'), - id: z.string(), - status: z.string(), - }), - z.object({ - type: z.literal('file_search_call'), - id: z.string(), - }), - z.object({ - type: z.literal('image_generation_call'), - id: z.string(), - }), - z.object({ - type: z.literal('code_interpreter_call'), - id: z.string(), - container_id: z.string(), - code: z.string().nullable(), - outputs: z - .array( - z.discriminatedUnion('type', [ - z.object({ type: z.literal('logs'), logs: z.string() }), - z.object({ type: z.literal('image'), url: z.string() }), - ]), - ) - .nullable(), - status: z.string(), - }), - z.object({ - type: z.literal('mcp_call'), - id: z.string(), - status: z.string(), - approval_request_id: z.string().nullish(), - }), - z.object({ - type: z.literal('mcp_list_tools'), - id: z.string(), - }), - z.object({ - type: z.literal('mcp_approval_request'), - id: z.string(), - }), - z.object({ - type: z.literal('apply_patch_call'), - id: z.string(), - call_id: z.string(), - status: z.enum(['in_progress', 'completed']), - operation: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('create_file'), - path: z.string(), - diff: z.string(), - }), - z.object({ - type: z.literal('delete_file'), - path: z.string(), - }), - z.object({ - type: z.literal('update_file'), - path: z.string(), - diff: z.string(), - }), - ]), - }), - z.object({ - type: z.literal('custom_tool_call'), - id: z.string(), - call_id: z.string(), - name: z.string(), - input: z.string(), - }), - z.object({ - type: z.literal('shell_call'), - id: z.string(), - call_id: z.string(), - status: z.enum(['in_progress', 'completed', 'incomplete']), - action: z.object({ - commands: z.array(z.string()), - }), - }), - z.object({ - type: z.literal('shell_call_output'), - id: z.string(), - call_id: z.string(), - status: z.enum(['in_progress', 'completed', 'incomplete']), - output: z.array( - z.object({ - stdout: z.string(), - stderr: z.string(), - outcome: z.discriminatedUnion('type', [ - z.object({ type: z.literal('timeout') }), - z.object({ - type: z.literal('exit'), - exit_code: z.number(), - }), - ]), - }), - ), - }), - z.object({ - type: z.literal('tool_search_call'), - id: z.string(), - execution: z.enum(['server', 'client']), - call_id: z.string().nullable(), - status: z.enum(['in_progress', 'completed', 'incomplete']), - arguments: z.unknown(), - }), - z.object({ - type: z.literal('tool_search_output'), - id: z.string(), - execution: z.enum(['server', 'client']), - call_id: z.string().nullable(), - status: z.enum(['in_progress', 'completed', 'incomplete']), - tools: z.array(z.record(z.string(), jsonValueSchema.optional())), - }), - ]), - }), - z.object({ - type: z.literal('response.output_item.done'), - output_index: z.number(), - item: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('message'), - id: z.string(), - phase: z.enum(['commentary', 'final_answer']).nullish(), - }), - z.object({ - type: z.literal('reasoning'), - id: z.string(), - encrypted_content: z.string().nullish(), - }), - z.object({ - type: z.literal('function_call'), - id: z.string(), - call_id: z.string(), - name: z.string(), - arguments: z.string(), - status: z.literal('completed'), - }), - z.object({ - type: z.literal('custom_tool_call'), - id: z.string(), - call_id: z.string(), - name: z.string(), - input: z.string(), - status: z.literal('completed'), - }), - z.object({ - type: z.literal('code_interpreter_call'), - id: z.string(), - code: z.string().nullable(), - container_id: z.string(), - outputs: z - .array( - z.discriminatedUnion('type', [ - z.object({ type: z.literal('logs'), logs: z.string() }), - z.object({ type: z.literal('image'), url: z.string() }), - ]), - ) - .nullable(), - }), - z.object({ - type: z.literal('image_generation_call'), - id: z.string(), - result: z.string(), - }), - z.object({ - type: z.literal('web_search_call'), - id: z.string(), - status: z.string(), - action: z - .discriminatedUnion('type', [ - z.object({ - type: z.literal('search'), - query: z.string().nullish(), - sources: z - .array( - z.discriminatedUnion('type', [ - z.object({ type: z.literal('url'), url: z.string() }), - z.object({ type: z.literal('api'), name: z.string() }), - ]), - ) - .nullish(), - }), - z.object({ - type: z.literal('open_page'), - url: z.string().nullish(), - }), - z.object({ - type: z.literal('find_in_page'), - url: z.string().nullish(), - pattern: z.string().nullish(), - }), - ]) - .nullish(), - }), - z.object({ - type: z.literal('file_search_call'), - id: z.string(), - queries: z.array(z.string()), - results: z - .array( - z.object({ - attributes: z.record( - z.string(), - z.union([z.string(), z.number(), z.boolean()]), - ), - file_id: z.string(), - filename: z.string(), - score: z.number(), - text: z.string(), - }), - ) - .nullish(), - }), - z.object({ - type: z.literal('local_shell_call'), - id: z.string(), - call_id: z.string(), - action: z.object({ - type: z.literal('exec'), - command: z.array(z.string()), - timeout_ms: z.number().optional(), - user: z.string().optional(), - working_directory: z.string().optional(), - env: z.record(z.string(), z.string()).optional(), - }), - }), - z.object({ - type: z.literal('computer_call'), - id: z.string(), - status: z.literal('completed'), - }), - z.object({ - type: z.literal('mcp_call'), - id: z.string(), - status: z.string(), - arguments: z.string(), - name: z.string(), - server_label: z.string(), - output: z.string().nullish(), - error: z - .union([ - z.string(), - z - .object({ - type: z.string().optional(), - code: z.union([z.number(), z.string()]).optional(), - message: z.string().optional(), - }) - .loose(), - ]) - .nullish(), - approval_request_id: z.string().nullish(), - }), - z.object({ - type: z.literal('mcp_list_tools'), - id: z.string(), - server_label: z.string(), - tools: z.array( - z.object({ - name: z.string(), - description: z.string().optional(), - input_schema: z.any(), - annotations: z.record(z.string(), z.unknown()).optional(), - }), - ), - error: z - .union([ - z.string(), - z - .object({ - type: z.string().optional(), - code: z.union([z.number(), z.string()]).optional(), - message: z.string().optional(), - }) - .loose(), - ]) - .optional(), - }), - z.object({ - type: z.literal('mcp_approval_request'), - id: z.string(), - server_label: z.string(), - name: z.string(), - arguments: z.string(), - approval_request_id: z.string().optional(), - }), - z.object({ - type: z.literal('apply_patch_call'), - id: z.string(), - call_id: z.string(), - status: z.enum(['in_progress', 'completed']), - operation: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('create_file'), - path: z.string(), - diff: z.string(), - }), - z.object({ - type: z.literal('delete_file'), - path: z.string(), - }), - z.object({ - type: z.literal('update_file'), - path: z.string(), - diff: z.string(), - }), - ]), - }), - z.object({ - type: z.literal('shell_call'), - id: z.string(), - call_id: z.string(), - status: z.enum(['in_progress', 'completed', 'incomplete']), - action: z.object({ - commands: z.array(z.string()), - }), - }), - z.object({ - type: z.literal('shell_call_output'), - id: z.string(), - call_id: z.string(), - status: z.enum(['in_progress', 'completed', 'incomplete']), - output: z.array( - z.object({ - stdout: z.string(), - stderr: z.string(), - outcome: z.discriminatedUnion('type', [ - z.object({ type: z.literal('timeout') }), - z.object({ - type: z.literal('exit'), - exit_code: z.number(), - }), - ]), - }), - ), - }), - z.object({ - type: z.literal('tool_search_call'), - id: z.string(), - execution: z.enum(['server', 'client']), - call_id: z.string().nullable(), - status: z.enum(['in_progress', 'completed', 'incomplete']), - arguments: z.unknown(), - }), - z.object({ - type: z.literal('tool_search_output'), - id: z.string(), - execution: z.enum(['server', 'client']), - call_id: z.string().nullable(), - status: z.enum(['in_progress', 'completed', 'incomplete']), - tools: z.array(z.record(z.string(), jsonValueSchema.optional())), - }), - ]), - }), - z.object({ - type: z.literal('response.function_call_arguments.delta'), - item_id: z.string(), - output_index: z.number(), - delta: z.string(), - }), - z.object({ - type: z.literal('response.custom_tool_call_input.delta'), - item_id: z.string(), - output_index: z.number(), - delta: z.string(), - }), - z.object({ - type: z.literal('response.image_generation_call.partial_image'), - item_id: z.string(), - output_index: z.number(), - partial_image_b64: z.string(), - }), - z.object({ - type: z.literal('response.code_interpreter_call_code.delta'), - item_id: z.string(), - output_index: z.number(), - delta: z.string(), - }), - z.object({ - type: z.literal('response.code_interpreter_call_code.done'), - item_id: z.string(), - output_index: z.number(), - code: z.string(), - }), - z.object({ - type: z.literal('response.output_text.annotation.added'), - annotation: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('url_citation'), - start_index: z.number(), - end_index: z.number(), - url: z.string(), - title: z.string(), - }), - z.object({ - type: z.literal('file_citation'), - file_id: z.string(), - filename: z.string(), - index: z.number(), - }), - z.object({ - type: z.literal('container_file_citation'), - container_id: z.string(), - file_id: z.string(), - filename: z.string(), - start_index: z.number(), - end_index: z.number(), - }), - z.object({ - type: z.literal('file_path'), - file_id: z.string(), - index: z.number(), - }), - ]), - }), - z.object({ - type: z.literal('response.reasoning_summary_part.added'), - item_id: z.string(), - summary_index: z.number(), - }), - z.object({ - type: z.literal('response.reasoning_summary_text.delta'), - item_id: z.string(), - summary_index: z.number(), - delta: z.string(), - }), - z.object({ - type: z.literal('response.reasoning_summary_part.done'), - item_id: z.string(), - summary_index: z.number(), - }), - z.object({ - type: z.literal('response.apply_patch_call_operation_diff.delta'), - item_id: z.string(), - output_index: z.number(), - delta: z.string(), - obfuscation: z.string().nullish(), - }), - z.object({ - type: z.literal('response.apply_patch_call_operation_diff.done'), - item_id: z.string(), - output_index: z.number(), - diff: z.string(), - }), - z.object({ - type: z.literal('error'), - sequence_number: z.number(), - error: z.object({ - type: z.string(), - code: z.string(), - message: z.string(), - param: z.string().nullish(), - }), - }), - z - .object({ type: z.string() }) - .loose() - .transform(value => ({ - type: 'unknown_chunk' as const, - message: value.type, - })), // fallback for unknown chunks - ]), - ), -); - -export type OpenAIResponsesChunk = InferSchema< - typeof openaiResponsesChunkSchema ->; - -export type OpenAIResponsesLogprobs = NonNullable< - (OpenAIResponsesChunk & { - type: 'response.output_text.delta'; - })['logprobs'] -> | null; - -export type OpenAIResponsesWebSearchAction = NonNullable< - ((OpenAIResponsesChunk & { - type: 'response.output_item.done'; - })['item'] & { - type: 'web_search_call'; - })['action'] ->; - -export const openaiResponsesResponseSchema = lazySchema(() => - zodSchema( - z.object({ - id: z.string().optional(), - created_at: z.number().optional(), - error: z - .object({ - message: z.string(), - type: z.string(), - param: z.string().nullish(), - code: z.string(), - }) - .nullish(), - model: z.string().optional(), - output: z - .array( - z.discriminatedUnion('type', [ - z.object({ - type: z.literal('message'), - role: z.literal('assistant'), - id: z.string(), - phase: z.enum(['commentary', 'final_answer']).nullish(), - content: z.array( - z.object({ - type: z.literal('output_text'), - text: z.string(), - logprobs: z - .array( - z.object({ - token: z.string(), - logprob: z.number(), - top_logprobs: z.array( - z.object({ - token: z.string(), - logprob: z.number(), - }), - ), - }), - ) - .nullish(), - annotations: z.array( - z.discriminatedUnion('type', [ - z.object({ - type: z.literal('url_citation'), - start_index: z.number(), - end_index: z.number(), - url: z.string(), - title: z.string(), - }), - z.object({ - type: z.literal('file_citation'), - file_id: z.string(), - filename: z.string(), - index: z.number(), - }), - z.object({ - type: z.literal('container_file_citation'), - container_id: z.string(), - file_id: z.string(), - filename: z.string(), - start_index: z.number(), - end_index: z.number(), - }), - z.object({ - type: z.literal('file_path'), - file_id: z.string(), - index: z.number(), - }), - ]), - ), - }), - ), - }), - z.object({ - type: z.literal('web_search_call'), - id: z.string(), - status: z.string(), - action: z - .discriminatedUnion('type', [ - z.object({ - type: z.literal('search'), - query: z.string().nullish(), - sources: z - .array( - z.discriminatedUnion('type', [ - z.object({ type: z.literal('url'), url: z.string() }), - z.object({ - type: z.literal('api'), - name: z.string(), - }), - ]), - ) - .nullish(), - }), - z.object({ - type: z.literal('open_page'), - url: z.string().nullish(), - }), - z.object({ - type: z.literal('find_in_page'), - url: z.string().nullish(), - pattern: z.string().nullish(), - }), - ]) - .nullish(), - }), - z.object({ - type: z.literal('file_search_call'), - id: z.string(), - queries: z.array(z.string()), - results: z - .array( - z.object({ - attributes: z.record( - z.string(), - z.union([z.string(), z.number(), z.boolean()]), - ), - file_id: z.string(), - filename: z.string(), - score: z.number(), - text: z.string(), - }), - ) - .nullish(), - }), - z.object({ - type: z.literal('code_interpreter_call'), - id: z.string(), - code: z.string().nullable(), - container_id: z.string(), - outputs: z - .array( - z.discriminatedUnion('type', [ - z.object({ type: z.literal('logs'), logs: z.string() }), - z.object({ type: z.literal('image'), url: z.string() }), - ]), - ) - .nullable(), - }), - z.object({ - type: z.literal('image_generation_call'), - id: z.string(), - result: z.string(), - }), - z.object({ - type: z.literal('local_shell_call'), - id: z.string(), - call_id: z.string(), - action: z.object({ - type: z.literal('exec'), - command: z.array(z.string()), - timeout_ms: z.number().optional(), - user: z.string().optional(), - working_directory: z.string().optional(), - env: z.record(z.string(), z.string()).optional(), - }), - }), - z.object({ - type: z.literal('function_call'), - call_id: z.string(), - name: z.string(), - arguments: z.string(), - id: z.string(), - }), - z.object({ - type: z.literal('custom_tool_call'), - call_id: z.string(), - name: z.string(), - input: z.string(), - id: z.string(), - }), - z.object({ - type: z.literal('computer_call'), - id: z.string(), - status: z.string().optional(), - }), - z.object({ - type: z.literal('reasoning'), - id: z.string(), - encrypted_content: z.string().nullish(), - summary: z.array( - z.object({ - type: z.literal('summary_text'), - text: z.string(), - }), - ), - }), - z.object({ - type: z.literal('mcp_call'), - id: z.string(), - status: z.string(), - arguments: z.string(), - name: z.string(), - server_label: z.string(), - output: z.string().nullish(), - error: z - .union([ - z.string(), - z - .object({ - type: z.string().optional(), - code: z.union([z.number(), z.string()]).optional(), - message: z.string().optional(), - }) - .loose(), - ]) - .nullish(), - approval_request_id: z.string().nullish(), - }), - z.object({ - type: z.literal('mcp_list_tools'), - id: z.string(), - server_label: z.string(), - tools: z.array( - z.object({ - name: z.string(), - description: z.string().optional(), - input_schema: z.any(), - annotations: z.record(z.string(), z.unknown()).optional(), - }), - ), - error: z - .union([ - z.string(), - z - .object({ - type: z.string().optional(), - code: z.union([z.number(), z.string()]).optional(), - message: z.string().optional(), - }) - .loose(), - ]) - .optional(), - }), - z.object({ - type: z.literal('mcp_approval_request'), - id: z.string(), - server_label: z.string(), - name: z.string(), - arguments: z.string(), - approval_request_id: z.string().optional(), - }), - z.object({ - type: z.literal('apply_patch_call'), - id: z.string(), - call_id: z.string(), - status: z.enum(['in_progress', 'completed']), - operation: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('create_file'), - path: z.string(), - diff: z.string(), - }), - z.object({ - type: z.literal('delete_file'), - path: z.string(), - }), - z.object({ - type: z.literal('update_file'), - path: z.string(), - diff: z.string(), - }), - ]), - }), - z.object({ - type: z.literal('shell_call'), - id: z.string(), - call_id: z.string(), - status: z.enum(['in_progress', 'completed', 'incomplete']), - action: z.object({ - commands: z.array(z.string()), - }), - }), - z.object({ - type: z.literal('shell_call_output'), - id: z.string(), - call_id: z.string(), - status: z.enum(['in_progress', 'completed', 'incomplete']), - output: z.array( - z.object({ - stdout: z.string(), - stderr: z.string(), - outcome: z.discriminatedUnion('type', [ - z.object({ type: z.literal('timeout') }), - z.object({ - type: z.literal('exit'), - exit_code: z.number(), - }), - ]), - }), - ), - }), - z.object({ - type: z.literal('tool_search_call'), - id: z.string(), - execution: z.enum(['server', 'client']), - call_id: z.string().nullable(), - status: z.enum(['in_progress', 'completed', 'incomplete']), - arguments: z.unknown(), - }), - z.object({ - type: z.literal('tool_search_output'), - id: z.string(), - execution: z.enum(['server', 'client']), - call_id: z.string().nullable(), - status: z.enum(['in_progress', 'completed', 'incomplete']), - tools: z.array(z.record(z.string(), jsonValueSchema.optional())), - }), - ]), - ) - .optional(), - service_tier: z.string().nullish(), - incomplete_details: z.object({ reason: z.string() }).nullish(), - usage: z - .object({ - input_tokens: z.number(), - input_tokens_details: z - .object({ cached_tokens: z.number().nullish() }) - .nullish(), - output_tokens: z.number(), - output_tokens_details: z - .object({ reasoning_tokens: z.number().nullish() }) - .nullish(), - }) - .optional(), - }), - ), -); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-language-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-language-model.ts deleted file mode 100644 index fe9616c81..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-language-model.ts +++ /dev/null @@ -1,2256 +0,0 @@ -import { - APICallError, - JSONValue, - LanguageModelV3, - LanguageModelV3Prompt, - LanguageModelV3CallOptions, - LanguageModelV3Content, - LanguageModelV3FinishReason, - LanguageModelV3GenerateResult, - LanguageModelV3ProviderTool, - LanguageModelV3StreamPart, - LanguageModelV3StreamResult, - LanguageModelV3ToolApprovalRequest, - SharedV3ProviderMetadata, - SharedV3Warning, -} from '@ai-sdk/provider'; -import { - combineHeaders, - createEventSourceResponseHandler, - createJsonResponseHandler, - createToolNameMapping, - generateId, - InferSchema, - parseProviderOptions, - ParseResult, - postJsonToApi, -} from '@ai-sdk/provider-utils'; -import { OpenAIConfig } from '../openai-config'; -import { openaiFailedResponseHandler } from '../openai-error'; -import { getOpenAILanguageModelCapabilities } from '../openai-language-model-capabilities'; -import { applyPatchInputSchema } from '../tool/apply-patch'; -import { - codeInterpreterInputSchema, - codeInterpreterOutputSchema, -} from '../tool/code-interpreter'; -import { fileSearchOutputSchema } from '../tool/file-search'; -import { imageGenerationOutputSchema } from '../tool/image-generation'; -import { localShellInputSchema } from '../tool/local-shell'; -import { mcpOutputSchema } from '../tool/mcp'; -import { shellInputSchema, shellOutputSchema } from '../tool/shell'; -import { - toolSearchInputSchema, - toolSearchOutputSchema, -} from '../tool/tool-search'; -import { webSearchOutputSchema } from '../tool/web-search'; -import { - convertOpenAIResponsesUsage, - OpenAIResponsesUsage, -} from './convert-openai-responses-usage'; -import { convertToOpenAIResponsesInput } from './convert-to-openai-responses-input'; -import { mapOpenAIResponseFinishReason } from './map-openai-responses-finish-reason'; -import { - OpenAIResponsesChunk, - openaiResponsesChunkSchema, - OpenAIResponsesIncludeOptions, - OpenAIResponsesIncludeValue, - OpenAIResponsesLogprobs, - openaiResponsesResponseSchema, - OpenAIResponsesWebSearchAction, - OpenAIResponsesApplyPatchOperationDiffDeltaChunk, - OpenAIResponsesApplyPatchOperationDiffDoneChunk, -} from './openai-responses-api'; -import { - OpenAIResponsesModelId, - openaiLanguageModelResponsesOptionsSchema, - TOP_LOGPROBS_MAX, -} from './openai-responses-options'; -import { prepareResponsesTools } from './openai-responses-prepare-tools'; -import { - ResponsesProviderMetadata, - ResponsesReasoningProviderMetadata, - ResponsesSourceDocumentProviderMetadata, - ResponsesTextProviderMetadata, -} from './openai-responses-provider-metadata'; - -/** - * Extracts a mapping from MCP approval request IDs to their corresponding tool call IDs - * from the prompt. When an MCP tool requires approval, we generate a tool call ID to track - * the pending approval in our system. When the user responds to the approval (and we - * continue the conversation), we need to map the approval request ID back to our tool call ID - * so that tool results reference the correct tool call. - */ -function extractApprovalRequestIdToToolCallIdMapping( - prompt: LanguageModelV3Prompt, -): Record { - const mapping: Record = {}; - for (const message of prompt) { - if (message.role !== 'assistant') continue; - for (const part of message.content) { - if (part.type !== 'tool-call') continue; - const approvalRequestId = part.providerOptions?.openai - ?.approvalRequestId as string | undefined; - if (approvalRequestId != null) { - mapping[approvalRequestId] = part.toolCallId; - } - } - } - return mapping; -} - -export class OpenAIResponsesLanguageModel implements LanguageModelV3 { - readonly specificationVersion = 'v3'; - - readonly modelId: OpenAIResponsesModelId; - - private readonly config: OpenAIConfig; - - constructor(modelId: OpenAIResponsesModelId, config: OpenAIConfig) { - this.modelId = modelId; - this.config = config; - } - - readonly supportedUrls: Record = { - 'image/*': [/^https?:\/\/.*$/], - 'application/pdf': [/^https?:\/\/.*$/], - }; - - get provider(): string { - return this.config.provider; - } - - private async getArgs({ - maxOutputTokens, - temperature, - stopSequences, - topP, - topK, - presencePenalty, - frequencyPenalty, - seed, - prompt, - providerOptions, - tools, - toolChoice, - responseFormat, - }: LanguageModelV3CallOptions) { - const warnings: SharedV3Warning[] = []; - const modelCapabilities = getOpenAILanguageModelCapabilities(this.modelId); - - if (topK != null) { - warnings.push({ type: 'unsupported', feature: 'topK' }); - } - - if (seed != null) { - warnings.push({ type: 'unsupported', feature: 'seed' }); - } - - if (presencePenalty != null) { - warnings.push({ type: 'unsupported', feature: 'presencePenalty' }); - } - - if (frequencyPenalty != null) { - warnings.push({ type: 'unsupported', feature: 'frequencyPenalty' }); - } - - if (stopSequences != null) { - warnings.push({ type: 'unsupported', feature: 'stopSequences' }); - } - - const providerOptionsName = this.config.provider.includes('azure') - ? 'azure' - : 'openai'; - let openaiOptions = await parseProviderOptions({ - provider: providerOptionsName, - providerOptions, - schema: openaiLanguageModelResponsesOptionsSchema, - }); - - if (openaiOptions == null && providerOptionsName !== 'openai') { - openaiOptions = await parseProviderOptions({ - provider: 'openai', - providerOptions, - schema: openaiLanguageModelResponsesOptionsSchema, - }); - } - - const isReasoningModel = - openaiOptions?.forceReasoning ?? modelCapabilities.isReasoningModel; - - if (openaiOptions?.conversation && openaiOptions?.previousResponseId) { - warnings.push({ - type: 'unsupported', - feature: 'conversation', - details: 'conversation and previousResponseId cannot be used together', - }); - } - - const toolNameMapping = createToolNameMapping({ - tools, - providerToolNames: { - 'openai.code_interpreter': 'code_interpreter', - 'openai.file_search': 'file_search', - 'openai.image_generation': 'image_generation', - 'openai.local_shell': 'local_shell', - 'openai.shell': 'shell', - 'openai.web_search': 'web_search', - 'openai.web_search_preview': 'web_search_preview', - 'openai.mcp': 'mcp', - 'openai.apply_patch': 'apply_patch', - 'openai.tool_search': 'tool_search', - }, - resolveProviderToolName: tool => - tool.id === 'openai.custom' - ? (tool.args as { name?: string }).name - : undefined, - }); - - const customProviderToolNames = new Set(); - const { - tools: openaiTools, - toolChoice: openaiToolChoice, - toolWarnings, - } = await prepareResponsesTools({ - tools, - toolChoice, - toolNameMapping, - customProviderToolNames, - }); - - const { input, warnings: inputWarnings } = - await convertToOpenAIResponsesInput({ - prompt, - toolNameMapping, - systemMessageMode: - openaiOptions?.systemMessageMode ?? - (isReasoningModel - ? 'developer' - : modelCapabilities.systemMessageMode), - providerOptionsName, - fileIdPrefixes: this.config.fileIdPrefixes, - store: openaiOptions?.store ?? true, - hasConversation: openaiOptions?.conversation != null, - hasLocalShellTool: hasOpenAITool('openai.local_shell'), - hasShellTool: hasOpenAITool('openai.shell'), - hasApplyPatchTool: hasOpenAITool('openai.apply_patch'), - customProviderToolNames: - customProviderToolNames.size > 0 - ? customProviderToolNames - : undefined, - }); - - warnings.push(...inputWarnings); - - const strictJsonSchema = openaiOptions?.strictJsonSchema ?? true; - - let include: OpenAIResponsesIncludeOptions = openaiOptions?.include; - - function addInclude(key: OpenAIResponsesIncludeValue) { - if (include == null) { - include = [key]; - } else if (!include.includes(key)) { - include = [...include, key]; - } - } - - function hasOpenAITool(id: string) { - return ( - tools?.find(tool => tool.type === 'provider' && tool.id === id) != null - ); - } - - // when logprobs are requested, automatically include them: - const topLogprobs = - typeof openaiOptions?.logprobs === 'number' - ? openaiOptions?.logprobs - : openaiOptions?.logprobs === true - ? TOP_LOGPROBS_MAX - : undefined; - - if (topLogprobs) { - addInclude('message.output_text.logprobs'); - } - - // when a web search tool is present, automatically include the sources: - const webSearchToolName = ( - tools?.find( - tool => - tool.type === 'provider' && - (tool.id === 'openai.web_search' || - tool.id === 'openai.web_search_preview'), - ) as LanguageModelV3ProviderTool | undefined - )?.name; - - if (webSearchToolName) { - addInclude('web_search_call.action.sources'); - } - - // when a code interpreter tool is present, automatically include the outputs: - if (hasOpenAITool('openai.code_interpreter')) { - addInclude('code_interpreter_call.outputs'); - } - - const store = openaiOptions?.store; - - // store defaults to true in the OpenAI responses API, so check for false exactly: - if (store === false && isReasoningModel) { - addInclude('reasoning.encrypted_content'); - } - - const baseArgs = { - model: this.modelId, - input, - temperature, - top_p: topP, - max_output_tokens: maxOutputTokens, - - ...((responseFormat?.type === 'json' || openaiOptions?.textVerbosity) && { - text: { - ...(responseFormat?.type === 'json' && { - format: - responseFormat.schema != null - ? { - type: 'json_schema', - strict: strictJsonSchema, - name: responseFormat.name ?? 'response', - description: responseFormat.description, - schema: responseFormat.schema, - } - : { type: 'json_object' }, - }), - ...(openaiOptions?.textVerbosity && { - verbosity: openaiOptions.textVerbosity, - }), - }, - }), - - // provider options: - conversation: openaiOptions?.conversation, - max_tool_calls: openaiOptions?.maxToolCalls, - metadata: openaiOptions?.metadata, - parallel_tool_calls: openaiOptions?.parallelToolCalls, - previous_response_id: openaiOptions?.previousResponseId, - store, - user: openaiOptions?.user, - instructions: openaiOptions?.instructions, - service_tier: openaiOptions?.serviceTier, - include, - prompt_cache_key: openaiOptions?.promptCacheKey, - prompt_cache_retention: openaiOptions?.promptCacheRetention, - safety_identifier: openaiOptions?.safetyIdentifier, - top_logprobs: topLogprobs, - truncation: openaiOptions?.truncation, - - // model-specific settings: - ...(isReasoningModel && - (openaiOptions?.reasoningEffort != null || - openaiOptions?.reasoningSummary != null) && { - reasoning: { - ...(openaiOptions?.reasoningEffort != null && { - effort: openaiOptions.reasoningEffort, - }), - ...(openaiOptions?.reasoningSummary != null && { - summary: openaiOptions.reasoningSummary, - }), - }, - }), - }; - - // remove unsupported settings for reasoning models - // see https://platform.openai.com/docs/guides/reasoning#limitations - if (isReasoningModel) { - // when reasoning effort is none, gpt-5.1 models allow temperature, topP, logprobs - // https://platform.openai.com/docs/guides/latest-model#gpt-5-1-parameter-compatibility - if ( - !( - openaiOptions?.reasoningEffort === 'none' && - modelCapabilities.supportsNonReasoningParameters - ) - ) { - if (baseArgs.temperature != null) { - baseArgs.temperature = undefined; - warnings.push({ - type: 'unsupported', - feature: 'temperature', - details: 'temperature is not supported for reasoning models', - }); - } - - if (baseArgs.top_p != null) { - baseArgs.top_p = undefined; - warnings.push({ - type: 'unsupported', - feature: 'topP', - details: 'topP is not supported for reasoning models', - }); - } - } - } else { - if (openaiOptions?.reasoningEffort != null) { - warnings.push({ - type: 'unsupported', - feature: 'reasoningEffort', - details: 'reasoningEffort is not supported for non-reasoning models', - }); - } - - if (openaiOptions?.reasoningSummary != null) { - warnings.push({ - type: 'unsupported', - feature: 'reasoningSummary', - details: 'reasoningSummary is not supported for non-reasoning models', - }); - } - } - - // Validate flex processing support - if ( - openaiOptions?.serviceTier === 'flex' && - !modelCapabilities.supportsFlexProcessing - ) { - warnings.push({ - type: 'unsupported', - feature: 'serviceTier', - details: - 'flex processing is only available for o3, o4-mini, and gpt-5 models', - }); - // Remove from args if not supported - delete (baseArgs as any).service_tier; - } - - // Validate priority processing support - if ( - openaiOptions?.serviceTier === 'priority' && - !modelCapabilities.supportsPriorityProcessing - ) { - warnings.push({ - type: 'unsupported', - feature: 'serviceTier', - details: - 'priority processing is only available for supported models (gpt-4, gpt-5, gpt-5-mini, o3, o4-mini) and requires Enterprise access. gpt-5-nano is not supported', - }); - // Remove from args if not supported - delete (baseArgs as any).service_tier; - } - - const shellToolEnvType = ( - tools?.find( - tool => tool.type === 'provider' && tool.id === 'openai.shell', - ) as { args?: { environment?: { type?: string } } } | undefined - )?.args?.environment?.type; - - const isShellProviderExecuted = - shellToolEnvType === 'containerAuto' || - shellToolEnvType === 'containerReference'; - - return { - webSearchToolName, - args: { - ...baseArgs, - tools: openaiTools, - tool_choice: openaiToolChoice, - }, - warnings: [...warnings, ...toolWarnings], - store, - toolNameMapping, - providerOptionsName, - isShellProviderExecuted, - }; - } - - async doGenerate( - options: LanguageModelV3CallOptions, - ): Promise { - const { - args: body, - warnings, - webSearchToolName, - toolNameMapping, - providerOptionsName, - isShellProviderExecuted, - } = await this.getArgs(options); - const url = this.config.url({ - path: '/responses', - modelId: this.modelId, - }); - - const approvalRequestIdToDummyToolCallIdFromPrompt = - extractApprovalRequestIdToToolCallIdMapping(options.prompt); - - const { - responseHeaders, - value: response, - rawValue: rawResponse, - } = await postJsonToApi({ - url, - headers: combineHeaders(this.config.headers(), options.headers), - body, - failedResponseHandler: openaiFailedResponseHandler, - successfulResponseHandler: createJsonResponseHandler( - openaiResponsesResponseSchema, - ), - abortSignal: options.abortSignal, - fetch: this.config.fetch, - }); - - if (response.error) { - throw new APICallError({ - message: response.error.message, - url, - requestBodyValues: body, - statusCode: 400, - responseHeaders, - responseBody: rawResponse as string, - isRetryable: false, - }); - } - - const content: Array = []; - const logprobs: Array = []; - - // flag that checks if there have been client-side tool calls (not executed by openai) - let hasFunctionCall = false; - const hostedToolSearchCallIds: string[] = []; - - // map response content to content array (defined when there is no error) - for (const part of response.output!) { - switch (part.type) { - case 'reasoning': { - // when there are no summary parts, we need to add an empty reasoning part: - if (part.summary.length === 0) { - part.summary.push({ type: 'summary_text', text: '' }); - } - - for (const summary of part.summary) { - content.push({ - type: 'reasoning' as const, - text: summary.text, - providerMetadata: { - [providerOptionsName]: { - itemId: part.id, - reasoningEncryptedContent: part.encrypted_content ?? null, - } satisfies ResponsesReasoningProviderMetadata, - }, - }); - } - break; - } - - case 'image_generation_call': { - content.push({ - type: 'tool-call', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName('image_generation'), - input: '{}', - providerExecuted: true, - }); - - content.push({ - type: 'tool-result', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName('image_generation'), - result: { - result: part.result, - } satisfies InferSchema, - }); - - break; - } - - case 'tool_search_call': { - const toolCallId = part.call_id ?? part.id; - const isHosted = part.execution === 'server'; - - if (isHosted) { - hostedToolSearchCallIds.push(toolCallId); - } - - content.push({ - type: 'tool-call', - toolCallId, - toolName: toolNameMapping.toCustomToolName('tool_search'), - input: JSON.stringify({ - arguments: part.arguments, - call_id: part.call_id, - } satisfies InferSchema), - ...(isHosted ? { providerExecuted: true } : {}), - providerMetadata: { - [providerOptionsName]: { - itemId: part.id, - }, - }, - }); - - break; - } - - case 'tool_search_output': { - const toolCallId = - part.call_id ?? hostedToolSearchCallIds.shift() ?? part.id; - - content.push({ - type: 'tool-result', - toolCallId, - toolName: toolNameMapping.toCustomToolName('tool_search'), - result: { - tools: part.tools, - } satisfies InferSchema, - providerMetadata: { - [providerOptionsName]: { - itemId: part.id, - }, - }, - }); - - break; - } - - case 'local_shell_call': { - content.push({ - type: 'tool-call', - toolCallId: part.call_id, - toolName: toolNameMapping.toCustomToolName('local_shell'), - input: JSON.stringify({ - action: part.action, - } satisfies InferSchema), - providerMetadata: { - [providerOptionsName]: { - itemId: part.id, - }, - }, - }); - - break; - } - - case 'shell_call': { - content.push({ - type: 'tool-call', - toolCallId: part.call_id, - toolName: toolNameMapping.toCustomToolName('shell'), - input: JSON.stringify({ - action: { - commands: part.action.commands, - }, - } satisfies InferSchema), - ...(isShellProviderExecuted && { providerExecuted: true }), - providerMetadata: { - [providerOptionsName]: { - itemId: part.id, - }, - }, - }); - - break; - } - - case 'shell_call_output': { - content.push({ - type: 'tool-result', - toolCallId: part.call_id, - toolName: toolNameMapping.toCustomToolName('shell'), - result: { - output: part.output.map(item => ({ - stdout: item.stdout, - stderr: item.stderr, - outcome: - item.outcome.type === 'exit' - ? { - type: 'exit' as const, - exitCode: item.outcome.exit_code, - } - : { type: 'timeout' as const }, - })), - } satisfies InferSchema, - }); - break; - } - - case 'message': { - for (const contentPart of part.content) { - if ( - options.providerOptions?.[providerOptionsName]?.logprobs && - contentPart.logprobs - ) { - logprobs.push(contentPart.logprobs); - } - - const providerMetadata: SharedV3ProviderMetadata[string] = { - itemId: part.id, - ...(part.phase != null && { phase: part.phase }), - ...(contentPart.annotations.length > 0 && { - annotations: contentPart.annotations, - }), - } satisfies ResponsesTextProviderMetadata; - - content.push({ - type: 'text', - text: contentPart.text, - providerMetadata: { - [providerOptionsName]: providerMetadata, - }, - }); - - for (const annotation of contentPart.annotations) { - if (annotation.type === 'url_citation') { - content.push({ - type: 'source', - sourceType: 'url', - id: this.config.generateId?.() ?? generateId(), - url: annotation.url, - title: annotation.title, - }); - } else if (annotation.type === 'file_citation') { - content.push({ - type: 'source', - sourceType: 'document', - id: this.config.generateId?.() ?? generateId(), - mediaType: 'text/plain', - title: annotation.filename, - filename: annotation.filename, - providerMetadata: { - [providerOptionsName]: { - type: annotation.type, - fileId: annotation.file_id, - index: annotation.index, - } satisfies Extract< - ResponsesSourceDocumentProviderMetadata, - { type: 'file_citation' } - >, - }, - }); - } else if (annotation.type === 'container_file_citation') { - content.push({ - type: 'source', - sourceType: 'document', - id: this.config.generateId?.() ?? generateId(), - mediaType: 'text/plain', - title: annotation.filename, - filename: annotation.filename, - providerMetadata: { - [providerOptionsName]: { - type: annotation.type, - fileId: annotation.file_id, - containerId: annotation.container_id, - } satisfies Extract< - ResponsesSourceDocumentProviderMetadata, - { type: 'container_file_citation' } - >, - }, - }); - } else if (annotation.type === 'file_path') { - content.push({ - type: 'source', - sourceType: 'document', - id: this.config.generateId?.() ?? generateId(), - mediaType: 'application/octet-stream', - title: annotation.file_id, - filename: annotation.file_id, - providerMetadata: { - [providerOptionsName]: { - type: annotation.type, - fileId: annotation.file_id, - index: annotation.index, - } satisfies Extract< - ResponsesSourceDocumentProviderMetadata, - { type: 'file_path' } - >, - }, - }); - } - } - } - - break; - } - - case 'function_call': { - hasFunctionCall = true; - - content.push({ - type: 'tool-call', - toolCallId: part.call_id, - toolName: part.name, - input: part.arguments, - providerMetadata: { - [providerOptionsName]: { - itemId: part.id, - }, - }, - }); - break; - } - - case 'custom_tool_call': { - hasFunctionCall = true; - const toolName = toolNameMapping.toCustomToolName(part.name); - - content.push({ - type: 'tool-call', - toolCallId: part.call_id, - toolName, - input: JSON.stringify(part.input), - providerMetadata: { - [providerOptionsName]: { - itemId: part.id, - }, - }, - }); - break; - } - - case 'web_search_call': { - content.push({ - type: 'tool-call', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName( - webSearchToolName ?? 'web_search', - ), - input: JSON.stringify({}), - providerExecuted: true, - }); - - content.push({ - type: 'tool-result', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName( - webSearchToolName ?? 'web_search', - ), - result: mapWebSearchOutput(part.action), - }); - - break; - } - - case 'mcp_call': { - const toolCallId = - part.approval_request_id != null - ? (approvalRequestIdToDummyToolCallIdFromPrompt[ - part.approval_request_id - ] ?? part.id) - : part.id; - - const toolName = `mcp.${part.name}`; - - content.push({ - type: 'tool-call', - toolCallId, - toolName, - input: part.arguments, - providerExecuted: true, - dynamic: true, - }); - - content.push({ - type: 'tool-result', - toolCallId, - toolName, - result: { - type: 'call', - serverLabel: part.server_label, - name: part.name, - arguments: part.arguments, - ...(part.output != null ? { output: part.output } : {}), - ...(part.error != null - ? { error: part.error as unknown as JSONValue } - : {}), - } satisfies InferSchema, - providerMetadata: { - [providerOptionsName]: { - itemId: part.id, - }, - }, - }); - break; - } - - case 'mcp_list_tools': { - // skip - break; - } - - case 'mcp_approval_request': { - const approvalRequestId = part.approval_request_id ?? part.id; - const dummyToolCallId = this.config.generateId?.() ?? generateId(); - const toolName = `mcp.${part.name}`; - - content.push({ - type: 'tool-call', - toolCallId: dummyToolCallId, - toolName, - input: part.arguments, - providerExecuted: true, - dynamic: true, - }); - - content.push({ - type: 'tool-approval-request', - approvalId: approvalRequestId, - toolCallId: dummyToolCallId, - } satisfies LanguageModelV3ToolApprovalRequest); - break; - } - - case 'computer_call': { - content.push({ - type: 'tool-call', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName('computer_use'), - input: '', - providerExecuted: true, - }); - - content.push({ - type: 'tool-result', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName('computer_use'), - result: { - type: 'computer_use_tool_result', - status: part.status || 'completed', - }, - }); - break; - } - - case 'file_search_call': { - content.push({ - type: 'tool-call', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName('file_search'), - input: '{}', - providerExecuted: true, - }); - - content.push({ - type: 'tool-result', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName('file_search'), - result: { - queries: part.queries, - results: - part.results?.map(result => ({ - attributes: result.attributes, - fileId: result.file_id, - filename: result.filename, - score: result.score, - text: result.text, - })) ?? null, - } satisfies InferSchema, - }); - break; - } - - case 'code_interpreter_call': { - content.push({ - type: 'tool-call', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName('code_interpreter'), - input: JSON.stringify({ - code: part.code, - containerId: part.container_id, - } satisfies InferSchema), - providerExecuted: true, - }); - - content.push({ - type: 'tool-result', - toolCallId: part.id, - toolName: toolNameMapping.toCustomToolName('code_interpreter'), - result: { - outputs: part.outputs, - } satisfies InferSchema, - }); - break; - } - - case 'apply_patch_call': { - content.push({ - type: 'tool-call', - toolCallId: part.call_id, - toolName: toolNameMapping.toCustomToolName('apply_patch'), - input: JSON.stringify({ - callId: part.call_id, - operation: part.operation, - } satisfies InferSchema), - providerMetadata: { - [providerOptionsName]: { - itemId: part.id, - }, - }, - }); - - break; - } - } - } - - const providerMetadata: SharedV3ProviderMetadata = { - [providerOptionsName]: { - responseId: response.id, - ...(logprobs.length > 0 ? { logprobs } : {}), - ...(typeof response.service_tier === 'string' - ? { serviceTier: response.service_tier } - : {}), - } satisfies ResponsesProviderMetadata, - }; - - const usage = response.usage!; // defined when there is no error - - return { - content, - finishReason: { - unified: mapOpenAIResponseFinishReason({ - finishReason: response.incomplete_details?.reason, - hasFunctionCall, - }), - raw: response.incomplete_details?.reason ?? undefined, - }, - usage: convertOpenAIResponsesUsage(usage), - request: { body }, - response: { - id: response.id, - timestamp: new Date(response.created_at! * 1000), - modelId: response.model, - headers: responseHeaders, - body: rawResponse, - }, - providerMetadata, - warnings, - }; - } - - async doStream( - options: LanguageModelV3CallOptions, - ): Promise { - const { - args: body, - warnings, - webSearchToolName, - toolNameMapping, - store, - providerOptionsName, - isShellProviderExecuted, - } = await this.getArgs(options); - - const { responseHeaders, value: response } = await postJsonToApi({ - url: this.config.url({ - path: '/responses', - modelId: this.modelId, - }), - headers: combineHeaders(this.config.headers(), options.headers), - body: { - ...body, - stream: true, - }, - failedResponseHandler: openaiFailedResponseHandler, - successfulResponseHandler: createEventSourceResponseHandler( - openaiResponsesChunkSchema, - ), - abortSignal: options.abortSignal, - fetch: this.config.fetch, - }); - - const self = this; - - const approvalRequestIdToDummyToolCallIdFromPrompt = - extractApprovalRequestIdToToolCallIdMapping(options.prompt); - - const approvalRequestIdToDummyToolCallIdFromStream = new Map< - string, - string - >(); - - let finishReason: LanguageModelV3FinishReason = { - unified: 'other', - raw: undefined, - }; - let usage: OpenAIResponsesUsage | undefined = undefined; - const logprobs: Array = []; - let responseId: string | null = null; - - const ongoingToolCalls: Record< - number, - | { - toolName: string; - toolCallId: string; - codeInterpreter?: { - containerId: string; - }; - applyPatch?: { - hasDiff: boolean; - endEmitted: boolean; - }; - toolSearchExecution?: 'server' | 'client'; - } - | undefined - > = {}; - - // set annotations in 'text-end' part providerMetadata. - const ongoingAnnotations: Array< - Extract< - OpenAIResponsesChunk, - { type: 'response.output_text.annotation.added' } - >['annotation'] - > = []; - - // track the phase of the current message being streamed - let activeMessagePhase: 'commentary' | 'final_answer' | undefined; - - // flag that checks if there have been client-side tool calls (not executed by openai) - let hasFunctionCall = false; - - const activeReasoning: Record< - string, - { - encryptedContent?: string | null; - // summary index as string to reasoning part state: - summaryParts: Record; - } - > = {}; - - let serviceTier: string | undefined; - const hostedToolSearchCallIds: string[] = []; - - return { - stream: response.pipeThrough( - new TransformStream< - ParseResult, - LanguageModelV3StreamPart - >({ - start(controller) { - controller.enqueue({ type: 'stream-start', warnings }); - }, - - transform(chunk, controller) { - if (options.includeRawChunks) { - controller.enqueue({ type: 'raw', rawValue: chunk.rawValue }); - } - - // handle failed chunk parsing / validation: - if (!chunk.success) { - finishReason = { unified: 'error', raw: undefined }; - controller.enqueue({ type: 'error', error: chunk.error }); - return; - } - - const value = chunk.value; - - if (isResponseOutputItemAddedChunk(value)) { - if (value.item.type === 'function_call') { - ongoingToolCalls[value.output_index] = { - toolName: value.item.name, - toolCallId: value.item.call_id, - }; - - controller.enqueue({ - type: 'tool-input-start', - id: value.item.call_id, - toolName: value.item.name, - }); - } else if (value.item.type === 'custom_tool_call') { - const toolName = toolNameMapping.toCustomToolName( - value.item.name, - ); - ongoingToolCalls[value.output_index] = { - toolName, - toolCallId: value.item.call_id, - }; - - controller.enqueue({ - type: 'tool-input-start', - id: value.item.call_id, - toolName, - }); - } else if (value.item.type === 'web_search_call') { - ongoingToolCalls[value.output_index] = { - toolName: toolNameMapping.toCustomToolName( - webSearchToolName ?? 'web_search', - ), - toolCallId: value.item.id, - }; - - controller.enqueue({ - type: 'tool-input-start', - id: value.item.id, - toolName: toolNameMapping.toCustomToolName( - webSearchToolName ?? 'web_search', - ), - providerExecuted: true, - }); - - controller.enqueue({ - type: 'tool-input-end', - id: value.item.id, - }); - - controller.enqueue({ - type: 'tool-call', - toolCallId: value.item.id, - toolName: toolNameMapping.toCustomToolName( - webSearchToolName ?? 'web_search', - ), - input: JSON.stringify({}), - providerExecuted: true, - }); - } else if (value.item.type === 'computer_call') { - ongoingToolCalls[value.output_index] = { - toolName: toolNameMapping.toCustomToolName('computer_use'), - toolCallId: value.item.id, - }; - - controller.enqueue({ - type: 'tool-input-start', - id: value.item.id, - toolName: toolNameMapping.toCustomToolName('computer_use'), - providerExecuted: true, - }); - } else if (value.item.type === 'code_interpreter_call') { - ongoingToolCalls[value.output_index] = { - toolName: - toolNameMapping.toCustomToolName('code_interpreter'), - toolCallId: value.item.id, - codeInterpreter: { - containerId: value.item.container_id, - }, - }; - - controller.enqueue({ - type: 'tool-input-start', - id: value.item.id, - toolName: - toolNameMapping.toCustomToolName('code_interpreter'), - providerExecuted: true, - }); - - controller.enqueue({ - type: 'tool-input-delta', - id: value.item.id, - delta: `{"containerId":"${value.item.container_id}","code":"`, - }); - } else if (value.item.type === 'file_search_call') { - controller.enqueue({ - type: 'tool-call', - toolCallId: value.item.id, - toolName: toolNameMapping.toCustomToolName('file_search'), - input: '{}', - providerExecuted: true, - }); - } else if (value.item.type === 'image_generation_call') { - controller.enqueue({ - type: 'tool-call', - toolCallId: value.item.id, - toolName: - toolNameMapping.toCustomToolName('image_generation'), - input: '{}', - providerExecuted: true, - }); - } else if (value.item.type === 'tool_search_call') { - const toolCallId = value.item.id; - const toolName = - toolNameMapping.toCustomToolName('tool_search'); - const isHosted = value.item.execution === 'server'; - - ongoingToolCalls[value.output_index] = { - toolName, - toolCallId, - toolSearchExecution: value.item.execution ?? 'server', - }; - - if (isHosted) { - controller.enqueue({ - type: 'tool-input-start', - id: toolCallId, - toolName, - providerExecuted: true, - }); - } - } else if (value.item.type === 'tool_search_output') { - // handled on output_item.done so we can pair it with the call - } else if ( - value.item.type === 'mcp_call' || - value.item.type === 'mcp_list_tools' || - value.item.type === 'mcp_approval_request' - ) { - // Emit MCP tool-call/approval parts on output_item.done instead, so we can: - // - alias mcp_call IDs when an approval_request_id is present - // - emit a proper tool-approval-request part for MCP approvals - } else if (value.item.type === 'apply_patch_call') { - const { call_id: callId, operation } = value.item; - - ongoingToolCalls[value.output_index] = { - toolName: toolNameMapping.toCustomToolName('apply_patch'), - toolCallId: callId, - applyPatch: { - // delete_file doesn't have diff - hasDiff: operation.type === 'delete_file', - endEmitted: operation.type === 'delete_file', - }, - }; - - controller.enqueue({ - type: 'tool-input-start', - id: callId, - toolName: toolNameMapping.toCustomToolName('apply_patch'), - }); - - if (operation.type === 'delete_file') { - const inputString = JSON.stringify({ - callId, - operation, - } satisfies InferSchema); - - controller.enqueue({ - type: 'tool-input-delta', - id: callId, - delta: inputString, - }); - - controller.enqueue({ - type: 'tool-input-end', - id: callId, - }); - } else { - controller.enqueue({ - type: 'tool-input-delta', - id: callId, - delta: `{"callId":"${escapeJSONDelta(callId)}","operation":{"type":"${escapeJSONDelta(operation.type)}","path":"${escapeJSONDelta(operation.path)}","diff":"`, - }); - } - } else if (value.item.type === 'shell_call') { - ongoingToolCalls[value.output_index] = { - toolName: toolNameMapping.toCustomToolName('shell'), - toolCallId: value.item.call_id, - }; - } else if (value.item.type === 'shell_call_output') { - // shell_call_output is handled in output_item.done - } else if (value.item.type === 'message') { - ongoingAnnotations.splice(0, ongoingAnnotations.length); - activeMessagePhase = value.item.phase ?? undefined; - controller.enqueue({ - type: 'text-start', - id: value.item.id, - providerMetadata: { - [providerOptionsName]: { - itemId: value.item.id, - ...(value.item.phase != null && { - phase: value.item.phase, - }), - }, - }, - }); - } else if ( - isResponseOutputItemAddedChunk(value) && - value.item.type === 'reasoning' - ) { - activeReasoning[value.item.id] = { - encryptedContent: value.item.encrypted_content, - summaryParts: { 0: 'active' }, - }; - - controller.enqueue({ - type: 'reasoning-start', - id: `${value.item.id}:0`, - providerMetadata: { - [providerOptionsName]: { - itemId: value.item.id, - reasoningEncryptedContent: - value.item.encrypted_content ?? null, - } satisfies ResponsesReasoningProviderMetadata, - }, - }); - } - } else if (isResponseOutputItemDoneChunk(value)) { - if (value.item.type === 'message') { - const phase = value.item.phase ?? activeMessagePhase; - activeMessagePhase = undefined; - controller.enqueue({ - type: 'text-end', - id: value.item.id, - providerMetadata: { - [providerOptionsName]: { - itemId: value.item.id, - ...(phase != null && { phase }), - ...(ongoingAnnotations.length > 0 && { - annotations: ongoingAnnotations, - }), - } satisfies ResponsesTextProviderMetadata, - }, - }); - } else if (value.item.type === 'function_call') { - ongoingToolCalls[value.output_index] = undefined; - hasFunctionCall = true; - - controller.enqueue({ - type: 'tool-input-end', - id: value.item.call_id, - }); - - controller.enqueue({ - type: 'tool-call', - toolCallId: value.item.call_id, - toolName: value.item.name, - input: value.item.arguments, - providerMetadata: { - [providerOptionsName]: { - itemId: value.item.id, - }, - }, - }); - } else if (value.item.type === 'custom_tool_call') { - ongoingToolCalls[value.output_index] = undefined; - hasFunctionCall = true; - const toolName = toolNameMapping.toCustomToolName( - value.item.name, - ); - - controller.enqueue({ - type: 'tool-input-end', - id: value.item.call_id, - }); - - controller.enqueue({ - type: 'tool-call', - toolCallId: value.item.call_id, - toolName, - input: JSON.stringify(value.item.input), - providerMetadata: { - [providerOptionsName]: { - itemId: value.item.id, - }, - }, - }); - } else if (value.item.type === 'web_search_call') { - ongoingToolCalls[value.output_index] = undefined; - - controller.enqueue({ - type: 'tool-result', - toolCallId: value.item.id, - toolName: toolNameMapping.toCustomToolName( - webSearchToolName ?? 'web_search', - ), - result: mapWebSearchOutput(value.item.action), - }); - } else if (value.item.type === 'computer_call') { - ongoingToolCalls[value.output_index] = undefined; - - controller.enqueue({ - type: 'tool-input-end', - id: value.item.id, - }); - - controller.enqueue({ - type: 'tool-call', - toolCallId: value.item.id, - toolName: toolNameMapping.toCustomToolName('computer_use'), - input: '', - providerExecuted: true, - }); - - controller.enqueue({ - type: 'tool-result', - toolCallId: value.item.id, - toolName: toolNameMapping.toCustomToolName('computer_use'), - result: { - type: 'computer_use_tool_result', - status: value.item.status || 'completed', - }, - }); - } else if (value.item.type === 'file_search_call') { - ongoingToolCalls[value.output_index] = undefined; - - controller.enqueue({ - type: 'tool-result', - toolCallId: value.item.id, - toolName: toolNameMapping.toCustomToolName('file_search'), - result: { - queries: value.item.queries, - results: - value.item.results?.map(result => ({ - attributes: result.attributes, - fileId: result.file_id, - filename: result.filename, - score: result.score, - text: result.text, - })) ?? null, - } satisfies InferSchema, - }); - } else if (value.item.type === 'code_interpreter_call') { - ongoingToolCalls[value.output_index] = undefined; - - controller.enqueue({ - type: 'tool-result', - toolCallId: value.item.id, - toolName: - toolNameMapping.toCustomToolName('code_interpreter'), - result: { - outputs: value.item.outputs, - } satisfies InferSchema, - }); - } else if (value.item.type === 'image_generation_call') { - controller.enqueue({ - type: 'tool-result', - toolCallId: value.item.id, - toolName: - toolNameMapping.toCustomToolName('image_generation'), - result: { - result: value.item.result, - } satisfies InferSchema, - }); - } else if (value.item.type === 'tool_search_call') { - const toolCall = ongoingToolCalls[value.output_index]; - const isHosted = value.item.execution === 'server'; - - if (toolCall != null) { - const toolCallId = isHosted - ? toolCall.toolCallId - : (value.item.call_id ?? value.item.id); - - if (isHosted) { - hostedToolSearchCallIds.push(toolCallId); - } else { - controller.enqueue({ - type: 'tool-input-start', - id: toolCallId, - toolName: toolCall.toolName, - }); - } - - controller.enqueue({ - type: 'tool-input-end', - id: toolCallId, - }); - - controller.enqueue({ - type: 'tool-call', - toolCallId, - toolName: toolCall.toolName, - input: JSON.stringify({ - arguments: value.item.arguments, - call_id: isHosted ? null : toolCallId, - } satisfies InferSchema), - ...(isHosted ? { providerExecuted: true } : {}), - providerMetadata: { - [providerOptionsName]: { - itemId: value.item.id, - }, - }, - }); - } - - ongoingToolCalls[value.output_index] = undefined; - } else if (value.item.type === 'tool_search_output') { - const toolCallId = - value.item.call_id ?? - hostedToolSearchCallIds.shift() ?? - value.item.id; - - controller.enqueue({ - type: 'tool-result', - toolCallId, - toolName: toolNameMapping.toCustomToolName('tool_search'), - result: { - tools: value.item.tools, - } satisfies InferSchema, - providerMetadata: { - [providerOptionsName]: { - itemId: value.item.id, - }, - }, - }); - } else if (value.item.type === 'mcp_call') { - ongoingToolCalls[value.output_index] = undefined; - - const approvalRequestId = - value.item.approval_request_id ?? undefined; - - // when MCP tools require approval, we track them with our own - // tool call IDs and then map OpenAI's approval_request_id back to our ID so results match. - const aliasedToolCallId = - approvalRequestId != null - ? (approvalRequestIdToDummyToolCallIdFromStream.get( - approvalRequestId, - ) ?? - approvalRequestIdToDummyToolCallIdFromPrompt[ - approvalRequestId - ] ?? - value.item.id) - : value.item.id; - - const toolName = `mcp.${value.item.name}`; - - controller.enqueue({ - type: 'tool-call', - toolCallId: aliasedToolCallId, - toolName, - input: value.item.arguments, - providerExecuted: true, - dynamic: true, - }); - - controller.enqueue({ - type: 'tool-result', - toolCallId: aliasedToolCallId, - toolName, - result: { - type: 'call', - serverLabel: value.item.server_label, - name: value.item.name, - arguments: value.item.arguments, - ...(value.item.output != null - ? { output: value.item.output } - : {}), - ...(value.item.error != null - ? { error: value.item.error as unknown as JSONValue } - : {}), - } satisfies InferSchema, - providerMetadata: { - [providerOptionsName]: { - itemId: value.item.id, - }, - }, - }); - } else if (value.item.type === 'mcp_list_tools') { - // Skip listTools - we don't expose this to the UI or send it back - ongoingToolCalls[value.output_index] = undefined; - - // skip - } else if (value.item.type === 'apply_patch_call') { - const toolCall = ongoingToolCalls[value.output_index]; - if ( - toolCall?.applyPatch && - !toolCall.applyPatch.endEmitted && - value.item.operation.type !== 'delete_file' - ) { - if (!toolCall.applyPatch.hasDiff) { - controller.enqueue({ - type: 'tool-input-delta', - id: toolCall.toolCallId, - delta: escapeJSONDelta(value.item.operation.diff), - }); - } - - controller.enqueue({ - type: 'tool-input-delta', - id: toolCall.toolCallId, - delta: '"}}', - }); - - controller.enqueue({ - type: 'tool-input-end', - id: toolCall.toolCallId, - }); - - toolCall.applyPatch.endEmitted = true; - } - - // Emit the final tool-call with complete diff when status is 'completed' - if (toolCall && value.item.status === 'completed') { - controller.enqueue({ - type: 'tool-call', - toolCallId: toolCall.toolCallId, - toolName: toolNameMapping.toCustomToolName('apply_patch'), - input: JSON.stringify({ - callId: value.item.call_id, - operation: value.item.operation, - } satisfies InferSchema), - providerMetadata: { - [providerOptionsName]: { - itemId: value.item.id, - }, - }, - }); - } - - ongoingToolCalls[value.output_index] = undefined; - } else if (value.item.type === 'mcp_approval_request') { - ongoingToolCalls[value.output_index] = undefined; - - const dummyToolCallId = - self.config.generateId?.() ?? generateId(); - const approvalRequestId = - value.item.approval_request_id ?? value.item.id; - approvalRequestIdToDummyToolCallIdFromStream.set( - approvalRequestId, - dummyToolCallId, - ); - - const toolName = `mcp.${value.item.name}`; - - controller.enqueue({ - type: 'tool-call', - toolCallId: dummyToolCallId, - toolName, - input: value.item.arguments, - providerExecuted: true, - dynamic: true, - }); - - controller.enqueue({ - type: 'tool-approval-request', - approvalId: approvalRequestId, - toolCallId: dummyToolCallId, - }); - } else if (value.item.type === 'local_shell_call') { - ongoingToolCalls[value.output_index] = undefined; - - controller.enqueue({ - type: 'tool-call', - toolCallId: value.item.call_id, - toolName: toolNameMapping.toCustomToolName('local_shell'), - input: JSON.stringify({ - action: { - type: 'exec', - command: value.item.action.command, - timeoutMs: value.item.action.timeout_ms, - user: value.item.action.user, - workingDirectory: value.item.action.working_directory, - env: value.item.action.env, - }, - } satisfies InferSchema), - providerMetadata: { - [providerOptionsName]: { itemId: value.item.id }, - }, - }); - } else if (value.item.type === 'shell_call') { - ongoingToolCalls[value.output_index] = undefined; - - controller.enqueue({ - type: 'tool-call', - toolCallId: value.item.call_id, - toolName: toolNameMapping.toCustomToolName('shell'), - input: JSON.stringify({ - action: { - commands: value.item.action.commands, - }, - } satisfies InferSchema), - ...(isShellProviderExecuted && { - providerExecuted: true, - }), - providerMetadata: { - [providerOptionsName]: { itemId: value.item.id }, - }, - }); - } else if (value.item.type === 'shell_call_output') { - controller.enqueue({ - type: 'tool-result', - toolCallId: value.item.call_id, - toolName: toolNameMapping.toCustomToolName('shell'), - result: { - output: value.item.output.map( - (item: { - stdout: string; - stderr: string; - outcome: - | { type: 'exit'; exit_code: number } - | { type: 'timeout' }; - }) => ({ - stdout: item.stdout, - stderr: item.stderr, - outcome: - item.outcome.type === 'exit' - ? { - type: 'exit' as const, - exitCode: item.outcome.exit_code, - } - : { type: 'timeout' as const }, - }), - ), - } satisfies InferSchema, - }); - } else if (value.item.type === 'reasoning') { - const activeReasoningPart = activeReasoning[value.item.id]; - - // get all active or can-conclude summary parts' ids - // to conclude ongoing reasoning parts: - const summaryPartIndices = Object.entries( - activeReasoningPart.summaryParts, - ) - .filter( - ([_, status]) => - status === 'active' || status === 'can-conclude', - ) - .map(([summaryIndex]) => summaryIndex); - - for (const summaryIndex of summaryPartIndices) { - controller.enqueue({ - type: 'reasoning-end', - id: `${value.item.id}:${summaryIndex}`, - providerMetadata: { - [providerOptionsName]: { - itemId: value.item.id, - reasoningEncryptedContent: - value.item.encrypted_content ?? null, - } satisfies ResponsesReasoningProviderMetadata, - }, - }); - } - - delete activeReasoning[value.item.id]; - } - } else if (isResponseFunctionCallArgumentsDeltaChunk(value)) { - const toolCall = ongoingToolCalls[value.output_index]; - - if (toolCall != null) { - controller.enqueue({ - type: 'tool-input-delta', - id: toolCall.toolCallId, - delta: value.delta, - }); - } - } else if (isResponseCustomToolCallInputDeltaChunk(value)) { - const toolCall = ongoingToolCalls[value.output_index]; - - if (toolCall != null) { - controller.enqueue({ - type: 'tool-input-delta', - id: toolCall.toolCallId, - delta: value.delta, - }); - } - } else if (isResponseApplyPatchCallOperationDiffDeltaChunk(value)) { - const toolCall = ongoingToolCalls[value.output_index]; - - if (toolCall?.applyPatch) { - controller.enqueue({ - type: 'tool-input-delta', - id: toolCall.toolCallId, - delta: escapeJSONDelta(value.delta), - }); - - toolCall.applyPatch.hasDiff = true; - } - } else if (isResponseApplyPatchCallOperationDiffDoneChunk(value)) { - const toolCall = ongoingToolCalls[value.output_index]; - - if (toolCall?.applyPatch && !toolCall.applyPatch.endEmitted) { - if (!toolCall.applyPatch.hasDiff) { - controller.enqueue({ - type: 'tool-input-delta', - id: toolCall.toolCallId, - delta: escapeJSONDelta(value.diff), - }); - - toolCall.applyPatch.hasDiff = true; - } - - controller.enqueue({ - type: 'tool-input-delta', - id: toolCall.toolCallId, - delta: '"}}', - }); - - controller.enqueue({ - type: 'tool-input-end', - id: toolCall.toolCallId, - }); - - toolCall.applyPatch.endEmitted = true; - } - } else if (isResponseImageGenerationCallPartialImageChunk(value)) { - controller.enqueue({ - type: 'tool-result', - toolCallId: value.item_id, - toolName: toolNameMapping.toCustomToolName('image_generation'), - result: { - result: value.partial_image_b64, - } satisfies InferSchema, - preliminary: true, - }); - } else if (isResponseCodeInterpreterCallCodeDeltaChunk(value)) { - const toolCall = ongoingToolCalls[value.output_index]; - - if (toolCall != null) { - controller.enqueue({ - type: 'tool-input-delta', - id: toolCall.toolCallId, - delta: escapeJSONDelta(value.delta), - }); - } - } else if (isResponseCodeInterpreterCallCodeDoneChunk(value)) { - const toolCall = ongoingToolCalls[value.output_index]; - - if (toolCall != null) { - controller.enqueue({ - type: 'tool-input-delta', - id: toolCall.toolCallId, - delta: '"}', - }); - - controller.enqueue({ - type: 'tool-input-end', - id: toolCall.toolCallId, - }); - - // immediately send the tool call after the input end: - controller.enqueue({ - type: 'tool-call', - toolCallId: toolCall.toolCallId, - toolName: - toolNameMapping.toCustomToolName('code_interpreter'), - input: JSON.stringify({ - code: value.code, - containerId: toolCall.codeInterpreter!.containerId, - } satisfies InferSchema), - providerExecuted: true, - }); - } - } else if (isResponseCreatedChunk(value)) { - responseId = value.response.id; - controller.enqueue({ - type: 'response-metadata', - id: value.response.id, - timestamp: new Date(value.response.created_at * 1000), - modelId: value.response.model, - }); - } else if (isTextDeltaChunk(value)) { - controller.enqueue({ - type: 'text-delta', - id: value.item_id, - delta: value.delta, - }); - - if ( - options.providerOptions?.[providerOptionsName]?.logprobs && - value.logprobs - ) { - logprobs.push(value.logprobs); - } - } else if (value.type === 'response.reasoning_summary_part.added') { - // the first reasoning start is pushed in isResponseOutputItemAddedReasoningChunk - if (value.summary_index > 0) { - const activeReasoningPart = activeReasoning[value.item_id]!; - - activeReasoningPart.summaryParts[value.summary_index] = - 'active'; - - // since there is a new active summary part, we can conclude all can-conclude summary parts - for (const summaryIndex of Object.keys( - activeReasoningPart.summaryParts, - )) { - if ( - activeReasoningPart.summaryParts[summaryIndex] === - 'can-conclude' - ) { - controller.enqueue({ - type: 'reasoning-end', - id: `${value.item_id}:${summaryIndex}`, - providerMetadata: { - [providerOptionsName]: { - itemId: value.item_id, - } satisfies ResponsesReasoningProviderMetadata, - }, - }); - activeReasoningPart.summaryParts[summaryIndex] = - 'concluded'; - } - } - - controller.enqueue({ - type: 'reasoning-start', - id: `${value.item_id}:${value.summary_index}`, - providerMetadata: { - [providerOptionsName]: { - itemId: value.item_id, - reasoningEncryptedContent: - activeReasoning[value.item_id]?.encryptedContent ?? - null, - } satisfies ResponsesReasoningProviderMetadata, - }, - }); - } - } else if (value.type === 'response.reasoning_summary_text.delta') { - controller.enqueue({ - type: 'reasoning-delta', - id: `${value.item_id}:${value.summary_index}`, - delta: value.delta, - providerMetadata: { - [providerOptionsName]: { - itemId: value.item_id, - } satisfies ResponsesReasoningProviderMetadata, - }, - }); - } else if (value.type === 'response.reasoning_summary_part.done') { - // when OpenAI stores the message data, we can immediately conclude the reasoning part - // since we do not need to send the encrypted content. - if (store) { - controller.enqueue({ - type: 'reasoning-end', - id: `${value.item_id}:${value.summary_index}`, - providerMetadata: { - [providerOptionsName]: { - itemId: value.item_id, - } satisfies ResponsesReasoningProviderMetadata, - }, - }); - - // mark the summary part as concluded - activeReasoning[value.item_id]!.summaryParts[ - value.summary_index - ] = 'concluded'; - } else { - // mark the summary part as can-conclude only - // because we need to have a final summary part with the encrypted content - activeReasoning[value.item_id]!.summaryParts[ - value.summary_index - ] = 'can-conclude'; - } - } else if (isResponseFinishedChunk(value)) { - finishReason = { - unified: mapOpenAIResponseFinishReason({ - finishReason: value.response.incomplete_details?.reason, - hasFunctionCall, - }), - raw: value.response.incomplete_details?.reason ?? undefined, - }; - usage = value.response.usage; - if (typeof value.response.service_tier === 'string') { - serviceTier = value.response.service_tier; - } - } else if (isResponseFailedChunk(value)) { - const incompleteReason = - value.response.incomplete_details?.reason; - finishReason = { - unified: incompleteReason - ? mapOpenAIResponseFinishReason({ - finishReason: incompleteReason, - hasFunctionCall, - }) - : 'error', - raw: incompleteReason ?? 'error', - }; - usage = value.response.usage ?? undefined; - } else if (isResponseAnnotationAddedChunk(value)) { - ongoingAnnotations.push(value.annotation); - if (value.annotation.type === 'url_citation') { - controller.enqueue({ - type: 'source', - sourceType: 'url', - id: self.config.generateId?.() ?? generateId(), - url: value.annotation.url, - title: value.annotation.title, - }); - } else if (value.annotation.type === 'file_citation') { - controller.enqueue({ - type: 'source', - sourceType: 'document', - id: self.config.generateId?.() ?? generateId(), - mediaType: 'text/plain', - title: value.annotation.filename, - filename: value.annotation.filename, - providerMetadata: { - [providerOptionsName]: { - type: value.annotation.type, - fileId: value.annotation.file_id, - index: value.annotation.index, - } satisfies Extract< - ResponsesSourceDocumentProviderMetadata, - { type: 'file_citation' } - >, - }, - }); - } else if (value.annotation.type === 'container_file_citation') { - controller.enqueue({ - type: 'source', - sourceType: 'document', - id: self.config.generateId?.() ?? generateId(), - mediaType: 'text/plain', - title: value.annotation.filename, - filename: value.annotation.filename, - providerMetadata: { - [providerOptionsName]: { - type: value.annotation.type, - fileId: value.annotation.file_id, - containerId: value.annotation.container_id, - } satisfies Extract< - ResponsesSourceDocumentProviderMetadata, - { type: 'container_file_citation' } - >, - }, - }); - } else if (value.annotation.type === 'file_path') { - controller.enqueue({ - type: 'source', - sourceType: 'document', - id: self.config.generateId?.() ?? generateId(), - mediaType: 'application/octet-stream', - title: value.annotation.file_id, - filename: value.annotation.file_id, - providerMetadata: { - [providerOptionsName]: { - type: value.annotation.type, - fileId: value.annotation.file_id, - index: value.annotation.index, - } satisfies Extract< - ResponsesSourceDocumentProviderMetadata, - { type: 'file_path' } - >, - }, - }); - } - } else if (isErrorChunk(value)) { - controller.enqueue({ type: 'error', error: value }); - } - }, - - flush(controller) { - const providerMetadata: SharedV3ProviderMetadata = { - [providerOptionsName]: { - responseId: responseId, - ...(logprobs.length > 0 ? { logprobs } : {}), - ...(serviceTier !== undefined ? { serviceTier } : {}), - } satisfies ResponsesProviderMetadata, - }; - - controller.enqueue({ - type: 'finish', - finishReason, - usage: convertOpenAIResponsesUsage(usage), - providerMetadata, - }); - }, - }), - ), - request: { body }, - response: { headers: responseHeaders }, - }; - } -} - -function isTextDeltaChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { type: 'response.output_text.delta' } { - return chunk.type === 'response.output_text.delta'; -} - -function isResponseOutputItemDoneChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { type: 'response.output_item.done' } { - return chunk.type === 'response.output_item.done'; -} - -function isResponseFinishedChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { - type: 'response.completed' | 'response.incomplete'; -} { - return ( - chunk.type === 'response.completed' || chunk.type === 'response.incomplete' - ); -} - -function isResponseFailedChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { type: 'response.failed' } { - return chunk.type === 'response.failed'; -} - -function isResponseCreatedChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { type: 'response.created' } { - return chunk.type === 'response.created'; -} - -function isResponseFunctionCallArgumentsDeltaChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { - type: 'response.function_call_arguments.delta'; -} { - return chunk.type === 'response.function_call_arguments.delta'; -} - -function isResponseCustomToolCallInputDeltaChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { - type: 'response.custom_tool_call_input.delta'; -} { - return chunk.type === 'response.custom_tool_call_input.delta'; -} - -function isResponseImageGenerationCallPartialImageChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { - type: 'response.image_generation_call.partial_image'; -} { - return chunk.type === 'response.image_generation_call.partial_image'; -} - -function isResponseCodeInterpreterCallCodeDeltaChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { - type: 'response.code_interpreter_call_code.delta'; -} { - return chunk.type === 'response.code_interpreter_call_code.delta'; -} - -function isResponseCodeInterpreterCallCodeDoneChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { - type: 'response.code_interpreter_call_code.done'; -} { - return chunk.type === 'response.code_interpreter_call_code.done'; -} - -function isResponseApplyPatchCallOperationDiffDeltaChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesApplyPatchOperationDiffDeltaChunk { - return chunk.type === 'response.apply_patch_call_operation_diff.delta'; -} - -function isResponseApplyPatchCallOperationDiffDoneChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesApplyPatchOperationDiffDoneChunk { - return chunk.type === 'response.apply_patch_call_operation_diff.done'; -} - -function isResponseOutputItemAddedChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { type: 'response.output_item.added' } { - return chunk.type === 'response.output_item.added'; -} - -function isResponseAnnotationAddedChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { - type: 'response.output_text.annotation.added'; -} { - return chunk.type === 'response.output_text.annotation.added'; -} - -function isErrorChunk( - chunk: OpenAIResponsesChunk, -): chunk is OpenAIResponsesChunk & { type: 'error' } { - return chunk.type === 'error'; -} - -function mapWebSearchOutput( - action: OpenAIResponsesWebSearchAction | null | undefined, -): InferSchema { - if (action == null) { - return {}; - } - - switch (action.type) { - case 'search': - return { - action: { type: 'search', query: action.query ?? undefined }, - // include sources when provided by the Responses API (behind include flag) - ...(action.sources != null && { sources: action.sources }), - }; - case 'open_page': - return { action: { type: 'openPage', url: action.url } }; - case 'find_in_page': - return { - action: { - type: 'findInPage', - url: action.url, - pattern: action.pattern, - }, - }; - } -} - -// The delta is embedded in a JSON string. -// To escape it, we use JSON.stringify and slice to remove the outer quotes. -function escapeJSONDelta(delta: string) { - return JSON.stringify(delta).slice(1, -1); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-options.ts deleted file mode 100644 index 4477d7a12..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-options.ts +++ /dev/null @@ -1,317 +0,0 @@ -import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -/** - * `top_logprobs` request body argument can be set to an integer between - * 0 and 20 specifying the number of most likely tokens to return at each - * token position, each with an associated log probability. - * - * @see https://platform.openai.com/docs/api-reference/responses/create#responses_create-top_logprobs - */ -export const TOP_LOGPROBS_MAX = 20; - -export const openaiResponsesReasoningModelIds = [ - 'o1', - 'o1-2024-12-17', - 'o3', - 'o3-2025-04-16', - 'o3-mini', - 'o3-mini-2025-01-31', - 'o4-mini', - 'o4-mini-2025-04-16', - 'gpt-5', - 'gpt-5-2025-08-07', - 'gpt-5-codex', - 'gpt-5-mini', - 'gpt-5-mini-2025-08-07', - 'gpt-5-nano', - 'gpt-5-nano-2025-08-07', - 'gpt-5-pro', - 'gpt-5-pro-2025-10-06', - 'gpt-5.1', - 'gpt-5.1-chat-latest', - 'gpt-5.1-codex-mini', - 'gpt-5.1-codex', - 'gpt-5.1-codex-max', - 'gpt-5.2', - 'gpt-5.2-chat-latest', - 'gpt-5.2-pro', - 'gpt-5.2-codex', - 'gpt-5.3-chat-latest', - 'gpt-5.3-codex', - 'gpt-5.4', - 'gpt-5.4-2026-03-05', - 'gpt-5.4-mini', - 'gpt-5.4-mini-2026-03-17', - 'gpt-5.4-nano', - 'gpt-5.4-nano-2026-03-17', - 'gpt-5.4-pro', - 'gpt-5.4-pro-2026-03-05', -] as const; - -export const openaiResponsesModelIds = [ - 'gpt-4.1', - 'gpt-4.1-2025-04-14', - 'gpt-4.1-mini', - 'gpt-4.1-mini-2025-04-14', - 'gpt-4.1-nano', - 'gpt-4.1-nano-2025-04-14', - 'gpt-4o', - 'gpt-4o-2024-05-13', - 'gpt-4o-2024-08-06', - 'gpt-4o-2024-11-20', - 'gpt-4o-audio-preview', - 'gpt-4o-audio-preview-2024-12-17', - 'gpt-4o-search-preview', - 'gpt-4o-search-preview-2025-03-11', - 'gpt-4o-mini-search-preview', - 'gpt-4o-mini-search-preview-2025-03-11', - 'gpt-4o-mini', - 'gpt-4o-mini-2024-07-18', - 'gpt-3.5-turbo-0125', - 'gpt-3.5-turbo', - 'gpt-3.5-turbo-1106', - 'gpt-5-chat-latest', - ...openaiResponsesReasoningModelIds, -] as const; - -export type OpenAIResponsesModelId = - | 'gpt-3.5-turbo-0125' - | 'gpt-3.5-turbo-1106' - | 'gpt-3.5-turbo' - | 'gpt-4.1-2025-04-14' - | 'gpt-4.1-mini-2025-04-14' - | 'gpt-4.1-mini' - | 'gpt-4.1-nano-2025-04-14' - | 'gpt-4.1-nano' - | 'gpt-4.1' - | 'gpt-4o-2024-05-13' - | 'gpt-4o-2024-08-06' - | 'gpt-4o-2024-11-20' - | 'gpt-4o-mini-2024-07-18' - | 'gpt-4o-mini' - | 'gpt-4o' - | 'gpt-5.1' - | 'gpt-5.1-2025-11-13' - | 'gpt-5.1-chat-latest' - | 'gpt-5.1-codex-mini' - | 'gpt-5.1-codex' - | 'gpt-5.1-codex-max' - | 'gpt-5.2' - | 'gpt-5.2-2025-12-11' - | 'gpt-5.2-chat-latest' - | 'gpt-5.2-pro' - | 'gpt-5.2-pro-2025-12-11' - | 'gpt-5.2-codex' - | 'gpt-5.3-chat-latest' - | 'gpt-5.3-codex' - | 'gpt-5.4' - | 'gpt-5.4-2026-03-05' - | 'gpt-5.4-mini' - | 'gpt-5.4-mini-2026-03-17' - | 'gpt-5.4-nano' - | 'gpt-5.4-nano-2026-03-17' - | 'gpt-5.4-pro' - | 'gpt-5.4-pro-2026-03-05' - | 'gpt-5-2025-08-07' - | 'gpt-5-chat-latest' - | 'gpt-5-codex' - | 'gpt-5-mini-2025-08-07' - | 'gpt-5-mini' - | 'gpt-5-nano-2025-08-07' - | 'gpt-5-nano' - | 'gpt-5-pro-2025-10-06' - | 'gpt-5-pro' - | 'gpt-5' - | 'o1-2024-12-17' - | 'o1' - | 'o3-2025-04-16' - | 'o3-mini-2025-01-31' - | 'o3-mini' - | 'o3' - | 'o4-mini' - | 'o4-mini-2025-04-16' - | (string & {}); - -// TODO AI SDK 6: use optional here instead of nullish -export const openaiLanguageModelResponsesOptionsSchema = lazySchema(() => - zodSchema( - z.object({ - /** - * The ID of the OpenAI Conversation to continue. - * You must create a conversation first via the OpenAI API. - * Cannot be used in conjunction with `previousResponseId`. - * Defaults to `undefined`. - * @see https://platform.openai.com/docs/api-reference/conversations/create - */ - conversation: z.string().nullish(), - - /** - * The set of extra fields to include in the response (advanced, usually not needed). - * Example values: 'reasoning.encrypted_content', 'file_search_call.results', 'message.output_text.logprobs'. - */ - include: z - .array( - z.enum([ - 'reasoning.encrypted_content', // handled internally by default, only needed for unknown reasoning models - 'file_search_call.results', - 'message.output_text.logprobs', - ]), - ) - .nullish(), - - /** - * Instructions for the model. - * They can be used to change the system or developer message when continuing a conversation using the `previousResponseId` option. - * Defaults to `undefined`. - */ - instructions: z.string().nullish(), - - /** - * Return the log probabilities of the tokens. Including logprobs will increase - * the response size and can slow down response times. However, it can - * be useful to better understand how the model is behaving. - * - * Setting to true will return the log probabilities of the tokens that - * were generated. - * - * Setting to a number will return the log probabilities of the top n - * tokens that were generated. - * - * @see https://platform.openai.com/docs/api-reference/responses/create - * @see https://cookbook.openai.com/examples/using_logprobs - */ - logprobs: z - .union([z.boolean(), z.number().min(1).max(TOP_LOGPROBS_MAX)]) - .optional(), - - /** - * The maximum number of total calls to built-in tools that can be processed in a response. - * This maximum number applies across all built-in tool calls, not per individual tool. - * Any further attempts to call a tool by the model will be ignored. - */ - maxToolCalls: z.number().nullish(), - - /** - * Additional metadata to store with the generation. - */ - metadata: z.any().nullish(), - - /** - * Whether to use parallel tool calls. Defaults to `true`. - */ - parallelToolCalls: z.boolean().nullish(), - - /** - * The ID of the previous response. You can use it to continue a conversation. - * Defaults to `undefined`. - */ - previousResponseId: z.string().nullish(), - - /** - * Sets a cache key to tie this prompt to cached prefixes for better caching performance. - */ - promptCacheKey: z.string().nullish(), - - /** - * The retention policy for the prompt cache. - * - 'in_memory': Default. Standard prompt caching behavior. - * - '24h': Extended prompt caching that keeps cached prefixes active for up to 24 hours. - * Currently only available for 5.1 series models. - * - * @default 'in_memory' - */ - promptCacheRetention: z.enum(['in_memory', '24h']).nullish(), - - /** - * Reasoning effort for reasoning models. Defaults to `medium`. If you use - * `providerOptions` to set the `reasoningEffort` option, this model setting will be ignored. - * Valid values: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' - * - * The 'none' type for `reasoningEffort` is only available for OpenAI's GPT-5.1 - * models. Also, the 'xhigh' type for `reasoningEffort` is only available for - * OpenAI's GPT-5.1-Codex-Max model. Setting `reasoningEffort` to 'none' or 'xhigh' with unsupported models will result in - * an error. - */ - reasoningEffort: z.string().nullish(), - - /** - * Controls reasoning summary output from the model. - * Set to "auto" to automatically receive the richest level available, - * or "detailed" for comprehensive summaries. - */ - reasoningSummary: z.string().nullish(), - - /** - * The identifier for safety monitoring and tracking. - */ - safetyIdentifier: z.string().nullish(), - - /** - * Service tier for the request. - * Set to 'flex' for 50% cheaper processing at the cost of increased latency (available for o3, o4-mini, and gpt-5 models). - * Set to 'priority' for faster processing with Enterprise access (available for gpt-4, gpt-5, gpt-5-mini, o3, o4-mini; gpt-5-nano is not supported). - * - * Defaults to 'auto'. - */ - serviceTier: z.enum(['auto', 'flex', 'priority', 'default']).nullish(), - - /** - * Whether to store the generation. Defaults to `true`. - */ - store: z.boolean().nullish(), - - /** - * Whether to use strict JSON schema validation. - * Defaults to `true`. - */ - strictJsonSchema: z.boolean().nullish(), - - /** - * Controls the verbosity of the model's responses. Lower values ('low') will result - * in more concise responses, while higher values ('high') will result in more verbose responses. - * Valid values: 'low', 'medium', 'high'. - */ - textVerbosity: z.enum(['low', 'medium', 'high']).nullish(), - - /** - * Controls output truncation. 'auto' (default) performs truncation automatically; - * 'disabled' turns truncation off. - */ - truncation: z.enum(['auto', 'disabled']).nullish(), - - /** - * A unique identifier representing your end-user, which can help OpenAI to - * monitor and detect abuse. - * Defaults to `undefined`. - * @see https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids - */ - user: z.string().nullish(), - - /** - * Override the system message mode for this model. - * - 'system': Use the 'system' role for system messages (default for most models) - * - 'developer': Use the 'developer' role for system messages (used by reasoning models) - * - 'remove': Remove system messages entirely - * - * If not specified, the mode is automatically determined based on the model. - */ - systemMessageMode: z.enum(['system', 'developer', 'remove']).optional(), - - /** - * Force treating this model as a reasoning model. - * - * This is useful for "stealth" reasoning models (e.g. via a custom baseURL) - * where the model ID is not recognized by the SDK's allowlist. - * - * When enabled, the SDK applies reasoning-model parameter compatibility rules - * and defaults `systemMessageMode` to `developer` unless overridden. - */ - forceReasoning: z.boolean().optional(), - }), - ), -); - -export type OpenAILanguageModelResponsesOptions = InferSchema< - typeof openaiLanguageModelResponsesOptionsSchema ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-prepare-tools.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-prepare-tools.ts deleted file mode 100644 index f96b5b667..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-prepare-tools.ts +++ /dev/null @@ -1,433 +0,0 @@ -import { - LanguageModelV3CallOptions, - SharedV3Warning, - UnsupportedFunctionalityError, -} from '@ai-sdk/provider'; -import { ToolNameMapping, validateTypes } from '@ai-sdk/provider-utils'; -import { codeInterpreterArgsSchema } from '../tool/code-interpreter'; -import { fileSearchArgsSchema } from '../tool/file-search'; -import { imageGenerationArgsSchema } from '../tool/image-generation'; -import { customArgsSchema } from '../tool/custom'; -import { mcpArgsSchema } from '../tool/mcp'; -import { shellArgsSchema } from '../tool/shell'; -import { toolSearchArgsSchema } from '../tool/tool-search'; -import { webSearchArgsSchema } from '../tool/web-search'; -import { webSearchPreviewArgsSchema } from '../tool/web-search-preview'; -import { OpenAIResponsesTool } from './openai-responses-api'; - -export async function prepareResponsesTools({ - tools, - toolChoice, - toolNameMapping, - customProviderToolNames, -}: { - tools: LanguageModelV3CallOptions['tools']; - toolChoice: LanguageModelV3CallOptions['toolChoice'] | undefined; - toolNameMapping?: ToolNameMapping; - customProviderToolNames?: Set; -}): Promise<{ - tools?: Array; - toolChoice?: - | 'auto' - | 'none' - | 'required' - | { type: 'file_search' } - | { type: 'web_search_preview' } - | { type: 'web_search' } - | { type: 'function'; name: string } - | { type: 'custom'; name: string } - | { type: 'code_interpreter' } - | { type: 'mcp' } - | { type: 'image_generation' } - | { type: 'apply_patch' }; - toolWarnings: SharedV3Warning[]; -}> { - // when the tools array is empty, change it to undefined to prevent errors: - tools = tools?.length ? tools : undefined; - - const toolWarnings: SharedV3Warning[] = []; - - if (tools == null) { - return { tools: undefined, toolChoice: undefined, toolWarnings }; - } - - const openaiTools: Array = []; - const resolvedCustomProviderToolNames = - customProviderToolNames ?? new Set(); - - for (const tool of tools) { - switch (tool.type) { - case 'function': { - const openaiOptions = tool.providerOptions?.openai as - | { deferLoading?: boolean } - | undefined; - const deferLoading = openaiOptions?.deferLoading; - - openaiTools.push({ - type: 'function', - name: tool.name, - description: tool.description, - parameters: tool.inputSchema, - ...(tool.strict != null ? { strict: tool.strict } : {}), - ...(deferLoading != null ? { defer_loading: deferLoading } : {}), - }); - break; - } - case 'provider': { - switch (tool.id) { - case 'openai.file_search': { - const args = await validateTypes({ - value: tool.args, - schema: fileSearchArgsSchema, - }); - - openaiTools.push({ - type: 'file_search', - vector_store_ids: args.vectorStoreIds, - max_num_results: args.maxNumResults, - ranking_options: args.ranking - ? { - ranker: args.ranking.ranker, - score_threshold: args.ranking.scoreThreshold, - } - : undefined, - filters: args.filters, - }); - - break; - } - case 'openai.local_shell': { - openaiTools.push({ - type: 'local_shell', - }); - break; - } - case 'openai.shell': { - const args = await validateTypes({ - value: tool.args, - schema: shellArgsSchema, - }); - - openaiTools.push({ - type: 'shell', - ...(args.environment && { - environment: mapShellEnvironment(args.environment), - }), - }); - break; - } - case 'openai.apply_patch': { - openaiTools.push({ - type: 'apply_patch', - }); - break; - } - case 'openai.web_search_preview': { - const args = await validateTypes({ - value: tool.args, - schema: webSearchPreviewArgsSchema, - }); - openaiTools.push({ - type: 'web_search_preview', - search_context_size: args.searchContextSize, - user_location: args.userLocation, - }); - break; - } - case 'openai.web_search': { - const args = await validateTypes({ - value: tool.args, - schema: webSearchArgsSchema, - }); - openaiTools.push({ - type: 'web_search', - filters: - args.filters != null - ? { allowed_domains: args.filters.allowedDomains } - : undefined, - external_web_access: args.externalWebAccess, - search_context_size: args.searchContextSize, - user_location: args.userLocation, - }); - break; - } - case 'openai.code_interpreter': { - const args = await validateTypes({ - value: tool.args, - schema: codeInterpreterArgsSchema, - }); - - openaiTools.push({ - type: 'code_interpreter', - container: - args.container == null - ? { type: 'auto', file_ids: undefined } - : typeof args.container === 'string' - ? args.container - : { type: 'auto', file_ids: args.container.fileIds }, - }); - break; - } - case 'openai.image_generation': { - const args = await validateTypes({ - value: tool.args, - schema: imageGenerationArgsSchema, - }); - - openaiTools.push({ - type: 'image_generation', - background: args.background, - input_fidelity: args.inputFidelity, - input_image_mask: args.inputImageMask - ? { - file_id: args.inputImageMask.fileId, - image_url: args.inputImageMask.imageUrl, - } - : undefined, - model: args.model, - moderation: args.moderation, - partial_images: args.partialImages, - quality: args.quality, - output_compression: args.outputCompression, - output_format: args.outputFormat, - size: args.size, - }); - break; - } - case 'openai.mcp': { - const args = await validateTypes({ - value: tool.args, - schema: mcpArgsSchema, - }); - - const mapApprovalFilter = (filter: { toolNames?: string[] }) => ({ - tool_names: filter.toolNames, - }); - - const requireApproval = args.requireApproval; - const requireApprovalParam: - | 'always' - | 'never' - | { - never?: { tool_names?: string[] }; - } - | undefined = - requireApproval == null - ? undefined - : typeof requireApproval === 'string' - ? requireApproval - : requireApproval.never != null - ? { never: mapApprovalFilter(requireApproval.never) } - : undefined; - - openaiTools.push({ - type: 'mcp', - server_label: args.serverLabel, - allowed_tools: Array.isArray(args.allowedTools) - ? args.allowedTools - : args.allowedTools - ? { - read_only: args.allowedTools.readOnly, - tool_names: args.allowedTools.toolNames, - } - : undefined, - authorization: args.authorization, - connector_id: args.connectorId, - headers: args.headers, - require_approval: requireApprovalParam ?? 'never', - server_description: args.serverDescription, - server_url: args.serverUrl, - }); - - break; - } - case 'openai.custom': { - const args = await validateTypes({ - value: tool.args, - schema: customArgsSchema, - }); - - openaiTools.push({ - type: 'custom', - name: args.name, - description: args.description, - format: args.format, - }); - resolvedCustomProviderToolNames.add(args.name); - break; - } - case 'openai.tool_search': { - const args = await validateTypes({ - value: tool.args, - schema: toolSearchArgsSchema, - }); - openaiTools.push({ - type: 'tool_search', - ...(args.execution != null ? { execution: args.execution } : {}), - ...(args.description != null - ? { description: args.description } - : {}), - ...(args.parameters != null - ? { parameters: args.parameters } - : {}), - }); - break; - } - } - break; - } - default: - toolWarnings.push({ - type: 'unsupported', - feature: `function tool ${tool}`, - }); - break; - } - } - - if (toolChoice == null) { - return { tools: openaiTools, toolChoice: undefined, toolWarnings }; - } - - const type = toolChoice.type; - - switch (type) { - case 'auto': - case 'none': - case 'required': - return { tools: openaiTools, toolChoice: type, toolWarnings }; - case 'tool': { - const resolvedToolName = - toolNameMapping?.toProviderToolName(toolChoice.toolName) ?? - toolChoice.toolName; - - return { - tools: openaiTools, - toolChoice: - resolvedToolName === 'code_interpreter' || - resolvedToolName === 'file_search' || - resolvedToolName === 'image_generation' || - resolvedToolName === 'web_search_preview' || - resolvedToolName === 'web_search' || - resolvedToolName === 'mcp' || - resolvedToolName === 'apply_patch' - ? { type: resolvedToolName } - : resolvedCustomProviderToolNames.has(resolvedToolName) - ? { type: 'custom', name: resolvedToolName } - : { type: 'function', name: resolvedToolName }, - toolWarnings, - }; - } - default: { - const _exhaustiveCheck: never = type; - throw new UnsupportedFunctionalityError({ - functionality: `tool choice type: ${_exhaustiveCheck}`, - }); - } - } -} - -function mapShellEnvironment(environment: { - type?: string; - [key: string]: unknown; -}): NonNullable< - Extract['environment'] -> { - if (environment.type === 'containerReference') { - const env = environment as { - type: 'containerReference'; - containerId: string; - }; - return { - type: 'container_reference', - container_id: env.containerId, - }; - } - - if (environment.type === 'containerAuto') { - const env = environment as { - type: 'containerAuto'; - fileIds?: string[]; - memoryLimit?: '1g' | '4g' | '16g' | '64g'; - networkPolicy?: { - type: string; - allowedDomains?: string[]; - domainSecrets?: Array<{ - domain: string; - name: string; - value: string; - }>; - }; - skills?: Array<{ - type: string; - skillId?: string; - version?: string; - name?: string; - description?: string; - source?: { type: string; mediaType: string; data: string }; - }>; - }; - - return { - type: 'container_auto', - file_ids: env.fileIds, - memory_limit: env.memoryLimit, - network_policy: - env.networkPolicy == null - ? undefined - : env.networkPolicy.type === 'disabled' - ? { type: 'disabled' as const } - : { - type: 'allowlist' as const, - allowed_domains: env.networkPolicy.allowedDomains!, - domain_secrets: env.networkPolicy.domainSecrets, - }, - skills: mapShellSkills(env.skills), - }; - } - - const env = environment as { - type?: 'local'; - skills?: Array<{ - name: string; - description: string; - path: string; - }>; - }; - return { - type: 'local', - skills: env.skills, - }; -} - -function mapShellSkills( - skills: - | Array<{ - type: string; - skillId?: string; - version?: string; - name?: string; - description?: string; - source?: { type: string; mediaType: string; data: string }; - }> - | undefined, -) { - return skills?.map(skill => - skill.type === 'skillReference' - ? { - type: 'skill_reference' as const, - skill_id: skill.skillId!, - version: skill.version, - } - : { - type: 'inline' as const, - name: skill.name!, - description: skill.description!, - source: { - type: 'base64' as const, - media_type: skill.source!.mediaType as 'application/zip', - data: skill.source!.data, - }, - }, - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-provider-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-provider-metadata.ts deleted file mode 100644 index a0e245033..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/responses/openai-responses-provider-metadata.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { - openaiResponsesChunkSchema, - OpenAIResponsesLogprobs, -} from './openai-responses-api'; -import { InferSchema } from '@ai-sdk/provider-utils'; - -type OpenaiResponsesChunk = InferSchema; - -type ResponsesOutputTextAnnotationProviderMetadata = Extract< - OpenaiResponsesChunk, - { type: 'response.output_text.annotation.added' } ->['annotation']; - -export type ResponsesProviderMetadata = { - responseId: string | null | undefined; - logprobs?: Array; - serviceTier?: string; -}; - -export type ResponsesReasoningProviderMetadata = { - itemId: string; - reasoningEncryptedContent?: string | null; -}; - -export type OpenaiResponsesReasoningProviderMetadata = { - openai: ResponsesReasoningProviderMetadata; -}; - -export type OpenaiResponsesProviderMetadata = { - openai: ResponsesProviderMetadata; -}; - -export type ResponsesTextProviderMetadata = { - itemId: string; - phase?: 'commentary' | 'final_answer' | null; - annotations?: Array; -}; - -export type OpenaiResponsesTextProviderMetadata = { - openai: ResponsesTextProviderMetadata; -}; - -export type ResponsesSourceDocumentProviderMetadata = - | { - type: 'file_citation'; - fileId: string; - index: number; - } - | { - type: 'container_file_citation'; - fileId: string; - containerId: string; - } - | { - type: 'file_path'; - fileId: string; - index: number; - }; - -export type OpenaiResponsesSourceDocumentProviderMetadata = { - openai: ResponsesSourceDocumentProviderMetadata; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/speech/openai-speech-api.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/speech/openai-speech-api.ts deleted file mode 100644 index 6dd14415f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/speech/openai-speech-api.ts +++ /dev/null @@ -1,38 +0,0 @@ -export type OpenAISpeechAPITypes = { - /** - * The voice to use when generating the audio. - * Supported voices are alloy, ash, ballad, coral, echo, fable, onyx, nova, sage, shimmer, and verse. - * @default 'alloy' - */ - voice?: - | 'alloy' - | 'ash' - | 'ballad' - | 'coral' - | 'echo' - | 'fable' - | 'onyx' - | 'nova' - | 'sage' - | 'shimmer' - | 'verse'; - - /** - * The speed of the generated audio. - * Select a value from 0.25 to 4.0. - * @default 1.0 - */ - speed?: number; - - /** - * The format of the generated audio. - * @default 'mp3' - */ - response_format?: 'mp3' | 'opus' | 'aac' | 'flac' | 'wav' | 'pcm'; - - /** - * Instructions for the speech generation e.g. "Speak in a slow and steady tone". - * Does not work with tts-1 or tts-1-hd. - */ - instructions?: string; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/speech/openai-speech-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/speech/openai-speech-model.ts deleted file mode 100644 index 05a2dea35..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/speech/openai-speech-model.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { SpeechModelV3, SharedV3Warning } from '@ai-sdk/provider'; -import { - combineHeaders, - createBinaryResponseHandler, - parseProviderOptions, - postJsonToApi, -} from '@ai-sdk/provider-utils'; -import { OpenAIConfig } from '../openai-config'; -import { openaiFailedResponseHandler } from '../openai-error'; -import { OpenAISpeechAPITypes } from './openai-speech-api'; -import { - openaiSpeechModelOptionsSchema, - OpenAISpeechModelId, -} from './openai-speech-options'; - -interface OpenAISpeechModelConfig extends OpenAIConfig { - _internal?: { - currentDate?: () => Date; - }; -} - -export class OpenAISpeechModel implements SpeechModelV3 { - readonly specificationVersion = 'v3'; - - get provider(): string { - return this.config.provider; - } - - constructor( - readonly modelId: OpenAISpeechModelId, - private readonly config: OpenAISpeechModelConfig, - ) {} - - private async getArgs({ - text, - voice = 'alloy', - outputFormat = 'mp3', - speed, - instructions, - language, - providerOptions, - }: Parameters[0]) { - const warnings: SharedV3Warning[] = []; - - // Parse provider options - const openAIOptions = await parseProviderOptions({ - provider: 'openai', - providerOptions, - schema: openaiSpeechModelOptionsSchema, - }); - - // Create request body - const requestBody: Record = { - model: this.modelId, - input: text, - voice, - response_format: 'mp3', - speed, - instructions, - }; - - if (outputFormat) { - if (['mp3', 'opus', 'aac', 'flac', 'wav', 'pcm'].includes(outputFormat)) { - requestBody.response_format = outputFormat; - } else { - warnings.push({ - type: 'unsupported', - feature: 'outputFormat', - details: `Unsupported output format: ${outputFormat}. Using mp3 instead.`, - }); - } - } - - // Add provider-specific options - if (openAIOptions) { - const speechModelOptions: OpenAISpeechAPITypes = {}; - - for (const key in speechModelOptions) { - const value = speechModelOptions[key as keyof OpenAISpeechAPITypes]; - if (value !== undefined) { - requestBody[key] = value; - } - } - } - - if (language) { - warnings.push({ - type: 'unsupported', - feature: 'language', - details: `OpenAI speech models do not support language selection. Language parameter "${language}" was ignored.`, - }); - } - - return { - requestBody, - warnings, - }; - } - - async doGenerate( - options: Parameters[0], - ): Promise>> { - const currentDate = this.config._internal?.currentDate?.() ?? new Date(); - const { requestBody, warnings } = await this.getArgs(options); - - const { - value: audio, - responseHeaders, - rawValue: rawResponse, - } = await postJsonToApi({ - url: this.config.url({ - path: '/audio/speech', - modelId: this.modelId, - }), - headers: combineHeaders(this.config.headers(), options.headers), - body: requestBody, - failedResponseHandler: openaiFailedResponseHandler, - successfulResponseHandler: createBinaryResponseHandler(), - abortSignal: options.abortSignal, - fetch: this.config.fetch, - }); - - return { - audio, - warnings, - request: { - body: JSON.stringify(requestBody), - }, - response: { - timestamp: currentDate, - modelId: this.modelId, - headers: responseHeaders, - body: rawResponse, - }, - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/speech/openai-speech-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/speech/openai-speech-options.ts deleted file mode 100644 index f2442c010..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/speech/openai-speech-options.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export type OpenAISpeechModelId = - | 'tts-1' - | 'tts-1-1106' - | 'tts-1-hd' - | 'tts-1-hd-1106' - | 'gpt-4o-mini-tts' - | 'gpt-4o-mini-tts-2025-03-20' - | 'gpt-4o-mini-tts-2025-12-15' - | (string & {}); - -// https://platform.openai.com/docs/api-reference/audio/createSpeech -export const openaiSpeechModelOptionsSchema = lazySchema(() => - zodSchema( - z.object({ - instructions: z.string().nullish(), - speed: z.number().min(0.25).max(4.0).default(1.0).nullish(), - }), - ), -); - -export type OpenAISpeechModelOptions = InferSchema< - typeof openaiSpeechModelOptionsSchema ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/apply-patch.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/apply-patch.ts deleted file mode 100644 index 50b888679..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/apply-patch.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -/** - * Schema for the apply_patch input - what the model sends. - * - * Refer the official spec here: https://platform.openai.com/docs/api-reference/responses/create#responses_create-input-input_item_list-item-apply_patch_tool_call - * - */ -export const applyPatchInputSchema = lazySchema(() => - zodSchema( - z.object({ - callId: z.string(), - operation: z.discriminatedUnion('type', [ - z.object({ - type: z.literal('create_file'), - path: z.string(), - diff: z.string(), - }), - z.object({ - type: z.literal('delete_file'), - path: z.string(), - }), - z.object({ - type: z.literal('update_file'), - path: z.string(), - diff: z.string(), - }), - ]), - }), - ), -); - -/** - * Schema for the apply_patch output - what we send back. - */ -export const applyPatchOutputSchema = lazySchema(() => - zodSchema( - z.object({ - status: z.enum(['completed', 'failed']), - output: z.string().optional(), - }), - ), -); - -/** - * Schema for tool arguments (configuration options). - * The apply_patch tool doesn't require any configuration options. - */ -export const applyPatchArgsSchema = lazySchema(() => zodSchema(z.object({}))); - -/** - * Type definitions for the apply_patch operations. - */ -export type ApplyPatchOperation = - | { - type: 'create_file'; - /** - * Path of the file to create relative to the workspace root. - */ - path: string; - /** - * Unified diff content to apply when creating the file. - */ - diff: string; - } - | { - type: 'delete_file'; - /** - * Path of the file to delete relative to the workspace root. - */ - path: string; - } - | { - type: 'update_file'; - /** - * Path of the file to update relative to the workspace root. - */ - path: string; - /** - * Unified diff content to apply to the existing file. - */ - diff: string; - }; - -/** - * The apply_patch tool lets GPT-5.1 create, update, and delete files in your - * codebase using structured diffs. Instead of just suggesting edits, the model - * emits patch operations that your application applies and then reports back on, - * enabling iterative, multi-step code editing workflows. - * - * The tool factory creates a provider-defined tool that: - * - Receives patch operations from the model (create_file, update_file, delete_file) - * - Returns the status of applying those patches (completed or failed) - * - */ -export const applyPatchToolFactory = createProviderToolFactoryWithOutputSchema< - { - /** - * The unique ID of the apply patch tool call generated by the model. - */ - callId: string; - - /** - * The specific create, delete, or update instruction for the apply_patch tool call. - */ - operation: ApplyPatchOperation; - }, - { - /** - * The status of the apply patch tool call output. - * - 'completed': The patch was applied successfully. - * - 'failed': The patch failed to apply. - */ - status: 'completed' | 'failed'; - - /** - * Optional human-readable log text from the apply patch tool - * (e.g., patch results or errors). - */ - output?: string; - }, - // No configuration options for apply_patch - {} ->({ - id: 'openai.apply_patch', - inputSchema: applyPatchInputSchema, - outputSchema: applyPatchOutputSchema, -}); - -/** - * The apply_patch tool lets GPT-5.1 create, update, and delete files in your - * codebase using structured diffs. Instead of just suggesting edits, the model - * emits patch operations that your application applies and then reports back on, - * enabling iterative, multi-step code editing workflows. - */ -export const applyPatch = applyPatchToolFactory; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/code-interpreter.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/code-interpreter.ts deleted file mode 100644 index d921444de..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/code-interpreter.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const codeInterpreterInputSchema = lazySchema(() => - zodSchema( - z.object({ - code: z.string().nullish(), - containerId: z.string(), - }), - ), -); - -export const codeInterpreterOutputSchema = lazySchema(() => - zodSchema( - z.object({ - outputs: z - .array( - z.discriminatedUnion('type', [ - z.object({ type: z.literal('logs'), logs: z.string() }), - z.object({ type: z.literal('image'), url: z.string() }), - ]), - ) - .nullish(), - }), - ), -); - -export const codeInterpreterArgsSchema = lazySchema(() => - zodSchema( - z.object({ - container: z - .union([ - z.string(), - z.object({ - fileIds: z.array(z.string()).optional(), - }), - ]) - .optional(), - }), - ), -); - -type CodeInterpreterArgs = { - /** - * The code interpreter container. - * Can be a container ID - * or an object that specifies uploaded file IDs to make available to your code. - */ - container?: string | { fileIds?: string[] }; -}; - -export const codeInterpreterToolFactory = - createProviderToolFactoryWithOutputSchema< - { - /** - * The code to run, or null if not available. - */ - code?: string | null; - - /** - * The ID of the container used to run the code. - */ - containerId: string; - }, - { - /** - * The outputs generated by the code interpreter, such as logs or images. - * Can be null if no outputs are available. - */ - outputs?: Array< - | { - type: 'logs'; - - /** - * The logs output from the code interpreter. - */ - logs: string; - } - | { - type: 'image'; - - /** - * The URL of the image output from the code interpreter. - */ - url: string; - } - > | null; - }, - CodeInterpreterArgs - >({ - id: 'openai.code_interpreter', - inputSchema: codeInterpreterInputSchema, - outputSchema: codeInterpreterOutputSchema, - }); - -export const codeInterpreter = ( - args: CodeInterpreterArgs = {}, // default -) => { - return codeInterpreterToolFactory(args); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/custom.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/custom.ts deleted file mode 100644 index 91c223852..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/custom.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { - createProviderToolFactory, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const customArgsSchema = lazySchema(() => - zodSchema( - z.object({ - name: z.string(), - description: z.string().optional(), - format: z - .union([ - z.object({ - type: z.literal('grammar'), - syntax: z.enum(['regex', 'lark']), - definition: z.string(), - }), - z.object({ - type: z.literal('text'), - }), - ]) - .optional(), - }), - ), -); - -const customInputSchema = lazySchema(() => zodSchema(z.string())); - -export const customToolFactory = createProviderToolFactory< - string, - { - /** - * The name of the custom tool, used to identify it in the API. - */ - name: string; - - /** - * An optional description of what the tool does. - */ - description?: string; - - /** - * The output format specification for the tool. - * Omit for unconstrained text output. - */ - format?: - | { - type: 'grammar'; - syntax: 'regex' | 'lark'; - definition: string; - } - | { - type: 'text'; - }; - } ->({ - id: 'openai.custom', - inputSchema: customInputSchema, -}); - -export const customTool = (args: Parameters[0]) => - customToolFactory(args); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/file-search.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/file-search.ts deleted file mode 100644 index a82a11e12..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/file-search.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import { - OpenAIResponsesFileSearchToolComparisonFilter, - OpenAIResponsesFileSearchToolCompoundFilter, -} from '../responses/openai-responses-api'; - -const comparisonFilterSchema = z.object({ - key: z.string(), - type: z.enum(['eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'in', 'nin']), - value: z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]), -}); - -const compoundFilterSchema: z.ZodType = z.object({ - type: z.enum(['and', 'or']), - filters: z.array( - z.union([comparisonFilterSchema, z.lazy(() => compoundFilterSchema)]), - ), -}); - -export const fileSearchArgsSchema = lazySchema(() => - zodSchema( - z.object({ - vectorStoreIds: z.array(z.string()), - maxNumResults: z.number().optional(), - ranking: z - .object({ - ranker: z.string().optional(), - scoreThreshold: z.number().optional(), - }) - .optional(), - filters: z - .union([comparisonFilterSchema, compoundFilterSchema]) - .optional(), - }), - ), -); - -export const fileSearchOutputSchema = lazySchema(() => - zodSchema( - z.object({ - queries: z.array(z.string()), - results: z - .array( - z.object({ - attributes: z.record(z.string(), z.unknown()), - fileId: z.string(), - filename: z.string(), - score: z.number(), - text: z.string(), - }), - ) - .nullable(), - }), - ), -); - -export const fileSearch = createProviderToolFactoryWithOutputSchema< - {}, - { - /** - * The search query to execute. - */ - queries: string[]; - - /** - * The results of the file search tool call. - */ - results: - | null - | { - /** - * Set of 16 key-value pairs that can be attached to an object. - * This can be useful for storing additional information about the object - * in a structured format, and querying for objects via API or the dashboard. - * Keys are strings with a maximum length of 64 characters. - * Values are strings with a maximum length of 512 characters, booleans, or numbers. - */ - attributes: Record; - - /** - * The unique ID of the file. - */ - fileId: string; - - /** - * The name of the file. - */ - filename: string; - - /** - * The relevance score of the file - a value between 0 and 1. - */ - score: number; - - /** - * The text that was retrieved from the file. - */ - text: string; - }[]; - }, - { - /** - * List of vector store IDs to search through. - */ - vectorStoreIds: string[]; - - /** - * Maximum number of search results to return. Defaults to 10. - */ - maxNumResults?: number; - - /** - * Ranking options for the search. - */ - ranking?: { - /** - * The ranker to use for the file search. - */ - ranker?: string; - - /** - * The score threshold for the file search, a number between 0 and 1. - * Numbers closer to 1 will attempt to return only the most relevant results, - * but may return fewer results. - */ - scoreThreshold?: number; - }; - - /** - * A filter to apply. - */ - filters?: - | OpenAIResponsesFileSearchToolComparisonFilter - | OpenAIResponsesFileSearchToolCompoundFilter; - } ->({ - id: 'openai.file_search', - inputSchema: z.object({}), - outputSchema: fileSearchOutputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/image-generation.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/image-generation.ts deleted file mode 100644 index b7d2eb051..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/image-generation.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const imageGenerationArgsSchema = lazySchema(() => - zodSchema( - z - .object({ - background: z.enum(['auto', 'opaque', 'transparent']).optional(), - inputFidelity: z.enum(['low', 'high']).optional(), - inputImageMask: z - .object({ - fileId: z.string().optional(), - imageUrl: z.string().optional(), - }) - .optional(), - model: z.string().optional(), - moderation: z.enum(['auto']).optional(), - outputCompression: z.number().int().min(0).max(100).optional(), - outputFormat: z.enum(['png', 'jpeg', 'webp']).optional(), - partialImages: z.number().int().min(0).max(3).optional(), - quality: z.enum(['auto', 'low', 'medium', 'high']).optional(), - size: z - .enum(['1024x1024', '1024x1536', '1536x1024', 'auto']) - .optional(), - }) - .strict(), - ), -); - -const imageGenerationInputSchema = lazySchema(() => zodSchema(z.object({}))); - -export const imageGenerationOutputSchema = lazySchema(() => - zodSchema(z.object({ result: z.string() })), -); - -type ImageGenerationArgs = { - /** - * Background type for the generated image. Default is 'auto'. - */ - background?: 'auto' | 'opaque' | 'transparent'; - - /** - * Input fidelity for the generated image. Default is 'low'. - */ - inputFidelity?: 'low' | 'high'; - - /** - * Optional mask for inpainting. - * Contains image_url (string, optional) and file_id (string, optional). - */ - inputImageMask?: { - /** - * File ID for the mask image. - */ - fileId?: string; - - /** - * Base64-encoded mask image. - */ - imageUrl?: string; - }; - - /** - * The image generation model to use. Default: gpt-image-1. - */ - model?: string; - - /** - * Moderation level for the generated image. Default: auto. - */ - moderation?: 'auto'; - - /** - * Compression level for the output image. Default: 100. - */ - outputCompression?: number; - - /** - * The output format of the generated image. One of png, webp, or jpeg. - * Default: png - */ - outputFormat?: 'png' | 'jpeg' | 'webp'; - - /** - * Number of partial images to generate in streaming mode, from 0 (default value) to 3. - */ - partialImages?: number; - - /** - * The quality of the generated image. - * One of low, medium, high, or auto. Default: auto. - */ - quality?: 'auto' | 'low' | 'medium' | 'high'; - - /** - * The size of the generated image. - * One of 1024x1024, 1024x1536, 1536x1024, or auto. - * Default: auto. - */ - size?: 'auto' | '1024x1024' | '1024x1536' | '1536x1024'; -}; - -const imageGenerationToolFactory = createProviderToolFactoryWithOutputSchema< - {}, - { - /** - * The generated image encoded in base64. - */ - result: string; - }, - ImageGenerationArgs ->({ - id: 'openai.image_generation', - inputSchema: imageGenerationInputSchema, - outputSchema: imageGenerationOutputSchema, -}); - -export const imageGeneration = ( - args: ImageGenerationArgs = {}, // default -) => { - return imageGenerationToolFactory(args); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/local-shell.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/local-shell.ts deleted file mode 100644 index 96bdb5db2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/local-shell.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const localShellInputSchema = lazySchema(() => - zodSchema( - z.object({ - action: z.object({ - type: z.literal('exec'), - command: z.array(z.string()), - timeoutMs: z.number().optional(), - user: z.string().optional(), - workingDirectory: z.string().optional(), - env: z.record(z.string(), z.string()).optional(), - }), - }), - ), -); - -export const localShellOutputSchema = lazySchema(() => - zodSchema(z.object({ output: z.string() })), -); - -export const localShell = createProviderToolFactoryWithOutputSchema< - { - /** - * Execute a shell command on the server. - */ - action: { - type: 'exec'; - - /** - * The command to run. - */ - command: string[]; - - /** - * Optional timeout in milliseconds for the command. - */ - timeoutMs?: number; - - /** - * Optional user to run the command as. - */ - user?: string; - - /** - * Optional working directory to run the command in. - */ - workingDirectory?: string; - - /** - * Environment variables to set for the command. - */ - env?: Record; - }; - }, - { - /** - * The output of local shell tool call. - */ - output: string; - }, - {} ->({ - id: 'openai.local_shell', - inputSchema: localShellInputSchema, - outputSchema: localShellOutputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/mcp.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/mcp.ts deleted file mode 100644 index 57db1e99a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/mcp.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { JSONValue } from '@ai-sdk/provider'; -import { z } from 'zod/v4'; - -const jsonValueSchema: z.ZodType = z.lazy(() => - z.union([ - z.string(), - z.number(), - z.boolean(), - z.null(), - z.array(jsonValueSchema), - z.record(z.string(), jsonValueSchema), - ]), -); - -export const mcpArgsSchema = lazySchema(() => - zodSchema( - z - .object({ - serverLabel: z.string(), - allowedTools: z - .union([ - z.array(z.string()), - z.object({ - readOnly: z.boolean().optional(), - toolNames: z.array(z.string()).optional(), - }), - ]) - .optional(), - authorization: z.string().optional(), - connectorId: z.string().optional(), - headers: z.record(z.string(), z.string()).optional(), - - requireApproval: z - .union([ - z.enum(['always', 'never']), - z.object({ - never: z - .object({ - toolNames: z.array(z.string()).optional(), - }) - .optional(), - }), - ]) - .optional(), - serverDescription: z.string().optional(), - serverUrl: z.string().optional(), - }) - .refine( - v => v.serverUrl != null || v.connectorId != null, - 'One of serverUrl or connectorId must be provided.', - ), - ), -); - -const mcpInputSchema = lazySchema(() => zodSchema(z.object({}))); - -export const mcpOutputSchema = lazySchema(() => - zodSchema( - z.object({ - type: z.literal('call'), - serverLabel: z.string(), - name: z.string(), - arguments: z.string(), - output: z.string().nullish(), - error: z.union([z.string(), jsonValueSchema]).optional(), - }), - ), -); - -type McpArgs = { - /** A label for this MCP server, used to identify it in tool calls. */ - serverLabel: string; - /** List of allowed tool names or a filter object. */ - allowedTools?: - | string[] - | { - readOnly?: boolean; - toolNames?: string[]; - }; - /** OAuth access token usable with the remote MCP server or connector. */ - authorization?: string; - /** Identifier for a service connector. */ - connectorId?: string; - /** Optional HTTP headers to send to the MCP server. */ - headers?: Record; - /** - * Which tools require approval before execution. - */ - requireApproval?: - | 'always' - | 'never' - | { - never?: { - toolNames?: string[]; - }; - }; - /** Optional description of the MCP server. */ - serverDescription?: string; - /** URL for the MCP server. One of serverUrl or connectorId must be provided. */ - serverUrl?: string; -}; - -export const mcpToolFactory = createProviderToolFactoryWithOutputSchema< - {}, - { - type: 'call'; - serverLabel: string; - name: string; - arguments: string; - output?: string | null; - error?: JSONValue; - }, - McpArgs ->({ - id: 'openai.mcp', - inputSchema: mcpInputSchema, - outputSchema: mcpOutputSchema, -}); - -export const mcp = (args: McpArgs) => mcpToolFactory(args); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/shell.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/shell.ts deleted file mode 100644 index 439b78ebf..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/shell.ts +++ /dev/null @@ -1,203 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const shellInputSchema = lazySchema(() => - zodSchema( - z.object({ - action: z.object({ - commands: z.array(z.string()), - timeoutMs: z.number().optional(), - maxOutputLength: z.number().optional(), - }), - }), - ), -); - -export const shellOutputSchema = lazySchema(() => - zodSchema( - z.object({ - output: z.array( - z.object({ - stdout: z.string(), - stderr: z.string(), - outcome: z.discriminatedUnion('type', [ - z.object({ type: z.literal('timeout') }), - z.object({ type: z.literal('exit'), exitCode: z.number() }), - ]), - }), - ), - }), - ), -); - -const shellSkillsSchema = z - .array( - z.discriminatedUnion('type', [ - z.object({ - type: z.literal('skillReference'), - skillId: z.string(), - version: z.string().optional(), - }), - z.object({ - type: z.literal('inline'), - name: z.string(), - description: z.string(), - source: z.object({ - type: z.literal('base64'), - mediaType: z.literal('application/zip'), - data: z.string(), - }), - }), - ]), - ) - .optional(); - -export const shellArgsSchema = lazySchema(() => - zodSchema( - z.object({ - environment: z - .union([ - z.object({ - type: z.literal('containerAuto'), - fileIds: z.array(z.string()).optional(), - memoryLimit: z.enum(['1g', '4g', '16g', '64g']).optional(), - networkPolicy: z - .discriminatedUnion('type', [ - z.object({ type: z.literal('disabled') }), - z.object({ - type: z.literal('allowlist'), - allowedDomains: z.array(z.string()), - domainSecrets: z - .array( - z.object({ - domain: z.string(), - name: z.string(), - value: z.string(), - }), - ) - .optional(), - }), - ]) - .optional(), - skills: shellSkillsSchema, - }), - z.object({ - type: z.literal('containerReference'), - containerId: z.string(), - }), - z.object({ - type: z.literal('local').optional(), - skills: z - .array( - z.object({ - name: z.string(), - description: z.string(), - path: z.string(), - }), - ) - .optional(), - }), - ]) - .optional(), - }), - ), -); - -type ShellArgs = { - environment?: - | { - type: 'containerAuto'; - fileIds?: string[]; - memoryLimit?: '1g' | '4g' | '16g' | '64g'; - networkPolicy?: - | { type: 'disabled' } - | { - type: 'allowlist'; - allowedDomains: string[]; - domainSecrets?: Array<{ - domain: string; - name: string; - value: string; - }>; - }; - skills?: Array< - | { type: 'skillReference'; skillId: string; version?: string } - | { - type: 'inline'; - name: string; - description: string; - source: { - type: 'base64'; - mediaType: 'application/zip'; - data: string; - }; - } - >; - } - | { - type: 'containerReference'; - containerId: string; - } - | { - type?: 'local'; - skills?: Array<{ - name: string; - description: string; - path: string; - }>; - }; -}; - -export const shell = createProviderToolFactoryWithOutputSchema< - { - /** - * Shell tool action containing commands to execute. - */ - action: { - /** - * A list of shell commands to execute. - */ - commands: string[]; - - /** - * Optional timeout in milliseconds for the commands. - */ - timeoutMs?: number; - - /** - * Optional maximum number of characters to return from each command. - */ - maxOutputLength?: number; - }; - }, - { - /** - * An array of shell call output contents. - */ - output: Array<{ - /** - * Standard output from the command. - */ - stdout: string; - - /** - * Standard error from the command. - */ - stderr: string; - - /** - * The outcome of the shell execution - either timeout or exit with code. - */ - outcome: { type: 'timeout' } | { type: 'exit'; exitCode: number }; - }>; - }, - ShellArgs ->({ - id: 'openai.shell', - inputSchema: shellInputSchema, - outputSchema: shellOutputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/tool-search.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/tool-search.ts deleted file mode 100644 index 28d69eb47..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/tool-search.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { JSONObject } from '@ai-sdk/provider'; -import { - createProviderToolFactoryWithOutputSchema, - FlexibleSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const toolSearchArgsSchema = lazySchema(() => - zodSchema( - z.object({ - execution: z.enum(['server', 'client']).optional(), - description: z.string().optional(), - parameters: z.record(z.string(), z.unknown()).optional(), - }), - ), -); - -export const toolSearchInputSchema = lazySchema(() => - zodSchema( - z.object({ - arguments: z.unknown().optional(), - call_id: z.string().nullish(), - }), - ), -); - -export const toolSearchOutputSchema: FlexibleSchema<{ - tools: Array; -}> = lazySchema(() => - zodSchema( - z.object({ - tools: z.array(z.record(z.string(), z.unknown())), - }), - ), -) as FlexibleSchema<{ tools: Array }>; - -const toolSearchToolFactory = createProviderToolFactoryWithOutputSchema< - { - /** - * The arguments from the tool_search_call. - * This is preserved for multi-turn conversation reconstruction. - */ - arguments?: unknown; - - /** - * The call ID from the tool_search_call. - * Present for client-executed tool search; null for hosted. - */ - call_id?: string | null; - }, - { - /** - * The tools that were loaded by the tool search. - * These are the deferred tools that the model requested to load. - * Each tool is represented as a JSON object with properties depending on its type. - * - * Common properties include: - * - `type`: The type of the tool (e.g., 'function', 'web_search', etc.) - * - `name`: The name of the tool (for function tools) - * - `description`: A description of the tool - * - `deferLoading`: Whether this tool was deferred (had defer_loading: true) - * - `parameters`: The JSON Schema for the function parameters (for function tools) - * - `strict`: Whether to enable strict schema adherence (for function tools) - */ - tools: Array; - }, - { - /** - * Whether the tool search is executed by the server (hosted) or client. - * - `'server'` (default): OpenAI performs the search across deferred tools. - * - `'client'`: The model emits a `tool_search_call` and your `execute` - * function performs the lookup, returning the tools to load. - */ - execution?: 'server' | 'client'; - - /** - * A description of the tool search capability. - * Only used for client-executed tool search. - */ - description?: string; - - /** - * JSON Schema for the search arguments your application expects. - * Only used for client-executed tool search. - */ - parameters?: Record; - } ->({ - id: 'openai.tool_search', - inputSchema: toolSearchInputSchema, - outputSchema: toolSearchOutputSchema, -}); - -export const toolSearch = ( - args: Parameters[0] = {}, -) => toolSearchToolFactory(args); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/web-search-preview.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/web-search-preview.ts deleted file mode 100644 index 24405147f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/web-search-preview.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const webSearchPreviewArgsSchema = lazySchema(() => - zodSchema( - z.object({ - searchContextSize: z.enum(['low', 'medium', 'high']).optional(), - userLocation: z - .object({ - type: z.literal('approximate'), - country: z.string().optional(), - city: z.string().optional(), - region: z.string().optional(), - timezone: z.string().optional(), - }) - .optional(), - }), - ), -); - -export const webSearchPreviewInputSchema = lazySchema(() => - zodSchema(z.object({})), -); - -const webSearchPreviewOutputSchema = lazySchema(() => - zodSchema( - z.object({ - action: z - .discriminatedUnion('type', [ - z.object({ - type: z.literal('search'), - query: z.string().optional(), - }), - z.object({ - type: z.literal('openPage'), - url: z.string().nullish(), - }), - z.object({ - type: z.literal('findInPage'), - url: z.string().nullish(), - pattern: z.string().nullish(), - }), - ]) - .optional(), - }), - ), -); - -export const webSearchPreview = createProviderToolFactoryWithOutputSchema< - { - // Web search preview doesn't take input parameters - it's controlled by the prompt - }, - { - /** - * An object describing the specific action taken in this web search call. - * Includes details on how the model used the web (search, open_page, find_in_page). - */ - action?: - | { - /** - * Action type "search" - Performs a web search query. - */ - type: 'search'; - - /** - * The search query. - */ - query?: string; - } - | { - /** - * Action type "openPage" - Opens a specific URL from search results. - */ - type: 'openPage'; - - /** - * The URL opened by the model. - */ - url?: string | null; - } - | { - /** - * Action type "findInPage": Searches for a pattern within a loaded page. - */ - type: 'findInPage'; - - /** - * The URL of the page searched for the pattern. - */ - url?: string | null; - - /** - * The pattern or text to search for within the page. - */ - pattern?: string | null; - }; - }, - { - /** - * Search context size to use for the web search. - * - high: Most comprehensive context, highest cost, slower response - * - medium: Balanced context, cost, and latency (default) - * - low: Least context, lowest cost, fastest response - */ - searchContextSize?: 'low' | 'medium' | 'high'; - - /** - * User location information to provide geographically relevant search results. - */ - userLocation?: { - /** - * Type of location (always 'approximate') - */ - type: 'approximate'; - /** - * Two-letter ISO country code (e.g., 'US', 'GB') - */ - country?: string; - /** - * City name (free text, e.g., 'Minneapolis') - */ - city?: string; - /** - * Region name (free text, e.g., 'Minnesota') - */ - region?: string; - /** - * IANA timezone (e.g., 'America/Chicago') - */ - timezone?: string; - }; - } ->({ - id: 'openai.web_search_preview', - inputSchema: webSearchPreviewInputSchema, - outputSchema: webSearchPreviewOutputSchema, -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/web-search.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/web-search.ts deleted file mode 100644 index 2bceb6809..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/tool/web-search.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { - createProviderToolFactoryWithOutputSchema, - lazySchema, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const webSearchArgsSchema = lazySchema(() => - zodSchema( - z.object({ - externalWebAccess: z.boolean().optional(), - filters: z - .object({ allowedDomains: z.array(z.string()).optional() }) - .optional(), - searchContextSize: z.enum(['low', 'medium', 'high']).optional(), - userLocation: z - .object({ - type: z.literal('approximate'), - country: z.string().optional(), - city: z.string().optional(), - region: z.string().optional(), - timezone: z.string().optional(), - }) - .optional(), - }), - ), -); - -const webSearchInputSchema = lazySchema(() => zodSchema(z.object({}))); - -export const webSearchOutputSchema = lazySchema(() => - zodSchema( - z.object({ - action: z - .discriminatedUnion('type', [ - z.object({ - type: z.literal('search'), - query: z.string().optional(), - }), - z.object({ - type: z.literal('openPage'), - url: z.string().nullish(), - }), - z.object({ - type: z.literal('findInPage'), - url: z.string().nullish(), - pattern: z.string().nullish(), - }), - ]) - .optional(), - sources: z - .array( - z.discriminatedUnion('type', [ - z.object({ type: z.literal('url'), url: z.string() }), - z.object({ type: z.literal('api'), name: z.string() }), - ]), - ) - .optional(), - }), - ), -); - -export const webSearchToolFactory = createProviderToolFactoryWithOutputSchema< - { - // Web search doesn't take input parameters - it's controlled by the prompt - }, - { - /** - * An object describing the specific action taken in this web search call. - * Includes details on how the model used the web (search, open_page, find_in_page). - */ - action?: - | { - /** - * Action type "search" - Performs a web search query. - */ - type: 'search'; - - /** - * The search query. - */ - query?: string; - } - | { - /** - * Action type "openPage" - Opens a specific URL from search results. - */ - type: 'openPage'; - - /** - * The URL opened by the model. - */ - url?: string | null; - } - | { - /** - * Action type "findInPage": Searches for a pattern within a loaded page. - */ - type: 'findInPage'; - - /** - * The URL of the page searched for the pattern. - */ - url?: string | null; - - /** - * The pattern or text to search for within the page. - */ - pattern?: string | null; - }; - - /** - * Optional sources cited by the model for the web search call. - */ - sources?: Array< - { type: 'url'; url: string } | { type: 'api'; name: string } - >; - }, - { - /** - * Whether to use external web access for fetching live content. - * - true: Fetch live web content (default) - * - false: Use cached/indexed results - */ - externalWebAccess?: boolean; - - /** - * Filters for the search. - */ - filters?: { - /** - * Allowed domains for the search. - * If not provided, all domains are allowed. - * Subdomains of the provided domains are allowed as well. - */ - allowedDomains?: string[]; - }; - - /** - * Search context size to use for the web search. - * - high: Most comprehensive context, highest cost, slower response - * - medium: Balanced context, cost, and latency (default) - * - low: Least context, lowest cost, fastest response - */ - searchContextSize?: 'low' | 'medium' | 'high'; - - /** - * User location information to provide geographically relevant search results. - */ - userLocation?: { - /** - * Type of location (always 'approximate') - */ - type: 'approximate'; - /** - * Two-letter ISO country code (e.g., 'US', 'GB') - */ - country?: string; - /** - * City name (free text, e.g., 'Minneapolis') - */ - city?: string; - /** - * Region name (free text, e.g., 'Minnesota') - */ - region?: string; - /** - * IANA timezone (e.g., 'America/Chicago') - */ - timezone?: string; - }; - } ->({ - id: 'openai.web_search', - inputSchema: webSearchInputSchema, - outputSchema: webSearchOutputSchema, -}); - -export const webSearch = ( - args: Parameters[0] = {}, // default -) => webSearchToolFactory(args); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/transcription/openai-transcription-api.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/transcription/openai-transcription-api.ts deleted file mode 100644 index 4753c65b6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/transcription/openai-transcription-api.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export const openaiTranscriptionResponseSchema = lazySchema(() => - zodSchema( - z.object({ - text: z.string(), - language: z.string().nullish(), - duration: z.number().nullish(), - words: z - .array( - z.object({ - word: z.string(), - start: z.number(), - end: z.number(), - }), - ) - .nullish(), - segments: z - .array( - z.object({ - id: z.number(), - seek: z.number(), - start: z.number(), - end: z.number(), - text: z.string(), - tokens: z.array(z.number()), - temperature: z.number(), - avg_logprob: z.number(), - compression_ratio: z.number(), - no_speech_prob: z.number(), - }), - ) - .nullish(), - }), - ), -); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/transcription/openai-transcription-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/transcription/openai-transcription-model.ts deleted file mode 100644 index ef5efa080..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/transcription/openai-transcription-model.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { - TranscriptionModelV3, - TranscriptionModelV3CallOptions, - SharedV3Warning, -} from '@ai-sdk/provider'; -import { - combineHeaders, - convertBase64ToUint8Array, - createJsonResponseHandler, - mediaTypeToExtension, - parseProviderOptions, - postFormDataToApi, -} from '@ai-sdk/provider-utils'; -import { OpenAIConfig } from '../openai-config'; -import { openaiFailedResponseHandler } from '../openai-error'; -import { openaiTranscriptionResponseSchema } from './openai-transcription-api'; -import { - OpenAITranscriptionModelId, - openAITranscriptionModelOptions, - OpenAITranscriptionModelOptions, -} from './openai-transcription-options'; - -export type OpenAITranscriptionCallOptions = Omit< - TranscriptionModelV3CallOptions, - 'providerOptions' -> & { - providerOptions?: { - openai?: OpenAITranscriptionModelOptions; - }; -}; - -interface OpenAITranscriptionModelConfig extends OpenAIConfig { - _internal?: { - currentDate?: () => Date; - }; -} - -// https://platform.openai.com/docs/guides/speech-to-text#supported-languages -const languageMap = { - afrikaans: 'af', - arabic: 'ar', - armenian: 'hy', - azerbaijani: 'az', - belarusian: 'be', - bosnian: 'bs', - bulgarian: 'bg', - catalan: 'ca', - chinese: 'zh', - croatian: 'hr', - czech: 'cs', - danish: 'da', - dutch: 'nl', - english: 'en', - estonian: 'et', - finnish: 'fi', - french: 'fr', - galician: 'gl', - german: 'de', - greek: 'el', - hebrew: 'he', - hindi: 'hi', - hungarian: 'hu', - icelandic: 'is', - indonesian: 'id', - italian: 'it', - japanese: 'ja', - kannada: 'kn', - kazakh: 'kk', - korean: 'ko', - latvian: 'lv', - lithuanian: 'lt', - macedonian: 'mk', - malay: 'ms', - marathi: 'mr', - maori: 'mi', - nepali: 'ne', - norwegian: 'no', - persian: 'fa', - polish: 'pl', - portuguese: 'pt', - romanian: 'ro', - russian: 'ru', - serbian: 'sr', - slovak: 'sk', - slovenian: 'sl', - spanish: 'es', - swahili: 'sw', - swedish: 'sv', - tagalog: 'tl', - tamil: 'ta', - thai: 'th', - turkish: 'tr', - ukrainian: 'uk', - urdu: 'ur', - vietnamese: 'vi', - welsh: 'cy', -}; - -export class OpenAITranscriptionModel implements TranscriptionModelV3 { - readonly specificationVersion = 'v3'; - - get provider(): string { - return this.config.provider; - } - - constructor( - readonly modelId: OpenAITranscriptionModelId, - private readonly config: OpenAITranscriptionModelConfig, - ) {} - - private async getArgs({ - audio, - mediaType, - providerOptions, - }: OpenAITranscriptionCallOptions) { - const warnings: SharedV3Warning[] = []; - - // Parse provider options - const openAIOptions = await parseProviderOptions({ - provider: 'openai', - providerOptions, - schema: openAITranscriptionModelOptions, - }); - - // Create form data with base fields - const formData = new FormData(); - const blob = - audio instanceof Uint8Array - ? new Blob([audio]) - : new Blob([convertBase64ToUint8Array(audio)]); - - formData.append('model', this.modelId); - const fileExtension = mediaTypeToExtension(mediaType); - formData.append( - 'file', - new File([blob], 'audio', { type: mediaType }), - `audio.${fileExtension}`, - ); - - // Add provider-specific options - if (openAIOptions) { - const transcriptionModelOptions = { - include: openAIOptions.include, - language: openAIOptions.language, - prompt: openAIOptions.prompt, - // https://platform.openai.com/docs/api-reference/audio/createTranscription#audio_createtranscription-response_format - // prefer verbose_json to get segments for models that support it - response_format: [ - 'gpt-4o-transcribe', - 'gpt-4o-mini-transcribe', - ].includes(this.modelId) - ? 'json' - : 'verbose_json', - temperature: openAIOptions.temperature, - timestamp_granularities: openAIOptions.timestampGranularities, - }; - - for (const [key, value] of Object.entries(transcriptionModelOptions)) { - if (value != null) { - if (Array.isArray(value)) { - for (const item of value) { - formData.append(`${key}[]`, String(item)); - } - } else { - formData.append(key, String(value)); - } - } - } - } - - return { - formData, - warnings, - }; - } - - async doGenerate( - options: OpenAITranscriptionCallOptions, - ): Promise>> { - const currentDate = this.config._internal?.currentDate?.() ?? new Date(); - const { formData, warnings } = await this.getArgs(options); - - const { - value: response, - responseHeaders, - rawValue: rawResponse, - } = await postFormDataToApi({ - url: this.config.url({ - path: '/audio/transcriptions', - modelId: this.modelId, - }), - headers: combineHeaders(this.config.headers(), options.headers), - formData, - failedResponseHandler: openaiFailedResponseHandler, - successfulResponseHandler: createJsonResponseHandler( - openaiTranscriptionResponseSchema, - ), - abortSignal: options.abortSignal, - fetch: this.config.fetch, - }); - - const language = - response.language != null && response.language in languageMap - ? languageMap[response.language as keyof typeof languageMap] - : undefined; - - return { - text: response.text, - segments: - response.segments?.map(segment => ({ - text: segment.text, - startSecond: segment.start, - endSecond: segment.end, - })) ?? - response.words?.map(word => ({ - text: word.word, - startSecond: word.start, - endSecond: word.end, - })) ?? - [], - language, - durationInSeconds: response.duration ?? undefined, - warnings, - response: { - timestamp: currentDate, - modelId: this.modelId, - headers: responseHeaders, - body: rawResponse, - }, - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/transcription/openai-transcription-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/transcription/openai-transcription-options.ts deleted file mode 100644 index b992b423d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/transcription/openai-transcription-options.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; - -export type OpenAITranscriptionModelId = - | 'whisper-1' - | 'gpt-4o-mini-transcribe' - | 'gpt-4o-mini-transcribe-2025-03-20' - | 'gpt-4o-mini-transcribe-2025-12-15' - | 'gpt-4o-transcribe' - | 'gpt-4o-transcribe-diarize' - | (string & {}); - -// https://platform.openai.com/docs/api-reference/audio/createTranscription -export const openAITranscriptionModelOptions = lazySchema(() => - zodSchema( - z.object({ - /** - * Additional information to include in the transcription response. - */ - - include: z.array(z.string()).optional(), - - /** - * The language of the input audio in ISO-639-1 format. - */ - language: z.string().optional(), - - /** - * An optional text to guide the model's style or continue a previous audio segment. - */ - prompt: z.string().optional(), - - /** - * The sampling temperature, between 0 and 1. - * @default 0 - */ - temperature: z.number().min(0).max(1).default(0).optional(), - - /** - * The timestamp granularities to populate for this transcription. - * @default ['segment'] - */ - timestampGranularities: z - .array(z.enum(['word', 'segment'])) - .default(['segment']) - .optional(), - }), - ), -); - -export type OpenAITranscriptionModelOptions = InferSchema< - typeof openAITranscriptionModelOptions ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/transcription/transcription-test.mp3 b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/transcription/transcription-test.mp3 deleted file mode 100644 index 6a4cf7b67..000000000 Binary files a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/transcription/transcription-test.mp3 and /dev/null differ diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/version.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/version.ts deleted file mode 100644 index 7a35d46f5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/openai/src/version.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Version string of this package injected at build time. -declare const __PACKAGE_VERSION__: string | undefined; -export const VERSION: string = - typeof __PACKAGE_VERSION__ !== 'undefined' - ? __PACKAGE_VERSION__ - : '0.0.0-test'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/CHANGELOG.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/CHANGELOG.md deleted file mode 100644 index 2efe6d401..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/CHANGELOG.md +++ /dev/null @@ -1,1574 +0,0 @@ -# @ai-sdk/provider-utils - -## 4.0.21 - -### Patch Changes - -- 055cd68: fix: publish v6 to latest npm dist tag - -## 4.0.20 - -### Patch Changes - -- 64ac0fd: fix(security): validate redirect targets in download functions to prevent SSRF bypass - - Both `downloadBlob` and `download` now validate the final URL after following HTTP redirects, preventing attackers from bypassing SSRF protections via open redirects to internal/private addresses. - -## 4.0.19 - -### Patch Changes - -- ad4cfc2: Add URL validation to `downloadBlob` and `download` to prevent blind SSRF attacks. Private/internal IP addresses, localhost, and non-HTTP protocols are now rejected before fetching. - -## 4.0.18 - -### Patch Changes - -- 824b295: fix(provider-utils): prevent unicode escape bypass in secureJsonParse - -## 4.0.17 - -### Patch Changes - -- 08336f1: fix(bedrock): strip file extensions from filename - -## 4.0.16 - -### Patch Changes - -- 58bc42d: feat(provider/openai): support custom tools with alias mapping - -## 4.0.15 - -### Patch Changes - -- 4024a3a: security: prevent unbounded memory growth in download functions - - The `download()` and `downloadBlob()` functions now enforce a default 2 GiB size limit when downloading from user-provided URLs. Downloads that exceed this limit are aborted with a `DownloadError` instead of consuming unbounded memory and crashing the process. The `abortSignal` parameter is now passed through to `fetch()` in all download call sites. - - Added `download` option to `transcribe()` and `experimental_generateVideo()` for providing a custom download function. Use the new `createDownload({ maxBytes })` factory to configure download size limits. - -## 4.0.14 - -### Patch Changes - -- Updated dependencies [7168375] - - @ai-sdk/provider@3.0.8 - -## 4.0.13 - -### Patch Changes - -- Updated dependencies [53f6731] - - @ai-sdk/provider@3.0.7 - -## 4.0.12 - -### Patch Changes - -- 96936e5: fix(provider-utils): export only types from standard-schema package - -## 4.0.11 - -### Patch Changes - -- 2810850: fix(ai): improve type validation error messages with field paths and entity identifiers -- Updated dependencies [2810850] - - @ai-sdk/provider@3.0.6 - -## 4.0.10 - -### Patch Changes - -- 462ad00: fix(provider-utils): recognize bun fetch errors as retryable - -## 4.0.9 - -### Patch Changes - -- 4de5a1d: chore: excluded tests from src folder in npm package -- Updated dependencies [4de5a1d] - - @ai-sdk/provider@3.0.5 - -## 4.0.8 - -### Patch Changes - -- Updated dependencies [5c090e7] - - @ai-sdk/provider@3.0.4 - -## 4.0.7 - -### Patch Changes - -- 46f46e4: fix(provider-utils): improve tool type inference when using `inputExamples` with Zod schemas that use `.optional().default()` or `.refine()`. - -## 4.0.6 - -### Patch Changes - -- 1b11dcb: chore(ai): include sources in npm package -- Updated dependencies [1b11dcb] - - @ai-sdk/provider@3.0.3 - -## 4.0.5 - -### Patch Changes - -- 34d1c8a: fix(provider-utils): add additionalProperties field for standard schema function - -## 4.0.4 - -### Patch Changes - -- Updated dependencies [d937c8f] - - @ai-sdk/provider@3.0.2 - -## 4.0.3 - -### Patch Changes - -- 0b429d4: fix(provider-utils): handle anyOf/allOf/oneOf and definitions in addAdditionalPropertiesToJsonSchema - -## 4.0.2 - -### Patch Changes - -- 863d34f: fix: trigger release to update `@latest` -- Updated dependencies [863d34f] - - @ai-sdk/provider@3.0.1 - -## 4.0.1 - -### Patch Changes - -- 29264a3: feat: add MCP tool approval - -## 4.0.0 - -### Major Changes - -- dee8b05: ai SDK 6 beta - -### Minor Changes - -- 78928cb: release: start 5.1 beta - -### Patch Changes - -- 0adc679: feat(provider): shared spec v3 -- 50b70d6: feat(anthropic): add programmatic tool calling -- dce03c4: feat: tool input examples -- 3b1d015: feat(ai): Effect schema support -- 95f65c2: chore: use import \* from zod/v4 -- 016b111: fix(provider-utils): make ReadableStream.cancel() properly finalize async iterators -- 58920e0: refactor: consolidate header normalization across packages, remove duplicates, preserve custom headers -- 954c356: feat(openai): allow custom names for provider-defined tools -- 544d4e8: chore(specification): rename v3 provider defined tool to provider tool -- 521c537: feat(ai): Tool.needsApproval can be a function -- e8109d3: feat: tool execution approval -- 03849b0: move DelayedPromise into provider utils -- e06565c: feat(provider-utils): add needsApproval support to provider-defined tools -- 32d8dbb: fix(provider-utils): compatibility with V8 readonly execution environment -- d116b4b: feat(ai): arktype support -- 293a6b7: Added a title to the tools -- 703459a: feat: tool execution approval for dynamic tools -- 83e5744: feat: support async Tool.toModelOutput -- 7e32fea: feat(ai): valibot support -- 3ed5519: chore: rename ToolCallOptions to ToolExecutionOptions -- 8dac895: feat: `LanguageModelV3` -- cbb1d35: Update for provider-util changeset after change in PR #8588 -- 9061dc0: feat: image editing -- 32223c8: feat: add toolCallId arg to toModelOutput -- c1efac4: feat: add input arg to toModelOutput -- 4616b86: chore: update zod peer depenedency version -- 4f16c37: chore(provider-utils): upgrade eventsource-parser to 3.0.6 -- 81e29ab: chore: update docs -- 6306603: chore: replace Validator with Schema -- fca786b: feat(provider-utils): add MaybePromiseLike type -- 763d04a: feat: Standard JSON Schema support -- 3794514: feat: flexible tool output content support -- e9e157f: fix: generate zod4 json schema from input schema -- 960ec8f: chore: change argument of toModelOutput to parameter object -- 1bd7d32: feat: tool-specific strict mode -- f0b2157: fix: revert zod import change -- 95f65c2: chore: load zod schemas lazily -- Updated dependencies - - @ai-sdk/provider@3.0.0 - -## 4.0.0-beta.59 - -### Patch Changes - -- Updated dependencies [475189e] - - @ai-sdk/provider@3.0.0-beta.32 - -## 4.0.0-beta.58 - -### Patch Changes - -- Updated dependencies [2625a04] - - @ai-sdk/provider@3.0.0-beta.31 - -## 4.0.0-beta.57 - -### Patch Changes - -- Updated dependencies [cbf52cd] - - @ai-sdk/provider@3.0.0-beta.30 - -## 4.0.0-beta.56 - -### Patch Changes - -- Updated dependencies [9549c9e] - - @ai-sdk/provider@3.0.0-beta.29 - -## 4.0.0-beta.55 - -### Patch Changes - -- 50b70d6: feat(anthropic): add programmatic tool calling - -## 4.0.0-beta.54 - -### Patch Changes - -- 9061dc0: feat: image editing -- Updated dependencies [9061dc0] - - @ai-sdk/provider@3.0.0-beta.28 - -## 4.0.0-beta.53 - -### Patch Changes - -- Updated dependencies [366f50b] - - @ai-sdk/provider@3.0.0-beta.27 - -## 4.0.0-beta.52 - -### Patch Changes - -- 763d04a: feat: Standard JSON Schema support - -## 4.0.0-beta.51 - -### Patch Changes - -- c1efac4: feat: add input arg to toModelOutput - -## 4.0.0-beta.50 - -### Patch Changes - -- 32223c8: feat: add toolCallId arg to toModelOutput - -## 4.0.0-beta.49 - -### Patch Changes - -- 83e5744: feat: support async Tool.toModelOutput - -## 4.0.0-beta.48 - -### Patch Changes - -- 960ec8f: chore: change argument of toModelOutput to parameter object - -## 4.0.0-beta.47 - -### Patch Changes - -- e9e157f: fix: generate zod4 json schema from input schema - -## 4.0.0-beta.46 - -### Patch Changes - -- 81e29ab: chore: update docs - -## 4.0.0-beta.45 - -### Patch Changes - -- Updated dependencies [3bd2689] - - @ai-sdk/provider@3.0.0-beta.26 - -## 4.0.0-beta.44 - -### Patch Changes - -- Updated dependencies [53f3368] - - @ai-sdk/provider@3.0.0-beta.25 - -## 4.0.0-beta.43 - -### Patch Changes - -- dce03c4: feat: tool input examples -- Updated dependencies [dce03c4] - - @ai-sdk/provider@3.0.0-beta.24 - -## 4.0.0-beta.42 - -### Patch Changes - -- 3ed5519: chore: rename ToolCallOptions to ToolExecutionOptions - -## 4.0.0-beta.41 - -### Patch Changes - -- 1bd7d32: feat: tool-specific strict mode -- Updated dependencies [1bd7d32] - - @ai-sdk/provider@3.0.0-beta.23 - -## 4.0.0-beta.40 - -### Patch Changes - -- 544d4e8: chore(specification): rename v3 provider defined tool to provider tool -- Updated dependencies [544d4e8] - - @ai-sdk/provider@3.0.0-beta.22 - -## 4.0.0-beta.39 - -### Patch Changes - -- 954c356: feat(openai): allow custom names for provider-defined tools -- Updated dependencies [954c356] - - @ai-sdk/provider@3.0.0-beta.21 - -## 4.0.0-beta.38 - -### Patch Changes - -- 03849b0: move DelayedPromise into provider utils - -## 4.0.0-beta.37 - -### Patch Changes - -- Updated dependencies [457318b] - - @ai-sdk/provider@3.0.0-beta.20 - -## 4.0.0-beta.36 - -### Patch Changes - -- Updated dependencies [8d9e8ad] - - @ai-sdk/provider@3.0.0-beta.19 - -## 4.0.0-beta.35 - -### Patch Changes - -- Updated dependencies [10d819b] - - @ai-sdk/provider@3.0.0-beta.18 - -## 4.0.0-beta.34 - -### Patch Changes - -- Updated dependencies [db913bd] - - @ai-sdk/provider@3.0.0-beta.17 - -## 4.0.0-beta.33 - -### Patch Changes - -- Updated dependencies [b681d7d] - - @ai-sdk/provider@3.0.0-beta.16 - -## 4.0.0-beta.32 - -### Patch Changes - -- 32d8dbb: fix(provider-utils): compatibility with V8 readonly execution environment - -## 4.0.0-beta.31 - -### Patch Changes - -- Updated dependencies [bb36798] - - @ai-sdk/provider@3.0.0-beta.15 - -## 4.0.0-beta.30 - -### Patch Changes - -- 4f16c37: chore(provider-utils): upgrade eventsource-parser to 3.0.6 - -## 4.0.0-beta.29 - -### Patch Changes - -- Updated dependencies [af3780b] - - @ai-sdk/provider@3.0.0-beta.14 - -## 4.0.0-beta.28 - -### Patch Changes - -- 016b111: fix(provider-utils): make ReadableStream.cancel() properly finalize async iterators - -## 4.0.0-beta.27 - -### Patch Changes - -- Updated dependencies [37c58a0] - - @ai-sdk/provider@3.0.0-beta.13 - -## 4.0.0-beta.26 - -### Patch Changes - -- Updated dependencies [d1bdadb] - - @ai-sdk/provider@3.0.0-beta.12 - -## 4.0.0-beta.25 - -### Patch Changes - -- Updated dependencies [4c44a5b] - - @ai-sdk/provider@3.0.0-beta.11 - -## 4.0.0-beta.24 - -### Patch Changes - -- Updated dependencies [0c3b58b] - - @ai-sdk/provider@3.0.0-beta.10 - -## 4.0.0-beta.23 - -### Patch Changes - -- Updated dependencies [a755db5] - - @ai-sdk/provider@3.0.0-beta.9 - -## 4.0.0-beta.22 - -### Patch Changes - -- 58920e0: refactor: consolidate header normalization across packages, remove duplicates, preserve custom headers - -## 4.0.0-beta.21 - -### Patch Changes - -- 293a6b7: Added a title to the tools - -## 4.0.0-beta.20 - -### Patch Changes - -- fca786b: feat(provider-utils): add MaybePromiseLike type - -## 4.0.0-beta.19 - -### Patch Changes - -- 3794514: feat: flexible tool output content support -- Updated dependencies [3794514] - - @ai-sdk/provider@3.0.0-beta.8 - -## 4.0.0-beta.18 - -### Patch Changes - -- Updated dependencies [81d4308] - - @ai-sdk/provider@3.0.0-beta.7 - -## 4.0.0-beta.17 - -### Patch Changes - -- 703459a: feat: tool execution approval for dynamic tools - -## 4.0.0-beta.16 - -### Patch Changes - -- 6306603: chore: replace Validator with Schema - -## 4.0.0-beta.15 - -### Patch Changes - -- f0b2157: fix: revert zod import change - -## 4.0.0-beta.14 - -### Patch Changes - -- 3b1d015: feat(ai): Effect schema support - -## 4.0.0-beta.13 - -### Patch Changes - -- d116b4b: feat(ai): arktype support - -## 4.0.0-beta.12 - -### Patch Changes - -- 7e32fea: feat(ai): valibot support - -## 4.0.0-beta.11 - -### Patch Changes - -- 95f65c2: chore: use import \* from zod/v4 -- 95f65c2: chore: load zod schemas lazily - -## 4.0.0-beta.10 - -### Major Changes - -- dee8b05: ai SDK 6 beta - -### Patch Changes - -- Updated dependencies [dee8b05] - - @ai-sdk/provider@3.0.0-beta.6 - -## 3.1.0-beta.9 - -### Patch Changes - -- 521c537: feat(ai): Tool.needsApproval can be a function - -## 3.1.0-beta.8 - -### Patch Changes - -- e06565c: feat(provider-utils): add needsApproval support to provider-defined tools - -## 3.1.0-beta.7 - -### Patch Changes - -- e8109d3: feat: tool execution approval -- Updated dependencies - - @ai-sdk/provider@2.1.0-beta.5 - -## 3.1.0-beta.6 - -### Patch Changes - -- 0adc679: feat(provider): shared spec v3 -- Updated dependencies - - @ai-sdk/provider@2.1.0-beta.4 - -## 3.1.0-beta.5 - -### Patch Changes - -- 8dac895: feat: `LanguageModelV3` -- Updated dependencies [8dac895] - - @ai-sdk/provider@2.1.0-beta.3 - -## 3.1.0-beta.4 - -### Patch Changes - -- 4616b86: chore: update zod peer depenedency version - -## 3.1.0-beta.3 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.1.0-beta.2 - -## 3.1.0-beta.2 - -### Patch Changes - -- Updated dependencies [0c4822d] - - @ai-sdk/provider@2.1.0-beta.1 - -## 3.1.0-beta.1 - -### Patch Changes - -- cbb1d35: Update for provider-util changeset after change in PR #8588 - -## 3.1.0-beta.0 - -### Minor Changes - -- 78928cb: release: start 5.1 beta - -### Patch Changes - -- Updated dependencies [78928cb] - - @ai-sdk/provider@2.1.0-beta.0 - -## 3.0.9 - -### Patch Changes - -- 0294b58: feat(ai): set `ai`, `@ai-sdk/provider-utils`, and runtime in `user-agent` header - -## 3.0.8 - -### Patch Changes - -- 99964ed: fix(provider-utils): fix type inference for toModelOutput - -## 3.0.7 - -### Patch Changes - -- 886e7cd: chore(provider-utils): upgrade event-source parser to 3.0.5 - -## 3.0.6 - -### Patch Changes - -- 1b5a3d3: chore(provider-util): integrate zod-to-json-schema - -## 3.0.5 - -### Patch Changes - -- 0857788: fix(provider/groq): `experimental_transcribe` fails with valid Buffer - -## 3.0.4 - -### Patch Changes - -- 68751f9: fix(provider-utils): add inject json utility function - -## 3.0.3 - -### Patch Changes - -- 034e229: fix(provider/utils): fix FlexibleSchema type inference with zod/v3 -- f25040d: fix(provider-utils): fix tools type inference - -## 3.0.2 - -### Patch Changes - -- 38ac190: feat(ai): preliminary tool results - -## 3.0.1 - -### Patch Changes - -- 90d212f: feat (ai): add experimental tool call context - -## 3.0.0 - -### Major Changes - -- 5d142ab: remove deprecated `CoreToolCall` and `CoreToolResult` types -- d5f588f: AI SDK 5 -- e025824: refactoring (ai): restructure provider-defined tools -- 40acf9b: feat (ui): introduce ChatStore and ChatTransport -- 957b739: chore (provider-utils): rename TestServerCall.requestBody to requestBodyJson -- ea7a7c9: feat (ui): UI message metadata -- 41fa418: chore (provider-utils): return IdGenerator interface -- 71f938d: feat (ai): add output schema for tools - -### Patch Changes - -- a571d6e: chore(provider-utils): move ToolResultContent to provider-utils -- e7fcc86: feat (ai): introduce dynamic tools -- 45c1ea2: refactoring: introduce FlexibleSchema -- 060370c: feat(provider-utils): add TestServerCall#requestCredentials -- 0571b98: chore (provider-utils): update eventsource-parser to 3.0.3 -- 4fef487: feat: support for zod v4 for schema validation - - All these methods now accept both a zod v4 and zod v3 schemas for validation: - - - `generateObject()` - - `streamObject()` - - `generateText()` - - `experimental_useObject()` from `@ai-sdk/react` - - `streamUI()` from `@ai-sdk/rsc` - -- 0c0c0b3: refactor (provider-utils): move `customAlphabet()` method from `nanoid` into codebase -- 8ba77a7: chore (provider-utils): use eventsource-parser library -- a166433: feat: add transcription with experimental_transcribe -- 9f95b35: refactor (provider-utils): copy relevant code from `secure-json-parse` into codebase -- 66962ed: fix(packages): export node10 compatible types -- 05d2819: feat: allow zod 4.x as peer dependency -- ac34802: Add clear object function to StructuredObject -- 63d791d: chore (utils): remove unused test helpers -- 87b828f: fix(provider-utils): fix SSE parser bug (CRLF) -- bfdca8d: feat (ai): add InferToolInput and InferToolOutput helpers -- 0ff02bb: chore(provider-utils): move over jsonSchema -- 39a4fab: fix (provider-utils): detect failed fetch in browser environments -- 57edfcb: Adds support for async zod validators -- faf8446: chore (provider-utils): switch to standard-schema -- d1a034f: feature: using Zod 4 for internal stuff -- 88a8ee5: fix (ai): support abort during retry waits -- 205077b: fix: improve Zod compatibility -- 28a5ed5: refactoring: move tools helper into provider-utils -- dd5fd43: feat (ai): support dynamic tools in Chat onToolCall -- 383cbfa: feat (ai): add isAborted to onFinish callback for ui message streams -- Updated dependencies - - @ai-sdk/provider@2.0.0 - -## 3.0.0-beta.10 - -### Patch Changes - -- 88a8ee5: fix (ai): support abort during retry waits - -## 3.0.0-beta.9 - -### Patch Changes - -- Updated dependencies [27deb4d] - - @ai-sdk/provider@2.0.0-beta.2 - -## 3.0.0-beta.8 - -### Patch Changes - -- dd5fd43: feat (ai): support dynamic tools in Chat onToolCall - -## 3.0.0-beta.7 - -### Patch Changes - -- e7fcc86: feat (ai): introduce dynamic tools - -## 3.0.0-beta.6 - -### Patch Changes - -- ac34802: Add clear object function to StructuredObject - -## 3.0.0-beta.5 - -### Patch Changes - -- 57edfcb: Adds support for async zod validators -- 383cbfa: feat (ai): add isAborted to onFinish callback for ui message streams - -## 3.0.0-beta.4 - -### Patch Changes - -- 205077b: fix: improve Zod compatibility - -## 3.0.0-beta.3 - -### Patch Changes - -- 05d2819: feat: allow zod 4.x as peer dependency - -## 3.0.0-beta.2 - -### Patch Changes - -- 0571b98: chore (provider-utils): update eventsource-parser to 3.0.3 -- 39a4fab: fix (provider-utils): detect failed fetch in browser environments -- d1a034f: feature: using Zod 4 for internal stuff - -## 3.0.0-beta.1 - -### Major Changes - -- e025824: refactoring (ai): restructure provider-defined tools -- 71f938d: feat (ai): add output schema for tools - -### Patch Changes - -- 45c1ea2: refactoring: introduce FlexibleSchema -- bfdca8d: feat (ai): add InferToolInput and InferToolOutput helpers -- 28a5ed5: refactoring: move tools helper into provider-utils -- Updated dependencies - - @ai-sdk/provider@2.0.0-beta.1 - -## 3.0.0-alpha.15 - -### Patch Changes - -- 8ba77a7: chore (provider-utils): use eventsource-parser library -- Updated dependencies [48d257a] - - @ai-sdk/provider@2.0.0-alpha.15 - -## 3.0.0-alpha.14 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-alpha.14 - -## 3.0.0-alpha.13 - -### Patch Changes - -- Updated dependencies [68ecf2f] - - @ai-sdk/provider@2.0.0-alpha.13 - -## 3.0.0-alpha.12 - -### Patch Changes - -- Updated dependencies [e2aceaf] - - @ai-sdk/provider@2.0.0-alpha.12 - -## 3.0.0-alpha.11 - -### Patch Changes - -- Updated dependencies [c1e6647] - - @ai-sdk/provider@2.0.0-alpha.11 - -## 3.0.0-alpha.10 - -### Patch Changes - -- Updated dependencies [c4df419] - - @ai-sdk/provider@2.0.0-alpha.10 - -## 3.0.0-alpha.9 - -### Patch Changes - -- Updated dependencies [811dff3] - - @ai-sdk/provider@2.0.0-alpha.9 - -## 3.0.0-alpha.8 - -### Patch Changes - -- 4fef487: feat: support for zod v4 for schema validation - - All these methods now accept both a zod v4 and zod v3 schemas for validation: - - - `generateObject()` - - `streamObject()` - - `generateText()` - - `experimental_useObject()` from `@ai-sdk/react` - - `streamUI()` from `@ai-sdk/rsc` - -- Updated dependencies [9222aeb] - - @ai-sdk/provider@2.0.0-alpha.8 - -## 3.0.0-alpha.7 - -### Patch Changes - -- Updated dependencies [5c56081] - - @ai-sdk/provider@2.0.0-alpha.7 - -## 3.0.0-alpha.6 - -### Patch Changes - -- Updated dependencies [0d2c085] - - @ai-sdk/provider@2.0.0-alpha.6 - -## 3.0.0-alpha.4 - -### Patch Changes - -- Updated dependencies [dc714f3] - - @ai-sdk/provider@2.0.0-alpha.4 - -## 3.0.0-alpha.3 - -### Patch Changes - -- Updated dependencies [6b98118] - - @ai-sdk/provider@2.0.0-alpha.3 - -## 3.0.0-alpha.2 - -### Patch Changes - -- Updated dependencies [26535e0] - - @ai-sdk/provider@2.0.0-alpha.2 - -## 3.0.0-alpha.1 - -### Patch Changes - -- Updated dependencies [3f2f00c] - - @ai-sdk/provider@2.0.0-alpha.1 - -## 3.0.0-canary.19 - -### Patch Changes - -- faf8446: chore (provider-utils): switch to standard-schema - -## 3.0.0-canary.18 - -### Major Changes - -- 40acf9b: feat (ui): introduce ChatStore and ChatTransport - -## 3.0.0-canary.17 - -### Major Changes - -- ea7a7c9: feat (ui): UI message metadata - -## 3.0.0-canary.16 - -### Patch Changes - -- 87b828f: fix(provider-utils): fix SSE parser bug (CRLF) - -## 3.0.0-canary.15 - -### Major Changes - -- 41fa418: chore (provider-utils): return IdGenerator interface - -### Patch Changes - -- a571d6e: chore(provider-utils): move ToolResultContent to provider-utils -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.14 - -## 3.0.0-canary.14 - -### Major Changes - -- 957b739: chore (provider-utils): rename TestServerCall.requestBody to requestBodyJson - -### Patch Changes - -- Updated dependencies [9bd5ab5] - - @ai-sdk/provider@2.0.0-canary.13 - -## 3.0.0-canary.13 - -### Patch Changes - -- 0ff02bb: chore(provider-utils): move over jsonSchema -- Updated dependencies [7b3ae3f] - - @ai-sdk/provider@2.0.0-canary.12 - -## 3.0.0-canary.12 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.11 - -## 3.0.0-canary.11 - -### Patch Changes - -- 66962ed: fix(packages): export node10 compatible types -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.10 - -## 3.0.0-canary.10 - -### Patch Changes - -- Updated dependencies [e86be6f] - - @ai-sdk/provider@2.0.0-canary.9 - -## 3.0.0-canary.9 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.8 - -## 3.0.0-canary.8 - -### Major Changes - -- 5d142ab: remove deprecated `CoreToolCall` and `CoreToolResult` types - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.7 - -## 3.0.0-canary.7 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.6 - -## 3.0.0-canary.6 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.5 - -## 3.0.0-canary.5 - -### Patch Changes - -- Updated dependencies [6f6bb89] - - @ai-sdk/provider@2.0.0-canary.4 - -## 3.0.0-canary.4 - -### Patch Changes - -- Updated dependencies [d1a1aa1] - - @ai-sdk/provider@2.0.0-canary.3 - -## 3.0.0-canary.3 - -### Patch Changes - -- a166433: feat: add transcription with experimental_transcribe -- 9f95b35: refactor (provider-utils): copy relevant code from `secure-json-parse` into codebase -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.2 - -## 3.0.0-canary.2 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.1 - -## 3.0.0-canary.1 - -### Patch Changes - -- 060370c: feat(provider-utils): add TestServerCall#requestCredentials -- 0c0c0b3: refactor (provider-utils): move `customAlphabet()` method from `nanoid` into codebase -- 63d791d: chore (utils): remove unused test helpers - -## 3.0.0-canary.0 - -### Major Changes - -- d5f588f: AI SDK 5 - -### Patch Changes - -- Updated dependencies [d5f588f] - - @ai-sdk/provider@2.0.0-canary.0 - -## 2.2.3 - -### Patch Changes - -- 28be004: chore (provider-utils): add error method to TestStreamController - -## 2.2.2 - -### Patch Changes - -- b01120e: chore (provider-utils): update unified test server - -## 2.2.1 - -### Patch Changes - -- f10f0fa: fix (provider-utils): improve event source stream parsing performance - -## 2.2.0 - -### Minor Changes - -- 5bc638d: AI SDK 4.2 - -### Patch Changes - -- Updated dependencies [5bc638d] - - @ai-sdk/provider@1.1.0 - -## 2.1.15 - -### Patch Changes - -- d0c4659: feat (provider-utils): parseProviderOptions function - -## 2.1.14 - -### Patch Changes - -- Updated dependencies [0bd5bc6] - - @ai-sdk/provider@1.0.12 - -## 2.1.13 - -### Patch Changes - -- Updated dependencies [2e1101a] - - @ai-sdk/provider@1.0.11 - -## 2.1.12 - -### Patch Changes - -- 1531959: feat (provider-utils): add readable-stream to unified test server - -## 2.1.11 - -### Patch Changes - -- Updated dependencies [e1d3d42] - - @ai-sdk/provider@1.0.10 - -## 2.1.10 - -### Patch Changes - -- Updated dependencies [ddf9740] - - @ai-sdk/provider@1.0.9 - -## 2.1.9 - -### Patch Changes - -- Updated dependencies [2761f06] - - @ai-sdk/provider@1.0.8 - -## 2.1.8 - -### Patch Changes - -- 2e898b4: chore (ai): move mockId test helper into provider utils - -## 2.1.7 - -### Patch Changes - -- 3ff4ef8: feat (provider-utils): export removeUndefinedEntries for working with e.g. headers - -## 2.1.6 - -### Patch Changes - -- Updated dependencies [d89c3b9] - - @ai-sdk/provider@1.0.7 - -## 2.1.5 - -### Patch Changes - -- 3a602ca: chore (core): rename CoreTool to Tool - -## 2.1.4 - -### Patch Changes - -- 066206e: feat (provider-utils): move delay to provider-utils from ai - -## 2.1.3 - -### Patch Changes - -- 39e5c1f: feat (provider-utils): add getFromApi and response handlers for binary responses and status-code errors - -## 2.1.2 - -### Patch Changes - -- ed012d2: feat (provider): add metadata extraction mechanism to openai-compatible providers -- Updated dependencies [3a58a2e] - - @ai-sdk/provider@1.0.6 - -## 2.1.1 - -### Patch Changes - -- e7a9ec9: feat (provider-utils): include raw value in json parse results -- Updated dependencies [0a699f1] - - @ai-sdk/provider@1.0.5 - -## 2.1.0 - -### Minor Changes - -- 62ba5ad: release: AI SDK 4.1 - -## 2.0.8 - -### Patch Changes - -- 00114c5: feat: expose IDGenerator and createIdGenerator - -## 2.0.7 - -### Patch Changes - -- 90fb95a: chore (provider-utils): switch to unified test server -- e6dfef4: feat (provider/fireworks): Support add'l image models. -- 6636db6: feat (provider-utils): add unified test server - -## 2.0.6 - -### Patch Changes - -- 19a2ce7: feat (provider/fireworks): Add image model support. -- 6337688: feat: change image generation errors to warnings -- Updated dependencies - - @ai-sdk/provider@1.0.4 - -## 2.0.5 - -### Patch Changes - -- 5ed5e45: chore (config): Use ts-library.json tsconfig for no-UI libs. -- Updated dependencies [5ed5e45] - - @ai-sdk/provider@1.0.3 - -## 2.0.4 - -### Patch Changes - -- Updated dependencies [09a9cab] - - @ai-sdk/provider@1.0.2 - -## 2.0.3 - -### Patch Changes - -- 0984f0b: feat (provider-utils): Add resolvable type and utility routine. - -## 2.0.2 - -### Patch Changes - -- Updated dependencies [b446ae5] - - @ai-sdk/provider@1.0.1 - -## 2.0.1 - -### Patch Changes - -- c3ab5de: fix (provider-utils): downgrade nanoid and secure-json-parse (ESM compatibility) - -## 2.0.0 - -### Major Changes - -- b469a7e: chore: remove isXXXError methods -- b1da952: chore (provider-utils): remove convertStreamToArray -- 8426f55: chore (ai):increase id generator default size from 7 to 16. -- db46ce5: chore (provider-utils): remove isParseableJson export - -### Patch Changes - -- dce4158: chore (dependencies): update eventsource-parser to 3.0.0 -- dce4158: chore (dependencies): update nanoid to 5.0.8 -- Updated dependencies - - @ai-sdk/provider@1.0.0 - -## 2.0.0-canary.3 - -### Major Changes - -- 8426f55: chore (ai):increase id generator default size from 7 to 16. - -## 2.0.0-canary.2 - -### Patch Changes - -- dce4158: chore (dependencies): update eventsource-parser to 3.0.0 -- dce4158: chore (dependencies): update nanoid to 5.0.8 - -## 2.0.0-canary.1 - -### Major Changes - -- b1da952: chore (provider-utils): remove convertStreamToArray - -## 2.0.0-canary.0 - -### Major Changes - -- b469a7e: chore: remove isXXXError methods -- db46ce5: chore (provider-utils): remove isParseableJson export - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@1.0.0-canary.0 - -## 1.0.22 - -### Patch Changes - -- aa98cdb: chore: more flexible dependency versioning -- 7b937c5: feat (provider-utils): improve id generator robustness -- 811a317: feat (ai/core): multi-part tool results (incl. images) -- Updated dependencies - - @ai-sdk/provider@0.0.26 - -## 1.0.21 - -### Patch Changes - -- Updated dependencies [b9b0d7b] - - @ai-sdk/provider@0.0.25 - -## 1.0.20 - -### Patch Changes - -- Updated dependencies [d595d0d] - - @ai-sdk/provider@0.0.24 - -## 1.0.19 - -### Patch Changes - -- 273f696: fix (ai/provider-utils): expose size argument in generateId - -## 1.0.18 - -### Patch Changes - -- 03313cd: feat (ai): expose response id, response model, response timestamp in telemetry and api -- Updated dependencies - - @ai-sdk/provider@0.0.23 - -## 1.0.17 - -### Patch Changes - -- Updated dependencies [26515cb] - - @ai-sdk/provider@0.0.22 - -## 1.0.16 - -### Patch Changes - -- 09f895f: feat (ai/core): no-schema output for generateObject / streamObject - -## 1.0.15 - -### Patch Changes - -- d67fa9c: feat (provider/amazon-bedrock): add support for session tokens - -## 1.0.14 - -### Patch Changes - -- Updated dependencies [f2c025e] - - @ai-sdk/provider@0.0.21 - -## 1.0.13 - -### Patch Changes - -- Updated dependencies [6ac355e] - - @ai-sdk/provider@0.0.20 - -## 1.0.12 - -### Patch Changes - -- dd712ac: fix: use FetchFunction type to prevent self-reference - -## 1.0.11 - -### Patch Changes - -- Updated dependencies [dd4a0f5] - - @ai-sdk/provider@0.0.19 - -## 1.0.10 - -### Patch Changes - -- 4bd27a9: chore (ai/provider): refactor type validation -- 845754b: fix (ai/provider): fix atob/btoa execution on cloudflare edge workers -- Updated dependencies [4bd27a9] - - @ai-sdk/provider@0.0.18 - -## 1.0.9 - -### Patch Changes - -- Updated dependencies [029af4c] - - @ai-sdk/provider@0.0.17 - -## 1.0.8 - -### Patch Changes - -- Updated dependencies [d58517b] - - @ai-sdk/provider@0.0.16 - -## 1.0.7 - -### Patch Changes - -- Updated dependencies [96aed25] - - @ai-sdk/provider@0.0.15 - -## 1.0.6 - -### Patch Changes - -- 9614584: fix (ai/core): use Symbol.for -- 0762a22: feat (ai/core): support zod transformers in generateObject & streamObject - -## 1.0.5 - -### Patch Changes - -- a8d1c9e9: feat (ai/core): parallel image download -- Updated dependencies [a8d1c9e9] - - @ai-sdk/provider@0.0.14 - -## 1.0.4 - -### Patch Changes - -- 4f88248f: feat (core): support json schema - -## 1.0.3 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@0.0.13 - -## 1.0.2 - -### Patch Changes - -- Updated dependencies [b7290943] - - @ai-sdk/provider@0.0.12 - -## 1.0.1 - -### Patch Changes - -- d481729f: fix (ai/provider-utils): generalize to Error (DomException not always available) - -## 1.0.0 - -### Major Changes - -- 5edc6110: feat (provider-utils): change getRequestHeader() test helper to return Record (breaking change) - -### Patch Changes - -- 5edc6110: feat (provider-utils): add combineHeaders helper -- Updated dependencies [5edc6110] - - @ai-sdk/provider@0.0.11 - -## 0.0.16 - -### Patch Changes - -- 02f6a088: feat (provider-utils): add convertArrayToAsyncIterable test helper - -## 0.0.15 - -### Patch Changes - -- 85712895: feat (@ai-sdk/provider-utils): add createJsonStreamResponseHandler -- 85712895: chore (@ai-sdk/provider-utils): move test helper to provider utils - -## 0.0.14 - -### Patch Changes - -- 7910ae84: feat (providers): support custom fetch implementations - -## 0.0.13 - -### Patch Changes - -- Updated dependencies [102ca22f] - - @ai-sdk/provider@0.0.10 - -## 0.0.12 - -### Patch Changes - -- 09295e2e: feat (@ai-sdk/provider-utils): add download helper -- 043a5de2: fix (provider-utils): rename to isParsableJson -- Updated dependencies [09295e2e] - - @ai-sdk/provider@0.0.9 - -## 0.0.11 - -### Patch Changes - -- Updated dependencies [f39c0dd2] - - @ai-sdk/provider@0.0.8 - -## 0.0.10 - -### Patch Changes - -- Updated dependencies [8e780288] - - @ai-sdk/provider@0.0.7 - -## 0.0.9 - -### Patch Changes - -- 6a50ac4: feat (provider-utils): add loadSetting and convertAsyncGeneratorToReadableStream helpers -- Updated dependencies [6a50ac4] - - @ai-sdk/provider@0.0.6 - -## 0.0.8 - -### Patch Changes - -- Updated dependencies [0f6bc4e] - - @ai-sdk/provider@0.0.5 - -## 0.0.7 - -### Patch Changes - -- Updated dependencies [325ca55] - - @ai-sdk/provider@0.0.4 - -## 0.0.6 - -### Patch Changes - -- 276f22b: fix (ai/provider): improve request error handling - -## 0.0.5 - -### Patch Changes - -- Updated dependencies [41d5736] - - @ai-sdk/provider@0.0.3 - -## 0.0.4 - -### Patch Changes - -- 56ef84a: ai/core: fix abort handling in transformation stream - -## 0.0.3 - -### Patch Changes - -- 25f3350: ai/core: add support for getting raw response headers. -- Updated dependencies - - @ai-sdk/provider@0.0.2 - -## 0.0.2 - -### Patch Changes - -- eb150a6: ai/core: remove scaling of setting values (breaking change). If you were using the temperature, frequency penalty, or presence penalty settings, you need to update the providers and adjust the setting values. -- Updated dependencies [eb150a6] - - @ai-sdk/provider@0.0.1 - -## 0.0.1 - -### Patch Changes - -- 7b8791d: Rename baseUrl to baseURL. Automatically remove trailing slashes. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/README.md deleted file mode 100644 index f7ee1685f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/README.md +++ /dev/null @@ -1 +0,0 @@ -# AI SDK - Provider Implementation Utilities diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/package.json deleted file mode 100644 index a666da5df..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/package.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "@ai-sdk/provider-utils", - "version": "4.0.21", - "license": "Apache-2.0", - "sideEffects": false, - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", - "source": "./src/index.ts", - "files": [ - "dist/**/*", - "src", - "!src/**/*.test.ts", - "!src/**/*.test-d.ts", - "!src/**/__snapshots__", - "!src/**/__fixtures__", - "CHANGELOG.md", - "README.md", - "test.d.ts" - ], - "exports": { - "./package.json": "./package.json", - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" - }, - "./test": { - "types": "./dist/test/index.d.ts", - "import": "./dist/test/index.mjs", - "module": "./dist/test/index.mjs", - "require": "./dist/test/index.js" - } - }, - "dependencies": { - "@standard-schema/spec": "^1.1.0", - "eventsource-parser": "^3.0.6", - "@ai-sdk/provider": "3.0.8" - }, - "devDependencies": { - "@types/node": "20.17.24", - "msw": "2.7.0", - "tsup": "^8", - "typescript": "5.8.3", - "zod": "3.25.76", - "@vercel/ai-tsconfig": "0.0.0" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public" - }, - "homepage": "https://ai-sdk.dev/docs", - "repository": { - "type": "git", - "url": "git+https://github.com/vercel/ai.git" - }, - "bugs": { - "url": "https://github.com/vercel/ai/issues" - }, - "keywords": [ - "ai" - ], - "scripts": { - "build": "pnpm clean && tsup --tsconfig tsconfig.build.json", - "build:watch": "pnpm clean && tsup --watch", - "clean": "del-cli dist *.tsbuildinfo", - "lint": "eslint \"./**/*.ts*\"", - "type-check": "tsc --build", - "prettier-check": "prettier --check \"./**/*.ts*\"", - "test": "pnpm test:node && pnpm test:edge", - "test:update": "pnpm test:node -u", - "test:watch": "vitest --config vitest.node.config.js", - "test:edge": "vitest --config vitest.edge.config.js --run", - "test:node": "vitest --config vitest.node.config.js --run" - } -} \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/add-additional-properties-to-json-schema.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/add-additional-properties-to-json-schema.ts deleted file mode 100644 index 2c259bdad..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/add-additional-properties-to-json-schema.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { JSONSchema7, JSONSchema7Definition } from '@ai-sdk/provider'; - -/** - * Recursively adds additionalProperties: false to the JSON schema. This is necessary because some providers (e.g. OpenAI) do not support additionalProperties: true. - */ -export function addAdditionalPropertiesToJsonSchema( - jsonSchema: JSONSchema7, -): JSONSchema7 { - if ( - jsonSchema.type === 'object' || - (Array.isArray(jsonSchema.type) && jsonSchema.type.includes('object')) - ) { - jsonSchema.additionalProperties = false; - const { properties } = jsonSchema; - if (properties != null) { - for (const key of Object.keys(properties)) { - properties[key] = visit(properties[key]); - } - } - } - - if (jsonSchema.items != null) { - jsonSchema.items = Array.isArray(jsonSchema.items) - ? jsonSchema.items.map(visit) - : visit(jsonSchema.items); - } - - if (jsonSchema.anyOf != null) { - jsonSchema.anyOf = jsonSchema.anyOf.map(visit); - } - - if (jsonSchema.allOf != null) { - jsonSchema.allOf = jsonSchema.allOf.map(visit); - } - - if (jsonSchema.oneOf != null) { - jsonSchema.oneOf = jsonSchema.oneOf.map(visit); - } - - const { definitions } = jsonSchema; - if (definitions != null) { - for (const key of Object.keys(definitions)) { - definitions[key] = visit(definitions[key]); - } - } - - return jsonSchema; -} - -function visit(def: JSONSchema7Definition): JSONSchema7Definition { - if (typeof def === 'boolean') return def; - return addAdditionalPropertiesToJsonSchema(def); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/combine-headers.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/combine-headers.ts deleted file mode 100644 index 5f842268d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/combine-headers.ts +++ /dev/null @@ -1,11 +0,0 @@ -export function combineHeaders( - ...headers: Array | undefined> -): Record { - return headers.reduce( - (combinedHeaders, currentHeaders) => ({ - ...combinedHeaders, - ...(currentHeaders ?? {}), - }), - {}, - ) as Record; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/convert-async-iterator-to-readable-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/convert-async-iterator-to-readable-stream.ts deleted file mode 100644 index dd1121ca1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/convert-async-iterator-to-readable-stream.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Converts an AsyncIterator to a ReadableStream. - * - * @template T - The type of elements produced by the AsyncIterator. - * @param { } iterator - The AsyncIterator to convert. - * @returns {ReadableStream} - A ReadableStream that provides the same data as the AsyncIterator. - */ -export function convertAsyncIteratorToReadableStream( - iterator: AsyncIterator, -): ReadableStream { - let cancelled = false; - - return new ReadableStream({ - /** - * Called when the consumer wants to pull more data from the stream. - * - * @param {ReadableStreamDefaultController} controller - The controller to enqueue data into the stream. - * @returns {Promise} - */ - async pull(controller) { - if (cancelled) return; - try { - const { value, done } = await iterator.next(); - if (done) { - controller.close(); - } else { - controller.enqueue(value); - } - } catch (error) { - controller.error(error); - } - }, - /** - * Called when the consumer cancels the stream. - */ - async cancel(reason?: unknown) { - cancelled = true; - if (iterator.return) { - try { - await iterator.return(reason); - } catch { - // intentionally ignore errors during cancellation - } - } - }, - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/convert-image-model-file-to-data-uri.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/convert-image-model-file-to-data-uri.ts deleted file mode 100644 index 5115fb739..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/convert-image-model-file-to-data-uri.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ImageModelV3File } from '@ai-sdk/provider'; -import { convertUint8ArrayToBase64 } from './uint8-utils'; - -/** - * Convert an ImageModelV3File to a URL or data URI string. - * - * If the file is a URL, it returns the URL as-is. - * If the file is base64 data, it returns a data URI with the base64 data. - * If the file is a Uint8Array, it converts it to base64 and returns a data URI. - */ -export function convertImageModelFileToDataUri(file: ImageModelV3File): string { - if (file.type === 'url') return file.url; - - return `data:${file.mediaType};base64,${ - typeof file.data === 'string' - ? file.data - : convertUint8ArrayToBase64(file.data) - }`; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/convert-to-form-data.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/convert-to-form-data.ts deleted file mode 100644 index c2459ef93..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/convert-to-form-data.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Converts an input object to FormData for multipart/form-data requests. - * - * Handles the following cases: - * - `null` or `undefined` values are skipped - * - Arrays with a single element are appended as a single value - * - Arrays with multiple elements are appended with `[]` suffix (e.g., `image[]`) - * unless `useArrayBrackets` is set to `false` - * - All other values are appended directly - * - * @param input - The input object to convert. Use a generic type for type validation. - * @param options - Optional configuration object. - * @param options.useArrayBrackets - Whether to add `[]` suffix for multi-element arrays. - * Defaults to `true`. Set to `false` for APIs that expect repeated keys without brackets. - * @returns A FormData object containing the input values. - * - * @example - * ```ts - * type MyInput = { - * model: string; - * prompt: string; - * images: Blob[]; - * }; - * - * const formData = convertToFormData({ - * model: 'gpt-image-1', - * prompt: 'A cat', - * images: [blob1, blob2], - * }); - * ``` - */ -export function convertToFormData>( - input: T, - options: { useArrayBrackets?: boolean } = {}, -): FormData { - const { useArrayBrackets = true } = options; - const formData = new FormData(); - - for (const [key, value] of Object.entries(input)) { - if (value == null) { - continue; - } - - if (Array.isArray(value)) { - if (value.length === 1) { - formData.append(key, value[0] as string | Blob); - continue; - } - - const arrayKey = useArrayBrackets ? `${key}[]` : key; - for (const item of value) { - formData.append(arrayKey, item as string | Blob); - } - continue; - } - - formData.append(key, value as string | Blob); - } - - return formData; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/create-tool-name-mapping.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/create-tool-name-mapping.ts deleted file mode 100644 index 7116dd242..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/create-tool-name-mapping.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { - LanguageModelV3FunctionTool, - LanguageModelV3ProviderTool, -} from '@ai-sdk/provider'; - -/** - * Interface for mapping between custom tool names and provider tool names. - */ -export interface ToolNameMapping { - /** - * Maps a custom tool name (used by the client) to the provider's tool name. - * If the custom tool name does not have a mapping, returns the input name. - * - * @param customToolName - The custom name of the tool defined by the client. - * @returns The corresponding provider tool name, or the input name if not mapped. - */ - toProviderToolName: (customToolName: string) => string; - - /** - * Maps a provider tool name to the custom tool name used by the client. - * If the provider tool name does not have a mapping, returns the input name. - * - * @param providerToolName - The name of the tool as understood by the provider. - * @returns The corresponding custom tool name, or the input name if not mapped. - */ - toCustomToolName: (providerToolName: string) => string; -} - -/** - * @param tools - Tools that were passed to the language model. - * @param providerToolNames - Maps the provider tool ids to the provider tool names. - */ -export function createToolNameMapping({ - tools = [], - providerToolNames, - resolveProviderToolName, -}: { - /** - * Tools that were passed to the language model. - */ - tools: - | Array - | undefined; - - /** - * Maps the provider tool ids to the provider tool names. - */ - providerToolNames: Record<`${string}.${string}`, string>; - - /** - * Optional resolver for provider tool names that cannot be represented as - * static id -> name mappings (e.g. dynamic provider names). - */ - resolveProviderToolName?: ( - tool: LanguageModelV3ProviderTool, - ) => string | undefined; -}): ToolNameMapping { - const customToolNameToProviderToolName: Record = {}; - const providerToolNameToCustomToolName: Record = {}; - - for (const tool of tools) { - if (tool.type === 'provider') { - const providerToolName = - resolveProviderToolName?.(tool) ?? - (tool.id in providerToolNames ? providerToolNames[tool.id] : undefined); - - if (providerToolName == null) { - continue; - } - - customToolNameToProviderToolName[tool.name] = providerToolName; - providerToolNameToCustomToolName[providerToolName] = tool.name; - } - } - - return { - toProviderToolName: (customToolName: string) => - customToolNameToProviderToolName[customToolName] ?? customToolName, - toCustomToolName: (providerToolName: string) => - providerToolNameToCustomToolName[providerToolName] ?? providerToolName, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/delay.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/delay.ts deleted file mode 100644 index a99ea5698..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/delay.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Creates a Promise that resolves after a specified delay - * @param delayInMs - The delay duration in milliseconds. If null or undefined, resolves immediately. - * @param signal - Optional AbortSignal to cancel the delay - * @returns A Promise that resolves after the specified delay - * @throws {DOMException} When the signal is aborted - */ -export async function delay( - delayInMs?: number | null, - options?: { - abortSignal?: AbortSignal; - }, -): Promise { - if (delayInMs == null) { - return Promise.resolve(); - } - - const signal = options?.abortSignal; - - return new Promise((resolve, reject) => { - if (signal?.aborted) { - reject(createAbortError()); - return; - } - - const timeoutId = setTimeout(() => { - cleanup(); - resolve(); - }, delayInMs); - - const cleanup = () => { - clearTimeout(timeoutId); - signal?.removeEventListener('abort', onAbort); - }; - - const onAbort = () => { - cleanup(); - reject(createAbortError()); - }; - - signal?.addEventListener('abort', onAbort); - }); -} - -function createAbortError(): DOMException { - return new DOMException('Delay was aborted', 'AbortError'); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/delayed-promise.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/delayed-promise.ts deleted file mode 100644 index d25c8a2c5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/delayed-promise.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Delayed promise. It is only constructed once the value is accessed. - * This is useful to avoid unhandled promise rejections when the promise is created - * but not accessed. - */ -export class DelayedPromise { - private status: - | { type: 'pending' } - | { type: 'resolved'; value: T } - | { type: 'rejected'; error: unknown } = { type: 'pending' }; - private _promise: Promise | undefined; - private _resolve: undefined | ((value: T) => void) = undefined; - private _reject: undefined | ((error: unknown) => void) = undefined; - - get promise(): Promise { - if (this._promise) { - return this._promise; - } - - this._promise = new Promise((resolve, reject) => { - if (this.status.type === 'resolved') { - resolve(this.status.value); - } else if (this.status.type === 'rejected') { - reject(this.status.error); - } - - this._resolve = resolve; - this._reject = reject; - }); - - return this._promise; - } - - resolve(value: T): void { - this.status = { type: 'resolved', value }; - - if (this._promise) { - this._resolve?.(value); - } - } - - reject(error: unknown): void { - this.status = { type: 'rejected', error }; - - if (this._promise) { - this._reject?.(error); - } - } - - isResolved(): boolean { - return this.status.type === 'resolved'; - } - - isRejected(): boolean { - return this.status.type === 'rejected'; - } - - isPending(): boolean { - return this.status.type === 'pending'; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/download-blob.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/download-blob.ts deleted file mode 100644 index 56fdbc31f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/download-blob.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { DownloadError } from './download-error'; -import { - readResponseWithSizeLimit, - DEFAULT_MAX_DOWNLOAD_SIZE, -} from './read-response-with-size-limit'; -import { validateDownloadUrl } from './validate-download-url'; - -/** - * Download a file from a URL and return it as a Blob. - * - * @param url - The URL to download from. - * @param options - Optional settings for the download. - * @param options.maxBytes - Maximum allowed download size in bytes. Defaults to 100 MiB. - * @param options.abortSignal - An optional abort signal to cancel the download. - * @returns A Promise that resolves to the downloaded Blob. - * - * @throws DownloadError if the download fails or exceeds maxBytes. - */ -export async function downloadBlob( - url: string, - options?: { maxBytes?: number; abortSignal?: AbortSignal }, -): Promise { - validateDownloadUrl(url); - try { - const response = await fetch(url, { - signal: options?.abortSignal, - }); - - // Validate final URL after redirects to prevent SSRF via open redirect - if (response.redirected) { - validateDownloadUrl(response.url); - } - - if (!response.ok) { - throw new DownloadError({ - url, - statusCode: response.status, - statusText: response.statusText, - }); - } - - const data = await readResponseWithSizeLimit({ - response, - url, - maxBytes: options?.maxBytes ?? DEFAULT_MAX_DOWNLOAD_SIZE, - }); - - const contentType = response.headers.get('content-type') ?? undefined; - return new Blob([data], contentType ? { type: contentType } : undefined); - } catch (error) { - if (DownloadError.isInstance(error)) { - throw error; - } - - throw new DownloadError({ url, cause: error }); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/download-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/download-error.ts deleted file mode 100644 index 455e5b377..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/download-error.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; - -const name = 'AI_DownloadError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class DownloadError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly url: string; - readonly statusCode?: number; - readonly statusText?: string; - - constructor({ - url, - statusCode, - statusText, - cause, - message = cause == null - ? `Failed to download ${url}: ${statusCode} ${statusText}` - : `Failed to download ${url}: ${cause}`, - }: { - url: string; - statusCode?: number; - statusText?: string; - message?: string; - cause?: unknown; - }) { - super({ name, message, cause }); - - this.url = url; - this.statusCode = statusCode; - this.statusText = statusText; - } - - static isInstance(error: unknown): error is DownloadError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/extract-response-headers.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/extract-response-headers.ts deleted file mode 100644 index 4056ce2f5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/extract-response-headers.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Extracts the headers from a response object and returns them as a key-value object. - * - * @param response - The response object to extract headers from. - * @returns The headers as a key-value object. - */ -export function extractResponseHeaders(response: Response) { - return Object.fromEntries([...response.headers]); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/fetch-function.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/fetch-function.ts deleted file mode 100644 index f7882f903..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/fetch-function.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Fetch function type (standardizes the version of fetch used). - */ -export type FetchFunction = typeof globalThis.fetch; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/generate-id.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/generate-id.ts deleted file mode 100644 index 32a8a53be..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/generate-id.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { InvalidArgumentError } from '@ai-sdk/provider'; - -/** - * Creates an ID generator. - * The total length of the ID is the sum of the prefix, separator, and random part length. - * Not cryptographically secure. - * - * @param alphabet - The alphabet to use for the ID. Default: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'. - * @param prefix - The prefix of the ID to generate. Optional. - * @param separator - The separator between the prefix and the random part of the ID. Default: '-'. - * @param size - The size of the random part of the ID to generate. Default: 16. - */ -export const createIdGenerator = ({ - prefix, - size = 16, - alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', - separator = '-', -}: { - prefix?: string; - separator?: string; - size?: number; - alphabet?: string; -} = {}): IdGenerator => { - const generator = () => { - const alphabetLength = alphabet.length; - const chars = new Array(size); - for (let i = 0; i < size; i++) { - chars[i] = alphabet[(Math.random() * alphabetLength) | 0]; - } - return chars.join(''); - }; - - if (prefix == null) { - return generator; - } - - // check that the prefix is not part of the alphabet (otherwise prefix checking can fail randomly) - if (alphabet.includes(separator)) { - throw new InvalidArgumentError({ - argument: 'separator', - message: `The separator "${separator}" must not be part of the alphabet "${alphabet}".`, - }); - } - - return () => `${prefix}${separator}${generator()}`; -}; - -/** - * A function that generates an ID. - */ -export type IdGenerator = () => string; - -/** - * Generates a 16-character random string to use for IDs. - * Not cryptographically secure. - */ -export const generateId = createIdGenerator(); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/get-error-message.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/get-error-message.ts deleted file mode 100644 index 62c29e58a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/get-error-message.ts +++ /dev/null @@ -1,15 +0,0 @@ -export function getErrorMessage(error: unknown | undefined) { - if (error == null) { - return 'unknown error'; - } - - if (typeof error === 'string') { - return error; - } - - if (error instanceof Error) { - return error.message; - } - - return JSON.stringify(error); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/get-from-api.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/get-from-api.ts deleted file mode 100644 index 0a786dd06..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/get-from-api.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { APICallError } from '@ai-sdk/provider'; -import { extractResponseHeaders } from './extract-response-headers'; -import { FetchFunction } from './fetch-function'; -import { handleFetchError } from './handle-fetch-error'; -import { isAbortError } from './is-abort-error'; -import { ResponseHandler } from './response-handler'; -import { getRuntimeEnvironmentUserAgent } from './get-runtime-environment-user-agent'; -import { withUserAgentSuffix } from './with-user-agent-suffix'; -import { VERSION } from './version'; - -// use function to allow for mocking in tests: -const getOriginalFetch = () => globalThis.fetch; - -export const getFromApi = async ({ - url, - headers = {}, - successfulResponseHandler, - failedResponseHandler, - abortSignal, - fetch = getOriginalFetch(), -}: { - url: string; - headers?: Record; - failedResponseHandler: ResponseHandler; - successfulResponseHandler: ResponseHandler; - abortSignal?: AbortSignal; - fetch?: FetchFunction; -}) => { - try { - const response = await fetch(url, { - method: 'GET', - headers: withUserAgentSuffix( - headers, - `ai-sdk/provider-utils/${VERSION}`, - getRuntimeEnvironmentUserAgent(), - ), - signal: abortSignal, - }); - - const responseHeaders = extractResponseHeaders(response); - - if (!response.ok) { - let errorInformation: { - value: Error; - responseHeaders?: Record | undefined; - }; - - try { - errorInformation = await failedResponseHandler({ - response, - url, - requestBodyValues: {}, - }); - } catch (error) { - if (isAbortError(error) || APICallError.isInstance(error)) { - throw error; - } - - throw new APICallError({ - message: 'Failed to process error response', - cause: error, - statusCode: response.status, - url, - responseHeaders, - requestBodyValues: {}, - }); - } - - throw errorInformation.value; - } - - try { - return await successfulResponseHandler({ - response, - url, - requestBodyValues: {}, - }); - } catch (error) { - if (error instanceof Error) { - if (isAbortError(error) || APICallError.isInstance(error)) { - throw error; - } - } - - throw new APICallError({ - message: 'Failed to process successful response', - cause: error, - statusCode: response.status, - url, - responseHeaders, - requestBodyValues: {}, - }); - } - } catch (error) { - throw handleFetchError({ error, url, requestBodyValues: {} }); - } -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/get-runtime-environment-user-agent.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/get-runtime-environment-user-agent.ts deleted file mode 100644 index f553f7353..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/get-runtime-environment-user-agent.ts +++ /dev/null @@ -1,24 +0,0 @@ -export function getRuntimeEnvironmentUserAgent( - globalThisAny: any = globalThis as any, -): string { - // Browsers - if (globalThisAny.window) { - return `runtime/browser`; - } - - // Cloudflare Workers / Deno / Bun / Node.js >= 21.1 - if (globalThisAny.navigator?.userAgent) { - return `runtime/${globalThisAny.navigator.userAgent.toLowerCase()}`; - } - - // Nodes.js < 21.1 - if (globalThisAny.process?.versions?.node) { - return `runtime/node.js/${globalThisAny.process.version.substring(0)}`; - } - - if (globalThisAny.EdgeRuntime) { - return `runtime/vercel-edge`; - } - - return 'runtime/unknown'; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/handle-fetch-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/handle-fetch-error.ts deleted file mode 100644 index d9774ab6b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/handle-fetch-error.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { APICallError } from '@ai-sdk/provider'; -import { isAbortError } from './is-abort-error'; - -const FETCH_FAILED_ERROR_MESSAGES = ['fetch failed', 'failed to fetch']; - -const BUN_ERROR_CODES = [ - 'ConnectionRefused', - 'ConnectionClosed', - 'FailedToOpenSocket', - 'ECONNRESET', - 'ECONNREFUSED', - 'ETIMEDOUT', - 'EPIPE', -]; - -function isBunNetworkError(error: unknown): error is Error & { code?: string } { - if (!(error instanceof Error)) { - return false; - } - - const code = (error as any).code; - if (typeof code === 'string' && BUN_ERROR_CODES.includes(code)) { - return true; - } - - return false; -} - -export function handleFetchError({ - error, - url, - requestBodyValues, -}: { - error: unknown; - url: string; - requestBodyValues: unknown; -}) { - if (isAbortError(error)) { - return error; - } - - // unwrap original error when fetch failed (for easier debugging): - if ( - error instanceof TypeError && - FETCH_FAILED_ERROR_MESSAGES.includes(error.message.toLowerCase()) - ) { - const cause = (error as any).cause; - - if (cause != null) { - // Failed to connect to server: - return new APICallError({ - message: `Cannot connect to API: ${cause.message}`, - cause, - url, - requestBodyValues, - isRetryable: true, // retry when network error - }); - } - } - - if (isBunNetworkError(error)) { - return new APICallError({ - message: `Cannot connect to API: ${error.message}`, - cause: error, - url, - requestBodyValues, - isRetryable: true, - }); - } - - return error; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/index.ts deleted file mode 100644 index dc1d45d76..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/index.ts +++ /dev/null @@ -1,73 +0,0 @@ -export * from './combine-headers'; -export { convertAsyncIteratorToReadableStream } from './convert-async-iterator-to-readable-stream'; -export { - createToolNameMapping, - type ToolNameMapping, -} from './create-tool-name-mapping'; -export * from './delay'; -export { DelayedPromise } from './delayed-promise'; -export * from './extract-response-headers'; -export { convertImageModelFileToDataUri } from './convert-image-model-file-to-data-uri'; -export { convertToFormData } from './convert-to-form-data'; -export { downloadBlob } from './download-blob'; -export { DownloadError } from './download-error'; -export { - readResponseWithSizeLimit, - DEFAULT_MAX_DOWNLOAD_SIZE, -} from './read-response-with-size-limit'; -export * from './fetch-function'; -export { createIdGenerator, generateId, type IdGenerator } from './generate-id'; -export * from './get-error-message'; -export * from './get-from-api'; -export { getRuntimeEnvironmentUserAgent } from './get-runtime-environment-user-agent'; -export { injectJsonInstructionIntoMessages } from './inject-json-instruction'; -export * from './is-abort-error'; -export { isNonNullable } from './is-non-nullable'; -export { isUrlSupported } from './is-url-supported'; -export * from './load-api-key'; -export { loadOptionalSetting } from './load-optional-setting'; -export { loadSetting } from './load-setting'; -export { type MaybePromiseLike } from './maybe-promise-like'; -export { mediaTypeToExtension } from './media-type-to-extension'; -export { normalizeHeaders } from './normalize-headers'; -export * from './parse-json'; -export { parseJsonEventStream } from './parse-json-event-stream'; -export { parseProviderOptions } from './parse-provider-options'; -export * from './post-to-api'; -export { - createProviderToolFactory, - createProviderToolFactoryWithOutputSchema, - type ProviderToolFactory, - type ProviderToolFactoryWithOutputSchema, -} from './provider-tool-factory'; -export * from './remove-undefined-entries'; -export * from './resolve'; -export * from './response-handler'; -export { - asSchema, - jsonSchema, - lazySchema, - zodSchema, - type FlexibleSchema, - type InferSchema, - type LazySchema, - type Schema, - type ValidationResult, -} from './schema'; -export { stripFileExtension } from './strip-file-extension'; -export * from './uint8-utils'; -export { validateDownloadUrl } from './validate-download-url'; -export * from './validate-types'; -export { VERSION } from './version'; -export { withUserAgentSuffix } from './with-user-agent-suffix'; -export * from './without-trailing-slash'; - -// folder re-exports -export * from './types'; - -// external re-exports -export type * from '@standard-schema/spec'; -export { - EventSourceParserStream, - type EventSourceMessage, -} from 'eventsource-parser/stream'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/inject-json-instruction.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/inject-json-instruction.ts deleted file mode 100644 index f307b7595..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/inject-json-instruction.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { - JSONSchema7, - LanguageModelV3Message, - LanguageModelV3Prompt, -} from '@ai-sdk/provider'; - -const DEFAULT_SCHEMA_PREFIX = 'JSON schema:'; -const DEFAULT_SCHEMA_SUFFIX = - 'You MUST answer with a JSON object that matches the JSON schema above.'; -const DEFAULT_GENERIC_SUFFIX = 'You MUST answer with JSON.'; - -export function injectJsonInstruction({ - prompt, - schema, - schemaPrefix = schema != null ? DEFAULT_SCHEMA_PREFIX : undefined, - schemaSuffix = schema != null - ? DEFAULT_SCHEMA_SUFFIX - : DEFAULT_GENERIC_SUFFIX, -}: { - prompt?: string; - schema?: JSONSchema7; - schemaPrefix?: string; - schemaSuffix?: string; -}): string { - return [ - prompt != null && prompt.length > 0 ? prompt : undefined, - prompt != null && prompt.length > 0 ? '' : undefined, // add a newline if prompt is not null - schemaPrefix, - schema != null ? JSON.stringify(schema) : undefined, - schemaSuffix, - ] - .filter(line => line != null) - .join('\n'); -} - -export function injectJsonInstructionIntoMessages({ - messages, - schema, - schemaPrefix, - schemaSuffix, -}: { - messages: LanguageModelV3Prompt; - schema?: JSONSchema7; - schemaPrefix?: string; - schemaSuffix?: string; -}): LanguageModelV3Prompt { - const systemMessage: LanguageModelV3Message = - messages[0]?.role === 'system' - ? { ...messages[0] } - : { role: 'system', content: '' }; - - systemMessage.content = injectJsonInstruction({ - prompt: systemMessage.content, - schema, - schemaPrefix, - schemaSuffix, - }); - - return [ - systemMessage, - ...(messages[0]?.role === 'system' ? messages.slice(1) : messages), - ]; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/is-abort-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/is-abort-error.ts deleted file mode 100644 index 195c6e473..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/is-abort-error.ts +++ /dev/null @@ -1,8 +0,0 @@ -export function isAbortError(error: unknown): error is Error { - return ( - (error instanceof Error || error instanceof DOMException) && - (error.name === 'AbortError' || - error.name === 'ResponseAborted' || // Next.js - error.name === 'TimeoutError') - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/is-async-iterable.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/is-async-iterable.ts deleted file mode 100644 index 1bd9ce1d3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/is-async-iterable.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function isAsyncIterable(obj: any): obj is AsyncIterable { - return obj != null && typeof obj[Symbol.asyncIterator] === 'function'; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/is-non-nullable.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/is-non-nullable.ts deleted file mode 100644 index 39963ded3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/is-non-nullable.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Type guard that checks whether a value is not `null` or `undefined`. - * - * @template T - The type of the value to check. - * @param value - The value to check. - * @returns `true` if the value is neither `null` nor `undefined`, otherwise `false`. - */ -export function isNonNullable( - value: T | undefined | null, -): value is NonNullable { - return value != null; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/is-url-supported.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/is-url-supported.ts deleted file mode 100644 index 94db5e773..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/is-url-supported.ts +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Checks if the given URL is supported natively by the model. - * - * @param mediaType - The media type of the URL. Case-sensitive. - * @param url - The URL to check. - * @param supportedUrls - A record where keys are case-sensitive media types (or '*') - * and values are arrays of RegExp patterns for URLs. - * - * @returns `true` if the URL matches a pattern under the specific media type - * or the wildcard '*', `false` otherwise. - */ -export function isUrlSupported({ - mediaType, - url, - supportedUrls, -}: { - mediaType: string; - url: string; - supportedUrls: Record; -}): boolean { - // standardize media type and url to lower case - url = url.toLowerCase(); - mediaType = mediaType.toLowerCase(); - - return ( - Object.entries(supportedUrls) - // standardize supported url map into lowercase prefixes: - .map(([key, value]) => { - const mediaType = key.toLowerCase(); - return mediaType === '*' || mediaType === '*/*' - ? { mediaTypePrefix: '', regexes: value } - : { mediaTypePrefix: mediaType.replace(/\*/, ''), regexes: value }; - }) - // gather all regexp pattern from matched media type prefixes: - .filter(({ mediaTypePrefix }) => mediaType.startsWith(mediaTypePrefix)) - .flatMap(({ regexes }) => regexes) - // check if any pattern matches the url: - .some(pattern => pattern.test(url)) - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/load-api-key.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/load-api-key.ts deleted file mode 100644 index 44d9c9967..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/load-api-key.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { LoadAPIKeyError } from '@ai-sdk/provider'; - -export function loadApiKey({ - apiKey, - environmentVariableName, - apiKeyParameterName = 'apiKey', - description, -}: { - apiKey: string | undefined; - environmentVariableName: string; - apiKeyParameterName?: string; - description: string; -}): string { - if (typeof apiKey === 'string') { - return apiKey; - } - - if (apiKey != null) { - throw new LoadAPIKeyError({ - message: `${description} API key must be a string.`, - }); - } - - if (typeof process === 'undefined') { - throw new LoadAPIKeyError({ - message: `${description} API key is missing. Pass it using the '${apiKeyParameterName}' parameter. Environment variables is not supported in this environment.`, - }); - } - - apiKey = process.env[environmentVariableName]; - - if (apiKey == null) { - throw new LoadAPIKeyError({ - message: `${description} API key is missing. Pass it using the '${apiKeyParameterName}' parameter or the ${environmentVariableName} environment variable.`, - }); - } - - if (typeof apiKey !== 'string') { - throw new LoadAPIKeyError({ - message: `${description} API key must be a string. The value of the ${environmentVariableName} environment variable is not a string.`, - }); - } - - return apiKey; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/load-optional-setting.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/load-optional-setting.ts deleted file mode 100644 index bce841c02..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/load-optional-setting.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Loads an optional `string` setting from the environment or a parameter. - * - * @param settingValue - The setting value. - * @param environmentVariableName - The environment variable name. - * @returns The setting value. - */ -export function loadOptionalSetting({ - settingValue, - environmentVariableName, -}: { - settingValue: string | undefined; - environmentVariableName: string; -}): string | undefined { - if (typeof settingValue === 'string') { - return settingValue; - } - - if (settingValue != null || typeof process === 'undefined') { - return undefined; - } - - settingValue = process.env[environmentVariableName]; - - if (settingValue == null || typeof settingValue !== 'string') { - return undefined; - } - - return settingValue; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/load-setting.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/load-setting.ts deleted file mode 100644 index 2042fcb89..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/load-setting.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { LoadSettingError } from '@ai-sdk/provider'; - -/** - * Loads a `string` setting from the environment or a parameter. - * - * @param settingValue - The setting value. - * @param environmentVariableName - The environment variable name. - * @param settingName - The setting name. - * @param description - The description of the setting. - * @returns The setting value. - */ -export function loadSetting({ - settingValue, - environmentVariableName, - settingName, - description, -}: { - settingValue: string | undefined; - environmentVariableName: string; - settingName: string; - description: string; -}): string { - if (typeof settingValue === 'string') { - return settingValue; - } - - if (settingValue != null) { - throw new LoadSettingError({ - message: `${description} setting must be a string.`, - }); - } - - if (typeof process === 'undefined') { - throw new LoadSettingError({ - message: - `${description} setting is missing. ` + - `Pass it using the '${settingName}' parameter. ` + - `Environment variables is not supported in this environment.`, - }); - } - - settingValue = process.env[environmentVariableName]; - - if (settingValue == null) { - throw new LoadSettingError({ - message: - `${description} setting is missing. ` + - `Pass it using the '${settingName}' parameter ` + - `or the ${environmentVariableName} environment variable.`, - }); - } - - if (typeof settingValue !== 'string') { - throw new LoadSettingError({ - message: - `${description} setting must be a string. ` + - `The value of the ${environmentVariableName} environment variable is not a string.`, - }); - } - - return settingValue; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/maybe-promise-like.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/maybe-promise-like.ts deleted file mode 100644 index f3dc1c577..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/maybe-promise-like.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type MaybePromiseLike = - | T // Raw value - | PromiseLike; // Promise of value diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/media-type-to-extension.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/media-type-to-extension.ts deleted file mode 100644 index 40b475390..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/media-type-to-extension.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Maps a media type to its corresponding file extension. - * It was originally introduced to set a filename for audio file uploads - * in https://github.com/vercel/ai/pull/8159. - * - * @param mediaType The media type to map. - * @returns The corresponding file extension - * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types - */ -export function mediaTypeToExtension(mediaType: string) { - const [_type, subtype = ''] = mediaType.toLowerCase().split('/'); - - return ( - { - mpeg: 'mp3', - 'x-wav': 'wav', - opus: 'ogg', - mp4: 'm4a', - 'x-m4a': 'm4a', - }[subtype] ?? subtype - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/normalize-headers.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/normalize-headers.ts deleted file mode 100644 index ade0a3431..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/normalize-headers.ts +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Normalizes different header inputs into a plain record with lower-case keys. - * Entries with `undefined` or `null` values are removed. - * - * @param headers - Input headers (`Headers`, tuples array, plain record) to normalize. - * @returns A record containing the normalized header entries. - */ -export function normalizeHeaders( - headers: - | HeadersInit - | Record - | Array<[string, string | undefined]> - | undefined, -): Record { - if (headers == null) { - return {}; - } - - const normalized: Record = {}; - - if (headers instanceof Headers) { - headers.forEach((value, key) => { - normalized[key.toLowerCase()] = value; - }); - } else { - if (!Array.isArray(headers)) { - headers = Object.entries(headers); - } - - for (const [key, value] of headers) { - if (value != null) { - normalized[key.toLowerCase()] = value; - } - } - } - - return normalized; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/parse-json-event-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/parse-json-event-stream.ts deleted file mode 100644 index bd23542b9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/parse-json-event-stream.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { - EventSourceMessage, - EventSourceParserStream, -} from 'eventsource-parser/stream'; -import { ParseResult, safeParseJSON } from './parse-json'; -import { FlexibleSchema } from './schema'; - -/** - * Parses a JSON event stream into a stream of parsed JSON objects. - */ -export function parseJsonEventStream({ - stream, - schema, -}: { - stream: ReadableStream; - schema: FlexibleSchema; -}): ReadableStream> { - return stream - .pipeThrough(new TextDecoderStream()) - .pipeThrough(new EventSourceParserStream()) - .pipeThrough( - new TransformStream>({ - async transform({ data }, controller) { - // ignore the 'DONE' event that e.g. OpenAI sends: - if (data === '[DONE]') { - return; - } - - controller.enqueue(await safeParseJSON({ text: data, schema })); - }, - }), - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/parse-json.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/parse-json.ts deleted file mode 100644 index f6bcc5369..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/parse-json.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { - JSONParseError, - JSONValue, - TypeValidationError, -} from '@ai-sdk/provider'; -import { secureJsonParse } from './secure-json-parse'; -import { safeValidateTypes, validateTypes } from './validate-types'; -import { FlexibleSchema } from './schema'; - -/** - * Parses a JSON string into an unknown object. - * - * @param text - The JSON string to parse. - * @returns {JSONValue} - The parsed JSON object. - */ -export async function parseJSON(options: { - text: string; - schema?: undefined; -}): Promise; -/** - * Parses a JSON string into a strongly-typed object using the provided schema. - * - * @template T - The type of the object to parse the JSON into. - * @param {string} text - The JSON string to parse. - * @param {Validator} schema - The schema to use for parsing the JSON. - * @returns {Promise} - The parsed object. - */ -export async function parseJSON(options: { - text: string; - schema: FlexibleSchema; -}): Promise; -export async function parseJSON({ - text, - schema, -}: { - text: string; - schema?: FlexibleSchema; -}): Promise { - try { - const value = secureJsonParse(text); - - if (schema == null) { - return value; - } - - return validateTypes({ value, schema }); - } catch (error) { - if ( - JSONParseError.isInstance(error) || - TypeValidationError.isInstance(error) - ) { - throw error; - } - - throw new JSONParseError({ text, cause: error }); - } -} - -export type ParseResult = - | { success: true; value: T; rawValue: unknown } - | { - success: false; - error: JSONParseError | TypeValidationError; - rawValue: unknown; - }; - -/** - * Safely parses a JSON string and returns the result as an object of type `unknown`. - * - * @param text - The JSON string to parse. - * @returns {Promise} Either an object with `success: true` and the parsed data, or an object with `success: false` and the error that occurred. - */ -export async function safeParseJSON(options: { - text: string; - schema?: undefined; -}): Promise>; -/** - * Safely parses a JSON string into a strongly-typed object, using a provided schema to validate the object. - * - * @template T - The type of the object to parse the JSON into. - * @param {string} text - The JSON string to parse. - * @param {Validator} schema - The schema to use for parsing the JSON. - * @returns An object with either a `success` flag and the parsed and typed data, or a `success` flag and an error object. - */ -export async function safeParseJSON(options: { - text: string; - schema: FlexibleSchema; -}): Promise>; -export async function safeParseJSON({ - text, - schema, -}: { - text: string; - schema?: FlexibleSchema; -}): Promise> { - try { - const value = secureJsonParse(text); - - if (schema == null) { - return { success: true, value: value as T, rawValue: value }; - } - - return await safeValidateTypes({ value, schema }); - } catch (error) { - return { - success: false, - error: JSONParseError.isInstance(error) - ? error - : new JSONParseError({ text, cause: error }), - rawValue: undefined, - }; - } -} - -export function isParsableJson(input: string): boolean { - try { - secureJsonParse(input); - return true; - } catch { - return false; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/parse-provider-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/parse-provider-options.ts deleted file mode 100644 index aa11c5f07..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/parse-provider-options.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { InvalidArgumentError } from '@ai-sdk/provider'; -import { safeValidateTypes } from './validate-types'; -import { FlexibleSchema } from './schema'; - -export async function parseProviderOptions({ - provider, - providerOptions, - schema, -}: { - provider: string; - providerOptions: Record | undefined; - schema: FlexibleSchema; -}): Promise { - if (providerOptions?.[provider] == null) { - return undefined; - } - - const parsedProviderOptions = await safeValidateTypes({ - value: providerOptions[provider], - schema, - }); - - if (!parsedProviderOptions.success) { - throw new InvalidArgumentError({ - argument: 'providerOptions', - message: `invalid ${provider} provider options`, - cause: parsedProviderOptions.error, - }); - } - - return parsedProviderOptions.value; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/post-to-api.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/post-to-api.ts deleted file mode 100644 index 6e387dda3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/post-to-api.ts +++ /dev/null @@ -1,166 +0,0 @@ -import { APICallError } from '@ai-sdk/provider'; -import { extractResponseHeaders } from './extract-response-headers'; -import { FetchFunction } from './fetch-function'; -import { handleFetchError } from './handle-fetch-error'; -import { isAbortError } from './is-abort-error'; -import { ResponseHandler } from './response-handler'; -import { getRuntimeEnvironmentUserAgent } from './get-runtime-environment-user-agent'; -import { withUserAgentSuffix } from './with-user-agent-suffix'; -import { VERSION } from './version'; - -// use function to allow for mocking in tests: -const getOriginalFetch = () => globalThis.fetch; - -export const postJsonToApi = async ({ - url, - headers, - body, - failedResponseHandler, - successfulResponseHandler, - abortSignal, - fetch, -}: { - url: string; - headers?: Record; - body: unknown; - failedResponseHandler: ResponseHandler; - successfulResponseHandler: ResponseHandler; - abortSignal?: AbortSignal; - fetch?: FetchFunction; -}) => - postToApi({ - url, - headers: { - 'Content-Type': 'application/json', - ...headers, - }, - body: { - content: JSON.stringify(body), - values: body, - }, - failedResponseHandler, - successfulResponseHandler, - abortSignal, - fetch, - }); - -export const postFormDataToApi = async ({ - url, - headers, - formData, - failedResponseHandler, - successfulResponseHandler, - abortSignal, - fetch, -}: { - url: string; - headers?: Record; - formData: FormData; - failedResponseHandler: ResponseHandler; - successfulResponseHandler: ResponseHandler; - abortSignal?: AbortSignal; - fetch?: FetchFunction; -}) => - postToApi({ - url, - headers, - body: { - content: formData, - values: Object.fromEntries((formData as any).entries()), - }, - failedResponseHandler, - successfulResponseHandler, - abortSignal, - fetch, - }); - -export const postToApi = async ({ - url, - headers = {}, - body, - successfulResponseHandler, - failedResponseHandler, - abortSignal, - fetch = getOriginalFetch(), -}: { - url: string; - headers?: Record; - body: { - content: string | FormData | Uint8Array; - values: unknown; - }; - failedResponseHandler: ResponseHandler; - successfulResponseHandler: ResponseHandler; - abortSignal?: AbortSignal; - fetch?: FetchFunction; -}) => { - try { - const response = await fetch(url, { - method: 'POST', - headers: withUserAgentSuffix( - headers, - `ai-sdk/provider-utils/${VERSION}`, - getRuntimeEnvironmentUserAgent(), - ), - body: body.content, - signal: abortSignal, - }); - - const responseHeaders = extractResponseHeaders(response); - - if (!response.ok) { - let errorInformation: { - value: Error; - responseHeaders?: Record | undefined; - }; - - try { - errorInformation = await failedResponseHandler({ - response, - url, - requestBodyValues: body.values, - }); - } catch (error) { - if (isAbortError(error) || APICallError.isInstance(error)) { - throw error; - } - - throw new APICallError({ - message: 'Failed to process error response', - cause: error, - statusCode: response.status, - url, - responseHeaders, - requestBodyValues: body.values, - }); - } - - throw errorInformation.value; - } - - try { - return await successfulResponseHandler({ - response, - url, - requestBodyValues: body.values, - }); - } catch (error) { - if (error instanceof Error) { - if (isAbortError(error) || APICallError.isInstance(error)) { - throw error; - } - } - - throw new APICallError({ - message: 'Failed to process successful response', - cause: error, - statusCode: response.status, - url, - responseHeaders, - requestBodyValues: body.values, - }); - } - } catch (error) { - throw handleFetchError({ error, url, requestBodyValues: body.values }); - } -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/provider-tool-factory.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/provider-tool-factory.ts deleted file mode 100644 index 2c29130e0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/provider-tool-factory.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { tool, Tool, ToolExecuteFunction } from './types/tool'; -import { FlexibleSchema } from './schema'; - -export type ProviderToolFactory = ( - options: ARGS & { - execute?: ToolExecuteFunction; - needsApproval?: Tool['needsApproval']; - toModelOutput?: Tool['toModelOutput']; - onInputStart?: Tool['onInputStart']; - onInputDelta?: Tool['onInputDelta']; - onInputAvailable?: Tool['onInputAvailable']; - }, -) => Tool; - -export function createProviderToolFactory({ - id, - inputSchema, -}: { - id: `${string}.${string}`; - inputSchema: FlexibleSchema; -}): ProviderToolFactory { - return ({ - execute, - outputSchema, - needsApproval, - toModelOutput, - onInputStart, - onInputDelta, - onInputAvailable, - ...args - }: ARGS & { - execute?: ToolExecuteFunction; - outputSchema?: FlexibleSchema; - needsApproval?: Tool['needsApproval']; - toModelOutput?: Tool['toModelOutput']; - onInputStart?: Tool['onInputStart']; - onInputDelta?: Tool['onInputDelta']; - onInputAvailable?: Tool['onInputAvailable']; - }): Tool => - tool({ - type: 'provider', - id, - args, - inputSchema, - outputSchema, - execute, - needsApproval, - toModelOutput, - onInputStart, - onInputDelta, - onInputAvailable, - }); -} - -export type ProviderToolFactoryWithOutputSchema< - INPUT, - OUTPUT, - ARGS extends object, -> = ( - options: ARGS & { - execute?: ToolExecuteFunction; - needsApproval?: Tool['needsApproval']; - toModelOutput?: Tool['toModelOutput']; - onInputStart?: Tool['onInputStart']; - onInputDelta?: Tool['onInputDelta']; - onInputAvailable?: Tool['onInputAvailable']; - }, -) => Tool; - -export function createProviderToolFactoryWithOutputSchema< - INPUT, - OUTPUT, - ARGS extends object, ->({ - id, - inputSchema, - outputSchema, - supportsDeferredResults, -}: { - id: `${string}.${string}`; - inputSchema: FlexibleSchema; - outputSchema: FlexibleSchema; - /** - * Whether this provider-executed tool supports deferred results. - * - * When true, the tool result may not be returned in the same turn as the - * tool call (e.g., when using programmatic tool calling where a server tool - * triggers a client-executed tool, and the server tool's result is deferred - * until the client tool is resolved). - * - * @default false - */ - supportsDeferredResults?: boolean; -}): ProviderToolFactoryWithOutputSchema { - return ({ - execute, - needsApproval, - toModelOutput, - onInputStart, - onInputDelta, - onInputAvailable, - ...args - }: ARGS & { - execute?: ToolExecuteFunction; - needsApproval?: Tool['needsApproval']; - toModelOutput?: Tool['toModelOutput']; - onInputStart?: Tool['onInputStart']; - onInputDelta?: Tool['onInputDelta']; - onInputAvailable?: Tool['onInputAvailable']; - }): Tool => - tool({ - type: 'provider', - id, - args, - inputSchema, - outputSchema, - execute, - needsApproval, - toModelOutput, - onInputStart, - onInputDelta, - onInputAvailable, - supportsDeferredResults, - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/read-response-with-size-limit.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/read-response-with-size-limit.ts deleted file mode 100644 index 6be70d720..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/read-response-with-size-limit.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { DownloadError } from './download-error'; - -/** - * Default maximum download size: 2 GiB. - * - * `fetch().arrayBuffer()` has ~2x peak memory overhead (undici buffers the - * body internally, then creates the JS ArrayBuffer), so very large downloads - * risk exceeding the default V8 heap limit on 64-bit systems and terminating - * the process with an out-of-memory error. - * - * Setting this limit converts an unrecoverable OOM crash into a catchable - * `DownloadError`. - */ -export const DEFAULT_MAX_DOWNLOAD_SIZE = 2 * 1024 * 1024 * 1024; - -/** - * Reads a fetch Response body with a size limit to prevent memory exhaustion. - * - * Checks the Content-Length header for early rejection, then reads the body - * incrementally via ReadableStream and aborts with a DownloadError when the - * limit is exceeded. - * - * @param response - The fetch Response to read. - * @param url - The URL being downloaded (used in error messages). - * @param maxBytes - Maximum allowed bytes. Defaults to DEFAULT_MAX_DOWNLOAD_SIZE. - * @returns A Uint8Array containing the response body. - * @throws DownloadError if the response exceeds maxBytes. - */ -export async function readResponseWithSizeLimit({ - response, - url, - maxBytes = DEFAULT_MAX_DOWNLOAD_SIZE, -}: { - response: Response; - url: string; - maxBytes?: number; -}): Promise { - // Early rejection based on Content-Length header - const contentLength = response.headers.get('content-length'); - if (contentLength != null) { - const length = parseInt(contentLength, 10); - if (!isNaN(length) && length > maxBytes) { - throw new DownloadError({ - url, - message: `Download of ${url} exceeded maximum size of ${maxBytes} bytes (Content-Length: ${length}).`, - }); - } - } - - const body = response.body; - - // Handle missing body (empty responses) - if (body == null) { - return new Uint8Array(0); - } - - const reader = body.getReader(); - const chunks: Uint8Array[] = []; - let totalBytes = 0; - - try { - while (true) { - const { done, value } = await reader.read(); - - if (done) { - break; - } - - totalBytes += value.length; - - if (totalBytes > maxBytes) { - throw new DownloadError({ - url, - message: `Download of ${url} exceeded maximum size of ${maxBytes} bytes.`, - }); - } - - chunks.push(value); - } - } finally { - try { - await reader.cancel(); - } finally { - reader.releaseLock(); - } - } - - // Concatenate chunks into a single Uint8Array - const result = new Uint8Array(totalBytes); - let offset = 0; - for (const chunk of chunks) { - result.set(chunk, offset); - offset += chunk.length; - } - - return result; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/remove-undefined-entries.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/remove-undefined-entries.ts deleted file mode 100644 index bf315fad8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/remove-undefined-entries.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Removes entries from a record where the value is null or undefined. - * @param record - The input object whose entries may be null or undefined. - * @returns A new object containing only entries with non-null and non-undefined values. - */ -export function removeUndefinedEntries( - record: Record, -): Record { - return Object.fromEntries( - Object.entries(record).filter(([_key, value]) => value != null), - ) as Record; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/resolve.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/resolve.ts deleted file mode 100644 index 1ff8e7903..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/resolve.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { MaybePromiseLike } from './maybe-promise-like'; - -export type Resolvable = MaybePromiseLike | (() => MaybePromiseLike); - -/** - * Resolves a value that could be a raw value, a Promise, a function returning a value, - * or a function returning a Promise. - */ -export async function resolve(value: Resolvable): Promise { - // If it's a function, call it to get the value/promise - if (typeof value === 'function') { - value = (value as Function)(); - } - - // Otherwise just resolve whatever we got (value or promise) - return Promise.resolve(value as T); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/response-handler.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/response-handler.ts deleted file mode 100644 index b96834a96..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/response-handler.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { APICallError, EmptyResponseBodyError } from '@ai-sdk/provider'; -import { extractResponseHeaders } from './extract-response-headers'; -import { parseJSON, ParseResult, safeParseJSON } from './parse-json'; -import { parseJsonEventStream } from './parse-json-event-stream'; -import { FlexibleSchema } from './schema'; - -export type ResponseHandler = (options: { - url: string; - requestBodyValues: unknown; - response: Response; -}) => PromiseLike<{ - value: RETURN_TYPE; - rawValue?: unknown; - responseHeaders?: Record; -}>; - -export const createJsonErrorResponseHandler = - ({ - errorSchema, - errorToMessage, - isRetryable, - }: { - errorSchema: FlexibleSchema; - errorToMessage: (error: T) => string; - isRetryable?: (response: Response, error?: T) => boolean; - }): ResponseHandler => - async ({ response, url, requestBodyValues }) => { - const responseBody = await response.text(); - const responseHeaders = extractResponseHeaders(response); - - // Some providers return an empty response body for some errors: - if (responseBody.trim() === '') { - return { - responseHeaders, - value: new APICallError({ - message: response.statusText, - url, - requestBodyValues, - statusCode: response.status, - responseHeaders, - responseBody, - isRetryable: isRetryable?.(response), - }), - }; - } - - // resilient parsing in case the response is not JSON or does not match the schema: - try { - const parsedError = await parseJSON({ - text: responseBody, - schema: errorSchema, - }); - - return { - responseHeaders, - value: new APICallError({ - message: errorToMessage(parsedError), - url, - requestBodyValues, - statusCode: response.status, - responseHeaders, - responseBody, - data: parsedError, - isRetryable: isRetryable?.(response, parsedError), - }), - }; - } catch (parseError) { - return { - responseHeaders, - value: new APICallError({ - message: response.statusText, - url, - requestBodyValues, - statusCode: response.status, - responseHeaders, - responseBody, - isRetryable: isRetryable?.(response), - }), - }; - } - }; - -export const createEventSourceResponseHandler = - ( - chunkSchema: FlexibleSchema, - ): ResponseHandler>> => - async ({ response }: { response: Response }) => { - const responseHeaders = extractResponseHeaders(response); - - if (response.body == null) { - throw new EmptyResponseBodyError({}); - } - - return { - responseHeaders, - value: parseJsonEventStream({ - stream: response.body, - schema: chunkSchema, - }), - }; - }; - -export const createJsonResponseHandler = - (responseSchema: FlexibleSchema): ResponseHandler => - async ({ response, url, requestBodyValues }) => { - const responseBody = await response.text(); - - const parsedResult = await safeParseJSON({ - text: responseBody, - schema: responseSchema, - }); - - const responseHeaders = extractResponseHeaders(response); - - if (!parsedResult.success) { - throw new APICallError({ - message: 'Invalid JSON response', - cause: parsedResult.error, - statusCode: response.status, - responseHeaders, - responseBody, - url, - requestBodyValues, - }); - } - - return { - responseHeaders, - value: parsedResult.value, - rawValue: parsedResult.rawValue, - }; - }; - -export const createBinaryResponseHandler = - (): ResponseHandler => - async ({ response, url, requestBodyValues }) => { - const responseHeaders = extractResponseHeaders(response); - - if (!response.body) { - throw new APICallError({ - message: 'Response body is empty', - url, - requestBodyValues, - statusCode: response.status, - responseHeaders, - responseBody: undefined, - }); - } - - try { - const buffer = await response.arrayBuffer(); - return { - responseHeaders, - value: new Uint8Array(buffer), - }; - } catch (error) { - throw new APICallError({ - message: 'Failed to read response as array buffer', - url, - requestBodyValues, - statusCode: response.status, - responseHeaders, - responseBody: undefined, - cause: error, - }); - } - }; - -export const createStatusCodeErrorResponseHandler = - (): ResponseHandler => - async ({ response, url, requestBodyValues }) => { - const responseHeaders = extractResponseHeaders(response); - const responseBody = await response.text(); - - return { - responseHeaders, - value: new APICallError({ - message: response.statusText, - url, - requestBodyValues: requestBodyValues as Record, - statusCode: response.status, - responseHeaders, - responseBody, - }), - }; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/schema.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/schema.ts deleted file mode 100644 index 74064de48..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/schema.ts +++ /dev/null @@ -1,267 +0,0 @@ -import { JSONSchema7, TypeValidationError } from '@ai-sdk/provider'; -import { StandardSchemaV1, StandardJSONSchemaV1 } from '@standard-schema/spec'; -import * as z3 from 'zod/v3'; -import * as z4 from 'zod/v4'; -import { addAdditionalPropertiesToJsonSchema } from './add-additional-properties-to-json-schema'; -import { zod3ToJsonSchema } from './to-json-schema/zod3-to-json-schema'; - -/** - * Used to mark schemas so we can support both Zod and custom schemas. - */ -const schemaSymbol = Symbol.for('vercel.ai.schema'); - -export type ValidationResult = - | { success: true; value: OBJECT } - | { success: false; error: Error }; - -export type Schema = { - /** - * Used to mark schemas so we can support both Zod and custom schemas. - */ - [schemaSymbol]: true; - - /** - * Schema type for inference. - */ - _type: OBJECT; - - /** - * Optional. Validates that the structure of a value matches this schema, - * and returns a typed version of the value if it does. - */ - readonly validate?: ( - value: unknown, - ) => ValidationResult | PromiseLike>; - - /** - * The JSON Schema for the schema. It is passed to the providers. - */ - readonly jsonSchema: JSONSchema7 | PromiseLike; -}; - -/** - * Creates a schema with deferred creation. - * This is important to reduce the startup time of the library - * and to avoid initializing unused validators. - * - * @param createValidator A function that creates a schema. - * @returns A function that returns a schema. - */ -export function lazySchema( - createSchema: () => Schema, -): LazySchema { - // cache the validator to avoid initializing it multiple times - let schema: Schema | undefined; - return () => { - if (schema == null) { - schema = createSchema(); - } - return schema; - }; -} - -export type LazySchema = () => Schema; - -export type ZodSchema = - | z3.Schema - | z4.core.$ZodType; - -export type StandardSchema = StandardSchemaV1 & - StandardJSONSchemaV1; - -export type FlexibleSchema = - | Schema - | LazySchema - | ZodSchema - | StandardSchema; - -export type InferSchema = - SCHEMA extends ZodSchema - ? T - : SCHEMA extends StandardSchema - ? T - : SCHEMA extends LazySchema - ? T - : SCHEMA extends Schema - ? T - : never; - -/** - * Create a schema using a JSON Schema. - * - * @param jsonSchema The JSON Schema for the schema. - * @param options.validate Optional. A validation function for the schema. - */ -export function jsonSchema( - jsonSchema: - | JSONSchema7 - | PromiseLike - | (() => JSONSchema7 | PromiseLike), - { - validate, - }: { - validate?: ( - value: unknown, - ) => ValidationResult | PromiseLike>; - } = {}, -): Schema { - return { - [schemaSymbol]: true, - _type: undefined as OBJECT, // should never be used directly - get jsonSchema() { - if (typeof jsonSchema === 'function') { - jsonSchema = jsonSchema(); // cache the function results - } - return jsonSchema; - }, - validate, - }; -} - -function isSchema(value: unknown): value is Schema { - return ( - typeof value === 'object' && - value !== null && - schemaSymbol in value && - value[schemaSymbol] === true && - 'jsonSchema' in value && - 'validate' in value - ); -} - -export function asSchema( - schema: FlexibleSchema | undefined, -): Schema { - return schema == null - ? jsonSchema({ properties: {}, additionalProperties: false }) - : isSchema(schema) - ? schema - : '~standard' in schema - ? schema['~standard'].vendor === 'zod' - ? zodSchema(schema as ZodSchema) - : standardSchema(schema as StandardSchema) - : schema(); -} - -function standardSchema( - standardSchema: StandardSchema, -): Schema { - return jsonSchema( - () => - addAdditionalPropertiesToJsonSchema( - standardSchema['~standard'].jsonSchema.input({ - target: 'draft-07', - }) as JSONSchema7, - ), - { - validate: async value => { - const result = await standardSchema['~standard'].validate(value); - return 'value' in result - ? { success: true, value: result.value } - : { - success: false, - error: new TypeValidationError({ - value, - cause: result.issues, - }), - }; - }, - }, - ); -} - -export function zod3Schema( - zodSchema: z3.Schema, - options?: { - /** - * Enables support for references in the schema. - * This is required for recursive schemas, e.g. with `z.lazy`. - * However, not all language models and providers support such references. - * Defaults to `false`. - */ - useReferences?: boolean; - }, -): Schema { - // default to no references (to support openapi conversion for google) - const useReferences = options?.useReferences ?? false; - - return jsonSchema( - // defer json schema creation to avoid unnecessary computation when only validation is needed - () => - zod3ToJsonSchema(zodSchema, { - $refStrategy: useReferences ? 'root' : 'none', - }) as JSONSchema7, - { - validate: async value => { - const result = await zodSchema.safeParseAsync(value); - return result.success - ? { success: true, value: result.data } - : { success: false, error: result.error }; - }, - }, - ); -} - -export function zod4Schema( - zodSchema: z4.core.$ZodType, - options?: { - /** - * Enables support for references in the schema. - * This is required for recursive schemas, e.g. with `z.lazy`. - * However, not all language models and providers support such references. - * Defaults to `false`. - */ - useReferences?: boolean; - }, -): Schema { - // default to no references (to support openapi conversion for google) - const useReferences = options?.useReferences ?? false; - - return jsonSchema( - // defer json schema creation to avoid unnecessary computation when only validation is needed - () => - addAdditionalPropertiesToJsonSchema( - z4.toJSONSchema(zodSchema, { - target: 'draft-7', - io: 'input', - reused: useReferences ? 'ref' : 'inline', - }) as JSONSchema7, - ), - { - validate: async value => { - const result = await z4.safeParseAsync(zodSchema, value); - return result.success - ? { success: true, value: result.data } - : { success: false, error: result.error }; - }, - }, - ); -} - -export function isZod4Schema( - zodSchema: z4.core.$ZodType | z3.Schema, -): zodSchema is z4.core.$ZodType { - // https://zod.dev/library-authors?id=how-to-support-zod-3-and-zod-4-simultaneously - return '_zod' in zodSchema; -} - -export function zodSchema( - zodSchema: - | z4.core.$ZodType - | z3.Schema, - options?: { - /** - * Enables support for references in the schema. - * This is required for recursive schemas, e.g. with `z.lazy`. - * However, not all language models and providers support such references. - * Defaults to `false`. - */ - useReferences?: boolean; - }, -): Schema { - if (isZod4Schema(zodSchema)) { - return zod4Schema(zodSchema, options); - } else { - return zod3Schema(zodSchema, options); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/secure-json-parse.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/secure-json-parse.ts deleted file mode 100644 index 52ff0e6ad..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/secure-json-parse.ts +++ /dev/null @@ -1,96 +0,0 @@ -// Licensed under BSD-3-Clause (this file only) -// Code adapted from https://github.com/fastify/secure-json-parse/blob/783fcb1b5434709466759847cec974381939673a/index.js -// -// Copyright (c) Vercel, Inc. (https://vercel.com) -// Copyright (c) 2019 The Fastify Team -// Copyright (c) 2019, Sideway Inc, and project contributors -// All rights reserved. -// -// The complete list of contributors can be found at: -// - https://github.com/hapijs/bourne/graphs/contributors -// - https://github.com/fastify/secure-json-parse/graphs/contributors -// - https://github.com/vercel/ai/commits/main/packages/provider-utils/src/secure-parse-json.ts -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -const suspectProtoRx = - /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/; -const suspectConstructorRx = - /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/; - -function _parse(text: string) { - // Parse normally - const obj = JSON.parse(text); - - // Ignore null and non-objects - if (obj === null || typeof obj !== 'object') { - return obj; - } - - if ( - suspectProtoRx.test(text) === false && - suspectConstructorRx.test(text) === false - ) { - return obj; - } - - // Scan result for proto keys - return filter(obj); -} - -function filter(obj: any) { - let next = [obj]; - - while (next.length) { - const nodes = next; - next = []; - - for (const node of nodes) { - if (Object.prototype.hasOwnProperty.call(node, '__proto__')) { - throw new SyntaxError('Object contains forbidden prototype property'); - } - - if ( - Object.prototype.hasOwnProperty.call(node, 'constructor') && - node.constructor !== null && - typeof node.constructor === 'object' && - Object.prototype.hasOwnProperty.call(node.constructor, 'prototype') - ) { - throw new SyntaxError('Object contains forbidden prototype property'); - } - - for (const key in node) { - const value = node[key]; - if (value && typeof value === 'object') { - next.push(value); - } - } - } - } - return obj; -} - -export function secureJsonParse(text: string) { - const { stackTraceLimit } = Error; - try { - // Performance optimization, see https://github.com/fastify/secure-json-parse/pull/90 - Error.stackTraceLimit = 0; - } catch (e) { - // Fallback in case Error is immutable (v8 readonly) - return _parse(text); - } - - try { - return _parse(text); - } finally { - Error.stackTraceLimit = stackTraceLimit; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/strip-file-extension.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/strip-file-extension.ts deleted file mode 100644 index 03b1c8f0d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/strip-file-extension.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Strips file extension segments from a filename. - * - * Examples: - * - "report.pdf" -> "report" - * - "archive.tar.gz" -> "archive" - * - "filename" -> "filename" - */ -export function stripFileExtension(filename: string): string { - const firstDotIndex = filename.indexOf('.'); - - return firstDotIndex === -1 ? filename : filename.slice(0, firstDotIndex); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-array-to-async-iterable.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-array-to-async-iterable.ts deleted file mode 100644 index 7e1a6fbec..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-array-to-async-iterable.ts +++ /dev/null @@ -1,9 +0,0 @@ -export function convertArrayToAsyncIterable(values: T[]): AsyncIterable { - return { - async *[Symbol.asyncIterator]() { - for (const value of values) { - yield value; - } - }, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-array-to-readable-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-array-to-readable-stream.ts deleted file mode 100644 index ac945e5e3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-array-to-readable-stream.ts +++ /dev/null @@ -1,15 +0,0 @@ -export function convertArrayToReadableStream( - values: T[], -): ReadableStream { - return new ReadableStream({ - start(controller) { - try { - for (const value of values) { - controller.enqueue(value); - } - } finally { - controller.close(); - } - }, - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-async-iterable-to-array.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-async-iterable-to-array.ts deleted file mode 100644 index 88e442fea..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-async-iterable-to-array.ts +++ /dev/null @@ -1,9 +0,0 @@ -export async function convertAsyncIterableToArray( - iterable: AsyncIterable, -): Promise { - const result: T[] = []; - for await (const item of iterable) { - result.push(item); - } - return result; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-readable-stream-to-array.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-readable-stream-to-array.ts deleted file mode 100644 index 307e33179..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-readable-stream-to-array.ts +++ /dev/null @@ -1,14 +0,0 @@ -export async function convertReadableStreamToArray( - stream: ReadableStream, -): Promise { - const reader = stream.getReader(); - const result: T[] = []; - - while (true) { - const { done, value } = await reader.read(); - if (done) break; - result.push(value); - } - - return result; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-response-stream-to-array.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-response-stream-to-array.ts deleted file mode 100644 index 3c1fa79b9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/convert-response-stream-to-array.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { convertReadableStreamToArray } from './convert-readable-stream-to-array'; - -export async function convertResponseStreamToArray( - response: Response, -): Promise { - return convertReadableStreamToArray( - response.body!.pipeThrough(new TextDecoderStream()), - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/index.ts deleted file mode 100644 index a8a334ea8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './convert-array-to-async-iterable'; -export * from './convert-array-to-readable-stream'; -export * from './convert-async-iterable-to-array'; -export * from './convert-readable-stream-to-array'; -export * from './convert-response-stream-to-array'; -export * from './is-node-version'; -export * from './mock-id'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/is-node-version.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/is-node-version.ts deleted file mode 100644 index 51f35c604..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/is-node-version.ts +++ /dev/null @@ -1,4 +0,0 @@ -export function isNodeVersion(version: number) { - const nodeMajorVersion = parseInt(process.version.slice(1).split('.')[0], 10); - return nodeMajorVersion === version; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/mock-id.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/mock-id.ts deleted file mode 100644 index 45914a134..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/test/mock-id.ts +++ /dev/null @@ -1,8 +0,0 @@ -export function mockId({ - prefix = 'id', -}: { - prefix?: string; -} = {}): () => string { - let counter = 0; - return () => `${prefix}-${counter++}`; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/LICENSE deleted file mode 100644 index b3b48f8f4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/LICENSE +++ /dev/null @@ -1,16 +0,0 @@ -ISC License - -Copyright (c) 2020, Stefan Terdell -Copyright (c) 2025, Vercel Inc. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/README.md deleted file mode 100644 index ed978d3e8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# `zod-to-json-schema` - -Originally copied from https://github.com/StefanTerdell/zod-to-json-schema because its `peerDependency` on `"zod": "^3.24.1"` while `ai` needs to support `zod@4` if users already use it. We want to avoid having both `zod@3` and `zod@4` in the dependency tree of our users. - -The code in this directory and sub-directories is released under the ISC license: - -``` -ISC License - -Copyright (c) 2020, Stefan Terdell -Copyright (c) 2025, Vercel Inc. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/get-relative-path.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/get-relative-path.ts deleted file mode 100644 index cf80a293e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/get-relative-path.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const getRelativePath = (pathA: string[], pathB: string[]) => { - let i = 0; - for (; i < pathA.length && i < pathB.length; i++) { - if (pathA[i] !== pathB[i]) break; - } - return [(pathA.length - i).toString(), ...pathB.slice(i)].join('/'); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/index.ts deleted file mode 100644 index 1d4d8a589..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { zod3ToJsonSchema } from './zod3-to-json-schema'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/options.ts deleted file mode 100644 index ab5b031c6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/options.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { ZodSchema, ZodTypeDef } from 'zod/v3'; -import { Refs, Seen } from './refs'; -import { JsonSchema7Type } from './parse-types'; - -export type DateStrategy = - | 'format:date-time' - | 'format:date' - | 'string' - | 'integer'; - -export const ignoreOverride = Symbol( - 'Let zodToJsonSchema decide on which parser to use', -); - -export type OverrideCallback = ( - def: ZodTypeDef, - refs: Refs, - seen: Seen | undefined, - forceResolution?: boolean, -) => JsonSchema7Type | undefined | typeof ignoreOverride; - -export type PostProcessCallback = ( - jsonSchema: JsonSchema7Type | undefined, - def: ZodTypeDef, - refs: Refs, -) => JsonSchema7Type | undefined; - -export const jsonDescription: PostProcessCallback = (jsonSchema, def) => { - if (def.description) { - try { - return { - ...jsonSchema, - ...JSON.parse(def.description), - }; - } catch {} - } - - return jsonSchema; -}; - -export type Options = { - name: string | undefined; - $refStrategy: 'root' | 'relative' | 'none' | 'seen'; - basePath: string[]; - effectStrategy: 'input' | 'any'; - pipeStrategy: 'input' | 'output' | 'all'; - dateStrategy: DateStrategy | DateStrategy[]; - mapStrategy: 'entries' | 'record'; - removeAdditionalStrategy: 'passthrough' | 'strict'; - allowedAdditionalProperties: true | undefined; - rejectedAdditionalProperties: false | undefined; - strictUnions: boolean; - definitionPath: string; - definitions: Record; - errorMessages: boolean; - patternStrategy: 'escape' | 'preserve'; - applyRegexFlags: boolean; - emailStrategy: 'format:email' | 'format:idn-email' | 'pattern:zod'; - base64Strategy: 'format:binary' | 'contentEncoding:base64' | 'pattern:zod'; - nameStrategy: 'ref' | 'title'; - override?: OverrideCallback; - postProcess?: PostProcessCallback; -}; - -export const defaultOptions: Options = { - name: undefined, - $refStrategy: 'root', - basePath: ['#'], - effectStrategy: 'input', - pipeStrategy: 'all', - dateStrategy: 'format:date-time', - mapStrategy: 'entries', - removeAdditionalStrategy: 'passthrough', - allowedAdditionalProperties: true, - rejectedAdditionalProperties: false, - definitionPath: 'definitions', - strictUnions: false, - definitions: {}, - errorMessages: false, - patternStrategy: 'escape', - applyRegexFlags: false, - emailStrategy: 'format:email', - base64Strategy: 'contentEncoding:base64', - nameStrategy: 'ref', -}; - -export const getDefaultOptions = ( - options: Partial | string | undefined, -) => - (typeof options === 'string' - ? { - ...defaultOptions, - name: options, - } - : { - ...defaultOptions, - ...options, - }) as Options; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parse-def.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parse-def.ts deleted file mode 100644 index b2f6b8d7b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parse-def.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { ZodTypeDef } from 'zod/v3'; -import { Refs, Seen } from './refs'; -import { ignoreOverride } from './options'; -import { JsonSchema7Type } from './parse-types'; -import { selectParser } from './select-parser'; -import { getRelativePath } from './get-relative-path'; -import { parseAnyDef } from './parsers/any'; - -export function parseDef( - def: ZodTypeDef, - refs: Refs, - forceResolution = false, // Forces a new schema to be instantiated even though its def has been seen. Used for improving refs in definitions. See https://github.com/StefanTerdell/zod-to-json-schema/pull/61. -): JsonSchema7Type | undefined { - const seenItem = refs.seen.get(def); - - if (refs.override) { - const overrideResult = refs.override?.( - def, - refs, - seenItem, - forceResolution, - ); - - if (overrideResult !== ignoreOverride) { - return overrideResult; - } - } - - if (seenItem && !forceResolution) { - const seenSchema = get$ref(seenItem, refs); - - if (seenSchema !== undefined) { - return seenSchema; - } - } - - const newItem: Seen = { def, path: refs.currentPath, jsonSchema: undefined }; - - refs.seen.set(def, newItem); - - const jsonSchemaOrGetter = selectParser(def, (def as any).typeName, refs); - - // If the return was a function, then the inner definition needs to be extracted before a call to parseDef (recursive) - const jsonSchema = - typeof jsonSchemaOrGetter === 'function' - ? parseDef(jsonSchemaOrGetter(), refs) - : jsonSchemaOrGetter; - - if (jsonSchema) { - addMeta(def, refs, jsonSchema); - } - - if (refs.postProcess) { - const postProcessResult = refs.postProcess(jsonSchema, def, refs); - - newItem.jsonSchema = jsonSchema; - - return postProcessResult; - } - - newItem.jsonSchema = jsonSchema; - - return jsonSchema; -} - -const get$ref = ( - item: Seen, - refs: Refs, -): - | { - $ref: string; - } - | {} - | undefined => { - switch (refs.$refStrategy) { - case 'root': - return { $ref: item.path.join('/') }; - case 'relative': - return { $ref: getRelativePath(refs.currentPath, item.path) }; - case 'none': - case 'seen': { - if ( - item.path.length < refs.currentPath.length && - item.path.every((value, index) => refs.currentPath[index] === value) - ) { - console.warn( - `Recursive reference detected at ${refs.currentPath.join( - '/', - )}! Defaulting to any`, - ); - - return parseAnyDef(); - } - - return refs.$refStrategy === 'seen' ? parseAnyDef() : undefined; - } - } -}; - -const addMeta = ( - def: ZodTypeDef, - refs: Refs, - jsonSchema: JsonSchema7Type, -): JsonSchema7Type => { - if (def.description) { - jsonSchema.description = def.description; - } - return jsonSchema; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parse-types.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parse-types.ts deleted file mode 100644 index 2da338f12..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parse-types.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { JsonSchema7AnyType } from './parsers/any'; -import { JsonSchema7ArrayType } from './parsers/array'; -import { JsonSchema7BigintType } from './parsers/bigint'; -import { JsonSchema7BooleanType } from './parsers/boolean'; -import { JsonSchema7DateType } from './parsers/date'; -import { JsonSchema7EnumType } from './parsers/enum'; -import { JsonSchema7AllOfType } from './parsers/intersection'; -import { JsonSchema7LiteralType } from './parsers/literal'; -import { JsonSchema7MapType } from './parsers/map'; -import { JsonSchema7NativeEnumType } from './parsers/native-enum'; -import { JsonSchema7NeverType } from './parsers/never'; -import { JsonSchema7NullType } from './parsers/null'; -import { JsonSchema7NullableType } from './parsers/nullable'; -import { JsonSchema7NumberType } from './parsers/number'; -import { JsonSchema7ObjectType } from './parsers/object'; -import { JsonSchema7RecordType } from './parsers/record'; -import { JsonSchema7SetType } from './parsers/set'; -import { JsonSchema7StringType } from './parsers/string'; -import { JsonSchema7TupleType } from './parsers/tuple'; -import { JsonSchema7UndefinedType } from './parsers/undefined'; -import { JsonSchema7UnionType } from './parsers/union'; -import { JsonSchema7UnknownType } from './parsers/unknown'; - -type JsonSchema7RefType = { $ref: string }; -type JsonSchema7Meta = { - title?: string; - default?: any; - description?: string; -}; - -export type JsonSchema7TypeUnion = - | JsonSchema7StringType - | JsonSchema7ArrayType - | JsonSchema7NumberType - | JsonSchema7BigintType - | JsonSchema7BooleanType - | JsonSchema7DateType - | JsonSchema7EnumType - | JsonSchema7LiteralType - | JsonSchema7NativeEnumType - | JsonSchema7NullType - | JsonSchema7NumberType - | JsonSchema7ObjectType - | JsonSchema7RecordType - | JsonSchema7TupleType - | JsonSchema7UnionType - | JsonSchema7UndefinedType - | JsonSchema7RefType - | JsonSchema7NeverType - | JsonSchema7MapType - | JsonSchema7AnyType - | JsonSchema7NullableType - | JsonSchema7AllOfType - | JsonSchema7UnknownType - | JsonSchema7SetType; - -export type JsonSchema7Type = JsonSchema7TypeUnion & JsonSchema7Meta; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/any.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/any.ts deleted file mode 100644 index 5e119edaa..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/any.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type JsonSchema7AnyType = { $ref?: string }; - -export function parseAnyDef(): JsonSchema7AnyType { - return {}; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/array.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/array.ts deleted file mode 100644 index 940b10527..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/array.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { ZodArrayDef, ZodFirstPartyTypeKind } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; - -export type JsonSchema7ArrayType = { - type: 'array'; - items?: JsonSchema7Type; - minItems?: number; - maxItems?: number; -}; - -export function parseArrayDef(def: ZodArrayDef, refs: Refs) { - const res: JsonSchema7ArrayType = { - type: 'array', - }; - if ( - def.type?._def && - def.type?._def?.typeName !== ZodFirstPartyTypeKind.ZodAny - ) { - res.items = parseDef(def.type._def, { - ...refs, - currentPath: [...refs.currentPath, 'items'], - }); - } - - if (def.minLength) { - res.minItems = def.minLength.value; - } - if (def.maxLength) { - res.maxItems = def.maxLength.value; - } - if (def.exactLength) { - res.minItems = def.exactLength.value; - res.maxItems = def.exactLength.value; - } - return res; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/bigint.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/bigint.ts deleted file mode 100644 index 1185a6f81..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/bigint.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { ZodBigIntDef } from 'zod/v3'; - -export type JsonSchema7BigintType = { - type: 'integer'; - format: 'int64'; - minimum?: BigInt; - exclusiveMinimum?: BigInt; - maximum?: BigInt; - exclusiveMaximum?: BigInt; - multipleOf?: BigInt; -}; - -export function parseBigintDef(def: ZodBigIntDef): JsonSchema7BigintType { - const res: JsonSchema7BigintType = { - type: 'integer', - format: 'int64', - }; - - if (!def.checks) return res; - - for (const check of def.checks) { - switch (check.kind) { - case 'min': - if (check.inclusive) { - res.minimum = check.value; - } else { - res.exclusiveMinimum = check.value; - } - break; - case 'max': - if (check.inclusive) { - res.maximum = check.value; - } else { - res.exclusiveMaximum = check.value; - } - - break; - case 'multipleOf': - res.multipleOf = check.value; - break; - } - } - return res; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/boolean.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/boolean.ts deleted file mode 100644 index b6376346f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/boolean.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type JsonSchema7BooleanType = { - type: 'boolean'; -}; - -export function parseBooleanDef(): JsonSchema7BooleanType { - return { type: 'boolean' }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/branded.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/branded.ts deleted file mode 100644 index d388a2dbd..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/branded.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ZodBrandedDef } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { Refs } from '../refs'; - -export function parseBrandedDef(_def: ZodBrandedDef, refs: Refs) { - return parseDef(_def.type._def, refs); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/catch.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/catch.ts deleted file mode 100644 index b20308ad6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/catch.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ZodCatchDef } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { Refs } from '../refs'; - -export const parseCatchDef = (def: ZodCatchDef, refs: Refs) => { - return parseDef(def.innerType._def, refs); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/date.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/date.ts deleted file mode 100644 index a46832879..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/date.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { ZodDateDef } from 'zod/v3'; -import { Refs } from '../refs'; -import { DateStrategy } from '../options'; - -export type JsonSchema7DateType = - | { - type: 'integer' | 'string'; - format: 'unix-time' | 'date-time' | 'date'; - minimum?: number; - maximum?: number; - } - | { - anyOf: JsonSchema7DateType[]; - }; - -export function parseDateDef( - def: ZodDateDef, - refs: Refs, - overrideDateStrategy?: DateStrategy, -): JsonSchema7DateType { - const strategy = overrideDateStrategy ?? refs.dateStrategy; - - if (Array.isArray(strategy)) { - return { - anyOf: strategy.map((item, i) => parseDateDef(def, refs, item)), - }; - } - - switch (strategy) { - case 'string': - case 'format:date-time': - return { - type: 'string', - format: 'date-time', - }; - case 'format:date': - return { - type: 'string', - format: 'date', - }; - case 'integer': - return integerDateParser(def); - } -} - -const integerDateParser = (def: ZodDateDef) => { - const res: JsonSchema7DateType = { - type: 'integer', - format: 'unix-time', - }; - - for (const check of def.checks) { - switch (check.kind) { - case 'min': - res.minimum = check.value; - break; - case 'max': - res.maximum = check.value; - break; - } - } - - return res; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/default.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/default.ts deleted file mode 100644 index 26438e303..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/default.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { ZodDefaultDef } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; - -export function parseDefaultDef( - _def: ZodDefaultDef, - refs: Refs, -): JsonSchema7Type & { default: any } { - return { - ...parseDef(_def.innerType._def, refs), - default: _def.defaultValue(), - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/effects.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/effects.ts deleted file mode 100644 index 6f659c028..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/effects.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { ZodEffectsDef } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; -import { parseAnyDef } from './any'; - -export function parseEffectsDef( - _def: ZodEffectsDef, - refs: Refs, -): JsonSchema7Type | undefined { - return refs.effectStrategy === 'input' - ? parseDef(_def.schema._def, refs) - : parseAnyDef(); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/enum.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/enum.ts deleted file mode 100644 index 9a6e02384..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/enum.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ZodEnumDef } from 'zod/v3'; - -export type JsonSchema7EnumType = { - type: 'string'; - enum: string[]; -}; - -export function parseEnumDef(def: ZodEnumDef): JsonSchema7EnumType { - return { - type: 'string', - enum: Array.from(def.values), - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/intersection.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/intersection.ts deleted file mode 100644 index e2916d249..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/intersection.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { ZodIntersectionDef } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; -import { JsonSchema7StringType } from './string'; - -export type JsonSchema7AllOfType = { - allOf: JsonSchema7Type[]; - unevaluatedProperties?: boolean; -}; - -const isJsonSchema7AllOfType = ( - type: JsonSchema7Type | JsonSchema7StringType, -): type is JsonSchema7AllOfType => { - if ('type' in type && type.type === 'string') return false; - return 'allOf' in type; -}; - -export function parseIntersectionDef( - def: ZodIntersectionDef, - refs: Refs, -): JsonSchema7AllOfType | JsonSchema7Type | undefined { - const allOf = [ - parseDef(def.left._def, { - ...refs, - currentPath: [...refs.currentPath, 'allOf', '0'], - }), - parseDef(def.right._def, { - ...refs, - currentPath: [...refs.currentPath, 'allOf', '1'], - }), - ].filter((x): x is JsonSchema7Type => !!x); - - const mergedAllOf: JsonSchema7Type[] = []; - // If either of the schemas is an allOf, merge them into a single allOf - allOf.forEach(schema => { - if (isJsonSchema7AllOfType(schema)) { - mergedAllOf.push(...schema.allOf); - } else { - let nestedSchema: JsonSchema7Type = schema; - if ( - 'additionalProperties' in schema && - schema.additionalProperties === false - ) { - const { additionalProperties, ...rest } = schema; - nestedSchema = rest; - } - mergedAllOf.push(nestedSchema); - } - }); - return mergedAllOf.length ? { allOf: mergedAllOf } : undefined; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/literal.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/literal.ts deleted file mode 100644 index bb1c38407..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/literal.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { ZodLiteralDef } from 'zod/v3'; - -export type JsonSchema7LiteralType = - | { - type: 'string' | 'number' | 'integer' | 'boolean'; - const: string | number | boolean; - } - | { - type: 'object' | 'array'; - }; - -export function parseLiteralDef(def: ZodLiteralDef): JsonSchema7LiteralType { - const parsedType = typeof def.value; - if ( - parsedType !== 'bigint' && - parsedType !== 'number' && - parsedType !== 'boolean' && - parsedType !== 'string' - ) { - return { - type: Array.isArray(def.value) ? 'array' : 'object', - }; - } - - return { - type: parsedType === 'bigint' ? 'integer' : parsedType, - const: def.value, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/map.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/map.ts deleted file mode 100644 index b719f61fa..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/map.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { ZodMapDef } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; -import { parseAnyDef } from './any'; -import { JsonSchema7RecordType, parseRecordDef } from './record'; - -export type JsonSchema7MapType = { - type: 'array'; - maxItems: 125; - items: { - type: 'array'; - items: [JsonSchema7Type, JsonSchema7Type]; - minItems: 2; - maxItems: 2; - }; -}; - -export function parseMapDef( - def: ZodMapDef, - refs: Refs, -): JsonSchema7MapType | JsonSchema7RecordType { - if (refs.mapStrategy === 'record') { - return parseRecordDef(def, refs); - } - - const keys = - parseDef(def.keyType._def, { - ...refs, - currentPath: [...refs.currentPath, 'items', 'items', '0'], - }) || parseAnyDef(); - const values = - parseDef(def.valueType._def, { - ...refs, - currentPath: [...refs.currentPath, 'items', 'items', '1'], - }) || parseAnyDef(); - return { - type: 'array', - maxItems: 125, - items: { - type: 'array', - items: [keys, values], - minItems: 2, - maxItems: 2, - }, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/native-enum.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/native-enum.ts deleted file mode 100644 index cff192520..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/native-enum.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { ZodNativeEnumDef } from 'zod/v3'; - -export type JsonSchema7NativeEnumType = { - type: 'string' | 'number' | ['string', 'number']; - enum: (string | number)[]; -}; - -export function parseNativeEnumDef( - def: ZodNativeEnumDef, -): JsonSchema7NativeEnumType { - const object = def.values; - const actualKeys = Object.keys(def.values).filter((key: string) => { - return typeof object[object[key]] !== 'number'; - }); - - const actualValues = actualKeys.map((key: string) => object[key]); - - const parsedTypes = Array.from( - new Set(actualValues.map((values: string | number) => typeof values)), - ); - - return { - type: - parsedTypes.length === 1 - ? parsedTypes[0] === 'string' - ? 'string' - : 'number' - : ['string', 'number'], - enum: actualValues, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/never.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/never.ts deleted file mode 100644 index 7957830a2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/never.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { JsonSchema7AnyType, parseAnyDef } from './any'; - -export type JsonSchema7NeverType = { - not: JsonSchema7AnyType; -}; - -export function parseNeverDef(): JsonSchema7NeverType | undefined { - return { not: parseAnyDef() }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/null.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/null.ts deleted file mode 100644 index a1335a397..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/null.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type JsonSchema7NullType = { - type: 'null'; -}; - -export function parseNullDef(): JsonSchema7NullType { - return { - type: 'null', - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/nullable.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/nullable.ts deleted file mode 100644 index 8e064381c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/nullable.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { ZodNullableDef } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; -import { JsonSchema7NullType } from './null'; -import { primitiveMappings } from './union'; - -export type JsonSchema7NullableType = - | { - anyOf: [JsonSchema7Type, JsonSchema7NullType]; - } - | { - type: [string, 'null']; - }; - -export function parseNullableDef( - def: ZodNullableDef, - refs: Refs, -): JsonSchema7NullableType | undefined { - if ( - ['ZodString', 'ZodNumber', 'ZodBigInt', 'ZodBoolean', 'ZodNull'].includes( - def.innerType._def.typeName, - ) && - (!def.innerType._def.checks || !def.innerType._def.checks.length) - ) { - return { - type: [ - primitiveMappings[ - def.innerType._def.typeName as keyof typeof primitiveMappings - ], - 'null', - ], - }; - } - - const base = parseDef(def.innerType._def, { - ...refs, - currentPath: [...refs.currentPath, 'anyOf', '0'], - }); - - return base && { anyOf: [base, { type: 'null' }] }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/number.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/number.ts deleted file mode 100644 index 318ee41eb..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/number.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { ZodNumberDef } from 'zod/v3'; - -export type JsonSchema7NumberType = { - type: 'number' | 'integer'; - minimum?: number; - exclusiveMinimum?: number; - maximum?: number; - exclusiveMaximum?: number; - multipleOf?: number; -}; - -export function parseNumberDef(def: ZodNumberDef): JsonSchema7NumberType { - const res: JsonSchema7NumberType = { - type: 'number', - }; - - if (!def.checks) return res; - - for (const check of def.checks) { - switch (check.kind) { - case 'int': - res.type = 'integer'; - break; - case 'min': - if (check.inclusive) { - res.minimum = check.value; - } else { - res.exclusiveMinimum = check.value; - } - break; - case 'max': - if (check.inclusive) { - res.maximum = check.value; - } else { - res.exclusiveMaximum = check.value; - } - break; - case 'multipleOf': - res.multipleOf = check.value; - break; - } - } - return res; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/object.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/object.ts deleted file mode 100644 index 44ef33abf..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/object.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { ZodObjectDef, ZodTypeAny } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; - -export type JsonSchema7ObjectType = { - type: 'object'; - properties: Record; - additionalProperties?: boolean | JsonSchema7Type; - required?: string[]; -}; - -export function parseObjectDef(def: ZodObjectDef, refs: Refs) { - const result: JsonSchema7ObjectType = { - type: 'object', - properties: {}, - }; - - const required: string[] = []; - - const shape = def.shape(); - - for (const propName in shape) { - let propDef = shape[propName]; - - if (propDef === undefined || propDef._def === undefined) { - continue; - } - - const propOptional = safeIsOptional(propDef); - - const parsedDef = parseDef(propDef._def, { - ...refs, - currentPath: [...refs.currentPath, 'properties', propName], - propertyPath: [...refs.currentPath, 'properties', propName], - }); - - if (parsedDef === undefined) { - continue; - } - - result.properties[propName] = parsedDef; - - if (!propOptional) { - required.push(propName); - } - } - - if (required.length) { - result.required = required; - } - - const additionalProperties = decideAdditionalProperties(def, refs); - - if (additionalProperties !== undefined) { - result.additionalProperties = additionalProperties; - } - - return result; -} - -function decideAdditionalProperties(def: ZodObjectDef, refs: Refs) { - if (def.catchall._def.typeName !== 'ZodNever') { - return parseDef(def.catchall._def, { - ...refs, - currentPath: [...refs.currentPath, 'additionalProperties'], - }); - } - - switch (def.unknownKeys) { - case 'passthrough': - return refs.allowedAdditionalProperties; - case 'strict': - return refs.rejectedAdditionalProperties; - case 'strip': - return refs.removeAdditionalStrategy === 'strict' - ? refs.allowedAdditionalProperties - : refs.rejectedAdditionalProperties; - } -} - -function safeIsOptional(schema: ZodTypeAny): boolean { - try { - return schema.isOptional(); - } catch { - return true; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/optional.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/optional.ts deleted file mode 100644 index 0ff940676..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/optional.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ZodOptionalDef } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; -import { parseAnyDef } from './any'; - -export const parseOptionalDef = ( - def: ZodOptionalDef, - refs: Refs, -): JsonSchema7Type | undefined => { - if (refs.currentPath.toString() === refs.propertyPath?.toString()) { - return parseDef(def.innerType._def, refs); - } - - const innerSchema = parseDef(def.innerType._def, { - ...refs, - currentPath: [...refs.currentPath, 'anyOf', '1'], - }); - - return innerSchema - ? { anyOf: [{ not: parseAnyDef() }, innerSchema] } - : parseAnyDef(); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/pipeline.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/pipeline.ts deleted file mode 100644 index 73bb89641..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/pipeline.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { ZodPipelineDef } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; -import { JsonSchema7AllOfType } from './intersection'; - -export const parsePipelineDef = ( - def: ZodPipelineDef, - refs: Refs, -): JsonSchema7AllOfType | JsonSchema7Type | undefined => { - if (refs.pipeStrategy === 'input') { - return parseDef(def.in._def, refs); - } else if (refs.pipeStrategy === 'output') { - return parseDef(def.out._def, refs); - } - - const a = parseDef(def.in._def, { - ...refs, - currentPath: [...refs.currentPath, 'allOf', '0'], - }); - const b = parseDef(def.out._def, { - ...refs, - currentPath: [...refs.currentPath, 'allOf', a ? '1' : '0'], - }); - - return { - allOf: [a, b].filter((x): x is JsonSchema7Type => x !== undefined), - }; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/promise.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/promise.ts deleted file mode 100644 index 35d43d8a9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/promise.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ZodPromiseDef } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; - -export function parsePromiseDef( - def: ZodPromiseDef, - refs: Refs, -): JsonSchema7Type | undefined { - return parseDef(def.type._def, refs); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/readonly.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/readonly.ts deleted file mode 100644 index 048b6fcd2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/readonly.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ZodReadonlyDef } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { Refs } from '../refs'; - -export const parseReadonlyDef = (def: ZodReadonlyDef, refs: Refs) => { - return parseDef(def.innerType._def, refs); -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/record.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/record.ts deleted file mode 100644 index 03c76c034..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/record.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { - ZodFirstPartyTypeKind, - ZodMapDef, - ZodRecordDef, - ZodTypeAny, -} from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; -import { parseBrandedDef } from './branded'; -import { JsonSchema7EnumType } from './enum'; -import { JsonSchema7StringType, parseStringDef } from './string'; - -type JsonSchema7RecordPropertyNamesType = - | Omit - | Omit; - -export type JsonSchema7RecordType = { - type: 'object'; - additionalProperties?: JsonSchema7Type | true; - propertyNames?: JsonSchema7RecordPropertyNamesType; -}; - -export function parseRecordDef( - def: ZodRecordDef | ZodMapDef, - refs: Refs, -): JsonSchema7RecordType { - const schema: JsonSchema7RecordType = { - type: 'object', - additionalProperties: - parseDef(def.valueType._def, { - ...refs, - currentPath: [...refs.currentPath, 'additionalProperties'], - }) ?? refs.allowedAdditionalProperties, - }; - - if ( - def.keyType?._def.typeName === ZodFirstPartyTypeKind.ZodString && - def.keyType._def.checks?.length - ) { - const { type, ...keyType } = parseStringDef(def.keyType._def, refs); - - return { - ...schema, - propertyNames: keyType, - }; - } else if (def.keyType?._def.typeName === ZodFirstPartyTypeKind.ZodEnum) { - return { - ...schema, - propertyNames: { - enum: def.keyType._def.values, - }, - }; - } else if ( - def.keyType?._def.typeName === ZodFirstPartyTypeKind.ZodBranded && - def.keyType._def.type._def.typeName === ZodFirstPartyTypeKind.ZodString && - def.keyType._def.type._def.checks?.length - ) { - const { type, ...keyType } = parseBrandedDef( - def.keyType._def, - refs, - ) as JsonSchema7StringType; - - return { - ...schema, - propertyNames: keyType, - }; - } - - return schema; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/set.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/set.ts deleted file mode 100644 index a81f4b438..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/set.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { ZodSetDef } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; - -export type JsonSchema7SetType = { - type: 'array'; - uniqueItems: true; - items?: JsonSchema7Type; - minItems?: number; - maxItems?: number; -}; - -export function parseSetDef(def: ZodSetDef, refs: Refs): JsonSchema7SetType { - const items = parseDef(def.valueType._def, { - ...refs, - currentPath: [...refs.currentPath, 'items'], - }); - - const schema: JsonSchema7SetType = { - type: 'array', - uniqueItems: true, - items, - }; - - if (def.minSize) { - schema.minItems = def.minSize.value; - } - - if (def.maxSize) { - schema.maxItems = def.maxSize.value; - } - - return schema; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/string.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/string.ts deleted file mode 100644 index 9cc298da8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/string.ts +++ /dev/null @@ -1,426 +0,0 @@ -import { ZodStringDef } from 'zod/v3'; -import { Refs } from '../refs'; - -let emojiRegex: RegExp | undefined = undefined; - -/** - * Generated from the regular expressions found here as of 2024-05-22: - * https://github.com/colinhacks/zod/blob/master/src/types.ts. - * - * Expressions with /i flag have been changed accordingly. - */ -export const zodPatterns = { - /** - * `c` was changed to `[cC]` to replicate /i flag - */ - cuid: /^[cC][^\s-]{8,}$/, - cuid2: /^[0-9a-z]+$/, - ulid: /^[0-9A-HJKMNP-TV-Z]{26}$/, - /** - * `a-z` was added to replicate /i flag - */ - email: - /^(?!\.)(?!.*\.\.)([a-zA-Z0-9_'+\-\.]*)[a-zA-Z0-9_+-]@([a-zA-Z0-9][a-zA-Z0-9\-]*\.)+[a-zA-Z]{2,}$/, - /** - * Constructed a valid Unicode RegExp - * - * Lazily instantiate since this type of regex isn't supported - * in all envs (e.g. React Native). - * - * See: - * https://github.com/colinhacks/zod/issues/2433 - * Fix in Zod: - * https://github.com/colinhacks/zod/commit/9340fd51e48576a75adc919bff65dbc4a5d4c99b - */ - emoji: () => { - if (emojiRegex === undefined) { - emojiRegex = RegExp( - '^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$', - 'u', - ); - } - return emojiRegex; - }, - /** - * Unused - */ - uuid: /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/, - /** - * Unused - */ - ipv4: /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/, - ipv4Cidr: - /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/, - /** - * Unused - */ - ipv6: /^(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$/, - ipv6Cidr: - /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/, - base64: /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/, - base64url: - /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/, - nanoid: /^[a-zA-Z0-9_-]{21}$/, - jwt: /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/, -} as const; - -export type JsonSchema7StringType = { - type: 'string'; - minLength?: number; - maxLength?: number; - format?: - | 'email' - | 'idn-email' - | 'uri' - | 'uuid' - | 'date-time' - | 'ipv4' - | 'ipv6' - | 'date' - | 'time' - | 'duration'; - pattern?: string; - allOf?: { - pattern: string; - }[]; - anyOf?: { - format: string; - }[]; - contentEncoding?: string; -}; - -export function parseStringDef( - def: ZodStringDef, - refs: Refs, -): JsonSchema7StringType { - const res: JsonSchema7StringType = { - type: 'string', - }; - - if (def.checks) { - for (const check of def.checks) { - switch (check.kind) { - case 'min': - res.minLength = - typeof res.minLength === 'number' - ? Math.max(res.minLength, check.value) - : check.value; - break; - case 'max': - res.maxLength = - typeof res.maxLength === 'number' - ? Math.min(res.maxLength, check.value) - : check.value; - - break; - case 'email': - switch (refs.emailStrategy) { - case 'format:email': - addFormat(res, 'email', check.message, refs); - break; - case 'format:idn-email': - addFormat(res, 'idn-email', check.message, refs); - break; - case 'pattern:zod': - addPattern(res, zodPatterns.email, check.message, refs); - break; - } - - break; - case 'url': - addFormat(res, 'uri', check.message, refs); - break; - case 'uuid': - addFormat(res, 'uuid', check.message, refs); - break; - case 'regex': - addPattern(res, check.regex, check.message, refs); - break; - case 'cuid': - addPattern(res, zodPatterns.cuid, check.message, refs); - break; - case 'cuid2': - addPattern(res, zodPatterns.cuid2, check.message, refs); - break; - case 'startsWith': - addPattern( - res, - RegExp(`^${escapeLiteralCheckValue(check.value, refs)}`), - check.message, - refs, - ); - break; - case 'endsWith': - addPattern( - res, - RegExp(`${escapeLiteralCheckValue(check.value, refs)}$`), - check.message, - refs, - ); - break; - case 'datetime': - addFormat(res, 'date-time', check.message, refs); - break; - case 'date': - addFormat(res, 'date', check.message, refs); - break; - case 'time': - addFormat(res, 'time', check.message, refs); - break; - case 'duration': - addFormat(res, 'duration', check.message, refs); - break; - case 'length': - res.minLength = - typeof res.minLength === 'number' - ? Math.max(res.minLength, check.value) - : check.value; - res.maxLength = - typeof res.maxLength === 'number' - ? Math.min(res.maxLength, check.value) - : check.value; - break; - case 'includes': { - addPattern( - res, - RegExp(escapeLiteralCheckValue(check.value, refs)), - check.message, - refs, - ); - break; - } - case 'ip': { - if (check.version !== 'v6') { - addFormat(res, 'ipv4', check.message, refs); - } - if (check.version !== 'v4') { - addFormat(res, 'ipv6', check.message, refs); - } - break; - } - case 'base64url': - addPattern(res, zodPatterns.base64url, check.message, refs); - break; - case 'jwt': - addPattern(res, zodPatterns.jwt, check.message, refs); - break; - case 'cidr': { - if (check.version !== 'v6') { - addPattern(res, zodPatterns.ipv4Cidr, check.message, refs); - } - if (check.version !== 'v4') { - addPattern(res, zodPatterns.ipv6Cidr, check.message, refs); - } - break; - } - case 'emoji': - addPattern(res, zodPatterns.emoji(), check.message, refs); - break; - case 'ulid': { - addPattern(res, zodPatterns.ulid, check.message, refs); - break; - } - case 'base64': { - switch (refs.base64Strategy) { - case 'format:binary': { - addFormat(res, 'binary' as any, check.message, refs); - break; - } - - case 'contentEncoding:base64': { - res.contentEncoding = 'base64'; - break; - } - - case 'pattern:zod': { - addPattern(res, zodPatterns.base64, check.message, refs); - break; - } - } - break; - } - case 'nanoid': { - addPattern(res, zodPatterns.nanoid, check.message, refs); - } - case 'toLowerCase': - case 'toUpperCase': - case 'trim': - break; - default: - /* c8 ignore next */ - ((_: never) => {})(check); - } - } - } - - return res; -} - -function escapeLiteralCheckValue(literal: string, refs: Refs): string { - return refs.patternStrategy === 'escape' - ? escapeNonAlphaNumeric(literal) - : literal; -} - -const ALPHA_NUMERIC = new Set( - 'ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789', -); - -function escapeNonAlphaNumeric(source: string) { - let result = ''; - - for (let i = 0; i < source.length; i++) { - if (!ALPHA_NUMERIC.has(source[i])) { - result += '\\'; - } - - result += source[i]; - } - - return result; -} - -// Adds a "format" keyword to the schema. If a format exists, both formats will be joined in an allOf-node, along with subsequent ones. -function addFormat( - schema: JsonSchema7StringType, - value: Required['format'], - message: string | undefined, - refs: Refs, -) { - if (schema.format || schema.anyOf?.some(x => x.format)) { - if (!schema.anyOf) { - schema.anyOf = []; - } - - if (schema.format) { - schema.anyOf!.push({ - format: schema.format, - }); - delete schema.format; - } - - schema.anyOf!.push({ - format: value, - ...(message && - refs.errorMessages && { errorMessage: { format: message } }), - }); - } else { - schema.format = value; - } -} - -// Adds a "pattern" keyword to the schema. If a pattern exists, both patterns will be joined in an allOf-node, along with subsequent ones. -function addPattern( - schema: JsonSchema7StringType, - regex: RegExp, - message: string | undefined, - refs: Refs, -) { - if (schema.pattern || schema.allOf?.some(x => x.pattern)) { - if (!schema.allOf) { - schema.allOf = []; - } - - if (schema.pattern) { - schema.allOf!.push({ - pattern: schema.pattern, - }); - delete schema.pattern; - } - - schema.allOf!.push({ - pattern: stringifyRegExpWithFlags(regex, refs), - ...(message && - refs.errorMessages && { errorMessage: { pattern: message } }), - }); - } else { - schema.pattern = stringifyRegExpWithFlags(regex, refs); - } -} - -// Mutate z.string.regex() in a best attempt to accommodate for regex flags when applyRegexFlags is true -function stringifyRegExpWithFlags(regex: RegExp, refs: Refs): string { - if (!refs.applyRegexFlags || !regex.flags) { - return regex.source; - } - - // Currently handled flags - const flags = { - i: regex.flags.includes('i'), // Case-insensitive - m: regex.flags.includes('m'), // `^` and `$` matches adjacent to newline characters - s: regex.flags.includes('s'), // `.` matches newlines - }; - - // The general principle here is to step through each character, one at a time, applying mutations as flags require. We keep track when the current character is escaped, and when it's inside a group /like [this]/ or (also) a range like /[a-z]/. The following is fairly brittle imperative code; edit at your peril! - const source = flags.i ? regex.source.toLowerCase() : regex.source; - let pattern = ''; - let isEscaped = false; - let inCharGroup = false; - let inCharRange = false; - - for (let i = 0; i < source.length; i++) { - if (isEscaped) { - pattern += source[i]; - isEscaped = false; - continue; - } - - if (flags.i) { - if (inCharGroup) { - if (source[i].match(/[a-z]/)) { - if (inCharRange) { - pattern += source[i]; - pattern += `${source[i - 2]}-${source[i]}`.toUpperCase(); - inCharRange = false; - } else if (source[i + 1] === '-' && source[i + 2]?.match(/[a-z]/)) { - pattern += source[i]; - inCharRange = true; - } else { - pattern += `${source[i]}${source[i].toUpperCase()}`; - } - continue; - } - } else if (source[i].match(/[a-z]/)) { - pattern += `[${source[i]}${source[i].toUpperCase()}]`; - continue; - } - } - - if (flags.m) { - if (source[i] === '^') { - pattern += `(^|(?<=[\r\n]))`; - continue; - } else if (source[i] === '$') { - pattern += `($|(?=[\r\n]))`; - continue; - } - } - - if (flags.s && source[i] === '.') { - pattern += inCharGroup ? `${source[i]}\r\n` : `[${source[i]}\r\n]`; - continue; - } - - pattern += source[i]; - if (source[i] === '\\') { - isEscaped = true; - } else if (inCharGroup && source[i] === ']') { - inCharGroup = false; - } else if (!inCharGroup && source[i] === '[') { - inCharGroup = true; - } - } - - try { - new RegExp(pattern); - } catch { - console.warn( - `Could not convert regex pattern at ${refs.currentPath.join( - '/', - )} to a flag-independent form! Falling back to the flag-ignorant source`, - ); - return regex.source; - } - - return pattern; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/tuple.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/tuple.ts deleted file mode 100644 index 9a05c946c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/tuple.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { ZodTupleDef, ZodTupleItems, ZodTypeAny } from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; - -export type JsonSchema7TupleType = { - type: 'array'; - minItems: number; - items: JsonSchema7Type[]; -} & ( - | { - maxItems: number; - } - | { - additionalItems?: JsonSchema7Type; - } -); - -export function parseTupleDef( - def: ZodTupleDef, - refs: Refs, -): JsonSchema7TupleType { - if (def.rest) { - return { - type: 'array', - minItems: def.items.length, - items: def.items - .map((x, i) => - parseDef(x._def, { - ...refs, - currentPath: [...refs.currentPath, 'items', `${i}`], - }), - ) - .reduce( - (acc: JsonSchema7Type[], x) => (x === undefined ? acc : [...acc, x]), - [], - ), - additionalItems: parseDef(def.rest._def, { - ...refs, - currentPath: [...refs.currentPath, 'additionalItems'], - }), - }; - } else { - return { - type: 'array', - minItems: def.items.length, - maxItems: def.items.length, - items: def.items - .map((x, i) => - parseDef(x._def, { - ...refs, - currentPath: [...refs.currentPath, 'items', `${i}`], - }), - ) - .reduce( - (acc: JsonSchema7Type[], x) => (x === undefined ? acc : [...acc, x]), - [], - ), - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/undefined.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/undefined.ts deleted file mode 100644 index 0d18409fa..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/undefined.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { JsonSchema7AnyType, parseAnyDef } from './any'; - -export type JsonSchema7UndefinedType = { - not: JsonSchema7AnyType; -}; - -export function parseUndefinedDef(): JsonSchema7UndefinedType { - return { - not: parseAnyDef(), - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/union.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/union.ts deleted file mode 100644 index 35730ea1a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/union.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { - ZodDiscriminatedUnionDef, - ZodLiteralDef, - ZodTypeAny, - ZodUnionDef, -} from 'zod/v3'; -import { parseDef } from '../parse-def'; -import { JsonSchema7Type } from '../parse-types'; -import { Refs } from '../refs'; - -export const primitiveMappings = { - ZodString: 'string', - ZodNumber: 'number', - ZodBigInt: 'integer', - ZodBoolean: 'boolean', - ZodNull: 'null', -} as const; -type ZodPrimitive = keyof typeof primitiveMappings; -type JsonSchema7Primitive = - (typeof primitiveMappings)[keyof typeof primitiveMappings]; - -export type JsonSchema7UnionType = - | JsonSchema7PrimitiveUnionType - | JsonSchema7AnyOfType; - -type JsonSchema7PrimitiveUnionType = - | { - type: JsonSchema7Primitive | JsonSchema7Primitive[]; - } - | { - type: JsonSchema7Primitive | JsonSchema7Primitive[]; - enum: (string | number | bigint | boolean | null)[]; - }; - -type JsonSchema7AnyOfType = { - anyOf: JsonSchema7Type[]; -}; - -export function parseUnionDef( - def: ZodUnionDef | ZodDiscriminatedUnionDef, - refs: Refs, -): JsonSchema7PrimitiveUnionType | JsonSchema7AnyOfType | undefined { - const options: readonly ZodTypeAny[] = - def.options instanceof Map ? Array.from(def.options.values()) : def.options; - - // This blocks tries to look ahead a bit to produce nicer looking schemas with type array instead of anyOf. - if ( - options.every( - x => - x._def.typeName in primitiveMappings && - (!x._def.checks || !x._def.checks.length), - ) - ) { - // all types in union are primitive and lack checks, so might as well squash into {type: [...]} - - const types = options.reduce((types: JsonSchema7Primitive[], x) => { - const type = primitiveMappings[x._def.typeName as ZodPrimitive]; //Can be safely casted due to row 43 - return type && !types.includes(type) ? [...types, type] : types; - }, []); - - return { - type: types.length > 1 ? types : types[0], - }; - } else if ( - options.every(x => x._def.typeName === 'ZodLiteral' && !x.description) - ) { - // all options literals - - const types = options.reduce( - (acc: JsonSchema7Primitive[], x: { _def: ZodLiteralDef }) => { - const type = typeof x._def.value; - switch (type) { - case 'string': - case 'number': - case 'boolean': - return [...acc, type]; - case 'bigint': - return [...acc, 'integer' as const]; - case 'object': - if (x._def.value === null) return [...acc, 'null' as const]; - case 'symbol': - case 'undefined': - case 'function': - default: - return acc; - } - }, - [], - ); - - if (types.length === options.length) { - // all the literals are primitive, as far as null can be considered primitive - - const uniqueTypes = types.filter((x, i, a) => a.indexOf(x) === i); - return { - type: uniqueTypes.length > 1 ? uniqueTypes : uniqueTypes[0], - enum: options.reduce( - (acc, x) => { - return acc.includes(x._def.value) ? acc : [...acc, x._def.value]; - }, - [] as (string | number | bigint | boolean | null)[], - ), - }; - } - } else if (options.every(x => x._def.typeName === 'ZodEnum')) { - return { - type: 'string', - enum: options.reduce( - (acc: string[], x) => [ - ...acc, - ...x._def.values.filter((x: string) => !acc.includes(x)), - ], - [], - ), - }; - } - - return asAnyOf(def, refs); -} - -const asAnyOf = ( - def: ZodUnionDef | ZodDiscriminatedUnionDef, - refs: Refs, -): JsonSchema7PrimitiveUnionType | JsonSchema7AnyOfType | undefined => { - const anyOf = ( - (def.options instanceof Map - ? Array.from(def.options.values()) - : def.options) as any[] - ) - .map((x, i) => - parseDef(x._def, { - ...refs, - currentPath: [...refs.currentPath, 'anyOf', `${i}`], - }), - ) - .filter( - (x): x is JsonSchema7Type => - !!x && - (!refs.strictUnions || - (typeof x === 'object' && Object.keys(x).length > 0)), - ); - - return anyOf.length ? { anyOf } : undefined; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/unknown.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/unknown.ts deleted file mode 100644 index 946a367a4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/parsers/unknown.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { JsonSchema7AnyType, parseAnyDef } from './any'; - -export type JsonSchema7UnknownType = JsonSchema7AnyType; - -export function parseUnknownDef(): JsonSchema7UnknownType { - return parseAnyDef(); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/refs.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/refs.ts deleted file mode 100644 index b951d0581..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/refs.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { ZodTypeDef } from 'zod/v3'; -import { getDefaultOptions, Options } from './options'; -import { JsonSchema7Type } from './parse-types'; - -export type Refs = { - seen: Map; - currentPath: string[]; - propertyPath: string[] | undefined; -} & Options; - -export type Seen = { - def: ZodTypeDef; - path: string[]; - jsonSchema: JsonSchema7Type | undefined; -}; - -export const getRefs = (options?: string | Partial): Refs => { - const _options = getDefaultOptions(options); - const currentPath = - _options.name !== undefined - ? [..._options.basePath, _options.definitionPath, _options.name] - : _options.basePath; - return { - ..._options, - currentPath: currentPath, - propertyPath: undefined, - seen: new Map( - Object.entries(_options.definitions).map(([name, def]) => [ - def._def, - { - def: def._def, - path: [..._options.basePath, _options.definitionPath, name], - // Resolution of references will be forced even though seen, so it's ok that the schema is undefined here for now. - jsonSchema: undefined, - }, - ]), - ), - }; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/select-parser.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/select-parser.ts deleted file mode 100644 index b0ee33787..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/select-parser.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { ZodFirstPartyTypeKind } from 'zod/v3'; -import { parseAnyDef } from './parsers/any'; -import { parseArrayDef } from './parsers/array'; -import { parseBigintDef } from './parsers/bigint'; -import { parseBooleanDef } from './parsers/boolean'; -import { parseBrandedDef } from './parsers/branded'; -import { parseCatchDef } from './parsers/catch'; -import { parseDateDef } from './parsers/date'; -import { parseDefaultDef } from './parsers/default'; -import { parseEffectsDef } from './parsers/effects'; -import { parseEnumDef } from './parsers/enum'; -import { parseIntersectionDef } from './parsers/intersection'; -import { parseLiteralDef } from './parsers/literal'; -import { parseMapDef } from './parsers/map'; -import { parseNativeEnumDef } from './parsers/native-enum'; -import { parseNeverDef } from './parsers/never'; -import { parseNullDef } from './parsers/null'; -import { parseNullableDef } from './parsers/nullable'; -import { parseNumberDef } from './parsers/number'; -import { parseObjectDef } from './parsers/object'; -import { parseOptionalDef } from './parsers/optional'; -import { parsePipelineDef } from './parsers/pipeline'; -import { parsePromiseDef } from './parsers/promise'; -import { parseRecordDef } from './parsers/record'; -import { parseSetDef } from './parsers/set'; -import { parseStringDef } from './parsers/string'; -import { parseTupleDef } from './parsers/tuple'; -import { parseUndefinedDef } from './parsers/undefined'; -import { parseUnionDef } from './parsers/union'; -import { parseUnknownDef } from './parsers/unknown'; -import { Refs } from './refs'; -import { parseReadonlyDef } from './parsers/readonly'; -import { JsonSchema7Type } from './parse-types'; - -export type InnerDefGetter = () => any; - -export const selectParser = ( - def: any, - typeName: ZodFirstPartyTypeKind, - refs: Refs, -): JsonSchema7Type | undefined | InnerDefGetter => { - switch (typeName) { - case ZodFirstPartyTypeKind.ZodString: - return parseStringDef(def, refs); - case ZodFirstPartyTypeKind.ZodNumber: - return parseNumberDef(def); - case ZodFirstPartyTypeKind.ZodObject: - return parseObjectDef(def, refs); - case ZodFirstPartyTypeKind.ZodBigInt: - return parseBigintDef(def); - case ZodFirstPartyTypeKind.ZodBoolean: - return parseBooleanDef(); - case ZodFirstPartyTypeKind.ZodDate: - return parseDateDef(def, refs); - case ZodFirstPartyTypeKind.ZodUndefined: - return parseUndefinedDef(); - case ZodFirstPartyTypeKind.ZodNull: - return parseNullDef(); - case ZodFirstPartyTypeKind.ZodArray: - return parseArrayDef(def, refs); - case ZodFirstPartyTypeKind.ZodUnion: - case ZodFirstPartyTypeKind.ZodDiscriminatedUnion: - return parseUnionDef(def, refs); - case ZodFirstPartyTypeKind.ZodIntersection: - return parseIntersectionDef(def, refs); - case ZodFirstPartyTypeKind.ZodTuple: - return parseTupleDef(def, refs); - case ZodFirstPartyTypeKind.ZodRecord: - return parseRecordDef(def, refs); - case ZodFirstPartyTypeKind.ZodLiteral: - return parseLiteralDef(def); - case ZodFirstPartyTypeKind.ZodEnum: - return parseEnumDef(def); - case ZodFirstPartyTypeKind.ZodNativeEnum: - return parseNativeEnumDef(def); - case ZodFirstPartyTypeKind.ZodNullable: - return parseNullableDef(def, refs); - case ZodFirstPartyTypeKind.ZodOptional: - return parseOptionalDef(def, refs); - case ZodFirstPartyTypeKind.ZodMap: - return parseMapDef(def, refs); - case ZodFirstPartyTypeKind.ZodSet: - return parseSetDef(def, refs); - case ZodFirstPartyTypeKind.ZodLazy: - return () => (def as any).getter()._def; - case ZodFirstPartyTypeKind.ZodPromise: - return parsePromiseDef(def, refs); - case ZodFirstPartyTypeKind.ZodNaN: - case ZodFirstPartyTypeKind.ZodNever: - return parseNeverDef(); - case ZodFirstPartyTypeKind.ZodEffects: - return parseEffectsDef(def, refs); - case ZodFirstPartyTypeKind.ZodAny: - return parseAnyDef(); - case ZodFirstPartyTypeKind.ZodUnknown: - return parseUnknownDef(); - case ZodFirstPartyTypeKind.ZodDefault: - return parseDefaultDef(def, refs); - case ZodFirstPartyTypeKind.ZodBranded: - return parseBrandedDef(def, refs); - case ZodFirstPartyTypeKind.ZodReadonly: - return parseReadonlyDef(def, refs); - case ZodFirstPartyTypeKind.ZodCatch: - return parseCatchDef(def, refs); - case ZodFirstPartyTypeKind.ZodPipeline: - return parsePipelineDef(def, refs); - case ZodFirstPartyTypeKind.ZodFunction: - case ZodFirstPartyTypeKind.ZodVoid: - case ZodFirstPartyTypeKind.ZodSymbol: - return undefined; - default: - /* c8 ignore next */ - return ((_: never) => undefined)(typeName); - } -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/zod3-to-json-schema.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/zod3-to-json-schema.ts deleted file mode 100644 index 8eb2c3069..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/to-json-schema/zod3-to-json-schema/zod3-to-json-schema.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { ZodSchema } from 'zod/v3'; -import { Options } from './options'; -import { parseDef } from './parse-def'; -import { JsonSchema7Type } from './parse-types'; -import { getRefs } from './refs'; -import { parseAnyDef } from './parsers/any'; - -const zod3ToJsonSchema = ( - schema: ZodSchema, - options?: Partial | string, -): JsonSchema7Type & { - $schema?: string; - definitions?: { - [key: string]: JsonSchema7Type; - }; -} => { - const refs = getRefs(options); - - let definitions = - typeof options === 'object' && options.definitions - ? Object.entries(options.definitions).reduce( - (acc: { [key: string]: JsonSchema7Type }, [name, schema]) => ({ - ...acc, - [name]: - parseDef( - schema._def, - { - ...refs, - currentPath: [...refs.basePath, refs.definitionPath, name], - }, - true, - ) ?? parseAnyDef(), - }), - {}, - ) - : undefined; - - const name = - typeof options === 'string' - ? options - : options?.nameStrategy === 'title' - ? undefined - : options?.name; - - const main = - parseDef( - schema._def, - name === undefined - ? refs - : { - ...refs, - currentPath: [...refs.basePath, refs.definitionPath, name], - }, - false, - ) ?? (parseAnyDef() as JsonSchema7Type); - - const title = - typeof options === 'object' && - options.name !== undefined && - options.nameStrategy === 'title' - ? options.name - : undefined; - - if (title !== undefined) { - main.title = title; - } - - const combined: ReturnType = - name === undefined - ? definitions - ? { - ...main, - [refs.definitionPath]: definitions, - } - : main - : { - $ref: [ - ...(refs.$refStrategy === 'relative' ? [] : refs.basePath), - refs.definitionPath, - name, - ].join('/'), - [refs.definitionPath]: { - ...definitions, - [name]: main, - }, - }; - - combined.$schema = 'http://json-schema.org/draft-07/schema#'; - - return combined; -}; - -export { zod3ToJsonSchema }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/assistant-model-message.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/assistant-model-message.ts deleted file mode 100644 index 9f0a02cac..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/assistant-model-message.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - FilePart, - ReasoningPart, - TextPart, - ToolCallPart, - ToolResultPart, -} from './content-part'; -import { ProviderOptions } from './provider-options'; -import { ToolApprovalRequest } from './tool-approval-request'; - -/** - * An assistant message. It can contain text, tool calls, or a combination of text and tool calls. - */ -export type AssistantModelMessage = { - role: 'assistant'; - content: AssistantContent; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; -}; - -/** - * Content of an assistant message. - * It can be a string or an array of text, image, reasoning, redacted reasoning, and tool call parts. - */ -export type AssistantContent = - | string - | Array< - | TextPart - | FilePart - | ReasoningPart - | ToolCallPart - | ToolResultPart - | ToolApprovalRequest - >; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/content-part.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/content-part.ts deleted file mode 100644 index 92fb6e239..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/content-part.ts +++ /dev/null @@ -1,379 +0,0 @@ -import { JSONValue } from '@ai-sdk/provider'; -import { DataContent } from './data-content'; -import { ProviderOptions } from './provider-options'; - -/** - * Text content part of a prompt. It contains a string of text. - */ -export interface TextPart { - type: 'text'; - - /** - * The text content. - */ - text: string; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; -} - -/** - * Image content part of a prompt. It contains an image. - */ -export interface ImagePart { - type: 'image'; - - /** - * Image data. Can either be: - * - * - data: a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer - * - URL: a URL that points to the image - */ - image: DataContent | URL; - - /** - * Optional IANA media type of the image. - * - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType?: string; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; -} - -/** - * File content part of a prompt. It contains a file. - */ -export interface FilePart { - type: 'file'; - - /** - * File data. Can either be: - * - * - data: a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer - * - URL: a URL that points to the image - */ - data: DataContent | URL; - - /** - * Optional filename of the file. - */ - filename?: string; - - /** - * IANA media type of the file. - * - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; -} - -/** - * Reasoning content part of a prompt. It contains a reasoning. - */ -export interface ReasoningPart { - type: 'reasoning'; - - /** - * The reasoning text. - */ - text: string; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; -} - -/** - * Tool call content part of a prompt. It contains a tool call (usually generated by the AI model). - */ -export interface ToolCallPart { - type: 'tool-call'; - - /** - * ID of the tool call. This ID is used to match the tool call with the tool result. - */ - toolCallId: string; - - /** - * Name of the tool that is being called. - */ - toolName: string; - - /** - * Arguments of the tool call. This is a JSON-serializable object that matches the tool's input schema. - */ - input: unknown; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; - - /** - * Whether the tool call was executed by the provider. - */ - providerExecuted?: boolean; -} - -/** - * Tool result content part of a prompt. It contains the result of the tool call with the matching ID. - */ -export interface ToolResultPart { - type: 'tool-result'; - - /** - * ID of the tool call that this result is associated with. - */ - toolCallId: string; - - /** - * Name of the tool that generated this result. - */ - toolName: string; - - /** - * Result of the tool call. This is a JSON-serializable object. - */ - output: ToolResultOutput; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; -} - -/** - * Output of a tool result. - */ -export type ToolResultOutput = - | { - /** - * Text tool output that should be directly sent to the API. - */ - type: 'text'; - value: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - type: 'json'; - value: JSONValue; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - /** - * Type when the user has denied the execution of the tool call. - */ - type: 'execution-denied'; - - /** - * Optional reason for the execution denial. - */ - reason?: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - type: 'error-text'; - value: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - type: 'error-json'; - value: JSONValue; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - type: 'content'; - value: Array< - | { - type: 'text'; - - /** - * Text content. - */ - text: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - /** - * @deprecated Use image-data or file-data instead. - */ - type: 'media'; - data: string; - mediaType: string; - } - | { - type: 'file-data'; - - /** - * Base-64 encoded media data. - */ - data: string; - - /** - * IANA media type. - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Optional filename of the file. - */ - filename?: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - type: 'file-url'; - - /** - * URL of the file. - */ - url: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - type: 'file-id'; - - /** - * ID of the file. - * - * If you use multiple providers, you need to - * specify the provider specific ids using - * the Record option. The key is the provider - * name, e.g. 'openai' or 'anthropic'. - */ - fileId: string | Record; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - /** - * Images that are referenced using base64 encoded data. - */ - type: 'image-data'; - - /** - * Base-64 encoded image data. - */ - data: string; - - /** - * IANA media type. - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - /** - * Images that are referenced using a URL. - */ - type: 'image-url'; - - /** - * URL of the image. - */ - url: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - /** - * Images that are referenced using a provider file id. - */ - type: 'image-file-id'; - - /** - * Image that is referenced using a provider file id. - * - * If you use multiple providers, you need to - * specify the provider specific ids using - * the Record option. The key is the provider - * name, e.g. 'openai' or 'anthropic'. - */ - fileId: string | Record; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - /** - * Custom content part. This can be used to implement - * provider-specific content parts. - */ - type: 'custom'; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - >; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/data-content.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/data-content.ts deleted file mode 100644 index f36d785e5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/data-content.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Data content. Can either be a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer. - */ -export type DataContent = string | Uint8Array | ArrayBuffer | Buffer; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/execute-tool.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/execute-tool.ts deleted file mode 100644 index 7780d582f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/execute-tool.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { isAsyncIterable } from '../is-async-iterable'; -import { ToolExecutionOptions, ToolExecuteFunction } from './tool'; - -export async function* executeTool({ - execute, - input, - options, -}: { - execute: ToolExecuteFunction; - input: INPUT; - options: ToolExecutionOptions; -}): AsyncGenerator< - { type: 'preliminary'; output: OUTPUT } | { type: 'final'; output: OUTPUT } -> { - const result = execute(input, options); - - if (isAsyncIterable(result)) { - let lastOutput: OUTPUT | undefined; - for await (const output of result) { - lastOutput = output; - yield { type: 'preliminary', output }; - } - yield { type: 'final', output: lastOutput! }; - } else { - yield { type: 'final', output: await result }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/index.ts deleted file mode 100644 index 7cb7fb0e3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -export type { - AssistantContent, - AssistantModelMessage, -} from './assistant-model-message'; -export type { - FilePart, - ImagePart, - ReasoningPart, - TextPart, - ToolCallPart, - ToolResultOutput, - ToolResultPart, -} from './content-part'; -export type { DataContent } from './data-content'; -export { executeTool } from './execute-tool'; -export type { ModelMessage } from './model-message'; -export type { ProviderOptions } from './provider-options'; -export type { SystemModelMessage } from './system-model-message'; -export { - dynamicTool, - tool, - type InferToolInput, - type InferToolOutput, - type Tool, - type ToolExecutionOptions, - type ToolExecuteFunction, - type ToolNeedsApprovalFunction, -} from './tool'; -export type { ToolApprovalRequest } from './tool-approval-request'; -export type { ToolApprovalResponse } from './tool-approval-response'; -export type { ToolCall } from './tool-call'; -export type { ToolContent, ToolModelMessage } from './tool-model-message'; -export type { ToolResult } from './tool-result'; -export type { UserContent, UserModelMessage } from './user-model-message'; -import type { ToolExecutionOptions } from './tool'; - -/** - * @deprecated Use ToolExecutionOptions instead. - */ -export type ToolCallOptions = ToolExecutionOptions; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/model-message.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/model-message.ts deleted file mode 100644 index b0c5dda37..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/model-message.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { AssistantModelMessage } from './assistant-model-message'; -import { SystemModelMessage } from './system-model-message'; -import { ToolModelMessage } from './tool-model-message'; -import { UserModelMessage } from './user-model-message'; - -/** - * A message that can be used in the `messages` field of a prompt. - * It can be a user message, an assistant message, or a tool message. - */ -export type ModelMessage = - | SystemModelMessage - | UserModelMessage - | AssistantModelMessage - | ToolModelMessage; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/provider-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/provider-options.ts deleted file mode 100644 index 8260c7ab2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/provider-options.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { SharedV3ProviderOptions } from '@ai-sdk/provider'; - -/** - * Additional provider-specific options. - * - * They are passed through to the provider from the AI SDK and enable - * provider-specific functionality that can be fully encapsulated in the provider. - */ -export type ProviderOptions = SharedV3ProviderOptions; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/system-model-message.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/system-model-message.ts deleted file mode 100644 index b35af571c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/system-model-message.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ProviderOptions } from './provider-options'; - -/** - * A system message. It can contain system information. - * - * Note: using the "system" part of the prompt is strongly preferred - * to increase the resilience against prompt injection attacks, - * and because not all providers support several system messages. - */ -export type SystemModelMessage = { - role: 'system'; - content: string; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-approval-request.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-approval-request.ts deleted file mode 100644 index 25d390bc5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-approval-request.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Tool approval request prompt part. - */ -export type ToolApprovalRequest = { - type: 'tool-approval-request'; - - /** - * ID of the tool approval. - */ - approvalId: string; - - /** - * ID of the tool call that the approval request is for. - */ - toolCallId: string; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-approval-response.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-approval-response.ts deleted file mode 100644 index 494bd5a4f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-approval-response.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Tool approval response prompt part. - */ -export type ToolApprovalResponse = { - type: 'tool-approval-response'; - - /** - * ID of the tool approval. - */ - approvalId: string; - - /** - * Flag indicating whether the approval was granted or denied. - */ - approved: boolean; - - /** - * Optional reason for the approval or denial. - */ - reason?: string; - - /** - * Flag indicating whether the tool call is provider-executed. - * Only provider-executed tool approval responses should be sent to the model. - */ - providerExecuted?: boolean; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-call.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-call.ts deleted file mode 100644 index fb5919ab3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-call.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Typed tool call that is returned by generateText and streamText. - * It contains the tool call ID, the tool name, and the tool arguments. - */ -export interface ToolCall { - /** - * ID of the tool call. This ID is used to match the tool call with the tool result. - */ - toolCallId: string; - - /** - * Name of the tool that is being called. - */ - toolName: NAME; - - /** - * Arguments of the tool call. This is a JSON-serializable object that matches the tool's input schema. - */ - input: INPUT; - - /** - * Whether the tool call will be executed by the provider. - * If this flag is not set or is false, the tool call will be executed by the client. - */ - providerExecuted?: boolean; - - /** - * Whether the tool is dynamic. - */ - dynamic?: boolean; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-model-message.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-model-message.ts deleted file mode 100644 index 777d10f8b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-model-message.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ToolResultPart } from './content-part'; -import { ProviderOptions } from './provider-options'; -import { ToolApprovalResponse } from './tool-approval-response'; - -/** - * A tool message. It contains the result of one or more tool calls. - */ -export type ToolModelMessage = { - role: 'tool'; - content: ToolContent; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; -}; - -/** - * Content of a tool message. It is an array of tool result parts. - */ -export type ToolContent = Array; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-result.ts deleted file mode 100644 index c54028dac..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool-result.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Typed tool result that is returned by `generateText` and `streamText`. - * It contains the tool call ID, the tool name, the tool arguments, and the tool result. - */ -export interface ToolResult { - /** - * ID of the tool call. This ID is used to match the tool call with the tool result. - */ - toolCallId: string; - - /** - * Name of the tool that was called. - */ - toolName: NAME; - - /** - * Arguments of the tool call. This is a JSON-serializable object that matches the tool's input schema. - */ - input: INPUT; - - /** - * Result of the tool call. This is the result of the tool's execution. - */ - output: OUTPUT; - - /** - * Whether the tool result has been executed by the provider. - */ - providerExecuted?: boolean; - - /** - * Whether the tool is dynamic. - */ - dynamic?: boolean; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool.ts deleted file mode 100644 index b07089fe2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/tool.ts +++ /dev/null @@ -1,324 +0,0 @@ -import { JSONValue } from '@ai-sdk/provider'; -import { FlexibleSchema } from '../schema'; -import { ToolResultOutput } from './content-part'; -import { ModelMessage } from './model-message'; -import { ProviderOptions } from './provider-options'; - -/** - * Additional options that are sent into each tool call. - */ -export interface ToolExecutionOptions { - /** - * The ID of the tool call. You can use it e.g. when sending tool-call related information with stream data. - */ - toolCallId: string; - - /** - * Messages that were sent to the language model to initiate the response that contained the tool call. - * The messages **do not** include the system prompt nor the assistant response that contained the tool call. - */ - messages: ModelMessage[]; - - /** - * An optional abort signal that indicates that the overall operation should be aborted. - */ - abortSignal?: AbortSignal; - - /** - * User-defined context. - * - * Treat the context object as immutable inside tools. - * Mutating the context object can lead to race conditions and unexpected results - * when tools are called in parallel. - * - * If you need to mutate the context, analyze the tool calls and results - * in `prepareStep` and update it there. - * - * Experimental (can break in patch releases). - */ - experimental_context?: unknown; -} - -/** - * Function that is called to determine if the tool needs approval before it can be executed. - */ -export type ToolNeedsApprovalFunction = ( - input: INPUT, - options: { - /** - * The ID of the tool call. You can use it e.g. when sending tool-call related information with stream data. - */ - toolCallId: string; - - /** - * Messages that were sent to the language model to initiate the response that contained the tool call. - * The messages **do not** include the system prompt nor the assistant response that contained the tool call. - */ - messages: ModelMessage[]; - - /** - * Additional context. - * - * Experimental (can break in patch releases). - */ - experimental_context?: unknown; - }, -) => boolean | PromiseLike; - -export type ToolExecuteFunction = ( - input: INPUT, - options: ToolExecutionOptions, -) => AsyncIterable | PromiseLike | OUTPUT; - -// 0 extends 1 & N checks for any -// [N] extends [never] checks for never -type NeverOptional = 0 extends 1 & N - ? Partial - : [N] extends [never] - ? Partial> - : T; - -type ToolOutputProperties = NeverOptional< - OUTPUT, - | { - /** - * An async function that is called with the arguments from the tool call and produces a result. - * If not provided, the tool will not be executed automatically. - * - * @args is the input of the tool call. - * @options.abortSignal is a signal that can be used to abort the tool call. - */ - execute: ToolExecuteFunction; - - outputSchema?: FlexibleSchema; - } - | { - outputSchema: FlexibleSchema; - - execute?: never; - } ->; - -/** - * A tool contains the description and the schema of the input that the tool expects. - * This enables the language model to generate the input. - * - * The tool can also contain an optional execute function for the actual execution function of the tool. - */ -export type Tool< - INPUT extends JSONValue | unknown | never = any, - OUTPUT extends JSONValue | unknown | never = any, -> = { - /** - * An optional description of what the tool does. - * Will be used by the language model to decide whether to use the tool. - * Not used for provider-defined tools. - */ - description?: string; - - /** - * An optional title of the tool. - */ - title?: string; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; - - /** - * The schema of the input that the tool expects. - * The language model will use this to generate the input. - * It is also used to validate the output of the language model. - * - * You can use descriptions on the schema properties to make the input understandable for the language model. - */ - inputSchema: FlexibleSchema; - - /** - * An optional list of input examples that show the language - * model what the input should look like. - */ - inputExamples?: Array<{ input: NoInfer }>; - - /** - * Whether the tool needs approval before it can be executed. - */ - needsApproval?: - | boolean - | ToolNeedsApprovalFunction<[INPUT] extends [never] ? unknown : INPUT>; - - /** - * Strict mode setting for the tool. - * - * Providers that support strict mode will use this setting to determine - * how the input should be generated. Strict mode will always produce - * valid inputs, but it might limit what input schemas are supported. - */ - strict?: boolean; - - /** - * Optional function that is called when the argument streaming starts. - * Only called when the tool is used in a streaming context. - */ - onInputStart?: (options: ToolExecutionOptions) => void | PromiseLike; - - /** - * Optional function that is called when an argument streaming delta is available. - * Only called when the tool is used in a streaming context. - */ - onInputDelta?: ( - options: { inputTextDelta: string } & ToolExecutionOptions, - ) => void | PromiseLike; - - /** - * Optional function that is called when a tool call can be started, - * even if the execute function is not provided. - */ - onInputAvailable?: ( - options: { - input: [INPUT] extends [never] ? unknown : INPUT; - } & ToolExecutionOptions, - ) => void | PromiseLike; -} & ToolOutputProperties & { - /** - * Optional conversion function that maps the tool result to an output that can be used by the language model. - * - * If not provided, the tool result will be sent as a JSON object. - */ - toModelOutput?: (options: { - /** - * The ID of the tool call. You can use it e.g. when sending tool-call related information with stream data. - */ - toolCallId: string; - - /** - * The input of the tool call. - */ - input: [INPUT] extends [never] ? unknown : INPUT; - - /** - * The output of the tool call. - */ - output: 0 extends 1 & OUTPUT - ? any - : [OUTPUT] extends [never] - ? any - : NoInfer; - }) => ToolResultOutput | PromiseLike; - } & ( - | { - /** - * Tool with user-defined input and output schemas. - */ - type?: undefined | 'function'; - } - | { - /** - * Tool that is defined at runtime (e.g. an MCP tool). - * The types of input and output are not known at development time. - */ - type: 'dynamic'; - } - | { - /** - * Tool with provider-defined input and output schemas. - */ - type: 'provider'; - - /** - * The ID of the tool. Must follow the format `.`. - */ - id: `${string}.${string}`; - - /** - * The arguments for configuring the tool. Must match the expected arguments defined by the provider for this tool. - */ - args: Record; - - /** - * Whether this provider-executed tool supports deferred results. - * - * When true, the tool result may not be returned in the same turn as the - * tool call (e.g., when using programmatic tool calling where a server tool - * triggers a client-executed tool, and the server tool's result is deferred - * until the client tool is resolved). - * - * This flag allows the AI SDK to handle tool results that arrive without - * a matching tool call in the current response. - * - * @default false - */ - supportsDeferredResults?: boolean; - } - ); - -/** - * Infer the input type of a tool. - */ -export type InferToolInput = - TOOL extends Tool ? INPUT : never; - -/** - * Infer the output type of a tool. - */ -export type InferToolOutput = - TOOL extends Tool ? OUTPUT : never; - -/** - * Helper function for inferring the execute args of a tool. - */ -// Note: overload order is important for auto-completion -export function tool( - tool: Tool, -): Tool; -export function tool(tool: Tool): Tool; -export function tool(tool: Tool): Tool; -export function tool(tool: Tool): Tool; -export function tool(tool: any): any { - return tool; -} - -/** - * Defines a dynamic tool. - */ -export function dynamicTool(tool: { - description?: string; - title?: string; - providerOptions?: ProviderOptions; - inputSchema: FlexibleSchema; - execute: ToolExecuteFunction; - - /** - * Optional conversion function that maps the tool result to an output that can be used by the language model. - * - * If not provided, the tool result will be sent as a JSON object. - */ - toModelOutput?: (options: { - /** - * The ID of the tool call. You can use it e.g. when sending tool-call related information with stream data. - */ - toolCallId: string; - - /** - * The input of the tool call. - */ - input: unknown; - - /** - * The output of the tool call. - */ - output: unknown; - }) => ToolResultOutput | PromiseLike; - - /** - * Whether the tool needs approval before it can be executed. - */ - needsApproval?: boolean | ToolNeedsApprovalFunction; -}): Tool & { - type: 'dynamic'; -} { - return { ...tool, type: 'dynamic' }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/user-model-message.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/user-model-message.ts deleted file mode 100644 index 04ac1bf33..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/types/user-model-message.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { FilePart, ImagePart, TextPart } from './content-part'; -import { ProviderOptions } from './provider-options'; - -/** - * A user message. It can contain text or a combination of text and images. - */ -export type UserModelMessage = { - role: 'user'; - content: UserContent; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; -}; - -/** - * Content of a user message. It can be a string or an array of text and image parts. - */ -export type UserContent = string | Array; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/uint8-utils.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/uint8-utils.ts deleted file mode 100644 index b8063097d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/uint8-utils.ts +++ /dev/null @@ -1,26 +0,0 @@ -// btoa and atob need to be invoked as a function call, not as a method call. -// Otherwise CloudFlare will throw a -// "TypeError: Illegal invocation: function called with incorrect this reference" -const { btoa, atob } = globalThis; - -export function convertBase64ToUint8Array(base64String: string) { - const base64Url = base64String.replace(/-/g, '+').replace(/_/g, '/'); - const latin1string = atob(base64Url); - return Uint8Array.from(latin1string, byte => byte.codePointAt(0)!); -} - -export function convertUint8ArrayToBase64(array: Uint8Array): string { - let latin1string = ''; - - // Note: regular for loop to support older JavaScript versions that - // do not support for..of on Uint8Array - for (let i = 0; i < array.length; i++) { - latin1string += String.fromCodePoint(array[i]); - } - - return btoa(latin1string); -} - -export function convertToBase64(value: string | Uint8Array): string { - return value instanceof Uint8Array ? convertUint8ArrayToBase64(value) : value; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/validate-download-url.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/validate-download-url.ts deleted file mode 100644 index 7c026ad6b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/validate-download-url.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { DownloadError } from './download-error'; - -/** - * Validates that a URL is safe to download from, blocking private/internal addresses - * to prevent SSRF attacks. - * - * @param url - The URL string to validate. - * @throws DownloadError if the URL is unsafe. - */ -export function validateDownloadUrl(url: string): void { - let parsed: URL; - try { - parsed = new URL(url); - } catch { - throw new DownloadError({ - url, - message: `Invalid URL: ${url}`, - }); - } - - // Only allow http and https protocols - if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') { - throw new DownloadError({ - url, - message: `URL scheme must be http or https, got ${parsed.protocol}`, - }); - } - - const hostname = parsed.hostname; - - // Block empty hostname - if (!hostname) { - throw new DownloadError({ - url, - message: `URL must have a hostname`, - }); - } - - // Block localhost and .local domains - if ( - hostname === 'localhost' || - hostname.endsWith('.local') || - hostname.endsWith('.localhost') - ) { - throw new DownloadError({ - url, - message: `URL with hostname ${hostname} is not allowed`, - }); - } - - // Check for IPv6 addresses (enclosed in brackets in URLs) - if (hostname.startsWith('[') && hostname.endsWith(']')) { - const ipv6 = hostname.slice(1, -1); - if (isPrivateIPv6(ipv6)) { - throw new DownloadError({ - url, - message: `URL with IPv6 address ${hostname} is not allowed`, - }); - } - return; - } - - // Check for IPv4 addresses - if (isIPv4(hostname)) { - if (isPrivateIPv4(hostname)) { - throw new DownloadError({ - url, - message: `URL with IP address ${hostname} is not allowed`, - }); - } - return; - } -} - -function isIPv4(hostname: string): boolean { - const parts = hostname.split('.'); - if (parts.length !== 4) return false; - return parts.every(part => { - const num = Number(part); - return ( - Number.isInteger(num) && num >= 0 && num <= 255 && String(num) === part - ); - }); -} - -function isPrivateIPv4(ip: string): boolean { - const parts = ip.split('.').map(Number); - const [a, b] = parts; - - // 0.0.0.0/8 - if (a === 0) return true; - // 10.0.0.0/8 - if (a === 10) return true; - // 127.0.0.0/8 - if (a === 127) return true; - // 169.254.0.0/16 - if (a === 169 && b === 254) return true; - // 172.16.0.0/12 - if (a === 172 && b >= 16 && b <= 31) return true; - // 192.168.0.0/16 - if (a === 192 && b === 168) return true; - - return false; -} - -function isPrivateIPv6(ip: string): boolean { - const normalized = ip.toLowerCase(); - - // ::1 (loopback) - if (normalized === '::1') return true; - // :: (unspecified) - if (normalized === '::') return true; - - // Check for IPv4-mapped addresses (::ffff:x.x.x.x or ::ffff:HHHH:HHHH) - if (normalized.startsWith('::ffff:')) { - const mappedPart = normalized.slice(7); - // Dotted-decimal form: ::ffff:127.0.0.1 - if (isIPv4(mappedPart)) { - return isPrivateIPv4(mappedPart); - } - // Hex form: ::ffff:7f00:1 (URL parser normalizes to this) - const hexParts = mappedPart.split(':'); - if (hexParts.length === 2) { - const high = parseInt(hexParts[0], 16); - const low = parseInt(hexParts[1], 16); - if (!isNaN(high) && !isNaN(low)) { - const a = (high >> 8) & 0xff; - const b = high & 0xff; - const c = (low >> 8) & 0xff; - const d = low & 0xff; - return isPrivateIPv4(`${a}.${b}.${c}.${d}`); - } - } - } - - // fc00::/7 (unique local addresses - fc00:: and fd00::) - if (normalized.startsWith('fc') || normalized.startsWith('fd')) return true; - - // fe80::/10 (link-local) - if (normalized.startsWith('fe80')) return true; - - return false; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/validate-types.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/validate-types.ts deleted file mode 100644 index 80abb4d8f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/validate-types.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { TypeValidationContext, TypeValidationError } from '@ai-sdk/provider'; -import { FlexibleSchema, asSchema } from './schema'; - -/** - * Validates the types of an unknown object using a schema and - * return a strongly-typed object. - * - * @template T - The type of the object to validate. - * @param {string} options.value - The object to validate. - * @param {Validator} options.schema - The schema to use for validating the JSON. - * @param {TypeValidationContext} options.context - Optional context about what is being validated. - * @returns {Promise} - The typed object. - */ -export async function validateTypes({ - value, - schema, - context, -}: { - value: unknown; - schema: FlexibleSchema; - context?: TypeValidationContext; -}): Promise { - const result = await safeValidateTypes({ value, schema, context }); - - if (!result.success) { - throw TypeValidationError.wrap({ value, cause: result.error, context }); - } - - return result.value; -} - -/** - * Safely validates the types of an unknown object using a schema and - * return a strongly-typed object. - * - * @template T - The type of the object to validate. - * @param {string} options.value - The JSON object to validate. - * @param {Validator} options.schema - The schema to use for validating the JSON. - * @param {TypeValidationContext} options.context - Optional context about what is being validated. - * @returns An object with either a `success` flag and the parsed and typed data, or a `success` flag and an error object. - */ -export async function safeValidateTypes({ - value, - schema, - context, -}: { - value: unknown; - schema: FlexibleSchema; - context?: TypeValidationContext; -}): Promise< - | { - success: true; - value: OBJECT; - rawValue: unknown; - } - | { - success: false; - error: TypeValidationError; - rawValue: unknown; - } -> { - const actualSchema = asSchema(schema); - - try { - if (actualSchema.validate == null) { - return { success: true, value: value as OBJECT, rawValue: value }; - } - - const result = await actualSchema.validate(value); - - if (result.success) { - return { success: true, value: result.value, rawValue: value }; - } - - return { - success: false, - error: TypeValidationError.wrap({ value, cause: result.error, context }), - rawValue: value, - }; - } catch (error) { - return { - success: false, - error: TypeValidationError.wrap({ value, cause: error, context }), - rawValue: value, - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/version.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/version.ts deleted file mode 100644 index 7a35d46f5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/version.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Version string of this package injected at build time. -declare const __PACKAGE_VERSION__: string | undefined; -export const VERSION: string = - typeof __PACKAGE_VERSION__ !== 'undefined' - ? __PACKAGE_VERSION__ - : '0.0.0-test'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/with-user-agent-suffix.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/with-user-agent-suffix.ts deleted file mode 100644 index 999795898..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/with-user-agent-suffix.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { normalizeHeaders } from './normalize-headers'; - -/** - * Appends suffix parts to the `user-agent` header. - * If a `user-agent` header already exists, the suffix parts are appended to it. - * If no `user-agent` header exists, a new one is created with the suffix parts. - * Automatically removes undefined entries from the headers. - * - * @param headers - The original headers. - * @param userAgentSuffixParts - The parts to append to the `user-agent` header. - * @returns The new headers with the `user-agent` header set or updated. - */ -export function withUserAgentSuffix( - headers: HeadersInit | Record | undefined, - ...userAgentSuffixParts: string[] -): Record { - const normalizedHeaders = new Headers(normalizeHeaders(headers)); - - const currentUserAgentHeader = normalizedHeaders.get('user-agent') || ''; - - normalizedHeaders.set( - 'user-agent', - [currentUserAgentHeader, ...userAgentSuffixParts].filter(Boolean).join(' '), - ); - - return Object.fromEntries(normalizedHeaders.entries()); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/without-trailing-slash.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/without-trailing-slash.ts deleted file mode 100644 index 8d2ec1c04..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/src/without-trailing-slash.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function withoutTrailingSlash(url: string | undefined) { - return url?.replace(/\/$/, ''); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/test.d.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/test.d.ts deleted file mode 100644 index 990366a86..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider-utils/test.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/test'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/CHANGELOG.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/CHANGELOG.md deleted file mode 100644 index d8779066e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/CHANGELOG.md +++ /dev/null @@ -1,979 +0,0 @@ -# @ai-sdk/provider - -## 3.0.8 - -### Patch Changes - -- 7168375: feat (ai, provider): default global provider video model resolution - -## 3.0.7 - -### Patch Changes - -- 53f6731: feat (ai, provider): experimental generate video support - -## 3.0.6 - -### Patch Changes - -- 2810850: fix(ai): improve type validation error messages with field paths and entity identifiers - -## 3.0.5 - -### Patch Changes - -- 4de5a1d: chore: excluded tests from src folder in npm package - -## 3.0.4 - -### Patch Changes - -- 5c090e7: fix(ai): fix LanguageModelV2ProviderTool type - -## 3.0.3 - -### Patch Changes - -- 1b11dcb: chore(ai): include sources in npm package - -## 3.0.2 - -### Patch Changes - -- d937c8f: Add Image model middleware support via `wrapImageModel` and `ImageModelV3Middleware`. - -## 3.0.1 - -### Patch Changes - -- 863d34f: fix: trigger release to update `@latest` - -## 3.0.0 - -### Major Changes - -- dee8b05: ai SDK 6 beta - -### Minor Changes - -- 78928cb: release: start 5.1 beta - -### Patch Changes - -- 0c3b58b: fix(provider): add specificationVersion to ProviderV3 -- 0adc679: feat(provider): shared spec v3 -- d1bdadb: Added reranking model -- 046aa3b: feat(provider): speech model v3 spec -- 8d9e8ad: chore(provider): remove generics from EmbeddingModelV3 - - Before - - ```ts - model.textEmbeddingModel('my-model-id'); - ``` - - After - - ```ts - model.embeddingModel('my-model-id'); - ``` - -- dce03c4: feat: tool input examples -- 2625a04: feat(openai); update spec for mcp approval -- 37c58a0: This release introduces `wrapEmbeddingModel`, a new helper that brings embedding model customization capabilities similar to `wrapLanguageModel`. -- 2b0caef: feat(provider): add preliminary provider executed tool results to language model specification -- 954c356: feat(openai): allow custom names for provider-defined tools -- 544d4e8: chore(specification): rename v3 provider defined tool to provider tool -- 0c4822d: feat: `EmbeddingModelV3` -- 4c44a5b: fix(spec): allow `undefined` values in `JSONObject` type -- e8109d3: feat: tool execution approval -- ed329cb: feat: `Provider-V3` -- 53f3368: feat(provider): support embedding model call warnings in specification -- 3bd2689: feat: extended token usage -- bb36798: fix(spec): `LanguageModelV3ToolResult["result"]` change from `unknown` to `NonNullable` -- 8dac895: feat: `LanguageModelV3` -- a755db5: feat(provider): Add SharedV3Warning type -- 475189e: chore(specification): rename EmbeddingModelCallOptions -- 457318b: chore(provider,ai): switch to SharedV3Warning and unified warnings -- b681d7d: feat: expose usage tokens for 'generateImage' function -- db913bd: fix(google): add thought signature to gemini 3 pro image parts -- 9061dc0: feat: image editing -- 366f50b: chore(provider): add deprecated textEmbeddingModel and textEmbedding aliases -- 81d4308: feat: provider-executed dynamic tools -- 9549c9e: chore(specification): extract types -- af3780b: chore(provider): remove providerExecuted from LanguageModelV3ToolResult -- 522f6b8: feat: `ImageModelV3` -- 10d819b: fix(packages/provider): fix CallWarning and allow strings as type -- 3794514: feat: flexible tool output content support -- cbf52cd: feat: expose raw finish reason -- 1bd7d32: feat: tool-specific strict mode - -## 3.0.0-beta.32 - -### Patch Changes - -- 475189e: chore(specification): rename EmbeddingModelCallOptions - -## 3.0.0-beta.31 - -### Patch Changes - -- 2625a04: feat(openai); update spec for mcp approval - -## 3.0.0-beta.30 - -### Patch Changes - -- cbf52cd: feat: expose raw finish reason - -## 3.0.0-beta.29 - -### Patch Changes - -- 9549c9e: chore(specification): extract types - -## 3.0.0-beta.28 - -### Patch Changes - -- 9061dc0: feat: image editing - -## 3.0.0-beta.27 - -### Patch Changes - -- 366f50b: chore(provider): add deprecated textEmbeddingModel and textEmbedding aliases - -## 3.0.0-beta.26 - -### Patch Changes - -- 3bd2689: feat: extended token usage - -## 3.0.0-beta.25 - -### Patch Changes - -- 53f3368: feat(provider): support embedding model call warnings in specification - -## 3.0.0-beta.24 - -### Patch Changes - -- dce03c4: feat: tool input examples - -## 3.0.0-beta.23 - -### Patch Changes - -- 1bd7d32: feat: tool-specific strict mode - -## 3.0.0-beta.22 - -### Patch Changes - -- 544d4e8: chore(specification): rename v3 provider defined tool to provider tool - -## 3.0.0-beta.21 - -### Patch Changes - -- 954c356: feat(openai): allow custom names for provider-defined tools - -## 3.0.0-beta.20 - -### Patch Changes - -- 457318b: chore(provider,ai): switch to SharedV3Warning and unified warnings - -## 3.0.0-beta.19 - -### Patch Changes - -- 8d9e8ad: chore(provider): remove generics from EmbeddingModelV3 - - Before - - ```ts - model.textEmbeddingModel('my-model-id'); - ``` - - After - - ```ts - model.embeddingModel('my-model-id'); - ``` - -## 3.0.0-beta.18 - -### Patch Changes - -- 10d819b: fix(packages/provider): fix CallWarning and allow strings as type - -## 3.0.0-beta.17 - -### Patch Changes - -- db913bd: fix(google): add thought signature to gemini 3 pro image parts - -## 3.0.0-beta.16 - -### Patch Changes - -- b681d7d: feat: expose usage tokens for 'generateImage' function - -## 3.0.0-beta.15 - -### Patch Changes - -- bb36798: fix(spec): `LanguageModelV3ToolResult["result"]` change from `unknown` to `NonNullable` - -## 3.0.0-beta.14 - -### Patch Changes - -- af3780b: chore(provider): remove providerExecuted from LanguageModelV3ToolResult - -## 3.0.0-beta.13 - -### Patch Changes - -- 37c58a0: This release introduces `wrapEmbeddingModel`, a new helper that brings embedding model customization capabilities similar to `wrapLanguageModel`. - -## 3.0.0-beta.12 - -### Patch Changes - -- d1bdadb: Added reranking model - -## 3.0.0-beta.11 - -### Patch Changes - -- 4c44a5b: fix(spec): allow `undefined` values in `JSONObject` type - -## 3.0.0-beta.10 - -### Patch Changes - -- 0c3b58b: fix(provider): add specificationVersion to ProviderV3 - -## 3.0.0-beta.9 - -### Patch Changes - -- a755db5: feat(provider): Add SharedV3Warning type - -## 3.0.0-beta.8 - -### Patch Changes - -- 3794514: feat: flexible tool output content support - -## 3.0.0-beta.7 - -### Patch Changes - -- 81d4308: feat: provider-executed dynamic tools - -## 3.0.0-beta.6 - -### Major Changes - -- dee8b05: ai SDK 6 beta - -## 2.1.0-beta.5 - -### Patch Changes - -- 046aa3b: feat(provider): speech model v3 spec -- e8109d3: feat: tool execution approval - -## 2.1.0-beta.4 - -### Patch Changes - -- 0adc679: feat(provider): shared spec v3 -- 2b0caef: feat(provider): add preliminary provider executed tool results to language model specification - -## 2.1.0-beta.3 - -### Patch Changes - -- 8dac895: feat: `LanguageModelV3` - -## 2.1.0-beta.2 - -### Patch Changes - -- ed329cb: feat: `Provider-V3` -- 522f6b8: feat: `ImageModelV3` - -## 2.1.0-beta.1 - -### Patch Changes - -- 0c4822d: feat: `EmbeddingModelV3` - -## 2.1.0-beta.0 - -### Minor Changes - -- 78928cb: release: start 5.1 beta - -## 2.0.0 - -### Major Changes - -- 742b7be: feat: forward id, streaming start, streaming end of content blocks -- 7cddb72: refactoring (provider): collapse provider defined tools into single definition -- ccce59b: feat (provider): support changing provider, model, supportedUrls in middleware -- e2b9e4b: feat (provider): add name for provider defined tools for future validation -- 95857aa: chore: restructure language model supported urls -- 6f6bb89: chore (provider): cleanup request and rawRequest (language model v2) -- d1a1aa1: chore (provider): merge rawRequest into request (language model v2) -- 63f9e9b: chore (provider,ai): tools have input/output instead of args,result -- d5f588f: AI SDK 5 -- b6b43c7: chore: move warnings into stream-start part (spec) -- 411e483: chore (provider): refactor usage (language model v2) -- abf9a79: chore: rename mimeType to mediaType -- 14c9410: chore: refactor file towards source pattern (spec) -- e86be6f: chore: remove logprobs -- 0d06df6: chore (ai): remove v1 providers -- d9c98f4: chore: refactor reasoning parts (spec) -- a3f768e: chore: restructure reasoning support -- 7435eb5: feat: upgrade speech models to v2 specification -- 0054544: chore: refactor source parts (spec) -- 9e9c809: chore: refactor tool call and tool call delta parts (spec) -- 32831c6: chore: refactor text parts (spec) -- 6dc848c: chore (provider): remove image parts -- d0f9495: chore: refactor file parts (spec) -- 7979f7f: feat (provider): support reasoning tokens, cached input tokens, total token in usage information -- 44f4aba: feat: upgrade transcription models to v2 specification -- 7ea4132: chore: remove object generation mode -- 023ba40: feat (provider): support arbitrary media types in tool results -- e030615: chore (provider): remove prompt type from language model v2 spec -- 5e57fae: refactoring (provider): restructure tool result output -- c57e248: chore (provider): remove mode -- 3795467: chore: return content array from doGenerate (spec) -- 1766ede: chore: rename maxTokens to maxOutputTokens -- 33f4a6a: chore (provider): rename providerMetadata inputs to providerOptions - -### Patch Changes - -- dc714f3: release alpha.4 -- b5da06a: update to LanguageModelV2ProviderDefinedClientTool to add server side tool later on -- 48d257a: release alpha.15 -- 0d2c085: chore (provider): tweak provider definition -- 9222aeb: release alpha.8 -- e2aceaf: feat: add raw chunk support -- 7b3ae3f: chore (provider): change getSupportedUrls to supportedUrls (language model v2) -- a166433: feat: add transcription with experimental_transcribe -- 26735b5: chore(embedding-model): add v2 interface -- 443d8ec: feat(embedding-model-v2): add response body field -- a8c8bd5: feat(embed-many): respect supportsParallelCalls & concurrency -- 9bf7291: chore(providers/openai): enable structuredOutputs by default & switch to provider option -- 2e13791: feat(anthropic): add server-side web search support -- 472524a: spec (ai): add provider options to tools -- dd3ff01: chore: add language setting to speechv2 -- 9301f86: refactor (image-model): rename `ImageModelV1` to `ImageModelV2` -- 0a87932: core (ai): change transcription model mimeType to mediaType -- c4a2fec: chore (provider): extract shared provider options and metadata (spec) -- 79457bd: chore (provider): extract LanguageModelV2File -- 8aa9e20: feat: add speech with experimental_generateSpeech -- 4617fab: chore(embedding-models): remove remaining settings -- cb68df0: feat: add transcription and speech model support to provider registry -- ad80501: chore (provider): allow both binary and base64 file content (spec) - - Before - - ```ts - import { convertUint8ArrayToBase64 } from '@ai-sdk/provider-utils'; - - // Had to manually convert binary data to base64 - const fileData = new Uint8Array([0, 1, 2, 3]); - const filePart = { - type: 'file', - mediaType: 'application/pdf', - data: convertUint8ArrayToBase64(fileData), // Required conversion - }; - ``` - - After - - ```ts - // Can use binary data directly - const fileData = new Uint8Array([0, 1, 2, 3]); - const filePart = { - type: 'file', - mediaType: 'application/pdf', - data: fileData, // Direct Uint8Array support - }; - ``` - -- 68ecf2f: release alpha.13 -- 6b98118: release alpha.3 -- 3f2f00c: feat: `ImageModelV2#maxImagesPerCall` can be set to a function that returns a `number` or `undefined`, optionally as a promise - - pull request: https://github.com/vercel/ai/pull/6343 - -- 9bd5ab5: feat (provider): add providerMetadata to ImageModelV2 interface (#5977) - - The `experimental_generateImage` method from the `ai` package now returnes revised prompts for OpenAI's image models. - - ```js - const prompt = 'Santa Claus driving a Cadillac'; - - const { providerMetadata } = await experimental_generateImage({ - model: openai.image('dall-e-3'), - prompt, - }); - - const revisedPrompt = providerMetadata.openai.images[0]?.revisedPrompt; - - console.log({ - prompt, - revisedPrompt, - }); - ``` - -- 5c56081: release alpha.7 -- fd65bc6: chore(embedding-model-v2): rename rawResponse to response -- 26535e0: release alpha.2 -- 393138b: feat(embedding-model-v2): add providerOptions -- 7182d14: Remove `Experimental_LanguageModelV2Middleware` type -- c1e6647: release alpha.11 -- 811dff3: release alpha.9 -- f10304b: feat(tool-calling): don't require the user to have to pass parameters -- 27deb4d: feat (provider/gateway): Add providerMetadata to embeddings response -- c4df419: release alpha.10 - -## 2.0.0-beta.2 - -### Patch Changes - -- 27deb4d: feat (provider/gateway): Add providerMetadata to embeddings response - -## 2.0.0-beta.1 - -### Major Changes - -- 742b7be: feat: forward id, streaming start, streaming end of content blocks -- 7cddb72: refactoring (provider): collapse provider defined tools into single definition -- ccce59b: feat (provider): support changing provider, model, supportedUrls in middleware -- e2b9e4b: feat (provider): add name for provider defined tools for future validation -- 0d06df6: chore (ai): remove v1 providers -- 7435eb5: feat: upgrade speech models to v2 specification -- 44f4aba: feat: upgrade transcription models to v2 specification -- 023ba40: feat (provider): support arbitrary media types in tool results -- 5e57fae: refactoring (provider): restructure tool result output - -### Patch Changes - -- 472524a: spec (ai): add provider options to tools -- dd3ff01: chore: add language setting to speechv2 -- cb68df0: feat: add transcription and speech model support to provider registry - -## 2.0.0-alpha.15 - -### Patch Changes - -- 48d257a: release alpha.15 - -## 2.0.0-alpha.14 - -### Major Changes - -- 63f9e9b: chore (provider,ai): tools have input/output instead of args,result - -### Patch Changes - -- b5da06a: update to LanguageModelV2ProviderDefinedClientTool to add server side tool later on -- 2e13791: feat(anthropic): add server-side web search support - -## 2.0.0-alpha.13 - -### Patch Changes - -- 68ecf2f: release alpha.13 - -## 2.0.0-alpha.12 - -### Patch Changes - -- e2aceaf: feat: add raw chunk support - -## 2.0.0-alpha.11 - -### Patch Changes - -- c1e6647: release alpha.11 - -## 2.0.0-alpha.10 - -### Patch Changes - -- c4df419: release alpha.10 - -## 2.0.0-alpha.9 - -### Patch Changes - -- 811dff3: release alpha.9 - -## 2.0.0-alpha.8 - -### Patch Changes - -- 9222aeb: release alpha.8 - -## 2.0.0-alpha.7 - -### Patch Changes - -- 5c56081: release alpha.7 - -## 2.0.0-alpha.6 - -### Patch Changes - -- 0d2c085: chore (provider): tweak provider definition - -## 2.0.0-alpha.4 - -### Patch Changes - -- dc714f3: release alpha.4 - -## 2.0.0-alpha.3 - -### Patch Changes - -- 6b98118: release alpha.3 - -## 2.0.0-alpha.2 - -### Patch Changes - -- 26535e0: release alpha.2 - -## 2.0.0-alpha.1 - -### Patch Changes - -- 3f2f00c: feat: `ImageModelV2#maxImagesPerCall` can be set to a function that returns a `number` or `undefined`, optionally as a promise - - pull request: https://github.com/vercel/ai/pull/6343 - -## 2.0.0-canary.14 - -### Major Changes - -- 7979f7f: feat (provider): support reasoning tokens, cached input tokens, total token in usage information - -### Patch Changes - -- a8c8bd5: feat(embed-many): respect supportsParallelCalls & concurrency - -## 2.0.0-canary.13 - -### Patch Changes - -- 9bd5ab5: feat (provider): add providerMetadata to ImageModelV2 interface (#5977) - - The `experimental_generateImage` method from the `ai` package now returnes revised prompts for OpenAI's image models. - - ```js - const prompt = 'Santa Claus driving a Cadillac'; - - const { providerMetadata } = await experimental_generateImage({ - model: openai.image('dall-e-3'), - prompt, - }); - - const revisedPrompt = providerMetadata.openai.images[0]?.revisedPrompt; - - console.log({ - prompt, - revisedPrompt, - }); - ``` - -## 2.0.0-canary.12 - -### Patch Changes - -- 7b3ae3f: chore (provider): change getSupportedUrls to supportedUrls (language model v2) - -## 2.0.0-canary.11 - -### Major Changes - -- e030615: chore (provider): remove prompt type from language model v2 spec - -### Patch Changes - -- 9bf7291: chore(providers/openai): enable structuredOutputs by default & switch to provider option -- 4617fab: chore(embedding-models): remove remaining settings - -## 2.0.0-canary.10 - -### Major Changes - -- a3f768e: chore: restructure reasoning support - -### Patch Changes - -- 9301f86: refactor (image-model): rename `ImageModelV1` to `ImageModelV2` - -## 2.0.0-canary.9 - -### Major Changes - -- e86be6f: chore: remove logprobs - -## 2.0.0-canary.8 - -### Major Changes - -- 95857aa: chore: restructure language model supported urls -- 7ea4132: chore: remove object generation mode - -## 2.0.0-canary.7 - -### Major Changes - -- b6b43c7: chore: move warnings into stream-start part (spec) -- 3795467: chore: return content array from doGenerate (spec) - -### Patch Changes - -- 8aa9e20: feat: add speech with experimental_generateSpeech - -## 2.0.0-canary.6 - -### Major Changes - -- 14c9410: chore: refactor file towards source pattern (spec) -- d9c98f4: chore: refactor reasoning parts (spec) -- 0054544: chore: refactor source parts (spec) -- 9e9c809: chore: refactor tool call and tool call delta parts (spec) -- 32831c6: chore: refactor text parts (spec) -- d0f9495: chore: refactor file parts (spec) - -### Patch Changes - -- 26735b5: chore(embedding-model): add v2 interface -- 443d8ec: feat(embedding-model-v2): add response body field -- c4a2fec: chore (provider): extract shared provider options and metadata (spec) -- fd65bc6: chore(embedding-model-v2): rename rawResponse to response -- 393138b: feat(embedding-model-v2): add providerOptions -- 7182d14: Remove `Experimental_LanguageModelV2Middleware` type - -## 2.0.0-canary.5 - -### Major Changes - -- 411e483: chore (provider): refactor usage (language model v2) -- ad80501: chore (provider): allow both binary and base64 file content (spec) -- 1766ede: chore: rename maxTokens to maxOutputTokens - -### Patch Changes - -- 79457bd: chore (provider): extract LanguageModelV2File -- f10304b: feat(tool-calling): don't require the user to have to pass parameters - -## 2.0.0-canary.4 - -### Major Changes - -- 6f6bb89: chore (provider): cleanup request and rawRequest (language model v2) - -## 2.0.0-canary.3 - -### Major Changes - -- d1a1aa1: chore (provider): merge rawRequest into request (language model v2) - -## 2.0.0-canary.2 - -### Major Changes - -- abf9a79: chore: rename mimeType to mediaType -- 6dc848c: chore (provider): remove image parts - -### Patch Changes - -- a166433: feat: add transcription with experimental_transcribe -- 0a87932: core (ai): change transcription model mimeType to mediaType - -## 2.0.0-canary.1 - -### Major Changes - -- c57e248: chore (provider): remove mode -- 33f4a6a: chore (provider): rename providerMetadata inputs to providerOptions - -## 2.0.0-canary.0 - -### Major Changes - -- d5f588f: AI SDK 5 - -## 1.1.0 - -### Minor Changes - -- 5bc638d: AI SDK 4.2 - -## 1.0.12 - -### Patch Changes - -- 0bd5bc6: feat (ai): support model-generated files - -## 1.0.11 - -### Patch Changes - -- 2e1101a: feat (provider/openai): pdf input support - -## 1.0.10 - -### Patch Changes - -- e1d3d42: feat (ai): expose raw response body in generateText and generateObject - -## 1.0.9 - -### Patch Changes - -- ddf9740: feat (ai): add anthropic reasoning - -## 1.0.8 - -### Patch Changes - -- 2761f06: fix (ai/provider): publish with LanguageModelV1Source - -## 1.0.7 - -### Patch Changes - -- d89c3b9: feat (provider): add image model support to provider specification - -## 1.0.6 - -### Patch Changes - -- 3a58a2e: feat (ai/core): throw NoImageGeneratedError from generateImage when no predictions are returned. - -## 1.0.5 - -### Patch Changes - -- 0a699f1: feat: add reasoning token support - -## 1.0.4 - -### Patch Changes - -- 19a2ce7: feat (provider): add message option to UnsupportedFunctionalityError -- 6337688: feat: change image generation errors to warnings - -## 1.0.3 - -### Patch Changes - -- 5ed5e45: chore (config): Use ts-library.json tsconfig for no-UI libs. - -## 1.0.2 - -### Patch Changes - -- 09a9cab: feat (ai/core): add experimental generateImage function - -## 1.0.1 - -### Patch Changes - -- b446ae5: feat (provider): Define type for ObjectGenerationMode. - -## 1.0.0 - -### Major Changes - -- b469a7e: chore: remove isXXXError methods -- c0ddc24: chore (ai): remove toJSON method from AI SDK errors - -## 1.0.0-canary.0 - -### Major Changes - -- b469a7e: chore: remove isXXXError methods -- c0ddc24: chore (ai): remove toJSON method from AI SDK errors - -## 0.0.26 - -### Patch Changes - -- aa98cdb: chore: more flexible dependency versioning -- 1486128: feat: add supportsUrl to language model specification -- 7b937c5: feat (provider-utils): improve id generator robustness -- 3b1b69a: feat: provider-defined tools -- 811a317: feat (ai/core): multi-part tool results (incl. images) - -## 0.0.25 - -### Patch Changes - -- b9b0d7b: feat (ai): access raw request body - -## 0.0.24 - -### Patch Changes - -- d595d0d: feat (ai/core): file content parts - -## 0.0.23 - -### Patch Changes - -- 03313cd: feat (ai): expose response id, response model, response timestamp in telemetry and api -- 3be7c1c: fix (provider/anthropic): support prompt caching on assistant messages - -## 0.0.22 - -### Patch Changes - -- 26515cb: feat (ai/provider): introduce ProviderV1 specification - -## 0.0.21 - -### Patch Changes - -- f2c025e: feat (ai/core): prompt validation - -## 0.0.20 - -### Patch Changes - -- 6ac355e: feat (provider/anthropic): add cache control support - -## 0.0.19 - -### Patch Changes - -- dd4a0f5: fix (ai/provider): remove invalid check in isJSONParseError - -## 0.0.18 - -### Patch Changes - -- 4bd27a9: chore (ai/provider): refactor type validation - -## 0.0.17 - -### Patch Changes - -- 029af4c: feat (ai/core): support schema name & description in generateObject & streamObject - -## 0.0.16 - -### Patch Changes - -- d58517b: feat (ai/openai): structured outputs - -## 0.0.15 - -### Patch Changes - -- 96aed25: fix (ai/provider): release new version - -## 0.0.14 - -### Patch Changes - -- a8d1c9e9: feat (ai/core): parallel image download - -## 0.0.13 - -### Patch Changes - -- 2b9da0f0: feat (core): support stopSequences setting. -- a5b58845: feat (core): support topK setting -- 4aa8deb3: feat (provider): support responseFormat setting in provider api -- 13b27ec6: chore (ai/core): remove grammar mode - -## 0.0.12 - -### Patch Changes - -- b7290943: feat (ai/core): add token usage to embed and embedMany - -## 0.0.11 - -### Patch Changes - -- 5edc6110: feat (provider): add headers support to language and embedding model spec - -## 0.0.10 - -### Patch Changes - -- 102ca22f: fix (@ai-sdk/provider): fix TypeValidationError.isTypeValidationError - -## 0.0.9 - -### Patch Changes - -- 09295e2e: feat (@ai-sdk/provider): add DownloadError - -## 0.0.8 - -### Patch Changes - -- f39c0dd2: feat (provider): add toolChoice to language model specification - -## 0.0.7 - -### Patch Changes - -- 8e780288: feat (ai/provider): add "unknown" finish reason (for models that don't provide a finish reason) - -## 0.0.6 - -### Patch Changes - -- 6a50ac4: feat (provider): add additional error types - -## 0.0.5 - -### Patch Changes - -- 0f6bc4e: feat (ai/core): add embed function - -## 0.0.4 - -### Patch Changes - -- 325ca55: feat (ai/core): improve image content part error message - -## 0.0.3 - -### Patch Changes - -- 41d5736: ai/core: re-expose language model types. - -## 0.0.2 - -### Patch Changes - -- d6431ae: ai/core: add logprobs support (thanks @SamStenner for the contribution) -- 25f3350: ai/core: add support for getting raw response headers. - -## 0.0.1 - -### Patch Changes - -- eb150a6: ai/core: remove scaling of setting values (breaking change). If you were using the temperature, frequency penalty, or presence penalty settings, you need to update the providers and adjust the setting values. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/LICENSE deleted file mode 100644 index 6c16c29f4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2023 Vercel, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/README.md deleted file mode 100644 index 0e858d875..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/README.md +++ /dev/null @@ -1 +0,0 @@ -# AI SDK - Provider Language Model Specification diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/package.json deleted file mode 100644 index 6cbb699e3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/package.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "name": "@ai-sdk/provider", - "version": "3.0.8", - "license": "Apache-2.0", - "sideEffects": false, - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", - "source": "./src/index.ts", - "files": [ - "dist/**/*", - "src", - "!src/**/*.test.ts", - "!src/**/*.test-d.ts", - "!src/**/__snapshots__", - "!src/**/__fixtures__", - "CHANGELOG.md", - "README.md" - ], - "exports": { - "./package.json": "./package.json", - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" - } - }, - "dependencies": { - "json-schema": "^0.4.0" - }, - "devDependencies": { - "@types/json-schema": "7.0.15", - "@types/node": "20.17.24", - "tsup": "^8", - "typescript": "5.8.3", - "@vercel/ai-tsconfig": "0.0.0" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public" - }, - "homepage": "https://ai-sdk.dev/docs", - "repository": { - "type": "git", - "url": "git+https://github.com/vercel/ai.git" - }, - "bugs": { - "url": "https://github.com/vercel/ai/issues" - }, - "keywords": [ - "ai" - ], - "scripts": { - "build": "pnpm clean && tsup --tsconfig tsconfig.build.json", - "build:watch": "pnpm clean && tsup --watch", - "clean": "del-cli dist *.tsbuildinfo", - "lint": "eslint \"./**/*.ts*\"", - "type-check": "tsc --build", - "prettier-check": "prettier --check \"./**/*.ts*\"" - } -} \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model-middleware/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model-middleware/index.ts deleted file mode 100644 index ca7b39f38..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model-middleware/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './v3/index'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model-middleware/v3/embedding-model-v3-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model-middleware/v3/embedding-model-v3-middleware.ts deleted file mode 100644 index c98f6c384..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model-middleware/v3/embedding-model-v3-middleware.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { EmbeddingModelV3 } from '../../embedding-model/v3/embedding-model-v3'; -import { EmbeddingModelV3CallOptions } from '../../embedding-model/v3/embedding-model-v3-call-options'; - -/** - * Middleware for EmbeddingModelV3. - * This type defines the structure for middleware that can be used to modify - * the behavior of EmbeddingModelV3 operations. - */ -export type EmbeddingModelV3Middleware = { - /** - * Middleware specification version. Use `v3` for the current version. - */ - readonly specificationVersion: 'v3'; - - /** - * Override the provider name if desired. - * @param options.model - The embedding model instance. - */ - overrideProvider?: (options: { model: EmbeddingModelV3 }) => string; - - /** - * Override the model ID if desired. - * @param options.model - The embedding model instance. - */ - overrideModelId?: (options: { model: EmbeddingModelV3 }) => string; - - /** - * Override the limit of how many embeddings can be generated in a single API call if desired. - * @param options.model - The embedding model instance. - */ - overrideMaxEmbeddingsPerCall?: (options: { - model: EmbeddingModelV3; - }) => PromiseLike | number | undefined; - - /** - * Override support for handling multiple embedding calls in parallel, if desired.. - * @param options.model - The embedding model instance. - */ - overrideSupportsParallelCalls?: (options: { - model: EmbeddingModelV3; - }) => PromiseLike | boolean; - - /** - * Transforms the parameters before they are passed to the embed model. - * @param options - Object containing the type of operation and the parameters. - * @param options.params - The original parameters for the embedding model call. - * @returns A promise that resolves to the transformed parameters. - */ - transformParams?: (options: { - params: EmbeddingModelV3CallOptions; - model: EmbeddingModelV3; - }) => PromiseLike; - - /** - * Wraps the embed operation of the embedding model. - * - * @param options - Object containing the embed function, parameters, and model. - * @param options.doEmbed - The original embed function. - * @param options.params - The parameters for the embed call. If the - * `transformParams` middleware is used, this will be the transformed parameters. - * @param options.model - The embedding model instance. - * @returns A promise that resolves to the result of the generate operation. - */ - wrapEmbed?: (options: { - doEmbed: () => ReturnType; - params: EmbeddingModelV3CallOptions; - model: EmbeddingModelV3; - }) => Promise>>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model-middleware/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model-middleware/v3/index.ts deleted file mode 100644 index 00203ebee..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model-middleware/v3/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './embedding-model-v3-middleware'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/index.ts deleted file mode 100644 index f0a4a20cc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './v3/index'; -export * from './v2/index'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v2/embedding-model-v2-embedding.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v2/embedding-model-v2-embedding.ts deleted file mode 100644 index b6800300f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v2/embedding-model-v2-embedding.ts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * An embedding is a vector, i.e. an array of numbers. - * It is e.g. used to represent a text as a vector of word embeddings. - */ -export type EmbeddingModelV2Embedding = Array; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v2/embedding-model-v2.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v2/embedding-model-v2.ts deleted file mode 100644 index 4129bde0d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v2/embedding-model-v2.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { - SharedV2Headers, - SharedV2ProviderOptions, - SharedV2ProviderMetadata, -} from '../../shared'; -import { EmbeddingModelV2Embedding } from './embedding-model-v2-embedding'; - -/** - * Specification for an embedding model that implements the embedding model - * interface version 2. - * - * VALUE is the type of the values that the model can embed. - * This will allow us to go beyond text embeddings in the future, - * e.g. to support image embeddings - */ -export type EmbeddingModelV2 = { - /** - * The embedding model must specify which embedding model interface - * version it implements. This will allow us to evolve the embedding - * model interface and retain backwards compatibility. The different - * implementation versions can be handled as a discriminated union - * on our side. - */ - readonly specificationVersion: 'v2'; - - /** - * Name of the provider for logging purposes. - */ - readonly provider: string; - - /** - * Provider-specific model ID for logging purposes. - */ - readonly modelId: string; - - /** - * Limit of how many embeddings can be generated in a single API call. - * - * Use Infinity for models that do not have a limit. - */ - readonly maxEmbeddingsPerCall: - | PromiseLike - | number - | undefined; - - /** - * True if the model can handle multiple embedding calls in parallel. - */ - readonly supportsParallelCalls: PromiseLike | boolean; - - /** - * Generates a list of embeddings for the given input text. - * - * Naming: "do" prefix to prevent accidental direct usage of the method - * by the user. - */ - doEmbed(options: { - /** - * List of values to embed. - */ - values: Array; - - /** - * Abort signal for cancelling the operation. - */ - abortSignal?: AbortSignal; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV2ProviderOptions; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; - }): PromiseLike<{ - /** - * Generated embeddings. They are in the same order as the input values. - */ - embeddings: Array; - - /** - * Token usage. We only have input tokens for embeddings. - */ - usage?: { tokens: number }; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - providerMetadata?: SharedV2ProviderMetadata; - - /** - * Optional response information for debugging purposes. - */ - response?: { - /** - * Response headers. - */ - headers?: SharedV2Headers; - - /** - * The response body. - */ - body?: unknown; - }; - }>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v2/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v2/index.ts deleted file mode 100644 index ca4d0c8d9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v2/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './embedding-model-v2'; -export * from './embedding-model-v2-embedding'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/embedding-model-v3-call-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/embedding-model-v3-call-options.ts deleted file mode 100644 index a2f9e362e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/embedding-model-v3-call-options.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { SharedV3Headers, SharedV3ProviderOptions } from '../../shared'; - -export type EmbeddingModelV3CallOptions = { - /** - * List of text values to generate embeddings for. - */ - values: Array; - - /** - * Abort signal for cancelling the operation. - */ - abortSignal?: AbortSignal; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV3ProviderOptions; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: SharedV3Headers; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/embedding-model-v3-embedding.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/embedding-model-v3-embedding.ts deleted file mode 100644 index 1060a4441..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/embedding-model-v3-embedding.ts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * An embedding is a vector, i.e. an array of numbers. - * It is e.g. used to represent a text as a vector of word embeddings. - */ -export type EmbeddingModelV3Embedding = Array; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/embedding-model-v3-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/embedding-model-v3-result.ts deleted file mode 100644 index 8407871fc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/embedding-model-v3-result.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { - SharedV3Headers, - SharedV3ProviderMetadata, - SharedV3Warning, -} from '../../shared'; -import { EmbeddingModelV3Embedding } from './embedding-model-v3-embedding'; - -/** - * The result of a embedding model doEmbed call. - */ -export type EmbeddingModelV3Result = { - /** - * Generated embeddings. They are in the same order as the input values. - */ - embeddings: Array; - - /** - * Token usage. We only have input tokens for embeddings. - */ - usage?: { tokens: number }; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - providerMetadata?: SharedV3ProviderMetadata; - - /** - * Optional response information for debugging purposes. - */ - response?: { - /** - * Response headers. - */ - headers?: SharedV3Headers; - - /** - * The response body. - */ - body?: unknown; - }; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - warnings: Array; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/embedding-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/embedding-model-v3.ts deleted file mode 100644 index ba7762586..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/embedding-model-v3.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { EmbeddingModelV3CallOptions } from './embedding-model-v3-call-options'; -import { EmbeddingModelV3Result } from './embedding-model-v3-result'; - -/** - * Specification for an embedding model that implements the embedding model - * interface version 3. - * - * It is specific to text embeddings. - */ -export type EmbeddingModelV3 = { - /** - * The embedding model must specify which embedding model interface - * version it implements. This will allow us to evolve the embedding - * model interface and retain backwards compatibility. The different - * implementation versions can be handled as a discriminated union - * on our side. - */ - readonly specificationVersion: 'v3'; - - /** - * Name of the provider for logging purposes. - */ - readonly provider: string; - - /** - * Provider-specific model ID for logging purposes. - */ - readonly modelId: string; - - /** - * Limit of how many embeddings can be generated in a single API call. - * - * Use Infinity for models that do not have a limit. - */ - readonly maxEmbeddingsPerCall: - | PromiseLike - | number - | undefined; - - /** - * True if the model can handle multiple embedding calls in parallel. - */ - readonly supportsParallelCalls: PromiseLike | boolean; - - /** - * Generates a list of embeddings for the given input text. - * - * Naming: "do" prefix to prevent accidental direct usage of the method - * by the user. - */ - doEmbed( - options: EmbeddingModelV3CallOptions, - ): PromiseLike; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/index.ts deleted file mode 100644 index 243f48514..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/embedding-model/v3/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './embedding-model-v3'; -export * from './embedding-model-v3-call-options'; -export * from './embedding-model-v3-embedding'; -export * from './embedding-model-v3-result'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/ai-sdk-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/ai-sdk-error.ts deleted file mode 100644 index f23b9b3b9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/ai-sdk-error.ts +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Symbol used for identifying AI SDK Error instances. - * Enables checking if an error is an instance of AISDKError across package versions. - */ -const marker = 'vercel.ai.error'; -const symbol = Symbol.for(marker); - -/** - * Custom error class for AI SDK related errors. - * @extends Error - */ -export class AISDKError extends Error { - private readonly [symbol] = true; // used in isInstance - - /** - * The underlying cause of the error, if any. - */ - readonly cause?: unknown; - - /** - * Creates an AI SDK Error. - * - * @param {Object} params - The parameters for creating the error. - * @param {string} params.name - The name of the error. - * @param {string} params.message - The error message. - * @param {unknown} [params.cause] - The underlying cause of the error. - */ - constructor({ - name, - message, - cause, - }: { - name: string; - message: string; - cause?: unknown; - }) { - super(message); - - this.name = name; - this.cause = cause; - } - - /** - * Checks if the given error is an AI SDK Error. - * @param {unknown} error - The error to check. - * @returns {boolean} True if the error is an AI SDK Error, false otherwise. - */ - static isInstance(error: unknown): error is AISDKError { - return AISDKError.hasMarker(error, marker); - } - - protected static hasMarker(error: unknown, marker: string): boolean { - const markerSymbol = Symbol.for(marker); - return ( - error != null && - typeof error === 'object' && - markerSymbol in error && - typeof error[markerSymbol] === 'boolean' && - error[markerSymbol] === true - ); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/api-call-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/api-call-error.ts deleted file mode 100644 index 1423c05cf..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/api-call-error.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; - -const name = 'AI_APICallError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class APICallError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly url: string; - readonly requestBodyValues: unknown; - readonly statusCode?: number; - - readonly responseHeaders?: Record; - readonly responseBody?: string; - - readonly isRetryable: boolean; - readonly data?: unknown; - - constructor({ - message, - url, - requestBodyValues, - statusCode, - responseHeaders, - responseBody, - cause, - isRetryable = statusCode != null && - (statusCode === 408 || // request timeout - statusCode === 409 || // conflict - statusCode === 429 || // too many requests - statusCode >= 500), // server error - data, - }: { - message: string; - url: string; - requestBodyValues: unknown; - statusCode?: number; - responseHeaders?: Record; - responseBody?: string; - cause?: unknown; - isRetryable?: boolean; - data?: unknown; - }) { - super({ name, message, cause }); - - this.url = url; - this.requestBodyValues = requestBodyValues; - this.statusCode = statusCode; - this.responseHeaders = responseHeaders; - this.responseBody = responseBody; - this.isRetryable = isRetryable; - this.data = data; - } - - static isInstance(error: unknown): error is APICallError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/empty-response-body-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/empty-response-body-error.ts deleted file mode 100644 index a20e0baca..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/empty-response-body-error.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; - -const name = 'AI_EmptyResponseBodyError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class EmptyResponseBodyError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - constructor({ message = 'Empty response body' }: { message?: string } = {}) { - super({ name, message }); - } - - static isInstance(error: unknown): error is EmptyResponseBodyError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/get-error-message.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/get-error-message.ts deleted file mode 100644 index 62c29e58a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/get-error-message.ts +++ /dev/null @@ -1,15 +0,0 @@ -export function getErrorMessage(error: unknown | undefined) { - if (error == null) { - return 'unknown error'; - } - - if (typeof error === 'string') { - return error; - } - - if (error instanceof Error) { - return error.message; - } - - return JSON.stringify(error); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/index.ts deleted file mode 100644 index 4e7d48251..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -export { AISDKError } from './ai-sdk-error'; -export { APICallError } from './api-call-error'; -export { EmptyResponseBodyError } from './empty-response-body-error'; -export { getErrorMessage } from './get-error-message'; -export { InvalidArgumentError } from './invalid-argument-error'; -export { InvalidPromptError } from './invalid-prompt-error'; -export { InvalidResponseDataError } from './invalid-response-data-error'; -export { JSONParseError } from './json-parse-error'; -export { LoadAPIKeyError } from './load-api-key-error'; -export { LoadSettingError } from './load-setting-error'; -export { NoContentGeneratedError } from './no-content-generated-error'; -export { NoSuchModelError } from './no-such-model-error'; -export { TooManyEmbeddingValuesForCallError } from './too-many-embedding-values-for-call-error'; -export type { TypeValidationContext } from './type-validation-error'; -export { TypeValidationError } from './type-validation-error'; -export { UnsupportedFunctionalityError } from './unsupported-functionality-error'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/invalid-argument-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/invalid-argument-error.ts deleted file mode 100644 index afdaa47a0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/invalid-argument-error.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; - -const name = 'AI_InvalidArgumentError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * A function argument is invalid. - */ -export class InvalidArgumentError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly argument: string; - - constructor({ - message, - cause, - argument, - }: { - argument: string; - message: string; - cause?: unknown; - }) { - super({ name, message, cause }); - - this.argument = argument; - } - - static isInstance(error: unknown): error is InvalidArgumentError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/invalid-prompt-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/invalid-prompt-error.ts deleted file mode 100644 index 7e969887e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/invalid-prompt-error.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; - -const name = 'AI_InvalidPromptError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * A prompt is invalid. This error should be thrown by providers when they cannot - * process a prompt. - */ -export class InvalidPromptError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly prompt: unknown; - - constructor({ - prompt, - message, - cause, - }: { - prompt: unknown; - message: string; - cause?: unknown; - }) { - super({ name, message: `Invalid prompt: ${message}`, cause }); - - this.prompt = prompt; - } - - static isInstance(error: unknown): error is InvalidPromptError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/invalid-response-data-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/invalid-response-data-error.ts deleted file mode 100644 index 20da72418..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/invalid-response-data-error.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; - -const name = 'AI_InvalidResponseDataError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Server returned a response with invalid data content. - * This should be thrown by providers when they cannot parse the response from the API. - */ -export class InvalidResponseDataError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly data: unknown; - - constructor({ - data, - message = `Invalid response data: ${JSON.stringify(data)}.`, - }: { - data: unknown; - message?: string; - }) { - super({ name, message }); - - this.data = data; - } - - static isInstance(error: unknown): error is InvalidResponseDataError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/json-parse-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/json-parse-error.ts deleted file mode 100644 index 6a39eca80..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/json-parse-error.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; -import { getErrorMessage } from './get-error-message'; - -const name = 'AI_JSONParseError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class JSONParseError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly text: string; - - constructor({ text, cause }: { text: string; cause: unknown }) { - super({ - name, - message: - `JSON parsing failed: ` + - `Text: ${text}.\n` + - `Error message: ${getErrorMessage(cause)}`, - cause, - }); - - this.text = text; - } - - static isInstance(error: unknown): error is JSONParseError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/load-api-key-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/load-api-key-error.ts deleted file mode 100644 index aa73983a3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/load-api-key-error.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; - -const name = 'AI_LoadAPIKeyError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class LoadAPIKeyError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - constructor({ message }: { message: string }) { - super({ name, message }); - } - - static isInstance(error: unknown): error is LoadAPIKeyError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/load-setting-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/load-setting-error.ts deleted file mode 100644 index b2b07553f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/load-setting-error.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; - -const name = 'AI_LoadSettingError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class LoadSettingError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - constructor({ message }: { message: string }) { - super({ name, message }); - } - - static isInstance(error: unknown): error is LoadSettingError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/no-content-generated-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/no-content-generated-error.ts deleted file mode 100644 index 680a30d64..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/no-content-generated-error.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; - -const name = 'AI_NoContentGeneratedError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Thrown when the AI provider fails to generate any content. - */ -export class NoContentGeneratedError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - constructor({ - message = 'No content generated.', - }: { message?: string } = {}) { - super({ name, message }); - } - - static isInstance(error: unknown): error is NoContentGeneratedError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/no-such-model-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/no-such-model-error.ts deleted file mode 100644 index 252ff96b8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/no-such-model-error.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; - -const name = 'AI_NoSuchModelError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class NoSuchModelError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly modelId: string; - readonly modelType: - | 'languageModel' - | 'embeddingModel' - | 'imageModel' - | 'transcriptionModel' - | 'speechModel' - | 'rerankingModel' - | 'videoModel'; - - constructor({ - errorName = name, - modelId, - modelType, - message = `No such ${modelType}: ${modelId}`, - }: { - errorName?: string; - modelId: string; - modelType: - | 'languageModel' - | 'embeddingModel' - | 'imageModel' - | 'transcriptionModel' - | 'speechModel' - | 'rerankingModel' - | 'videoModel'; - message?: string; - }) { - super({ name: errorName, message }); - - this.modelId = modelId; - this.modelType = modelType; - } - - static isInstance(error: unknown): error is NoSuchModelError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/too-many-embedding-values-for-call-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/too-many-embedding-values-for-call-error.ts deleted file mode 100644 index 17b6c26fc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/too-many-embedding-values-for-call-error.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; - -const name = 'AI_TooManyEmbeddingValuesForCallError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class TooManyEmbeddingValuesForCallError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly provider: string; - readonly modelId: string; - readonly maxEmbeddingsPerCall: number; - readonly values: Array; - - constructor(options: { - provider: string; - modelId: string; - maxEmbeddingsPerCall: number; - values: Array; - }) { - super({ - name, - message: - `Too many values for a single embedding call. ` + - `The ${options.provider} model "${options.modelId}" can only embed up to ` + - `${options.maxEmbeddingsPerCall} values per call, but ${options.values.length} values were provided.`, - }); - - this.provider = options.provider; - this.modelId = options.modelId; - this.maxEmbeddingsPerCall = options.maxEmbeddingsPerCall; - this.values = options.values; - } - - static isInstance( - error: unknown, - ): error is TooManyEmbeddingValuesForCallError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/type-validation-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/type-validation-error.ts deleted file mode 100644 index 83f3c6e9d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/type-validation-error.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; -import { getErrorMessage } from './get-error-message'; - -const name = 'AI_TypeValidationError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export interface TypeValidationContext { - /** - * Field path in dot notation (e.g., "message.metadata", "message.parts[3].data") - */ - field?: string; - - /** - * Entity name (e.g., tool name, data type name) - */ - entityName?: string; - - /** - * Entity identifier (e.g., message ID, tool call ID) - */ - entityId?: string; -} - -export class TypeValidationError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly value: unknown; - readonly context?: TypeValidationContext; - - constructor({ - value, - cause, - context, - }: { - value: unknown; - cause: unknown; - context?: TypeValidationContext; - }) { - let contextPrefix = 'Type validation failed'; - - if (context?.field) { - contextPrefix += ` for ${context.field}`; - } - - if (context?.entityName || context?.entityId) { - contextPrefix += ' ('; - const parts: string[] = []; - if (context.entityName) { - parts.push(context.entityName); - } - if (context.entityId) { - parts.push(`id: "${context.entityId}"`); - } - contextPrefix += parts.join(', '); - contextPrefix += ')'; - } - - super({ - name, - message: - `${contextPrefix}: ` + - `Value: ${JSON.stringify(value)}.\n` + - `Error message: ${getErrorMessage(cause)}`, - cause, - }); - - this.value = value; - this.context = context; - } - - static isInstance(error: unknown): error is TypeValidationError { - return AISDKError.hasMarker(error, marker); - } - - /** - * Wraps an error into a TypeValidationError. - * If the cause is already a TypeValidationError with the same value and context, it returns the cause. - * Otherwise, it creates a new TypeValidationError. - * - * @param {Object} params - The parameters for wrapping the error. - * @param {unknown} params.value - The value that failed validation. - * @param {unknown} params.cause - The original error or cause of the validation failure. - * @param {TypeValidationContext} params.context - Optional context about what is being validated. - * @returns {TypeValidationError} A TypeValidationError instance. - */ - static wrap({ - value, - cause, - context, - }: { - value: unknown; - cause: unknown; - context?: TypeValidationContext; - }): TypeValidationError { - if ( - TypeValidationError.isInstance(cause) && - cause.value === value && - cause.context?.field === context?.field && - cause.context?.entityName === context?.entityName && - cause.context?.entityId === context?.entityId - ) { - return cause; - } - - return new TypeValidationError({ value, cause, context }); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/unsupported-functionality-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/unsupported-functionality-error.ts deleted file mode 100644 index 679240d59..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/errors/unsupported-functionality-error.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { AISDKError } from './ai-sdk-error'; - -const name = 'AI_UnsupportedFunctionalityError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class UnsupportedFunctionalityError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly functionality: string; - - constructor({ - functionality, - message = `'${functionality}' functionality not supported.`, - }: { - functionality: string; - message?: string; - }) { - super({ name, message }); - this.functionality = functionality; - } - - static isInstance(error: unknown): error is UnsupportedFunctionalityError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model-middleware/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model-middleware/index.ts deleted file mode 100644 index ca7b39f38..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model-middleware/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './v3/index'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model-middleware/v3/image-model-v3-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model-middleware/v3/image-model-v3-middleware.ts deleted file mode 100644 index 41340cbe0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model-middleware/v3/image-model-v3-middleware.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { ImageModelV3 } from '../../image-model/v3/image-model-v3'; -import { ImageModelV3CallOptions } from '../../image-model/v3/image-model-v3-call-options'; - -/** - * Middleware for ImageModelV3. - * This type defines the structure for middleware that can be used to modify - * the behavior of ImageModelV3 operations. - */ -export type ImageModelV3Middleware = { - /** - * Middleware specification version. Use `v3` for the current version. - */ - readonly specificationVersion: 'v3'; - - /** - * Override the provider name if desired. - * @param options.model - The image model instance. - */ - overrideProvider?: (options: { model: ImageModelV3 }) => string; - - /** - * Override the model ID if desired. - * @param options.model - The image model instance. - */ - overrideModelId?: (options: { model: ImageModelV3 }) => string; - - /** - * Override the limit of how many images can be generated in a single API call if desired. - * @param options.model - The image model instance. - */ - overrideMaxImagesPerCall?: (options: { - model: ImageModelV3; - }) => ImageModelV3['maxImagesPerCall']; - - /** - * Transforms the parameters before they are passed to the image model. - * @param options - Object containing the parameters. - * @param options.params - The original parameters for the image model call. - * @returns A promise that resolves to the transformed parameters. - */ - transformParams?: (options: { - params: ImageModelV3CallOptions; - model: ImageModelV3; - }) => PromiseLike; - - /** - * Wraps the generate operation of the image model. - * - * @param options - Object containing the generate function, parameters, and model. - * @param options.doGenerate - The original generate function. - * @param options.params - The parameters for the generate call. If the - * `transformParams` middleware is used, this will be the transformed parameters. - * @param options.model - The image model instance. - * @returns A promise that resolves to the result of the generate operation. - */ - wrapGenerate?: (options: { - doGenerate: () => ReturnType; - params: ImageModelV3CallOptions; - model: ImageModelV3; - }) => Promise>>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model-middleware/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model-middleware/v3/index.ts deleted file mode 100644 index dac856ba0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model-middleware/v3/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './image-model-v3-middleware'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/index.ts deleted file mode 100644 index f0a4a20cc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './v3/index'; -export * from './v2/index'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v2/image-model-v2-call-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v2/image-model-v2-call-options.ts deleted file mode 100644 index bbc4b7160..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v2/image-model-v2-call-options.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { SharedV2ProviderOptions } from '../../shared'; - -export type ImageModelV2CallOptions = { - /** - * Prompt for the image generation. - */ - prompt: string; - - /** - * Number of images to generate. - */ - n: number; - - /** - * Size of the images to generate. - * Must have the format `{width}x{height}`. - * `undefined` will use the provider's default size. - */ - size: `${number}x${number}` | undefined; - - /** - * Aspect ratio of the images to generate. - * Must have the format `{width}:{height}`. - * `undefined` will use the provider's default aspect ratio. - */ - aspectRatio: `${number}:${number}` | undefined; - - /** - * Seed for the image generation. - * `undefined` will use the provider's default seed. - */ - seed: number | undefined; - - /** - * Additional provider-specific options that are passed through to the provider - * as body parameters. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * ```ts - * { - * "openai": { - * "style": "vivid" - * } - * } - * ``` - */ - providerOptions: SharedV2ProviderOptions; - - /** - * Abort signal for cancelling the operation. - */ - abortSignal?: AbortSignal; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v2/image-model-v2-call-warning.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v2/image-model-v2-call-warning.ts deleted file mode 100644 index 6ea317b67..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v2/image-model-v2-call-warning.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { ImageModelV2CallOptions } from './image-model-v2-call-options'; - -/** - * Warning from the model provider for this call. The call will proceed, but e.g. - * some settings might not be supported, which can lead to suboptimal results. - */ -export type ImageModelV2CallWarning = - | { - type: 'unsupported-setting'; - setting: keyof ImageModelV2CallOptions; - details?: string; - } - | { - type: 'other'; - message: string; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v2/image-model-v2.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v2/image-model-v2.ts deleted file mode 100644 index d00b63252..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v2/image-model-v2.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { JSONArray, JSONValue } from '../../json-value'; -import { ImageModelV2CallOptions } from './image-model-v2-call-options'; -import { ImageModelV2CallWarning } from './image-model-v2-call-warning'; - -export type ImageModelV2ProviderMetadata = Record< - string, - { - images: JSONArray; - } & JSONValue ->; - -type GetMaxImagesPerCallFunction = (options: { - modelId: string; -}) => PromiseLike | number | undefined; - -/** - * Image generation model specification version 2. - */ -export type ImageModelV2 = { - /** - * The image model must specify which image model interface - * version it implements. This will allow us to evolve the image - * model interface and retain backwards compatibility. The different - * implementation versions can be handled as a discriminated union - * on our side. - */ - readonly specificationVersion: 'v2'; - - /** - * Name of the provider for logging purposes. - */ - readonly provider: string; - - /** - * Provider-specific model ID for logging purposes. - */ - readonly modelId: string; - - /** - * Limit of how many images can be generated in a single API call. - * Can be set to a number for a fixed limit, to undefined to use - * the global limit, or a function that returns a number or undefined, - * optionally as a promise. - */ - readonly maxImagesPerCall: number | undefined | GetMaxImagesPerCallFunction; - - /** - * Generates an array of images. - */ - doGenerate(options: ImageModelV2CallOptions): PromiseLike<{ - /** - * Generated images as base64 encoded strings or binary data. - * The images should be returned without any unnecessary conversion. - * If the API returns base64 encoded strings, the images should be returned - * as base64 encoded strings. If the API returns binary data, the images should - * be returned as binary data. - */ - images: Array | Array; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - warnings: Array; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - * - * The outer record is keyed by the provider name, and the inner - * record is provider-specific metadata. It always includes an - * `images` key with image-specific metadata - * - * ```ts - * { - * "openai": { - * "images": ["revisedPrompt": "Revised prompt here."] - * } - * } - * ``` - */ - providerMetadata?: ImageModelV2ProviderMetadata; - - /** - * Response information for telemetry and debugging purposes. - */ - response: { - /** - * Timestamp for the start of the generated response. - */ - timestamp: Date; - - /** - * The ID of the response model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers. - */ - headers: Record | undefined; - }; - }>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v2/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v2/index.ts deleted file mode 100644 index 8395d2fe0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v2/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type { - ImageModelV2, - ImageModelV2ProviderMetadata, -} from './image-model-v2'; -export type { ImageModelV2CallOptions } from './image-model-v2-call-options'; -export type { ImageModelV2CallWarning } from './image-model-v2-call-warning'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/image-model-v3-call-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/image-model-v3-call-options.ts deleted file mode 100644 index 761dfc398..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/image-model-v3-call-options.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { SharedV3ProviderOptions } from '../../shared'; -import { ImageModelV3File } from './image-model-v3-file'; - -export type ImageModelV3CallOptions = { - /** - * Prompt for the image generation. Some operations, like upscaling, may not require a prompt. - */ - prompt: string | undefined; - - /** - * Number of images to generate. - */ - n: number; - - /** - * Size of the images to generate. - * Must have the format `{width}x{height}`. - * `undefined` will use the provider's default size. - */ - size: `${number}x${number}` | undefined; - - /** - * Aspect ratio of the images to generate. - * Must have the format `{width}:{height}`. - * `undefined` will use the provider's default aspect ratio. - */ - aspectRatio: `${number}:${number}` | undefined; - - /** - * Seed for the image generation. - * `undefined` will use the provider's default seed. - */ - seed: number | undefined; - - /** - * Array of images for image editing or variation generation. - * The images should be provided as base64 encoded strings or binary data. - */ - files: ImageModelV3File[] | undefined; - - /** - * Mask image for inpainting operations. - * The mask should be provided as base64 encoded strings or binary data. - */ - mask: ImageModelV3File | undefined; - - /** - * Additional provider-specific options that are passed through to the provider - * as body parameters. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * - * ```ts - * { - * "openai": { - * "style": "vivid" - * } - * } - * ``` - */ - providerOptions: SharedV3ProviderOptions; - - /** - * Abort signal for cancelling the operation. - */ - abortSignal?: AbortSignal; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/image-model-v3-file.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/image-model-v3-file.ts deleted file mode 100644 index 1d37f2be1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/image-model-v3-file.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { SharedV3ProviderMetadata } from '../../shared'; - -/** - * An image file that can be used for image editing or variation generation. - */ -export type ImageModelV3File = - | { - type: 'file'; - - /** - * The IANA media type of the file, e.g. `image/png`. Any string is supported. - * - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Generated file data as base64 encoded strings or binary data. - * - * The file data should be returned without any unnecessary conversion. - * If the API returns base64 encoded strings, the file data should be returned - * as base64 encoded strings. If the API returns binary data, the file data should - * be returned as binary data. - */ - data: string | Uint8Array; - - /** - * Optional provider-specific metadata for the file part. - */ - providerOptions?: SharedV3ProviderMetadata; - } - | { - type: 'url'; - - /** - * The URL of the image file. - */ - url: string; - - /** - * Optional provider-specific metadata for the file part. - */ - providerOptions?: SharedV3ProviderMetadata; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/image-model-v3-usage.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/image-model-v3-usage.ts deleted file mode 100644 index 7f523a2e9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/image-model-v3-usage.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Usage information for an image model call. - */ -export type ImageModelV3Usage = { - /** - * The number of input (prompt) tokens used. - */ - inputTokens: number | undefined; - - /** - * The number of output tokens used, if reported by the provider. - */ - outputTokens: number | undefined; - - /** - * The total number of tokens as reported by the provider. - */ - totalTokens: number | undefined; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/image-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/image-model-v3.ts deleted file mode 100644 index b11a10150..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/image-model-v3.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { JSONArray, JSONValue } from '../../json-value'; -import { ImageModelV3Usage } from './image-model-v3-usage'; -import { ImageModelV3CallOptions } from './image-model-v3-call-options'; -import { SharedV3Warning } from '../../shared/v3/shared-v3-warning'; - -export type ImageModelV3ProviderMetadata = Record< - string, - { - images: JSONArray; - } & JSONValue ->; - -type GetMaxImagesPerCallFunction = (options: { - modelId: string; -}) => PromiseLike | number | undefined; - -/** - * Image generation model specification version 3. - */ -export type ImageModelV3 = { - /** - * The image model must specify which image model interface - * version it implements. This will allow us to evolve the image - * model interface and retain backwards compatibility. The different - * implementation versions can be handled as a discriminated union - * on our side. - */ - readonly specificationVersion: 'v3'; - - /** - * Name of the provider for logging purposes. - */ - readonly provider: string; - - /** - * Provider-specific model ID for logging purposes. - */ - readonly modelId: string; - - /** - * Limit of how many images can be generated in a single API call. - * Can be set to a number for a fixed limit, to undefined to use - * the global limit, or a function that returns a number or undefined, - * optionally as a promise. - */ - readonly maxImagesPerCall: number | undefined | GetMaxImagesPerCallFunction; - - /** - * Generates an array of images. - */ - doGenerate(options: ImageModelV3CallOptions): PromiseLike<{ - /** - * Generated images as base64 encoded strings or binary data. - * The images should be returned without any unnecessary conversion. - * If the API returns base64 encoded strings, the images should be returned - * as base64 encoded strings. If the API returns binary data, the images should - * be returned as binary data. - */ - images: Array | Array; - - /** - * Warnings for the call, e.g. unsupported features. - */ - warnings: Array; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - * - * The outer record is keyed by the provider name, and the inner - * record is provider-specific metadata. It always includes an - * `images` key with image-specific metadata - * - * ```ts - * { - * "openai": { - * "images": ["revisedPrompt": "Revised prompt here."] - * } - * } - * ``` - */ - providerMetadata?: ImageModelV3ProviderMetadata; - - /** - * Response information for telemetry and debugging purposes. - */ - response: { - /** - * Timestamp for the start of the generated response. - */ - timestamp: Date; - - /** - * The ID of the response model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers. - */ - headers: Record | undefined; - }; - - /** - * Optional token usage for the image generation call (if the provider reports it). - */ - usage?: ImageModelV3Usage; - }>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/index.ts deleted file mode 100644 index 06494af86..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/image-model/v3/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type { - ImageModelV3, - ImageModelV3ProviderMetadata, -} from './image-model-v3'; -export type { ImageModelV3CallOptions } from './image-model-v3-call-options'; -export type { ImageModelV3Usage } from './image-model-v3-usage'; -export type { ImageModelV3File } from './image-model-v3-file'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/index.ts deleted file mode 100644 index 8bfadb53f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -export * from './embedding-model/index'; -export * from './errors/index'; -export * from './image-model/index'; -export * from './image-model-middleware/index'; -export * from './json-value/index'; -export * from './language-model-middleware/index'; -export * from './embedding-model-middleware/index'; -export * from './language-model/index'; -export * from './provider/index'; -export * from './reranking-model/index'; -export * from './shared/index'; -export * from './speech-model/index'; -export * from './transcription-model/index'; -export * from './video-model/index'; - -export type { JSONSchema7, JSONSchema7Definition } from 'json-schema'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/json-value/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/json-value/index.ts deleted file mode 100644 index 55bd352c7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/json-value/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { isJSONArray, isJSONObject, isJSONValue } from './is-json'; -export type { JSONArray, JSONObject, JSONValue } from './json-value'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/json-value/is-json.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/json-value/is-json.ts deleted file mode 100644 index a6c1c0e71..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/json-value/is-json.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { JSONArray, JSONObject, JSONValue } from './json-value'; - -export function isJSONValue(value: unknown): value is JSONValue { - if ( - value === null || - typeof value === 'string' || - typeof value === 'number' || - typeof value === 'boolean' - ) { - return true; - } - - if (Array.isArray(value)) { - return value.every(isJSONValue); - } - - if (typeof value === 'object') { - return Object.entries(value).every( - ([key, val]) => - typeof key === 'string' && (val === undefined || isJSONValue(val)), - ); - } - - return false; -} - -export function isJSONArray(value: unknown): value is JSONArray { - return Array.isArray(value) && value.every(isJSONValue); -} - -export function isJSONObject(value: unknown): value is JSONObject { - return ( - value != null && - typeof value === 'object' && - Object.entries(value).every( - ([key, val]) => - typeof key === 'string' && (val === undefined || isJSONValue(val)), - ) - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/json-value/json-value.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/json-value/json-value.ts deleted file mode 100644 index 1ec7ab5cd..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/json-value/json-value.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * A JSON value can be a string, number, boolean, object, array, or null. - * JSON values can be serialized and deserialized by the JSON.stringify and JSON.parse methods. - */ -export type JSONValue = - | null - | string - | number - | boolean - | JSONObject - | JSONArray; - -export type JSONObject = { - [key: string]: JSONValue | undefined; -}; - -export type JSONArray = JSONValue[]; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/index.ts deleted file mode 100644 index f0a4a20cc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './v3/index'; -export * from './v2/index'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/v2/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/v2/index.ts deleted file mode 100644 index d41cfbd28..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/v2/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './language-model-v2-middleware'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/v2/language-model-v2-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/v2/language-model-v2-middleware.ts deleted file mode 100644 index e548ef0c0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/v2/language-model-v2-middleware.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { LanguageModelV2 } from '../../language-model/v2/language-model-v2'; -import { LanguageModelV2CallOptions } from '../../language-model/v2/language-model-v2-call-options'; - -/** - * Experimental middleware for LanguageModelV2. - * This type defines the structure for middleware that can be used to modify - * the behavior of LanguageModelV2 operations. - */ -export type LanguageModelV2Middleware = { - /** - * Middleware specification version. Use `v2` for the current version. - */ - middlewareVersion?: 'v2' | undefined; // backwards compatibility - - /** - * Override the provider name if desired. - * @param options.model - The language model instance. - */ - overrideProvider?: (options: { model: LanguageModelV2 }) => string; - - /** - * Override the model ID if desired. - * @param options.model - The language model instance. - */ - overrideModelId?: (options: { model: LanguageModelV2 }) => string; - - /** - * Override the supported URLs if desired. - * @param options.model - The language model instance. - */ - overrideSupportedUrls?: (options: { - model: LanguageModelV2; - }) => PromiseLike> | Record; - - /** - * Transforms the parameters before they are passed to the language model. - * @param options - Object containing the type of operation and the parameters. - * @param options.type - The type of operation ('generate' or 'stream'). - * @param options.params - The original parameters for the language model call. - * @returns A promise that resolves to the transformed parameters. - */ - transformParams?: (options: { - type: 'generate' | 'stream'; - params: LanguageModelV2CallOptions; - model: LanguageModelV2; - }) => PromiseLike; - - /** - * Wraps the generate operation of the language model. - * @param options - Object containing the generate function, parameters, and model. - * @param options.doGenerate - The original generate function. - * @param options.doStream - The original stream function. - * @param options.params - The parameters for the generate call. If the - * `transformParams` middleware is used, this will be the transformed parameters. - * @param options.model - The language model instance. - * @returns A promise that resolves to the result of the generate operation. - */ - wrapGenerate?: (options: { - doGenerate: () => ReturnType; - doStream: () => ReturnType; - params: LanguageModelV2CallOptions; - model: LanguageModelV2; - }) => Promise>>; - - /** - * Wraps the stream operation of the language model. - * - * @param options - Object containing the stream function, parameters, and model. - * @param options.doGenerate - The original generate function. - * @param options.doStream - The original stream function. - * @param options.params - The parameters for the stream call. If the - * `transformParams` middleware is used, this will be the transformed parameters. - * @param options.model - The language model instance. - * @returns A promise that resolves to the result of the stream operation. - */ - wrapStream?: (options: { - doGenerate: () => ReturnType; - doStream: () => ReturnType; - params: LanguageModelV2CallOptions; - model: LanguageModelV2; - }) => PromiseLike>>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/v3/index.ts deleted file mode 100644 index 4e88a2ebf..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/v3/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './language-model-v3-middleware'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/v3/language-model-v3-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/v3/language-model-v3-middleware.ts deleted file mode 100644 index 854e9ea90..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model-middleware/v3/language-model-v3-middleware.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { LanguageModelV3 } from '../../language-model/v3/language-model-v3'; -import { LanguageModelV3CallOptions } from '../../language-model/v3/language-model-v3-call-options'; -import { LanguageModelV3GenerateResult } from '../../language-model/v3/language-model-v3-generate-result'; -import { LanguageModelV3StreamResult } from '../../language-model/v3/language-model-v3-stream-result'; - -/** - * Experimental middleware for LanguageModelV3. - * This type defines the structure for middleware that can be used to modify - * the behavior of LanguageModelV3 operations. - */ -export type LanguageModelV3Middleware = { - /** - * Middleware specification version. Use `v3` for the current version. - */ - readonly specificationVersion: 'v3'; - - /** - * Override the provider name if desired. - * @param options.model - The language model instance. - */ - overrideProvider?: (options: { model: LanguageModelV3 }) => string; - - /** - * Override the model ID if desired. - * @param options.model - The language model instance. - */ - overrideModelId?: (options: { model: LanguageModelV3 }) => string; - - /** - * Override the supported URLs if desired. - * @param options.model - The language model instance. - */ - overrideSupportedUrls?: (options: { - model: LanguageModelV3; - }) => PromiseLike> | Record; - - /** - * Transforms the parameters before they are passed to the language model. - * @param options - Object containing the type of operation and the parameters. - * @param options.type - The type of operation ('generate' or 'stream'). - * @param options.params - The original parameters for the language model call. - * @returns A promise that resolves to the transformed parameters. - */ - transformParams?: (options: { - type: 'generate' | 'stream'; - params: LanguageModelV3CallOptions; - model: LanguageModelV3; - }) => PromiseLike; - - /** - * Wraps the generate operation of the language model. - * @param options - Object containing the generate function, parameters, and model. - * @param options.doGenerate - The original generate function. - * @param options.doStream - The original stream function. - * @param options.params - The parameters for the generate call. If the - * `transformParams` middleware is used, this will be the transformed parameters. - * @param options.model - The language model instance. - * @returns A promise that resolves to the result of the generate operation. - */ - wrapGenerate?: (options: { - doGenerate: () => PromiseLike; - doStream: () => PromiseLike; - params: LanguageModelV3CallOptions; - model: LanguageModelV3; - }) => PromiseLike; - - /** - * Wraps the stream operation of the language model. - * - * @param options - Object containing the stream function, parameters, and model. - * @param options.doGenerate - The original generate function. - * @param options.doStream - The original stream function. - * @param options.params - The parameters for the stream call. If the - * `transformParams` middleware is used, this will be the transformed parameters. - * @param options.model - The language model instance. - * @returns A promise that resolves to the result of the stream operation. - */ - wrapStream?: (options: { - doGenerate: () => PromiseLike; - doStream: () => PromiseLike; - params: LanguageModelV3CallOptions; - model: LanguageModelV3; - }) => PromiseLike; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/index.ts deleted file mode 100644 index f0a4a20cc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './v3/index'; -export * from './v2/index'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/index.ts deleted file mode 100644 index b0bb4279e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -export * from './language-model-v2'; -export * from './language-model-v2-call-options'; -export * from './language-model-v2-call-warning'; -export * from './language-model-v2-content'; -export * from './language-model-v2-data-content'; -export * from './language-model-v2-file'; -export * from './language-model-v2-finish-reason'; -export * from './language-model-v2-function-tool'; -export * from './language-model-v2-prompt'; -export * from './language-model-v2-provider-defined-tool'; -export * from './language-model-v2-reasoning'; -export * from './language-model-v2-response-metadata'; -export * from './language-model-v2-source'; -export * from './language-model-v2-stream-part'; -export * from './language-model-v2-text'; -export * from './language-model-v2-tool-call'; -export * from './language-model-v2-tool-choice'; -export * from './language-model-v2-usage'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-call-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-call-options.ts deleted file mode 100644 index f21ce04f6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-call-options.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { JSONSchema7 } from 'json-schema'; -import { SharedV2ProviderOptions } from '../../shared/v2/shared-v2-provider-options'; -import { LanguageModelV2FunctionTool } from './language-model-v2-function-tool'; -import { LanguageModelV2Prompt } from './language-model-v2-prompt'; -import { LanguageModelV2ProviderDefinedTool } from './language-model-v2-provider-defined-tool'; -import { LanguageModelV2ToolChoice } from './language-model-v2-tool-choice'; - -export type LanguageModelV2CallOptions = { - /** - * A language mode prompt is a standardized prompt type. - * - * Note: This is **not** the user-facing prompt. The AI SDK methods will map the - * user-facing prompt types such as chat or instruction prompts to this format. - * That approach allows us to evolve the user facing prompts without breaking - * the language model interface. - */ - prompt: LanguageModelV2Prompt; - - /** - * Maximum number of tokens to generate. - */ - maxOutputTokens?: number; - - /** - * Temperature setting. The range depends on the provider and model. - */ - temperature?: number; - - /** - * Stop sequences. - * If set, the model will stop generating text when one of the stop sequences is generated. - * Providers may have limits on the number of stop sequences. - */ - stopSequences?: string[]; - - /** - * Nucleus sampling. - */ - topP?: number; - - /** - * Only sample from the top K options for each subsequent token. - * - * Used to remove "long tail" low probability responses. - * Recommended for advanced use cases only. You usually only need to use temperature. - */ - topK?: number; - - /** - * Presence penalty setting. It affects the likelihood of the model to - * repeat information that is already in the prompt. - */ - presencePenalty?: number; - - /** - * Frequency penalty setting. It affects the likelihood of the model - * to repeatedly use the same words or phrases. - */ - frequencyPenalty?: number; - - /** - * Response format. The output can either be text or JSON. Default is text. - * - * If JSON is selected, a schema can optionally be provided to guide the LLM. - */ - responseFormat?: - | { type: 'text' } - | { - type: 'json'; - - /** - * JSON schema that the generated output should conform to. - */ - schema?: JSONSchema7; - - /** - * Name of output that should be generated. Used by some providers for additional LLM guidance. - */ - name?: string; - - /** - * Description of the output that should be generated. Used by some providers for additional LLM guidance. - */ - description?: string; - }; - - /** - * The seed (integer) to use for random sampling. If set and supported - * by the model, calls will generate deterministic results. - */ - seed?: number; - - /** - * The tools that are available for the model. - */ - tools?: Array< - LanguageModelV2FunctionTool | LanguageModelV2ProviderDefinedTool - >; - - /** - * Specifies how the tool should be selected. Defaults to 'auto'. - */ - toolChoice?: LanguageModelV2ToolChoice; - - /** - * Include raw chunks in the stream. Only applicable for streaming calls. - */ - includeRawChunks?: boolean; - - /** - * Abort signal for cancelling the operation. - */ - abortSignal?: AbortSignal; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV2ProviderOptions; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-call-warning.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-call-warning.ts deleted file mode 100644 index ba22880fc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-call-warning.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { LanguageModelV2CallOptions } from './language-model-v2-call-options'; -import { LanguageModelV2FunctionTool } from './language-model-v2-function-tool'; -import { LanguageModelV2ProviderDefinedTool } from './language-model-v2-provider-defined-tool'; - -/** - * Warning from the model provider for this call. The call will proceed, but e.g. - * some settings might not be supported, which can lead to suboptimal results. - */ -export type LanguageModelV2CallWarning = - | { - type: 'unsupported-setting'; - setting: Omit; - details?: string; - } - | { - type: 'unsupported-tool'; - tool: LanguageModelV2FunctionTool | LanguageModelV2ProviderDefinedTool; - details?: string; - } - | { - type: 'other'; - message: string; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-content.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-content.ts deleted file mode 100644 index 19a063bc5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-content.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { LanguageModelV2File } from './language-model-v2-file'; -import { LanguageModelV2Reasoning } from './language-model-v2-reasoning'; -import { LanguageModelV2Source } from './language-model-v2-source'; -import { LanguageModelV2Text } from './language-model-v2-text'; -import { LanguageModelV2ToolCall } from './language-model-v2-tool-call'; -import { LanguageModelV2ToolResult } from './language-model-v2-tool-result'; - -export type LanguageModelV2Content = - | LanguageModelV2Text - | LanguageModelV2Reasoning - | LanguageModelV2File - | LanguageModelV2Source - | LanguageModelV2ToolCall - | LanguageModelV2ToolResult; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-data-content.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-data-content.ts deleted file mode 100644 index eed128e43..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-data-content.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Data content. Can be a Uint8Array, base64 encoded data as a string or a URL. - */ -export type LanguageModelV2DataContent = Uint8Array | string | URL; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-file.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-file.ts deleted file mode 100644 index f887b5d34..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-file.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * A file that has been generated by the model. - * Generated files as base64 encoded strings or binary data. - * The files should be returned without any unnecessary conversion. - */ -export type LanguageModelV2File = { - type: 'file'; - - /** - * The IANA media type of the file, e.g. `image/png` or `audio/mp3`. - * - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Generated file data as base64 encoded strings or binary data. - * - * The file data should be returned without any unnecessary conversion. - * If the API returns base64 encoded strings, the file data should be returned - * as base64 encoded strings. If the API returns binary data, the file data should - * be returned as binary data. - */ - data: string | Uint8Array; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-finish-reason.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-finish-reason.ts deleted file mode 100644 index 8a571f534..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-finish-reason.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Reason why a language model finished generating a response. - * - * Can be one of the following: - * - `stop`: model generated stop sequence - * - `length`: model generated maximum number of tokens - * - `content-filter`: content filter violation stopped the model - * - `tool-calls`: model triggered tool calls - * - `error`: model stopped because of an error - * - `other`: model stopped for other reasons - * - `unknown`: the model has not transmitted a finish reason - */ -export type LanguageModelV2FinishReason = - | 'stop' // model generated stop sequence - | 'length' // model generated maximum number of tokens - | 'content-filter' // content filter violation stopped the model - | 'tool-calls' // model triggered tool calls - | 'error' // model stopped because of an error - | 'other' // model stopped for other reasons - | 'unknown'; // the model has not transmitted a finish reason diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-function-tool.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-function-tool.ts deleted file mode 100644 index b8cb325d9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-function-tool.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { JSONSchema7 } from 'json-schema'; -import { SharedV2ProviderOptions } from '../../shared'; - -/** - * A tool has a name, a description, and a set of parameters. - * - * Note: this is **not** the user-facing tool definition. The AI SDK methods will - * map the user-facing tool definitions to this format. - */ -export type LanguageModelV2FunctionTool = { - /** - * The type of the tool (always 'function'). - */ - type: 'function'; - - /** - * The name of the tool. Unique within this model call. - */ - name: string; - - /** - * A description of the tool. The language model uses this to understand the - * tool's purpose and to provide better completion suggestions. - */ - description?: string; - - /** - * The parameters that the tool expects. The language model uses this to - * understand the tool's input requirements and to provide matching suggestions. - */ - inputSchema: JSONSchema7; - - /** - * The provider-specific options for the tool. - */ - providerOptions?: SharedV2ProviderOptions; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-prompt.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-prompt.ts deleted file mode 100644 index 29254c6f8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-prompt.ts +++ /dev/null @@ -1,218 +0,0 @@ -import { JSONValue } from '../../json-value/json-value'; -import { SharedV2ProviderOptions } from '../../shared/v2/shared-v2-provider-options'; -import { LanguageModelV2DataContent } from './language-model-v2-data-content'; - -/** - * A prompt is a list of messages. - * - * Note: Not all models and prompt formats support multi-modal inputs and - * tool calls. The validation happens at runtime. - * - * Note: This is not a user-facing prompt. The AI SDK methods will map the - * user-facing prompt types such as chat or instruction prompts to this format. - */ -export type LanguageModelV2Prompt = Array; - -export type LanguageModelV2Message = - // Note: there could be additional parts for each role in the future, - // e.g. when the assistant can return images or the user can share files - // such as PDFs. - ( - | { - role: 'system'; - content: string; - } - | { - role: 'user'; - content: Array; - } - | { - role: 'assistant'; - content: Array< - | LanguageModelV2TextPart - | LanguageModelV2FilePart - | LanguageModelV2ReasoningPart - | LanguageModelV2ToolCallPart - | LanguageModelV2ToolResultPart - >; - } - | { - role: 'tool'; - content: Array; - } - ) & { - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV2ProviderOptions; - }; - -/** - * Text content part of a prompt. It contains a string of text. - */ -export interface LanguageModelV2TextPart { - type: 'text'; - - /** - * The text content. - */ - text: string; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV2ProviderOptions; -} - -/** - * Reasoning content part of a prompt. It contains a string of reasoning text. - */ -export interface LanguageModelV2ReasoningPart { - type: 'reasoning'; - - /** - * The reasoning text. - */ - text: string; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV2ProviderOptions; -} - -/** - * File content part of a prompt. It contains a file. - */ -export interface LanguageModelV2FilePart { - type: 'file'; - - /** - * Optional filename of the file. - */ - filename?: string; - - /** - * File data. Can be a Uint8Array, base64 encoded data as a string or a URL. - */ - data: LanguageModelV2DataContent; - - /** - * IANA media type of the file. - * - * Can support wildcards, e.g. `image/*` (in which case the provider needs to take appropriate action). - * - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV2ProviderOptions; -} - -/** - * Tool call content part of a prompt. It contains a tool call (usually generated by the AI model). - */ -export interface LanguageModelV2ToolCallPart { - type: 'tool-call'; - - /** - * ID of the tool call. This ID is used to match the tool call with the tool result. - */ - toolCallId: string; - - /** - * Name of the tool that is being called. - */ - toolName: string; - - /** - * Arguments of the tool call. This is a JSON-serializable object that matches the tool's input schema. - */ - input: unknown; - - /** - * Whether the tool call will be executed by the provider. - * If this flag is not set or is false, the tool call will be executed by the client. - */ - providerExecuted?: boolean; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV2ProviderOptions; -} - -/** - * Tool result content part of a prompt. It contains the result of the tool call with the matching ID. - */ -export interface LanguageModelV2ToolResultPart { - type: 'tool-result'; - - /** - * ID of the tool call that this result is associated with. - */ - toolCallId: string; - - /** - * Name of the tool that generated this result. - */ - toolName: string; - - /** - * Result of the tool call. - */ - output: LanguageModelV2ToolResultOutput; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV2ProviderOptions; -} - -export type LanguageModelV2ToolResultOutput = - | { type: 'text'; value: string } - | { type: 'json'; value: JSONValue } - | { type: 'error-text'; value: string } - | { type: 'error-json'; value: JSONValue } - | { - type: 'content'; - value: Array< - | { - type: 'text'; - - /** - * Text content. - */ - text: string; - } - | { - type: 'media'; - - /** - * Base-64 encoded media data. - */ - data: string; - - /** - * IANA media type. - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - } - >; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-provider-defined-tool.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-provider-defined-tool.ts deleted file mode 100644 index 8cf2eaa04..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-provider-defined-tool.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * The configuration of a tool that is defined by the provider. - */ -export type LanguageModelV2ProviderDefinedTool = { - /** - * The type of the tool (always 'provider-defined'). - */ - type: 'provider-defined'; - - /** - * The ID of the tool. Should follow the format `.`. - */ - id: `${string}.${string}`; - - /** - * The name of the tool that the user must use in the tool set. - */ - name: string; - - /** - * The arguments for configuring the tool. Must match the expected arguments defined by the provider for this tool. - */ - args: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-reasoning.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-reasoning.ts deleted file mode 100644 index 0b76933cb..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-reasoning.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { SharedV2ProviderMetadata } from '../../shared'; - -/** - * Reasoning that the model has generated. - */ -export type LanguageModelV2Reasoning = { - type: 'reasoning'; - text: string; - - /** - * Optional provider-specific metadata for the reasoning part. - */ - providerMetadata?: SharedV2ProviderMetadata; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-response-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-response-metadata.ts deleted file mode 100644 index 6fe959a99..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-response-metadata.ts +++ /dev/null @@ -1,16 +0,0 @@ -export interface LanguageModelV2ResponseMetadata { - /** - * ID for the generated response, if the provider sends one. - */ - id?: string; - - /** - * Timestamp for the start of the generated response, if the provider sends one. - */ - timestamp?: Date; - - /** - * The ID of the response model that was used to generate the response, if the provider sends one. - */ - modelId?: string; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-source.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-source.ts deleted file mode 100644 index 25b59a45d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-source.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { SharedV2ProviderMetadata } from '../../shared/v2/shared-v2-provider-metadata'; - -/** - * A source that has been used as input to generate the response. - */ -export type LanguageModelV2Source = - | { - type: 'source'; - - /** - * The type of source - URL sources reference web content. - */ - sourceType: 'url'; - - /** - * The ID of the source. - */ - id: string; - - /** - * The URL of the source. - */ - url: string; - - /** - * The title of the source. - */ - title?: string; - - /** - * Additional provider metadata for the source. - */ - providerMetadata?: SharedV2ProviderMetadata; - } - | { - type: 'source'; - - /** - * The type of source - document sources reference files/documents. - */ - sourceType: 'document'; - - /** - * The ID of the source. - */ - id: string; - - /** - * IANA media type of the document (e.g., 'application/pdf'). - */ - mediaType: string; - - /** - * The title of the document. - */ - title: string; - - /** - * Optional filename of the document. - */ - filename?: string; - - /** - * Additional provider metadata for the source. - */ - providerMetadata?: SharedV2ProviderMetadata; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-stream-part.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-stream-part.ts deleted file mode 100644 index 7ef46f3d5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-stream-part.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { SharedV2ProviderMetadata } from '../../shared/v2/shared-v2-provider-metadata'; -import { LanguageModelV2CallWarning } from './language-model-v2-call-warning'; -import { LanguageModelV2File } from './language-model-v2-file'; -import { LanguageModelV2FinishReason } from './language-model-v2-finish-reason'; -import { LanguageModelV2ResponseMetadata } from './language-model-v2-response-metadata'; -import { LanguageModelV2Source } from './language-model-v2-source'; -import { LanguageModelV2ToolCall } from './language-model-v2-tool-call'; -import { LanguageModelV2ToolResult } from './language-model-v2-tool-result'; -import { LanguageModelV2Usage } from './language-model-v2-usage'; - -export type LanguageModelV2StreamPart = - // Text blocks: - | { - type: 'text-start'; - providerMetadata?: SharedV2ProviderMetadata; - id: string; - } - | { - type: 'text-delta'; - id: string; - providerMetadata?: SharedV2ProviderMetadata; - delta: string; - } - | { - type: 'text-end'; - providerMetadata?: SharedV2ProviderMetadata; - id: string; - } - - // Reasoning blocks: - | { - type: 'reasoning-start'; - providerMetadata?: SharedV2ProviderMetadata; - id: string; - } - | { - type: 'reasoning-delta'; - id: string; - providerMetadata?: SharedV2ProviderMetadata; - delta: string; - } - | { - type: 'reasoning-end'; - id: string; - providerMetadata?: SharedV2ProviderMetadata; - } - - // Tool calls and results: - | { - type: 'tool-input-start'; - id: string; - toolName: string; - providerMetadata?: SharedV2ProviderMetadata; - providerExecuted?: boolean; - } - | { - type: 'tool-input-delta'; - id: string; - delta: string; - providerMetadata?: SharedV2ProviderMetadata; - } - | { - type: 'tool-input-end'; - id: string; - providerMetadata?: SharedV2ProviderMetadata; - } - | LanguageModelV2ToolCall - | LanguageModelV2ToolResult - - // Files and sources: - | LanguageModelV2File - | LanguageModelV2Source - - // stream start event with warnings for the call, e.g. unsupported settings: - | { - type: 'stream-start'; - warnings: Array; - } - - // metadata for the response. - // separate stream part so it can be sent once it is available. - | ({ type: 'response-metadata' } & LanguageModelV2ResponseMetadata) - - // metadata that is available after the stream is finished: - | { - type: 'finish'; - usage: LanguageModelV2Usage; - finishReason: LanguageModelV2FinishReason; - providerMetadata?: SharedV2ProviderMetadata; - } - - // raw chunks if enabled - | { - type: 'raw'; - rawValue: unknown; - } - - // error parts are streamed, allowing for multiple errors - | { - type: 'error'; - error: unknown; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-text.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-text.ts deleted file mode 100644 index 622221513..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-text.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { SharedV2ProviderMetadata } from '../../shared/v2/shared-v2-provider-metadata'; - -/** - * Text that the model has generated. - */ -export type LanguageModelV2Text = { - type: 'text'; - - /** - * The text content. - */ - text: string; - - providerMetadata?: SharedV2ProviderMetadata; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-tool-call.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-tool-call.ts deleted file mode 100644 index eb1dc972b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-tool-call.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { SharedV2ProviderMetadata } from '../../shared/v2/shared-v2-provider-metadata'; - -/** - * Tool calls that the model has generated. - */ -export type LanguageModelV2ToolCall = { - type: 'tool-call'; - - /** - * The identifier of the tool call. It must be unique across all tool calls. - */ - toolCallId: string; - - /** - * The name of the tool that should be called. - */ - toolName: string; - - /** - * Stringified JSON object with the tool call arguments. Must match the - * parameters schema of the tool. - */ - input: string; - - /** - * Whether the tool call will be executed by the provider. - * If this flag is not set or is false, the tool call will be executed by the client. - */ - providerExecuted?: boolean; - - /** - * Additional provider-specific metadata for the tool call. - */ - providerMetadata?: SharedV2ProviderMetadata; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-tool-choice.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-tool-choice.ts deleted file mode 100644 index 2c7d00c63..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-tool-choice.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type LanguageModelV2ToolChoice = - | { type: 'auto' } // the tool selection is automatic (can be no tool) - | { type: 'none' } // no tool must be selected - | { type: 'required' } // one of the available tools must be selected - | { type: 'tool'; toolName: string }; // a specific tool must be selected: diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-tool-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-tool-result.ts deleted file mode 100644 index 5aa2b00a0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-tool-result.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { SharedV2ProviderMetadata } from '../../shared/v2/shared-v2-provider-metadata'; - -/** - * Result of a tool call that has been executed by the provider. - */ -export type LanguageModelV2ToolResult = { - type: 'tool-result'; - - /** - * The ID of the tool call that this result is associated with. - */ - toolCallId: string; - - /** - * Name of the tool that generated this result. - */ - toolName: string; - - /** - * Result of the tool call. This is a JSON-serializable object. - */ - result: unknown; - - /** - * Optional flag if the result is an error or an error message. - */ - isError?: boolean; - - /** - * Whether the tool result was generated by the provider. - * If this flag is set to true, the tool result was generated by the provider. - * If this flag is not set or is false, the tool result was generated by the client. - */ - providerExecuted?: boolean; - - /** - * Additional provider-specific metadata for the tool result. - */ - providerMetadata?: SharedV2ProviderMetadata; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-usage.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-usage.ts deleted file mode 100644 index 0e87ff47c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2-usage.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Usage information for a language model call. - * - * If your API return additional usage information, you can add it to the - * provider metadata under your provider's key. - */ -export type LanguageModelV2Usage = { - /** - * The number of input (prompt) tokens used. - */ - inputTokens: number | undefined; - - /** - * The number of output (completion) tokens used. - */ - outputTokens: number | undefined; - - /** - * The total number of tokens as reported by the provider. - * This number might be different from the sum of `inputTokens` and `outputTokens` - * and e.g. include reasoning tokens or other overhead. - */ - totalTokens: number | undefined; - - /** - * The number of reasoning tokens used. - */ - reasoningTokens?: number | undefined; - - /** - * The number of cached input tokens. - */ - cachedInputTokens?: number | undefined; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2.ts deleted file mode 100644 index b7d19762c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v2/language-model-v2.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { SharedV2Headers } from '../../shared'; -import { SharedV2ProviderMetadata } from '../../shared/v2/shared-v2-provider-metadata'; -import { LanguageModelV2CallOptions } from './language-model-v2-call-options'; -import { LanguageModelV2CallWarning } from './language-model-v2-call-warning'; -import { LanguageModelV2Content } from './language-model-v2-content'; -import { LanguageModelV2FinishReason } from './language-model-v2-finish-reason'; -import { LanguageModelV2ResponseMetadata } from './language-model-v2-response-metadata'; -import { LanguageModelV2StreamPart } from './language-model-v2-stream-part'; -import { LanguageModelV2Usage } from './language-model-v2-usage'; - -/** - * Specification for a language model that implements the language model interface version 2. - */ -export type LanguageModelV2 = { - /** - * The language model must specify which language model interface version it implements. - */ - readonly specificationVersion: 'v2'; - - /** - * Name of the provider for logging purposes. - */ - readonly provider: string; - - /** - * Provider-specific model ID for logging purposes. - */ - readonly modelId: string; - - /** - * Supported URL patterns by media type for the provider. - * - * The keys are media type patterns or full media types (e.g. `*\/*` for everything, `audio/*`, `video/*`, or `application/pdf`). - * and the values are arrays of regular expressions that match the URL paths. - * - * The matching should be against lower-case URLs. - * - * Matched URLs are supported natively by the model and are not downloaded. - * - * @returns A map of supported URL patterns by media type (as a promise or a plain object). - */ - supportedUrls: - | PromiseLike> - | Record; - - /** - * Generates a language model output (non-streaming). - * - * Naming: "do" prefix to prevent accidental direct usage of the method - * by the user. - */ - doGenerate(options: LanguageModelV2CallOptions): PromiseLike<{ - /** - * Ordered content that the model has generated. - */ - content: Array; - - /** - * Finish reason. - */ - finishReason: LanguageModelV2FinishReason; - - /** - * Usage information. - */ - usage: LanguageModelV2Usage; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - providerMetadata?: SharedV2ProviderMetadata; - - /** - * Optional request information for telemetry and debugging purposes. - */ - request?: { - /** - * Request HTTP body that was sent to the provider API. - */ - body?: unknown; - }; - - /** - * Optional response information for telemetry and debugging purposes. - */ - response?: LanguageModelV2ResponseMetadata & { - /** - * Response headers. - */ - headers?: SharedV2Headers; - - /** - * Response HTTP body. - */ - body?: unknown; - }; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - warnings: Array; - }>; - - /** - * Generates a language model output (streaming). - * - * Naming: "do" prefix to prevent accidental direct usage of the method - * by the user. - * - * @return A stream of higher-level language model output parts. - */ - doStream(options: LanguageModelV2CallOptions): PromiseLike<{ - stream: ReadableStream; - - /** - * Optional request information for telemetry and debugging purposes. - */ - request?: { - /** - * Request HTTP body that was sent to the provider API. - */ - body?: unknown; - }; - - /** - * Optional response data. - */ - response?: { - /** - * Response headers. - */ - headers?: SharedV2Headers; - }; - }>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/index.ts deleted file mode 100644 index 4294793a4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -export * from './language-model-v3'; -export * from './language-model-v3-call-options'; -export * from './language-model-v3-content'; -export * from './language-model-v3-data-content'; -export * from './language-model-v3-file'; -export * from './language-model-v3-finish-reason'; -export * from './language-model-v3-function-tool'; -export * from './language-model-v3-generate-result'; -export * from './language-model-v3-prompt'; -export * from './language-model-v3-provider-tool'; -export * from './language-model-v3-reasoning'; -export * from './language-model-v3-response-metadata'; -export * from './language-model-v3-source'; -export * from './language-model-v3-stream-part'; -export * from './language-model-v3-stream-result'; -export * from './language-model-v3-text'; -export * from './language-model-v3-tool-approval-request'; -export * from './language-model-v3-tool-call'; -export * from './language-model-v3-tool-choice'; -export * from './language-model-v3-tool-result'; -export * from './language-model-v3-usage'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-call-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-call-options.ts deleted file mode 100644 index 820438be6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-call-options.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { JSONSchema7 } from 'json-schema'; -import { SharedV3ProviderOptions } from '../../shared/v3/shared-v3-provider-options'; -import { LanguageModelV3FunctionTool } from './language-model-v3-function-tool'; -import { LanguageModelV3Prompt } from './language-model-v3-prompt'; -import { LanguageModelV3ProviderTool } from './language-model-v3-provider-tool'; -import { LanguageModelV3ToolChoice } from './language-model-v3-tool-choice'; - -export type LanguageModelV3CallOptions = { - /** - * A language mode prompt is a standardized prompt type. - * - * Note: This is **not** the user-facing prompt. The AI SDK methods will map the - * user-facing prompt types such as chat or instruction prompts to this format. - * That approach allows us to evolve the user facing prompts without breaking - * the language model interface. - */ - prompt: LanguageModelV3Prompt; - - /** - * Maximum number of tokens to generate. - */ - maxOutputTokens?: number; - - /** - * Temperature setting. The range depends on the provider and model. - */ - temperature?: number; - - /** - * Stop sequences. - * If set, the model will stop generating text when one of the stop sequences is generated. - * Providers may have limits on the number of stop sequences. - */ - stopSequences?: string[]; - - /** - * Nucleus sampling. - */ - topP?: number; - - /** - * Only sample from the top K options for each subsequent token. - * - * Used to remove "long tail" low probability responses. - * Recommended for advanced use cases only. You usually only need to use temperature. - */ - topK?: number; - - /** - * Presence penalty setting. It affects the likelihood of the model to - * repeat information that is already in the prompt. - */ - presencePenalty?: number; - - /** - * Frequency penalty setting. It affects the likelihood of the model - * to repeatedly use the same words or phrases. - */ - frequencyPenalty?: number; - - /** - * Response format. The output can either be text or JSON. Default is text. - * - * If JSON is selected, a schema can optionally be provided to guide the LLM. - */ - responseFormat?: - | { type: 'text' } - | { - type: 'json'; - - /** - * JSON schema that the generated output should conform to. - */ - schema?: JSONSchema7; - - /** - * Name of output that should be generated. Used by some providers for additional LLM guidance. - */ - name?: string; - - /** - * Description of the output that should be generated. Used by some providers for additional LLM guidance. - */ - description?: string; - }; - - /** - * The seed (integer) to use for random sampling. If set and supported - * by the model, calls will generate deterministic results. - */ - seed?: number; - - /** - * The tools that are available for the model. - */ - tools?: Array; - - /** - * Specifies how the tool should be selected. Defaults to 'auto'. - */ - toolChoice?: LanguageModelV3ToolChoice; - - /** - * Include raw chunks in the stream. Only applicable for streaming calls. - */ - includeRawChunks?: boolean; - - /** - * Abort signal for cancelling the operation. - */ - abortSignal?: AbortSignal; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV3ProviderOptions; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-content.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-content.ts deleted file mode 100644 index 9f0806e3a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-content.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { LanguageModelV3File } from './language-model-v3-file'; -import { LanguageModelV3Reasoning } from './language-model-v3-reasoning'; -import { LanguageModelV3Source } from './language-model-v3-source'; -import { LanguageModelV3Text } from './language-model-v3-text'; -import { LanguageModelV3ToolApprovalRequest } from './language-model-v3-tool-approval-request'; -import { LanguageModelV3ToolCall } from './language-model-v3-tool-call'; -import { LanguageModelV3ToolResult } from './language-model-v3-tool-result'; - -export type LanguageModelV3Content = - | LanguageModelV3Text - | LanguageModelV3Reasoning - | LanguageModelV3File - | LanguageModelV3ToolApprovalRequest - | LanguageModelV3Source - | LanguageModelV3ToolCall - | LanguageModelV3ToolResult; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-data-content.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-data-content.ts deleted file mode 100644 index ba1acdeea..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-data-content.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Data content. Can be a Uint8Array, base64 encoded data as a string or a URL. - */ -export type LanguageModelV3DataContent = Uint8Array | string | URL; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-file.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-file.ts deleted file mode 100644 index 5828ab4cc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-file.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { SharedV3ProviderMetadata } from '../../shared'; - -/** - * A file that has been generated by the model. - * Generated files as base64 encoded strings or binary data. - * The files should be returned without any unnecessary conversion. - */ -export type LanguageModelV3File = { - type: 'file'; - - /** - * The IANA media type of the file, e.g. `image/png` or `audio/mp3`. - * - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Generated file data as base64 encoded strings or binary data. - * - * The file data should be returned without any unnecessary conversion. - * If the API returns base64 encoded strings, the file data should be returned - * as base64 encoded strings. If the API returns binary data, the file data should - * be returned as binary data. - */ - data: string | Uint8Array; - - /** - * Optional provider-specific metadata for the file part. - */ - providerMetadata?: SharedV3ProviderMetadata; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-finish-reason.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-finish-reason.ts deleted file mode 100644 index 9e3447620..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-finish-reason.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Reason why a language model finished generating a response. - * - * Contains both a unified finish reason and a raw finish reason from the provider. - * The unified finish reason is used to provide a consistent finish reason across different providers. - * The raw finish reason is used to provide the original finish reason from the provider. - */ -export type LanguageModelV3FinishReason = { - /** - * Unified finish reason. This enables using the same finish reason across different providers. - * - * Can be one of the following: - * - `stop`: model generated stop sequence - * - `length`: model generated maximum number of tokens - * - `content-filter`: content filter violation stopped the model - * - `tool-calls`: model triggered tool calls - * - `error`: model stopped because of an error - * - `other`: model stopped for other reasons - */ - unified: - | 'stop' - | 'length' - | 'content-filter' - | 'tool-calls' - | 'error' - | 'other'; - - /** - * Raw finish reason from the provider. - * This is the original finish reason from the provider. - */ - raw: string | undefined; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-function-tool.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-function-tool.ts deleted file mode 100644 index 4c00087b9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-function-tool.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { JSONSchema7 } from 'json-schema'; -import { SharedV3ProviderOptions } from '../../shared'; -import { JSONObject } from '../../json-value'; - -/** - * A tool has a name, a description, and a set of parameters. - * - * Note: this is **not** the user-facing tool definition. The AI SDK methods will - * map the user-facing tool definitions to this format. - */ -export type LanguageModelV3FunctionTool = { - /** - * The type of the tool (always 'function'). - */ - type: 'function'; - - /** - * The name of the tool. Unique within this model call. - */ - name: string; - - /** - * A description of the tool. The language model uses this to understand the - * tool's purpose and to provide better completion suggestions. - */ - description?: string; - - /** - * The parameters that the tool expects. The language model uses this to - * understand the tool's input requirements and to provide matching suggestions. - */ - inputSchema: JSONSchema7; - - /** - * An optional list of input examples that show the language - * model what the input should look like. - */ - inputExamples?: Array<{ input: JSONObject }>; - - /** - * Strict mode setting for the tool. - * - * Providers that support strict mode will use this setting to determine - * how the input should be generated. Strict mode will always produce - * valid inputs, but it might limit what input schemas are supported. - */ - strict?: boolean; - - /** - * The provider-specific options for the tool. - */ - providerOptions?: SharedV3ProviderOptions; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-generate-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-generate-result.ts deleted file mode 100644 index c06dbb1b2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-generate-result.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { SharedV3Headers, SharedV3Warning } from '../../shared'; -import { SharedV3ProviderMetadata } from '../../shared/v3/shared-v3-provider-metadata'; -import { LanguageModelV3Content } from './language-model-v3-content'; -import { LanguageModelV3FinishReason } from './language-model-v3-finish-reason'; -import { LanguageModelV3ResponseMetadata } from './language-model-v3-response-metadata'; -import { LanguageModelV3Usage } from './language-model-v3-usage'; - -/** - * The result of a language model doGenerate call. - */ -export type LanguageModelV3GenerateResult = { - /** - * Ordered content that the model has generated. - */ - content: Array; - - /** - * The finish reason. - */ - finishReason: LanguageModelV3FinishReason; - - /** - * The usage information. - */ - usage: LanguageModelV3Usage; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - providerMetadata?: SharedV3ProviderMetadata; - - /** - * Optional request information for telemetry and debugging purposes. - */ - request?: { - /** - * Request HTTP body that was sent to the provider API. - */ - body?: unknown; - }; - - /** - * Optional response information for telemetry and debugging purposes. - */ - response?: LanguageModelV3ResponseMetadata & { - /** - * Response headers. - */ - headers?: SharedV3Headers; - - /** - * Response HTTP body. - */ - body?: unknown; - }; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - warnings: Array; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-prompt.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-prompt.ts deleted file mode 100644 index 8203afa64..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-prompt.ts +++ /dev/null @@ -1,422 +0,0 @@ -import { JSONValue } from '../../json-value/json-value'; -import { SharedV3ProviderOptions } from '../../shared/v3/shared-v3-provider-options'; -import { LanguageModelV3DataContent } from './language-model-v3-data-content'; - -/** - * A prompt is a list of messages. - * - * Note: Not all models and prompt formats support multi-modal inputs and - * tool calls. The validation happens at runtime. - * - * Note: This is not a user-facing prompt. The AI SDK methods will map the - * user-facing prompt types such as chat or instruction prompts to this format. - */ -export type LanguageModelV3Prompt = Array; - -export type LanguageModelV3Message = - // Note: there could be additional parts for each role in the future, - // e.g. when the assistant can return images or the user can share files - // such as PDFs. - ( - | { - role: 'system'; - content: string; - } - | { - role: 'user'; - content: Array; - } - | { - role: 'assistant'; - content: Array< - | LanguageModelV3TextPart - | LanguageModelV3FilePart - | LanguageModelV3ReasoningPart - | LanguageModelV3ToolCallPart - | LanguageModelV3ToolResultPart - >; - } - | { - role: 'tool'; - content: Array< - | LanguageModelV3ToolResultPart - | LanguageModelV3ToolApprovalResponsePart - >; - } - ) & { - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV3ProviderOptions; - }; - -/** - * Text content part of a prompt. It contains a string of text. - */ -export interface LanguageModelV3TextPart { - type: 'text'; - - /** - * The text content. - */ - text: string; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV3ProviderOptions; -} - -/** - * Reasoning content part of a prompt. It contains a string of reasoning text. - */ -export interface LanguageModelV3ReasoningPart { - type: 'reasoning'; - - /** - * The reasoning text. - */ - text: string; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV3ProviderOptions; -} - -/** - * File content part of a prompt. It contains a file. - */ -export interface LanguageModelV3FilePart { - type: 'file'; - - /** - * Optional filename of the file. - */ - filename?: string; - - /** - * File data. Can be a Uint8Array, base64 encoded data as a string or a URL. - */ - data: LanguageModelV3DataContent; - - /** - * IANA media type of the file. - * - * Can support wildcards, e.g. `image/*` (in which case the provider needs to take appropriate action). - * - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV3ProviderOptions; -} - -/** - * Tool call content part of a prompt. It contains a tool call (usually generated by the AI model). - */ -export interface LanguageModelV3ToolCallPart { - type: 'tool-call'; - - /** - * ID of the tool call. This ID is used to match the tool call with the tool result. - */ - toolCallId: string; - - /** - * Name of the tool that is being called. - */ - toolName: string; - - /** - * Arguments of the tool call. This is a JSON-serializable object that matches the tool's input schema. - */ - input: unknown; - - /** - * Whether the tool call will be executed by the provider. - * If this flag is not set or is false, the tool call will be executed by the client. - */ - providerExecuted?: boolean; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV3ProviderOptions; -} - -/** - * Tool result content part of a prompt. It contains the result of the tool call with the matching ID. - */ -export interface LanguageModelV3ToolResultPart { - type: 'tool-result'; - - /** - * ID of the tool call that this result is associated with. - */ - toolCallId: string; - - /** - * Name of the tool that generated this result. - */ - toolName: string; - - /** - * Result of the tool call. - */ - output: LanguageModelV3ToolResultOutput; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV3ProviderOptions; -} - -/** - * Tool approval response content part of a prompt. It contains the user's - * decision to approve or deny a provider-executed tool call. - */ -export interface LanguageModelV3ToolApprovalResponsePart { - type: 'tool-approval-response'; - - /** - * ID of the approval request that this response refers to. - */ - approvalId: string; - - /** - * Whether the approval was granted (true) or denied (false). - */ - approved: boolean; - - /** - * Optional reason for approval or denial. - */ - reason?: string; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV3ProviderOptions; -} - -/** - * Result of a tool call. - */ -export type LanguageModelV3ToolResultOutput = - | { - /** - * Text tool output that should be directly sent to the API. - */ - type: 'text'; - value: string; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - | { - type: 'json'; - value: JSONValue; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - | { - /** - * Type when the user has denied the execution of the tool call. - */ - type: 'execution-denied'; - - /** - * Optional reason for the execution denial. - */ - reason?: string; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - | { - type: 'error-text'; - value: string; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - | { - type: 'error-json'; - value: JSONValue; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - | { - type: 'content'; - value: Array< - | { - type: 'text'; - - /** - * Text content. - */ - text: string; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - | { - type: 'file-data'; - - /** - * Base-64 encoded media data. - */ - data: string; - - /** - * IANA media type. - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Optional filename of the file. - */ - filename?: string; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - | { - type: 'file-url'; - - /** - * URL of the file. - */ - url: string; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - | { - type: 'file-id'; - - /** - * ID of the file. - * - * If you use multiple providers, you need to - * specify the provider specific ids using - * the Record option. The key is the provider - * name, e.g. 'openai' or 'anthropic'. - */ - fileId: string | Record; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - | { - /** - * Images that are referenced using base64 encoded data. - */ - type: 'image-data'; - - /** - * Base-64 encoded image data. - */ - data: string; - - /** - * IANA media type. - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - | { - /** - * Images that are referenced using a URL. - */ - type: 'image-url'; - - /** - * URL of the image. - */ - url: string; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - | { - /** - * Images that are referenced using a provider file id. - */ - type: 'image-file-id'; - - /** - * Image that is referenced using a provider file id. - * - * If you use multiple providers, you need to - * specify the provider specific ids using - * the Record option. The key is the provider - * name, e.g. 'openai' or 'anthropic'. - */ - fileId: string | Record; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - | { - /** - * Custom content part. This can be used to implement - * provider-specific content parts. - */ - type: 'custom'; - - /** - * Provider-specific options. - */ - providerOptions?: SharedV3ProviderOptions; - } - >; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-provider-tool.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-provider-tool.ts deleted file mode 100644 index 4520aa7fc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-provider-tool.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * The configuration of a provider tool. - * - * Provider tools are tools that are specific to a certain provider. - * The input and output schemas are defined be the provider, and - * some of the tools are also executed on the provider systems. - */ -export type LanguageModelV3ProviderTool = { - /** - * The type of the tool (always 'provider'). - */ - type: 'provider'; - - /** - * The ID of the tool. Should follow the format `.`. - */ - id: `${string}.${string}`; - - /** - * The name of the tool. Unique within this model call. - */ - name: string; - - /** - * The arguments for configuring the tool. Must match the expected arguments defined by the provider for this tool. - */ - args: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-reasoning.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-reasoning.ts deleted file mode 100644 index af55926a6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-reasoning.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { SharedV3ProviderMetadata } from '../../shared'; - -/** - * Reasoning that the model has generated. - */ -export type LanguageModelV3Reasoning = { - type: 'reasoning'; - text: string; - - /** - * Optional provider-specific metadata for the reasoning part. - */ - providerMetadata?: SharedV3ProviderMetadata; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-response-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-response-metadata.ts deleted file mode 100644 index b862e3584..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-response-metadata.ts +++ /dev/null @@ -1,16 +0,0 @@ -export interface LanguageModelV3ResponseMetadata { - /** - * ID for the generated response, if the provider sends one. - */ - id?: string; - - /** - * Timestamp for the start of the generated response, if the provider sends one. - */ - timestamp?: Date; - - /** - * The ID of the response model that was used to generate the response, if the provider sends one. - */ - modelId?: string; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-source.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-source.ts deleted file mode 100644 index 67d14082c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-source.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { SharedV3ProviderMetadata } from '../../shared/v3/shared-v3-provider-metadata'; - -/** - * A source that has been used as input to generate the response. - */ -export type LanguageModelV3Source = - | { - type: 'source'; - - /** - * The type of source - URL sources reference web content. - */ - sourceType: 'url'; - - /** - * The ID of the source. - */ - id: string; - - /** - * The URL of the source. - */ - url: string; - - /** - * The title of the source. - */ - title?: string; - - /** - * Additional provider metadata for the source. - */ - providerMetadata?: SharedV3ProviderMetadata; - } - | { - type: 'source'; - - /** - * The type of source - document sources reference files/documents. - */ - sourceType: 'document'; - - /** - * The ID of the source. - */ - id: string; - - /** - * IANA media type of the document (e.g., 'application/pdf'). - */ - mediaType: string; - - /** - * The title of the document. - */ - title: string; - - /** - * Optional filename of the document. - */ - filename?: string; - - /** - * Additional provider metadata for the source. - */ - providerMetadata?: SharedV3ProviderMetadata; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-stream-part.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-stream-part.ts deleted file mode 100644 index f7915c438..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-stream-part.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { SharedV3ProviderMetadata } from '../../shared/v3/shared-v3-provider-metadata'; -import { SharedV3Warning } from '../../shared/v3/shared-v3-warning'; -import { LanguageModelV3File } from './language-model-v3-file'; -import { LanguageModelV3FinishReason } from './language-model-v3-finish-reason'; -import { LanguageModelV3ResponseMetadata } from './language-model-v3-response-metadata'; -import { LanguageModelV3Source } from './language-model-v3-source'; -import { LanguageModelV3ToolApprovalRequest } from './language-model-v3-tool-approval-request'; -import { LanguageModelV3ToolCall } from './language-model-v3-tool-call'; -import { LanguageModelV3ToolResult } from './language-model-v3-tool-result'; -import { LanguageModelV3Usage } from './language-model-v3-usage'; - -export type LanguageModelV3StreamPart = - // Text blocks: - | { - type: 'text-start'; - providerMetadata?: SharedV3ProviderMetadata; - id: string; - } - | { - type: 'text-delta'; - id: string; - providerMetadata?: SharedV3ProviderMetadata; - delta: string; - } - | { - type: 'text-end'; - providerMetadata?: SharedV3ProviderMetadata; - id: string; - } - - // Reasoning blocks: - | { - type: 'reasoning-start'; - providerMetadata?: SharedV3ProviderMetadata; - id: string; - } - | { - type: 'reasoning-delta'; - id: string; - providerMetadata?: SharedV3ProviderMetadata; - delta: string; - } - | { - type: 'reasoning-end'; - id: string; - providerMetadata?: SharedV3ProviderMetadata; - } - - // Tool calls and results: - | { - type: 'tool-input-start'; - id: string; - toolName: string; - providerMetadata?: SharedV3ProviderMetadata; - providerExecuted?: boolean; - dynamic?: boolean; - title?: string; - } - | { - type: 'tool-input-delta'; - id: string; - delta: string; - providerMetadata?: SharedV3ProviderMetadata; - } - | { - type: 'tool-input-end'; - id: string; - providerMetadata?: SharedV3ProviderMetadata; - } - | LanguageModelV3ToolApprovalRequest - | LanguageModelV3ToolCall - | LanguageModelV3ToolResult - - // Files and sources: - | LanguageModelV3File - | LanguageModelV3Source - - // stream start event with warnings for the call, e.g. unsupported settings: - | { - type: 'stream-start'; - warnings: Array; - } - - // metadata for the response. - // separate stream part so it can be sent once it is available. - | ({ type: 'response-metadata' } & LanguageModelV3ResponseMetadata) - - // metadata that is available after the stream is finished: - | { - type: 'finish'; - usage: LanguageModelV3Usage; - finishReason: LanguageModelV3FinishReason; - providerMetadata?: SharedV3ProviderMetadata; - } - - // raw chunks if enabled - | { - type: 'raw'; - rawValue: unknown; - } - - // error parts are streamed, allowing for multiple errors - | { - type: 'error'; - error: unknown; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-stream-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-stream-result.ts deleted file mode 100644 index c9ed38907..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-stream-result.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { SharedV3Headers } from '../../shared'; -import { LanguageModelV3StreamPart } from './language-model-v3-stream-part'; - -/** - * The result of a language model doStream call. - */ -export type LanguageModelV3StreamResult = { - /** - * The stream. - */ - stream: ReadableStream; - - /** - * Optional request information for telemetry and debugging purposes. - */ - request?: { - /** - * Request HTTP body that was sent to the provider API. - */ - body?: unknown; - }; - - /** - * Optional response data. - */ - response?: { - /** - * Response headers. - */ - headers?: SharedV3Headers; - }; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-text.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-text.ts deleted file mode 100644 index a4adf690d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-text.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { SharedV3ProviderMetadata } from '../../shared/v3/shared-v3-provider-metadata'; - -/** - * Text that the model has generated. - */ -export type LanguageModelV3Text = { - type: 'text'; - - /** - * The text content. - */ - text: string; - - providerMetadata?: SharedV3ProviderMetadata; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-tool-approval-request.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-tool-approval-request.ts deleted file mode 100644 index 92c694933..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-tool-approval-request.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { SharedV3ProviderMetadata } from '../../shared/v3/shared-v3-provider-metadata'; - -/** - * Tool approval request emitted by a provider for a provider-executed tool call. - * - * This is used for flows where the provider executes the tool (e.g. MCP tools) - * but requires an explicit user approval before continuing. - */ -export type LanguageModelV3ToolApprovalRequest = { - type: 'tool-approval-request'; - - /** - * ID of the approval request. This ID is referenced by the subsequent - * tool-approval-response (tool message) to approve or deny execution. - */ - approvalId: string; - - /** - * The tool call ID that this approval request is for. - */ - toolCallId: string; - - /** - * Additional provider-specific metadata for the approval request. - */ - providerMetadata?: SharedV3ProviderMetadata; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-tool-call.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-tool-call.ts deleted file mode 100644 index 66f7502e3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-tool-call.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { SharedV3ProviderMetadata } from '../../shared/v3/shared-v3-provider-metadata'; - -/** - * Tool calls that the model has generated. - */ -export type LanguageModelV3ToolCall = { - type: 'tool-call'; - - /** - * The identifier of the tool call. It must be unique across all tool calls. - */ - toolCallId: string; - - /** - * The name of the tool that should be called. - */ - toolName: string; - - /** - * Stringified JSON object with the tool call arguments. Must match the - * parameters schema of the tool. - */ - input: string; - - /** - * Whether the tool call will be executed by the provider. - * If this flag is not set or is false, the tool call will be executed by the client. - */ - providerExecuted?: boolean; - - /** - * Whether the tool is dynamic, i.e. defined at runtime. - * For example, MCP (Model Context Protocol) tools that are executed by the provider. - */ - dynamic?: boolean; - - /** - * Additional provider-specific metadata for the tool call. - */ - providerMetadata?: SharedV3ProviderMetadata; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-tool-choice.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-tool-choice.ts deleted file mode 100644 index 3d386036e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-tool-choice.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type LanguageModelV3ToolChoice = - | { type: 'auto' } // the tool selection is automatic (can be no tool) - | { type: 'none' } // no tool must be selected - | { type: 'required' } // one of the available tools must be selected - | { type: 'tool'; toolName: string }; // a specific tool must be selected: diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-tool-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-tool-result.ts deleted file mode 100644 index b53b7f141..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-tool-result.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { JSONValue } from '../../json-value'; -import { SharedV3ProviderMetadata } from '../../shared/v3/shared-v3-provider-metadata'; - -/** - * Result of a tool call that has been executed by the provider. - */ -export type LanguageModelV3ToolResult = { - type: 'tool-result'; - - /** - * The ID of the tool call that this result is associated with. - */ - toolCallId: string; - - /** - * Name of the tool that generated this result. - */ - toolName: string; - - /** - * Result of the tool call. This is a JSON-serializable object. - */ - result: NonNullable; - - /** - * Optional flag if the result is an error or an error message. - */ - isError?: boolean; - - /** - * Whether the tool result is preliminary. - * - * Preliminary tool results replace each other, e.g. image previews. - * There always has to be a final, non-preliminary tool result. - * - * If this flag is set to true, the tool result is preliminary. - * If this flag is not set or is false, the tool result is not preliminary. - */ - preliminary?: boolean; - - /** - * Whether the tool is dynamic, i.e. defined at runtime. - * For example, MCP (Model Context Protocol) tools that are executed by the provider. - */ - dynamic?: boolean; - - /** - * Additional provider-specific metadata for the tool result. - */ - providerMetadata?: SharedV3ProviderMetadata; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-usage.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-usage.ts deleted file mode 100644 index b43bfdde3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3-usage.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { JSONObject } from '../../json-value'; - -/** - * Usage information for a language model call. - */ -export type LanguageModelV3Usage = { - /** - * Information about the input tokens. - */ - inputTokens: { - /** - * The total number of input (prompt) tokens used. - */ - total: number | undefined; - - /** - * The number of non-cached input (prompt) tokens used. - */ - noCache: number | undefined; - - /** - * The number of cached input (prompt) tokens read. - */ - cacheRead: number | undefined; - - /** - * The number of cached input (prompt) tokens written. - */ - cacheWrite: number | undefined; - }; - - /** - * Information about the output tokens. - */ - outputTokens: { - /** - * The total number of output (completion) tokens used. - */ - total: number | undefined; - - /** - * The number of text tokens used. - */ - text: number | undefined; - - /** - * The number of reasoning tokens used. - */ - reasoning: number | undefined; - }; - - /** - * Raw usage information from the provider. - * - * This is the usage information in the shape that the provider returns. - * It can include additional information that is not part of the standard usage information. - */ - raw?: JSONObject; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3.ts deleted file mode 100644 index 4021d3dec..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/language-model/v3/language-model-v3.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { LanguageModelV3CallOptions } from './language-model-v3-call-options'; -import { LanguageModelV3GenerateResult } from './language-model-v3-generate-result'; -import { LanguageModelV3StreamResult } from './language-model-v3-stream-result'; - -/** - * Specification for a language model that implements the language model interface version 3. - */ -export type LanguageModelV3 = { - /** - * The language model must specify which language model interface version it implements. - */ - readonly specificationVersion: 'v3'; - - /** - * Provider ID. - */ - readonly provider: string; - - /** - * Provider-specific model ID. - */ - readonly modelId: string; - - /** - * Supported URL patterns by media type for the provider. - * - * The keys are media type patterns or full media types (e.g. `*\/*` for everything, `audio/*`, `video/*`, or `application/pdf`). - * and the values are arrays of regular expressions that match the URL paths. - * - * The matching should be against lower-case URLs. - * - * Matched URLs are supported natively by the model and are not downloaded. - * - * @returns A map of supported URL patterns by media type (as a promise or a plain object). - */ - supportedUrls: - | PromiseLike> - | Record; - - /** - * Generates a language model output (non-streaming). - - * Naming: "do" prefix to prevent accidental direct usage of the method - * by the user. - */ - doGenerate( - options: LanguageModelV3CallOptions, - ): PromiseLike; - - /** - * Generates a language model output (streaming). - * - * Naming: "do" prefix to prevent accidental direct usage of the method - * by the user. - * - * @return A stream of higher-level language model output parts. - */ - doStream( - options: LanguageModelV3CallOptions, - ): PromiseLike; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/index.ts deleted file mode 100644 index f0a4a20cc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './v3/index'; -export * from './v2/index'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/v2/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/v2/index.ts deleted file mode 100644 index 08d9d6c4b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/v2/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type { ProviderV2 } from './provider-v2'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/v2/provider-v2.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/v2/provider-v2.ts deleted file mode 100644 index 8b8d8ec13..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/v2/provider-v2.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { EmbeddingModelV2 } from '../../embedding-model/v2/embedding-model-v2'; -import { ImageModelV2 } from '../../image-model/v2/image-model-v2'; -import { LanguageModelV2 } from '../../language-model/v2/language-model-v2'; -import { SpeechModelV2 } from '../../speech-model/v2/speech-model-v2'; -import { TranscriptionModelV2 } from '../../transcription-model/v2/transcription-model-v2'; - -/** - * Provider for language, text embedding, and image generation models. - */ -export interface ProviderV2 { - /** - * Returns the language model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {LanguageModel} The language model associated with the id - * - * @throws {NoSuchModelError} If no such model exists. - */ - languageModel(modelId: string): LanguageModelV2; - - /** - * Returns the text embedding model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {LanguageModel} The language model associated with the id - * - * @throws {NoSuchModelError} If no such model exists. - */ - textEmbeddingModel(modelId: string): EmbeddingModelV2; - - /** - * Returns the image model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {ImageModel} The image model associated with the id - */ - imageModel(modelId: string): ImageModelV2; - - /** - * Returns the transcription model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {TranscriptionModel} The transcription model associated with the id - */ - transcriptionModel?(modelId: string): TranscriptionModelV2; - - /** - * Returns the speech model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {SpeechModel} The speech model associated with the id - */ - speechModel?(modelId: string): SpeechModelV2; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/v3/index.ts deleted file mode 100644 index 23561cb54..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/v3/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type { ProviderV3 } from './provider-v3'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/v3/provider-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/v3/provider-v3.ts deleted file mode 100644 index 98fc5a9b5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/provider/v3/provider-v3.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { EmbeddingModelV3 } from '../../embedding-model/v3/embedding-model-v3'; -import { ImageModelV3 } from '../../image-model/v3/image-model-v3'; -import { LanguageModelV3 } from '../../language-model/v3/language-model-v3'; -import { RerankingModelV3 } from '../../reranking-model/v3/reranking-model-v3'; -import { SpeechModelV3 } from '../../speech-model/v3/speech-model-v3'; -import { TranscriptionModelV3 } from '../../transcription-model/v3/transcription-model-v3'; - -/** - * Provider for language, text embedding, and image generation models. - */ -export interface ProviderV3 { - readonly specificationVersion: 'v3'; - - /** - * Returns the language model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {LanguageModel} The language model associated with the id - * - * @throws {NoSuchModelError} If no such model exists. - */ - languageModel(modelId: string): LanguageModelV3; - - /** - * Returns the text embedding model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {LanguageModel} The language model associated with the id - * - * @throws {NoSuchModelError} If no such model exists. - */ - embeddingModel(modelId: string): EmbeddingModelV3; - - /** - * Returns the text embedding model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {EmbeddingModel} The embedding model associated with the id - * - * @throws {NoSuchModelError} If no such model exists. - * - * @deprecated Use `embeddingModel` instead. - */ - textEmbeddingModel?(modelId: string): EmbeddingModelV3; - - /** - * Returns the image model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {ImageModel} The image model associated with the id - */ - imageModel(modelId: string): ImageModelV3; - - /** - * Returns the transcription model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {TranscriptionModel} The transcription model associated with the id - */ - transcriptionModel?(modelId: string): TranscriptionModelV3; - - /** - * Returns the speech model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {SpeechModel} The speech model associated with the id - */ - speechModel?(modelId: string): SpeechModelV3; - - /** - * Returns the reranking model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {RerankingModel} The reranking model associated with the id - * - * @throws {NoSuchModelError} If no such model exists. - */ - rerankingModel?(modelId: string): RerankingModelV3; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/reranking-model/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/reranking-model/index.ts deleted file mode 100644 index ca7b39f38..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/reranking-model/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './v3/index'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/reranking-model/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/reranking-model/v3/index.ts deleted file mode 100644 index 9d54b9093..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/reranking-model/v3/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export type { RerankingModelV3 } from './reranking-model-v3'; -export type { RerankingModelV3CallOptions } from './reranking-model-v3-call-options'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/reranking-model/v3/reranking-model-v3-call-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/reranking-model/v3/reranking-model-v3-call-options.ts deleted file mode 100644 index 8fd464664..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/reranking-model/v3/reranking-model-v3-call-options.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { JSONObject } from '../../json-value'; -import { SharedV3Headers, SharedV3ProviderOptions } from '../../shared/v3'; - -export type RerankingModelV3CallOptions = { - /** - * Documents to rerank. - * Either a list of texts or a list of JSON objects. - */ - documents: - | { type: 'text'; values: string[] } - | { type: 'object'; values: JSONObject[] }; - - /** - * The query is a string that represents the query to rerank the documents against. - */ - query: string; - - /** - * Optional limit returned documents to the top n documents. - */ - topN?: number; - - /** - * Abort signal for cancelling the operation. - */ - abortSignal?: AbortSignal; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: SharedV3ProviderOptions; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: SharedV3Headers; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/reranking-model/v3/reranking-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/reranking-model/v3/reranking-model-v3.ts deleted file mode 100644 index 3c403a997..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/reranking-model/v3/reranking-model-v3.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { - SharedV3Headers, - SharedV3ProviderMetadata, - SharedV3Warning, -} from '../../shared/v3/'; -import { RerankingModelV3CallOptions } from './reranking-model-v3-call-options'; - -/** - * Specification for a reranking model that implements the reranking model interface version 3. - */ -export type RerankingModelV3 = { - /** - * The reranking model must specify which reranking model interface version it implements. - */ - readonly specificationVersion: 'v3'; - - /** - * Provider ID. - */ - readonly provider: string; - - /** - * Provider-specific model ID. - */ - readonly modelId: string; - - /** - * Reranking a list of documents using the query. - */ - // Naming: "do" prefix to prevent accidental direct usage of the method by the user. - doRerank(options: RerankingModelV3CallOptions): PromiseLike<{ - /** - * Ordered list of reranked documents (via index before reranking). - * The documents are sorted by the descending order of relevance scores. - */ - ranking: Array<{ - /** - * The index of the document in the original list of documents before reranking. - */ - index: number; - - /** - * The relevance score of the document after reranking. - */ - relevanceScore: number; - }>; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerMetadata?: SharedV3ProviderMetadata; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - warnings?: Array; - - /** - * Optional response information for debugging purposes. - */ - response?: { - /** - * ID for the generated response, if the provider sends one. - */ - id?: string; - - /** - * Timestamp for the start of the generated response, if the provider sends one. - */ - timestamp?: Date; - - /** - * The ID of the response model that was used to generate the response, if the provider sends one. - */ - modelId?: string; - - /** - * Response headers. - */ - headers?: SharedV3Headers; - - /** - * Response body. - */ - body?: unknown; - }; - }>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/index.ts deleted file mode 100644 index f0a4a20cc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './v3/index'; -export * from './v2/index'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v2/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v2/index.ts deleted file mode 100644 index e41d84a34..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v2/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './shared-v2-headers'; -export * from './shared-v2-provider-metadata'; -export * from './shared-v2-provider-options'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v2/shared-v2-headers.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v2/shared-v2-headers.ts deleted file mode 100644 index 4be7da5c1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v2/shared-v2-headers.ts +++ /dev/null @@ -1 +0,0 @@ -export type SharedV2Headers = Record; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v2/shared-v2-provider-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v2/shared-v2-provider-metadata.ts deleted file mode 100644 index c3b880ca4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v2/shared-v2-provider-metadata.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { JSONValue } from '../../json-value/json-value'; - -/** - * Additional provider-specific metadata. - * Metadata are additional outputs from the provider. - * They are passed through to the provider from the AI SDK - * and enable provider-specific functionality - * that can be fully encapsulated in the provider. - * - * This enables us to quickly ship provider-specific functionality - * without affecting the core AI SDK. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * - * ```ts - * { - * "anthropic": { - * "cacheControl": { "type": "ephemeral" } - * } - * } - * ``` - */ -export type SharedV2ProviderMetadata = Record< - string, - Record ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v2/shared-v2-provider-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v2/shared-v2-provider-options.ts deleted file mode 100644 index 17c8c947c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v2/shared-v2-provider-options.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { JSONValue } from '../../json-value/json-value'; - -/** - * Additional provider-specific options. - * Options are additional input to the provider. - * They are passed through to the provider from the AI SDK - * and enable provider-specific functionality - * that can be fully encapsulated in the provider. - * - * This enables us to quickly ship provider-specific functionality - * without affecting the core AI SDK. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * - * ```ts - * { - * "anthropic": { - * "cacheControl": { "type": "ephemeral" } - * } - * } - * ``` - */ -export type SharedV2ProviderOptions = Record>; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/index.ts deleted file mode 100644 index 4abdc44b3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './shared-v3-headers'; -export * from './shared-v3-provider-metadata'; -export * from './shared-v3-provider-options'; -export * from './shared-v3-warning'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/shared-v3-headers.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/shared-v3-headers.ts deleted file mode 100644 index 02046309b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/shared-v3-headers.ts +++ /dev/null @@ -1 +0,0 @@ -export type SharedV3Headers = Record; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/shared-v3-provider-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/shared-v3-provider-metadata.ts deleted file mode 100644 index 635ab8fff..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/shared-v3-provider-metadata.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { JSONObject } from '../../json-value/json-value'; - -/** - * Additional provider-specific metadata. - * Metadata are additional outputs from the provider. - * They are passed through to the provider from the AI SDK - * and enable provider-specific functionality - * that can be fully encapsulated in the provider. - * - * This enables us to quickly ship provider-specific functionality - * without affecting the core AI SDK. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * - * ```ts - * { - * "anthropic": { - * "cacheControl": { "type": "ephemeral" } - * } - * } - * ``` - */ -export type SharedV3ProviderMetadata = Record; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/shared-v3-provider-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/shared-v3-provider-options.ts deleted file mode 100644 index 0d35c67ed..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/shared-v3-provider-options.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { JSONObject } from '../../json-value/json-value'; - -/** - * Additional provider-specific options. - * Options are additional input to the provider. - * They are passed through to the provider from the AI SDK - * and enable provider-specific functionality - * that can be fully encapsulated in the provider. - * - * This enables us to quickly ship provider-specific functionality - * without affecting the core AI SDK. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * - * ```ts - * { - * "anthropic": { - * "cacheControl": { "type": "ephemeral" } - * } - * } - * ``` - */ -export type SharedV3ProviderOptions = Record; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/shared-v3-warning.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/shared-v3-warning.ts deleted file mode 100644 index 1625a1c36..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/shared/v3/shared-v3-warning.ts +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Warning from the model. - * - * For example, that certain features are unsupported or compatibility - * functionality is used (which might lead to suboptimal results). - */ -export type SharedV3Warning = - | { - /** - * A feature is not supported by the model. - */ - type: 'unsupported'; - - /** - * The feature that is not supported. - */ - feature: string; - - /** - * Additional details about the warning. - */ - details?: string; - } - | { - /** - * A compatibility feature is used that might lead to suboptimal results. - */ - type: 'compatibility'; - - /** - * The feature that is used in a compatibility mode. - */ - feature: string; - - /** - * Additional details about the warning. - */ - details?: string; - } - | { - /** - * Other warning. - */ - type: 'other'; - - /** - * The message of the warning. - */ - message: string; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/index.ts deleted file mode 100644 index cc2132526..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './v2/index'; -export * from './v3/index'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v2/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v2/index.ts deleted file mode 100644 index 548bb0dba..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v2/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type { SpeechModelV2 } from './speech-model-v2'; -export type { SpeechModelV2CallOptions } from './speech-model-v2-call-options'; -export type { SpeechModelV2CallWarning } from './speech-model-v2-call-warning'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v2/speech-model-v2-call-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v2/speech-model-v2-call-options.ts deleted file mode 100644 index 94c2158a0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v2/speech-model-v2-call-options.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { JSONValue } from '../../json-value/json-value'; - -type SpeechModelV2ProviderOptions = Record>; - -export type SpeechModelV2CallOptions = { - /** - * Text to convert to speech. - */ - text: string; - - /** - * The voice to use for speech synthesis. - * This is provider-specific and may be a voice ID, name, or other identifier. - */ - voice?: string; - - /** - * The desired output format for the audio e.g. "mp3", "wav", etc. - */ - outputFormat?: string; - - /** - * Instructions for the speech generation e.g. "Speak in a slow and steady tone". - */ - instructions?: string; - - /** - * The speed of the speech generation. - */ - speed?: number; - - /** - * The language for speech generation. This should be an ISO 639-1 language code (e.g. "en", "es", "fr") - * or "auto" for automatic language detection. Provider support varies. - */ - language?: string; - - /** - * Additional provider-specific options that are passed through to the provider - * as body parameters. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * ```ts - * { - * "openai": {} - * } - * ``` - */ - providerOptions?: SpeechModelV2ProviderOptions; - - /** - * Abort signal for cancelling the operation. - */ - abortSignal?: AbortSignal; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v2/speech-model-v2-call-warning.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v2/speech-model-v2-call-warning.ts deleted file mode 100644 index 95aa718f4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v2/speech-model-v2-call-warning.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { SpeechModelV2CallOptions } from './speech-model-v2-call-options'; - -/** - * Warning from the model provider for this call. The call will proceed, but e.g. - * some settings might not be supported, which can lead to suboptimal results. - */ -export type SpeechModelV2CallWarning = - | { - type: 'unsupported-setting'; - setting: keyof SpeechModelV2CallOptions; - details?: string; - } - | { - type: 'other'; - message: string; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v2/speech-model-v2.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v2/speech-model-v2.ts deleted file mode 100644 index ba6992b52..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v2/speech-model-v2.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { JSONValue } from '../../json-value'; -import { SharedV2Headers } from '../../shared'; -import { SpeechModelV2CallOptions } from './speech-model-v2-call-options'; -import { SpeechModelV2CallWarning } from './speech-model-v2-call-warning'; - -/** - * Speech model specification version 2. - */ -export type SpeechModelV2 = { - /** - * The speech model must specify which speech model interface - * version it implements. This will allow us to evolve the speech - * model interface and retain backwards compatibility. The different - * implementation versions can be handled as a discriminated union - * on our side. - */ - readonly specificationVersion: 'v2'; - - /** - * Name of the provider for logging purposes. - */ - readonly provider: string; - - /** - * Provider-specific model ID for logging purposes. - */ - readonly modelId: string; - - /** - * Generates speech audio from text. - */ - doGenerate(options: SpeechModelV2CallOptions): PromiseLike<{ - /** - * Generated audio as an ArrayBuffer. - * The audio should be returned without any unnecessary conversion. - * If the API returns base64 encoded strings, the audio should be returned - * as base64 encoded strings. If the API returns binary data, the audio - * should be returned as binary data. - */ - audio: string | Uint8Array; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - warnings: Array; - - /** - * Optional request information for telemetry and debugging purposes. - */ - request?: { - /** - * Response body (available only for providers that use HTTP requests). - */ - body?: unknown; - }; - - /** - * Response information for telemetry and debugging purposes. - */ - response: { - /** - * Timestamp for the start of the generated response. - */ - timestamp: Date; - - /** - * The ID of the response model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers. - */ - headers?: SharedV2Headers; - - /** - * Response body. - */ - body?: unknown; - }; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - providerMetadata?: Record>; - }>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v3/index.ts deleted file mode 100644 index f35147e71..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v3/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export type { SpeechModelV3 } from './speech-model-v3'; -export type { SpeechModelV3CallOptions } from './speech-model-v3-call-options'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v3/speech-model-v3-call-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v3/speech-model-v3-call-options.ts deleted file mode 100644 index 39119b3da..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v3/speech-model-v3-call-options.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { JSONObject } from '../../json-value/json-value'; - -type SpeechModelV3ProviderOptions = Record; - -export type SpeechModelV3CallOptions = { - /** - * Text to convert to speech. - */ - text: string; - - /** - * The voice to use for speech synthesis. - * This is provider-specific and may be a voice ID, name, or other identifier. - */ - voice?: string; - - /** - * The desired output format for the audio e.g. "mp3", "wav", etc. - */ - outputFormat?: string; - - /** - * Instructions for the speech generation e.g. "Speak in a slow and steady tone". - */ - instructions?: string; - - /** - * The speed of the speech generation. - */ - speed?: number; - - /** - * The language for speech generation. This should be an ISO 639-1 language code (e.g. "en", "es", "fr") - * or "auto" for automatic language detection. Provider support varies. - */ - language?: string; - - /** - * Additional provider-specific options that are passed through to the provider - * as body parameters. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * ```ts - * { - * "openai": {} - * } - * ``` - */ - providerOptions?: SpeechModelV3ProviderOptions; - - /** - * Abort signal for cancelling the operation. - */ - abortSignal?: AbortSignal; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v3/speech-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v3/speech-model-v3.ts deleted file mode 100644 index 65794e385..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/speech-model/v3/speech-model-v3.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { JSONObject } from '../../json-value'; -import { SharedV2Headers } from '../../shared'; -import { SharedV3Warning } from '../../shared/v3/shared-v3-warning'; -import { SpeechModelV3CallOptions } from './speech-model-v3-call-options'; - -/** - * Speech model specification version 3. - */ -export type SpeechModelV3 = { - /** - * The speech model must specify which speech model interface - * version it implements. This will allow us to evolve the speech - * model interface and retain backwards compatibility. The different - * implementation versions can be handled as a discriminated union - * on our side. - */ - readonly specificationVersion: 'v3'; - - /** - * Name of the provider for logging purposes. - */ - readonly provider: string; - - /** - * Provider-specific model ID for logging purposes. - */ - readonly modelId: string; - - /** - * Generates speech audio from text. - */ - doGenerate(options: SpeechModelV3CallOptions): PromiseLike<{ - /** - * Generated audio as an ArrayBuffer. - * The audio should be returned without any unnecessary conversion. - * If the API returns base64 encoded strings, the audio should be returned - * as base64 encoded strings. If the API returns binary data, the audio - * should be returned as binary data. - */ - audio: string | Uint8Array; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - warnings: Array; - - /** - * Optional request information for telemetry and debugging purposes. - */ - request?: { - /** - * Response body (available only for providers that use HTTP requests). - */ - body?: unknown; - }; - - /** - * Response information for telemetry and debugging purposes. - */ - response: { - /** - * Timestamp for the start of the generated response. - */ - timestamp: Date; - - /** - * The ID of the response model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers. - */ - headers?: SharedV2Headers; - - /** - * Response body. - */ - body?: unknown; - }; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - providerMetadata?: Record; - }>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/index.ts deleted file mode 100644 index cc2132526..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './v2/index'; -export * from './v3/index'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v2/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v2/index.ts deleted file mode 100644 index ca92d8d1c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v2/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type { TranscriptionModelV2 } from './transcription-model-v2'; -export type { TranscriptionModelV2CallOptions } from './transcription-model-v2-call-options'; -export type { TranscriptionModelV2CallWarning } from './transcription-model-v2-call-warning'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v2/transcription-model-v2-call-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v2/transcription-model-v2-call-options.ts deleted file mode 100644 index b79facbc4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v2/transcription-model-v2-call-options.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { JSONValue } from '../../json-value/json-value'; - -type TranscriptionModelV2ProviderOptions = Record< - string, - Record ->; - -export type TranscriptionModelV2CallOptions = { - /** - * Audio data to transcribe. - * Accepts a `Uint8Array` or `string`, where `string` is a base64 encoded audio file. - */ - audio: Uint8Array | string; - - /** - * The IANA media type of the audio data. - * - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Additional provider-specific options that are passed through to the provider - * as body parameters. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * ```ts - * { - * "openai": { - * "timestampGranularities": ["word"] - * } - * } - * ``` - */ - providerOptions?: TranscriptionModelV2ProviderOptions; - - /** - * Abort signal for cancelling the operation. - */ - abortSignal?: AbortSignal; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v2/transcription-model-v2-call-warning.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v2/transcription-model-v2-call-warning.ts deleted file mode 100644 index b06780f60..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v2/transcription-model-v2-call-warning.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TranscriptionModelV2CallOptions } from './transcription-model-v2-call-options'; - -/** - * Warning from the model provider for this call. The call will proceed, but e.g. - * some settings might not be supported, which can lead to suboptimal results. - */ -export type TranscriptionModelV2CallWarning = - | { - type: 'unsupported-setting'; - setting: keyof TranscriptionModelV2CallOptions; - details?: string; - } - | { - type: 'other'; - message: string; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v2/transcription-model-v2.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v2/transcription-model-v2.ts deleted file mode 100644 index 28da8e735..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v2/transcription-model-v2.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { JSONValue } from '../../json-value'; -import { SharedV2Headers } from '../../shared'; -import { TranscriptionModelV2CallOptions } from './transcription-model-v2-call-options'; -import { TranscriptionModelV2CallWarning } from './transcription-model-v2-call-warning'; - -/** - * Transcription model specification version 2. - */ -export type TranscriptionModelV2 = { - /** - * The transcription model must specify which transcription model interface - * version it implements. This will allow us to evolve the transcription - * model interface and retain backwards compatibility. The different - * implementation versions can be handled as a discriminated union - * on our side. - */ - readonly specificationVersion: 'v2'; - - /** - * Name of the provider for logging purposes. - */ - readonly provider: string; - - /** - * Provider-specific model ID for logging purposes. - */ - readonly modelId: string; - - /** - * Generates a transcript. - */ - doGenerate(options: TranscriptionModelV2CallOptions): PromiseLike<{ - /** - * The complete transcribed text from the audio. - */ - text: string; - - /** - * Array of transcript segments with timing information. - * Each segment represents a portion of the transcribed text with start and end times. - */ - segments: Array<{ - /** - * The text content of this segment. - */ - text: string; - /** - * The start time of this segment in seconds. - */ - startSecond: number; - /** - * The end time of this segment in seconds. - */ - endSecond: number; - }>; - - /** - * The detected language of the audio content, as an ISO-639-1 code (e.g., 'en' for English). - * May be undefined if the language couldn't be detected. - */ - language: string | undefined; - - /** - * The total duration of the audio file in seconds. - * May be undefined if the duration couldn't be determined. - */ - durationInSeconds: number | undefined; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - warnings: Array; - - /** - * Optional request information for telemetry and debugging purposes. - */ - request?: { - /** - * Raw request HTTP body that was sent to the provider API as a string (JSON should be stringified). - * Non-HTTP(s) providers should not set this. - */ - body?: string; - }; - - /** - * Response information for telemetry and debugging purposes. - */ - response: { - /** - * Timestamp for the start of the generated response. - */ - timestamp: Date; - - /** - * The ID of the response model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers. - */ - headers?: SharedV2Headers; - - /** - * Response body. - */ - body?: unknown; - }; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - providerMetadata?: Record>; - }>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v3/index.ts deleted file mode 100644 index 0e2ca820e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v3/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export type { TranscriptionModelV3 } from './transcription-model-v3'; -export type { TranscriptionModelV3CallOptions } from './transcription-model-v3-call-options'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v3/transcription-model-v3-call-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v3/transcription-model-v3-call-options.ts deleted file mode 100644 index 380745ed1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v3/transcription-model-v3-call-options.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { JSONObject } from '../../json-value/json-value'; - -type TranscriptionModelV3ProviderOptions = Record; - -export type TranscriptionModelV3CallOptions = { - /** - * Audio data to transcribe. - * Accepts a `Uint8Array` or `string`, where `string` is a base64 encoded audio file. - */ - audio: Uint8Array | string; - - /** - * The IANA media type of the audio data. - * - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Additional provider-specific options that are passed through to the provider - * as body parameters. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * ```ts - * { - * "openai": { - * "timestampGranularities": ["word"] - * } - * } - * ``` - */ - providerOptions?: TranscriptionModelV3ProviderOptions; - - /** - * Abort signal for cancelling the operation. - */ - abortSignal?: AbortSignal; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v3/transcription-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v3/transcription-model-v3.ts deleted file mode 100644 index 068155aab..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/transcription-model/v3/transcription-model-v3.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { JSONObject } from '../../json-value'; -import { SharedV3Headers } from '../../shared'; -import { SharedV3Warning } from '../../shared/v3/shared-v3-warning'; -import { TranscriptionModelV3CallOptions } from './transcription-model-v3-call-options'; - -/** - * Transcription model specification version 3. - */ -export type TranscriptionModelV3 = { - /** - * The transcription model must specify which transcription model interface - * version it implements. This will allow us to evolve the transcription - * model interface and retain backwards compatibility. The different - * implementation versions can be handled as a discriminated union - * on our side. - */ - readonly specificationVersion: 'v3'; - - /** - * Name of the provider for logging purposes. - */ - readonly provider: string; - - /** - * Provider-specific model ID for logging purposes. - */ - readonly modelId: string; - - /** - * Generates a transcript. - */ - doGenerate(options: TranscriptionModelV3CallOptions): PromiseLike<{ - /** - * The complete transcribed text from the audio. - */ - text: string; - - /** - * Array of transcript segments with timing information. - * Each segment represents a portion of the transcribed text with start and end times. - */ - segments: Array<{ - /** - * The text content of this segment. - */ - text: string; - /** - * The start time of this segment in seconds. - */ - startSecond: number; - /** - * The end time of this segment in seconds. - */ - endSecond: number; - }>; - - /** - * The detected language of the audio content, as an ISO-639-1 code (e.g., 'en' for English). - * May be undefined if the language couldn't be detected. - */ - language: string | undefined; - - /** - * The total duration of the audio file in seconds. - * May be undefined if the duration couldn't be determined. - */ - durationInSeconds: number | undefined; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - warnings: Array; - - /** - * Optional request information for telemetry and debugging purposes. - */ - request?: { - /** - * Raw request HTTP body that was sent to the provider API as a string (JSON should be stringified). - * Non-HTTP(s) providers should not set this. - */ - body?: string; - }; - - /** - * Response information for telemetry and debugging purposes. - */ - response: { - /** - * Timestamp for the start of the generated response. - */ - timestamp: Date; - - /** - * The ID of the response model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers. - */ - headers?: SharedV3Headers; - - /** - * Response body. - */ - body?: unknown; - }; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - providerMetadata?: Record; - }>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/index.ts deleted file mode 100644 index ca7b39f38..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './v3/index'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/v3/index.ts deleted file mode 100644 index ee43e873f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/v3/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type { - VideoModelV3 as Experimental_VideoModelV3, - VideoModelV3VideoData as Experimental_VideoModelV3VideoData, -} from './video-model-v3'; -export type { VideoModelV3CallOptions as Experimental_VideoModelV3CallOptions } from './video-model-v3-call-options'; -export type { VideoModelV3File as Experimental_VideoModelV3File } from './video-model-v3-file'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/v3/video-model-v3-call-options.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/v3/video-model-v3-call-options.ts deleted file mode 100644 index 032fce073..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/v3/video-model-v3-call-options.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { SharedV3ProviderOptions } from '../../shared'; -import { VideoModelV3File } from './video-model-v3-file'; - -export type VideoModelV3CallOptions = { - /** - * Text prompt for the video generation. - */ - prompt: string | undefined; - - /** - * Number of videos to generate. Default: 1. - * Most video models only support n=1 due to computational cost. - */ - n: number; - - /** - * Aspect ratio of the videos to generate. - * Must have the format `{width}:{height}`. - * `undefined` will use the provider's default aspect ratio. - * Common values: '16:9', '9:16', '1:1', '21:9', '4:3' - */ - aspectRatio: `${number}:${number}` | undefined; - - /** - * Resolution of the video to generate. - * Format: `{width}x{height}` (e.g., '1280x720', '1920x1080') - * `undefined` will use the provider's default resolution. - */ - resolution: `${number}x${number}` | undefined; - - /** - * Duration of the video in seconds. - * `undefined` will use the provider's default duration. - * Typically 3-10 seconds for most models. - */ - duration: number | undefined; - - /** - * Frames per second (FPS) for the video. - * `undefined` will use the provider's default FPS. - * Common values: 24, 30, 60 - */ - fps: number | undefined; - - /** - * Seed for deterministic video generation. - * `undefined` will use a random seed. - */ - seed: number | undefined; - - /** - * Input image for image-to-video generation. - * The image serves as the starting frame that the model will animate. - */ - image: VideoModelV3File | undefined; - - /** - * Additional provider-specific options that are passed through to the provider - * as body parameters. - * - * Example: - * { - * "fal": { - * "loop": true, - * "motionStrength": 0.8 - * } - * } - */ - providerOptions: SharedV3ProviderOptions; - - /** - * Abort signal for cancelling the operation. - */ - abortSignal?: AbortSignal; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/v3/video-model-v3-file.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/v3/video-model-v3-file.ts deleted file mode 100644 index 6bd822ef3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/v3/video-model-v3-file.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { SharedV3ProviderMetadata } from '../../shared'; - -/** - * A video or image file that can be used for video editing or image-to-video generation. - * Supports both image inputs (for image-to-video) and video inputs (for editing). - */ -export type VideoModelV3File = - | { - type: 'file'; - - /** - * The IANA media type of the file. - * Video types: 'video/mp4', 'video/webm', 'video/quicktime' - * Image types: 'image/png', 'image/jpeg', 'image/webp' - */ - mediaType: string; - - /** - * File data as base64 encoded string or binary data. - */ - data: string | Uint8Array; - - /** - * Optional provider-specific metadata for the file part. - */ - providerOptions?: SharedV3ProviderMetadata; - } - | { - type: 'url'; - - /** - * The URL of the video or image file. - */ - url: string; - - /** - * Optional provider-specific metadata for the file part. - */ - providerOptions?: SharedV3ProviderMetadata; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/v3/video-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/v3/video-model-v3.ts deleted file mode 100644 index bff43c3a0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@ai-sdk/provider/src/video-model/v3/video-model-v3.ts +++ /dev/null @@ -1,132 +0,0 @@ -import type { VideoModelV3CallOptions } from './video-model-v3-call-options'; -import type { SharedV3ProviderMetadata } from '../../shared/v3/shared-v3-provider-metadata'; -import type { SharedV3Warning } from '../../shared/v3/shared-v3-warning'; - -type GetMaxVideosPerCallFunction = (options: { - modelId: string; -}) => PromiseLike | number | undefined; - -/** - * Generated video data. Can be a URL, base64-encoded string, or binary data. - */ -export type VideoModelV3VideoData = - | { - /** - * Video available as a URL (most common for video providers). - */ - type: 'url'; - url: string; - mediaType: string; - } - | { - /** - * Video as base64-encoded string. - */ - type: 'base64'; - data: string; - mediaType: string; - } - | { - /** - * Video as binary data. - */ - type: 'binary'; - data: Uint8Array; - mediaType: string; - }; - -/** - * Video generation model specification version 3. - */ -export type VideoModelV3 = { - /** - * The video model must specify which video model interface - * version it implements. This will allow us to evolve the video - * model interface and retain backwards compatibility. The different - * implementation versions can be handled as a discriminated union - * on our side. - */ - readonly specificationVersion: 'v3'; - - /** - * Name of the provider for logging purposes. - */ - readonly provider: string; - - /** - * Provider-specific model ID for logging purposes. - */ - readonly modelId: string; - - /** - * Limit of how many videos can be generated in a single API call. - * Can be set to a number for a fixed limit, to undefined to use - * the global limit, or a function that returns a number or undefined, - * optionally as a promise. - * - * Most video models only support generating 1 video at a time due to - * computational cost. Default is typically 1. - */ - readonly maxVideosPerCall: number | undefined | GetMaxVideosPerCallFunction; - - /** - * Generates an array of videos. - */ - doGenerate(options: VideoModelV3CallOptions): PromiseLike<{ - /** - * Generated videos as URLs, base64 strings, or binary data. - * - * Most providers return URLs to video files (MP4, WebM) due to large file sizes. - * Use the discriminated union to indicate the type of video data being returned. - */ - videos: Array; - - /** - * Warnings for the call, e.g. unsupported features. - */ - warnings: Array; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - * - * The outer record is keyed by the provider name, and the inner - * record is provider-specific metadata. - * - * ```ts - * { - * "fal": { - * "videos": [{ - * "duration": 5.0, - * "fps": 24, - * "width": 1280, - * "height": 720 - * }] - * } - * } - * ``` - */ - providerMetadata?: SharedV3ProviderMetadata; - - /** - * Response information for telemetry and debugging purposes. - */ - response: { - /** - * Timestamp for the start of the generated response. - */ - timestamp: Date; - - /** - * The ID of the response model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers. - */ - headers: Record | undefined; - }; - }>; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@esbuild/darwin-arm64/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@esbuild/darwin-arm64/README.md deleted file mode 100644 index c2c0398db..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@esbuild/darwin-arm64/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# esbuild - -This is the macOS ARM 64-bit binary for esbuild, a JavaScript bundler and minifier. See https://github.com/evanw/esbuild for details. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@esbuild/darwin-arm64/bin/esbuild b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@esbuild/darwin-arm64/bin/esbuild deleted file mode 100755 index 073f4e8e8..000000000 Binary files a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@esbuild/darwin-arm64/bin/esbuild and /dev/null differ diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@esbuild/darwin-arm64/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@esbuild/darwin-arm64/package.json deleted file mode 100644 index dc469443c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@esbuild/darwin-arm64/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "@esbuild/darwin-arm64", - "version": "0.27.4", - "description": "The macOS ARM 64-bit binary for esbuild, a JavaScript bundler.", - "repository": { - "type": "git", - "url": "git+https://github.com/evanw/esbuild.git" - }, - "license": "MIT", - "preferUnplugged": true, - "engines": { - "node": ">=18" - }, - "os": [ - "darwin" - ], - "cpu": [ - "arm64" - ] -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@opentelemetry/api/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@opentelemetry/api/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@opentelemetry/api/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@opentelemetry/api/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@opentelemetry/api/README.md deleted file mode 100644 index 59d4cd7a0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@opentelemetry/api/README.md +++ /dev/null @@ -1,116 +0,0 @@ -# OpenTelemetry API for JavaScript - -

- -API Reference -  •   -Documentation -
- - NPM Release - -
-

- -This package provides everything needed to interact with the OpenTelemetry API, including all TypeScript interfaces, enums, and no-op implementations. It is intended for use both on the server and in the browser. - -The methods in this package perform no operations by default. This means they can be safely called by a library or end-user application whether there is an SDK registered or not. In order to generate and export telemetry data, you will also need an SDK such as the [OpenTelemetry JS SDK][opentelemetry-js]. - -## Tracing Quick Start - -### You Will Need - -- An application you wish to instrument -- [OpenTelemetry JS SDK][opentelemetry-js] -- Node.js >=8.5.0 (14+ is preferred) or an ECMAScript 5+ compatible browser - -**Note:** ECMAScript 5+ compatibility is for this package only. Please refer to the documentation for the SDK you are using to determine its minimum ECMAScript version. - -**Note for library authors:** Only your end users will need an OpenTelemetry SDK. If you wish to support OpenTelemetry in your library, you only need to use the OpenTelemetry API. For more information, please read the [tracing documentation][docs-tracing]. - -### Install Dependencies - -```sh -npm install @opentelemetry/api @opentelemetry/sdk-trace-base -``` - -### Trace Your Application - -In order to get started with tracing, you will need to first register an SDK. The SDK you are using may provide a convenience method which calls the registration methods for you, but if you would like to call them directly they are documented here: [SDK registration methods][docs-sdk-registration]. - -Once you have registered an SDK, you can start and end spans. A simple example of basic SDK registration and tracing a simple operation is below. The example should export spans to the console once per second. For more information, see the [tracing documentation][docs-tracing]. - -```javascript -const { trace } = require("@opentelemetry/api"); -const { BasicTracerProvider, ConsoleSpanExporter, SimpleSpanProcessor } = require("@opentelemetry/sdk-trace-base"); - -// Create and register an SDK -const provider = new BasicTracerProvider(); -provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); -trace.setGlobalTracerProvider(provider); - -// Acquire a tracer from the global tracer provider which will be used to trace the application -const name = 'my-application-name'; -const version = '0.1.0'; -const tracer = trace.getTracer(name, version); - -// Trace your application by creating spans -async function operation() { - const span = tracer.startSpan("do operation"); - - // mock some work by sleeping 1 second - await new Promise((resolve, reject) => { - setTimeout(resolve, 1000); - }) - - span.end(); -} - -async function main() { - while (true) { - await operation(); - } -} - -main(); -``` - -## Version Compatibility - -Because the npm installer and node module resolution algorithm could potentially allow two or more copies of any given package to exist within the same `node_modules` structure, the OpenTelemetry API takes advantage of a variable on the `global` object to store the global API. When an API method in the API package is called, it checks if this `global` API exists and proxies calls to it if and only if it is a compatible API version. This means if a package has a dependency on an OpenTelemetry API version which is not compatible with the API used by the end user, the package will receive a no-op implementation of the API. - -## Upgrade Guidelines - -### 0.21.0 to 1.0.0 - -No breaking changes - -### 0.20.0 to 0.21.0 - -- [#78](https://github.com/open-telemetry/opentelemetry-js-api/issues/78) `api.context.bind` arguments reversed and `context` is now a required argument. -- [#46](https://github.com/open-telemetry/opentelemetry-js-api/issues/46) Noop classes and singletons are no longer exported. To create a noop span it is recommended to use `api.trace.wrapSpanContext` with `INVALID_SPAN_CONTEXT` instead of using the `NOOP_TRACER`. - -### 1.0.0-rc.3 to 0.20.0 - -- Removing `TimedEvent` which was not part of spec -- `HttpBaggage` renamed to `HttpBaggagePropagator` -- [#45](https://github.com/open-telemetry/opentelemetry-js-api/pull/45) `Span#context` renamed to `Span#spanContext` -- [#47](https://github.com/open-telemetry/opentelemetry-js-api/pull/47) `getSpan`/`setSpan`/`getSpanContext`/`setSpanContext` moved to `trace` namespace -- [#55](https://github.com/open-telemetry/opentelemetry-js-api/pull/55) `getBaggage`/`setBaggage`/`createBaggage` moved to `propagation` namespace - -## Useful links - -- For more information on OpenTelemetry, visit: -- For more about OpenTelemetry JavaScript: -- For help or feedback on this project, join us in [GitHub Discussions][discussions-url] - -## License - -Apache 2.0 - See [LICENSE][license-url] for more information. - -[opentelemetry-js]: https://github.com/open-telemetry/opentelemetry-js - -[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions -[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/main/api/LICENSE -[docs-tracing]: https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/tracing.md -[docs-sdk-registration]: https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/sdk-registration.md diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@opentelemetry/api/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@opentelemetry/api/package.json deleted file mode 100644 index f7ba45f96..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@opentelemetry/api/package.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "name": "@opentelemetry/api", - "version": "1.9.0", - "description": "Public API for OpenTelemetry", - "main": "build/src/index.js", - "module": "build/esm/index.js", - "esnext": "build/esnext/index.js", - "types": "build/src/index.d.ts", - "browser": { - "./src/platform/index.ts": "./src/platform/browser/index.ts", - "./build/esm/platform/index.js": "./build/esm/platform/browser/index.js", - "./build/esnext/platform/index.js": "./build/esnext/platform/browser/index.js", - "./build/src/platform/index.js": "./build/src/platform/browser/index.js" - }, - "exports": { - ".": { - "module": "./build/esm/index.js", - "esnext": "./build/esnext/index.js", - "types": "./build/src/index.d.ts", - "default": "./build/src/index.js" - }, - "./experimental": { - "module": "./build/esm/experimental/index.js", - "esnext": "./build/esnext/experimental/index.js", - "types": "./build/src/experimental/index.d.ts", - "default": "./build/src/experimental/index.js" - } - }, - "repository": "open-telemetry/opentelemetry-js", - "scripts": { - "clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json", - "codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../", - "codecov:webworker": "nyc report --reporter=json && codecov -f coverage/*.json -p ../", - "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../", - "precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies", - "compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json", - "docs": "typedoc", - "docs:deploy": "gh-pages --dist docs/out", - "docs:test": "linkinator docs/out --silent && linkinator docs/*.md *.md --markdown --silent", - "lint:fix": "eslint . --ext .ts --fix", - "lint": "eslint . --ext .ts", - "test:browser": "karma start --single-run", - "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'", - "test:eol": "ts-mocha -p tsconfig.json 'test/**/*.test.ts'", - "test:webworker": "karma start karma.worker.js --single-run", - "cycle-check": "dpdm --exit-code circular:1 src/index.ts", - "version": "node ../scripts/version-update.js", - "prewatch": "npm run precompile", - "watch": "tsc --build --watch tsconfig.json tsconfig.esm.json tsconfig.esnext.json", - "peer-api-check": "node ../scripts/peer-api-check.js" - }, - "keywords": [ - "opentelemetry", - "nodejs", - "browser", - "tracing", - "profiling", - "stats", - "monitoring" - ], - "author": "OpenTelemetry Authors", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - }, - "files": [ - "build/esm/**/*.js", - "build/esm/**/*.js.map", - "build/esm/**/*.d.ts", - "build/esnext/**/*.js", - "build/esnext/**/*.js.map", - "build/esnext/**/*.d.ts", - "build/src/**/*.js", - "build/src/**/*.js.map", - "build/src/**/*.d.ts", - "LICENSE", - "README.md" - ], - "publishConfig": { - "access": "public" - }, - "devDependencies": { - "@types/mocha": "10.0.6", - "@types/node": "18.6.5", - "@types/sinon": "17.0.3", - "@types/webpack": "5.28.5", - "@types/webpack-env": "1.16.3", - "babel-plugin-istanbul": "6.1.1", - "codecov": "3.8.3", - "cross-var": "1.1.0", - "dpdm": "3.13.1", - "karma": "6.4.3", - "karma-chrome-launcher": "3.1.0", - "karma-coverage": "2.2.1", - "karma-mocha": "2.0.1", - "karma-mocha-webworker": "1.3.0", - "karma-spec-reporter": "0.0.36", - "karma-webpack": "5.0.1", - "lerna": "6.6.2", - "memfs": "3.5.3", - "mocha": "10.2.0", - "nyc": "15.1.0", - "sinon": "15.1.2", - "ts-loader": "9.5.1", - "ts-mocha": "10.0.0", - "typescript": "4.4.4", - "unionfs": "4.5.4", - "webpack": "5.89.0" - }, - "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/api", - "sideEffects": false, - "gitHead": "c4d3351b6b3f5593c8d7cbfec97b45cea9fe1511" -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@standard-schema/spec/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@standard-schema/spec/LICENSE deleted file mode 100644 index ea54e0dda..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@standard-schema/spec/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2024 Colin McDonnell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@standard-schema/spec/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@standard-schema/spec/README.md deleted file mode 100644 index f9813ffa8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@standard-schema/spec/README.md +++ /dev/null @@ -1,198 +0,0 @@ -

- Standard Schema fire logo -
- Standard Schema

-

- A family of specs for interoperable TypeScript -
- standardschema.dev -

-
- - - -The Standard Schema project is a set of interfaces that standardize the provision and consumption of shared functionality in the TypeScript ecosystem. - -Its goal is to allow tools to accept a single input that includes all the types and capabilities they need— no library-specific adapters, no extra dependencies. The result is an ecosystem that's fair for implementers, friendly for consumers, and open for end users. - -## The specifications - -The specifications can be found below in their entirety. Libraries wishing to implement a spec can copy/paste the code block below into their codebase. They're also available at `@standard-schema/spec` on [npm](https://www.npmjs.com/package/@standard-schema/spec) and [JSR](https://jsr.io/@standard-schema/spec). - -```ts -// ######################### -// ### Standard Typed ### -// ######################### - -/** The Standard Typed interface. This is a base type extended by other specs. */ -export interface StandardTypedV1 { - /** The Standard properties. */ - readonly "~standard": StandardTypedV1.Props; -} - -export declare namespace StandardTypedV1 { - /** The Standard Typed properties interface. */ - export interface Props { - /** The version number of the standard. */ - readonly version: 1; - /** The vendor name of the schema library. */ - readonly vendor: string; - /** Inferred types associated with the schema. */ - readonly types?: Types | undefined; - } - - /** The Standard Typed types interface. */ - export interface Types { - /** The input type of the schema. */ - readonly input: Input; - /** The output type of the schema. */ - readonly output: Output; - } - - /** Infers the input type of a Standard Typed. */ - export type InferInput = NonNullable< - Schema["~standard"]["types"] - >["input"]; - - /** Infers the output type of a Standard Typed. */ - export type InferOutput = NonNullable< - Schema["~standard"]["types"] - >["output"]; -} - -// ########################## -// ### Standard Schema ### -// ########################## - -/** The Standard Schema interface. */ -export interface StandardSchemaV1 { - /** The Standard Schema properties. */ - readonly "~standard": StandardSchemaV1.Props; -} - -export declare namespace StandardSchemaV1 { - /** The Standard Schema properties interface. */ - export interface Props - extends StandardTypedV1.Props { - /** Validates unknown input values. */ - readonly validate: ( - value: unknown, - options?: StandardSchemaV1.Options | undefined - ) => Result | Promise>; - } - - /** The result interface of the validate function. */ - export type Result = SuccessResult | FailureResult; - - /** The result interface if validation succeeds. */ - export interface SuccessResult { - /** The typed output value. */ - readonly value: Output; - /** A falsy value for `issues` indicates success. */ - readonly issues?: undefined; - } - - export interface Options { - /** Explicit support for additional vendor-specific parameters, if needed. */ - readonly libraryOptions?: Record | undefined; - } - - /** The result interface if validation fails. */ - export interface FailureResult { - /** The issues of failed validation. */ - readonly issues: ReadonlyArray; - } - - /** The issue interface of the failure output. */ - export interface Issue { - /** The error message of the issue. */ - readonly message: string; - /** The path of the issue, if any. */ - readonly path?: ReadonlyArray | undefined; - } - - /** The path segment interface of the issue. */ - export interface PathSegment { - /** The key representing a path segment. */ - readonly key: PropertyKey; - } - - /** The Standard types interface. */ - export interface Types - extends StandardTypedV1.Types {} - - /** Infers the input type of a Standard. */ - export type InferInput = - StandardTypedV1.InferInput; - - /** Infers the output type of a Standard. */ - export type InferOutput = - StandardTypedV1.InferOutput; -} - -// ############################### -// ### Standard JSON Schema ### -// ############################### - -/** The Standard JSON Schema interface. */ -export interface StandardJSONSchemaV1 { - /** The Standard JSON Schema properties. */ - readonly "~standard": StandardJSONSchemaV1.Props; -} - -export declare namespace StandardJSONSchemaV1 { - /** The Standard JSON Schema properties interface. */ - export interface Props - extends StandardTypedV1.Props { - /** Methods for generating the input/output JSON Schema. */ - readonly jsonSchema: StandardJSONSchemaV1.Converter; - } - - /** The Standard JSON Schema converter interface. */ - export interface Converter { - /** Converts the input type to JSON Schema. May throw if conversion is not supported. */ - readonly input: ( - options: StandardJSONSchemaV1.Options - ) => Record; - /** Converts the output type to JSON Schema. May throw if conversion is not supported. */ - readonly output: ( - options: StandardJSONSchemaV1.Options - ) => Record; - } - - /** - * The target version of the generated JSON Schema. - * - * It is *strongly recommended* that implementers support `"draft-2020-12"` and `"draft-07"`, as they are both in wide use. All other targets can be implemented on a best-effort basis. Libraries should throw if they don't support a specified target. - * - * The `"openapi-3.0"` target is intended as a standardized specifier for OpenAPI 3.0 which is a superset of JSON Schema `"draft-04"`. - */ - export type Target = - | "draft-2020-12" - | "draft-07" - | "openapi-3.0" - // Accepts any string for future targets while preserving autocomplete - | ({} & string); - - /** The options for the input/output methods. */ - export interface Options { - /** Specifies the target version of the generated JSON Schema. Support for all versions is on a best-effort basis. If a given version is not supported, the library should throw. */ - readonly target: Target; - - /** Explicit support for additional vendor-specific parameters, if needed. */ - readonly libraryOptions?: Record | undefined; - } - - /** The Standard types interface. */ - export interface Types - extends StandardTypedV1.Types {} - - /** Infers the input type of a Standard. */ - export type InferInput = - StandardTypedV1.InferInput; - - /** Infers the output type of a Standard. */ - export type InferOutput = - StandardTypedV1.InferOutput; -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@standard-schema/spec/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@standard-schema/spec/package.json deleted file mode 100644 index 62bb55187..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@standard-schema/spec/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "@standard-schema/spec", - "description": "A family of specs for interoperable TypeScript", - "version": "1.1.0", - "license": "MIT", - "author": "Colin McDonnell", - "homepage": "https://standardschema.dev", - "repository": { - "type": "git", - "url": "https://github.com/standard-schema/standard-schema" - }, - "keywords": [ - "typescript", - "schema", - "validation", - "standard", - "interface" - ], - "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "standard-schema-spec": "./src/index.ts", - "import": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - } - } - }, - "sideEffects": false, - "files": [ - "dist" - ], - "publishConfig": { - "access": "public" - }, - "devDependencies": { - "tsup": "^8.3.0", - "typescript": "^5.6.2" - }, - "scripts": { - "lint": "pnpm biome lint ./src", - "format": "pnpm biome format --write ./src", - "check": "pnpm biome check ./src", - "build": "tsup" - } -} \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/CHANGELOG.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/CHANGELOG.md deleted file mode 100644 index c811d675d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/CHANGELOG.md +++ /dev/null @@ -1,83 +0,0 @@ -# @vercel/oidc - -## 3.1.0 - -### Minor Changes - -- Allow vercel/oidc to refresh the vercel CLI auth token when running locally ([#14543](https://github.com/vercel/vercel/pull/14543)) - -### Patch Changes - -- improve error messages for package consumers ([#14449](https://github.com/vercel/vercel/pull/14449)) - -## 3.0.5 - -### Patch Changes - -- Fix OIDC token expiry check ([#14306](https://github.com/vercel/vercel/pull/14306)) - -## 3.0.4 - -### Patch Changes - -- Fix directory permissions so that files can be created under the OIDC data directory in linux ([#14214](https://github.com/vercel/vercel/pull/14214)) - -## 3.0.3 - -### Patch Changes - -- fix(oidc): add `"workflow"` as export condition ([#14103](https://github.com/vercel/vercel/pull/14103)) - -## 3.0.2 - -### Patch Changes - -- fix(oidc): add `"react-native"` as export condition ([#14066](https://github.com/vercel/vercel/pull/14066)) - -## 3.0.1 - -### Patch Changes - -- feat(oidc): export `getContext()` method ([#14027](https://github.com/vercel/vercel/pull/14027)) - -- feat(oidc): add conditional export for browsers ([#14027](https://github.com/vercel/vercel/pull/14027)) - - Introduces a browser export with mock methods that don't require access to a file system or environment variables. This makes `@vercel/oidc` usable for universal libraries that are run in both frontend and backend. - -- fix(oidc): remove `ms` dependency ([#14027](https://github.com/vercel/vercel/pull/14027)) - -## 3.0.0 - -### Major Changes - -- Drop Node.js 18, bump minimum to Node.js 20 ([#13856](https://github.com/vercel/vercel/pull/13856)) - -## 2.0.2 - -### Patch Changes - -- fix "Cannot find module" error caused by dynamically importing files without their extensions ([#13815](https://github.com/vercel/vercel/pull/13815)) - -## 2.0.1 - -### Patch Changes - -- Fix package versions for oidc-aws-credentials-provider, vercel/functions, and publish the next version of vercel/oidc ([#13765](https://github.com/vercel/vercel/pull/13765)) - -## 2.1.0 - -### Minor Changes - -- Add refresh token ability to @vercel/oidc ([#13608](https://github.com/vercel/vercel/pull/13608)) - -## 2.0.0 - -### Major Changes - -- extract oidc and aws oidc credential helpers from @vercel/functions into @vercel/oidc and @vercel/oidc-aws-credentials-provider. @vercel/functions re-exports the new functions as deprecated to maintain backwards compatibility. ([#13548](https://github.com/vercel/vercel/pull/13548)) - -## 1.0.0 - -### Major Changes - -- Initial release ([#13548](https://github.com/vercel/vercel/pull/13548)) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/LICENSE deleted file mode 100644 index 5454d6d51..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2017 Vercel, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/README.md deleted file mode 100644 index 2e268553b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@vercel/oidc` - -Runtime OIDC helper methods intended to be used with your Vercel Functions diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/docs/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/docs/README.md deleted file mode 100644 index abdfce1f4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/docs/README.md +++ /dev/null @@ -1,104 +0,0 @@ -# @vercel/oidc - -## Table of contents - -### Functions - -- [getContext](README.md#getcontext) -- [getVercelOidcToken](README.md#getverceloidctoken) -- [getVercelOidcTokenSync](README.md#getverceloidctokensync) - -## Functions - -### getContext - -▸ **getContext**(): `Context` - -#### Returns - -`Context` - -#### Defined in - -[get-context.ts:7](https://github.com/vercel/vercel/blob/main/packages/oidc/src/get-context.ts#L7) - ---- - -### getVercelOidcToken - -▸ **getVercelOidcToken**(): [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<`string`\> - -Gets the current OIDC token from the request context or the environment variable. - -Do not cache this value, as it is subject to change in production! - -This function is used to retrieve the OIDC token from the request context or the environment variable. -It checks for the `x-vercel-oidc-token` header in the request context and falls back to the `VERCEL_OIDC_TOKEN` environment variable if the header is not present. - -Unlike the `getVercelOidcTokenSync` function, this function will refresh the token if it is expired in a development environment. - -**`Throws`** - -If the `x-vercel-oidc-token` header is missing from the request context and the environment variable `VERCEL_OIDC_TOKEN` is not set. If the token -is expired in a development environment, will also throw an error if the token cannot be refreshed: no CLI credentials are available, CLI credentials are expired, no project configuration is available -or the token refresh request fails. - -**`Example`** - -```js -// Using the OIDC token -getVercelOidcToken() - .then(token => { - console.log('OIDC Token:', token); - }) - .catch(error => { - console.error('Error:', error.message); - }); -``` - -#### Returns - -[`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<`string`\> - -A promise that resolves to the OIDC token. - -#### Defined in - -[get-vercel-oidc-token.ts:30](https://github.com/vercel/vercel/blob/main/packages/oidc/src/get-vercel-oidc-token.ts#L30) - ---- - -### getVercelOidcTokenSync - -▸ **getVercelOidcTokenSync**(): `string` - -Gets the current OIDC token from the request context or the environment variable. - -Do not cache this value, as it is subject to change in production! - -This function is used to retrieve the OIDC token from the request context or the environment variable. -It checks for the `x-vercel-oidc-token` header in the request context and falls back to the `VERCEL_OIDC_TOKEN` environment variable if the header is not present. - -This function will not refresh the token if it is expired. For refreshing the token, use the @{link getVercelOidcToken} function. - -**`Throws`** - -If the `x-vercel-oidc-token` header is missing from the request context and the environment variable `VERCEL_OIDC_TOKEN` is not set. - -**`Example`** - -```js -// Using the OIDC token -const token = getVercelOidcTokenSync(); -console.log('OIDC Token:', token); -``` - -#### Returns - -`string` - -The OIDC token. - -#### Defined in - -[get-vercel-oidc-token.ts:85](https://github.com/vercel/vercel/blob/main/packages/oidc/src/get-vercel-oidc-token.ts#L85) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/package.json deleted file mode 100644 index 0987ee2cc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/@vercel/oidc/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "@vercel/oidc", - "description": "Runtime OIDC helpers intended for use with Vercel Functions", - "homepage": "https://vercel.com", - "files": [ - "**/*.js", - "**/*.d.ts", - "**/*.md" - ], - "types": "./dist/index.d.ts", - "exports": { - ".": { - "browser": "./dist/index-browser.js", - "react-native": "./dist/index-browser.js", - "workflow": "./dist/index-browser.js", - "import": "./dist/index.js", - "require": "./dist/index.js" - } - }, - "version": "3.1.0", - "repository": { - "directory": "packages/oidc", - "type": "git", - "url": "git+https://github.com/vercel/vercel.git" - }, - "bugs": { - "url": "https://github.com/vercel/vercel/issues" - }, - "devDependencies": { - "tinyspawn": "1.3.1", - "typedoc": "0.24.6", - "typedoc-plugin-markdown": "4.1.2", - "typedoc-plugin-mdn-links": "3.2.3", - "typescript": "4.9.5", - "vitest": "2.0.1" - }, - "peerDependenciesMeta": {}, - "engines": { - "node": ">= 20" - }, - "license": "Apache-2.0", - "publishConfig": { - "access": "public" - }, - "scripts": { - "pretest": "pnpm run build:code", - "test": "vitest", - "build": "pnpm run build:code && pnpm run build:docs", - "build:code": "node ../../utils/build.mjs", - "build:docs": "typedoc && prettier --write docs/**/*.md docs/*.md" - } -} \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/CHANGELOG.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/CHANGELOG.md deleted file mode 100644 index 020243747..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/CHANGELOG.md +++ /dev/null @@ -1,7508 +0,0 @@ -# ai - -## 6.0.138 - -### Patch Changes - -- Updated dependencies [0db5cd8] - - @ai-sdk/gateway@3.0.80 - -## 6.0.137 - -### Patch Changes - -- Updated dependencies [3caa544] - - @ai-sdk/gateway@3.0.79 - -## 6.0.136 - -### Patch Changes - -- Updated dependencies [763e178] - - @ai-sdk/gateway@3.0.78 - -## 6.0.135 - -### Patch Changes - -- df6a330: chore(ai): remove all experimental agent events - -## 6.0.134 - -### Patch Changes - -- ed6876b: chore(ai): remove all experimental embed events - -## 6.0.133 - -### Patch Changes - -- 055cd68: fix: publish v6 to latest npm dist tag -- Updated dependencies [d99eb91] -- Updated dependencies [055cd68] - - @ai-sdk/gateway@3.0.77 - - @ai-sdk/provider-utils@4.0.21 - -## 6.0.132 - -### Patch Changes - -- 28fd5a5: README updates - -## 6.0.131 - -### Patch Changes - -- 14f25f9: feat(ai): introduce experimental callbacks for embed function - -## 6.0.130 - -### Patch Changes - -- Updated dependencies [25af909] - - @ai-sdk/gateway@3.0.76 - -## 6.0.129 - -### Patch Changes - -- Updated dependencies [f95e0c0] - - @ai-sdk/gateway@3.0.75 - -## 6.0.128 - -### Patch Changes - -- Updated dependencies [7324b56] - - @ai-sdk/gateway@3.0.74 - -## 6.0.127 - -### Patch Changes - -- Updated dependencies [ac0c407] -- Updated dependencies [e748159] - - @ai-sdk/gateway@3.0.73 - -## 6.0.126 - -### Patch Changes - -- 578615a: Remove custom User-Agent header from HttpChatTransport to fix CORS preflight failures in Safari and Firefox - -## 6.0.125 - -### Patch Changes - -- Updated dependencies [5ffb1ad] -- Updated dependencies [f5bf0c6] - - @ai-sdk/gateway@3.0.72 - -## 6.0.124 - -### Patch Changes - -- Updated dependencies [55ccbe2] - - @ai-sdk/gateway@3.0.71 - -## 6.0.123 - -### Patch Changes - -- ffe0f90: fix(anthropic): preserve the error code returned by model - -## 6.0.122 - -### Patch Changes - -- Updated dependencies [ca0b430] - - @ai-sdk/gateway@3.0.70 - -## 6.0.121 - -### Patch Changes - -- Updated dependencies [efdaefc] - - @ai-sdk/gateway@3.0.69 - -## 6.0.120 - -### Patch Changes - -- 78c0e26: feat(ai): pass result provider metadata across the stream - -## 6.0.119 - -### Patch Changes - -- ab286f1: fix(ai): doStream should reflect transformed values -- d68b122: feat(ai): add missing usage attributes - -## 6.0.118 - -### Patch Changes - -- 64ac0fd: fix(security): validate redirect targets in download functions to prevent SSRF bypass - - Both `downloadBlob` and `download` now validate the final URL after following HTTP redirects, preventing attackers from bypassing SSRF protections via open redirects to internal/private addresses. - -- Updated dependencies [64ac0fd] - - @ai-sdk/provider-utils@4.0.20 - - @ai-sdk/gateway@3.0.68 - -## 6.0.117 - -### Patch Changes - -- d23121f: chore(ai): add optional ChatRequestOptions to `addToolApprovalResponse` and `addToolOutput` -- Updated dependencies [2589004] - - @ai-sdk/gateway@3.0.67 - -## 6.0.116 - -### Patch Changes - -- ad4cfc2: Add URL validation to `downloadBlob` and `download` to prevent blind SSRF attacks. Private/internal IP addresses, localhost, and non-HTTP protocols are now rejected before fetching. -- Updated dependencies [ad4cfc2] - - @ai-sdk/provider-utils@4.0.19 - - @ai-sdk/gateway@3.0.66 - -## 6.0.115 - -### Patch Changes - -- Updated dependencies [824b295] - - @ai-sdk/provider-utils@4.0.18 - - @ai-sdk/gateway@3.0.65 - -## 6.0.114 - -### Patch Changes - -- 2291047: fix(ai): fix missing support for image thought signatures (e.g. for Gemini image models) - -## 6.0.113 - -### Patch Changes - -- 70d3980: fix(ai): use errorMode 'text' in approval continuation to preserve tool error messages - -## 6.0.112 - -### Patch Changes - -- Updated dependencies [db3d4ca] - - @ai-sdk/gateway@3.0.64 - -## 6.0.111 - -### Patch Changes - -- 2129c82: feat(ai): register global telemetry integrations - -## 6.0.110 - -### Patch Changes - -- Updated dependencies [1b01ec1] -- Updated dependencies [8df8e11] - - @ai-sdk/gateway@3.0.63 - -## 6.0.109 - -### Patch Changes - -- Updated dependencies [10bec50] - - @ai-sdk/gateway@3.0.62 - -## 6.0.108 - -### Patch Changes - -- 2a4f512: feat(ai): add telemetry interface and registry - -## 6.0.107 - -### Patch Changes - -- Updated dependencies [08336f1] - - @ai-sdk/provider-utils@4.0.17 - - @ai-sdk/gateway@3.0.61 - -## 6.0.106 - -### Patch Changes - -- Updated dependencies [29e9f4d] - - @ai-sdk/gateway@3.0.60 - -## 6.0.105 - -### Patch Changes - -- Updated dependencies [58bc42d] - - @ai-sdk/provider-utils@4.0.16 - - @ai-sdk/gateway@3.0.59 - -## 6.0.104 - -### Patch Changes - -- Updated dependencies [1330f2f] - - @ai-sdk/gateway@3.0.58 - -## 6.0.103 - -### Patch Changes - -- Updated dependencies [ba63bc2] - - @ai-sdk/gateway@3.0.57 - -## 6.0.102 - -### Patch Changes - -- Updated dependencies [45f0a7f] - - @ai-sdk/gateway@3.0.56 - -## 6.0.101 - -### Patch Changes - -- 5230482: fix(ai): Don't create duplicate tool parts when models call non-existent tools - -## 6.0.100 - -### Patch Changes - -- b7fba77: feat(ai): add event notifiers to core functions - -## 6.0.99 - -### Patch Changes - -- Updated dependencies [e8172b6] - - @ai-sdk/gateway@3.0.55 - -## 6.0.98 - -### Patch Changes - -- Updated dependencies [0c9395b] - - @ai-sdk/gateway@3.0.54 - -## 6.0.97 - -### Patch Changes - -- ebfdad1: feat(ai): experimental callbacks in ToolLoopAgent - -## 6.0.96 - -### Patch Changes - -- 30c9de6: feat(ai): experimental callbacks for streamText - -## 6.0.95 - -### Patch Changes - -- Updated dependencies [73b7e09] - - @ai-sdk/gateway@3.0.53 - -## 6.0.94 - -### Patch Changes - -- Updated dependencies [363fa44] - - @ai-sdk/gateway@3.0.52 - -## 6.0.93 - -### Patch Changes - -- d3769ec: feat(ai): add experimental callbacks in generateText - -## 6.0.92 - -### Patch Changes - -- Updated dependencies [765b013] - - @ai-sdk/gateway@3.0.51 - -## 6.0.91 - -### Patch Changes - -- Updated dependencies [a433cd3] - - @ai-sdk/gateway@3.0.50 - -## 6.0.90 - -### Patch Changes - -- 98e83ab: Fix `useChat` status briefly flashing to `submitted` on page load when `resume: true` is set and there is no active stream to resume. The `reconnectToStream` check is now performed before setting status to `submitted`, so status stays `ready` when the server responds with 204 (no active stream). - -## 6.0.89 - -### Patch Changes - -- Updated dependencies [5f693c8] - - @ai-sdk/gateway@3.0.49 - -## 6.0.88 - -### Patch Changes - -- Updated dependencies [2a1c664] - - @ai-sdk/gateway@3.0.48 - -## 6.0.87 - -### Patch Changes - -- Updated dependencies [6bbd05b] - - @ai-sdk/gateway@3.0.47 - -## 6.0.86 - -### Patch Changes - -- Updated dependencies [f75f18c] - - @ai-sdk/gateway@3.0.46 - -## 6.0.85 - -### Patch Changes - -- Updated dependencies [e858654] - - @ai-sdk/gateway@3.0.45 - -## 6.0.84 - -### Patch Changes - -- 4024a3a: security: prevent unbounded memory growth in download functions - - The `download()` and `downloadBlob()` functions now enforce a default 2 GiB size limit when downloading from user-provided URLs. Downloads that exceed this limit are aborted with a `DownloadError` instead of consuming unbounded memory and crashing the process. The `abortSignal` parameter is now passed through to `fetch()` in all download call sites. - - Added `download` option to `transcribe()` and `experimental_generateVideo()` for providing a custom download function. Use the new `createDownload({ maxBytes })` factory to configure download size limits. - -- Updated dependencies [4024a3a] - - @ai-sdk/provider-utils@4.0.15 - - @ai-sdk/gateway@3.0.44 - -## 6.0.83 - -### Patch Changes - -- Updated dependencies [b424e50] - - @ai-sdk/gateway@3.0.43 - -## 6.0.82 - -### Patch Changes - -- Updated dependencies [1819bc1] - - @ai-sdk/gateway@3.0.42 - -## 6.0.81 - -### Patch Changes - -- ee4beee: feat(ai): add onStepFinish callback to createUIMessageStream - -## 6.0.80 - -### Patch Changes - -- Updated dependencies [99fbed8] - - @ai-sdk/gateway@3.0.41 - -## 6.0.79 - -### Patch Changes - -- Updated dependencies [a2208a2] - - @ai-sdk/gateway@3.0.40 - -## 6.0.78 - -### Patch Changes - -- 59fcf30: fix(ai): make experimental_context required in ToolLoopAgentOnFinishCallback - - This fixes a type inconsistency where `ToolLoopAgentOnFinishCallback` had `experimental_context` as optional while `StreamTextOnFinishCallback` and `GenerateTextOnFinishCallback` had it as required. Since `ToolLoopAgent` delegates to `streamText`/`generateText`, and both always pass `experimental_context` when invoking the callback, the types should match. - -## 6.0.77 - -### Patch Changes - -- Updated dependencies [eea5d30] - - @ai-sdk/gateway@3.0.39 - -## 6.0.76 - -### Patch Changes - -- Updated dependencies [70028ab] - - @ai-sdk/gateway@3.0.38 - -## 6.0.75 - -### Patch Changes - -- 7168375: feat (ai, provider): default global provider video model resolution -- Updated dependencies [7168375] - - @ai-sdk/provider@3.0.8 - - @ai-sdk/gateway@3.0.37 - - @ai-sdk/provider-utils@4.0.14 - -## 6.0.74 - -### Patch Changes - -- 471009b: fix(ai): pass reasoning text in telemetry - -## 6.0.73 - -### Patch Changes - -- Updated dependencies [9892c58] - - @ai-sdk/gateway@3.0.36 - -## 6.0.72 - -### Patch Changes - -- Updated dependencies [8e2eaac] - - @ai-sdk/gateway@3.0.35 - -## 6.0.71 - -### Patch Changes - -- Updated dependencies [4867635] - - @ai-sdk/gateway@3.0.34 - -## 6.0.70 - -### Patch Changes - -- Updated dependencies [ae30443] - - @ai-sdk/gateway@3.0.33 - -## 6.0.69 - -### Patch Changes - -- d659305: fix(ai): auto-populate `originalMessages` in `createAgentUIStream` - -## 6.0.68 - -### Patch Changes - -- 8bf2660: chore(ai): export `DefaultGeneratedFile` - -## 6.0.67 - -### Patch Changes - -- 53f6731: feat (ai, provider): experimental generate video support -- Updated dependencies [53f6731] - - @ai-sdk/provider@3.0.7 - - @ai-sdk/gateway@3.0.32 - - @ai-sdk/provider-utils@4.0.13 - -## 6.0.66 - -### Patch Changes - -- Updated dependencies [96936e5] - - @ai-sdk/provider-utils@4.0.12 - - @ai-sdk/gateway@3.0.31 - -## 6.0.65 - -### Patch Changes - -- Updated dependencies [1a74972] - - @ai-sdk/gateway@3.0.30 - -## 6.0.64 - -### Patch Changes - -- ce9daa3: Fixed 'reasoning part reasoning-0 not found' error by ensuring 'reasoning-start' event is emitted for empty thinking blocks (eg. ) - -## 6.0.63 - -### Patch Changes - -- be95579: fix(ui): respect `Promise` when returned by `sendAutomaticallyWhen` - -## 6.0.62 - -### Patch Changes - -- 2810850: fix(ai): improve type validation error messages with field paths and entity identifiers -- Updated dependencies [2810850] - - @ai-sdk/provider-utils@4.0.11 - - @ai-sdk/provider@3.0.6 - - @ai-sdk/gateway@3.0.29 - -## 6.0.61 - -### Patch Changes - -- Updated dependencies [1524271] - - @ai-sdk/gateway@3.0.28 - -## 6.0.60 - -### Patch Changes - -- 5fc42fa: feat(ai): add experimental retention setting - -## 6.0.59 - -### Patch Changes - -- Updated dependencies [0acff64] - - @ai-sdk/gateway@3.0.27 - -## 6.0.58 - -### Patch Changes - -- Updated dependencies [a8be296] - - @ai-sdk/gateway@3.0.26 - -## 6.0.57 - -### Patch Changes - -- 65865d8: Fix handling of error results in deferrable tools - -## 6.0.56 - -### Patch Changes - -- Updated dependencies [15a78c7] - - @ai-sdk/gateway@3.0.25 - -## 6.0.55 - -### Patch Changes - -- 43a74df: chore(ai): add skill to README - -## 6.0.54 - -### Patch Changes - -- 2f8ac87: docs(ai): fix incorrect and outdated jsdoc - -## 6.0.53 - -### Patch Changes - -- 7ee3f10: chore: updated docs - -## 6.0.52 - -### Patch Changes - -- Updated dependencies [462ad00] - - @ai-sdk/provider-utils@4.0.10 - - @ai-sdk/gateway@3.0.24 - -## 6.0.51 - -### Patch Changes - -- ea0feb5: fix(ai): clean up step timeout when error occurs in streamText - -## 6.0.50 - -### Patch Changes - -- Updated dependencies [cbf1704] - - @ai-sdk/gateway@3.0.23 - -## 6.0.49 - -### Patch Changes - -- ded661b: feat(ai): add onStepFinish to agent.generate and agent.stream - -## 6.0.48 - -### Patch Changes - -- 4de5a1d: chore: excluded tests from src folder in npm package -- Updated dependencies [4de5a1d] - - @ai-sdk/gateway@3.0.22 - - @ai-sdk/provider@3.0.5 - - @ai-sdk/provider-utils@4.0.9 - -## 6.0.47 - -### Patch Changes - -- Updated dependencies [2b8369d] - - @ai-sdk/gateway@3.0.21 - -## 6.0.46 - -### Patch Changes - -- Updated dependencies [8dc54db] - - @ai-sdk/gateway@3.0.20 - -## 6.0.45 - -### Patch Changes - -- Updated dependencies [c60fdd8] - - @ai-sdk/gateway@3.0.19 - -## 6.0.44 - -### Patch Changes - -- Updated dependencies [7af4eb4] - - @ai-sdk/gateway@3.0.18 - -## 6.0.43 - -### Patch Changes - -- 2dc9bfa: fix(ai): handle provider-executed tools and tool-approval-response in validation - - - Skip validation for tool calls with `providerExecuted: true` (deferred results) - - Map approvalId to toolCallId for proper tool-approval-response handling - - Filter out empty tool messages after content filtering - - Fixes MissingToolResultError for async and approval-based tool flows - -## 6.0.42 - -### Patch Changes - -- Updated dependencies [66d78d5] - - @ai-sdk/gateway@3.0.17 - -## 6.0.41 - -### Patch Changes - -- 84b6e6d: Revert "feat(ai): expose token usage in useChat onFinish callback#11871 - -## 6.0.40 - -### Patch Changes - -- ab57783: Add usage information to onFinish callback in useChat - -## 6.0.39 - -### Patch Changes - -- 4e28ba0: fix(ai): propagate providerMetadata during input-streaming state - - Provider-executed tools (like MCP tools) need to send metadata during the streaming phase, but the implementation only set `callProviderMetadata` when `part.state === "input-available"`. This fix removes the overly-restrictive state check and adds `callProviderMetadata` to the input-streaming state types and schemas. - -## 6.0.38 - -### Patch Changes - -- Updated dependencies [5c090e7] - - @ai-sdk/provider@3.0.4 - - @ai-sdk/gateway@3.0.16 - - @ai-sdk/provider-utils@4.0.8 - -## 6.0.37 - -### Patch Changes - -- b5dab9b: fix(ai): maintain OpenTelemetry context across async generator yields - - Fixes an issue where OpenTelemetry context was lost at async generator yield boundaries, causing nested ToolLoopAgent spans to escape to the parent agent's level in observability platforms. - - The fix ensures that when `recordSpan` is used with async generators (e.g., in tool execution), the active context is explicitly maintained using `context.with()`, preventing span hierarchy corruption in nested agent scenarios. - - Closes #11720 - -## 6.0.36 - -### Patch Changes - -- 46f46e4: fix(provider-utils): improve tool type inference when using `inputExamples` with Zod schemas that use `.optional().default()` or `.refine()`. -- Updated dependencies [46f46e4] - - @ai-sdk/provider-utils@4.0.7 - - @ai-sdk/gateway@3.0.15 - -## 6.0.35 - -### Patch Changes - -- d7e7f1f: Add descriptive error messages for malformed UIMessageStream chunks. - -## 6.0.34 - -### Patch Changes - -- 1b11dcb: chore(ai): include sources in npm package -- Updated dependencies [1b11dcb] - - @ai-sdk/provider-utils@4.0.6 - - @ai-sdk/provider@3.0.3 - - @ai-sdk/gateway@3.0.14 - -## 6.0.33 - -### Patch Changes - -- 0ca078c: fix(ai): pass providerMetadata in smooth stream to preserve thinking tag - -## 6.0.32 - -### Patch Changes - -- ec24401: chore(ai): include docs in npm package - -## 6.0.31 - -### Patch Changes - -- Updated dependencies [92b339b] - - @ai-sdk/gateway@3.0.13 - -## 6.0.30 - -### Patch Changes - -- Updated dependencies [34d1c8a] - - @ai-sdk/provider-utils@4.0.5 - - @ai-sdk/gateway@3.0.12 - -## 6.0.29 - -### Patch Changes - -- fdce123: docs: update README with usage example for @ai-sdk/anthropic - -## 6.0.28 - -### Patch Changes - -- d4486d2: fix(ai): do not cleanup AsyncIterableStream twice - -## 6.0.27 - -### Patch Changes - -- Updated dependencies [891a60a] - - @ai-sdk/gateway@3.0.11 - -## 6.0.26 - -### Patch Changes - -- 40d4997: feat(ai): add middleware for extracting JSON - -## 6.0.25 - -### Patch Changes - -- b64f256: Add `elementStream` to `streamText` for streaming individual array elements when using `output: Output.array()`. - -## 6.0.24 - -### Patch Changes - -- 4f236c8: feat(ai): per-chunk timeouts for streamText - -## 6.0.23 - -### Patch Changes - -- a4c680a: feat(ai): per-step timeouts for generateText and streamText -- 8c6f067: feat(ai): support Intl.Segmenter in smoothStream - -## 6.0.22 - -### Patch Changes - -- f0d29de: chore(ai): remove \_internal.currentDate from streamText - -## 6.0.21 - -### Patch Changes - -- 9667780: fix(ai): preserve `rawInput` in `safeValidateUIMessages` for `output-error` tool parts - - Fixes #11406 - -## 6.0.20 - -### Patch Changes - -- f748c46: Updated Unified Provider Architecture section in README to describe AI Gateway as the default. - -## 6.0.19 - -### Patch Changes - -- Updated dependencies [2696fd2] - - @ai-sdk/gateway@3.0.10 - -## 6.0.18 - -### Patch Changes - -- d6ec0e2: chore(ai): remove \_internal.currentDate from generateText - -## 6.0.17 - -### Patch Changes - -- af0955e: streamText should throw timeout error with proper cause when it times out - -## 6.0.16 - -### Patch Changes - -- 81adf59: feat(ai): introduce timeout configuration object - -## 6.0.15 - -### Patch Changes - -- 3a73fb3: Include abort reason in stream chunks and document the new field - -## 6.0.14 - -### Patch Changes - -- 3f9453f: feat(ai): add timeout option to generateText, streamText, and Agent - -## 6.0.13 - -### Patch Changes - -- e2c445d: feat(ai): smoothStream reasoning support - -## 6.0.12 - -### Patch Changes - -- d937c8f: Add Image model middleware support via `wrapImageModel` and `ImageModelV3Middleware`. -- Updated dependencies [d937c8f] - - @ai-sdk/provider@3.0.2 - - @ai-sdk/gateway@3.0.9 - - @ai-sdk/provider-utils@4.0.4 - -## 6.0.11 - -### Patch Changes - -- Updated dependencies [8ec1984] - - @ai-sdk/gateway@3.0.8 - -## 6.0.10 - -### Patch Changes - -- ae26f95: Add missing `.catch()` handler to `executeToolCall` promise in `runToolsTransformation` to prevent potential stream hang when the promise rejects. - -## 6.0.9 - -### Patch Changes - -- 4e90233: feat(ui): add DirectChatTransport - -## 6.0.8 - -### Patch Changes - -- Updated dependencies [0b429d4] - - @ai-sdk/provider-utils@4.0.3 - - @ai-sdk/gateway@3.0.7 - -## 6.0.7 - -### Patch Changes - -- Updated dependencies [74c0157] - - @ai-sdk/gateway@3.0.6 - -## 6.0.6 - -### Patch Changes - -- Updated dependencies [7ee2d12] - - @ai-sdk/gateway@3.0.5 - -## 6.0.5 - -### Patch Changes - -- 863d34f: fix: trigger release to update `@latest` -- Updated dependencies [863d34f] - - @ai-sdk/gateway@3.0.4 - - @ai-sdk/provider@3.0.1 - - @ai-sdk/provider-utils@4.0.2 - -## 6.0.4 - -### Patch Changes - -- Updated dependencies [1dad057] - - @ai-sdk/gateway@3.0.3 - -## 6.0.3 - -### Patch Changes - -- 29264a3: feat: add MCP tool approval -- Updated dependencies [29264a3] - - @ai-sdk/provider-utils@4.0.1 - - @ai-sdk/gateway@3.0.2 - -## 6.0.2 - -### Patch Changes - -- 129ff26: fix(ai): skip tool input validation in `safeValidateUIMessages` when `output-error` state has undefined input - - Fixes #11392 - -- Updated dependencies [c0c8a0e] - - @ai-sdk/gateway@3.0.1 - -## 6.0.1 - -### Patch Changes - -- Updated dependencies [387980f] - - @ai-sdk/gateway@3.0.0 - -## 6.0.0 - -### Major Changes - -- dee8b05: ai SDK 6 beta - -### Minor Changes - -- 78928cb: release: start 5.1 beta - -### Patch Changes - -- 0c3b58b: fix(provider): add specificationVersion to ProviderV3 -- 58920e0: fix(ai): do not drop custom headers in HttpChatTransport -- a7da2b6: feat(agent): change output generics -- 0adc679: feat(provider): shared spec v3 -- 50b70d6: feat(anthropic): add programmatic tool calling -- 2d28066: chore(agent): limit agent call parameters -- fca786b: feat(agent): configurable call options -- 046aa3b: feat(provider): speech model v3 spec -- e1f6e8e: feat(ai): add Output.json() -- 8d9e8ad: chore(provider): remove generics from EmbeddingModelV3 - - Before - - ```ts - model.textEmbeddingModel("my-model-id"); - ``` - - After - - ```ts - model.embeddingModel("my-model-id"); - ``` - -- b67d224: Fixes an issue where `providerMetadata` and `providerExecuted` were lost when tool input validation failed -- ab6f01a: Improve ai gateway error message when api key is not present -- 9388ff1: feat(ui): add isDataUIPart helper -- dce03c4: feat: tool input examples -- 2625a04: feat(openai); update spec for mcp approval -- 37c58a0: This release introduces `wrapEmbeddingModel`, a new helper that brings embedding model customization capabilities similar to `wrapLanguageModel`. -- 4e2b04d: fix(gateway): throw error with user-friendly message in non-production environments if `AI_GATEWAY_API_KEY` is not configured -- ab1087b: feat(ai): `chat.addToolResult()` is now `chat.addToolOutput()` -- bb10a89: fix(ai): mcp errors to be jsonrpc 2.0 compliant -- 457f1c6: feat(ai): onFinish callback for generateText -- 95f65c2: chore: use import \* from zod/v4 -- 754df61: fix(ai): correct type field in arrayOutputStrategy from 'enum' to 'array' -- 58920e0: refactor: consolidate header normalization across packages, remove duplicates, preserve custom headers -- 954c356: feat(openai): allow custom names for provider-defined tools -- 7fdd89d: feat(agent): export AgentCallParameters and AgentStreamParameters types -- eca63f3: feat(ai): add OAuth for MCP clients + refactor to new package - - This change replaces - - ```ts - import { experimental_createMCPClient } from "ai"; - import { Experimental_StdioMCPTransport } from "ai/mcp-stdio"; - ``` - - with - - ```ts - import { experimental_createMCPClient } from "@ai-sdk/mcp"; - import { Experimental_StdioMCPTransport } from "@ai-sdk/mcp/mcp-stdio"; - ``` - -- 90e5bdd: chore(ai): restructure agent files -- 42cf7ed: fix(agent): use tool.toModelOutput when available -- 544d4e8: chore(specification): rename v3 provider defined tool to provider tool -- 4812235: fix(ai): add missing export for `LoadSettingError` -- 7f2c9b6: fix(ui): do not submit automatically when server return with error -- 614599a: chore(ai): deprecate generateObject and streamObject -- 0c4822d: feat: `EmbeddingModelV3` -- e062079: chore(agent): move Agent.respond into createAgentStreamResponse function -- 2b49dae: feat(agent): support UIMessageStreamOptions in createAgentStreamResponse -- ee651d7: `https://v6.ai-sdk.dev` -> `https://ai-sdk.dev` -- 5a4e732: Export `parseJsonEventStream` and `uiMessageChunkSchema` from "ai" package -- f733285: fix(ai): only parse experimental_output in generateText when finishReason is stop -- 9b83947: feat(ai): add convertDataPart option to convertToModelMessages - - Add optional convertDataPart callback for converting custom data parts (URLs, code files, etc.) to text or file parts that models can process. Fully type-safe using existing UIMessage generics. - -- 7eca093: fix(ai): update `uiMessageChunkSchema` to satisfy the `UIMessageChunk` type -- 077aea3: feat(ai): stable structured output on generateText, streamText, and ToolLoopAgent -- 9f20c87: chore: updated README -- 521c537: feat(ai): Tool.needsApproval can be a function -- 7169511: feat(agent): support context in onFinish callback -- e8109d3: feat: tool execution approval -- 03849b0: move DelayedPromise into provider utils -- ed329cb: feat: `Provider-V3` -- 22ef5c6: feat(ai): Output.text() is default output mode -- 9ba4324: feat(ai): support SystemModelMessage[] in system and instructions properties -- 3bd2689: feat: extended token usage -- 293a6b7: Added a title to the tools -- 7c3c216: fixed docs and exported NoSpeechGeneratedError -- c62ecf0: feat(ai): add support for v2 specs in transcription and speech models -- d1bdadb: Added experimental_rerank support -- 703459a: feat: tool execution approval for dynamic tools -- 3071620: fix header loss when statusText is undefined in writeHead -- 7e4649f: fix(core): Fix image download behavior when the initial model is swapped out during prepareStep -- 48454ab: fix(ai): handle backpressure in `writeToServerResponse` -- e06b663: feat(agent): support experimental stream transforms -- 83e5744: feat: support async Tool.toModelOutput -- 8c98371: Extend addToolResult to support error results -- b1405bf: feat(ai): send context into streamText / generateText onFinish callbacks -- a5e152d: fix(ai): back version support for V2 providers -- aa0515c: feat(ai): move Agent to stable -- f6f0c5a: chore: remove zod from ui packages -- 3ed5519: chore: rename ToolCallOptions to ToolExecutionOptions -- eb8d1cb: fix not catching of empty arrays in validateUIMessage -- e7d9b00: feat(agent): add optional name property to agent -- d5b25ee: feat(ai): add Output.array() -- d7bae86: feat(ai): add Output.choice() -- 8dac895: feat: `LanguageModelV3` -- a755db5: feat(ai): improve warnings with provider and model id -- 1c2a4c1: fix(ai): remove outdated jsdoc param descriptions -- 686103c: chore(ai): export ContentPart type -- 0d6c0d8: chore(ai): remove deprecated CodeMessage type and related types and functions -- 9b8d17e: fix(agent): move provider options to main agent config -- 79a8e7f: feat(agent): support abortSignal in createAgentUIStream -- d59ce25: fix(ai): do not mutate middleware array argument when wrapping -- 475189e: chore(specification): rename EmbeddingModelCallOptions -- 3d83f38: chore(ai): improve addToolInputExamplesMiddleware -- 457318b: chore(provider,ai): switch to SharedV3Warning and unified warnings -- b681d7d: feat: expose usage tokens for 'generateImage' function -- c99da05: feat(ai): add onFinish to Agent -- db913bd: fix(google): add thought signature to gemini 3 pro image parts -- 9061dc0: feat: image editing -- 8445d70: feat: export GatewayModelId and use to type LanguageModel -- 32223c8: feat: add toolCallId arg to toModelOutput -- 8370068: fix(provider/google): preserve thoughtSignature through tool execution -- 5e313e3: fix(agent): do not allow static tools when tools is empty -- db62f7d: Added schema name and description for generateText and output -- a7f6f81: Add safeValidateUIMessages utility to validate UI messages without throwing, returning a success/failure result object like Zod’s safeParse -- 79ba99f: feat(agent): add message metadata support when inferring UI messages -- c98373a: chore(agent): rename createAgentStreamResponse to createAgentUIStreamResponse -- 846e80e: fix(ai): bind functions for v2 -> v3 adapter -- bbdcb81: Add experimental_context parameter to prepareStep callback -- 67a407c: chore(ai): add warning when using v2 models with AISDK v6 -- 9524761: chore(ai): rename relevanceScore to score -- ca13d26: feat(ai): add output to StreamTextResult -- 4616b86: chore: update zod peer depenedency version -- a322efa: Added finishReason on useChat onFinish callbck -- 2d166e4: feat(provider/gateway): add support for image models -- 384142c: feat(agent): add abortSignal parameter to generate and stream -- 36b175c: chore(ai): change output generics -- 2b1bf9d: feat(ai): add pruneMessages helper function -- 81d4308: feat: provider-executed dynamic tools -- e0d1ea9: fix(ai): align logic of text-end with reasoning-end -- 2406576: chore(agent): rename messages property on agent ui stream functions to uiMessages -- b1aeea7: feat(ai): set default stopWhen on Agent to stepCountIs(20) -- dce4e7b: chore(agent): rename system to instructions -- 4ece5f9: feat(agent): add experimental_download to ToolLoopAgent -- a417a34: feat(agent): introduce version property -- 637eaa4: feat(ai): print model warnings in embed and embedMany -- 177b475: fix(ai): download files when intermediate file cannot be downloaded -- 21e20c0: feat(provider): transcription model v3 spec -- afe7093: feat: add middleware for tool input examples -- 61f7b0f: chore(agent): rename BasicAgent to ToolLoopAgent -- af9dab3: fix(ai): remove unused mode setting from generateObject and streamObject -- 522f6b8: feat: `ImageModelV3` -- 97b1d77: fix(ui): Don't resend messages for providerExecuted tools in lastAssistantMessageIsCompleteWithToolCalls and lastAssistantMessageIsCompleteWithApprovalResponses -- 69768c2: chore(ai): remove UI message reference from model message validation -- 27e8c3a: chore(ai): rename Agent to BasicAgent, introduce Agent interface -- 81e29ab: feat(ai): allow modifying experimental context in prepareStep -- 7da02d2: fix(ai): prune messages properly when toolCalls set to 'before-last-message' -- 763d04a: feat: Standard JSON Schema support -- 95b77e2: feat(agent): extract createAgentUIStream, add pipeAgentUIStreamToResponse -- 3794514: feat: flexible tool output content support -- cbf52cd: feat: expose raw finish reason -- 14ca35d: feat: add support for v2 specs -- 10c1322: fix: moved dependency `@ai-sdk/test-server` to devDependencies -- dcdac8c: chore(ai): rename tool helpers -- 960ec8f: chore: change argument of toModelOutput to parameter object -- b59d924: feat(ai): support SystemModelMessage in system and instructions properties -- 1bd7d32: feat: tool-specific strict mode -- 95f65c2: chore: load zod schemas lazily -- Updated dependencies - - @ai-sdk/provider@3.0.0 - - @ai-sdk/gateway@2.0.0 - - @ai-sdk/provider-utils@4.0.0 - -## 6.0.0-beta.169 - -### Patch Changes - -- ee651d7: `https://v6.ai-sdk.dev` -> `https://ai-sdk.dev` - -## 6.0.0-beta.168 - -### Patch Changes - -- Updated dependencies [7294355] - - @ai-sdk/gateway@2.0.0-beta.93 - -## 6.0.0-beta.167 - -### Patch Changes - -- 475189e: chore(specification): rename EmbeddingModelCallOptions -- Updated dependencies [475189e] - - @ai-sdk/provider@3.0.0-beta.32 - - @ai-sdk/gateway@2.0.0-beta.92 - - @ai-sdk/provider-utils@4.0.0-beta.59 - -## 6.0.0-beta.166 - -### Patch Changes - -- 9f20c87: chore: updated README - -## 6.0.0-beta.165 - -### Patch Changes - -- 2625a04: feat(openai); update spec for mcp approval -- Updated dependencies [2625a04] - - @ai-sdk/provider@3.0.0-beta.31 - - @ai-sdk/gateway@2.0.0-beta.91 - - @ai-sdk/provider-utils@4.0.0-beta.58 - -## 6.0.0-beta.164 - -### Patch Changes - -- cbf52cd: feat: expose raw finish reason -- Updated dependencies [cbf52cd] - - @ai-sdk/provider@3.0.0-beta.30 - - @ai-sdk/gateway@2.0.0-beta.90 - - @ai-sdk/provider-utils@4.0.0-beta.57 - -## 6.0.0-beta.163 - -### Patch Changes - -- Updated dependencies [9549c9e] - - @ai-sdk/provider@3.0.0-beta.29 - - @ai-sdk/gateway@2.0.0-beta.89 - - @ai-sdk/provider-utils@4.0.0-beta.56 - -## 6.0.0-beta.162 - -### Patch Changes - -- 50b70d6: feat(anthropic): add programmatic tool calling -- Updated dependencies [50b70d6] - - @ai-sdk/provider-utils@4.0.0-beta.55 - - @ai-sdk/gateway@2.0.0-beta.88 - -## 6.0.0-beta.161 - -### Patch Changes - -- Updated dependencies [ee71658] - - @ai-sdk/gateway@2.0.0-beta.87 - -## 6.0.0-beta.160 - -### Patch Changes - -- 9061dc0: feat: image editing -- Updated dependencies [9061dc0] - - @ai-sdk/provider-utils@4.0.0-beta.54 - - @ai-sdk/provider@3.0.0-beta.28 - - @ai-sdk/gateway@2.0.0-beta.86 - -## 6.0.0-beta.159 - -### Patch Changes - -- 3071620: fix header loss when statusText is undefined in writeHead -- Updated dependencies [870297d] - - @ai-sdk/gateway@2.0.0-beta.85 - -## 6.0.0-beta.158 - -### Patch Changes - -- Updated dependencies [366f50b] - - @ai-sdk/provider@3.0.0-beta.27 - - @ai-sdk/gateway@2.0.0-beta.84 - - @ai-sdk/provider-utils@4.0.0-beta.53 - -## 6.0.0-beta.157 - -### Patch Changes - -- 763d04a: feat: Standard JSON Schema support -- Updated dependencies [763d04a] - - @ai-sdk/provider-utils@4.0.0-beta.52 - - @ai-sdk/gateway@2.0.0-beta.83 - -## 6.0.0-beta.156 - -### Patch Changes - -- 2406576: chore(agent): rename messages property on agent ui stream functions to uiMessages - -## 6.0.0-beta.155 - -### Patch Changes - -- Updated dependencies [c1efac4] - - @ai-sdk/provider-utils@4.0.0-beta.51 - - @ai-sdk/gateway@2.0.0-beta.82 - -## 6.0.0-beta.154 - -### Patch Changes - -- 32223c8: feat: add toolCallId arg to toModelOutput -- Updated dependencies [32223c8] - - @ai-sdk/provider-utils@4.0.0-beta.50 - - @ai-sdk/gateway@2.0.0-beta.81 - -## 6.0.0-beta.153 - -### Patch Changes - -- 83e5744: feat: support async Tool.toModelOutput -- Updated dependencies [83e5744] - - @ai-sdk/provider-utils@4.0.0-beta.49 - - @ai-sdk/gateway@2.0.0-beta.80 - -## 6.0.0-beta.152 - -### Patch Changes - -- 960ec8f: chore: change argument of toModelOutput to parameter object -- Updated dependencies [960ec8f] - - @ai-sdk/provider-utils@4.0.0-beta.48 - - @ai-sdk/gateway@2.0.0-beta.79 - -## 6.0.0-beta.151 - -### Patch Changes - -- dcdac8c: chore(ai): rename tool helpers - -## 6.0.0-beta.150 - -### Patch Changes - -- db62f7d: Added schema name and description for generateText and output - -## 6.0.0-beta.149 - -### Patch Changes - -- 4e2b04d: fix(gateway): throw error with user-friendly message in non-production environments if `AI_GATEWAY_API_KEY` is not configured - -## 6.0.0-beta.148 - -### Patch Changes - -- Updated dependencies [f18ef7f] - - @ai-sdk/gateway@2.0.0-beta.78 - -## 6.0.0-beta.147 - -### Patch Changes - -- 637eaa4: feat(ai): print model warnings in embed and embedMany - -## 6.0.0-beta.146 - -### Patch Changes - -- Updated dependencies [e9e157f] - - @ai-sdk/provider-utils@4.0.0-beta.47 - - @ai-sdk/gateway@2.0.0-beta.77 - -## 6.0.0-beta.145 - -### Patch Changes - -- Updated dependencies [34ee8d0] - - @ai-sdk/gateway@2.0.0-beta.76 - -## 6.0.0-beta.144 - -### Patch Changes - -- ab6f01a: Improve ai gateway error message when api key is not present - -## 6.0.0-beta.143 - -### Patch Changes - -- 81e29ab: feat(ai): allow modifying experimental context in prepareStep -- Updated dependencies [81e29ab] - - @ai-sdk/provider-utils@4.0.0-beta.46 - - @ai-sdk/gateway@2.0.0-beta.75 - -## 6.0.0-beta.142 - -### Patch Changes - -- 7169511: feat(agent): support context in onFinish callback -- bbdcb81: Add experimental_context parameter to prepareStep callback - -## 6.0.0-beta.141 - -### Patch Changes - -- b1405bf: feat(ai): send context into streamText / generateText onFinish callbacks - -## 6.0.0-beta.140 - -### Patch Changes - -- 7fdd89d: feat(agent): export AgentCallParameters and AgentStreamParameters types - -## 6.0.0-beta.139 - -### Patch Changes - -- 3bd2689: feat: extended token usage -- Updated dependencies [3bd2689] - - @ai-sdk/provider@3.0.0-beta.26 - - @ai-sdk/gateway@2.0.0-beta.74 - - @ai-sdk/provider-utils@4.0.0-beta.45 - -## 6.0.0-beta.138 - -### Patch Changes - -- Updated dependencies [53f3368] - - @ai-sdk/provider@3.0.0-beta.25 - - @ai-sdk/gateway@2.0.0-beta.73 - - @ai-sdk/provider-utils@4.0.0-beta.44 - -## 6.0.0-beta.137 - -### Patch Changes - -- 9ba4324: feat(ai): support SystemModelMessage[] in system and instructions properties - -## 6.0.0-beta.136 - -### Patch Changes - -- 3d83f38: chore(ai): improve addToolInputExamplesMiddleware - -## 6.0.0-beta.135 - -### Patch Changes - -- afe7093: feat: add middleware for tool input examples - -## 6.0.0-beta.134 - -### Patch Changes - -- 686103c: chore(ai): export ContentPart type - -## 6.0.0-beta.133 - -### Patch Changes - -- dce03c4: feat: tool input examples -- Updated dependencies [dce03c4] - - @ai-sdk/provider-utils@4.0.0-beta.43 - - @ai-sdk/provider@3.0.0-beta.24 - - @ai-sdk/gateway@2.0.0-beta.72 - -## 6.0.0-beta.132 - -### Patch Changes - -- af9dab3: fix(ai): remove unused mode setting from generateObject and streamObject - -## 6.0.0-beta.131 - -### Patch Changes - -- 3ed5519: chore: rename ToolCallOptions to ToolExecutionOptions -- Updated dependencies [3ed5519] - - @ai-sdk/provider-utils@4.0.0-beta.42 - - @ai-sdk/gateway@2.0.0-beta.71 - -## 6.0.0-beta.130 - -### Patch Changes - -- 1bd7d32: feat: tool-specific strict mode -- Updated dependencies [1bd7d32] - - @ai-sdk/provider-utils@4.0.0-beta.41 - - @ai-sdk/provider@3.0.0-beta.23 - - @ai-sdk/gateway@2.0.0-beta.70 - -## 6.0.0-beta.129 - -### Patch Changes - -- 67a407c: chore(ai): add warning when using v2 models with AISDK v6 - -## 6.0.0-beta.128 - -### Patch Changes - -- Updated dependencies [b1624f0] - - @ai-sdk/gateway@2.0.0-beta.69 - -## 6.0.0-beta.127 - -### Patch Changes - -- 614599a: chore(ai): deprecate generateObject and streamObject - -## 6.0.0-beta.126 - -### Patch Changes - -- b67d224: Fixes an issue where `providerMetadata` and `providerExecuted` were lost when tool input validation failed - -## 6.0.0-beta.125 - -### Patch Changes - -- 0d6c0d8: chore(ai): remove deprecated CodeMessage type and related types and functions - -## 6.0.0-beta.124 - -### Patch Changes - -- 544d4e8: chore(specification): rename v3 provider defined tool to provider tool -- Updated dependencies [544d4e8] - - @ai-sdk/provider-utils@4.0.0-beta.40 - - @ai-sdk/provider@3.0.0-beta.22 - - @ai-sdk/gateway@2.0.0-beta.68 - -## 6.0.0-beta.123 - -### Patch Changes - -- 954c356: feat(openai): allow custom names for provider-defined tools -- Updated dependencies [954c356] - - @ai-sdk/provider-utils@4.0.0-beta.39 - - @ai-sdk/provider@3.0.0-beta.21 - - @ai-sdk/gateway@2.0.0-beta.67 - -## 6.0.0-beta.122 - -### Patch Changes - -- 03849b0: move DelayedPromise into provider utils -- Updated dependencies [03849b0] - - @ai-sdk/provider-utils@4.0.0-beta.38 - - @ai-sdk/gateway@2.0.0-beta.66 - -## 6.0.0-beta.121 - -### Patch Changes - -- Updated dependencies [cdd0bc2] - - @ai-sdk/gateway@2.0.0-beta.65 - -## 6.0.0-beta.120 - -### Patch Changes - -- 457318b: chore(provider,ai): switch to SharedV3Warning and unified warnings -- Updated dependencies [457318b] - - @ai-sdk/provider@3.0.0-beta.20 - - @ai-sdk/gateway@2.0.0-beta.64 - - @ai-sdk/provider-utils@4.0.0-beta.37 - -## 6.0.0-beta.119 - -### Patch Changes - -- b59d924: feat(ai): support SystemModelMessage in system and instructions properties - -## 6.0.0-beta.118 - -### Patch Changes - -- 8d9e8ad: chore(provider): remove generics from EmbeddingModelV3 - - Before - - ```ts - model.textEmbeddingModel("my-model-id"); - ``` - - After - - ```ts - model.embeddingModel("my-model-id"); - ``` - -- Updated dependencies [8d9e8ad] - - @ai-sdk/provider@3.0.0-beta.19 - - @ai-sdk/gateway@2.0.0-beta.63 - - @ai-sdk/provider-utils@4.0.0-beta.36 - -## 6.0.0-beta.117 - -### Patch Changes - -- Updated dependencies [10d819b] - - @ai-sdk/provider@3.0.0-beta.18 - - @ai-sdk/gateway@2.0.0-beta.62 - - @ai-sdk/provider-utils@4.0.0-beta.35 - -## 6.0.0-beta.116 - -### Patch Changes - -- 4ece5f9: feat(agent): add experimental_download to ToolLoopAgent - -## 6.0.0-beta.115 - -### Patch Changes - -- 7da02d2: fix(ai): prune messages properly when toolCalls set to 'before-last-message' - -## 6.0.0-beta.114 - -### Patch Changes - -- 69768c2: chore(ai): remove UI message reference from model message validation - -## 6.0.0-beta.113 - -### Patch Changes - -- 79a8e7f: feat(agent): support abortSignal in createAgentUIStream - -## 6.0.0-beta.112 - -### Patch Changes - -- e06b663: feat(agent): support experimental stream transforms - -## 6.0.0-beta.111 - -### Patch Changes - -- Updated dependencies [e8694af] - - @ai-sdk/gateway@2.0.0-beta.61 - -## 6.0.0-beta.110 - -### Patch Changes - -- db913bd: fix(google): add thought signature to gemini 3 pro image parts -- Updated dependencies [db913bd] - - @ai-sdk/provider@3.0.0-beta.17 - - @ai-sdk/gateway@2.0.0-beta.60 - - @ai-sdk/provider-utils@4.0.0-beta.34 - -## 6.0.0-beta.109 - -### Patch Changes - -- 79ba99f: feat(agent): add message metadata support when inferring UI messages - -## 6.0.0-beta.108 - -### Patch Changes - -- Updated dependencies [5dd4c6a] - - @ai-sdk/gateway@2.0.0-beta.59 - -## 6.0.0-beta.107 - -### Patch Changes - -- 8445d70: feat: export GatewayModelId and use to type LanguageModel - -## 6.0.0-beta.106 - -### Patch Changes - -- Updated dependencies [1425df5] - - @ai-sdk/gateway@2.0.0-beta.58 - -## 6.0.0-beta.105 - -### Patch Changes - -- Updated dependencies [bca7e61] - - @ai-sdk/gateway@2.0.0-beta.57 - -## 6.0.0-beta.104 - -### Patch Changes - -- 2d166e4: feat(provider/gateway): add support for image models -- Updated dependencies [2d166e4] - - @ai-sdk/gateway@2.0.0-beta.56 - -## 6.0.0-beta.103 - -### Patch Changes - -- Updated dependencies [cc5170d] - - @ai-sdk/gateway@2.0.0-beta.55 - -## 6.0.0-beta.102 - -### Patch Changes - -- Updated dependencies [5f66123] - - @ai-sdk/gateway@2.0.0-beta.54 - -## 6.0.0-beta.101 - -### Patch Changes - -- Updated dependencies [3782645] - - @ai-sdk/gateway@2.0.0-beta.53 - -## 6.0.0-beta.100 - -### Patch Changes - -- 8370068: fix(provider/google): preserve thoughtSignature through tool execution - -## 6.0.0-beta.99 - -### Patch Changes - -- 384142c: feat(agent): add abortSignal parameter to generate and stream - -## 6.0.0-beta.98 - -### Patch Changes - -- b681d7d: feat: expose usage tokens for 'generateImage' function -- Updated dependencies [b681d7d] - - @ai-sdk/provider@3.0.0-beta.16 - - @ai-sdk/gateway@2.0.0-beta.52 - - @ai-sdk/provider-utils@4.0.0-beta.33 - -## 6.0.0-beta.97 - -### Patch Changes - -- Updated dependencies [32d8dbb] - - @ai-sdk/provider-utils@4.0.0-beta.32 - - @ai-sdk/gateway@2.0.0-beta.51 - -## 6.0.0-beta.96 - -### Patch Changes - -- a322efa: Added finishReason on useChat onFinish callbck - -## 6.0.0-beta.95 - -### Patch Changes - -- eb8d1cb: fix not catching of empty arrays in validateUIMessage - -## 6.0.0-beta.94 - -### Patch Changes - -- ab1087b: feat(ai): `chat.addToolResult()` is now `chat.addToolOutput()` - -## 6.0.0-beta.93 - -### Patch Changes - -- Updated dependencies [bb36798] - - @ai-sdk/provider@3.0.0-beta.15 - - @ai-sdk/gateway@2.0.0-beta.50 - - @ai-sdk/provider-utils@4.0.0-beta.31 - -## 6.0.0-beta.92 - -### Patch Changes - -- 97b1d77: fix(ui): Don't resend messages for providerExecuted tools in lastAssistantMessageIsCompleteWithToolCalls and lastAssistantMessageIsCompleteWithApprovalResponses - -## 6.0.0-beta.91 - -### Patch Changes - -- Updated dependencies [4f16c37] - - @ai-sdk/provider-utils@4.0.0-beta.30 - - @ai-sdk/gateway@2.0.0-beta.49 - -## 6.0.0-beta.90 - -### Patch Changes - -- Updated dependencies [af3780b] - - @ai-sdk/provider@3.0.0-beta.14 - - @ai-sdk/gateway@2.0.0-beta.48 - - @ai-sdk/provider-utils@4.0.0-beta.29 - -## 6.0.0-beta.89 - -### Patch Changes - -- d59ce25: fix(ai): do not mutate middleware array argument when wrapping - -## 6.0.0-beta.88 - -### Patch Changes - -- 22ef5c6: feat(ai): Output.text() is default output mode - -## 6.0.0-beta.87 - -### Patch Changes - -- ca13d26: feat(ai): add output to StreamTextResult - -## 6.0.0-beta.86 - -### Patch Changes - -- 36b175c: chore(ai): change output generics - -## 6.0.0-beta.85 - -### Patch Changes - -- Updated dependencies [96322b7] - - @ai-sdk/gateway@2.0.0-beta.47 - -## 6.0.0-beta.84 - -### Patch Changes - -- Updated dependencies [016b111] - - @ai-sdk/provider-utils@4.0.0-beta.28 - - @ai-sdk/gateway@2.0.0-beta.46 - -## 6.0.0-beta.83 - -### Patch Changes - -- e1f6e8e: feat(ai): add Output.json() - -## 6.0.0-beta.82 - -### Patch Changes - -- 37c58a0: This release introduces `wrapEmbeddingModel`, a new helper that brings embedding model customization capabilities similar to `wrapLanguageModel`. -- Updated dependencies [37c58a0] - - @ai-sdk/provider@3.0.0-beta.13 - - @ai-sdk/gateway@2.0.0-beta.45 - - @ai-sdk/provider-utils@4.0.0-beta.27 - -## 6.0.0-beta.81 - -### Patch Changes - -- Updated dependencies [7d73922] - - @ai-sdk/gateway@2.0.0-beta.44 - -## 6.0.0-beta.80 - -### Patch Changes - -- 9524761: chore(ai): rename relevanceScore to score - -## 6.0.0-beta.79 - -### Patch Changes - -- d1bdadb: Added experimental_rerank support -- Updated dependencies [d1bdadb] - - @ai-sdk/provider@3.0.0-beta.12 - - @ai-sdk/gateway@2.0.0-beta.43 - - @ai-sdk/provider-utils@4.0.0-beta.26 - -## 6.0.0-beta.78 - -### Patch Changes - -- Updated dependencies [4c44a5b] - - @ai-sdk/provider@3.0.0-beta.11 - - @ai-sdk/gateway@2.0.0-beta.42 - - @ai-sdk/provider-utils@4.0.0-beta.25 - -## 6.0.0-beta.77 - -### Patch Changes - -- 0c3b58b: fix(provider): add specificationVersion to ProviderV3 -- Updated dependencies [0c3b58b] - - @ai-sdk/provider@3.0.0-beta.10 - - @ai-sdk/gateway@2.0.0-beta.41 - - @ai-sdk/provider-utils@4.0.0-beta.24 - -## 6.0.0-beta.76 - -### Patch Changes - -- a755db5: feat(ai): improve warnings with provider and model id -- Updated dependencies [a755db5] - - @ai-sdk/provider@3.0.0-beta.9 - - @ai-sdk/gateway@2.0.0-beta.40 - - @ai-sdk/provider-utils@4.0.0-beta.23 - -## 6.0.0-beta.75 - -### Patch Changes - -- 58920e0: fix(ai): do not drop custom headers in HttpChatTransport -- 58920e0: refactor: consolidate header normalization across packages, remove duplicates, preserve custom headers -- Updated dependencies [58920e0] - - @ai-sdk/provider-utils@4.0.0-beta.22 - - @ai-sdk/gateway@2.0.0-beta.39 - -## 6.0.0-beta.74 - -### Patch Changes - -- 293a6b7: Added a title to the tools -- Updated dependencies [293a6b7] - - @ai-sdk/provider-utils@4.0.0-beta.21 - - @ai-sdk/gateway@2.0.0-beta.38 - -## 6.0.0-beta.73 - -### Patch Changes - -- 754df61: fix(ai): correct type field in arrayOutputStrategy from 'enum' to 'array' - -## 6.0.0-beta.72 - -### Patch Changes - -- eca63f3: feat(ai): add OAuth for MCP clients + refactor to new package - - This change replaces - - ```ts - import { experimental_createMCPClient } from "ai"; - import { Experimental_StdioMCPTransport } from "ai/mcp-stdio"; - ``` - - with - - ```ts - import { experimental_createMCPClient } from "@ai-sdk/mcp"; - import { Experimental_StdioMCPTransport } from "@ai-sdk/mcp/mcp-stdio"; - ``` - -## 6.0.0-beta.71 - -### Patch Changes - -- 077aea3: feat(ai): stable structured output on generateText, streamText, and ToolLoopAgent - -## 6.0.0-beta.70 - -### Patch Changes - -- d7bae86: feat(ai): add Output.choice() - -## 6.0.0-beta.69 - -### Patch Changes - -- d5b25ee: feat(ai): add Output.array() - -## 6.0.0-beta.68 - -### Patch Changes - -- 9b83947: feat(ai): add convertDataPart option to convertToModelMessages - - Add optional convertDataPart callback for converting custom data parts (URLs, code files, etc.) to text or file parts that models can process. Fully type-safe using existing UIMessage generics. - -## 6.0.0-beta.67 - -### Patch Changes - -- Updated dependencies [2b6a848] - - @ai-sdk/gateway@2.0.0-beta.37 - -## 6.0.0-beta.66 - -### Patch Changes - -- fca786b: feat(agent): configurable call options -- Updated dependencies [fca786b] - - @ai-sdk/provider-utils@4.0.0-beta.20 - - @ai-sdk/gateway@2.0.0-beta.36 - -## 6.0.0-beta.65 - -### Patch Changes - -- dce4e7b: chore(agent): rename system to instructions - -## 6.0.0-beta.64 - -### Patch Changes - -- 2d28066: chore(agent): limit agent call parameters - -## 6.0.0-beta.63 - -### Patch Changes - -- a7da2b6: feat(agent): change output generics - -## 6.0.0-beta.62 - -### Patch Changes - -- 95b77e2: feat(agent): extract createAgentUIStream, add pipeAgentUIStreamToResponse - -## 6.0.0-beta.61 - -### Patch Changes - -- c98373a: chore(agent): rename createAgentStreamResponse to createAgentUIStreamResponse - -## 6.0.0-beta.60 - -### Patch Changes - -- 2b49dae: feat(agent): support UIMessageStreamOptions in createAgentStreamResponse - -## 6.0.0-beta.59 - -### Patch Changes - -- e062079: chore(agent): move Agent.respond into createAgentStreamResponse function - -## 6.0.0-beta.58 - -### Patch Changes - -- a417a34: feat(agent): introduce version property - -## 6.0.0-beta.57 - -### Patch Changes - -- 61f7b0f: chore(agent): rename BasicAgent to ToolLoopAgent - -## 6.0.0-beta.56 - -### Patch Changes - -- 3794514: feat: flexible tool output content support -- Updated dependencies [3794514] - - @ai-sdk/provider-utils@4.0.0-beta.19 - - @ai-sdk/provider@3.0.0-beta.8 - - @ai-sdk/gateway@2.0.0-beta.35 - -## 6.0.0-beta.55 - -### Patch Changes - -- 42cf7ed: fix(agent): use tool.toModelOutput when available - -## 6.0.0-beta.54 - -### Patch Changes - -- 9388ff1: feat(ui): add isDataUIPart helper - -## 6.0.0-beta.53 - -### Patch Changes - -- Updated dependencies [2f8b0c8] - - @ai-sdk/gateway@2.0.0-beta.34 - -## 6.0.0-beta.52 - -### Patch Changes - -- Updated dependencies [1890317] - - @ai-sdk/gateway@2.0.0-beta.33 - -## 6.0.0-beta.51 - -### Patch Changes - -- 5e313e3: fix(agent): do not allow static tools when tools is empty - -## 6.0.0-beta.50 - -### Patch Changes - -- 4812235: fix(ai): add missing export for `LoadSettingError` -- 81d4308: feat: provider-executed dynamic tools -- Updated dependencies [81d4308] - - @ai-sdk/provider@3.0.0-beta.7 - - @ai-sdk/gateway@2.0.0-beta.32 - - @ai-sdk/provider-utils@4.0.0-beta.18 - -## 6.0.0-beta.49 - -### Patch Changes - -- 703459a: feat: tool execution approval for dynamic tools -- Updated dependencies [703459a] - - @ai-sdk/provider-utils@4.0.0-beta.17 - - @ai-sdk/gateway@2.0.0-beta.31 - -## 6.0.0-beta.48 - -### Patch Changes - -- 7f2c9b6: fix(ui): do not submit automatically when server return with error - -## 6.0.0-beta.47 - -### Patch Changes - -- c62ecf0: feat(ai): add support for v2 specs in transcription and speech models - -## 6.0.0-beta.46 - -### Patch Changes - -- Updated dependencies [0a2ff8a] - - @ai-sdk/gateway@2.0.0-beta.30 - -## 6.0.0-beta.45 - -### Patch Changes - -- 48454ab: fix(ai): handle backpressure in `writeToServerResponse` - -## 6.0.0-beta.44 - -### Patch Changes - -- 2b1bf9d: feat(ai): add pruneMessages helper function - -## 6.0.0-beta.43 - -### Patch Changes - -- 27e8c3a: chore(ai): rename Agent to BasicAgent, introduce Agent interface - -## 6.0.0-beta.42 - -### Patch Changes - -- Updated dependencies [6306603] - - @ai-sdk/provider-utils@4.0.0-beta.16 - - @ai-sdk/gateway@2.0.0-beta.29 - -## 6.0.0-beta.41 - -### Patch Changes - -- Updated dependencies [f0b2157] - - @ai-sdk/gateway@2.0.0-beta.28 - - @ai-sdk/provider-utils@4.0.0-beta.15 - -## 6.0.0-beta.40 - -### Patch Changes - -- Updated dependencies [3b1d015] - - @ai-sdk/provider-utils@4.0.0-beta.14 - - @ai-sdk/gateway@2.0.0-beta.27 - -## 6.0.0-beta.39 - -### Patch Changes - -- f6f0c5a: chore: remove zod from ui packages - -## 6.0.0-beta.38 - -### Patch Changes - -- Updated dependencies [d116b4b] - - @ai-sdk/provider-utils@4.0.0-beta.13 - - @ai-sdk/gateway@2.0.0-beta.26 - -## 6.0.0-beta.37 - -### Patch Changes - -- Updated dependencies [7e32fea] - - @ai-sdk/provider-utils@4.0.0-beta.12 - - @ai-sdk/gateway@2.0.0-beta.25 - -## 6.0.0-beta.36 - -### Patch Changes - -- Updated dependencies [0e29b8b] - - @ai-sdk/gateway@2.0.0-beta.24 - -## 6.0.0-beta.35 - -### Patch Changes - -- Updated dependencies [acc14d8] - - @ai-sdk/gateway@2.0.0-beta.23 - -## 6.0.0-beta.34 - -### Patch Changes - -- bb10a89: fix(ai): mcp errors to be jsonrpc 2.0 compliant - -## 6.0.0-beta.33 - -### Patch Changes - -- f733285: fix(ai): only parse experimental_output in generateText when finishReason is stop - -## 6.0.0-beta.32 - -### Patch Changes - -- 7e4649f: fix(core): Fix image download behavior when the initial model is swapped out during prepareStep - -## 6.0.0-beta.31 - -### Patch Changes - -- 95f65c2: chore: use import \* from zod/v4 -- 95f65c2: chore: load zod schemas lazily -- Updated dependencies - - @ai-sdk/provider-utils@4.0.0-beta.11 - - @ai-sdk/gateway@2.0.0-beta.22 - -## 6.0.0-beta.30 - -### Patch Changes - -- Updated dependencies [7b1b1b1] - - @ai-sdk/gateway@2.0.0-beta.21 - -## 6.0.0-beta.29 - -### Major Changes - -- dee8b05: ai SDK 6 beta - -### Patch Changes - -- Updated dependencies [dee8b05] - - @ai-sdk/gateway@2.0.0-beta.20 - - @ai-sdk/provider@3.0.0-beta.6 - - @ai-sdk/provider-utils@4.0.0-beta.10 - -## 5.1.0-beta.28 - -### Patch Changes - -- 521c537: feat(ai): Tool.needsApproval can be a function -- Updated dependencies [521c537] - - @ai-sdk/provider-utils@3.1.0-beta.9 - - @ai-sdk/gateway@1.1.0-beta.19 - -## 5.1.0-beta.27 - -### Patch Changes - -- Updated dependencies [e06565c] - - @ai-sdk/provider-utils@3.1.0-beta.8 - - @ai-sdk/gateway@1.1.0-beta.18 - -## 5.1.0-beta.26 - -### Patch Changes - -- c99da05: feat(ai): add onFinish to Agent - -## 5.1.0-beta.25 - -### Patch Changes - -- 457f1c6: feat(ai): onFinish callback for generateText - -## 5.1.0-beta.24 - -### Patch Changes - -- 90e5bdd: chore(ai): restructure agent files - -## 5.1.0-beta.23 - -### Patch Changes - -- Updated dependencies [1d8ea2c] - - @ai-sdk/gateway@1.1.0-beta.17 - -## 5.1.0-beta.22 - -### Patch Changes - -- 046aa3b: feat(provider): speech model v3 spec -- e8109d3: feat: tool execution approval -- a5e152d: fix(ai): back version support for V2 providers -- 21e20c0: feat(provider): transcription model v3 spec -- Updated dependencies - - @ai-sdk/provider@2.1.0-beta.5 - - @ai-sdk/provider-utils@3.1.0-beta.7 - - @ai-sdk/gateway@1.1.0-beta.16 - -## 5.1.0-beta.21 - -### Patch Changes - -- Updated dependencies [ef62178] - - @ai-sdk/gateway@1.1.0-beta.15 - -## 5.1.0-beta.20 - -### Patch Changes - -- 846e80e: fix(ai): bind functions for v2 -> v3 adapter -- Updated dependencies [a90dca6] - - @ai-sdk/gateway@1.1.0-beta.14 - -## 5.1.0-beta.19 - -### Patch Changes - -- aa0515c: feat(ai): move Agent to stable -- e7d9b00: feat(agent): add optional name property to agent -- b1aeea7: feat(ai): set default stopWhen on Agent to stepCountIs(20) - -## 5.1.0-beta.18 - -### Patch Changes - -- 0adc679: feat(provider): shared spec v3 -- 9b8d17e: fix(agent): move provider options to main agent config -- Updated dependencies - - @ai-sdk/provider-utils@3.1.0-beta.6 - - @ai-sdk/provider@2.1.0-beta.4 - - @ai-sdk/gateway@1.1.0-beta.13 - -## 5.1.0-beta.17 - -### Patch Changes - -- Updated dependencies [e6bfe91] - - @ai-sdk/gateway@1.1.0-beta.12 - -## 5.1.0-beta.16 - -### Patch Changes - -- 14ca35d: feat: add support for v2 specs -- Updated dependencies [636e614] - - @ai-sdk/gateway@1.1.0-beta.11 - -## 5.1.0-beta.15 - -### Patch Changes - -- Updated dependencies [9f6149e] - - @ai-sdk/gateway@1.1.0-beta.10 - -## 5.1.0-beta.14 - -### Patch Changes - -- 7c3c216: fixed docs and exported NoSpeechGeneratedError -- 8dac895: feat: `LanguageModelV3` -- e0d1ea9: fix(ai): align logic of text-end with reasoning-end -- 10c1322: fix: moved dependency `@ai-sdk/test-server` to devDependencies -- Updated dependencies [8dac895] - - @ai-sdk/provider-utils@3.1.0-beta.5 - - @ai-sdk/provider@2.1.0-beta.3 - - @ai-sdk/gateway@1.1.0-beta.9 - -## 5.1.0-beta.13 - -### Patch Changes - -- 1c2a4c1: fix(ai): remove outdated jsdoc param descriptions - -## 5.1.0-beta.12 - -### Patch Changes - -- Updated dependencies [c823faf] - - @ai-sdk/gateway@1.1.0-beta.8 - -## 5.1.0-beta.11 - -### Patch Changes - -- 4616b86: chore: update zod peer depenedency version -- Updated dependencies [4616b86] - - @ai-sdk/provider-utils@3.1.0-beta.4 - - @ai-sdk/gateway@1.1.0-beta.7 - -## 5.1.0-beta.10 - -### Patch Changes - -- 8c98371: Extend addToolResult to support error results - -## 5.1.0-beta.9 - -### Patch Changes - -- ed329cb: feat: `Provider-V3` -- 177b475: fix(ai): download files when intermediate file cannot be downloaded -- 522f6b8: feat: `ImageModelV3` -- Updated dependencies - - @ai-sdk/gateway@1.1.0-beta.6 - - @ai-sdk/provider@2.1.0-beta.2 - - @ai-sdk/provider-utils@3.1.0-beta.3 - -## 5.1.0-beta.8 - -### Patch Changes - -- 7eca093: fix(ai): update `uiMessageChunkSchema` to satisfy the `UIMessageChunk` type - -## 5.1.0-beta.7 - -### Patch Changes - -- 5a4e732: Export `parseJsonEventStream` and `uiMessageChunkSchema` from "ai" package - -## 5.1.0-beta.6 - -### Patch Changes - -- 0c4822d: feat: `EmbeddingModelV3` -- Updated dependencies - - @ai-sdk/gateway@1.1.0-beta.5 - - @ai-sdk/provider@2.1.0-beta.1 - - @ai-sdk/provider-utils@3.1.0-beta.2 - -## 5.1.0-beta.5 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/gateway@1.1.0-beta.4 - -## 5.1.0-beta.4 - -### Patch Changes - -- Updated dependencies [ea9ca31] - - @ai-sdk/gateway@1.1.0-beta.3 - -## 5.1.0-beta.3 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/gateway@1.1.0-beta.2 - -## 5.1.0-beta.2 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/test-server@1.0.0-beta.0 - - @ai-sdk/provider-utils@3.1.0-beta.1 - - @ai-sdk/gateway@1.1.0-beta.1 - -## 5.1.0-beta.1 - -### Patch Changes - -- a7f6f81: Add safeValidateUIMessages utility to validate UI messages without throwing, returning a success/failure result object like Zod’s safeParse - -## 5.1.0-beta.0 - -### Minor Changes - -- 78928cb: release: start 5.1 beta - -### Patch Changes - -- Updated dependencies [78928cb] - - @ai-sdk/gateway@1.1.0-beta.0 - - @ai-sdk/provider@2.1.0-beta.0 - - @ai-sdk/provider-utils@3.1.0-beta.0 - -## 5.0.45 - -### Patch Changes - -- 76024fc: fix(ai): fix static tool call and result detection when dynamic is undefined -- 93d8b60: fix(ai): do not filter zero-length text parts that have provider options -- d8eb31f: fix(ai): fix webp image detection from base64 - -## 5.0.44 - -### Patch Changes - -- Updated dependencies [f49f924] - - @ai-sdk/gateway@1.0.23 - -## 5.0.43 - -### Patch Changes - -- 0294b58: feat(ai): set `ai`, `@ai-sdk/provider-utils`, and runtime in `user-agent` header -- Updated dependencies [0294b58] - - @ai-sdk/provider-utils@3.0.9 - - @ai-sdk/gateway@1.0.22 - -## 5.0.42 - -### Patch Changes - -- de5c066: fix(ai): forwarded providerExecuted flag in validateUIMessages - -## 5.0.41 - -### Patch Changes - -- cd91e4b: fix(ai): use correct type for reasoning outputs - -## 5.0.40 - -### Patch Changes - -- Updated dependencies [4ee3719] - - @ai-sdk/gateway@1.0.21 - -## 5.0.39 - -### Patch Changes - -- a0a725f: feat (ai): export createGateway - -## 5.0.38 - -### Patch Changes - -- Updated dependencies [350a328] - - @ai-sdk/gateway@1.0.20 - -## 5.0.37 - -### Patch Changes - -- d6785d7: feat (ai): add tool and agent helpers - -## 5.0.36 - -### Patch Changes - -- ccc2ded: feat (ai): export gateway provider - -## 5.0.35 - -### Patch Changes - -- 99c946a: export missing type - -## 5.0.34 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/gateway@1.0.19 - -## 5.0.33 - -### Patch Changes - -- Updated dependencies [5d59a8c] - - @ai-sdk/gateway@1.0.18 - -## 5.0.32 - -### Patch Changes - -- Updated dependencies [b6005cd] - - @ai-sdk/gateway@1.0.17 - -## 5.0.31 - -### Patch Changes - -- Updated dependencies [99964ed] - - @ai-sdk/provider-utils@3.0.8 - - @ai-sdk/gateway@1.0.16 - -## 5.0.30 - -### Patch Changes - -- 7fcc6be: feat(ai): throw InvalidArgumentError when messages is not provided - -## 5.0.29 - -### Patch Changes - -- e0e9449: feat(ui): sent isAbort, isDisconnect, isError in useChat onFinish callback - -## 5.0.28 - -### Patch Changes - -- 4b81e7d: fix(ai): remove vitest dependency from test exports -- d68a4f2: feat(ai): log warnings - -## 5.0.27 - -### Patch Changes - -- ca40fac: feat(ai): support custom download functions (experimental) - -## 5.0.26 - -### Patch Changes - -- 33cf848: feat(ai): pass messages to `useChat({ onFinish })` -- Updated dependencies - - @ai-sdk/gateway@1.0.15 - -## 5.0.25 - -### Patch Changes - -- ca65923: fix(ai): remove use of `expect()` from production code -- Updated dependencies [886e7cd] - - @ai-sdk/provider-utils@3.0.7 - - @ai-sdk/gateway@1.0.14 - -## 5.0.24 - -### Patch Changes - -- f8f3682: fix: call onFinish when stream is cancelled in toUIMessageStream - - Previously, onFinish was only called on normal stream completion. Now it's also called when the reader is cancelled (e.g., browser close, navigation), ensuring partial messages are persisted. - -- Updated dependencies - - @ai-sdk/provider-utils@3.0.6 - - @ai-sdk/gateway@1.0.13 - -## 5.0.23 - -### Patch Changes - -- 5099b3d: fix(ai): make `chat.addToolResult()` compatible with dynamic tool calls -- 7a2bf8d: fix(ai): support loop breaking behavior in async iterable stream -- Updated dependencies - - @ai-sdk/gateway@1.0.12 - -## 5.0.22 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/gateway@1.0.11 - -## 5.0.21 - -### Patch Changes - -- 581abea: fix(ai): call abort callback when stream is aborted during tool execution -- 3c178ec: feat(ai): improved type checking for prompt/messages input -- Updated dependencies [0857788] - - @ai-sdk/provider-utils@3.0.5 - - @ai-sdk/gateway@1.0.10 - -## 5.0.20 - -### Patch Changes - -- 8a87693: fix(ai) Make sure warnings promise in streamObject is resolved and properly collects and passes warnings - -## 5.0.19 - -### Patch Changes - -- 8da6e9c: fix(ai): use parsed tool input if possible when validation fails - -## 5.0.18 - -### Patch Changes - -- Updated dependencies [8b96f99] - - @ai-sdk/gateway@1.0.9 - -## 5.0.17 - -### Patch Changes - -- 4176ecb: feat(ai): add reasoning text to generateObject result -- 20f23f9: feat(ai): export LanguageModelMiddleware type - -## 5.0.16 - -### Patch Changes - -- Updated dependencies [68751f9] - - @ai-sdk/provider-utils@3.0.4 - - @ai-sdk/gateway@1.0.8 - -## 5.0.15 - -### Patch Changes - -- ca4f68f: feat(ai): add validateUIMessages function -- Updated dependencies [28a4006] - - @ai-sdk/gateway@1.0.7 - -## 5.0.14 - -### Patch Changes - -- 7729e32: fix(ai): expand mp3 detection to support all mpeg frame headers - -## 5.0.13 - -### Patch Changes - -- a7b2e66: Added providerOptions to agent stream and generate calls -- 9bed210: ### `extractReasoningMiddleware()`: delay sending `text-start` chunk to prevent rendering final text before reasoning - - When wrapping a text stream in `extractReasoningMiddleware()`, delay queing the `text-start` chunk until either `reasoning-start` chunk was queued or the first `text-delta` chunk is about to be queued, whichever comes first. - - https://github.com/vercel/ai/pull/8036 - -## 5.0.12 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/gateway@1.0.6 - - @ai-sdk/provider-utils@3.0.3 - -## 5.0.11 - -### Patch Changes - -- 38ac190: feat(ai): preliminary tool results -- e3a63cb: fix(ai): streamText promises reject when stream has errors -- Updated dependencies - - @ai-sdk/provider-utils@3.0.2 - - @ai-sdk/gateway@1.0.5 - -## 5.0.10 - -### Patch Changes - -- 63a5dc5: fix(ai): convert user message text/file part provider metadata in convertToModelMessages - -## 5.0.9 - -### Patch Changes - -- afd5c2a: fix(ai): preserve filename for file parts in convertToModelMessages - -## 5.0.8 - -### Patch Changes - -- Updated dependencies [35f93ce] - - @ai-sdk/gateway@1.0.4 - -## 5.0.7 - -### Patch Changes - -- 8e72304: fix (ai): handle invalid tool calls - -## 5.0.6 - -### Patch Changes - -- d983eee: feat(ai): allow passing model string for embeddings - -## 5.0.5 - -### Patch Changes - -- Updated dependencies [893aed6] - - @ai-sdk/gateway@1.0.3 - -## 5.0.4 - -### Patch Changes - -- Updated dependencies [444df49] - - @ai-sdk/gateway@1.0.2 - -## 5.0.3 - -### Patch Changes - -- 90d212f: feat (ai): add experimental tool call context -- Updated dependencies - - @ai-sdk/gateway@1.0.1 - - @ai-sdk/provider-utils@3.0.1 - -## 5.0.2 - -### Patch Changes - -- 401d73e: fix (ai): support dynamic tool calls in lastAssistantMessageIsCompleteWithToolCalls -- 69fde99: Set status to ready when reconnect stream is null - -## 5.0.1 - -### Patch Changes - -- 4d0c108: fix(ai/ui): convert provider metadata for system messages to model messages - -## 5.0.0 - -### Major Changes - -- e1cbf8a: chore(@ai-sdk/rsc): extract to separate package -- a847c3e: chore: rename reasoning to reasoningText etc -- 13fef90: chore (ai): remove automatic conversion of UI messages to model messages -- d964901: - remove setting temperature to `0` by default - - remove `null` option from `DefaultSettingsMiddleware` - - remove setting defaults for `temperature` and `stopSequences` in `ai` to enable middleware changes -- 0a710d8: feat (ui): typed tool parts in ui messages -- 9ad0484: feat (ai): automatic tool execution error handling -- 63f9e9b: chore (provider,ai): tools have input/output instead of args,result -- ab7ccef: chore (ai): change source ui message parts to source-url -- d5f588f: AI SDK 5 -- ec78cdc: chore (ai): remove "data" UIMessage role -- 6a83f7d: refactoring (ai): restructure message metadata transfer -- db345da: chore (ai): remove exports of internal ui functions -- 496bbc1: chore (ui): inline/remove ChatRequest type -- 72d7d72: chore (ai): stable activeTools -- 40acf9b: feat (ui): introduce ChatStore and ChatTransport -- 98f25e5: chore (ui): remove managed chat inputs -- 2d03e19: chore (ai): remove StreamCallbacks.onCompletion -- da70d79: chore (ai): remove getUIText helper -- c60f895: chore (ai): remove useChat keepLastMessageOnError -- 0560977: chore (ai): improve consistency of generate text result, stream text result, and step result -- 9477ebb: chore (ui): remove useAssistant hook (**breaking change**) -- 1f55c21: chore (ai): send reasoning to the client by default -- e7dc6c7: chore (ai): remove onResponse callback -- 8b86e99: chore (ai): replace `Message` with `UIMessage` -- 04d5063: chore (ai): rename default provider global to AI_SDK_DEFAULT_PROVIDER -- 319b989: chore (ai): remove content from ui messages -- 14c9410: chore: refactor file towards source pattern (spec) -- a34eb39: chore (ai): remove `data` and `allowEmptySubmit` from `ChatRequestOptions` -- f04fb4a: chore (ai): replace useChat attachments with file ui parts -- f7e8bf4: chore (ai): flatten ui message stream parts -- 257224b: chore (ai): separate TextStreamChatTransport -- fd1924b: chore (ai): remove redundant `mimeType` property -- 2524fc7: chore (ai): remove ui message toolInvocations property -- 6fba4c7: chore (ai): remove deprecated experimental_providerMetadata -- b4b4bb2: chore (ui): rename experimental_resume to resumeStream -- 441d042: chore (ui): data stream protocol v2 with SSEs -- ef256ed: chore (ai): refactor and use chatstore in svelte -- 516be5b: ### Move Image Model Settings into generate options - - Image Models no longer have settings. Instead, `maxImagesPerCall` can be passed directly to `generateImage()`. All other image settings can be passed to `providerOptions[provider]`. - - Before - - ```js - await generateImage({ - model: luma.image("photon-flash-1", { - maxImagesPerCall: 5, - pollIntervalMillis: 500, - }), - prompt, - n: 10, - }); - ``` - - After - - ```js - await generateImage({ - model: luma.image("photon-flash-1"), - prompt, - n: 10, - maxImagesPerCall: 5, - providerOptions: { - luma: { pollIntervalMillis: 5 }, - }, - }); - ``` - - Pull Request: https://github.com/vercel/ai/pull/6180 - -- a662dea: chore (ai): remove sendExtraMessageFields -- d884051: feat (ai): simplify default provider setup -- e8324c5: feat (ai): add args callbacks to tools -- fafc3f2: chore (ai): change file to parts to use urls instead of data -- 1ed0287: chore (ai): stable sendStart/sendFinish options -- c7710a9: chore (ai): rename DataStreamToSSETransformStream to JsonToSseTransformStream -- bfbfc4c: feat (ai): streamText/generateText: totalUsage contains usage for all steps. usage is for a single step. -- 9ae327d: chore (ui): replace chat store concept with chat instances -- 9315076: chore (ai): rename continueUntil to stopWhen. Rename maxSteps stop condition to stepCountIs. -- 247ee0c: chore (ai): remove steps from tool invocation ui parts -- 109c0ac: chore (ai): rename id to chatId (in post request, resume request, and useChat) -- 954aa73: feat (ui): extended regenerate support -- 33eb499: feat (ai): inject message id in createUIMessageStream -- 901df02: feat (ui): use UI_MESSAGE generic -- 4892798: chore (ai): always stream tool calls -- c25cbce: feat (ai): use console.error as default error handler for streamText and streamObject -- b33ed7a: chore (ai): rename DataStream* to UIMessage* -- ed675de: feat (ai): add ui data parts -- 7bb58d4: chore (ai): restructure prepareRequest -- ea7a7c9: feat (ui): UI message metadata -- 0463011: fix (ai): update source url stream part -- dcc549b: remove StreamTextResult.mergeIntoDataStream method - rename DataStreamOptions.getErrorMessage to onError - add pipeTextStreamToResponse function - add createTextStreamResponse function - change createDataStreamResponse function to accept a DataStream and not a DataStreamWriter - change pipeDataStreamToResponse function to accept a DataStream and not a DataStreamWriter - change pipeDataStreamToResponse function to have a single parameter -- 35fc02c: chore (ui): rename RequestOptions to CompletionRequestOptions -- 64f6d64: feat (ai): replace maxSteps with continueUntil (generateText) -- 175b868: chore (ai): rename reasoning UI parts 'reasoning' property to 'text' -- 60e2c56: feat (ai): restructure chat transports -- 765f1cd: chore (ai): remove deprecated useChat isLoading helper -- cb2b53a: chore (ai): refactor header preparation -- e244a78: chore (ai): remove StreamData and mergeStreams -- d306260: feat (ai): replace maxSteps with continueUntil (streamText) -- 4bfe9ec: chore (ai): remove ui message reasoning property -- 1766ede: chore: rename maxTokens to maxOutputTokens -- 2877a74: chore (ai): remove ui message data property -- 1409e13: chore (ai): remove experimental continueSteps -- b32e192: chore (ai): rename reasoning to reasoningText, rename reasoningDetails to reasoning (streamText, generateText) -- 92cb0a2: chore (ai): rename CoreMessage to ModelMessage -- 2b637d6: chore (ai): rename UIMessageStreamPart to UIMessageChunk - -### Minor Changes - -- b7eae2d: feat (core): Add finishReason field to NoObjectGeneratedError -- bcea599: feat (ai): add content to generateText result -- 48d675a: feat (ai): add content to streamText result -- c9ad635: feat (ai): add filename to file ui parts - -### Patch Changes - -- a571d6e: chore(provider-utils): move ToolResultContent to provider-utils -- de2d2ab: feat(ai): add provider and provider registry middleware functionality -- c22ad54: feat(smooth-stream): chunking callbacks -- d88455d: feat (ai): expose http chat transport type -- e7fcc86: feat (ai): introduce dynamic tools -- da1e6f0: feat (ui): add generics to ui message stream parts -- 48378b9: fix (ai): send null as tool output when tools return undefined -- 5d1e3ba: chore (ai): remove provider re-exports -- 93d53a1: chore (ai): remove cli -- e90d45d: chore (rsc): move HANGING_STREAM_WARNING_TIME constant into @ai-sdk/rsc package -- b32c141: feat (ai): add array support to stopWhen -- bc3109f: chore (ai): push stream-callbacks into langchain/llamaindex adapters -- 0d9583c: fix (ai): use user-provided media type when available -- 38ae5cc: feat (ai): export InferUIMessageChunk type -- 10b21eb: feat(cli): add ai command line interface -- 9e40cbe: Allow destructuring output and errorText on `ToolUIPart` type -- 6909543: feat (ai): support system parameter in Agent constructor -- 86cfc72: feat (ai): add ignoreIncompleteToolCalls option to convertToModelMessages -- 377bbcf: fix (ui): tool input can be undefined during input-streaming -- d8aeaef: feat(providers/fal): add transcribe -- ae77a99: chore (ai): rename text and reasoning chunks in streamText fullstream -- 4fef487: feat: support for zod v4 for schema validation - - All these methods now accept both a zod v4 and zod v3 schemas for validation: - - - `generateObject()` - - `streamObject()` - - `generateText()` - - `experimental_useObject()` from `@ai-sdk/react` - - `streamUI()` from `@ai-sdk/rsc` - -- b1e3abd: feat (ai): expose ui message stream headers -- 4f3e637: fix (ui): avoid caching globalThis.fetch in case it is patched by other libraries -- 14cb3be: chore(providers/llamaindex): extract to separate package -- 1f6ce57: feat (ai): infer tool call types in the `onToolCall` callback -- 16ccfb2: feat (ai): add readUIMessageStream helper -- 225f087: fix (ai/mcp): prevent mutation of customEnv -- ce1d1f3: feat (ai): export mock image, speech, and transcription models -- fc0380b: feat (ui): resolvable header, body, credentials in http chat transport -- 6622441: feat (ai): add static/dynamic toolCalls/toolResults helpers -- 4048ce3: fix (ai): add tests and examples for openai responses -- 6c42e56: feat (ai): validate ui stream data chunks -- bedb239: chore (ai): make ui stream parts value optional when it's not required -- 9b4d074: feat(streamObject): add enum support -- c8fce91: feat (ai): add experimental Agent abstraction -- 655cf3c: feat (ui): add onFinish to createUIMessageStream -- 3e10408: fix(utils/detect-mimetype): add support for detecting id3 tags -- d5ae088: feat (ui): add sendAutomaticallyWhen to Chat -- ced8eee: feat(ai): re-export zodSchema from main package -- c040e2f: fix (ui): inject generated response message id -- d3960e3: selectTelemetryAttributes more robustness -- faea29f: fix (provider/openai): multi-step reasoning with text -- 66af894: fix (ai): respect content order in toResponseMessages -- 332167b: chore (ai): move maxSteps into UseChatOptions -- 6b1c55c: feat (ai): introduce GLOBAL_DEFAULT_PROVIDER -- 5a975a4: feat (ui): update Chat tool result submission -- 507ac1d: fix (ui/react): update messages immediately with the submitted user message -- a166433: feat: add transcription with experimental_transcribe -- 26735b5: chore(embedding-model): add v2 interface -- c93a8bc: chore(ai): export AsyncIterableStream type from async-iterable-stream module -- 0d2c085: feat (ai): support string model ids through gateway -- 2b9bbcd: feat (ai): improve prompt validation error message -- a8c8bd5: feat(embed-many): respect supportsParallelCalls & concurrency -- 75c3396: fix (ai): handle errors in 2nd streamText doStream call -- cb9c9e4: remove deprecated `experimental_wrapLanguageModel` -- 9bf7291: chore(providers/openai): enable structuredOutputs by default & switch to provider option -- 9b0da33: fix (ai): do not send id with start unless specified -- 28ad69e: fix(react-native): support experimental_attachments without FileList global -- 0b78e17: chore(ai/generateObject): simplify function signature -- 20398f2: feat: ai sdk cli documentation + adjusted default model -- 66962ed: fix(packages): export node10 compatible types -- b71fe8d: fix(ai): remove jsondiffpatch dependency -- 7827a49: fix (ai/core): refactor `toResponseMessages` to filter out empty string/content -- bd8a36c: feat(embedding-model-v2/embedMany): add response body field -- d9209ca: fix (image-model): `specificationVersion: v1` -> `v2` -- b346545: feat (ai): add data ui part schemas -- 05d2819: feat: allow zod 4.x as peer dependency -- f2b041e: Fix custom `fetch` in HttpChatTransport -- 2a62513: Fix error thrown when emptying messages in onError or onFinish -- 143c55b: feat (ai): export Chat callback types -- 9301f86: refactor (image-model): rename `ImageModelV1` to `ImageModelV2` -- 904fa5e: feat (ai/core): add terminateOnError option to readUIMessageStream -- 0a87932: core (ai): change transcription model mimeType to mediaType -- 1675396: fix: avoid job executor deadlock when adding tool result -- 51f497d: feat (ai): step input message modification in prepareStep -- cee64b2: fix(otel): change back toolCall attributes of input/output back to args/result for compatibility -- f04ffe4: feat (ui): add onData callback to Chat -- bc24722: feat (ai): Add finishReason as a promise on StreamObjectResult to match StreamTextResult -- b6f9f3c: remove deprecated `CoreTool*` types -- 8aa9e20: feat: add speech with experimental_generateSpeech -- 4617fab: chore(embedding-models): remove remaining settings -- 8255639: ### Fix use with Google APIs + zod v4's `.literal()` schema - - Before [zod@3.25.49](https://github.com/colinhacks/zod/releases/tag/v3.25.49), requests to Google's APIs failed due to a missing `type` in the provided schema. The problem has been resolved for the `ai` SDK by bumping our `zod` peer dependencies to `^3.25.49`. - - pull request: https://github.com/vercel/ai/pull/6609 - -- f81c720: chore(ai): bundle dependencies in CLI binary -- cf9af6e: feat (ai): allow sync prepareStep -- ee38081: Add support for audio/webm to detect-media-type -- 2e4f9e4: feat (ai): improved error messages when using gateway -- 3e3b9df: fix (ai/mcp): better support for zero-argument MCP tools -- cda32ba: fix (ai): send `start` part in correct position in stream (streamText) -- 48a7606: feat (ai): support changing the system prompt in prepareSteps -- cb68df0: feat: add transcription and speech model support to provider registry -- db64cbe: fix (provider/openai): multi-step reasoning with tool calls -- 97c35c0: feat (ui): transient data parts -- 26695a3: feat (ui): add state for text and reasoning ui message parts -- 90ac328: fix (ui): tool part metadata support in ui messages -- 60132dd: fixed date formatting for updated mcp protocol version -- 4a1e0c8: fix(ai-cli): fix bundling and improve authentication error handling -- c6b64a7: feat (ai): allow async prepareRequest on HttpChatTransport -- fccf75c: update mcp protocol version -- 9121250: Expose provider metadata as an attribute on exported OTEL spans -- ea27cc6: chore (ai): use JSONValue definition from provider -- 90ca2b9: feat(ai): Record tool call errors on tool call spans recorded in `generateText` and `streamText`. -- 50f0362: fix (ai): fix experimental sendStart/sendFinish options in streamText -- 825e8d7: release alpha.5 -- 7d97ab6: release alpha.4 -- 0ff02bb: chore(provider-utils): move over jsonSchema -- 4f3776c: feat (ai): add InferUITools helper -- 9338f3e: fix (ai): throw error for v1 models -- 92c8e66: fix(ai/core): properly handle custom separator in provider registry -- 53569b8: feat (ai): add experimental repairText function to streamObject -- 82aa95d: fix (ai): merge data ui stream parts correctly -- e7d2ce3: feat: provider-executed tools -- add5ac1: feat (ai): make streamText toUIMessageStream async iterable -- 37a916d: feat (ai): add prepareSteps to streamText -- 30ac566: fix (ui): text message metadata support in ui messages -- 8026705: fix (core): send buffered text in smooth stream when stream parts change -- 9bd5ab5: feat (provider): add providerMetadata to ImageModelV2 interface (#5977) - - The `experimental_generateImage` method from the `ai` package now returnes revised prompts for OpenAI's image models. - - ```js - const prompt = "Santa Claus driving a Cadillac"; - - const { providerMetadata } = await experimental_generateImage({ - model: openai.image("dall-e-3"), - prompt, - }); - - const revisedPrompt = providerMetadata.openai.images[0]?.revisedPrompt; - - console.log({ - prompt, - revisedPrompt, - }); - ``` - -- ec5933d: chore (ai/mcp): add `assertCapability` method to experimental MCP client -- 09f41ac: fix (ui): add message metadata in Chat.sendMessage -- ff1c81a: feat (ai): add streamText onAbort callback -- af1d5a5: fix(ai): Unexpected reasoning-start event in extract reasoning middleware -- cb3b9c9: fix (ai): catch errors in ui message stream -- 86293e5: fix (ai): use correct generateMessageId in streamText toUIMessageStream -- d1a034f: feature: using Zod 4 for internal stuff -- fd65bc6: chore(embedding-model-v2): rename rawResponse to response -- d92b9a8: fix(ai): add support for MCP protocol version 2025-06-18 -- 102b066: fix (ai): fix invalid fetch call -- 142576e: feat (ui): support message replacement in chat via messageId param on sendMessage -- 84343eb: fix (ui): call sendAutomaticallyWhen with updated messages -- a76a62b: feat (ai): add experimental prepareStep callback to generateText -- 89ba235: fix (ui): support tool names with dash -- 8e31d46: feat (ai): export SourceDocumentUIPart -- bd398e4: fix (core): improve error handling in streamText's consumeStream method -- 88a8ee5: fix (ai): support abort during retry waits -- 205077b: fix: improve Zod compatibility -- d91b50d: chore(ui-utils): merge into ai package -- e4c8647: feat (ui): allow asynchronous onFinish in createUIMessageStream -- c808e4d: fix (ui): do not send changing assistant message ids when onFinish is provided -- e862b5b: feat (ai): allow sync tool.execute -- 395c85e: feat (ai): add consumeSseStream option to UI message stream responses -- 5bdff05: Removed deprecated `options.throwErrorForEmptyVectors` from `cosineSimilarity()`. Since `throwErrorForEmptyVectors` was the only option the entire `options` argument was removed. - - ```diff - - cosineSimilarity(vector1, vector2, options) - +cosineSimilarity(vector1, vector2) - ``` - -- 13b4f46: feat (ai): export experimental MCPClient and MCPClientConfig interfaces -- a4f3007: chore: remove ai/react -- 8e64e9c: feat (ai): allow using provider default temperature by specifying null -- b983b51: feat (ai): support model message array in prompt -- 56c232b: fix (ai): remove outdated sendStart jsdoc -- 7324c21: fix (ai/telemetry): Avoid JSON.stringify on Uint8Arrays for telemetry -- f10304b: feat(tool-calling): don't require the user to have to pass parameters -- dd5fd43: feat (ai): support dynamic tools in Chat onToolCall -- a753b3a: feat (provider/anthropic): cache control for tools -- 383cbfa: feat (ai): add isAborted to onFinish callback for ui message streams -- 27deb4d: feat (provider/gateway): Add providerMetadata to embeddings response -- 5f2b3d4: chore (ai): stable prepareStep -- 4c8f834: feat: automatically respect rate limit headers in retry logic - - Added automatic support for respecting rate limit headers (`retry-after-ms` and `retry-after`) in the SDK's retry logic. When these headers are present and contain reasonable values (0-60 seconds), the retry mechanism will use the server-specified delay instead of exponential backoff. This matches the behavior of Anthropic and OpenAI client SDKs and improves rate limit handling without requiring any API changes. - -- f2c7f19: feat (ui): add Chat.clearError() -- 7bd025b: fix (ai): fix sync tool execute with streamText -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0 - - @ai-sdk/provider@2.0.0 - - @ai-sdk/gateway@1.0.0 - -## 5.0.0-beta.34 - -### Patch Changes - -- 53569b8: feat (ai): add experimental repairText function to streamObject -- 88a8ee5: fix (ai): support abort during retry waits -- f2c7f19: feat (ui): add Chat.clearError() -- Updated dependencies - - @ai-sdk/gateway@1.0.0-beta.19 - - @ai-sdk/provider-utils@3.0.0-beta.10 - -## 5.0.0-beta.33 - -### Patch Changes - -- 48378b9: fix (ai): send null as tool output when tools return undefined -- 93d53a1: chore (ai): remove cli -- 27deb4d: feat (provider/gateway): Add providerMetadata to embeddings response -- Updated dependencies [27deb4d] - - @ai-sdk/gateway@1.0.0-beta.18 - - @ai-sdk/provider@2.0.0-beta.2 - - @ai-sdk/provider-utils@3.0.0-beta.9 - -## 5.0.0-beta.32 - -### Patch Changes - -- bc24722: feat (ai): Add finishReason as a promise on StreamObjectResult to match StreamTextResult -- 13b4f46: feat (ai): export experimental MCPClient and MCPClientConfig interfaces -- 56c232b: fix (ai): remove outdated sendStart jsdoc - -## 5.0.0-beta.31 - -### Patch Changes - -- 6622441: feat (ai): add static/dynamic toolCalls/toolResults helpers -- ced8eee: feat(ai): re-export zodSchema from main package -- cee64b2: fix(otel): change back toolCall attributes of input/output back to args/result for compatibility -- ee38081: Add support for audio/webm to detect-media-type -- dd5fd43: feat (ai): support dynamic tools in Chat onToolCall -- Updated dependencies [dd5fd43] - - @ai-sdk/provider-utils@3.0.0-beta.8 - - @ai-sdk/gateway@1.0.0-beta.17 - -## 5.0.0-beta.30 - -### Patch Changes - -- Updated dependencies [fedb55e] - - @ai-sdk/gateway@1.0.0-beta.16 - -## 5.0.0-beta.29 - -### Patch Changes - -- e7fcc86: feat (ai): introduce dynamic tools -- d92b9a8: fix(ai): add support for MCP protocol version 2025-06-18 -- Updated dependencies [e7fcc86] - - @ai-sdk/provider-utils@3.0.0-beta.7 - - @ai-sdk/gateway@1.0.0-beta.15 - -## 5.0.0-beta.28 - -### Patch Changes - -- 84343eb: fix (ui): call sendAutomaticallyWhen with updated messages -- a753b3a: feat (provider/anthropic): cache control for tools -- Updated dependencies [ac34802] - - @ai-sdk/provider-utils@3.0.0-beta.6 - - @ai-sdk/gateway@1.0.0-beta.14 - -## 5.0.0-beta.27 - -### Patch Changes - -- d5ae088: feat (ui): add sendAutomaticallyWhen to Chat -- Updated dependencies - - @ai-sdk/gateway@1.0.0-beta.13 - -## 5.0.0-beta.26 - -### Patch Changes - -- ae77a99: chore (ai): rename text and reasoning chunks in streamText fullstream -- 1f6ce57: feat (ai): infer tool call types in the `onToolCall` callback -- 5a975a4: feat (ui): update Chat tool result submission -- 2a62513: Fix error thrown when emptying messages in onError or onFinish -- 904fa5e: feat (ai/core): add terminateOnError option to readUIMessageStream -- f81c720: chore(ai): bundle dependencies in CLI binary -- Updated dependencies [70ebead] - - @ai-sdk/gateway@1.0.0-beta.12 - -## 5.0.0-beta.25 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/gateway@1.0.0-beta.11 - -## 5.0.0-beta.24 - -### Patch Changes - -- add5ac1: feat (ai): make streamText toUIMessageStream async iterable -- ff1c81a: feat (ai): add streamText onAbort callback -- e4c8647: feat (ui): allow asynchronous onFinish in createUIMessageStream -- 383cbfa: feat (ai): add isAborted to onFinish callback for ui message streams -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-beta.5 - - @ai-sdk/gateway@1.0.0-beta.10 - -## 5.0.0-beta.23 - -### Patch Changes - -- 89ba235: fix (ui): support tool names with dash - -## 5.0.0-beta.22 - -### Patch Changes - -- de2d2ab: feat(ai): add provider and provider registry middleware functionality -- 6c42e56: feat (ai): validate ui stream data chunks -- c93a8bc: chore(ai): export AsyncIterableStream type from async-iterable-stream module -- 20398f2: feat: ai sdk cli documentation + adjusted default model -- 86293e5: fix (ai): use correct generateMessageId in streamText toUIMessageStream -- 205077b: fix: improve Zod compatibility -- Updated dependencies [205077b] - - @ai-sdk/provider-utils@3.0.0-beta.4 - - @ai-sdk/gateway@1.0.0-beta.9 - -## 5.0.0-beta.21 - -### Patch Changes - -- 38ae5cc: feat (ai): export InferUIMessageChunk type -- faea29f: fix (provider/openai): multi-step reasoning with text -- 90ac328: fix (ui): tool part metadata support in ui messages -- 4a1e0c8: fix(ai-cli): fix bundling and improve authentication error handling -- 30ac566: fix (ui): text message metadata support in ui messages - -## 5.0.0-beta.20 - -### Patch Changes - -- 4c8f834: feat: automatically respect rate limit headers in retry logic - - Added automatic support for respecting rate limit headers (`retry-after-ms` and `retry-after`) in the SDK's retry logic. When these headers are present and contain reasonable values (0-60 seconds), the retry mechanism will use the server-specified delay instead of exponential backoff. This matches the behavior of Anthropic and OpenAI client SDKs and improves rate limit handling without requiring any API changes. - -## 5.0.0-beta.19 - -### Patch Changes - -- 10b21eb: feat(cli): add ai command line interface -- 75c3396: fix (ai): handle errors in 2nd streamText doStream call -- 05d2819: feat: allow zod 4.x as peer dependency -- db64cbe: fix (provider/openai): multi-step reasoning with tool calls -- Updated dependencies [05d2819] - - @ai-sdk/provider-utils@3.0.0-beta.3 - - @ai-sdk/gateway@1.0.0-beta.8 - -## 5.0.0-beta.18 - -### Patch Changes - -- d3960e3: selectTelemetryAttributes more robustness -- 9338f3e: fix (ai): throw error for v1 models - -## 5.0.0-beta.17 - -### Patch Changes - -- Updated dependencies [c190907] - - @ai-sdk/gateway@1.0.0-beta.7 - -## 5.0.0-beta.16 - -### Patch Changes - -- Updated dependencies [9e16bfd] - - @ai-sdk/gateway@1.0.0-beta.6 - -## 5.0.0-beta.15 - -### Patch Changes - -- 8e31d46: feat (ai): export SourceDocumentUIPart - -## 5.0.0-beta.14 - -### Patch Changes - -- Updated dependencies [30ab1de] - - @ai-sdk/gateway@1.0.0-beta.5 - -## 5.0.0-beta.13 - -### Patch Changes - -- 377bbcf: fix (ui): tool input can be undefined during input-streaming -- ce1d1f3: feat (ai): export mock image, speech, and transcription models -- c040e2f: fix (ui): inject generated response message id -- c808e4d: fix (ui): do not send changing assistant message ids when onFinish is provided - -## 5.0.0-beta.12 - -### Patch Changes - -- fc0380b: feat (ui): resolvable header, body, credentials in http chat transport -- 51f497d: feat (ai): step input message modification in prepareStep -- 4f3776c: feat (ai): add InferUITools helper - -## 5.0.0-beta.11 - -### Patch Changes - -- 9e40cbe: Allow destructuring output and errorText on `ToolUIPart` type - -## 5.0.0-beta.10 - -### Major Changes - -- 2b637d6: chore (ai): rename UIMessageStreamPart to UIMessageChunk - -### Patch Changes - -- 16ccfb2: feat (ai): add readUIMessageStream helper -- 90ca2b9: feat(ai): Record tool call errors on tool call spans recorded in `generateText` and `streamText`. -- af1d5a5: fix(ai): Unexpected reasoning-start event in extract reasoning middleware - -## 5.0.0-beta.9 - -### Patch Changes - -- 86cfc72: feat (ai): add ignoreIncompleteToolCalls option to convertToModelMessages - -## 5.0.0-beta.8 - -### Patch Changes - -- 6909543: feat (ai): support system parameter in Agent constructor -- c8fce91: feat (ai): add experimental Agent abstraction -- 9121250: Expose provider metadata as an attribute on exported OTEL spans -- Updated dependencies [97fedf9] - - @ai-sdk/gateway@1.0.0-beta.4 - -## 5.0.0-beta.7 - -### Patch Changes - -- 60132dd: fixed date formatting for updated mcp protocol version - -## 5.0.0-beta.6 - -### Patch Changes - -- 143c55b: feat (ai): export Chat callback types -- f04ffe4: feat (ui): add onData callback to Chat -- 97c35c0: feat (ui): transient data parts -- fccf75c: update mcp protocol version - -## 5.0.0-beta.5 - -### Patch Changes - -- 4f3e637: fix (ui): avoid caching globalThis.fetch in case it is patched by other libraries - -## 5.0.0-beta.4 - -### Patch Changes - -- 09f41ac: fix (ui): add message metadata in Chat.sendMessage - -## 5.0.0-beta.3 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/gateway@1.0.0-beta.3 - -## 5.0.0-beta.2 - -### Patch Changes - -- 0d9583c: fix (ai): use user-provided media type when available -- c6b64a7: feat (ai): allow async prepareRequest on HttpChatTransport -- cb3b9c9: fix (ai): catch errors in ui message stream -- d1a034f: feature: using Zod 4 for internal stuff -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-beta.2 - - @ai-sdk/gateway@1.0.0-beta.2 - -## 5.0.0-beta.1 - -### Major Changes - -- 9ad0484: feat (ai): automatic tool execution error handling - -### Patch Changes - -- d88455d: feat (ai): expose http chat transport type -- 4048ce3: fix (ai): add tests and examples for openai responses -- f2b041e: Fix custom `fetch` in HttpChatTransport -- cb68df0: feat: add transcription and speech model support to provider registry -- 26695a3: feat (ui): add state for text and reasoning ui message parts -- e7d2ce3: feat: provider-executed tools -- 102b066: fix (ai): fix invalid fetch call -- e862b5b: feat (ai): allow sync tool.execute -- 7bd025b: fix (ai): fix sync tool execute with streamText -- Updated dependencies - - @ai-sdk/provider@2.0.0-beta.1 - - @ai-sdk/provider-utils@3.0.0-beta.1 - - @ai-sdk/gateway@1.0.0-beta.1 - -## 5.0.0-alpha.15 - -### Major Changes - -- 04d5063: chore (ai): rename default provider global to AI_SDK_DEFAULT_PROVIDER -- b4b4bb2: chore (ui): rename experimental_resume to resumeStream -- d884051: feat (ai): simplify default provider setup -- 954aa73: feat (ui): extended regenerate support -- 60e2c56: feat (ai): restructure chat transports - -### Patch Changes - -- b1e3abd: feat (ai): expose ui message stream headers -- 142576e: feat (ui): support message replacement in chat via messageId param on sendMessage -- 395c85e: feat (ai): add consumeSseStream option to UI message stream responses -- Updated dependencies - - @ai-sdk/provider@2.0.0-alpha.15 - - @ai-sdk/provider-utils@3.0.0-alpha.15 - - @ai-sdk/gateway@1.0.0-alpha.15 - -## 5.0.0-alpha.14 - -### Major Changes - -- 63f9e9b: chore (provider,ai): tools have input/output instead of args,result - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-alpha.14 - - @ai-sdk/gateway@1.0.0-alpha.14 - - @ai-sdk/provider-utils@3.0.0-alpha.14 - -## 5.0.0-alpha.13 - -### Major Changes - -- 0a710d8: feat (ui): typed tool parts in ui messages -- 6a83f7d: refactoring (ai): restructure message metadata transfer -- 1f55c21: chore (ai): send reasoning to the client by default -- 33eb499: feat (ai): inject message id in createUIMessageStream -- 901df02: feat (ui): use UI_MESSAGE generic - -### Patch Changes - -- Updated dependencies [68ecf2f] - - @ai-sdk/provider@2.0.0-alpha.13 - - @ai-sdk/gateway@1.0.0-alpha.13 - - @ai-sdk/provider-utils@3.0.0-alpha.13 - -## 5.0.0-alpha.12 - -### Major Changes - -- 4892798: chore (ai): always stream tool calls - -### Patch Changes - -- da1e6f0: feat (ui): add generics to ui message stream parts -- Updated dependencies [e2aceaf] - - @ai-sdk/gateway@1.0.0-alpha.12 - - @ai-sdk/provider@2.0.0-alpha.12 - - @ai-sdk/provider-utils@3.0.0-alpha.12 - -## 5.0.0-alpha.11 - -### Major Changes - -- e8324c5: feat (ai): add args callbacks to tools - -### Patch Changes - -- Updated dependencies [c1e6647] - - @ai-sdk/provider@2.0.0-alpha.11 - - @ai-sdk/gateway@1.0.0-alpha.11 - - @ai-sdk/provider-utils@3.0.0-alpha.11 - -## 5.0.0-alpha.10 - -### Major Changes - -- 98f25e5: chore (ui): remove managed chat inputs -- 7bb58d4: chore (ai): restructure prepareRequest - -### Patch Changes - -- Updated dependencies [c4df419] - - @ai-sdk/provider@2.0.0-alpha.10 - - @ai-sdk/gateway@1.0.0-alpha.10 - - @ai-sdk/provider-utils@3.0.0-alpha.10 - -## 5.0.0-alpha.9 - -### Major Changes - -- 9ae327d: chore (ui): replace chat store concept with chat instances - -### Patch Changes - -- 8255639: ### Fix use with Google APIs + zod v4's `.literal()` schema - - Before [zod@3.25.49](https://github.com/colinhacks/zod/releases/tag/v3.25.49), requests to Google's APIs failed due to a missing `type` in the provided schema. The problem has been resolved for the `ai` SDK by bumping our `zod` peer dependencies to `^3.25.49`. - - pull request: https://github.com/vercel/ai/pull/6609 - -- Updated dependencies - - @ai-sdk/gateway@1.0.0-alpha.9 - - @ai-sdk/provider@2.0.0-alpha.9 - - @ai-sdk/provider-utils@3.0.0-alpha.9 - -## 5.0.0-alpha.8 - -### Major Changes - -- c25cbce: feat (ai): use console.error as default error handler for streamText and streamObject - -### Patch Changes - -- 4fef487: feat: support for zod v4 for schema validation - - All these methods now accept both a zod v4 and zod v3 schemas for validation: - - - `generateObject()` - - `streamObject()` - - `generateText()` - - `experimental_useObject()` from `@ai-sdk/react` - - `streamUI()` from `@ai-sdk/rsc` - -- 6b1c55c: feat (ai): introduce GLOBAL_DEFAULT_PROVIDER -- 2e4f9e4: feat (ai): improved error messages when using gateway -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-alpha.8 - - @ai-sdk/provider@2.0.0-alpha.8 - - @ai-sdk/gateway@1.0.0-alpha.8 - -## 5.0.0-alpha.7 - -### Major Changes - -- db345da: chore (ai): remove exports of internal ui functions -- 247ee0c: chore (ai): remove steps from tool invocation ui parts - -### Patch Changes - -- 9b0da33: fix (ai): do not send id with start unless specified -- Updated dependencies [5c56081] - - @ai-sdk/provider@2.0.0-alpha.7 - - @ai-sdk/gateway@1.0.0-alpha.7 - - @ai-sdk/provider-utils@3.0.0-alpha.7 - -## 5.0.0-alpha.6 - -### Patch Changes - -- 0d2c085: feat (ai): support string model ids through gateway -- 48a7606: feat (ai): support changing the system prompt in prepareSteps -- Updated dependencies - - @ai-sdk/provider@2.0.0-alpha.6 - - @ai-sdk/gateway@1.0.0-alpha.6 - - @ai-sdk/provider-utils@3.0.0-alpha.6 - -## 5.0.0-alpha.5 - -### Major Changes - -- ef256ed: chore (ai): refactor and use chatstore in svelte -- 1ed0287: chore (ai): stable sendStart/sendFinish options - -### Patch Changes - -- 655cf3c: feat (ui): add onFinish to createUIMessageStream -- 1675396: fix: avoid job executor deadlock when adding tool result -- cf9af6e: feat (ai): allow sync prepareStep -- 825e8d7: release alpha.5 -- 7324c21: fix (ai/telemetry): Avoid JSON.stringify on Uint8Arrays for telemetry - -## 5.0.0-alpha.4 - -### Major Changes - -- 72d7d72: chore (ai): stable activeTools -- 9315076: chore (ai): rename continueUntil to stopWhen. Rename maxSteps stop condition to stepCountIs. - -### Patch Changes - -- b32c141: feat (ai): add array support to stopWhen -- 7d97ab6: release alpha.4 -- 37a916d: feat (ai): add prepareSteps to streamText -- 5f2b3d4: chore (ai): stable prepareStep -- Updated dependencies [dc714f3] - - @ai-sdk/provider@2.0.0-alpha.4 - - @ai-sdk/provider-utils@3.0.0-alpha.4 - -## 5.0.0-alpha.3 - -### Major Changes - -- ab7ccef: chore (ai): change source ui message parts to source-url -- 257224b: chore (ai): separate TextStreamChatTransport -- 0463011: fix (ai): update source url stream part -- d306260: feat (ai): replace maxSteps with continueUntil (streamText) - -### Patch Changes - -- Updated dependencies [6b98118] - - @ai-sdk/provider@2.0.0-alpha.3 - - @ai-sdk/provider-utils@3.0.0-alpha.3 - -## 5.0.0-alpha.2 - -### Patch Changes - -- 82aa95d: fix (ai): merge data ui stream parts correctly -- Updated dependencies [26535e0] - - @ai-sdk/provider@2.0.0-alpha.2 - - @ai-sdk/provider-utils@3.0.0-alpha.2 - -## 5.0.0-alpha.1 - -### Major Changes - -- 109c0ac: chore (ai): rename id to chatId (in post request, resume request, and useChat) - -### Patch Changes - -- b346545: feat (ai): add data ui part schemas -- Updated dependencies [3f2f00c] - - @ai-sdk/provider@2.0.0-alpha.1 - - @ai-sdk/provider-utils@3.0.0-alpha.1 - -## 5.0.0-canary.24 - -### Major Changes - -- f7e8bf4: chore (ai): flatten ui message stream parts -- ed675de: feat (ai): add ui data parts -- 64f6d64: feat (ai): replace maxSteps with continueUntil (generateText) - -### Patch Changes - -- bedb239: chore (ai): make ui stream parts value optional when it's not required -- 507ac1d: fix (ui/react): update messages immediately with the submitted user message -- 2b9bbcd: feat (ai): improve prompt validation error message -- cda32ba: fix (ai): send `start` part in correct position in stream (streamText) -- 50f0362: fix (ai): fix experimental sendStart/sendFinish options in streamText -- Updated dependencies [faf8446] - - @ai-sdk/provider-utils@3.0.0-canary.19 - -## 5.0.0-canary.23 - -### Major Changes - -- 40acf9b: feat (ui): introduce ChatStore and ChatTransport - -### Patch Changes - -- Updated dependencies [40acf9b] - - @ai-sdk/provider-utils@3.0.0-canary.18 - -## 5.0.0-canary.22 - -### Major Changes - -- e7dc6c7: chore (ai): remove onResponse callback -- a34eb39: chore (ai): remove `data` and `allowEmptySubmit` from `ChatRequestOptions` -- b33ed7a: chore (ai): rename DataStream* to UIMessage* -- 765f1cd: chore (ai): remove deprecated useChat isLoading helper - -## 5.0.0-canary.21 - -### Major Changes - -- d964901: - remove setting temperature to `0` by default - - remove `null` option from `DefaultSettingsMiddleware` - - remove setting defaults for `temperature` and `stopSequences` in `ai` to enable middleware changes -- 0560977: chore (ai): improve consistency of generate text result, stream text result, and step result -- 516be5b: ### Move Image Model Settings into generate options - - Image Models no longer have settings. Instead, `maxImagesPerCall` can be passed directly to `generateImage()`. All other image settings can be passed to `providerOptions[provider]`. - - Before - - ```js - await generateImage({ - model: luma.image("photon-flash-1", { - maxImagesPerCall: 5, - pollIntervalMillis: 500, - }), - prompt, - n: 10, - }); - ``` - - After - - ```js - await generateImage({ - model: luma.image("photon-flash-1"), - prompt, - n: 10, - maxImagesPerCall: 5, - providerOptions: { - luma: { pollIntervalMillis: 5 }, - }, - }); - ``` - - Pull Request: https://github.com/vercel/ai/pull/6180 - -- bfbfc4c: feat (ai): streamText/generateText: totalUsage contains usage for all steps. usage is for a single step. -- ea7a7c9: feat (ui): UI message metadata -- 1409e13: chore (ai): remove experimental continueSteps - -### Patch Changes - -- 66af894: fix (ai): respect content order in toResponseMessages -- Updated dependencies [ea7a7c9] - - @ai-sdk/provider-utils@3.0.0-canary.17 - -## 5.0.0-canary.20 - -### Major Changes - -- 13fef90: chore (ai): remove automatic conversion of UI messages to model messages -- 496bbc1: chore (ui): inline/remove ChatRequest type -- da70d79: chore (ai): remove getUIText helper -- c7710a9: chore (ai): rename DataStreamToSSETransformStream to JsonToSseTransformStream -- 35fc02c: chore (ui): rename RequestOptions to CompletionRequestOptions -- b983b51: feat (ai): support model message array in prompt - -### Minor Changes - -- bcea599: feat (ai): add content to generateText result -- 48d675a: feat (ai): add content to streamText result - -### Patch Changes - -- e90d45d: chore (rsc): move HANGING_STREAM_WARNING_TIME constant into @ai-sdk/rsc package -- bc3109f: chore (ai): push stream-callbacks into langchain/llamaindex adapters -- Updated dependencies [87b828f] - - @ai-sdk/provider-utils@3.0.0-canary.16 - -## 5.0.0-canary.19 - -### Major Changes - -- 2d03e19: chore (ai): remove StreamCallbacks.onCompletion -- 319b989: chore (ai): remove content from ui messages -- 441d042: chore (ui): data stream protocol v2 with SSEs -- dcc549b: remove StreamTextResult.mergeIntoDataStream method - rename DataStreamOptions.getErrorMessage to onError - add pipeTextStreamToResponse function - add createTextStreamResponse function - change createDataStreamResponse function to accept a DataStream and not a DataStreamWriter - change pipeDataStreamToResponse function to accept a DataStream and not a DataStreamWriter - change pipeDataStreamToResponse function to have a single parameter -- cb2b53a: chore (ai): refactor header preparation -- e244a78: chore (ai): remove StreamData and mergeStreams - -## 5.0.0-canary.18 - -### Major Changes - -- c60f895: chore (ai): remove useChat keepLastMessageOnError -- a662dea: chore (ai): remove sendExtraMessageFields - -### Patch Changes - -- a571d6e: chore(provider-utils): move ToolResultContent to provider-utils -- 332167b: chore (ai): move maxSteps into UseChatOptions -- a8c8bd5: feat(embed-many): respect supportsParallelCalls & concurrency -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.15 - - @ai-sdk/provider@2.0.0-canary.14 - -## 5.0.0-canary.17 - -### Major Changes - -- f04fb4a: chore (ai): replace useChat attachments with file ui parts -- fd1924b: chore (ai): remove redundant `mimeType` property -- fafc3f2: chore (ai): change file to parts to use urls instead of data -- 92cb0a2: chore (ai): rename CoreMessage to ModelMessage - -### Minor Changes - -- c9ad635: feat (ai): add filename to file ui parts - -### Patch Changes - -- 9bd5ab5: feat (provider): add providerMetadata to ImageModelV2 interface (#5977) - - The `experimental_generateImage` method from the `ai` package now returnes revised prompts for OpenAI's image models. - - ```js - const prompt = "Santa Claus driving a Cadillac"; - - const { providerMetadata } = await experimental_generateImage({ - model: openai.image("dall-e-3"), - prompt, - }); - - const revisedPrompt = providerMetadata.openai.images[0]?.revisedPrompt; - - console.log({ - prompt, - revisedPrompt, - }); - ``` - -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.14 - - @ai-sdk/provider@2.0.0-canary.13 - -## 5.0.0-canary.16 - -### Major Changes - -- ec78cdc: chore (ai): remove "data" UIMessage role -- 8b86e99: chore (ai): replace `Message` with `UIMessage` -- 2524fc7: chore (ai): remove ui message toolInvocations property -- 175b868: chore (ai): rename reasoning UI parts 'reasoning' property to 'text' - -### Patch Changes - -- 9b4d074: feat(streamObject): add enum support -- 28ad69e: fix(react-native): support experimental_attachments without FileList global -- ec5933d: chore (ai/mcp): add `assertCapability` method to experimental MCP client - -## 5.0.0-canary.15 - -### Major Changes - -- 4bfe9ec: chore (ai): remove ui message reasoning property -- 2877a74: chore (ai): remove ui message data property - -### Patch Changes - -- d9209ca: fix (image-model): `specificationVersion: v1` -> `v2` -- ea27cc6: chore (ai): use JSONValue definition from provider -- 0ff02bb: chore(provider-utils): move over jsonSchema -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.12 - - @ai-sdk/provider-utils@3.0.0-canary.13 - -## 5.0.0-canary.14 - -### Patch Changes - -- 9bf7291: chore(providers/openai): enable structuredOutputs by default & switch to provider option -- 4617fab: chore(embedding-models): remove remaining settings -- a76a62b: feat (ai): add experimental prepareStep callback to generateText -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.11 - - @ai-sdk/provider-utils@3.0.0-canary.12 - -## 5.0.0-canary.13 - -### Patch Changes - -- 14cb3be: chore(providers/llamaindex): extract to separate package -- 66962ed: fix(packages): export node10 compatible types -- 9301f86: refactor (image-model): rename `ImageModelV1` to `ImageModelV2` -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.11 - - @ai-sdk/provider@2.0.0-canary.10 - -## 5.0.0-canary.12 - -### Patch Changes - -- Updated dependencies [e86be6f] - - @ai-sdk/provider@2.0.0-canary.9 - - @ai-sdk/provider-utils@3.0.0-canary.10 - -## 5.0.0-canary.11 - -### Patch Changes - -- 8e64e9c: feat (ai): allow using provider default temperature by specifying null -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.8 - - @ai-sdk/provider-utils@3.0.0-canary.9 - -## 5.0.0-canary.10 - -### Patch Changes - -- d8aeaef: feat(providers/fal): add transcribe -- 3e10408: fix(utils/detect-mimetype): add support for detecting id3 tags - -## 5.0.0-canary.9 - -### Major Changes - -- a847c3e: chore: rename reasoning to reasoningText etc -- b32e192: chore (ai): rename reasoning to reasoningText, rename reasoningDetails to reasoning (streamText, generateText) - -### Patch Changes - -- cb9c9e4: remove deprecated `experimental_wrapLanguageModel` -- 8aa9e20: feat: add speech with experimental_generateSpeech -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.8 - - @ai-sdk/provider@2.0.0-canary.7 - -## 5.0.0-canary.8 - -### Major Changes - -- 14c9410: chore: refactor file towards source pattern (spec) - -### Patch Changes - -- 5d1e3ba: chore (ai): remove provider re-exports -- 26735b5: chore(embedding-model): add v2 interface -- 7827a49: fix (ai/core): refactor `toResponseMessages` to filter out empty string/content -- bd8a36c: feat(embedding-model-v2/embedMany): add response body field -- b6f9f3c: remove deprecated `CoreTool*` types -- 92c8e66: fix(ai/core): properly handle custom separator in provider registry -- fd65bc6: chore(embedding-model-v2): rename rawResponse to response -- 5bdff05: Removed deprecated `options.throwErrorForEmptyVectors` from `cosineSimilarity()`. Since `throwErrorForEmptyVectors` was the only option the entire `options` argument was removed. - - ```diff - - cosineSimilarity(vector1, vector2, options) - +cosineSimilarity(vector1, vector2) - ``` - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.6 - - @ai-sdk/provider-utils@3.0.0-canary.7 - -## 5.0.0-canary.7 - -### Major Changes - -- 6fba4c7: chore (ai): remove deprecated experimental_providerMetadata -- 1766ede: chore: rename maxTokens to maxOutputTokens - -### Patch Changes - -- 0b78e17: chore(ai/generateObject): simplify function signature -- 3e3b9df: fix (ai/mcp): better support for zero-argument MCP tools -- f10304b: feat(tool-calling): don't require the user to have to pass parameters -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.5 - - @ai-sdk/provider-utils@3.0.0-canary.6 - -## 5.0.0-canary.6 - -### Patch Changes - -- Updated dependencies [6f6bb89] - - @ai-sdk/provider@2.0.0-canary.4 - - @ai-sdk/provider-utils@3.0.0-canary.5 - -## 5.0.0-canary.5 - -### Patch Changes - -- b71fe8d: fix(ai): remove jsondiffpatch dependency -- d91b50d: chore(ui-utils): merge into ai package -- Updated dependencies [d1a1aa1] - - @ai-sdk/provider@2.0.0-canary.3 - - @ai-sdk/provider-utils@3.0.0-canary.4 - -## 5.0.0-canary.4 - -### Major Changes - -- e1cbf8a: chore(@ai-sdk/rsc): extract to separate package - -### Patch Changes - -- 225f087: fix (ai/mcp): prevent mutation of customEnv -- a166433: feat: add transcription with experimental_transcribe -- 0a87932: core (ai): change transcription model mimeType to mediaType -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.3 - - @ai-sdk/provider@2.0.0-canary.2 - - @ai-sdk/ui-utils@2.0.0-canary.3 - -## 5.0.0-canary.3 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider@2.0.0-canary.1 - - @ai-sdk/provider-utils@3.0.0-canary.2 - - @ai-sdk/ui-utils@2.0.0-canary.2 - -## 5.0.0-canary.2 - -### Patch Changes - -- bd398e4: fix (core): improve error handling in streamText's consumeStream method - -## 5.0.0-canary.1 - -### Minor Changes - -- b7eae2d: feat (core): Add finishReason field to NoObjectGeneratedError - -### Patch Changes - -- c22ad54: feat(smooth-stream): chunking callbacks -- a4f3007: chore: remove ai/react -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.1 - - @ai-sdk/ui-utils@2.0.0-canary.1 - -## 5.0.0-canary.0 - -### Major Changes - -- d5f588f: AI SDK 5 -- 9477ebb: chore (ui): remove useAssistant hook (**breaking change**) - -### Patch Changes - -- 8026705: fix (core): send buffered text in smooth stream when stream parts change -- Updated dependencies - - @ai-sdk/provider-utils@3.0.0-canary.0 - - @ai-sdk/ui-utils@2.0.0-canary.0 - - @ai-sdk/react@2.0.0-canary.0 - - @ai-sdk/provider@2.0.0-canary.0 - -## 4.2.10 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/react@1.2.5 - - @ai-sdk/provider-utils@2.2.3 - - @ai-sdk/ui-utils@1.2.4 - -## 4.2.9 - -### Patch Changes - -- Updated dependencies [b01120e] - - @ai-sdk/provider-utils@2.2.2 - - @ai-sdk/react@1.2.4 - - @ai-sdk/ui-utils@1.2.3 - -## 4.2.8 - -### Patch Changes - -- 65243ce: fix (ui): introduce step start parts -- Updated dependencies [65243ce] - - @ai-sdk/ui-utils@1.2.2 - - @ai-sdk/react@1.2.3 - -## 4.2.7 - -### Patch Changes - -- e14c066: fix (ai/core): convert user ui messages with only parts (no content) to core messages - -## 4.2.6 - -### Patch Changes - -- 625591b: feat (ai/core): auto-complete for provider registry -- 6a1506f: feat (ai/core): custom separator support for provider registry -- ea3d998: chore (ai/core): move provider registry to stable - -## 4.2.5 - -### Patch Changes - -- Updated dependencies [d92fa29] - - @ai-sdk/react@1.2.2 - -## 4.2.4 - -### Patch Changes - -- 3d6d96d: fix (ai/core): validate that messages are not empty - -## 4.2.3 - -### Patch Changes - -- 0b3bf29: fix (ai/core): custom env support for stdio MCP transport - -## 4.2.2 - -### Patch Changes - -- f10f0fa: fix (provider-utils): improve event source stream parsing performance -- Updated dependencies [f10f0fa] - - @ai-sdk/provider-utils@2.2.1 - - @ai-sdk/react@1.2.1 - - @ai-sdk/ui-utils@1.2.1 - -## 4.2.1 - -### Patch Changes - -- b796152: feat (ai/core): add headers to MCP SSE transport -- 06361d6: feat (ai/core): expose JSON RPC types (MCP) - -## 4.2.0 - -### Minor Changes - -- 5bc638d: AI SDK 4.2 - -### Patch Changes - -- Updated dependencies [5bc638d] - - @ai-sdk/provider@1.1.0 - - @ai-sdk/provider-utils@2.2.0 - - @ai-sdk/react@1.2.0 - - @ai-sdk/ui-utils@1.2.0 - -## 4.1.66 - -### Patch Changes - -- 5d0fc29: chore (ai): improve cosine similarity calculation - -## 4.1.65 - -### Patch Changes - -- 16c444f: fix (ai): expose ai/mcp-stdio - -## 4.1.64 - -### Patch Changes - -- Updated dependencies [d0c4659] - - @ai-sdk/provider-utils@2.1.15 - - @ai-sdk/react@1.1.25 - - @ai-sdk/ui-utils@1.1.21 - -## 4.1.63 - -### Patch Changes - -- 0bd5bc6: feat (ai): support model-generated files -- Updated dependencies [0bd5bc6] - - @ai-sdk/provider@1.0.12 - - @ai-sdk/provider-utils@2.1.14 - - @ai-sdk/ui-utils@1.1.20 - - @ai-sdk/react@1.1.24 - -## 4.1.62 - -### Patch Changes - -- c9ed3c4: feat: enable custom mcp transports - breaking change: remove internal stdio transport creation - -## 4.1.61 - -### Patch Changes - -- 2e1101a: feat (provider/openai): pdf input support -- Updated dependencies [2e1101a] - - @ai-sdk/provider@1.0.11 - - @ai-sdk/provider-utils@2.1.13 - - @ai-sdk/ui-utils@1.1.19 - - @ai-sdk/react@1.1.23 - -## 4.1.60 - -### Patch Changes - -- 0b8797f: feat (ai/core): expose response body for each generateText step - -## 4.1.59 - -### Patch Changes - -- dd18049: fix (ai/core): suppress next.js warnings for node.js specific code path - -## 4.1.58 - -### Patch Changes - -- e9897eb: fix (ai/core): move process access into functions and use globalThis - -## 4.1.57 - -### Patch Changes - -- 092fdaa: feat (ai/core): add defaultSettingsMiddleware - -## 4.1.56 - -### Patch Changes - -- 80be82b: feat (ai/core): add simulateStreamingMiddleware -- 8109a24: fix (ai/core): limit node imports to types where possible - -## 4.1.55 - -### Patch Changes - -- 1531959: feat (ai/core): add MCP client for using MCP tools -- Updated dependencies [1531959] - - @ai-sdk/provider-utils@2.1.12 - - @ai-sdk/react@1.1.22 - - @ai-sdk/ui-utils@1.1.18 - -## 4.1.54 - -### Patch Changes - -- ee1c787: fix (ai/core): correct spread apply order to fix extract reasoning middleware with generateText - -## 4.1.53 - -### Patch Changes - -- e1d3d42: feat (ai): expose raw response body in generateText and generateObject -- Updated dependencies [e1d3d42] - - @ai-sdk/provider@1.0.10 - - @ai-sdk/provider-utils@2.1.11 - - @ai-sdk/ui-utils@1.1.17 - - @ai-sdk/react@1.1.21 - -## 4.1.52 - -### Patch Changes - -- 5329a69: fix (ai/core): fix duplicated reasoning in streamText onFinish and messages - -## 4.1.51 - -### Patch Changes - -- 0cb2647: feat (ai/core): add streamText sendStart & sendFinish data stream options - -## 4.1.50 - -### Patch Changes - -- ae98f0d: fix (ai/core): forward providerOptions for text, image, and file parts - -## 4.1.49 - -### Patch Changes - -- dc027d3: fix (ai/core): add reasoning support to appendResponseMessages - -## 4.1.48 - -### Patch Changes - -- Updated dependencies [6255fbc] - - @ai-sdk/react@1.1.20 - -## 4.1.47 - -### Patch Changes - -- Updated dependencies [da5c734] - - @ai-sdk/react@1.1.19 - -## 4.1.46 - -### Patch Changes - -- ddf9740: feat (ai): add anthropic reasoning -- Updated dependencies [ddf9740] - - @ai-sdk/provider@1.0.9 - - @ai-sdk/ui-utils@1.1.16 - - @ai-sdk/provider-utils@2.1.10 - - @ai-sdk/react@1.1.18 - -## 4.1.45 - -### Patch Changes - -- 93bd5a0: feat (ai/ui): add writeSource to createDataStream - -## 4.1.44 - -### Patch Changes - -- f8e7df2: fix (ai/core): add `startWithReasoning` option to `extractReasoningMiddleware` - -## 4.1.43 - -### Patch Changes - -- ef2e23b: feat (ai/core): add experimental repairText function to generateObject - -## 4.1.42 - -### Patch Changes - -- Updated dependencies [2761f06] - - @ai-sdk/provider@1.0.8 - - @ai-sdk/provider-utils@2.1.9 - - @ai-sdk/ui-utils@1.1.15 - - @ai-sdk/react@1.1.17 - -## 4.1.41 - -### Patch Changes - -- Updated dependencies [60c3220] - - @ai-sdk/react@1.1.16 - -## 4.1.40 - -### Patch Changes - -- Updated dependencies [c43df41] - - @ai-sdk/react@1.1.15 - -## 4.1.39 - -### Patch Changes - -- 075a9a9: fix (ai): improve tsdoc on custom provider - -## 4.1.38 - -### Patch Changes - -- 4c9c194: chore (ai): add description to provider-defined tools for better accessibility -- 2e898b4: chore (ai): move mockId test helper into provider utils -- Updated dependencies [2e898b4] - - @ai-sdk/provider-utils@2.1.8 - - @ai-sdk/react@1.1.14 - - @ai-sdk/ui-utils@1.1.14 - -## 4.1.37 - -### Patch Changes - -- c1e10d1: chore: export UIMessage type - -## 4.1.36 - -### Patch Changes - -- Updated dependencies [3ff4ef8] - - @ai-sdk/provider-utils@2.1.7 - - @ai-sdk/react@1.1.13 - - @ai-sdk/ui-utils@1.1.13 - -## 4.1.35 - -### Patch Changes - -- 166e09e: feat (ai/ui): forward source parts to useChat -- Updated dependencies [166e09e] - - @ai-sdk/ui-utils@1.1.12 - - @ai-sdk/react@1.1.12 - -## 4.1.34 - -### Patch Changes - -- dc49119: chore: deprecate ai/react - -## 4.1.33 - -### Patch Changes - -- 74f0f0e: chore (ai/core): move providerMetadata to stable - -## 4.1.32 - -### Patch Changes - -- c128ca5: fix (ai/core): fix streamText onFinish messages with structured output - -## 4.1.31 - -### Patch Changes - -- b30b1cc: feat (ai/core): add onError callback to streamObject - -## 4.1.30 - -### Patch Changes - -- 4ee5b6f: fix (core): remove invalid providerOptions from streamObject onFinish callback - -## 4.1.29 - -### Patch Changes - -- 605de49: feat (ai/core): export callback types - -## 4.1.28 - -### Patch Changes - -- 6eb7fc4: feat (ai/core): url source support - -## 4.1.27 - -### Patch Changes - -- Updated dependencies [318b351] - - @ai-sdk/ui-utils@1.1.11 - - @ai-sdk/react@1.1.11 - -## 4.1.26 - -### Patch Changes - -- 34983d4: fix (ai/core): bind supportsUrl when creating wrapper - -## 4.1.25 - -### Patch Changes - -- 5a21310: fix (ai/core): use ai types on custom provider to prevent ts error - -## 4.1.24 - -### Patch Changes - -- 38142b8: feat (ai/core): introduce streamText consumeStream - -## 4.1.23 - -### Patch Changes - -- b08f7c1: fix (ai/core): suppress errors in textStream - -## 4.1.22 - -### Patch Changes - -- 2bec72a: feat (ai/core): add onError callback to streamText - -## 4.1.21 - -### Patch Changes - -- d387989: feat (ai/core): re-export zodSchema - -## 4.1.20 - -### Patch Changes - -- bcc61d4: feat (ui): introduce message parts for useChat -- Updated dependencies [bcc61d4] - - @ai-sdk/ui-utils@1.1.10 - - @ai-sdk/react@1.1.10 - -## 4.1.19 - -### Patch Changes - -- Updated dependencies [6b8cc14] - - @ai-sdk/ui-utils@1.1.9 - - @ai-sdk/react@1.1.9 - -## 4.1.18 - -### Patch Changes - -- 6a1acfe: fix (ai/core): revert '@internal' tag on function definitions due to build impacts - -## 4.1.17 - -### Patch Changes - -- 5af8cdb: fix (ai/core): support this reference in model.supportsUrl implementations - -## 4.1.16 - -### Patch Changes - -- 7e299a4: feat (ai/core): wrapLanguageModel can apply multiple middlewares - -## 4.1.15 - -### Patch Changes - -- d89c3b9: feat (provider): add image model support to provider specification -- d89c3b9: feat (core): type ahead for model ids with custom provider -- 08f54fc: chore (ai/core): move custom provider to stable -- Updated dependencies [d89c3b9] - - @ai-sdk/provider@1.0.7 - - @ai-sdk/provider-utils@2.1.6 - - @ai-sdk/ui-utils@1.1.8 - - @ai-sdk/react@1.1.8 - -## 4.1.14 - -### Patch Changes - -- ca89615: fix (ai/core): only append assistant response at the end when there is a final user message - -## 4.1.13 - -### Patch Changes - -- 999085e: feat (ai/core): add write function to DataStreamWriter - -## 4.1.12 - -### Patch Changes - -- 0d2d9bf: fix (ui): single assistant message with multiple tool steps -- Updated dependencies - - @ai-sdk/react@1.1.7 - - @ai-sdk/ui-utils@1.1.7 - -## 4.1.11 - -### Patch Changes - -- 4c58da5: chore (core): move providerOptions to stable - -## 4.1.10 - -### Patch Changes - -- bf2c9c6: feat (core): move middleware to stable - -## 4.1.9 - -### Patch Changes - -- 3a602ca: chore (core): rename CoreTool to Tool -- Updated dependencies [3a602ca] - - @ai-sdk/provider-utils@2.1.5 - - @ai-sdk/ui-utils@1.1.6 - - @ai-sdk/react@1.1.6 - -## 4.1.8 - -### Patch Changes - -- 92f5f36: feat (core): add extractReasoningMiddleware - -## 4.1.7 - -### Patch Changes - -- 066206e: feat (provider-utils): move delay to provider-utils from ai -- Updated dependencies [066206e] - - @ai-sdk/provider-utils@2.1.4 - - @ai-sdk/react@1.1.5 - - @ai-sdk/ui-utils@1.1.5 - -## 4.1.6 - -### Patch Changes - -- Updated dependencies [39e5c1f] - - @ai-sdk/provider-utils@2.1.3 - - @ai-sdk/react@1.1.4 - - @ai-sdk/ui-utils@1.1.4 - -## 4.1.5 - -### Patch Changes - -- 9ce598c: feat (ai/ui): add reasoning support to useChat -- Updated dependencies [9ce598c] - - @ai-sdk/ui-utils@1.1.3 - - @ai-sdk/react@1.1.3 - -## 4.1.4 - -### Patch Changes - -- caaad11: feat (ai/core): re-export languagemodelv1 types for middleware implementations -- caaad11: feat (ai/core): expose TelemetrySettings type - -## 4.1.3 - -### Patch Changes - -- 7f30a77: feat (core): export core message schemas -- 4298996: feat (core): add helper for merging single client message - -## 4.1.2 - -### Patch Changes - -- 3c5fafa: chore (ai/core): move streamText toolCallStreaming option to stable -- 3a58a2e: feat (ai/core): throw NoImageGeneratedError from generateImage when no predictions are returned. -- Updated dependencies - - @ai-sdk/provider-utils@2.1.2 - - @ai-sdk/react@1.1.2 - - @ai-sdk/provider@1.0.6 - - @ai-sdk/ui-utils@1.1.2 - -## 4.1.1 - -### Patch Changes - -- 0a699f1: feat: add reasoning token support -- Updated dependencies - - @ai-sdk/ui-utils@1.1.1 - - @ai-sdk/provider-utils@2.1.1 - - @ai-sdk/provider@1.0.5 - - @ai-sdk/react@1.1.1 - -## 4.1.0 - -### Minor Changes - -- 62ba5ad: release: AI SDK 4.1 - -### Patch Changes - -- Updated dependencies [62ba5ad] - - @ai-sdk/provider-utils@2.1.0 - - @ai-sdk/react@1.1.0 - - @ai-sdk/ui-utils@1.1.0 - -## 4.0.41 - -### Patch Changes - -- Updated dependencies [44f04d5] - - @ai-sdk/react@1.0.14 - -## 4.0.40 - -### Patch Changes - -- 33592d2: fix (ai/core): switch to json schema 7 target for zod to json schema conversion -- Updated dependencies [33592d2] - - @ai-sdk/ui-utils@1.0.12 - - @ai-sdk/react@1.0.13 - -## 4.0.39 - -### Patch Changes - -- 00114c5: feat: expose IDGenerator and createIdGenerator -- 00114c5: feat (ui): generate and forward message ids for response messages -- Updated dependencies - - @ai-sdk/provider-utils@2.0.8 - - @ai-sdk/ui-utils@1.0.11 - - @ai-sdk/react@1.0.12 - -## 4.0.38 - -### Patch Changes - -- 0118fa7: fix (ai/core): handle empty tool invocation array in convertToCoreMessages - -## 4.0.37 - -### Patch Changes - -- 8304ed8: feat (ai/core): Add option `throwErrorForEmptyVectors` to cosineSimilarity -- ed28182: feat (ai/ui): add appendResponseMessages helper - -## 4.0.36 - -### Patch Changes - -- Updated dependencies [37f4510] - - @ai-sdk/ui-utils@1.0.10 - - @ai-sdk/react@1.0.11 - -## 4.0.35 - -### Patch Changes - -- 3491f78: feat (ai/core): support multiple stream text transforms - -## 4.0.34 - -### Patch Changes - -- 2495973: feat (ai/core): use openai compatible mode for json schema conversion -- 2495973: fix (ai/core): duplicate instead of using reference in json schema -- Updated dependencies - - @ai-sdk/ui-utils@1.0.9 - - @ai-sdk/react@1.0.10 - -## 4.0.33 - -### Patch Changes - -- 5510ee7: feat (ai/core): add stopStream option to streamText transforms - -## 4.0.32 - -### Patch Changes - -- de66619: feat (ai/core): add tool call id to ToolExecution error - -## 4.0.31 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/provider-utils@2.0.7 - - @ai-sdk/react@1.0.9 - - @ai-sdk/ui-utils@1.0.8 - -## 4.0.30 - -### Patch Changes - -- e4ce80c: fix (ai/core): prevent onFinish from masking stream errors - -## 4.0.29 - -### Patch Changes - -- a92f5f6: feat (ai/core): generate many images with parallel model calls - -## 4.0.28 - -### Patch Changes - -- 19a2ce7: feat (ai/core): add aspectRatio and seed options to generateImage -- 6337688: feat: change image generation errors to warnings -- 8b422ea: feat (ai/core): add caching to generated images -- Updated dependencies - - @ai-sdk/provider@1.0.4 - - @ai-sdk/provider-utils@2.0.6 - - @ai-sdk/ui-utils@1.0.7 - - @ai-sdk/react@1.0.8 - -## 4.0.27 - -### Patch Changes - -- a56734f: feat (ai/core): export simulateReadableStream in ai package -- 9589601: feat (ai/core): support null delay in smoothStream -- e3cc23a: feat (ai/core): support regexp chunking pattern in smoothStream -- e463e73: feat (ai/core): support skipping delays in simulateReadableStream - -## 4.0.26 - -### Patch Changes - -- a8f3242: feat (ai/core): add line chunking mode to smoothStream - -## 4.0.25 - -### Patch Changes - -- 0823899: fix (ai/core): throw error when accessing output when no output is defined in generateText (breaking/experimental) - -## 4.0.24 - -### Patch Changes - -- ae0485b: feat (ai/core): add experimental output setting to streamText - -## 4.0.23 - -### Patch Changes - -- bc4cd19: feat (ai/core): consolidate whitespace in smooth stream - -## 4.0.22 - -### Patch Changes - -- Updated dependencies [5ed5e45] - - @ai-sdk/provider-utils@2.0.5 - - @ai-sdk/provider@1.0.3 - - @ai-sdk/react@1.0.7 - - @ai-sdk/ui-utils@1.0.6 - -## 4.0.21 - -### Patch Changes - -- a8669a2: fix (ai/core): prefer auto-detected image mimetype -- 6fb3e91: fix (ai/core): include type in generateText toolResults result property. - -## 4.0.20 - -### Patch Changes - -- da9d240: fix (ai/core): suppress errors caused by writing to closed stream -- 6f1bfde: fix (ai/core): invoke streamText tool call repair when tool cannot be found - -## 4.0.19 - -### Patch Changes - -- c3a6065: fix (ai/core): apply transform before callbacks and resolvables - -## 4.0.18 - -### Patch Changes - -- 304e6d3: feat (ai/core): standardize generateObject, streamObject, and output errors to NoObjectGeneratedError -- 304e6d3: feat (ai/core): add additional information to NoObjectGeneratedError - -## 4.0.17 - -### Patch Changes - -- 54bbf21: fix (ai/core): change streamText.experimental_transform signature to support tool type inference - -## 4.0.16 - -### Patch Changes - -- e3fac3f: fix (ai/core): change smoothStream default delay to 10ms - -## 4.0.15 - -### Patch Changes - -- cc16a83: feat (ai/core): add smoothStream helper -- cc16a83: feat (ai/core): add experimental transform option to streamText - -## 4.0.14 - -### Patch Changes - -- 09a9cab: feat (ai/core): add experimental generateImage function -- Updated dependencies [09a9cab] - - @ai-sdk/provider@1.0.2 - - @ai-sdk/provider-utils@2.0.4 - - @ai-sdk/ui-utils@1.0.5 - - @ai-sdk/react@1.0.6 - -## 4.0.13 - -### Patch Changes - -- 9f32213: feat (ai/core): add experimental tool call repair - -## 4.0.12 - -### Patch Changes - -- 5167bec: fix (ai/core): forward streamText errors as error parts -- 0984f0b: feat (ai/core): add ToolExecutionError type -- Updated dependencies [0984f0b] - - @ai-sdk/provider-utils@2.0.3 - - @ai-sdk/react@1.0.5 - - @ai-sdk/ui-utils@1.0.4 - -## 4.0.11 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/ui-utils@1.0.3 - - @ai-sdk/react@1.0.4 - -## 4.0.10 - -### Patch Changes - -- 913872d: fix (ai/core): track promise from async createDataStream.execute - -## 4.0.9 - -### Patch Changes - -- fda9695: feat (ai/core): reworked data stream management - -## 4.0.8 - -### Patch Changes - -- a803d76: feat (ai/core): pass toolCallId option into tool execute function - -## 4.0.7 - -### Patch Changes - -- 5b4f07b: fix (ai/core): change default error message for data streams to "An error occurred." - -## 4.0.6 - -### Patch Changes - -- fc18132: feat (ai/core): experimental output for generateText -- 2779f6d: fix (ai/core): do not send maxRetries into providers - -## 4.0.5 - -### Patch Changes - -- Updated dependencies [630ac31] - - @ai-sdk/react@1.0.3 - -## 4.0.4 - -### Patch Changes - -- 6ff6689: fix (ai): trigger onFinal when stream adapter finishes -- 6ff6689: chore (ai): deprecate onCompletion (stream callbacks) - -## 4.0.3 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/ui-utils@1.0.2 - - @ai-sdk/provider@1.0.1 - - @ai-sdk/react@1.0.2 - - @ai-sdk/provider-utils@2.0.2 - -## 4.0.2 - -### Patch Changes - -- Updated dependencies [c3ab5de] - - @ai-sdk/provider-utils@2.0.1 - - @ai-sdk/react@1.0.1 - - @ai-sdk/ui-utils@1.0.1 - -## 4.0.1 - -### Patch Changes - -- b117255: feat (ai/core): add messages to tool call options - -## 4.0.0 - -### Major Changes - -- 4e38b38: chore (ai): remove LanguageModelResponseMetadataWithHeaders type -- 8bf5756: chore: remove legacy function/tool calling -- f0cb69d: chore (ai/core): remove experimental function exports -- da8c609: chore (ai): remove Tokens RSC helper -- cbab571: chore (ai): remove ExperimentalXXXMessage types -- b469a7e: chore: remove isXXXError methods -- 54cb888: chore (ai): remove experimental_StreamData export -- 4d61295: chore (ai): remove streamToResponse and streamingTextResponse -- 9a3d741: chore (ai): remove ExperimentalTool export -- 064257d: chore (ai/core): rename simulateReadableStream values parameter to chunks -- 60e69ed: chore (ai/core): remove ai-stream related methods from streamText -- a4f8ce9: chore (ai): AssistantResponse cleanups -- d3ae4f6: chore (ui/react): remove useObject setInput helper -- 7264b0a: chore (ai): remove responseMessages property from streamText/generateText result -- b801982: chore (ai/core): remove init option from streamText result methods -- f68d7b1: chore (ai/core): streamObject returns result immediately (no Promise) -- 6090cea: chore (ai): remove rawResponse from generate/stream result objects -- 073f282: chore (ai): remove AIStream and related exports -- 1c58337: chore (ai): remove 2.x prompt helpers -- a40a93d: chore (ai/ui): remove vue, svelte, solid re-export and dependency -- a7ad35a: chore: remove legacy providers & rsc render -- c0ddc24: chore (ai): remove toJSON method from AI SDK errors -- 007cb81: chore (ai): change `streamText` warnings result to Promise -- effbce3: chore (ai): remove responseMessage from streamText onFinish callback -- 545d133: chore (ai): remove deprecated roundtrip settings from streamText / generateText -- 7e89ccb: chore: remove nanoid export -- f967199: chore (ai/core): streamText returns result immediately (no Promise) -- 62d08fd: chore (ai): remove TokenUsage, CompletionTokenUsage, and EmbeddingTokenUsage types -- e5d2ce8: chore (ai): remove deprecated provider registry exports -- 70ce742: chore (ai): remove experimental_continuationSteps option -- 2f09717: chore (ai): remove deprecated telemetry data -- 0827bf9: chore (ai): remove LangChain adapter `toAIStream` method - -### Patch Changes - -- dce4158: chore (dependencies): update eventsource-parser to 3.0.0 -- f0ec721: chore (ai): remove openai peer dependency -- f9bb30c: chore (ai): remove unnecessary dev dependencies -- b053413: chore (ui): refactorings & README update -- Updated dependencies - - @ai-sdk/react@1.0.0 - - @ai-sdk/ui-utils@1.0.0 - - @ai-sdk/provider-utils@2.0.0 - - @ai-sdk/provider@1.0.0 - -## 4.0.0-canary.13 - -### Major Changes - -- 064257d: chore (ai/core): rename simulateReadableStream values parameter to chunks - -### Patch Changes - -- Updated dependencies - - @ai-sdk/react@1.0.0-canary.9 - - @ai-sdk/ui-utils@1.0.0-canary.9 - -## 4.0.0-canary.12 - -### Patch Changes - -- b053413: chore (ui): refactorings & README update -- Updated dependencies [b053413] - - @ai-sdk/ui-utils@1.0.0-canary.8 - - @ai-sdk/react@1.0.0-canary.8 - -## 4.0.0-canary.11 - -### Major Changes - -- f68d7b1: chore (ai/core): streamObject returns result immediately (no Promise) -- f967199: chore (ai/core): streamText returns result immediately (no Promise) - -## 4.0.0-canary.10 - -### Major Changes - -- effbce3: chore (ai): remove responseMessage from streamText onFinish callback - -### Patch Changes - -- Updated dependencies [fe4f109] - - @ai-sdk/ui-utils@1.0.0-canary.7 - - @ai-sdk/react@1.0.0-canary.7 - -## 4.0.0-canary.9 - -### Patch Changes - -- f0ec721: chore (ai): remove openai peer dependency - -## 4.0.0-canary.8 - -### Major Changes - -- 007cb81: chore (ai): change `streamText` warnings result to Promise - -### Patch Changes - -- Updated dependencies [70f28f6] - - @ai-sdk/ui-utils@1.0.0-canary.6 - - @ai-sdk/react@1.0.0-canary.6 - -## 4.0.0-canary.7 - -### Major Changes - -- 4e38b38: chore (ai): remove LanguageModelResponseMetadataWithHeaders type -- 54cb888: chore (ai): remove experimental_StreamData export -- 9a3d741: chore (ai): remove ExperimentalTool export -- a4f8ce9: chore (ai): AssistantResponse cleanups -- 7264b0a: chore (ai): remove responseMessages property from streamText/generateText result -- 62d08fd: chore (ai): remove TokenUsage, CompletionTokenUsage, and EmbeddingTokenUsage types -- e5d2ce8: chore (ai): remove deprecated provider registry exports -- 70ce742: chore (ai): remove experimental_continuationSteps option -- 0827bf9: chore (ai): remove LangChain adapter `toAIStream` method - -## 4.0.0-canary.6 - -### Major Changes - -- b801982: chore (ai/core): remove init option from streamText result methods - -### Patch Changes - -- f9bb30c: chore (ai): remove unnecessary dev dependencies - -## 4.0.0-canary.5 - -### Major Changes - -- 4d61295: chore (ai): remove streamToResponse and streamingTextResponse -- d3ae4f6: chore (ui/react): remove useObject setInput helper -- 6090cea: chore (ai): remove rawResponse from generate/stream result objects -- 2f09717: chore (ai): remove deprecated telemetry data - -### Patch Changes - -- Updated dependencies - - @ai-sdk/ui-utils@1.0.0-canary.5 - - @ai-sdk/react@1.0.0-canary.5 - - @ai-sdk/provider-utils@2.0.0-canary.3 - -## 4.0.0-canary.4 - -### Major Changes - -- f0cb69d: chore (ai/core): remove experimental function exports -- da8c609: chore (ai): remove Tokens RSC helper -- cbab571: chore (ai): remove ExperimentalXXXMessage types -- 60e69ed: chore (ai/core): remove ai-stream related methods from streamText -- 073f282: chore (ai): remove AIStream and related exports -- 545d133: chore (ai): remove deprecated roundtrip settings from streamText / generateText - -### Patch Changes - -- dce4158: chore (dependencies): update eventsource-parser to 3.0.0 -- Updated dependencies - - @ai-sdk/provider-utils@2.0.0-canary.2 - - @ai-sdk/react@1.0.0-canary.4 - - @ai-sdk/ui-utils@1.0.0-canary.4 - -## 4.0.0-canary.3 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/react@1.0.0-canary.3 - - @ai-sdk/provider-utils@2.0.0-canary.1 - - @ai-sdk/ui-utils@1.0.0-canary.3 - -## 4.0.0-canary.2 - -### Major Changes - -- b469a7e: chore: remove isXXXError methods -- c0ddc24: chore (ai): remove toJSON method from AI SDK errors - -### Patch Changes - -- Updated dependencies - - @ai-sdk/react@1.0.0-canary.2 - - @ai-sdk/provider-utils@2.0.0-canary.0 - - @ai-sdk/provider@1.0.0-canary.0 - - @ai-sdk/ui-utils@1.0.0-canary.2 - -## 4.0.0-canary.1 - -### Major Changes - -- 8bf5756: chore: remove legacy function/tool calling - -### Patch Changes - -- 1c58337: chore (ai): remove 2.x prompt helpers -- Updated dependencies [8bf5756] - - @ai-sdk/ui-utils@1.0.0-canary.1 - - @ai-sdk/react@1.0.0-canary.1 - -## 4.0.0-canary.0 - -### Major Changes - -- a40a93d: chore (ai/ui): remove vue, svelte, solid re-export and dependency - -### Patch Changes - -- a7ad35a: chore: remove legacy providers & rsc render -- 7e89ccb: chore: remove nanoid export -- Updated dependencies - - @ai-sdk/react@1.0.0-canary.0 - - @ai-sdk/ui-utils@1.0.0-canary.0 - -## 3.4.33 - -### Patch Changes - -- ac380e3: fix (provider/anthropic): continuation mode with 3+ steps - -## 3.4.32 - -### Patch Changes - -- 6bb9e51: fix (ai/core): expose response.messages in streamText - -## 3.4.31 - -### Patch Changes - -- Updated dependencies [2dfb93e] - - @ai-sdk/react@0.0.70 - -## 3.4.30 - -### Patch Changes - -- Updated dependencies [a85c965] - - @ai-sdk/ui-utils@0.0.50 - - @ai-sdk/react@0.0.69 - - @ai-sdk/solid@0.0.54 - - @ai-sdk/svelte@0.0.57 - - @ai-sdk/vue@0.0.59 - -## 3.4.29 - -### Patch Changes - -- 54b56f7: feat (ai/core): send tool and tool choice telemetry data - -## 3.4.28 - -### Patch Changes - -- 29f1390: feat (ai/test): add simulateReadableStream helper - -## 3.4.27 - -### Patch Changes - -- fa772ae: feat (ai/core): automatically convert ui messages to core messages - -## 3.4.26 - -### Patch Changes - -- 57f39ea: feat (ai/core): support multi-modal tool results in convertToCoreMessages - -## 3.4.25 - -### Patch Changes - -- 6e0fa1c: fix (ai/core): wait for tool results to arrive before sending finish event - -## 3.4.24 - -### Patch Changes - -- d92fd9f: feat (ui/svelte): support Svelte 5 peer dependency -- Updated dependencies [d92fd9f] - - @ai-sdk/svelte@0.0.56 - -## 3.4.23 - -### Patch Changes - -- 8301e41: fix (ai/react): update React peer dependency version to allow rc releases. -- Updated dependencies [8301e41] - - @ai-sdk/react@0.0.68 - -## 3.4.22 - -### Patch Changes - -- Updated dependencies [3bf8da0] - - @ai-sdk/ui-utils@0.0.49 - - @ai-sdk/react@0.0.67 - - @ai-sdk/solid@0.0.53 - - @ai-sdk/svelte@0.0.55 - - @ai-sdk/vue@0.0.58 - -## 3.4.21 - -### Patch Changes - -- 3954471: (experimental) fix passing "experimental_toToolResultContent" into PoolResultPart - -## 3.4.20 - -### Patch Changes - -- aa98cdb: chore: more flexible dependency versioning -- 1486128: feat: add supportsUrl to language model specification -- 3b1b69a: feat: provider-defined tools -- 85b98da: revert fix (ai/core): handle tool calls without results in message conversion -- 7ceed77: feat (ai/core): expose response message for each step -- 811a317: feat (ai/core): multi-part tool results (incl. images) -- Updated dependencies - - @ai-sdk/provider-utils@1.0.22 - - @ai-sdk/provider@0.0.26 - - @ai-sdk/ui-utils@0.0.48 - - @ai-sdk/svelte@0.0.54 - - @ai-sdk/react@0.0.66 - - @ai-sdk/vue@0.0.57 - - @ai-sdk/solid@0.0.52 - -## 3.4.19 - -### Patch Changes - -- b9b0d7b: feat (ai): access raw request body -- Updated dependencies [b9b0d7b] - - @ai-sdk/provider@0.0.25 - - @ai-sdk/provider-utils@1.0.21 - - @ai-sdk/ui-utils@0.0.47 - - @ai-sdk/react@0.0.65 - - @ai-sdk/solid@0.0.51 - - @ai-sdk/svelte@0.0.53 - - @ai-sdk/vue@0.0.56 - -## 3.4.18 - -### Patch Changes - -- 95c67b4: fix (ai/core): handle tool calls without results in message conversion - -## 3.4.17 - -### Patch Changes - -- e4ff512: fix (core): prevent unnecessary input/output serialization when telemetry is not enabled - -## 3.4.16 - -### Patch Changes - -- 01dcc44: feat (ai/core): add experimental activeTools option to generateText and streamText - -## 3.4.15 - -### Patch Changes - -- Updated dependencies [98a3b08] - - @ai-sdk/react@0.0.64 - -## 3.4.14 - -### Patch Changes - -- e930f40: feat (ai/core): expose core tool result and tool call types - -## 3.4.13 - -### Patch Changes - -- fc39158: fix (ai/core): add abortSignal to tool helper function - -## 3.4.12 - -### Patch Changes - -- a23da5b: feat (ai/core): forward abort signal to tools - -## 3.4.11 - -### Patch Changes - -- caedcda: feat (ai/ui): add setData helper to useChat -- Updated dependencies [caedcda] - - @ai-sdk/svelte@0.0.52 - - @ai-sdk/react@0.0.63 - - @ai-sdk/solid@0.0.50 - - @ai-sdk/vue@0.0.55 - -## 3.4.10 - -### Patch Changes - -- 0b557d7: feat (ai/core): add tracer option to telemetry settings -- 44f6bc5: feat (ai/core): expose StepResult type - -## 3.4.9 - -### Patch Changes - -- d347538: fix (ai/core): export FilePart interface - -## 3.4.8 - -### Patch Changes - -- Updated dependencies [b5f577e] - - @ai-sdk/vue@0.0.54 - -## 3.4.7 - -### Patch Changes - -- db04700: feat (core): support converting attachments to file parts -- 988707c: feat (ai/core): automatically download files from urls - -## 3.4.6 - -### Patch Changes - -- d595d0d: feat (ai/core): file content parts -- Updated dependencies [d595d0d] - - @ai-sdk/provider@0.0.24 - - @ai-sdk/provider-utils@1.0.20 - - @ai-sdk/ui-utils@0.0.46 - - @ai-sdk/react@0.0.62 - - @ai-sdk/solid@0.0.49 - - @ai-sdk/svelte@0.0.51 - - @ai-sdk/vue@0.0.53 - -## 3.4.5 - -### Patch Changes - -- cd77c5d: feat (ai/core): add isContinued to steps -- Updated dependencies [cd77c5d] - - @ai-sdk/ui-utils@0.0.45 - - @ai-sdk/react@0.0.61 - - @ai-sdk/solid@0.0.48 - - @ai-sdk/svelte@0.0.50 - - @ai-sdk/vue@0.0.52 - -## 3.4.4 - -### Patch Changes - -- 4db074b: fix (ai/core): correct whitespace in generateText continueSteps -- 1297e1b: fix (ai/core): correct whitespace in streamText continueSteps - -## 3.4.3 - -### Patch Changes - -- b270ae3: feat (ai/core): streamText continueSteps (experimental) -- b270ae3: chore (ai/core): rename generateText continuationSteps to continueSteps - -## 3.4.2 - -### Patch Changes - -- e6c7e98: feat (ai/core): add continuationSteps to generateText - -## 3.4.1 - -### Patch Changes - -- Updated dependencies [7e7104f] - - @ai-sdk/react@0.0.60 - -## 3.4.0 - -### Minor Changes - -- c0cea03: release (ai): 3.4 - -## 3.3.44 - -### Patch Changes - -- Updated dependencies [d3933e0] - - @ai-sdk/vue@0.0.51 - -## 3.3.43 - -### Patch Changes - -- fea6bec: fix (ai/core): support tool calls without arguments - -## 3.3.42 - -### Patch Changes - -- de37aee: feat (ai): Add support for LlamaIndex - -## 3.3.41 - -### Patch Changes - -- Updated dependencies [692e265] - - @ai-sdk/vue@0.0.50 - -## 3.3.40 - -### Patch Changes - -- a91c308: feat (ai/core): add responseMessages to streamText - -## 3.3.39 - -### Patch Changes - -- 33cf3e1: feat (ai/core): add providerMetadata to StepResult -- 17ee757: feat (ai/core): add onStepFinish callback to generateText - -## 3.3.38 - -### Patch Changes - -- 83da52c: feat (ai/core): add onStepFinish callback to streamText - -## 3.3.37 - -### Patch Changes - -- Updated dependencies [273f696] - - @ai-sdk/provider-utils@1.0.19 - - @ai-sdk/react@0.0.59 - - @ai-sdk/solid@0.0.47 - - @ai-sdk/svelte@0.0.49 - - @ai-sdk/ui-utils@0.0.44 - - @ai-sdk/vue@0.0.49 - -## 3.3.36 - -### Patch Changes - -- a3882f5: feat (ai/core): add steps property to streamText result and onFinish callback -- 1f590ef: chore (ai): rename roundtrips to steps -- 7e82d36: fix (ai/core): pass topK to providers -- Updated dependencies - - @ai-sdk/react@0.0.58 - - @ai-sdk/ui-utils@0.0.43 - - @ai-sdk/solid@0.0.46 - - @ai-sdk/svelte@0.0.48 - - @ai-sdk/vue@0.0.48 - -## 3.3.35 - -### Patch Changes - -- 14210d5: feat (ai/core): add sendUsage information to streamText data stream methods -- Updated dependencies [14210d5] - - @ai-sdk/ui-utils@0.0.42 - - @ai-sdk/react@0.0.57 - - @ai-sdk/solid@0.0.45 - - @ai-sdk/svelte@0.0.47 - - @ai-sdk/vue@0.0.47 - -## 3.3.34 - -### Patch Changes - -- a0403d6: feat (react): support sending attachments using append -- 678449a: feat (ai/core): export test helpers -- ff22fac: fix (ai/rsc): streamUI onFinish is called when tool calls have finished -- Updated dependencies [a0403d6] - - @ai-sdk/react@0.0.56 - -## 3.3.33 - -### Patch Changes - -- cbddc83: fix (ai/core): filter out empty text parts - -## 3.3.32 - -### Patch Changes - -- ce7a4af: feat (ai/core): support providerMetadata in functions - -## 3.3.31 - -### Patch Changes - -- 561fd7e: feat (ai/core): add output: enum to generateObject - -## 3.3.30 - -### Patch Changes - -- 6ee1f8e: feat (ai/core): add toDataStream to streamText result - -## 3.3.29 - -### Patch Changes - -- 1e3dfd2: feat (ai/core): enhance pipeToData/TextStreamResponse methods - -## 3.3.28 - -### Patch Changes - -- db61c53: feat (ai/core): middleware support - -## 3.3.27 - -### Patch Changes - -- 03313cd: feat (ai): expose response id, response model, response timestamp in telemetry and api -- 3be7c1c: fix (provider/anthropic): support prompt caching on assistant messages -- Updated dependencies - - @ai-sdk/provider-utils@1.0.18 - - @ai-sdk/provider@0.0.23 - - @ai-sdk/react@0.0.55 - - @ai-sdk/solid@0.0.44 - - @ai-sdk/svelte@0.0.46 - - @ai-sdk/ui-utils@0.0.41 - - @ai-sdk/vue@0.0.46 - -## 3.3.26 - -### Patch Changes - -- Updated dependencies [4ab883f] - - @ai-sdk/react@0.0.54 - -## 3.3.25 - -### Patch Changes - -- 4f1530f: feat (ai/core): add OpenTelemetry Semantic Conventions for GenAI operations to v1.27.0 of standard -- dad775f: feat (ai/core): add finish event and avg output tokens per second (telemetry) - -## 3.3.24 - -### Patch Changes - -- d87a655: fix (ai/core): provide fallback when globalThis.performance is not available - -## 3.3.23 - -### Patch Changes - -- b55e6f7: fix (ai/core): streamObject text stream in array mode must not include elements: prefix. - -## 3.3.22 - -### Patch Changes - -- a5a56fd: fix (ai/core): only send roundtrip-finish event after async tool calls are done - -## 3.3.21 - -### Patch Changes - -- aa2dc58: feat (ai/core): add maxToolRoundtrips to streamText -- Updated dependencies [aa2dc58] - - @ai-sdk/ui-utils@0.0.40 - - @ai-sdk/react@0.0.53 - - @ai-sdk/solid@0.0.43 - - @ai-sdk/svelte@0.0.45 - - @ai-sdk/vue@0.0.45 - -## 3.3.20 - -### Patch Changes - -- 7807677: fix (rsc): Deep clone currentState in getMutableState() - -## 3.3.19 - -### Patch Changes - -- 7235de0: fix (ai/core): convertToCoreMessages accepts Message[] - -## 3.3.18 - -### Patch Changes - -- 9e3b5a5: feat (ai/core): add experimental_customProvider -- 26515cb: feat (ai/provider): introduce ProviderV1 specification -- Updated dependencies [26515cb] - - @ai-sdk/provider@0.0.22 - - @ai-sdk/provider-utils@1.0.17 - - @ai-sdk/ui-utils@0.0.39 - - @ai-sdk/react@0.0.52 - - @ai-sdk/solid@0.0.42 - - @ai-sdk/svelte@0.0.44 - - @ai-sdk/vue@0.0.44 - -## 3.3.17 - -### Patch Changes - -- d151349: feat (ai/core): array output for generateObject / streamObject -- Updated dependencies [d151349] - - @ai-sdk/ui-utils@0.0.38 - - @ai-sdk/react@0.0.51 - - @ai-sdk/solid@0.0.41 - - @ai-sdk/svelte@0.0.43 - - @ai-sdk/vue@0.0.43 - -## 3.3.16 - -### Patch Changes - -- 09f895f: feat (ai/core): no-schema output for generateObject / streamObject -- Updated dependencies [09f895f] - - @ai-sdk/provider-utils@1.0.16 - - @ai-sdk/react@0.0.50 - - @ai-sdk/solid@0.0.40 - - @ai-sdk/svelte@0.0.42 - - @ai-sdk/ui-utils@0.0.37 - - @ai-sdk/vue@0.0.42 - -## 3.3.15 - -### Patch Changes - -- b5a82b7: chore (ai): update zod-to-json-schema to 3.23.2 -- Updated dependencies [b5a82b7] - - @ai-sdk/ui-utils@0.0.36 - - @ai-sdk/react@0.0.49 - - @ai-sdk/solid@0.0.39 - - @ai-sdk/svelte@0.0.41 - - @ai-sdk/vue@0.0.41 - -## 3.3.14 - -### Patch Changes - -- Updated dependencies [d67fa9c] - - @ai-sdk/provider-utils@1.0.15 - - @ai-sdk/react@0.0.48 - - @ai-sdk/solid@0.0.38 - - @ai-sdk/svelte@0.0.40 - - @ai-sdk/ui-utils@0.0.35 - - @ai-sdk/vue@0.0.40 - -## 3.3.13 - -### Patch Changes - -- 412f943: fix (ai/core): make Buffer validation optional for environments without buffer - -## 3.3.12 - -### Patch Changes - -- f2c025e: feat (ai/core): prompt validation -- Updated dependencies [f2c025e] - - @ai-sdk/provider@0.0.21 - - @ai-sdk/provider-utils@1.0.14 - - @ai-sdk/ui-utils@0.0.34 - - @ai-sdk/react@0.0.47 - - @ai-sdk/solid@0.0.37 - - @ai-sdk/svelte@0.0.39 - - @ai-sdk/vue@0.0.39 - -## 3.3.11 - -### Patch Changes - -- 03eb0f4: feat (ai/core): add "ai.operationId" telemetry attribute -- 099db96: feat (ai/core): add msToFirstChunk telemetry data -- Updated dependencies [b6c1dee] - - @ai-sdk/react@0.0.46 - -## 3.3.10 - -### Patch Changes - -- Updated dependencies [04084a3] - - @ai-sdk/vue@0.0.38 - -## 3.3.9 - -### Patch Changes - -- 6ac355e: feat (provider/anthropic): add cache control support -- b56dee1: chore (ai): deprecate prompt helpers -- Updated dependencies [6ac355e] - - @ai-sdk/provider@0.0.20 - - @ai-sdk/provider-utils@1.0.13 - - @ai-sdk/ui-utils@0.0.33 - - @ai-sdk/react@0.0.45 - - @ai-sdk/solid@0.0.36 - - @ai-sdk/svelte@0.0.38 - - @ai-sdk/vue@0.0.37 - -## 3.3.8 - -### Patch Changes - -- Updated dependencies [dd712ac] - - @ai-sdk/provider-utils@1.0.12 - - @ai-sdk/ui-utils@0.0.32 - - @ai-sdk/react@0.0.44 - - @ai-sdk/solid@0.0.35 - - @ai-sdk/svelte@0.0.37 - - @ai-sdk/vue@0.0.36 - -## 3.3.7 - -### Patch Changes - -- eccbd8e: feat (ai/core): add onChunk callback to streamText -- Updated dependencies [dd4a0f5] - - @ai-sdk/provider@0.0.19 - - @ai-sdk/provider-utils@1.0.11 - - @ai-sdk/ui-utils@0.0.31 - - @ai-sdk/react@0.0.43 - - @ai-sdk/solid@0.0.34 - - @ai-sdk/svelte@0.0.36 - - @ai-sdk/vue@0.0.35 - -## 3.3.6 - -### Patch Changes - -- e9c891d: feat (ai/react): useObject supports non-Zod schemas -- 3719e8a: chore (ai/core): provider registry code improvements -- Updated dependencies - - @ai-sdk/ui-utils@0.0.30 - - @ai-sdk/react@0.0.42 - - @ai-sdk/provider-utils@1.0.10 - - @ai-sdk/provider@0.0.18 - - @ai-sdk/solid@0.0.33 - - @ai-sdk/svelte@0.0.35 - - @ai-sdk/vue@0.0.34 - -## 3.3.5 - -### Patch Changes - -- 9ada023: feat (ai/core): mask data stream error messages with streamText -- Updated dependencies [e5b58f3] - - @ai-sdk/ui-utils@0.0.29 - - @ai-sdk/react@0.0.41 - - @ai-sdk/solid@0.0.32 - - @ai-sdk/svelte@0.0.34 - - @ai-sdk/vue@0.0.33 - -## 3.3.4 - -### Patch Changes - -- 029af4c: feat (ai/core): support schema name & description in generateObject & streamObject -- 3806c0c: chore (ai/ui): increase stream data warning timeout to 15 seconds -- db0118a: feat (ai/core): export Schema type -- Updated dependencies [029af4c] - - @ai-sdk/provider@0.0.17 - - @ai-sdk/provider-utils@1.0.9 - - @ai-sdk/ui-utils@0.0.28 - - @ai-sdk/react@0.0.40 - - @ai-sdk/solid@0.0.31 - - @ai-sdk/svelte@0.0.33 - - @ai-sdk/vue@0.0.32 - -## 3.3.3 - -### Patch Changes - -- d58517b: feat (ai/openai): structured outputs -- Updated dependencies [d58517b] - - @ai-sdk/provider@0.0.16 - - @ai-sdk/provider-utils@1.0.8 - - @ai-sdk/ui-utils@0.0.27 - - @ai-sdk/react@0.0.39 - - @ai-sdk/solid@0.0.30 - - @ai-sdk/svelte@0.0.32 - - @ai-sdk/vue@0.0.31 - -## 3.3.2 - -### Patch Changes - -- Updated dependencies [96aed25] - - @ai-sdk/provider@0.0.15 - - @ai-sdk/provider-utils@1.0.7 - - @ai-sdk/ui-utils@0.0.26 - - @ai-sdk/react@0.0.38 - - @ai-sdk/solid@0.0.29 - - @ai-sdk/svelte@0.0.31 - - @ai-sdk/vue@0.0.30 - -## 3.3.1 - -### Patch Changes - -- 9614584: fix (ai/core): use Symbol.for -- 0762a22: feat (ai/core): support zod transformers in generateObject & streamObject -- Updated dependencies - - @ai-sdk/provider-utils@1.0.6 - - @ai-sdk/react@0.0.37 - - @ai-sdk/solid@0.0.28 - - @ai-sdk/svelte@0.0.30 - - @ai-sdk/ui-utils@0.0.25 - - @ai-sdk/vue@0.0.29 - -## 3.3.0 - -### Minor Changes - -- dbc3afb7: chore (ai): release AI SDK 3.3 - -### Patch Changes - -- b9827186: feat (ai/core): update operation.name telemetry attribute to include function id and detailed name - -## 3.2.45 - -### Patch Changes - -- Updated dependencies [5be25124] - - @ai-sdk/ui-utils@0.0.24 - - @ai-sdk/react@0.0.36 - - @ai-sdk/solid@0.0.27 - - @ai-sdk/svelte@0.0.29 - - @ai-sdk/vue@0.0.28 - -## 3.2.44 - -### Patch Changes - -- Updated dependencies [a147d040] - - @ai-sdk/react@0.0.35 - -## 3.2.43 - -### Patch Changes - -- Updated dependencies [b68fae4f] - - @ai-sdk/react@0.0.34 - -## 3.2.42 - -### Patch Changes - -- f63c99e7: feat (ai/core): record OpenTelemetry gen_ai attributes -- Updated dependencies [fea7b604] - - @ai-sdk/ui-utils@0.0.23 - - @ai-sdk/react@0.0.33 - - @ai-sdk/solid@0.0.26 - - @ai-sdk/svelte@0.0.28 - - @ai-sdk/vue@0.0.27 - -## 3.2.41 - -### Patch Changes - -- a12044c7: feat (ai/core): add recordInputs / recordOutputs setting to telemetry options -- Updated dependencies [1d93d716] - - @ai-sdk/ui-utils@0.0.22 - - @ai-sdk/react@0.0.32 - - @ai-sdk/solid@0.0.25 - - @ai-sdk/svelte@0.0.27 - - @ai-sdk/vue@0.0.26 - -## 3.2.40 - -### Patch Changes - -- f56b7e66: feat (ai/ui): add toDataStreamResponse to LangchainAdapter. - -## 3.2.39 - -### Patch Changes - -- b694f2f9: feat (ai/svelte): add tool calling support to useChat -- Updated dependencies [b694f2f9] - - @ai-sdk/svelte@0.0.26 - -## 3.2.38 - -### Patch Changes - -- 5c4b8cfc: chore (ai/core): rename ai stream methods to data stream (in streamText, LangChainAdapter). -- c450fcf7: feat (ui): invoke useChat onFinish with finishReason and tokens -- e4a1719f: chore (ai/ui): rename streamMode to streamProtocol -- 10158bf2: fix (ai/core): generateObject.doGenerate sets object telemetry attribute -- Updated dependencies - - @ai-sdk/ui-utils@0.0.21 - - @ai-sdk/svelte@0.0.25 - - @ai-sdk/react@0.0.31 - - @ai-sdk/solid@0.0.24 - - @ai-sdk/vue@0.0.25 - -## 3.2.37 - -### Patch Changes - -- b2bee4c5: fix (ai/ui): send data, body, headers in useChat().reload -- Updated dependencies [b2bee4c5] - - @ai-sdk/svelte@0.0.24 - - @ai-sdk/react@0.0.30 - - @ai-sdk/solid@0.0.23 - -## 3.2.36 - -### Patch Changes - -- a8d1c9e9: feat (ai/core): parallel image download -- cfa360a8: feat (ai/core): add telemetry support to embedMany function. -- 49808ca5: feat (ai/core): add telemetry to streamObject -- Updated dependencies [a8d1c9e9] - - @ai-sdk/provider-utils@1.0.5 - - @ai-sdk/provider@0.0.14 - - @ai-sdk/react@0.0.29 - - @ai-sdk/svelte@0.0.23 - - @ai-sdk/ui-utils@0.0.20 - - @ai-sdk/vue@0.0.24 - - @ai-sdk/solid@0.0.22 - -## 3.2.35 - -### Patch Changes - -- 1be014b7: feat (ai/core): add telemetry support for embed function. -- 4f88248f: feat (core): support json schema -- 0d545231: chore (ai/svelte): change sswr into optional peer dependency -- Updated dependencies [4f88248f] - - @ai-sdk/provider-utils@1.0.4 - - @ai-sdk/react@0.0.28 - - @ai-sdk/svelte@0.0.22 - - @ai-sdk/ui-utils@0.0.19 - - @ai-sdk/vue@0.0.23 - - @ai-sdk/solid@0.0.21 - -## 3.2.34 - -### Patch Changes - -- 2b9da0f0: feat (core): support stopSequences setting. -- a5b58845: feat (core): support topK setting -- 420f170f: chore (ai/core): use interfaces for core function results -- 13b27ec6: chore (ai/core): remove grammar mode -- 644f6582: feat (ai/core): add telemetry to generateObject -- Updated dependencies - - @ai-sdk/provider@0.0.13 - - @ai-sdk/provider-utils@1.0.3 - - @ai-sdk/react@0.0.27 - - @ai-sdk/svelte@0.0.21 - - @ai-sdk/ui-utils@0.0.18 - - @ai-sdk/solid@0.0.20 - - @ai-sdk/vue@0.0.22 - -## 3.2.33 - -### Patch Changes - -- 4b2c09d9: feat (ai/ui): add mutator function support to useChat / setMessages -- 281e7662: chore: add description to ai package -- Updated dependencies - - @ai-sdk/ui-utils@0.0.17 - - @ai-sdk/svelte@0.0.20 - - @ai-sdk/react@0.0.26 - - @ai-sdk/solid@0.0.19 - - @ai-sdk/vue@0.0.21 - -## 3.2.32 - -### Patch Changes - -- Updated dependencies [5b7b3bbe] - - @ai-sdk/ui-utils@0.0.16 - - @ai-sdk/react@0.0.25 - - @ai-sdk/solid@0.0.18 - - @ai-sdk/svelte@0.0.19 - - @ai-sdk/vue@0.0.20 - -## 3.2.31 - -### Patch Changes - -- b86af092: feat (ai/core): add langchain stream event v2 support to LangChainAdapter - -## 3.2.30 - -### Patch Changes - -- Updated dependencies [19c3d50f] - - @ai-sdk/react@0.0.24 - - @ai-sdk/vue@0.0.19 - -## 3.2.29 - -### Patch Changes - -- e710b388: fix (ai/core): race condition in mergeStreams -- 6078a690: feat (ai/core): introduce stream data support in toAIStreamResponse - -## 3.2.28 - -### Patch Changes - -- 68d1f78c: fix (ai/core): do not construct object promise in streamObject result until requested -- f0bc1e79: feat (ai/ui): add system message support to convertToCoreMessages -- 1f67fe49: feat (ai/ui): stream tool calls with streamText and useChat -- Updated dependencies [1f67fe49] - - @ai-sdk/ui-utils@0.0.15 - - @ai-sdk/react@0.0.23 - - @ai-sdk/solid@0.0.17 - - @ai-sdk/svelte@0.0.18 - - @ai-sdk/vue@0.0.18 - -## 3.2.27 - -### Patch Changes - -- 811f4493: fix (ai/core): generateText token usage is sum over all roundtrips - -## 3.2.26 - -### Patch Changes - -- 8f545ce9: fix (ai/core): forward request headers in generateObject and streamObject - -## 3.2.25 - -### Patch Changes - -- 99ddbb74: feat (ai/react): add experimental support for managing attachments to useChat -- Updated dependencies [99ddbb74] - - @ai-sdk/ui-utils@0.0.14 - - @ai-sdk/react@0.0.22 - - @ai-sdk/solid@0.0.16 - - @ai-sdk/svelte@0.0.17 - - @ai-sdk/vue@0.0.17 - -## 3.2.24 - -### Patch Changes - -- f041c056: feat (ai/core): add roundtrips property to generateText result - -## 3.2.23 - -### Patch Changes - -- a6cb2c8b: feat (ai/ui): add keepLastMessageOnError option to useChat -- Updated dependencies [a6cb2c8b] - - @ai-sdk/ui-utils@0.0.13 - - @ai-sdk/svelte@0.0.16 - - @ai-sdk/react@0.0.21 - - @ai-sdk/solid@0.0.15 - - @ai-sdk/vue@0.0.16 - -## 3.2.22 - -### Patch Changes - -- 53fccf1c: fix (ai/core): report error on controller -- dd0d854e: feat (ai/vue): add useAssistant -- Updated dependencies [dd0d854e] - - @ai-sdk/vue@0.0.15 - -## 3.2.21 - -### Patch Changes - -- 56bbc2a7: feat (ai/ui): set body and headers directly on options for handleSubmit and append -- Updated dependencies [56bbc2a7] - - @ai-sdk/ui-utils@0.0.12 - - @ai-sdk/svelte@0.0.15 - - @ai-sdk/react@0.0.20 - - @ai-sdk/solid@0.0.14 - - @ai-sdk/vue@0.0.14 - -## 3.2.20 - -### Patch Changes - -- 671331b6: feat (core): add experimental OpenTelemetry support for generateText and streamText - -## 3.2.19 - -### Patch Changes - -- b7290943: chore (ai/core): rename TokenUsage type to CompletionTokenUsage -- b7290943: feat (ai/core): add token usage to embed and embedMany -- Updated dependencies [b7290943] - - @ai-sdk/provider@0.0.12 - - @ai-sdk/provider-utils@1.0.2 - - @ai-sdk/react@0.0.19 - - @ai-sdk/svelte@0.0.14 - - @ai-sdk/ui-utils@0.0.11 - - @ai-sdk/solid@0.0.13 - - @ai-sdk/vue@0.0.13 - -## 3.2.18 - -### Patch Changes - -- Updated dependencies [70d18003] - - @ai-sdk/react@0.0.18 - -## 3.2.17 - -### Patch Changes - -- 3db90c3d: allow empty handleSubmit submissions for useChat -- abb22602: feat (ai): verify that system messages have string content -- 5c1f0bd3: fix unclosed streamable value console message -- Updated dependencies - - @ai-sdk/react@0.0.17 - - @ai-sdk/svelte@0.0.13 - - @ai-sdk/solid@0.0.12 - - @ai-sdk/vue@0.0.12 - - @ai-sdk/provider-utils@1.0.1 - - @ai-sdk/ui-utils@0.0.10 - -## 3.2.16 - -### Patch Changes - -- Updated dependencies [3f756a6b] - - @ai-sdk/react@0.0.16 - -## 3.2.15 - -### Patch Changes - -- 6c99581e: fix (ai/react): stop() on useObject does not throw error and clears isLoading -- Updated dependencies [6c99581e] - - @ai-sdk/react@0.0.15 - -## 3.2.14 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/react@0.0.14 - - @ai-sdk/ui-utils@0.0.9 - - @ai-sdk/solid@0.0.11 - - @ai-sdk/svelte@0.0.12 - - @ai-sdk/vue@0.0.11 - -## 3.2.13 - -### Patch Changes - -- d3100b9c: feat (ai/ui): support custom fetch function in useChat, useCompletion, useAssistant, useObject -- Updated dependencies [d3100b9c] - - @ai-sdk/ui-utils@0.0.8 - - @ai-sdk/svelte@0.0.11 - - @ai-sdk/react@0.0.13 - - @ai-sdk/solid@0.0.10 - - @ai-sdk/vue@0.0.10 - -## 3.2.12 - -### Patch Changes - -- 5edc6110: feat (ai/core): add custom request header support -- Updated dependencies - - @ai-sdk/provider@0.0.11 - - @ai-sdk/provider-utils@1.0.0 - - @ai-sdk/react@0.0.12 - - @ai-sdk/svelte@0.0.10 - - @ai-sdk/ui-utils@0.0.7 - - @ai-sdk/solid@0.0.9 - - @ai-sdk/vue@0.0.9 - -## 3.2.11 - -### Patch Changes - -- c908f741: chore (ui/solid): update solidjs useChat and useCompletion to feature parity with React -- 827ef450: feat (ai/ui): improve error handling in useAssistant -- Updated dependencies - - @ai-sdk/solid@0.0.8 - - @ai-sdk/svelte@0.0.9 - - @ai-sdk/react@0.0.11 - -## 3.2.10 - -### Patch Changes - -- Updated dependencies - - @ai-sdk/react@0.0.10 - -## 3.2.9 - -### Patch Changes - -- 82d9c8de: feat (ai/ui): make event in useAssistant submitMessage optional -- Updated dependencies - - @ai-sdk/svelte@0.0.8 - - @ai-sdk/react@0.0.9 - - @ai-sdk/vue@0.0.8 - -## 3.2.8 - -### Patch Changes - -- 54bf4083: feat (ai/react): control request body in useChat -- Updated dependencies [54bf4083] - - @ai-sdk/ui-utils@0.0.6 - - @ai-sdk/react@0.0.8 - - @ai-sdk/solid@0.0.7 - - @ai-sdk/svelte@0.0.7 - - @ai-sdk/vue@0.0.7 - -## 3.2.7 - -### Patch Changes - -- d42b8907: feat (ui): make event in handleSubmit optional -- Updated dependencies [d42b8907] - - @ai-sdk/svelte@0.0.6 - - @ai-sdk/react@0.0.7 - - @ai-sdk/solid@0.0.6 - - @ai-sdk/vue@0.0.6 - -## 3.2.6 - -### Patch Changes - -- 74e28222: fix (ai/rsc): "could not find InternalStreamableUIClient" bug - -## 3.2.5 - -### Patch Changes - -- 4d426d0c: fix (ai): split provider and model ids correctly in the provider registry - -## 3.2.4 - -### Patch Changes - -- Updated dependencies [3cb103bc] - - @ai-sdk/react@0.0.6 - -## 3.2.3 - -### Patch Changes - -- 89b7552b: chore (ai): remove deprecation from ai/react imports, add experimental_useObject -- Updated dependencies [02f6a088] - - @ai-sdk/provider-utils@0.0.16 - - @ai-sdk/react@0.0.5 - - @ai-sdk/svelte@0.0.5 - - @ai-sdk/ui-utils@0.0.5 - - @ai-sdk/solid@0.0.5 - - @ai-sdk/vue@0.0.5 - -## 3.2.2 - -### Patch Changes - -- 0565cd72: feat (ai/core): add toJsonResponse to generateObject result. - -## 3.2.1 - -### Patch Changes - -- 008725ec: feat (ai): add textStream, toTextStreamResponse(), and pipeTextStreamToResponse() to streamObject -- 520fb2d5: feat (rsc): add streamUI onFinish callback -- Updated dependencies - - @ai-sdk/react@0.0.4 - - @ai-sdk/ui-utils@0.0.4 - - @ai-sdk/solid@0.0.4 - - @ai-sdk/svelte@0.0.4 - - @ai-sdk/vue@0.0.4 - -## 3.2.0 - -### Minor Changes - -- 85ef6d18: chore (ai): AI SDK 3.2 release - -### Patch Changes - -- b965dd2d: fix (core): pass settings correctly for generateObject and streamObject - -## 3.1.37 - -### Patch Changes - -- 85712895: chore (@ai-sdk/provider-utils): move test helper to provider utils -- Updated dependencies - - @ai-sdk/provider-utils@0.0.15 - - @ai-sdk/react@0.0.3 - - @ai-sdk/svelte@0.0.3 - - @ai-sdk/ui-utils@0.0.3 - - @ai-sdk/solid@0.0.3 - - @ai-sdk/vue@0.0.3 - -## 3.1.36 - -### Patch Changes - -- 4728c37f: feat (core): add text embedding model support to provider registry -- 8c49166e: chore (core): rename experimental_createModelRegistry to experimental_createProviderRegistry -- Updated dependencies [7910ae84] - - @ai-sdk/provider-utils@0.0.14 - - @ai-sdk/react@0.0.2 - - @ai-sdk/svelte@0.0.2 - - @ai-sdk/ui-utils@0.0.2 - - @ai-sdk/solid@0.0.2 - - @ai-sdk/vue@0.0.2 - -## 3.1.35 - -### Patch Changes - -- 06123501: feat (core): support https and data url strings in image parts - -## 3.1.34 - -### Patch Changes - -- d25566ac: feat (core): add cosineSimilarity helper function -- 87a5d27e: feat (core): introduce InvalidMessageRoleError. - -## 3.1.33 - -### Patch Changes - -- 6fb14b5d: chore (streams): deprecate nanoid export. -- 05536768: feat (core): add experimental model registry - -## 3.1.32 - -### Patch Changes - -- 3cabf078: fix(ai/rsc): Refactor streamable UI internal implementation - -## 3.1.31 - -### Patch Changes - -- 85f209a4: chore: extracted ui library support into separate modules -- 85f209a4: removed (streams): experimental_StreamingReactResponse was removed. Please use AI SDK RSC instead. -- Updated dependencies [85f209a4] - - @ai-sdk/ui-utils@0.0.1 - - @ai-sdk/svelte@0.0.1 - - @ai-sdk/react@0.0.1 - - @ai-sdk/solid@0.0.1 - - @ai-sdk/vue@0.0.1 - -## 3.1.30 - -### Patch Changes - -- fcf4323b: fix (core): filter out empty assistant text messages - -## 3.1.29 - -### Patch Changes - -- 28427d3e: feat (core): add streamObject onFinish callback - -## 3.1.28 - -### Patch Changes - -- 102ca22f: feat (core): add object promise to streamObject result -- Updated dependencies [102ca22f] - - @ai-sdk/provider@0.0.10 - - @ai-sdk/provider-utils@0.0.13 - -## 3.1.27 - -### Patch Changes - -- c9198d4d: feat (ui): send annotation and data fields in useChat when sendExtraMessageFields is true -- Updated dependencies - - @ai-sdk/provider@0.0.9 - - @ai-sdk/provider-utils@0.0.12 - -## 3.1.26 - -### Patch Changes - -- 5ee44cae: feat (provider): langchain StringOutputParser support - -## 3.1.25 - -### Patch Changes - -- ff281126: fix(ai/rsc): Remove extra reconcilation of streamUI - -## 3.1.24 - -### Patch Changes - -- 93cae126: fix(ai/rsc): Fix unsafe {} type in application code for StreamableValue -- 08b5c509: feat (core): add tokenUsage to streamObject result - -## 3.1.23 - -### Patch Changes - -- c03cafe6: chore (core, ui): rename maxAutomaticRoundtrips to maxToolRoundtrips - -## 3.1.22 - -### Patch Changes - -- 14bb8694: chore (ui): move maxAutomaticRoundtrips and addToolResult out of experimental - -## 3.1.21 - -### Patch Changes - -- 213f2411: fix (core,streams): support ResponseInit variants -- 09698bca: chore (streams): deprecate streaming helpers that have a provider replacement - -## 3.1.20 - -### Patch Changes - -- 0e1da476: feat (core): add maxAutomaticRoundtrips setting to generateText - -## 3.1.19 - -### Patch Changes - -- 9882d24b: fix (ui/svelte): send data to server -- 131bbd3e: fix (ui): remove console.log statements - -## 3.1.18 - -### Patch Changes - -- f9dee8ac: fix(ai/rsc): Fix types for createStreamableValue and createStreamableUI -- 1c0ebf8e: feat (core): add responseMessages to generateText result - -## 3.1.17 - -### Patch Changes - -- 92b993b7: ai/rsc: improve getAIState and getMutableAIState types -- 7de628e9: chore (ui): deprecate old function/tool call handling -- 7de628e9: feat (ui): add onToolCall handler to useChat - -## 3.1.16 - -### Patch Changes - -- f39c0dd2: feat (core, rsc): add toolChoice setting -- Updated dependencies [f39c0dd2] - - @ai-sdk/provider@0.0.8 - - @ai-sdk/provider-utils@0.0.11 - -## 3.1.15 - -### Patch Changes - -- 8e780288: feat (ai/core): add onFinish callback to streamText -- 8e780288: feat (ai/core): add text, toolCalls, and toolResults promises to StreamTextResult (matching the generateText result API with async methods) -- Updated dependencies [8e780288] - - @ai-sdk/provider@0.0.7 - - @ai-sdk/provider-utils@0.0.10 - -## 3.1.14 - -### Patch Changes - -- 6109c6a: feat (ai/react): add experimental_maxAutomaticRoundtrips to useChat - -## 3.1.13 - -### Patch Changes - -- 60117c9: dependencies (ai/ui): add React 18.3 and 19 support (peer dependency) -- Updated dependencies - - @ai-sdk/provider@0.0.6 - - @ai-sdk/provider-utils@0.0.9 - -## 3.1.12 - -### Patch Changes - -- ae05fb7: feat (ai/streams): add StreamData support to streamToResponse - -## 3.1.11 - -### Patch Changes - -- a085d42: fix (ai/ui): decouple StreamData chunks from LLM stream - -## 3.1.10 - -### Patch Changes - -- 3a21030: feat (ai/core): add embedMany function - -## 3.1.9 - -### Patch Changes - -- 18a9655: feat (ai/svelte): add useAssistant - -## 3.1.8 - -### Patch Changes - -- 0f6bc4e: feat (ai/core): add embed function -- Updated dependencies [0f6bc4e] - - @ai-sdk/provider@0.0.5 - - @ai-sdk/provider-utils@0.0.8 - -## 3.1.7 - -### Patch Changes - -- f617b97: feat (ai): support client/server tool calls with useChat and streamText - -## 3.1.6 - -### Patch Changes - -- 2e78acb: Deprecate StreamingReactResponse (use AI SDK RSC instead). -- 8439884: ai/rsc: make RSC streamable utils chainable -- 325ca55: feat (ai/core): improve image content part error message -- Updated dependencies [325ca55] - - @ai-sdk/provider@0.0.4 - - @ai-sdk/provider-utils@0.0.7 - -## 3.1.5 - -### Patch Changes - -- 5b01c13: feat (ai/core): add system message support in messages list - -## 3.1.4 - -### Patch Changes - -- ceb44bc: feat (ai/ui): add stop() helper to useAssistant (important: AssistantResponse now requires OpenAI SDK 4.42+) -- 37c9d4c: feat (ai/streams): add LangChainAdapter.toAIStream() - -## 3.1.3 - -### Patch Changes - -- 970a099: fix (ai/core): streamObject fixes partial json with empty objects correctly -- 1ac2390: feat (ai/core): add usage and finishReason to streamText result. -- Updated dependencies [276f22b] - - @ai-sdk/provider-utils@0.0.6 - -## 3.1.2 - -### Patch Changes - -- d1b1880: fix (ai/core): allow reading streams in streamText result multiple times - -## 3.1.1 - -### Patch Changes - -- 0f77132: ai/rsc: remove experimental\_ from streamUI - -## 3.1.0 - -### Minor Changes - -- 73356a9: Move AI Core functions out of experimental (streamText, generateText, streamObject, generateObject). - -## 3.0.35 - -### Patch Changes - -- 41d5736: ai/core: re-expose language model types. -- b4c68ec: ai/rsc: ReadableStream as provider for createStreamableValue; add .append() method -- Updated dependencies [41d5736] - - @ai-sdk/provider@0.0.3 - - @ai-sdk/provider-utils@0.0.5 - -## 3.0.34 - -### Patch Changes - -- b9a831e: ai/rsc: add experimental_streamUI() - -## 3.0.33 - -### Patch Changes - -- 56ef84a: ai/core: fix abort handling in transformation stream -- Updated dependencies [56ef84a] - - @ai-sdk/provider-utils@0.0.4 - -## 3.0.32 - -### Patch Changes - -- 0e0d2af: ai/core: add pipeTextStreamToResponse helper to streamText. - -## 3.0.31 - -### Patch Changes - -- 74c63b1: ai/core: add toAIStreamResponse() helper to streamText. - -## 3.0.30 - -### Patch Changes - -- e7e5898: use-assistant: fix missing message content - -## 3.0.29 - -### Patch Changes - -- 22a737e: Fix: mark useAssistant as in progress for append/submitMessage. - -## 3.0.28 - -### Patch Changes - -- d6431ae: ai/core: add logprobs support (thanks @SamStenner for the contribution) -- 25f3350: ai/core: add support for getting raw response headers. -- Updated dependencies - - @ai-sdk/provider@0.0.2 - - @ai-sdk/provider-utils@0.0.3 - -## 3.0.27 - -### Patch Changes - -- eb150a6: ai/core: remove scaling of setting values (breaking change). If you were using the temperature, frequency penalty, or presence penalty settings, you need to update the providers and adjust the setting values. -- Updated dependencies [eb150a6] - - @ai-sdk/provider-utils@0.0.2 - - @ai-sdk/provider@0.0.1 - -## 3.0.26 - -### Patch Changes - -- f90f6a1: ai/core: add pipeAIStreamToResponse() to streamText result. - -## 3.0.25 - -### Patch Changes - -- 1e84d6d: Fix: remove mistral lib type dependency. -- 9c2a049: Add append() helper to useAssistant. - -## 3.0.24 - -### Patch Changes - -- e94fb32: feat(ai/rsc): Make `onSetAIState` and `onGetUIState` stable - -## 3.0.23 - -### Patch Changes - -- 66b5892: Add streamMode parameter to useChat and useCompletion. -- Updated dependencies [7b8791d] - - @ai-sdk/provider-utils@0.0.1 - -## 3.0.22 - -### Patch Changes - -- d544886: Breaking change: extract experimental AI core provider packages. They can now be imported with e.g. import { openai } from '@ai-sdk/openai' after adding them to a project. -- ea6b0e1: Expose formatStreamPart, parseStreamPart, and readDataStream helpers. - -## 3.0.21 - -### Patch Changes - -- 87d3db5: Extracted @ai-sdk/provider package -- 8c40f8c: ai/core: Fix openai provider streamObject for gpt-4-turbo -- 5cd29bd: ai/core: add toTextStreamResponse() method to streamText result - -## 3.0.20 - -### Patch Changes - -- f42bbb5: Remove experimental from useAssistant and AssistantResponse. -- 149fe26: Deprecate -- 2eb4b55: Remove experimental\_ prefix from StreamData. -- e45fa96: Add stream support for Bedrock/Cohere. -- a6b2500: Deprecated the `experimental_streamData: true` setting from AIStreamCallbacksAndOptions. You can delete occurrences in your code. The stream data protocol is now used by default. - -## 3.0.19 - -### Patch Changes - -- 4f4c7f5: ai/core: Anthropic tool call support - -## 3.0.18 - -### Patch Changes - -- 63d587e: Add Anthropic provider for ai/core functions (no tool calling). -- 63d587e: Add automatic mime type detection for images in ai/core prompts. - -## 3.0.17 - -### Patch Changes - -- 2b991c4: Add Google Generative AI provider for ai/core functions. - -## 3.0.16 - -### Patch Changes - -- a54ea77: feat(ai/rsc): add `useStreamableValue` - -## 3.0.15 - -### Patch Changes - -- 4aed2a5: Add JSDoc comments for ai/core functions. -- cf8d12f: Export experimental language model specification under `ai/spec`. - -## 3.0.14 - -### Patch Changes - -- 8088de8: fix(ai/rsc): improve typings for `StreamableValue` -- 20007b9: feat(ai/rsc): support string diff and patch in streamable value -- 6039460: Support Bedrock Anthropic Stream for Messages API. -- e83bfe3: Added experimental ai/core functions (streamText, generateText, streamObject, generateObject). Add OpenAI and Mistral language model providers. - -## 3.0.13 - -### Patch Changes - -- 026d061: Expose setMessages in useAssistant hook -- 42209be: AssistantResponse: specify forwardStream return type. - -## 3.0.12 - -### Patch Changes - -- b99b008: fix(ai/rsc): avoid appending boundary if the same reference was passed - -## 3.0.11 - -### Patch Changes - -- ce009e2: Added OpenAI assistants streaming. -- 3f9bf3e: Updates types to OpenAI SDK 4.29.0 - -## 3.0.10 - -### Patch Changes - -- 33d261a: fix(ai/rsc): Fix .append() behavior - -## 3.0.9 - -### Patch Changes - -- 81ca3d6: fix(ai/rsc): improve .done() argument type - -## 3.0.8 - -### Patch Changes - -- a94aab2: ai/rsc: optimize streamable value stream size - -## 3.0.7 - -### Patch Changes - -- 9a9ae73: feat(ai/rsc): readStreamableValue - -## 3.0.6 - -### Patch Changes - -- 1355ad0: Fix: experimental_onToolCall is called with parsed tool args -- 9348f06: ai/rsc: improve dev error and warnings by trying to detect hanging streams -- 8be9404: fix type resolution - -## 3.0.5 - -### Patch Changes - -- a973f1e: Support Anthropic SDK v0.15.0 -- e25f3ca: type improvements - -## 3.0.4 - -### Patch Changes - -- 7962862: fix `useActions` type inference -- aab5324: Revert "fix(render): parse the args based on the zod schema" -- fe55612: Bump OpenAI dependency to 4.28.4; fix type error in render - -## 3.0.3 - -### Patch Changes - -- 4d816ca: fix(render): parse the args based on the zod schema -- d158a47: fix potential race conditions - -## 3.0.2 - -### Patch Changes - -- 73bd06e: fix(useActions): return typed object - -## 3.0.1 - -### Patch Changes - -- ac20a25: ai/rsc: fix text response and async generator -- b88778f: Added onText callback for text tokens. - -## 3.0.0 - -### Major Changes - -- 51054a9: add ai/rsc - -## 2.2.37 - -### Patch Changes - -- a6b5764: Add support for Mistral's JavaScript SDK - -## 2.2.36 - -### Patch Changes - -- 141f0ce: Fix: onFinal callback is invoked with text from onToolCall when onToolCall returns string - -## 2.2.35 - -### Patch Changes - -- b717dad: Adding Inkeep as a stream provider - -## 2.2.34 - -### Patch Changes - -- 2c8ffdb: cohere-stream: support AsyncIterable -- ed1e278: Message annotations handling for all Message types - -## 2.2.33 - -### Patch Changes - -- 8542ae7: react/use-assistant: add onError handler -- 97039ff: OpenAIStream: Add support for the Azure OpenAI client library - -## 2.2.32 - -### Patch Changes - -- 7851fa0: StreamData: add `annotations` and `appendMessageAnnotation` support - -## 2.2.31 - -### Patch Changes - -- 9b89c4d: react/use-assistant: Expose setInput -- 75751c9: ai/react: Add experimental_onToolCall to useChat. - -## 2.2.30 - -### Patch Changes - -- ac503e0: ai/solid: add chat request options to useChat -- b78a73e: Add GoogleGenerativeAIStream for Gemini support -- 5220336: ai/svelte: Add experimental_onToolCall to useChat. -- ef99062: Add support for the Anthropic message API -- 5220336: Add experimental_onToolCall to OpenAIStream. -- ac503e0: ai/vue: add chat request options to useChat - -## 2.2.29 - -### Patch Changes - -- 5a9ae2e: ai/prompt: add `experimental_buildOpenAIMessages` to validate and cast AI SDK messages to OpenAI messages - -## 2.2.28 - -### Patch Changes - -- 07a679c: Add data message support to useAssistant & assistantResponse. -- fbae595: ai/react: `api` functions are no longer used as a cache key in `useChat` - -## 2.2.27 - -### Patch Changes - -- 0fd1205: ai/vue: Add complex response parsing and StreamData support to useCompletion -- a7dc746: experimental_useAssistant: Expose extra fetch options -- 3dcf01e: ai/react Add data support to useCompletion -- 0c3b338: ai/svelte: Add complex response parsing and StreamData support to useCompletion -- 8284777: ai/solid: Add complex response parsing and StreamData support to useCompletion - -## 2.2.26 - -### Patch Changes - -- df1ad33: ai/vue: Add complex response parsing and StreamData support to useChat -- 3ff8a56: Add `generateId` to use-chat params to allow overriding message ID generation -- 6c2a49c: ai/react experimental_useAssistant() submit can be called without an event -- 8b4f7d1: ai/react: Add complex response parsing and StreamData support to useCompletion - -## 2.2.25 - -### Patch Changes - -- 1e61c69: chore: specify the minimum react version to 18 -- 6aec2d2: Expose threadId in useAssistant -- c2369df: Add AWS Bedrock support -- 223fde3: ai/svelte: Add complex response parsing and StreamData support to useChat - -## 2.2.24 - -### Patch Changes - -- 69ca8f5: ai/react: add experimental_useAssistant hook and experimental_AssistantResponse -- 3e2299e: experimental_StreamData/StreamingReactResponse: optimize parsing, improve types -- 70bd2ac: ai/solid: add experimental_StreamData support to useChat - -## 2.2.23 - -### Patch Changes - -- 5a04321: add StreamData support to StreamingReactResponse, add client-side data API to react/use-chat - -## 2.2.22 - -### Patch Changes - -- 4529831: ai/react: Do not store initialMessages in useState -- db5378c: experimental_StreamData: fix data type to be JSONValue - -## 2.2.21 - -### Patch Changes - -- 2c8d4bd: Support openai@4.16.0 and later - -## 2.2.20 - -### Patch Changes - -- 424d5ee: experimental_StreamData: fix trailing newline parsing bug in decoder -- c364c6a: cohere: fix closing cohere stream, avoids response from hanging - -## 2.2.19 - -### Patch Changes - -- 699552d: add experimental_StreamingReactResponse - -## 2.2.18 - -### Patch Changes - -- 0bd27f6: react/use-chat: allow client-side handling of function call without following response - -## 2.2.17 - -### Patch Changes - -- 5ed581d: Use interface instead of type for Message to allow declaration merging -- 9adec1e: vue and solid: fix including `function_call` and `name` fields in subsequent requests - -## 2.2.16 - -### Patch Changes - -- e569688: Fix for #637, resync interfaces - -## 2.2.15 - -### Patch Changes - -- c5d1857: fix: return complete response in onFinish when onCompletion isn't passed -- c5d1857: replicate-stream: fix types for replicate@0.20.0+ - -## 2.2.14 - -### Patch Changes - -- 6229d6b: openai: fix OpenAIStream types with openai@4.11+ - -## 2.2.13 - -### Patch Changes - -- a4a997f: all providers: reset error message on (re)submission - -## 2.2.12 - -### Patch Changes - -- cb181b4: ai/vue: wrap body with unref to support reactivity - -## 2.2.11 - -### Patch Changes - -- 2470658: ai/react: fix: handle partial chunks in react getStreamedResponse when using experimental_StreamData - -## 2.2.10 - -### Patch Changes - -- 8a2cbaf: vue/use-completion: fix: don't send network request for loading state" -- bbf4403: langchain-stream: return langchain `writer` from LangChainStream - -## 2.2.9 - -### Patch Changes - -- 3fc2b32: ai/vue: fix: make body parameter reactive - -## 2.2.8 - -### Patch Changes - -- 26bf998: ai/react: make reload/complete/append functions stable via useCallback - -## 2.2.7 - -### Patch Changes - -- 2f97630: react/use-chat: fix aborting clientside function calls too early -- 1157340: fix: infinite loop for experimental stream data (#484) - -## 2.2.6 - -### Patch Changes - -- e5bf68d: react/use-chat: fix experimental functions returning proper function messages - - Closes #478 - -## 2.2.5 - -### Patch Changes - -- e5bf68d: react/use-chat: fix experimental functions returning proper function messages - - Closes #478 - -## 2.2.4 - -### Patch Changes - -- 7b389a7: fix: improve safety for type check in openai-stream - -## 2.2.3 - -### Patch Changes - -- 867a3f9: Fix client-side function calling (#467, #469) - - add Completion type from the `openai` SDK to openai-stream (#472) - -## 2.2.2 - -### Patch Changes - -- 84e0cc8: Add experimental_StreamData and new opt-in wire protocol to enable streaming additional data. See https://github.com/vercel/ai/pull/425. - - Changes `onCompletion` back to run every completion, including recursive function calls. Adds an `onFinish` callback that runs once everything has streamed. - - If you're using experimental function handlers on the server _and_ caching via `onCompletion`, - you may want to adjust your caching code to account for recursive calls so the same key isn't used. - - ``` - let depth = 0 - - const stream = OpenAIStream(response, { - async onCompletion(completion) { - depth++ - await kv.set(key + '_' + depth, completion) - await kv.expire(key + '_' + depth, 60 * 60) - } - }) - ``` - -## 2.2.1 - -### Patch Changes - -- 04084a8: openai-stream: fix experimental_onFunctionCall types for OpenAI SDK v4 - -## 2.2.0 - -### Minor Changes - -- dca1ed9: Update packages and examples to use OpenAI SDK v4 - -## 2.1.34 - -### Patch Changes - -- c2917d3: Add support for the Anthropic SDK, newer Anthropic API versions, and improve Anthropic error handling - -## 2.1.33 - -### Patch Changes - -- 4ef8015: Prevent `isLoading` in vue integration from triggering extraneous network requests - -## 2.1.32 - -### Patch Changes - -- 5f91427: ai/svelte: fix isLoading return value - -## 2.1.31 - -### Patch Changes - -- ab2b973: fix pnpm-lock.yaml - -## 2.1.30 - -### Patch Changes - -- 4df2a49: Fix termination of ReplicateStream by removing the terminating `{}`from output - -## 2.1.29 - -### Patch Changes - -- 3929a41: Add ReplicateStream helper - -## 2.1.28 - -### Patch Changes - -- 9012e17: react/svelte/vue: fix making unnecessary SWR request to API endpoint - -## 2.1.27 - -### Patch Changes - -- 3d29799: React/Svelte/Vue: keep isLoading in sync between hooks with the same ID. - - React: don't throw error when submitting - -## 2.1.26 - -### Patch Changes - -- f50d9ef: Add experimental_buildLlama2Prompt helper for Hugging Face - -## 2.1.25 - -### Patch Changes - -- 877c16f: ai/react: don't throw error if onError is passed - -## 2.1.24 - -### Patch Changes - -- f3f5866: Adds SolidJS support and SolidStart example - -## 2.1.23 - -### Patch Changes - -- 0ebc2f0: streams/openai-stream: don't call onStart/onCompletion when recursing - -## 2.1.22 - -### Patch Changes - -- 9320e95: Add (experimental) prompt construction helpers for StarChat and OpenAssistant -- e3a7ec8: Support <|end|> token for StarChat beta in huggingface-stream - -## 2.1.21 - -### Patch Changes - -- 561a49a: Providing a function to `function_call` request parameter of the OpenAI Chat Completions API no longer breaks OpenAI function stream parsing. - -## 2.1.20 - -### Patch Changes - -- e361114: OpenAI functions: allow returning string in callback - -## 2.1.19 - -### Patch Changes - -- e4281ca: Add experimental server-side OpenAI function handling - -## 2.1.18 - -### Patch Changes - -- 6648b21: Add experimental client side OpenAI function calling to Svelte bindings -- e5b983f: feat(streams): add http error handling for openai - -## 2.1.17 - -### Patch Changes - -- 3ed65bf: Remove dependency on node crypto API - -## 2.1.16 - -### Patch Changes - -- 8bfb43d: Fix svelte peer dependency version - -## 2.1.15 - -### Patch Changes - -- 4a2b978: Update cohere stream and add docs - -## 2.1.14 - -### Patch Changes - -- 3164adb: Fix regression with generated ids - -## 2.1.13 - -### Patch Changes - -- fd82961: Use rfc4122 IDs when generating chat/completion IDs - -## 2.1.12 - -### Patch Changes - -- b7b93e5: Add RSC to ai/react - -## 2.1.11 - -### Patch Changes - -- 8bf637a: Fix langchain handlers so that they now are correctly invoked and update examples and docs to show correct usage (passing the handlers to `llm.call` and not the model itself). - -## 2.1.10 - -### Patch Changes - -- a7b3d0e: Experimental support for OpenAI function calling - -## 2.1.9 - -### Patch Changes - -- 9cdf968: core/react: add Tokens react server component - -## 2.1.8 - -### Patch Changes - -- 44d9879: Support extra request options in chat and completion hooks - -## 2.1.7 - -### Patch Changes - -- bde3898: Allow an async onResponse callback in useChat/useCompletion - -## 2.1.6 - -### Patch Changes - -- 23f0899: Set stream: true when decoding streamed chunks - -## 2.1.5 - -### Patch Changes - -- 89938b0: Provider direct callback handlers in LangChain now that `CallbackManager` is deprecated. - -## 2.1.4 - -### Patch Changes - -- c16d650: Improve type saftey for AIStream. Added JSDoc comments. - -## 2.1.3 - -### Patch Changes - -- a9591fe: Add `createdAt` on `user` input message in `useChat` (it was already present in `assistant` messages) - -## 2.1.2 - -### Patch Changes - -- f37d4ec: fix bundling - -## 2.1.1 - -### Patch Changes - -- 9fdb51a: fix: add better typing for store within svelte implementation (#104) - -## 2.1.0 - -### Minor Changes - -- 71f9c51: This adds Vue support for `ai` via the `ai/vue` subpath export. Vue composables `useChat` and `useCompletion` are provided. - -### Patch Changes - -- ad54c79: add tests - -## 2.0.1 - -### Patch Changes - -- be90740: - Switches `LangChainStream` helper callback `handler` to return use `handleChainEnd` instead of `handleLLMEnd` so as to work with sequential chains - -## 2.0.0 - -### Major Changes - -- 095de43: New package name! - -## 0.0.14 - -### Patch Changes - -- c6586a2: Add onError callback, include response text in error if response is not okay - -## 0.0.13 - -### Patch Changes - -- c1f4a91: Throw error when provided AI response isn't valid - -## 0.0.12 - -### Patch Changes - -- ea4e66a: improve API types - -## 0.0.11 - -### Patch Changes - -- a6bc35c: fix package exports for react and svelte subpackages - -## 0.0.10 - -### Patch Changes - -- 56f9537: add svelte apis - -## 0.0.9 - -### Patch Changes - -- 78477d3: - Create `/react` sub-package. - - Create `import { useChat, useCompletion } from 'ai/react'` and mark React as an optional peer dependency so we can add more framework support in the future. - - Also renamed `set` to `setMessages` and `setCompletion` to unify the API naming as we have `setInput` too. - - Added an `sendExtraMessageFields` field to `useChat` that defaults to `false`, to prevent OpenAI errors when `id` is not filtered out. -- c4c1be3: useCompletion.handleSubmit does not clear the input anymore -- 7de2185: create /react export - -## 0.0.8 - -### Patch Changes - -- fc83e95: Implement new start-of-stream newline trimming -- 2c6fa04: Optimize callbacks TransformStream to be more memory efficient when `onCompletion` is not specified - -## 0.0.7 - -### Patch Changes - -- fdfef52: - Splits the `EventSource` parser into a reusable helper - - Uses a `TransformStream` for this, so the stream respects back-pressure - - Splits the "forking" stream for callbacks into a reusable helper - - Changes the signature for `customParser` to avoid Stringify -> Encode -> Decode -> Parse round trip - - Uses ?.() optional call syntax for callbacks - - Uses string.includes to perform newline checking - - Handles the `null` `res.body` case - - Fixes Anthropic's streaming responses - - Anthropic returns cumulative responses, not deltas like OpenAI - - https://github.com/hwchase17/langchain/blob/3af36943/langchain/llms/anthropic.py#L190-L193 - -## 0.0.6 - -### Patch Changes - -- d70a9e7: Add streamToResponse -- 47b85b2: Improve abortController and callbacks of `useChat` -- 6f7b43a: Export `UseCompletionHelpers` as a TypeScript type alias - -## 0.0.5 - -### Patch Changes - -- 4405a8a: fix duplicated `'use client'` directives - -## 0.0.4 - -### Patch Changes - -- b869104: Added `LangChainStream`, `useCompletion`, and `useChat` - -## 0.0.3 - -### Patch Changes - -- 677d222: add useCompletion - -## 0.0.2 - -### Patch Changes - -- af400e2: Fix release script - -## 0.0.1 - -### Patch Changes - -- b7e227d: Add `useChat` hook - -## 0.0.2 - -### Patch Changes - -- 9a8a845: Testing out release diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/LICENSE deleted file mode 100644 index 6c16c29f4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2023 Vercel, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/README.md deleted file mode 100644 index 35d4302c2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/README.md +++ /dev/null @@ -1,238 +0,0 @@ -![hero illustration](./assets/hero.gif) - -# AI SDK - -The [AI SDK](https://ai-sdk.dev/docs) is a provider-agnostic TypeScript toolkit designed to help you build AI-powered applications and agents using popular UI frameworks like Next.js, React, Svelte, Vue, Angular, and runtimes like Node.js. - -To learn more about how to use the AI SDK, check out our [API Reference](https://ai-sdk.dev/docs/reference) and [Documentation](https://ai-sdk.dev/docs). - -## Installation - -You will need Node.js 18+ and npm (or another package manager) installed on your local development machine. - -```shell -npm install ai -``` - -## Skill for Coding Agents - -If you use coding agents such as Claude Code or Cursor, we highly recommend adding the AI SDK skill to your repository: - -```shell -npx skills add vercel/ai -``` - -## Unified Provider Architecture - -The AI SDK provides a [unified API](https://ai-sdk.dev/docs/foundations/providers-and-models) to interact with model providers like [OpenAI](https://ai-sdk.dev/providers/ai-sdk-providers/openai), [Anthropic](https://ai-sdk.dev/providers/ai-sdk-providers/anthropic), [Google](https://ai-sdk.dev/providers/ai-sdk-providers/google-generative-ai), and [more](https://ai-sdk.dev/providers/ai-sdk-providers). - -By default, the AI SDK uses the [Vercel AI Gateway](https://vercel.com/docs/ai-gateway) to give you access to all major providers out of the box. Just pass a model string for any supported model: - -```ts -const result = await generateText({ - model: 'anthropic/claude-opus-4.6', // or 'openai/gpt-5.4', 'google/gemini-3-flash', etc. - prompt: 'Hello!', -}); -``` - -You can also connect to providers directly using their SDK packages: - -```shell -npm install @ai-sdk/openai @ai-sdk/anthropic @ai-sdk/google -``` - -```ts -import { anthropic } from '@ai-sdk/anthropic'; - -const result = await generateText({ - model: anthropic('claude-opus-4-6'), // or openai('gpt-5.4'), google('gemini-3-flash'), etc. - prompt: 'Hello!', -}); -``` - -## Usage - -### Generating Text - -```ts -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: 'openai/gpt-5.4', // use Vercel AI Gateway - prompt: 'What is an agent?', -}); -``` - -### Generating Structured Data - -```ts -import { generateText, Output } from 'ai'; -import { z } from 'zod'; - -const { output } = await generateText({ - model: 'openai/gpt-5.4', - output: Output.object({ - schema: z.object({ - recipe: z.object({ - name: z.string(), - ingredients: z.array( - z.object({ name: z.string(), amount: z.string() }), - ), - steps: z.array(z.string()), - }), - }), - }), - prompt: 'Generate a lasagna recipe.', -}); -``` - -### Agents - -```ts -import { ToolLoopAgent } from 'ai'; - -const sandboxAgent = new ToolLoopAgent({ - model: 'openai/gpt-5.4', - system: 'You are an agent with access to a shell environment.', - tools: { - shell: openai.tools.localShell({ - execute: async ({ action }) => { - const [cmd, ...args] = action.command; - const sandbox = await getSandbox(); // Vercel Sandbox - const command = await sandbox.runCommand({ cmd, args }); - return { output: await command.stdout() }; - }, - }), - }, -}); -``` - -### UI Integration - -The [AI SDK UI](https://ai-sdk.dev/docs/ai-sdk-ui/overview) module provides a set of hooks that help you build chatbots and generative user interfaces. These hooks are framework agnostic, so they can be used in Next.js, React, Svelte, and Vue. - -You need to install the package for your framework, e.g.: - -```shell -npm install @ai-sdk/react -``` - -#### Agent @/agent/image-generation-agent.ts - -```ts -import { openai } from '@ai-sdk/openai'; -import { ToolLoopAgent, InferAgentUIMessage } from 'ai'; - -export const imageGenerationAgent = new ToolLoopAgent({ - model: 'openai/gpt-5.4', - tools: { - generateImage: openai.tools.imageGeneration({ - partialImages: 3, - }), - }, -}); - -export type ImageGenerationAgentMessage = InferAgentUIMessage< - typeof imageGenerationAgent ->; -``` - -#### Route (Next.js App Router) @/app/api/chat/route.ts - -```tsx -import { imageGenerationAgent } from '@/agent/image-generation-agent'; -import { createAgentUIStreamResponse } from 'ai'; - -export async function POST(req: Request) { - const { messages } = await req.json(); - - return createAgentUIStreamResponse({ - agent: imageGenerationAgent, - messages, - }); -} -``` - -#### UI Component for Tool @/component/image-generation-view.tsx - -```tsx -import { openai } from '@ai-sdk/openai'; -import { UIToolInvocation } from 'ai'; - -export default function ImageGenerationView({ - invocation, -}: { - invocation: UIToolInvocation>; -}) { - switch (invocation.state) { - case 'input-available': - return
Generating image...
; - case 'output-available': - return ; - } -} -``` - -#### Page @/app/page.tsx - -```tsx -'use client'; - -import { ImageGenerationAgentMessage } from '@/agent/image-generation-agent'; -import ImageGenerationView from '@/component/image-generation-view'; -import { useChat } from '@ai-sdk/react'; - -export default function Page() { - const { messages, status, sendMessage } = - useChat(); - - const [input, setInput] = useState(''); - const handleSubmit = e => { - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }; - - return ( -
- {messages.map(message => ( -
- {`${message.role}: `} - {message.parts.map((part, index) => { - switch (part.type) { - case 'text': - return
{part.text}
; - case 'tool-generateImage': - return ; - } - })} -
- ))} - -
- setInput(e.target.value)} - disabled={status !== 'ready'} - /> -
-
- ); -} -``` - -## Templates - -We've built [templates](https://ai-sdk.dev/docs/introduction#templates) that include AI SDK integrations for different use cases, providers, and frameworks. You can use these templates to get started with your AI-powered application. - -## Community - -The AI SDK community can be found on [the Vercel Community](https://community.vercel.com/c/ai-sdk/62) where you can ask questions, voice ideas, and share your projects with other people. - -## Contributing - -Contributions to the AI SDK are welcome and highly appreciated. However, before you jump right into it, we would like you to review our [Contribution Guidelines](https://github.com/vercel/ai/blob/main/CONTRIBUTING.md) to make sure you have smooth experience contributing to AI SDK. - -## Authors - -This library is created by [Vercel](https://vercel.com) and [Next.js](https://nextjs.org) team members, with contributions from the [Open Source Community](https://github.com/vercel/ai/graphs/contributors). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/00-introduction/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/00-introduction/index.mdx deleted file mode 100644 index 3474a23b5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/00-introduction/index.mdx +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: AI SDK by Vercel -description: The AI SDK is the TypeScript toolkit for building AI applications and agents with React, Next.js, Vue, Svelte, Node.js, and more. ---- - -# AI SDK - -The AI SDK is the TypeScript toolkit designed to help developers build AI-powered applications and agents with React, Next.js, Vue, Svelte, Node.js, and more. - -## Why use the AI SDK? - -Integrating large language models (LLMs) into applications is complicated and heavily dependent on the specific model provider you use. - -The AI SDK standardizes integrating artificial intelligence (AI) models across [supported providers](/docs/foundations/providers-and-models). This enables developers to focus on building great AI applications, not waste time on technical details. - -For example, here’s how you can generate text with various models using the AI SDK: - - - -The AI SDK has two main libraries: - -- **[AI SDK Core](/docs/ai-sdk-core):** A unified API for generating text, structured objects, tool calls, and building agents with LLMs. -- **[AI SDK UI](/docs/ai-sdk-ui):** A set of framework-agnostic hooks for quickly building chat and generative user interface. - -## Model Providers - -The AI SDK supports [multiple model providers](/providers). - - - -## Templates - -We've built some [templates](https://vercel.com/templates?type=ai) that include AI SDK integrations for different use cases, providers, and frameworks. You can use these templates to get started with your AI-powered application. - -### Starter Kits - - - -### Feature Exploration - - - -### Frameworks - - - -### Generative UI - - - -### Security - - - -## Join our Community - -If you have questions about anything related to the AI SDK, you're always welcome to ask our community on [the Vercel Community](https://community.vercel.com/c/ai-sdk/62). - -## `llms.txt` (for Cursor, Windsurf, Copilot, Claude etc.) - -You can access the entire AI SDK documentation in Markdown format at [ai-sdk.dev/llms.txt](/llms.txt). This can be used to ask any LLM (assuming it has a big enough context window) questions about the AI SDK based on the most up-to-date documentation. - -### Example Usage - -For instance, to prompt an LLM with questions about the AI SDK: - -1. Copy the documentation contents from [ai-sdk.dev/llms.txt](/llms.txt) -2. Use the following prompt format: - -```prompt -Documentation: -{paste documentation here} ---- -Based on the above documentation, answer the following: -{your question} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/01-overview.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/01-overview.mdx deleted file mode 100644 index 4544d98d5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/01-overview.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Overview -description: An overview of foundational concepts critical to understanding the AI SDK ---- - -# Overview - - - This page is a beginner-friendly introduction to high-level artificial - intelligence (AI) concepts. To dive right into implementing the AI SDK, feel - free to skip ahead to our [quickstarts](/docs/getting-started) or learn about - our [supported models and providers](/docs/foundations/providers-and-models). - - -The AI SDK standardizes integrating artificial intelligence (AI) models across [supported providers](/docs/foundations/providers-and-models). This enables developers to focus on building great AI applications, not waste time on technical details. - -For example, here’s how you can generate text with various models using the AI SDK: - - - -To effectively leverage the AI SDK, it helps to familiarize yourself with the following concepts: - -## Generative Artificial Intelligence - -**Generative artificial intelligence** refers to models that predict and generate various types of outputs (such as text, images, or audio) based on what’s statistically likely, pulling from patterns they’ve learned from their training data. For example: - -- Given a photo, a generative model can generate a caption. -- Given an audio file, a generative model can generate a transcription. -- Given a text description, a generative model can generate an image. - -## Large Language Models - -A **large language model (LLM)** is a subset of generative models focused primarily on **text**. An LLM takes a sequence of words as input and aims to predict the most likely sequence to follow. It assigns probabilities to potential next sequences and then selects one. The model continues to generate sequences until it meets a specified stopping criterion. - -LLMs learn by training on massive collections of written text, which means they will be better suited to some use cases than others. For example, a model trained on GitHub data would understand the probabilities of sequences in source code particularly well. - -However, it's crucial to understand LLMs' limitations. When asked about less known or absent information, like the birthday of a personal relative, LLMs might "hallucinate" or make up information. It's essential to consider how well-represented the information you need is in the model. - -## Embedding Models - -An **embedding model** is used to convert complex data (like words or images) into a dense vector (a list of numbers) representation, known as an embedding. Unlike generative models, embedding models do not generate new text or data. Instead, they provide representations of semantic and syntactic relationships between entities that can be used as input for other models or other natural language processing tasks. - -In the next section, you will learn about the difference between models providers and models, and which ones are available in the AI SDK. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/02-providers-and-models.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/02-providers-and-models.mdx deleted file mode 100644 index d6593368c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/02-providers-and-models.mdx +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: Providers and Models -description: Learn about the providers and models available in the AI SDK. ---- - -# Providers and Models - -Companies such as OpenAI and Anthropic (providers) offer access to a range of large language models (LLMs) with differing strengths and capabilities through their own APIs. - -Each provider typically has its own unique method for interfacing with their models, complicating the process of switching providers and increasing the risk of vendor lock-in. - -To solve these challenges, AI SDK Core offers a standardized approach to interacting with LLMs through a [language model specification](https://github.com/vercel/ai/tree/main/packages/provider/src/language-model/v3) that abstracts differences between providers. This unified interface allows you to switch between providers with ease while using the same API for all providers. - -Here is an overview of the AI SDK Provider Architecture: - - - -## AI SDK Providers - -The AI SDK comes with a wide range of providers that you can use to interact with different language models: - -- [xAI Grok Provider](/providers/ai-sdk-providers/xai) (`@ai-sdk/xai`) -- [OpenAI Provider](/providers/ai-sdk-providers/openai) (`@ai-sdk/openai`) -- [Azure OpenAI Provider](/providers/ai-sdk-providers/azure) (`@ai-sdk/azure`) -- [Anthropic Provider](/providers/ai-sdk-providers/anthropic) (`@ai-sdk/anthropic`) -- [Amazon Bedrock Provider](/providers/ai-sdk-providers/amazon-bedrock) (`@ai-sdk/amazon-bedrock`) -- [Google Generative AI Provider](/providers/ai-sdk-providers/google-generative-ai) (`@ai-sdk/google`) -- [Google Vertex Provider](/providers/ai-sdk-providers/google-vertex) (`@ai-sdk/google-vertex`) -- [Mistral Provider](/providers/ai-sdk-providers/mistral) (`@ai-sdk/mistral`) -- [Together.ai Provider](/providers/ai-sdk-providers/togetherai) (`@ai-sdk/togetherai`) -- [Cohere Provider](/providers/ai-sdk-providers/cohere) (`@ai-sdk/cohere`) -- [Fireworks Provider](/providers/ai-sdk-providers/fireworks) (`@ai-sdk/fireworks`) -- [DeepInfra Provider](/providers/ai-sdk-providers/deepinfra) (`@ai-sdk/deepinfra`) -- [DeepSeek Provider](/providers/ai-sdk-providers/deepseek) (`@ai-sdk/deepseek`) -- [Cerebras Provider](/providers/ai-sdk-providers/cerebras) (`@ai-sdk/cerebras`) -- [Groq Provider](/providers/ai-sdk-providers/groq) (`@ai-sdk/groq`) -- [Perplexity Provider](/providers/ai-sdk-providers/perplexity) (`@ai-sdk/perplexity`) -- [ElevenLabs Provider](/providers/ai-sdk-providers/elevenlabs) (`@ai-sdk/elevenlabs`) -- [LMNT Provider](/providers/ai-sdk-providers/lmnt) (`@ai-sdk/lmnt`) -- [Hume Provider](/providers/ai-sdk-providers/hume) (`@ai-sdk/hume`) -- [Rev.ai Provider](/providers/ai-sdk-providers/revai) (`@ai-sdk/revai`) -- [Deepgram Provider](/providers/ai-sdk-providers/deepgram) (`@ai-sdk/deepgram`) -- [Gladia Provider](/providers/ai-sdk-providers/gladia) (`@ai-sdk/gladia`) -- [AssemblyAI Provider](/providers/ai-sdk-providers/assemblyai) (`@ai-sdk/assemblyai`) -- [Baseten Provider](/providers/ai-sdk-providers/baseten) (`@ai-sdk/baseten`) - -You can also use the [OpenAI Compatible provider](/providers/openai-compatible-providers) with OpenAI-compatible APIs: - -- [LM Studio](/providers/openai-compatible-providers/lmstudio) -- [Heroku](/providers/openai-compatible-providers/heroku) - -Our [language model specification](https://github.com/vercel/ai/tree/main/packages/provider/src/language-model/v3) is published as an open-source package, which you can use to create [custom providers](/providers/community-providers/custom-providers). - -The open-source community has created the following providers: - -- [Ollama Provider](/providers/community-providers/ollama) (`ollama-ai-provider`) -- [FriendliAI Provider](/providers/community-providers/friendliai) (`@friendliai/ai-provider`) -- [Portkey Provider](/providers/community-providers/portkey) (`@portkey-ai/vercel-provider`) -- [Cloudflare Workers AI Provider](/providers/community-providers/cloudflare-workers-ai) (`workers-ai-provider`) -- [OpenRouter Provider](/providers/community-providers/openrouter) (`@openrouter/ai-sdk-provider`) -- [Apertis Provider](/providers/community-providers/apertis) (`@apertis/ai-sdk-provider`) -- [Aihubmix Provider](/providers/community-providers/aihubmix) (`@aihubmix/ai-sdk-provider`) -- [Requesty Provider](/providers/community-providers/requesty) (`@requesty/ai-sdk`) -- [Crosshatch Provider](/providers/community-providers/crosshatch) (`@crosshatch/ai-provider`) -- [Mixedbread Provider](/providers/community-providers/mixedbread) (`mixedbread-ai-provider`) -- [Voyage AI Provider](/providers/community-providers/voyage-ai) (`voyage-ai-provider`) -- [Mem0 Provider](/providers/community-providers/mem0) (`@mem0/vercel-ai-provider`) -- [Letta Provider](/providers/community-providers/letta) (`@letta-ai/vercel-ai-sdk-provider`) -- [Hindsight Provider](/providers/community-providers/hindsight) (`@vectorize-io/hindsight-ai-sdk`) -- [Supermemory Provider](/providers/community-providers/supermemory) (`@supermemory/tools`) -- [Spark Provider](/providers/community-providers/spark) (`spark-ai-provider`) -- [AnthropicVertex Provider](/providers/community-providers/anthropic-vertex-ai) (`anthropic-vertex-ai`) -- [LangDB Provider](/providers/community-providers/langdb) (`@langdb/vercel-provider`) -- [Dify Provider](/providers/community-providers/dify) (`dify-ai-provider`) -- [Sarvam Provider](/providers/community-providers/sarvam) (`sarvam-ai-provider`) -- [Claude Code Provider](/providers/community-providers/claude-code) (`ai-sdk-provider-claude-code`) -- [Browser AI Provider](/providers/community-providers/browser-ai) (`browser-ai`) -- [Gemini CLI Provider](/providers/community-providers/gemini-cli) (`ai-sdk-provider-gemini-cli`) -- [A2A Provider](/providers/community-providers/a2a) (`a2a-ai-provider`) -- [SAP-AI Provider](/providers/community-providers/sap-ai) (`@mymediset/sap-ai-provider`) -- [AI/ML API Provider](/providers/community-providers/aimlapi) (`@ai-ml.api/aimlapi-vercel-ai`) -- [MCP Sampling Provider](/providers/community-providers/mcp-sampling) (`@mcpc-tech/mcp-sampling-ai-provider`) -- [ACP Provider](/providers/community-providers/acp) (`@mcpc-tech/acp-ai-provider`) -- [OpenCode Provider](/providers/community-providers/opencode-sdk) (`ai-sdk-provider-opencode-sdk`) -- [Codex CLI Provider](/providers/community-providers/codex-cli) (`ai-sdk-provider-codex-cli`) -- [Soniox Provider](/providers/community-providers/soniox) (`@soniox/vercel-ai-sdk-provider`) -- [Zhipu (Z.AI) Provider](/providers/community-providers/zhipu) (`zhipu-ai-provider`) -- [OLLM Provider](/providers/community-providers/ollm) (`@ofoundation/ollm`) - -## Self-Hosted Models - -You can access self-hosted models with the following providers: - -- [Ollama Provider](/providers/community-providers/ollama) -- [LM Studio](/providers/openai-compatible-providers/lmstudio) -- [Baseten](/providers/ai-sdk-providers/baseten) -- [Browser AI](/providers/community-providers/browser-ai) - -Additionally, any self-hosted provider that supports the OpenAI specification can be used with the [OpenAI Compatible Provider](/providers/openai-compatible-providers). - -## Model Capabilities - -The AI providers support different language models with various capabilities. -Here are the capabilities of popular models: - -| Provider | Model | Image Input | Object Generation | Tool Usage | Tool Streaming | -| -------------------------------------------------- | ------------------------------------------- | ------------------- | ------------------- | ------------------- | ------------------- | -| [xAI Grok](/providers/ai-sdk-providers/xai) | `grok-4` | | | | | -| [xAI Grok](/providers/ai-sdk-providers/xai) | `grok-3` | | | | | -| [xAI Grok](/providers/ai-sdk-providers/xai) | `grok-3-mini` | | | | | -| [Vercel](/providers/ai-sdk-providers/vercel) | `v0-1.0-md` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.4-pro` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.4` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.4-mini` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.4-nano` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.3-chat-latest` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.2-pro` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.2-chat-latest` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.2` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5-mini` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5-nano` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.1-chat-latest` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.1-codex-mini` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.1-codex` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5.1` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5-codex` | | | | | -| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5-chat-latest` | | | | | -| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-opus-4-6` | | | | | -| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-sonnet-4-6` | | | | | -| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-opus-4-5` | | | | | -| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-opus-4-1` | | | | | -| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-opus-4-0` | | | | | -| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-sonnet-4-0` | | | | | -| [Mistral](/providers/ai-sdk-providers/mistral) | `pixtral-large-latest` | | | | | -| [Mistral](/providers/ai-sdk-providers/mistral) | `mistral-large-latest` | | | | | -| [Mistral](/providers/ai-sdk-providers/mistral) | `mistral-medium-latest` | | | | | -| [Mistral](/providers/ai-sdk-providers/mistral) | `mistral-medium-2505` | | | | | -| [Mistral](/providers/ai-sdk-providers/mistral) | `mistral-small-latest` | | | | | -| [Mistral](/providers/ai-sdk-providers/mistral) | `pixtral-12b-2409` | | | | | -| [DeepSeek](/providers/ai-sdk-providers/deepseek) | `deepseek-chat` | | | | | -| [DeepSeek](/providers/ai-sdk-providers/deepseek) | `deepseek-reasoner` | | | | | -| [Cerebras](/providers/ai-sdk-providers/cerebras) | `llama3.1-8b` | | | | | -| [Cerebras](/providers/ai-sdk-providers/cerebras) | `llama3.1-70b` | | | | | -| [Cerebras](/providers/ai-sdk-providers/cerebras) | `llama3.3-70b` | | | | | -| [Groq](/providers/ai-sdk-providers/groq) | `meta-llama/llama-4-scout-17b-16e-instruct` | | | | | -| [Groq](/providers/ai-sdk-providers/groq) | `llama-3.3-70b-versatile` | | | | | -| [Groq](/providers/ai-sdk-providers/groq) | `llama-3.1-8b-instant` | | | | | -| [Groq](/providers/ai-sdk-providers/groq) | `mixtral-8x7b-32768` | | | | | -| [Groq](/providers/ai-sdk-providers/groq) | `gemma2-9b-it` | | | | | - - - This table is not exhaustive. Additional models can be found in the provider - documentation pages and on the provider websites. - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/03-prompts.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/03-prompts.mdx deleted file mode 100644 index 712cf0eea..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/03-prompts.mdx +++ /dev/null @@ -1,616 +0,0 @@ ---- -title: Prompts -description: Learn about the Prompt structure used in the AI SDK. ---- - -# Prompts - -Prompts are instructions that you give a [large language model (LLM)](/docs/foundations/overview#large-language-models) to tell it what to do. -It's like when you ask someone for directions; the clearer your question, the better the directions you'll get. - -Many LLM providers offer complex interfaces for specifying prompts. They involve different roles and message types. -While these interfaces are powerful, they can be hard to use and understand. - -In order to simplify prompting, the AI SDK supports text, message, and system prompts. - -## Text Prompts - -Text prompts are strings. -They are ideal for simple generation use cases, -e.g. repeatedly generating content for variants of the same prompt text. - -You can set text prompts using the `prompt` property made available by AI SDK functions like [`streamText`](/docs/reference/ai-sdk-core/stream-text) or [`generateText`](/docs/reference/ai-sdk-core/generate-text). -You can structure the text in any way and inject variables, e.g. using a template literal. - -```ts highlight="3" -const result = await generateText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', -}); -``` - -You can also use template literals to provide dynamic data to your prompt. - -```ts highlight="3-5" -const result = await generateText({ - model: __MODEL__, - prompt: - `I am planning a trip to ${destination} for ${lengthOfStay} days. ` + - `Please suggest the best tourist activities for me to do.`, -}); -``` - -## System Prompts - -System prompts are the initial set of instructions given to models that help guide and constrain the models' behaviors and responses. -You can set system prompts using the `system` property. -System prompts work with both the `prompt` and the `messages` properties. - -```ts highlight="3-6" -const result = await generateText({ - model: __MODEL__, - system: - `You help planning travel itineraries. ` + - `Respond to the users' request with a list ` + - `of the best stops to make in their destination.`, - prompt: - `I am planning a trip to ${destination} for ${lengthOfStay} days. ` + - `Please suggest the best tourist activities for me to do.`, -}); -``` - - - When you use a message prompt, you can also use system messages instead of a - system prompt. - - -## Message Prompts - -A message prompt is an array of user, assistant, and tool messages. -They are great for chat interfaces and more complex, multi-modal prompts. -You can use the `messages` property to set message prompts. - -Each message has a `role` and a `content` property. The content can either be text (for user and assistant messages), or an array of relevant parts (data) for that message type. - -```ts highlight="3-7" -const result = await generateText({ - model: __MODEL__, - messages: [ - { role: 'user', content: 'Hi!' }, - { role: 'assistant', content: 'Hello, how can I help?' }, - { role: 'user', content: 'Where can I buy the best Currywurst in Berlin?' }, - ], -}); -``` - -Instead of sending a text in the `content` property, you can send an array of parts that includes a mix of text and other content parts. - - - Not all language models support all message and content types. For example, - some models might not be capable of handling multi-modal inputs or tool - messages. [Learn more about the capabilities of select - models](./providers-and-models#model-capabilities). - - -### Provider Options - -You can pass through additional provider-specific metadata to enable provider-specific functionality at 3 levels. - -#### Function Call Level - -Functions like [`streamText`](/docs/reference/ai-sdk-core/stream-text#provider-options) or [`generateText`](/docs/reference/ai-sdk-core/generate-text#provider-options) accept a `providerOptions` property. - -Adding provider options at the function call level should be used when you do not need granular control over where the provider options are applied. - -```ts -const { text } = await generateText({ - model: azure('your-deployment-name'), - providerOptions: { - openai: { - reasoningEffort: 'low', - }, - }, -}); -``` - -#### Message Level - -For granular control over applying provider options at the message level, you can pass `providerOptions` to the message object: - -```ts -import { ModelMessage } from 'ai'; - -const messages: ModelMessage[] = [ - { - role: 'system', - content: 'Cached system message', - providerOptions: { - // Sets a cache control breakpoint on the system message - anthropic: { cacheControl: { type: 'ephemeral' } }, - }, - }, -]; -``` - -#### Message Part Level - -Certain provider-specific options require configuration at the message part level: - -```ts -import { ModelMessage } from 'ai'; - -const messages: ModelMessage[] = [ - { - role: 'user', - content: [ - { - type: 'text', - text: 'Describe the image in detail.', - providerOptions: { - openai: { imageDetail: 'low' }, - }, - }, - { - type: 'image', - image: - 'https://github.com/vercel/ai/blob/main/examples/ai-functions/data/comic-cat.png?raw=true', - // Sets image detail configuration for image part: - providerOptions: { - openai: { imageDetail: 'low' }, - }, - }, - ], - }, -]; -``` - - - AI SDK UI hooks like [`useChat`](/docs/reference/ai-sdk-ui/use-chat) return - arrays of `UIMessage` objects, which do not support provider options. We - recommend using the - [`convertToModelMessages`](/docs/reference/ai-sdk-ui/convert-to-model-messages) - function to convert `UIMessage` objects to - [`ModelMessage`](/docs/reference/ai-sdk-core/model-message) objects before - applying or appending message(s) or message parts with `providerOptions`. - - -### User Messages - -#### Text Parts - -Text content is the most common type of content. It is a string that is passed to the model. - -If you only need to send text content in a message, the `content` property can be a string, -but you can also use it to send multiple content parts. - -```ts highlight="7-10" -const result = await generateText({ - model: __MODEL__, - messages: [ - { - role: 'user', - content: [ - { - type: 'text', - text: 'Where can I buy the best Currywurst in Berlin?', - }, - ], - }, - ], -}); -``` - -#### Image Parts - -User messages can include image parts. An image can be one of the following: - -- base64-encoded image: - - `string` with base-64 encoded content - - data URL `string`, e.g. `data:image/png;base64,...` -- binary image: - - `ArrayBuffer` - - `Uint8Array` - - `Buffer` -- URL: - - http(s) URL `string`, e.g. `https://example.com/image.png` - - `URL` object, e.g. `new URL('https://example.com/image.png')` - -##### Example: Binary image (Buffer) - -```ts highlight="8-11" -const result = await generateText({ - model, - messages: [ - { - role: 'user', - content: [ - { type: 'text', text: 'Describe the image in detail.' }, - { - type: 'image', - image: fs.readFileSync('./data/comic-cat.png'), - }, - ], - }, - ], -}); -``` - -##### Example: Base-64 encoded image (string) - -```ts highlight="8-11" -const result = await generateText({ - model: __MODEL__, - messages: [ - { - role: 'user', - content: [ - { type: 'text', text: 'Describe the image in detail.' }, - { - type: 'image', - image: fs.readFileSync('./data/comic-cat.png').toString('base64'), - }, - ], - }, - ], -}); -``` - -##### Example: Image URL (string) - -```ts highlight="8-12" -const result = await generateText({ - model: __MODEL__, - messages: [ - { - role: 'user', - content: [ - { type: 'text', text: 'Describe the image in detail.' }, - { - type: 'image', - image: - 'https://github.com/vercel/ai/blob/main/examples/ai-functions/data/comic-cat.png?raw=true', - }, - ], - }, - ], -}); -``` - -#### File Parts - - - Only a few providers and models currently support file parts: [Google - Generative AI](/providers/ai-sdk-providers/google-generative-ai), [Google - Vertex AI](/providers/ai-sdk-providers/google-vertex), - [OpenAI](/providers/ai-sdk-providers/openai) (for `wav` and `mp3` audio with - `gpt-4o-audio-preview`), [Anthropic](/providers/ai-sdk-providers/anthropic), - [OpenAI](/providers/ai-sdk-providers/openai) (for `pdf`). - - -User messages can include file parts. A file can be one of the following: - -- base64-encoded file: - - `string` with base-64 encoded content - - data URL `string`, e.g. `data:image/png;base64,...` -- binary data: - - `ArrayBuffer` - - `Uint8Array` - - `Buffer` -- URL: - - http(s) URL `string`, e.g. `https://example.com/some.pdf` - - `URL` object, e.g. `new URL('https://example.com/some.pdf')` - -You need to specify the MIME type of the file you are sending. - -##### Example: PDF file from Buffer - -```ts highlight="12-15" -import { google } from '@ai-sdk/google'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: google('gemini-2.5-flash'), - messages: [ - { - role: 'user', - content: [ - { type: 'text', text: 'What is the file about?' }, - { - type: 'file', - mediaType: 'application/pdf', - data: fs.readFileSync('./data/example.pdf'), - filename: 'example.pdf', // optional, not used by all providers - }, - ], - }, - ], -}); -``` - -##### Example: mp3 audio file from Buffer - -```ts highlight="12-14" -import { openai } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-4o-audio-preview'), - messages: [ - { - role: 'user', - content: [ - { type: 'text', text: 'What is the audio saying?' }, - { - type: 'file', - mediaType: 'audio/mpeg', - data: fs.readFileSync('./data/galileo.mp3'), - }, - ], - }, - ], -}); -``` - -#### Custom Download Function (Experimental) - -You can use custom download functions to implement throttling, retries, authentication, caching, and more. - -The default download implementation automatically downloads files in parallel when they are not supported by the model. - -Custom download function can be passed via the `experimental_download` property: - -```ts -const result = await generateText({ - model: __MODEL__, - experimental_download: async ( - requestedDownloads: Array<{ - url: URL; - isUrlSupportedByModel: boolean; - }>, - ): PromiseLike< - Array<{ - data: Uint8Array; - mediaType: string | undefined; - } | null> - > => { - // ... download the files and return an array with similar order - }, - messages: [ - { - role: 'user', - content: [ - { - type: 'file', - data: new URL('https://api.company.com/private/document.pdf'), - mediaType: 'application/pdf', - }, - ], - }, - ], -}); -``` - - - The `experimental_download` option is experimental and may change in future - releases. - - -### Assistant Messages - -Assistant messages are messages that have a role of `assistant`. -They are typically previous responses from the assistant -and can contain text, reasoning, and tool call parts. - -#### Example: Assistant message with text content - -```ts highlight="5" -const result = await generateText({ - model: __MODEL__, - messages: [ - { role: 'user', content: 'Hi!' }, - { role: 'assistant', content: 'Hello, how can I help?' }, - ], -}); -``` - -#### Example: Assistant message with text content in array - -```ts highlight="7" -const result = await generateText({ - model: __MODEL__, - messages: [ - { role: 'user', content: 'Hi!' }, - { - role: 'assistant', - content: [{ type: 'text', text: 'Hello, how can I help?' }], - }, - ], -}); -``` - -#### Example: Assistant message with tool call content - -```ts highlight="7-14" -const result = await generateText({ - model: __MODEL__, - messages: [ - { role: 'user', content: 'How many calories are in this block of cheese?' }, - { - role: 'assistant', - content: [ - { - type: 'tool-call', - toolCallId: '12345', - toolName: 'get-nutrition-data', - input: { cheese: 'Roquefort' }, - }, - ], - }, - ], -}); -``` - -#### Example: Assistant message with file content - - - This content part is for model-generated files. Only a few models support - this, and only for file types that they can generate. - - -```ts highlight="9-11" -const result = await generateText({ - model: __MODEL__, - messages: [ - { role: 'user', content: 'Generate an image of a roquefort cheese!' }, - { - role: 'assistant', - content: [ - { - type: 'file', - mediaType: 'image/png', - data: fs.readFileSync('./data/roquefort.jpg'), - }, - ], - }, - ], -}); -``` - -### Tool messages - - - [Tools](/docs/foundations/tools) (also known as function calling) are programs - that you can provide an LLM to extend its built-in functionality. This can be - anything from calling an external API to calling functions within your UI. - Learn more about Tools in [the next section](/docs/foundations/tools). - - -For models that support [tool](/docs/foundations/tools) calls, assistant messages can contain tool call parts, and tool messages can contain tool output parts. -A single assistant message can call multiple tools, and a single tool message can contain multiple tool results. - -```ts highlight="14-42" -const result = await generateText({ - model: __MODEL__, - messages: [ - { - role: 'user', - content: [ - { - type: 'text', - text: 'How many calories are in this block of cheese?', - }, - { type: 'image', image: fs.readFileSync('./data/roquefort.jpg') }, - ], - }, - { - role: 'assistant', - content: [ - { - type: 'tool-call', - toolCallId: '12345', - toolName: 'get-nutrition-data', - input: { cheese: 'Roquefort' }, - }, - // there could be more tool calls here (parallel calling) - ], - }, - { - role: 'tool', - content: [ - { - type: 'tool-result', - toolCallId: '12345', // needs to match the tool call id - toolName: 'get-nutrition-data', - output: { - type: 'json', - value: { - name: 'Cheese, roquefort', - calories: 369, - fat: 31, - protein: 22, - }, - }, - }, - // there could be more tool results here (parallel calling) - ], - }, - ], -}); -``` - -#### Multi-modal Tool Results - -Tool results can be multi-part and multi-modal, e.g. a text and an image. -You can use `output: { type: 'content', value: [...] }` to specify multi-part tool results. - -```ts highlight="14-27" -const result = await generateText({ - model: __MODEL__, - messages: [ - // ... - { - role: 'tool', - content: [ - { - type: 'tool-result', - toolCallId: '12345', // needs to match the tool call id - toolName: 'get-nutrition-data', - // for models that do not support multi-part tool results, - // you can include a regular output part: - output: { - type: 'json', - value: { - name: 'Cheese, roquefort', - calories: 369, - fat: 31, - protein: 22, - }, - }, - }, - { - type: 'tool-result', - toolCallId: '12345', // needs to match the tool call id - toolName: 'get-nutrition-data', - // for models that support multi-part tool results, - // you can include a multi-part content part: - output: { - type: 'content', - value: [ - { - type: 'text', - text: 'Here is the nutrition data for the cheese:', - }, - { - type: 'image-data', - data: fs - .readFileSync('./data/roquefort-nutrition-data.png') - .toString('base64'), - mediaType: 'image/png', - }, - ], - }, - }, - ], - }, - ], -}); -``` - -### System Messages - -System messages are messages that are sent to the model before the user messages to guide the assistant's behavior. -You can alternatively use the `system` property. - -```ts highlight="4" -const result = await generateText({ - model: __MODEL__, - messages: [ - { role: 'system', content: 'You help planning travel itineraries.' }, - { - role: 'user', - content: - 'I am planning a trip to Berlin for 3 days. Please suggest the best tourist activities for me to do.', - }, - ], -}); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/04-tools.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/04-tools.mdx deleted file mode 100644 index 1a400842a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/04-tools.mdx +++ /dev/null @@ -1,251 +0,0 @@ ---- -title: Tools -description: Learn about tools with the AI SDK. ---- - -# Tools - -While [large language models (LLMs)](/docs/foundations/overview#large-language-models) have incredible generation capabilities, -they struggle with discrete tasks (e.g. mathematics) and interacting with the outside world (e.g. getting the weather). - -Tools are actions that an LLM can invoke. -The results of these actions can be reported back to the LLM to be considered in the next response. - -For example, when you ask an LLM for the "weather in London", and there is a weather tool available, it could call a tool -with London as the argument. The tool would then fetch the weather data and return it to the LLM. The LLM can then use this -information in its response. - -## What is a tool? - -A tool is an object that can be called by the model to perform a specific task. -You can use tools with [`generateText`](/docs/reference/ai-sdk-core/generate-text) -and [`streamText`](/docs/reference/ai-sdk-core/stream-text) by passing one or more tools to the `tools` parameter. - -A tool consists of three properties: - -- **`description`**: An optional description of the tool that can influence when the tool is picked. -- **`inputSchema`**: A [Zod schema](/docs/reference/ai-sdk-core/zod-schema) or a [JSON schema](/docs/reference/ai-sdk-core/json-schema) that defines the input required for the tool to run. The schema is consumed by the LLM, and also used to validate the LLM tool calls. -- **`execute`**: An optional async function that is called with the arguments from the tool call. - - - `streamUI` uses UI generator tools with a `generate` function that can return - React components. - - -If the LLM decides to use a tool, it will generate a tool call. -Tools with an `execute` function are run automatically when these calls are generated. -The output of the tool calls are returned using tool result objects. - -You can automatically pass tool results back to the LLM -using [multi-step calls](/docs/ai-sdk-core/tools-and-tool-calling#multi-step-calls) with `streamText` and `generateText`. - -## Types of Tools - -The AI SDK supports three types of tools, each with different trade-offs: - -### Custom Tools - -Custom tools are tools you define entirely yourself, including the description, input schema, and execute function. They are provider-agnostic and give you full control. - -```ts -import { tool } from 'ai'; -import { z } from 'zod'; - -const weatherTool = tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - // Your implementation - return { temperature: 72, conditions: 'sunny' }; - }, -}); -``` - -**When to use**: When you need full control, want provider portability, or are implementing application-specific functionality. - -### Provider-Defined Tools - -Provider-defined tools are tools where the provider specifies the tool's `inputSchema` and `description`, but you provide the `execute` function. These are sometimes called "client tools" because execution happens on your side. - -Examples include Anthropic's `bash` and `text_editor` tools. The model has been specifically trained to use these tools effectively, which can result in better performance for supported tasks. - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: anthropic('claude-opus-4-5'), - tools: { - bash: anthropic.tools.bash_20250124({ - execute: async ({ command }) => { - // Your implementation to run the command - return runCommand(command); - }, - }), - }, - prompt: 'List files in the current directory', -}); -``` - -**When to use**: When the provider offers a tool the model is trained to use well, and you want better performance for that specific task. - -### Provider-Executed Tools - -Provider-executed tools are tools that run entirely on the provider's servers. You configure them, but the provider handles execution. These are sometimes called "server-side tools". - -Examples include OpenAI's web search and Anthropic's code execution. These provide out-of-the-box functionality without requiring you to set up infrastructure. - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5.2'), - tools: { - web_search: openai.tools.webSearch(), - }, - prompt: 'What happened in the news today?', -}); -``` - -**When to use**: When you want powerful functionality (like web search or sandboxed code execution) without managing the infrastructure yourself. - -### Comparison - -| Aspect | Custom Tools | Provider-Defined Tools | Provider-Executed Tools | -| ------------------ | ------------------------ | ---------------------- | ----------------------- | -| **Execution** | Your code | Your code | Provider's servers | -| **Schema** | You define | Provider defines | Provider defines | -| **Portability** | Works with any provider | Provider-specific | Provider-specific | -| **Model Training** | General tool use | Optimized for the tool | Optimized for the tool | -| **Setup** | You implement everything | You implement execute | Configuration only | - - - Provider-defined and provider-executed tools are documented in each provider's - page. See [Anthropic Provider](/providers/ai-sdk-providers/anthropic) and - [OpenAI Provider](/providers/ai-sdk-providers/openai) for examples. - - -## Schemas - -Schemas are used to define and validate the [tool input](/docs/ai-sdk-core/tools-and-tool-calling), tools outputs, and structured output generation. - -The AI SDK supports the following schemas: - -- [Zod](https://zod.dev/) v3 and v4 directly or via [`zodSchema()`](/docs/reference/ai-sdk-core/zod-schema) -- [Valibot](https://valibot.dev/) via [`valibotSchema()`](/docs/reference/ai-sdk-core/valibot-schema) from `@ai-sdk/valibot` -- [Standard JSON Schema](https://standardschema.dev/json-schema) compatible schemas -- Raw JSON schemas via [`jsonSchema()`](/docs/reference/ai-sdk-core/json-schema) - - - You can also use schemas for structured output generation with - [`generateText`](/docs/reference/ai-sdk-core/generate-text) and - [`streamText`](/docs/reference/ai-sdk-core/stream-text) using the `output` - setting. - - -## Tool Packages - -Given tools are JavaScript objects, they can be packaged and distributed through npm like any other library. This makes it easy to share reusable tools across projects and with the community. - -### Using Ready-Made Tool Packages - -Install a tool package and import the tools you need: - -```bash -pnpm add some-tool-package -``` - -Then pass them directly to `generateText`, `streamText`, or your agent definition: - -```ts highlight="2, 8" -import { generateText, stepCountIs } from 'ai'; -import { searchTool } from 'some-tool-package'; - -const { text } = await generateText({ - model: 'anthropic/claude-haiku-4.5', - prompt: 'When was Vercel Ship AI?', - tools: { - webSearch: searchTool, - }, - stopWhen: stepCountIs(10), -}); -``` - -### Publishing Your Own Tools - -You can publish your own tool packages to npm for others to use. Simply export your tool objects from your package: - -```ts filename="my-tools/index.ts" -import { tool } from 'ai'; -import { z } from 'zod'; - -export const myTool = tool({ - description: 'A helpful tool', - inputSchema: z.object({ - query: z.string(), - }), - execute: async ({ query }) => { - // your tool logic - return result; - }, -}); -``` - -Anyone can then install and use your tools by importing them. - -To get started, you can use the [AI SDK Tool Package Template](https://github.com/vercel-labs/ai-sdk-tool-as-package-template) which provides a ready-to-use starting point for publishing your own tools. - -## Toolsets - -When you work with tools, you typically need a mix of application-specific tools and general-purpose tools. The community has created various toolsets and resources to help you build and use tools. - -### Ready-to-Use Tool Packages - -These packages provide pre-built tools you can install and use immediately: - -- **[@exalabs/ai-sdk](https://www.npmjs.com/package/@exalabs/ai-sdk)** - Web search tool that lets AI search the web and get real-time information. -- **[@parallel-web/ai-sdk-tools](https://www.npmjs.com/package/@parallel-web/ai-sdk-tools)** - Web search and extract tools powered by Parallel Web API for real-time information and content extraction. -- **[@perplexity-ai/ai-sdk](https://www.npmjs.com/package/@perplexity-ai/ai-sdk)** - Search the web with real-time results and advanced filtering powered by Perplexity's Search API. -- **[@tavily/ai-sdk](https://www.npmjs.com/package/@tavily/ai-sdk)** - Search, extract, crawl, and map tools for enterprise-grade agents to explore the web in real-time. -- **[Stripe agent tools](https://docs.stripe.com/agents?framework=vercel)** - Tools for interacting with Stripe. -- **[StackOne ToolSet](https://docs.stackone.com/agents/typescript/frameworks/vercel-ai-sdk)** - Agentic integrations for hundreds of [enterprise SaaS](https://www.stackone.com/integrations) platforms. -- **[agentic](https://docs.agentic.so/marketplace/ts-sdks/ai-sdk)** - A collection of 20+ tools that connect to external APIs such as [Exa](https://exa.ai/) or [E2B](https://e2b.dev/). -- **[Amazon Bedrock AgentCore](https://github.com/aws/bedrock-agentcore-sdk-typescript)** - Fully managed AI agent services including [**Browser**](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/built-in-tools.html) (a fast and secure cloud-based browser runtime to enable agents to interact with web applications, fill forms, navigate websites, and extract information) and [**Code Interpreter**](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/built-in-tools.html) (an isolated sandbox environment for agents to execute code in Python, JavaScript, and TypeScript, enhancing accuracy and expanding ability to solve complex end-to-end tasks). -- **[@airweave/vercel-ai-sdk](https://www.npmjs.com/package/@airweave/vercel-ai-sdk)** - Unified semantic search across 35+ data sources (Notion, Slack, Google Drive, databases, and more) for AI agents. -- **[Composio](https://docs.composio.dev/providers/vercel)** - 250+ tools like GitHub, Gmail, Salesforce and [more](https://composio.dev/tools). -- **[JigsawStack](http://www.jigsawstack.com/docs/integration/vercel)** - Over 30+ small custom fine-tuned models available for specific uses. -- **[AI Tools Registry](https://ai-tools-registry.vercel.app)** - A Shadcn-compatible tool definitions and components registry for the AI SDK. -- **[Toolhouse](https://docs.toolhouse.ai/toolhouse/toolhouse-sdk/using-vercel-ai)** - AI function-calling in 3 lines of code for over 25 different actions. -- **[bash-tool](https://www.npmjs.com/package/bash-tool)** - Provides `bash`, `readFile`, and `writeFile` tools for AI agents. Supports [@vercel/sandbox](https://vercel.com/docs/vercel-sandbox) for full VM isolation. - -### MCP Tools - -These are pre-built tools available as MCP servers: - -- **[Smithery](https://smithery.ai/docs/integrations/vercel_ai_sdk)** - An open marketplace of 6,000+ MCPs, including [Browserbase](https://browserbase.com/) and [Exa](https://exa.ai/). -- **[Pipedream](https://pipedream.com/docs/connect/mcp/ai-frameworks/vercel-ai-sdk)** - Developer toolkit that lets you easily add 3,000+ integrations to your app or AI agent. -- **[Apify](https://docs.apify.com/platform/integrations/vercel-ai-sdk)** - Apify provides a [marketplace](https://apify.com/store) of thousands of tools for web scraping, data extraction, and browser automation. - -### Tool Building Tutorials - -These tutorials and guides help you build your own tools that integrate with specific services: - -- **[browserbase](https://docs.browserbase.com/integrations/vercel/introduction#vercel-ai-integration)** - Tutorial for building browser tools that run a headless browser. -- **[browserless](https://docs.browserless.io/ai-integrations/vercel-ai-sdk)** - Guide for integrating browser automation (self-hosted or cloud-based). -- **[AI Tool Maker](https://github.com/nihaocami/ai-tool-maker)** - A CLI utility to generate AI SDK tools from OpenAPI specs. -- **[Interlify](https://www.interlify.com/docs/integrate-with-vercel-ai)** - Guide for converting APIs into tools. -- **[DeepAgent](https://deepagent.amardeep.space/docs/vercel-ai-sdk)** - A suite of 50+ AI tools and integrations, seamlessly connecting with APIs like Tavily, E2B, Airtable and [more](https://deepagent.amardeep.space/docs). - - - Do you have open source tools or tool libraries that are compatible with the - AI SDK? Please [file a pull request](https://github.com/vercel/ai/pulls) to - add them to this list. - - -## Learn more - -The AI SDK Core [Tool Calling](/docs/ai-sdk-core/tools-and-tool-calling) -and [Agents](/docs/agents) documentation has more information about tools and tool calling. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/05-streaming.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/05-streaming.mdx deleted file mode 100644 index a4434b08f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/05-streaming.mdx +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Streaming -description: Why use streaming for AI applications? ---- - -# Streaming - -Streaming conversational text UIs (like ChatGPT) have gained massive popularity over the past few months. This section explores the benefits and drawbacks of streaming and blocking interfaces. - -[Large language models (LLMs)](/docs/foundations/overview#large-language-models) are extremely powerful. However, when generating long outputs, they can be very slow compared to the latency you're likely used to. If you try to build a traditional blocking UI, your users might easily find themselves staring at loading spinners for 5, 10, even up to 40s waiting for the entire LLM response to be generated. This can lead to a poor user experience, especially in conversational applications like chatbots. Streaming UIs can help mitigate this issue by **displaying parts of the response as they become available**. - -
- - - - - - -
- -## Real-world Examples - -Here are 2 examples that illustrate how streaming UIs can improve user experiences in a real-world setting – the first uses a blocking UI, while the second uses a streaming UI. - -### Blocking UI - - - -### Streaming UI - - - -As you can see, the streaming UI is able to start displaying the response much faster than the blocking UI. This is because the blocking UI has to wait for the entire response to be generated before it can display anything, while the streaming UI can display parts of the response as they become available. - -While streaming interfaces can greatly enhance user experiences, especially with larger language models, they aren't always necessary or beneficial. If you can achieve your desired functionality using a smaller, faster model without resorting to streaming, this route can often lead to simpler and more manageable development processes. - -However, regardless of the speed of your model, the AI SDK is designed to make implementing streaming UIs as simple as possible. In the example below, we stream text generation in under 10 lines of code using the SDK's [`streamText`](/docs/reference/ai-sdk-core/stream-text) function: - -```ts -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const { textStream } = streamText({ - model: __MODEL__, - prompt: 'Write a poem about embedding models.', -}); - -for await (const textPart of textStream) { - console.log(textPart); -} -``` - -For an introduction to streaming UIs and the AI SDK, check out our [Getting Started guides](/docs/getting-started). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/06-provider-options.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/06-provider-options.mdx deleted file mode 100644 index 44201184a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/06-provider-options.mdx +++ /dev/null @@ -1,337 +0,0 @@ ---- -title: Provider Options -description: Learn how to use provider-specific options to control reasoning, caching, and other advanced features. ---- - -# Provider Options - -Provider options let you pass provider-specific configuration that goes beyond the [standard settings](/docs/ai-sdk-core/settings) shared by all providers. They are set via the `providerOptions` property on functions like `generateText` and `streamText`. - -```ts -const result = await generateText({ - model: openai('gpt-5.2'), - prompt: 'Explain quantum entanglement.', - providerOptions: { - openai: { - reasoningEffort: 'low', - }, - }, -}); -``` - -Provider options are namespaced by the provider name (e.g. `openai`, `anthropic`) so you can even include options for multiple providers in the same call — only the options matching the active provider are used. See [Prompts: Provider Options](/docs/foundations/prompts#provider-options) for details on applying options at the message and message-part level. - -## Common Provider Options - -The sections below cover the most frequently used provider options, focusing on reasoning and output control for OpenAI and Anthropic. For a complete reference, see the individual provider pages: - -- [OpenAI provider options](/providers/ai-sdk-providers/openai) -- [Anthropic provider options](/providers/ai-sdk-providers/anthropic) - ---- - -## OpenAI - -### Reasoning Effort - -For reasoning models (e.g. `o3`, `o4-mini`, `gpt-5.2`), `reasoningEffort` controls how much internal reasoning the model performs before responding. Lower values are faster and cheaper; higher values produce more thorough answers. - -```ts -import { - openai, - type OpenAILanguageModelResponsesOptions, -} from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const { text, usage, providerMetadata } = await generateText({ - model: openai('gpt-5.2'), - prompt: 'Invent a new holiday and describe its traditions.', - providerOptions: { - openai: { - reasoningEffort: 'low', // 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' - } satisfies OpenAILanguageModelResponsesOptions, - }, -}); - -console.log('Reasoning tokens:', providerMetadata?.openai?.reasoningTokens); -``` - -| Value | Behavior | -| ----------- | ------------------------------------------ | -| `'none'` | No reasoning (GPT-5.1 models only) | -| `'minimal'` | Bare-minimum reasoning | -| `'low'` | Fast, concise reasoning | -| `'medium'` | Balanced (default) | -| `'high'` | Thorough reasoning | -| `'xhigh'` | Maximum reasoning (GPT-5.1-Codex-Max only) | - - - `'none'` and `'xhigh'` are only supported on specific models. Using them with - unsupported models will result in an error. - - -### Reasoning Summary - -When working with reasoning models, you may want to see _how_ the model arrived at its answer. The `reasoningSummary` option surfaces the model's thought process. - -#### Streaming - -```ts -import { - openai, - type OpenAILanguageModelResponsesOptions, -} from '@ai-sdk/openai'; -import { streamText } from 'ai'; - -const result = streamText({ - model: openai('gpt-5.2'), - prompt: 'Tell me about the Mission burrito debate in San Francisco.', - providerOptions: { - openai: { - reasoningSummary: 'detailed', // 'auto' | 'detailed' - } satisfies OpenAILanguageModelResponsesOptions, - }, -}); - -for await (const part of result.fullStream) { - if (part.type === 'reasoning') { - console.log(`Reasoning: ${part.textDelta}`); - } else if (part.type === 'text-delta') { - process.stdout.write(part.textDelta); - } -} -``` - -#### Non-streaming - -```ts -import { - openai, - type OpenAILanguageModelResponsesOptions, -} from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5.2'), - prompt: 'Tell me about the Mission burrito debate in San Francisco.', - providerOptions: { - openai: { - reasoningSummary: 'auto', - } satisfies OpenAILanguageModelResponsesOptions, - }, -}); - -console.log('Reasoning:', result.reasoning); -``` - -| Value | Behavior | -| ------------ | ------------------------------ | -| `'auto'` | Condensed summary of reasoning | -| `'detailed'` | Comprehensive reasoning output | - -### Text Verbosity - -Control the length and detail of the model's text response independently of reasoning: - -```ts -import { - openai, - type OpenAILanguageModelResponsesOptions, -} from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5-mini'), - prompt: 'Write a poem about a boy and his first pet dog.', - providerOptions: { - openai: { - textVerbosity: 'low', // 'low' | 'medium' | 'high' - } satisfies OpenAILanguageModelResponsesOptions, - }, -}); -``` - -| Value | Behavior | -| ---------- | -------------------------------- | -| `'low'` | Terse, minimal responses | -| `'medium'` | Balanced detail (default) | -| `'high'` | Verbose, comprehensive responses | - ---- - -## Anthropic - -### Thinking (Extended Reasoning) - -Anthropic's thinking feature gives Claude models a dedicated "thinking" phase before they respond. You enable it by providing a `thinking` object with a token budget. - -```ts -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const { text, reasoning, reasoningText } = await generateText({ - model: anthropic('claude-opus-4-20250514'), - prompt: 'How many people will live in the world in 2040?', - providerOptions: { - anthropic: { - thinking: { type: 'enabled', budgetTokens: 12000 }, - } satisfies AnthropicLanguageModelOptions, - }, -}); - -console.log('Reasoning:', reasoningText); -console.log('Answer:', text); -``` - -The `budgetTokens` value sets the upper limit on how many tokens the model can use for its internal reasoning. Higher budgets allow deeper reasoning but increase latency and cost. - - - Thinking is supported on `claude-opus-4-20250514`, `claude-sonnet-4-20250514`, - and `claude-sonnet-4-5-20250929` models. - - -### Effort - -The `effort` option provides a simpler way to control reasoning depth without specifying a token budget. It affects thinking, text responses, and function calls. - -```ts -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const { text, usage } = await generateText({ - model: anthropic('claude-opus-4-20250514'), - prompt: 'How many people will live in the world in 2040?', - providerOptions: { - anthropic: { - effort: 'low', // 'low' | 'medium' | 'high' - } satisfies AnthropicLanguageModelOptions, - }, -}); -``` - -| Value | Behavior | -| ---------- | ------------------------------------ | -| `'low'` | Minimal reasoning, fastest responses | -| `'medium'` | Balanced reasoning | -| `'high'` | Thorough reasoning (default) | - -### Fast Mode - -For `claude-opus-4-6`, the `speed` option enables approximately 2.5x faster output token speeds: - -```ts -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: anthropic('claude-opus-4-6'), - prompt: 'Write a short poem about the sea.', - providerOptions: { - anthropic: { - speed: 'fast', // 'fast' | 'standard' - } satisfies AnthropicLanguageModelOptions, - }, -}); -``` - ---- - -## Combining Options - -You can combine multiple provider options in a single call. For example, using both reasoning effort and reasoning summaries with OpenAI: - -```ts -import { - openai, - type OpenAILanguageModelResponsesOptions, -} from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-5.2'), - prompt: 'What are the implications of quantum computing for cryptography?', - providerOptions: { - openai: { - reasoningEffort: 'high', - reasoningSummary: 'detailed', - } satisfies OpenAILanguageModelResponsesOptions, - }, -}); -``` - -Or enabling thinking with a low effort level for Anthropic: - -```ts -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: anthropic('claude-opus-4-20250514'), - prompt: 'Explain the Riemann hypothesis in simple terms.', - providerOptions: { - anthropic: { - thinking: { type: 'enabled', budgetTokens: 8000 }, - effort: 'medium', - } satisfies AnthropicLanguageModelOptions, - }, -}); -``` - -## Using Provider Options with the AI Gateway - -Provider options work the same way when using the [Vercel AI Gateway](/providers/ai-sdk-providers/ai-gateway). Use the underlying provider name (e.g. `openai`, `anthropic`) as the key — not `gateway`. The AI Gateway forwards these options to the target provider automatically. - -```ts -import type { OpenAILanguageModelResponsesOptions } from '@ai-sdk/openai'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: 'openai/gpt-5.2', // AI Gateway model string - prompt: 'What are the implications of quantum computing for cryptography?', - providerOptions: { - openai: { - reasoningEffort: 'high', - reasoningSummary: 'detailed', - } satisfies OpenAILanguageModelResponsesOptions, - }, -}); -``` - -You can also combine gateway-specific options (like routing and fallbacks) with provider-specific options in the same call: - -```ts -import type { AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: 'anthropic/claude-sonnet-4', - prompt: 'Explain quantum computing', - providerOptions: { - // Gateway-specific: control routing - gateway: { - order: ['vertex', 'anthropic'], - } satisfies GatewayLanguageModelOptions, - // Provider-specific: enable reasoning - anthropic: { - thinking: { type: 'enabled', budgetTokens: 12000 }, - } satisfies AnthropicLanguageModelOptions, - }, -}); -``` - -For more on gateway routing, fallbacks, and other gateway-specific options, see the [AI Gateway provider documentation](/providers/ai-sdk-providers/ai-gateway#provider-options). - -## Type Safety - -Each provider exports a type for its options, which you can use with `satisfies` to get autocomplete and catch typos at build time: - -```ts -import { type OpenAILanguageModelResponsesOptions } from '@ai-sdk/openai'; -import { type AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -``` - -For a full list of available options, see the provider-specific documentation: - -- [OpenAI Provider](/providers/ai-sdk-providers/openai) -- [Anthropic Provider](/providers/ai-sdk-providers/anthropic) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/index.mdx deleted file mode 100644 index 320dd0997..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-foundations/index.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Foundations -description: A section that covers foundational knowledge around LLMs and concepts crucial to the AI SDK ---- - -# Foundations - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/00-choosing-a-provider.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/00-choosing-a-provider.mdx deleted file mode 100644 index 70ed1f7a4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/00-choosing-a-provider.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Choosing a Provider -description: Learn how to configure and authenticate with AI providers in the AI SDK. ---- - -# Choosing a Provider - -The AI SDK supports dozens of model providers through [first-party](/providers/ai-sdk-providers), [OpenAI-compatible](/providers/openai-compatible-providers), and [community](/providers/community-providers) packages. - -```ts -import { generateText } from 'ai'; -__PROVIDER_IMPORT__; - -const { text } = await generateText({ - model: __MODEL__, - prompt: 'What is love?', -}); -``` - -## AI Gateway - -The [Vercel AI Gateway](/providers/ai-sdk-providers/ai-gateway) is the fastest way to get started with the AI SDK. Access models from OpenAI, Anthropic, Google, and other providers. Authenticate with [OIDC](https://ai-sdk.dev/providers/ai-sdk-providers/ai-gateway#oidc-authentication-vercel-deployments) or an AI Gateway API key - -
- } - > - Get an API Key - -
- -Add your API key to your environment: - -```env filename=".env.local" -AI_GATEWAY_API_KEY=your_api_key_here -``` - -The AI Gateway is the default [global provider](/docs/ai-sdk-core/provider-management#global-provider-configuration), so you can access models using a simple string: - -```ts -import { generateText } from 'ai'; - -const { text } = await generateText({ - model: 'anthropic/claude-sonnet-4.5', - prompt: 'What is love?', -}); -``` - -You can also explicitly import and use the gateway provider: - -```ts -// Option 1: Import from 'ai' package (included by default) -import { gateway } from 'ai'; -model: gateway('anthropic/claude-sonnet-4.5'); - -// Option 2: Install and import from '@ai-sdk/gateway' package -import { gateway } from '@ai-sdk/gateway'; -model: gateway('anthropic/claude-sonnet-4.5'); -``` - -## Using Dedicated Providers - -You can also use [first-party](/providers/ai-sdk-providers), [OpenAI-compatible](/providers/openai-compatible-providers), and [community](/providers/community-providers) provider packages directly. Install the package and create a provider instance. For example, to use Anthropic: - -
- - - - - - - - - - - - - - -
- -```ts -import { anthropic } from '@ai-sdk/anthropic'; - -model: anthropic('claude-sonnet-4-5'); -``` - -You can change the default global provider so string model references use your preferred provider everywhere in your application. Learn more about [provider management](/docs/ai-sdk-core/provider-management#global-provider-configuration). - -See [available providers](/providers/ai-sdk-providers) for setup instructions for each provider. - -## Custom Providers - -You can build your own provider to integrate any service with the AI SDK. The AI SDK provides a [Language Model Specification](https://github.com/vercel/ai/tree/main/packages/provider/src/language-model/v3) that ensures compatibility across providers. - -```ts -import { generateText } from 'ai'; -import { yourProvider } from 'your-custom-provider'; - -const { text } = await generateText({ - model: yourProvider('your-model-id'), - prompt: 'What is love?', -}); -``` - -See [Writing a Custom Provider](/providers/community-providers/custom-providers) for a complete guide. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/01-navigating-the-library.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/01-navigating-the-library.mdx deleted file mode 100644 index b7147a626..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/01-navigating-the-library.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Navigating the Library -description: Learn how to navigate the AI SDK. ---- - -# Navigating the Library - -The AI SDK is a powerful toolkit for building AI applications. This page will help you pick the right tools for your requirements. - -Let’s start with a quick overview of the AI SDK, which is comprised of three parts: - -- **[AI SDK Core](/docs/ai-sdk-core/overview):** A unified, provider agnostic API for generating text, structured objects, and tool calls with LLMs. -- **[AI SDK UI](/docs/ai-sdk-ui/overview):** A set of framework-agnostic hooks for building chat and generative user interfaces. -- [AI SDK RSC](/docs/ai-sdk-rsc/overview): Stream generative user interfaces with React Server Components (RSC). Development is currently experimental and we recommend using [AI SDK UI](/docs/ai-sdk-ui/overview). - -## Choosing the Right Tool for Your Environment - -When deciding which part of the AI SDK to use, your first consideration should be the environment and existing stack you are working with. Different components of the SDK are tailored to specific frameworks and environments. - -| Library | Purpose | Environment Compatibility | -| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | -| [AI SDK Core](/docs/ai-sdk-core/overview) | Call any LLM with unified API (e.g. [generateText](/docs/reference/ai-sdk-core/generate-text) and [streamText](/docs/reference/ai-sdk-core/stream-text)) | Any JS environment (e.g. Node.js, Deno, Browser) | -| [AI SDK UI](/docs/ai-sdk-ui/overview) | Build streaming chat and generative UIs (e.g. [useChat](/docs/reference/ai-sdk-ui/use-chat)) | React & Next.js, Vue & Nuxt, Svelte & SvelteKit | -| [AI SDK RSC](/docs/ai-sdk-rsc/overview) | Stream generative UIs from Server to Client (e.g. [streamUI](/docs/reference/ai-sdk-rsc/stream-ui)). Development is currently experimental and we recommend using [AI SDK UI](/docs/ai-sdk-ui/overview). | Any framework that supports React Server Components (e.g. Next.js) | - -## Environment Compatibility - -These tools have been designed to work seamlessly with each other and it's likely that you will be using them together. Let's look at how you could decide which libraries to use based on your application environment, existing stack, and requirements. - -The following table outlines AI SDK compatibility based on environment: - -| Environment | [AI SDK Core](/docs/ai-sdk-core/overview) | [AI SDK UI](/docs/ai-sdk-ui/overview) | [AI SDK RSC](/docs/ai-sdk-rsc/overview) | -| --------------------- | ----------------------------------------- | ------------------------------------- | --------------------------------------- | -| None / Node.js / Deno | | | | -| Vue / Nuxt | | | | -| Svelte / SvelteKit | | | | -| Next.js Pages Router | | | | -| Next.js App Router | | | | - -## When to use AI SDK UI - -AI SDK UI provides a set of framework-agnostic hooks for quickly building **production-ready AI-native applications**. It offers: - -- Full support for streaming chat and client-side generative UI -- Utilities for handling common AI interaction patterns (i.e. chat, completion, assistant) -- Production-tested reliability and performance -- Compatibility across popular frameworks - -## AI SDK UI Framework Compatibility - -AI SDK UI supports the following frameworks: [React](https://react.dev/), [Svelte](https://svelte.dev/), and [Vue.js](https://vuejs.org/). Here is a comparison of the supported functions across these frameworks: - -| Function | React | Svelte | Vue.js | -| ---------------------------------------------------------- | ------------------- | ------------------- | ------------------- | -| [useChat](/docs/reference/ai-sdk-ui/use-chat) | | | | -| [useChat](/docs/reference/ai-sdk-ui/use-chat) tool calling | | | | -| [useCompletion](/docs/reference/ai-sdk-ui/use-completion) | | | | -| [useObject](/docs/reference/ai-sdk-ui/use-object) | | | | - - - [Contributions](https://github.com/vercel/ai/blob/main/CONTRIBUTING.md) are - welcome to implement missing features for non-React frameworks. - - -## When to use AI SDK RSC - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -[React Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components) -(RSCs) provide a new approach to building React applications that allow components -to render on the server, fetch data directly, and stream the results to the client, -reducing bundle size and improving performance. They also introduce a new way to -call server-side functions from anywhere in your application called [Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations). - -AI SDK RSC provides a number of utilities that allow you to stream values and UI directly from the server to the client. However, **it's important to be aware of current limitations**: - -- **Cancellation**: currently, it is not possible to abort a stream using Server Actions. This will be improved in future releases of React and Next.js. -- **Increased Data Transfer**: using [`createStreamableUI`](/docs/reference/ai-sdk-rsc/create-streamable-ui) can lead to quadratic data transfer (quadratic to the length of generated text). You can avoid this using [ `createStreamableValue` ](/docs/reference/ai-sdk-rsc/create-streamable-value) instead, and rendering the component client-side. -- **Re-mounting Issue During Streaming**: when using `createStreamableUI`, components re-mount on `.done()`, causing [flickering](https://github.com/vercel/ai/issues/2232). - -Given these limitations, **we recommend using [AI SDK UI](/docs/ai-sdk-ui/overview) for production applications**. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/02-nextjs-app-router.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/02-nextjs-app-router.mdx deleted file mode 100644 index 64eece823..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/02-nextjs-app-router.mdx +++ /dev/null @@ -1,559 +0,0 @@ ---- -title: Next.js App Router -description: Learn how to build your first agent with the AI SDK and Next.js App Router. ---- - -# Next.js App Router Quickstart - -The AI SDK is a powerful TypeScript library designed to help developers build AI-powered applications. - -In this quickstart tutorial, you'll build a simple agent with a streaming chat user interface. Along the way, you'll learn key concepts and techniques that are fundamental to using the AI SDK in your own projects. - -If you are unfamiliar with the concepts of [Prompt Engineering](/docs/advanced/prompt-engineering) and [HTTP Streaming](/docs/foundations/streaming), you can optionally read these documents first. - -## Prerequisites - -To follow this quickstart, you'll need: - -- Node.js 18+ and pnpm installed on your local development machine. -- A [ Vercel AI Gateway ](https://vercel.com/ai-gateway) API key. - -If you haven't obtained your Vercel AI Gateway API key, you can do so by [signing up](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai&title=Go+to+AI+Gateway) on the Vercel website. - -## Create Your Application - -Start by creating a new Next.js application. This command will create a new directory named `my-ai-app` and set up a basic Next.js application inside it. - -
- - Be sure to select yes when prompted to use the App Router and Tailwind CSS. - If you are looking for the Next.js Pages Router quickstart guide, you can - find it [here](/docs/getting-started/nextjs-pages-router). - -
- - - -Navigate to the newly created directory: - - - -### Install dependencies - -Install `ai` and `@ai-sdk/react`, the AI package and AI SDK's React hooks. The AI SDK's [ Vercel AI Gateway provider ](/providers/ai-sdk-providers/ai-gateway) ships with the `ai` package. You'll also install `zod`, a schema validation library used for defining tool inputs. - - - This guide uses the Vercel AI Gateway provider so you can access hundreds of - models from different providers with one API key, but you can switch to any - provider or model by installing its package. Check out available [AI SDK - providers](/providers/ai-sdk-providers) for more information. - - -
- - - - - - - - - - - - - - - - -
- -### Configure your AI Gateway API key - -Create a `.env.local` file in your project root and add your AI Gateway API key. This key authenticates your application with Vercel AI Gateway. - - - -Edit the `.env.local` file: - -```env filename=".env.local" -AI_GATEWAY_API_KEY=xxxxxxxxx -``` - -Replace `xxxxxxxxx` with your actual Vercel AI Gateway API key. - - - The AI SDK's Vercel AI Gateway Provider will default to using the - `AI_GATEWAY_API_KEY` environment variable. - - -## Create a Route Handler - -Create a route handler, `app/api/chat/route.ts` and add the following code: - -```tsx filename="app/api/chat/route.ts" -import { streamText, UIMessage, convertToModelMessages } from 'ai'; -__PROVIDER_IMPORT__; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse(); -} -``` - -Let's take a look at what is happening in this code: - -1. Define an asynchronous `POST` request handler and extract `messages` from the body of the request. The `messages` variable contains a history of the conversation between you and the chatbot and provides the chatbot with the necessary context to make the next generation. The `messages` are of UIMessage type, which are designed for use in application UI - they contain the entire message history and associated metadata like timestamps. -2. Call [`streamText`](/docs/reference/ai-sdk-core/stream-text), which is imported from the `ai` package. This function accepts a configuration object that contains a `model` provider and `messages` (defined in step 1). You can pass additional [settings](/docs/ai-sdk-core/settings) to further customize the model's behavior. The `messages` key expects a `ModelMessage[]` array. This type is different from `UIMessage` in that it does not include metadata, such as timestamps or sender information. To convert between these types, we use the `convertToModelMessages` function, which strips the UI-specific metadata and transforms the `UIMessage[]` array into the `ModelMessage[]` format that the model expects. -3. The `streamText` function returns a [`StreamTextResult`](/docs/reference/ai-sdk-core/stream-text#result-object). This result object contains the [ `toUIMessageStreamResponse` ](/docs/reference/ai-sdk-core/stream-text#to-ui-message-stream-response) function which converts the result to a streamed response object. -4. Finally, return the result to the client to stream the response. - -This Route Handler creates a POST request endpoint at `/api/chat`. - -## Choosing a Provider - -The AI SDK supports dozens of model providers through [first-party](/providers/ai-sdk-providers), [OpenAI-compatible](/providers/openai-compatible-providers), and [ community ](/providers/community-providers) packages. - -This quickstart uses the [Vercel AI Gateway](https://vercel.com/ai-gateway) provider, which is the default [global provider](/docs/ai-sdk-core/provider-management#global-provider-configuration). This means you can access models using a simple string in the model configuration: - -```ts -model: __MODEL__; -``` - -You can also explicitly import and use the gateway provider in two other equivalent ways: - -```ts -// Option 1: Import from 'ai' package (included by default) -import { gateway } from 'ai'; -model: gateway('anthropic/claude-sonnet-4.5'); - -// Option 2: Install and import from '@ai-sdk/gateway' package -import { gateway } from '@ai-sdk/gateway'; -model: gateway('anthropic/claude-sonnet-4.5'); -``` - -### Using other providers - -To use a different provider, install its package and create a provider instance. For example, to use OpenAI directly: - -
- - - - - - - - - - - - - - - - -
- -```ts -import { openai } from '@ai-sdk/openai'; - -model: openai('gpt-5.1'); -``` - -#### Updating the global provider - -You can change the default global provider so string model references use your preferred provider everywhere in your application. Learn more about [provider management](/docs/ai-sdk-core/provider-management#global-provider-configuration). - -Pick the approach that best matches how you want to manage providers across your application. - -## Wire up the UI - -Now that you have a Route Handler that can query an LLM, it's time to setup your frontend. The AI SDK's [ UI ](/docs/ai-sdk-ui) package abstracts the complexity of a chat interface into one hook, [`useChat`](/docs/reference/ai-sdk-ui/use-chat). - -Update your root page (`app/page.tsx`) with the following code to show a list of chat messages and provide a user message input: - -```tsx filename="app/page.tsx" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export default function Chat() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - return ( -
- {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return
{part.text}
; - } - })} -
- ))} - -
{ - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - > - setInput(e.currentTarget.value)} - /> -
-
- ); -} -``` - - - Make sure you add the `"use client"` directive to the top of your file. This - allows you to add interactivity with JavaScript. - - -This page utilizes the `useChat` hook, which will, by default, use the `POST` API route you created earlier (`/api/chat`). The hook provides functions and state for handling user input and form submission. The `useChat` hook provides multiple utility functions and state variables: - -- `messages` - the current chat messages (an array of objects with `id`, `role`, and `parts` properties). -- `sendMessage` - a function to send a message to the chat API. - -The component uses local state (`useState`) to manage the input field value, and handles form submission by calling `sendMessage` with the input text and then clearing the input field. - -The LLM's response is accessed through the message `parts` array. Each message contains an ordered array of `parts` that represents everything the model generated in its response. These parts can include plain text, reasoning tokens, and more that you will see later. The `parts` array preserves the sequence of the model's outputs, allowing you to display or process each component in the order it was generated. - -## Running Your Application - -With that, you have built everything you need for your chatbot! To start your application, use the command: - - - -Head to your browser and open http://localhost:3000. You should see an input field. Test it out by entering a message and see the AI chatbot respond in real-time! The AI SDK makes it fast and easy to build AI chat interfaces with Next.js. - -## Enhance Your Chatbot with Tools - -While large language models (LLMs) have incredible generation capabilities, they struggle with discrete tasks (e.g. mathematics) and interacting with the outside world (e.g. getting the weather). This is where [tools](/docs/ai-sdk-core/tools-and-tool-calling) come in. - -Tools are actions that an LLM can invoke. The results of these actions can be reported back to the LLM to be considered in the next response. - -For example, if a user asks about the current weather, without tools, the model would only be able to provide general information based on its training data. But with a weather tool, it can fetch and provide up-to-date, location-specific weather information. - -Let's enhance your chatbot by adding a simple weather tool. - -### Update Your Route Handler - -Modify your `app/api/chat/route.ts` file to include the new weather tool: - -```tsx filename="app/api/chat/route.ts" highlight="1,11-25" -import { streamText, UIMessage, convertToModelMessages, tool } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -In this updated code: - -1. You import the `tool` function from the `ai` package and `z` from `zod` for schema validation. -2. You define a `tools` object with a `weather` tool. This tool: - - - Has a description that helps the model understand when to use it. - - Defines `inputSchema` using a Zod schema, specifying that it requires a `location` string to execute this tool. The model will attempt to extract this input from the context of the conversation. If it can't, it will ask the user for the missing information. - - Defines an `execute` function that simulates getting weather data (in this case, it returns a random temperature). This is an asynchronous function running on the server so you can fetch real data from an external API. - -Now your chatbot can "fetch" weather information for any location the user asks about. When the model determines it needs to use the weather tool, it will generate a tool call with the necessary input. The `execute` function will then be automatically run, and the tool output will be added to the `messages` as a `tool` message. - -Try asking something like "What's the weather in New York?" and see how the model uses the new tool. - -Notice the blank response in the UI? This is because instead of generating a text response, the model generated a tool call. You can access the tool call and subsequent tool result on the client via the `tool-weather` part of the `message.parts` array. - - - Tool parts are always named `tool-{toolName}`, where `{toolName}` is the key - you used when defining the tool. In this case, since we defined the tool as - `weather`, the part type is `tool-weather`. - - -### Update the UI - -To display the tool invocation in your UI, update your `app/page.tsx` file: - -```tsx filename="app/page.tsx" highlight="18-22" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export default function Chat() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - return ( -
- {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return
{part.text}
; - case 'tool-weather': - return ( -
-                    {JSON.stringify(part, null, 2)}
-                  
- ); - } - })} -
- ))} - -
{ - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - > - setInput(e.currentTarget.value)} - /> -
-
- ); -} -``` - -With this change, you're updating the UI to handle different message parts. For text parts, you display the text content as before. For weather tool invocations, you display a JSON representation of the tool call and its result. - -Now, when you ask about the weather, you'll see the tool call and its result displayed in your chat interface. - -## Enabling Multi-Step Tool Calls - -You may have noticed that while the tool is now visible in the chat interface, the model isn't using this information to answer your original query. This is because once the model generates a tool call, it has technically completed its generation. - -To solve this, you can enable multi-step tool calls using `stopWhen`. By default, `stopWhen` is set to `stepCountIs(1)`, which means generation stops after the first step when there are tool results. By changing this condition, you can allow the model to automatically send tool results back to itself to trigger additional generations until your specified stopping condition is met. In this case, you want the model to continue generating so it can use the weather tool results to answer your original question. - -### Update Your Route Handler - -Modify your `app/api/chat/route.ts` file to include the `stopWhen` condition: - -```tsx filename="app/api/chat/route.ts" highlight="16" -import { - streamText, - UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - onStepFinish: ({ toolResults }) => { - console.log(toolResults); - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -In this updated code: - -1. You set `stopWhen` to be when `stepCountIs` 5, allowing the model to use up to 5 "steps" for any given generation. -2. You add an `onStepFinish` callback to log any `toolResults` from each step of the interaction, helping you understand the model's tool usage. - -Head back to the browser and ask about the weather in a location. You should now see the model using the weather tool results to answer your question. - -By setting `stopWhen: stepCountIs(5)`, you're allowing the model to use up to 5 "steps" for any given generation. This enables more complex interactions and allows the model to gather and process information over several steps if needed. You can see this in action by adding another tool to convert the temperature from Celsius to Fahrenheit. - -### Add another tool - -Update your `app/api/chat/route.ts` file to add a new tool to convert the temperature from Fahrenheit to Celsius: - -```tsx filename="app/api/chat/route.ts" highlight="31-46" -import { - streamText, - UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - convertFahrenheitToCelsius: tool({ - description: 'Convert a temperature in fahrenheit to celsius', - inputSchema: z.object({ - temperature: z - .number() - .describe('The temperature in fahrenheit to convert'), - }), - execute: async ({ temperature }) => { - const celsius = Math.round((temperature - 32) * (5 / 9)); - return { - celsius, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -### Update Your Frontend - -update your `app/page.tsx` file to render the new temperature conversion tool: - -```tsx filename="app/page.tsx" highlight="19" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export default function Chat() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - return ( -
- {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return
{part.text}
; - case 'tool-weather': - case 'tool-convertFahrenheitToCelsius': - return ( -
-                    {JSON.stringify(part, null, 2)}
-                  
- ); - } - })} -
- ))} - -
{ - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - > - setInput(e.currentTarget.value)} - /> -
-
- ); -} -``` - -This update handles the new `tool-convertFahrenheitToCelsius` part type, displaying the temperature conversion tool calls and results in the UI. - -Now, when you ask "What's the weather in New York in celsius?", you should see a more complete interaction: - -1. The model will call the weather tool for New York. -2. You'll see the tool output displayed. -3. It will then call the temperature conversion tool to convert the temperature from Fahrenheit to Celsius. -4. The model will then use that information to provide a natural language response about the weather in New York. - -This multi-step approach allows the model to gather information and use it to provide more accurate and contextual responses, making your chatbot considerably more useful. - -This simple example demonstrates how tools can expand your model's capabilities. You can create more complex tools to integrate with real APIs, databases, or any other external systems, allowing the model to access and process real-world data in real-time. Tools bridge the gap between the model's knowledge cutoff and current information. - -## Where to Next? - -You've built an AI chatbot using the AI SDK! From here, you have several paths to explore: - -- To learn more about the AI SDK, read through the [documentation](/docs). -- If you're interested in diving deeper with guides, check out the [RAG (retrieval-augmented generation)](/cookbook/guides/rag-chatbot) and [multi-modal chatbot](/cookbook/guides/multi-modal-chatbot) guides. -- To jumpstart your first AI project, explore available [templates](https://vercel.com/templates?type=ai). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/03-nextjs-pages-router.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/03-nextjs-pages-router.mdx deleted file mode 100644 index 2dc6665aa..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/03-nextjs-pages-router.mdx +++ /dev/null @@ -1,542 +0,0 @@ ---- -title: Next.js Pages Router -description: Learn how to build your first agent with the AI SDK and Next.js Pages Router. ---- - -# Next.js Pages Router Quickstart - -The AI SDK is a powerful TypeScript library designed to help developers build AI-powered applications. - -In this quickstart tutorial, you'll build a simple agent with a streaming chat user interface. Along the way, you'll learn key concepts and techniques that are fundamental to using the AI SDK in your own projects. - -If you are unfamiliar with the concepts of [Prompt Engineering](/docs/advanced/prompt-engineering) and [HTTP Streaming](/docs/foundations/streaming), you can optionally read these documents first. - -## Prerequisites - -To follow this quickstart, you'll need: - -- Node.js 18+ and pnpm installed on your local development machine. -- A [ Vercel AI Gateway ](https://vercel.com/ai-gateway) API key. - -If you haven't obtained your Vercel AI Gateway API key, you can do so by [signing up](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai&title=Go+to+AI+Gateway) on the Vercel website. - -## Setup Your Application - -Start by creating a new Next.js application. This command will create a new directory named `my-ai-app` and set up a basic Next.js application inside it. - - - Be sure to select no when prompted to use the App Router. If you are looking - for the Next.js App Router quickstart guide, you can find it - [here](/docs/getting-started/nextjs-app-router). - - - - -Navigate to the newly created directory: - - - -### Install dependencies - -Install `ai` and `@ai-sdk/react`, the AI package and AI SDK's React hooks. The AI SDK's [ Vercel AI Gateway provider ](/providers/ai-sdk-providers/ai-gateway) ships with the `ai` package. You'll also install `zod`, a schema validation library used for defining tool inputs. - - - This guide uses the Vercel AI Gateway provider so you can access hundreds of - models from different providers with one API key, but you can switch to any - provider or model by installing its package. Check out available [AI SDK - providers](/providers/ai-sdk-providers) for more information. - - -
- - - - - - - - - - - - - - - - -
- -### Configure your AI Gateway API key - -Create a `.env.local` file in your project root and add your AI Gateway API key. This key authenticates your application with the Vercel AI Gateway. - - - -Edit the `.env.local` file: - -```env filename=".env.local" -AI_GATEWAY_API_KEY=xxxxxxxxx -``` - -Replace `xxxxxxxxx` with your actual Vercel AI Gateway API key. - - - The AI SDK's Vercel AI Gateway Provider will default to using the - `AI_GATEWAY_API_KEY` environment variable. - - -## Create a Route Handler - - - As long as you are on Next.js 13+, you can use Route Handlers (using the App - Router) alongside the Pages Router. This is recommended to enable you to use - the Web APIs interface/signature and to better support streaming. - - -Create a Route Handler (`app/api/chat/route.ts`) and add the following code: - -```tsx filename="app/api/chat/route.ts" -import { streamText, UIMessage, convertToModelMessages } from 'ai'; -__PROVIDER_IMPORT__; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse(); -} -``` - -Let's take a look at what is happening in this code: - -1. Define an asynchronous `POST` request handler and extract `messages` from the body of the request. The `messages` variable contains a history of the conversation between you and the chatbot and provides the chatbot with the necessary context to make the next generation. The `messages` are of UIMessage type, which are designed for use in application UI - they contain the entire message history and associated metadata like timestamps. -2. Call [`streamText`](/docs/reference/ai-sdk-core/stream-text), which is imported from the `ai` package. This function accepts a configuration object that contains a `model` provider and `messages` (defined in step 1). You can pass additional [settings](/docs/ai-sdk-core/settings) to further customize the model's behavior. The `messages` key expects a `ModelMessage[]` array. This type is different from `UIMessage` in that it does not include metadata, such as timestamps or sender information. To convert between these types, we use the `convertToModelMessages` function, which strips the UI-specific metadata and transforms the `UIMessage[]` array into the `ModelMessage[]` format that the model expects. -3. The `streamText` function returns a [`StreamTextResult`](/docs/reference/ai-sdk-core/stream-text#result-object). This result object contains the [ `toUIMessageStreamResponse` ](/docs/reference/ai-sdk-core/stream-text#to-ui-message-stream-response) function which converts the result to a streamed response object. -4. Finally, return the result to the client to stream the response. - -This Route Handler creates a POST request endpoint at `/api/chat`. - -## Choosing a Provider - -The AI SDK supports dozens of model providers through [first-party](/providers/ai-sdk-providers), [OpenAI-compatible](/providers/openai-compatible-providers), and [ community ](/providers/community-providers) packages. - -This quickstart uses the [Vercel AI Gateway](https://vercel.com/ai-gateway) provider, which is the default [global provider](/docs/ai-sdk-core/provider-management#global-provider-configuration). This means you can access models using a simple string in the model configuration: - -```ts -model: __MODEL__; -``` - -You can also explicitly import and use the gateway provider in two other equivalent ways: - -```ts -// Option 1: Import from 'ai' package (included by default) -import { gateway } from 'ai'; -model: gateway('anthropic/claude-sonnet-4.5'); - -// Option 2: Install and import from '@ai-sdk/gateway' package -import { gateway } from '@ai-sdk/gateway'; -model: gateway('anthropic/claude-sonnet-4.5'); -``` - -### Using other providers - -To use a different provider, install its package and create a provider instance. For example, to use OpenAI directly: - -
- - - - - - - - - - - - - - - - -
- -```ts -import { openai } from '@ai-sdk/openai'; - -model: openai('gpt-5.1'); -``` - -#### Updating the global provider - -You can change the default global provider so string model references use your preferred provider everywhere in your application. Learn more about [provider management](/docs/ai-sdk-core/provider-management#global-provider-configuration). - -Pick the approach that best matches how you want to manage providers across your application. - -## Wire up the UI - -Now that you have an API route that can query an LLM, it's time to setup your frontend. The AI SDK's [ UI ](/docs/ai-sdk-ui) package abstract the complexity of a chat interface into one hook, [`useChat`](/docs/reference/ai-sdk-ui/use-chat). - -Update your root page (`pages/index.tsx`) with the following code to show a list of chat messages and provide a user message input: - -```tsx filename="pages/index.tsx" -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export default function Chat() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - return ( -
- {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return
{part.text}
; - } - })} -
- ))} - -
{ - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - > - setInput(e.currentTarget.value)} - /> -
-
- ); -} -``` - -This page utilizes the `useChat` hook, which will, by default, use the `POST` API route you created earlier (`/api/chat`). The hook provides functions and state for handling user input and form submission. The `useChat` hook provides multiple utility functions and state variables: - -- `messages` - the current chat messages (an array of objects with `id`, `role`, and `parts` properties). -- `sendMessage` - a function to send a message to the chat API. - -The component uses local state (`useState`) to manage the input field value, and handles form submission by calling `sendMessage` with the input text and then clearing the input field. - -The LLM's response is accessed through the message `parts` array. Each message contains an ordered array of `parts` that represents everything the model generated in its response. These parts can include plain text, reasoning tokens, and more that you will see later. The `parts` array preserves the sequence of the model's outputs, allowing you to display or process each component in the order it was generated. - -## Running Your Application - -With that, you have built everything you need for your chatbot! To start your application, use the command: - - - -Head to your browser and open http://localhost:3000. You should see an input field. Test it out by entering a message and see the AI chatbot respond in real-time! The AI SDK makes it fast and easy to build AI chat interfaces with Next.js. - -## Enhance Your Chatbot with Tools - -While large language models (LLMs) have incredible generation capabilities, they struggle with discrete tasks (e.g. mathematics) and interacting with the outside world (e.g. getting the weather). This is where [tools](/docs/ai-sdk-core/tools-and-tool-calling) come in. - -Tools are actions that an LLM can invoke. The results of these actions can be reported back to the LLM to be considered in the next response. - -For example, if a user asks about the current weather, without tools, the model would only be able to provide general information based on its training data. But with a weather tool, it can fetch and provide up-to-date, location-specific weather information. - -### Update Your Route Handler - -Let's start by giving your chatbot a weather tool. Update your Route Handler (`app/api/chat/route.ts`): - -```tsx filename="app/api/chat/route.ts" highlight="1,11-25" -import { streamText, UIMessage, convertToModelMessages, tool } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -In this updated code: - -1. You import the `tool` function from the `ai` package and `z` from `zod` for schema validation. -2. You define a `tools` object with a `weather` tool. This tool: - - - Has a description that helps the model understand when to use it. - - Defines `inputSchema` using a Zod schema, specifying that it requires a `location` string to execute this tool. The model will attempt to extract this input from the context of the conversation. If it can't, it will ask the user for the missing information. - - Defines an `execute` function that simulates getting weather data (in this case, it returns a random temperature). This is an asynchronous function running on the server so you can fetch real data from an external API. - -Now your chatbot can "fetch" weather information for any location the user asks about. When the model determines it needs to use the weather tool, it will generate a tool call with the necessary input. The `execute` function will then be automatically run, and the tool output will be added to the `messages` as a `tool` message. - -Try asking something like "What's the weather in New York?" and see how the model uses the new tool. - -Notice the blank response in the UI? This is because instead of generating a text response, the model generated a tool call. You can access the tool call and subsequent tool result on the client via the `tool-weather` part of the `message.parts` array. - - - Tool parts are always named `tool-{toolName}`, where `{toolName}` is the key - you used when defining the tool. In this case, since we defined the tool as - `weather`, the part type is `tool-weather`. - - -### Update the UI - -To display the tool invocations in your UI, update your `pages/index.tsx` file: - -```tsx filename="pages/index.tsx" highlight="16-21" -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export default function Chat() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - return ( -
- {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return
{part.text}
; - case 'tool-weather': - return ( -
-                    {JSON.stringify(part, null, 2)}
-                  
- ); - } - })} -
- ))} - -
{ - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - > - setInput(e.currentTarget.value)} - /> -
-
- ); -} -``` - -With this change, you're updating the UI to handle different message parts. For text parts, you display the text content as before. For weather tool invocations, you display a JSON representation of the tool call and its result. - -Now, when you ask about the weather, you'll see the tool call and its result displayed in your chat interface. - -## Enabling Multi-Step Tool Calls - -You may have noticed that while the tool is now visible in the chat interface, the model isn't using this information to answer your original query. This is because once the model generates a tool call, it has technically completed its generation. - -To solve this, you can enable multi-step tool calls using `stopWhen`. By default, `stopWhen` is set to `stepCountIs(1)`, which means generation stops after the first step when there are tool results. By changing this condition, you can allow the model to automatically send tool results back to itself to trigger additional generations until your specified stopping condition is met. In this case, you want the model to continue generating so it can use the weather tool results to answer your original question. - -### Update Your Route Handler - -Modify your `app/api/chat/route.ts` file to include the `stopWhen` condition: - -```tsx filename="app/api/chat/route.ts" highlight="16" -import { - streamText, - UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -Head back to the browser and ask about the weather in a location. You should now see the model using the weather tool results to answer your question. - -By setting `stopWhen: stepCountIs(5)`, you're allowing the model to use up to 5 "steps" for any given generation. This enables more complex interactions and allows the model to gather and process information over several steps if needed. You can see this in action by adding another tool to convert the temperature from Celsius to Fahrenheit. - -### Add another tool - -Update your `app/api/chat/route.ts` file to add a new tool to convert the temperature from Fahrenheit to Celsius: - -```tsx filename="app/api/chat/route.ts" highlight="31-46" -import { - streamText, - UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - convertFahrenheitToCelsius: tool({ - description: 'Convert a temperature in fahrenheit to celsius', - inputSchema: z.object({ - temperature: z - .number() - .describe('The temperature in fahrenheit to convert'), - }), - execute: async ({ temperature }) => { - const celsius = Math.round((temperature - 32) * (5 / 9)); - return { - celsius, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -### Update Your Frontend - -Update your `pages/index.tsx` file to render the new temperature conversion tool: - -```tsx filename="pages/index.tsx" highlight="17" -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export default function Chat() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - return ( -
- {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return
{part.text}
; - case 'tool-weather': - case 'tool-convertFahrenheitToCelsius': - return ( -
-                    {JSON.stringify(part, null, 2)}
-                  
- ); - } - })} -
- ))} - -
{ - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - > - setInput(e.currentTarget.value)} - /> -
-
- ); -} -``` - -This update handles the new `tool-convertFahrenheitToCelsius` part type, displaying the temperature conversion tool calls and results in the UI. - -Now, when you ask "What's the weather in New York in celsius?", you should see a more complete interaction: - -1. The model will call the weather tool for New York. -2. You'll see the tool output displayed. -3. It will then call the temperature conversion tool to convert the temperature from Fahrenheit to Celsius. -4. The model will then use that information to provide a natural language response about the weather in New York. - -This multi-step approach allows the model to gather information and use it to provide more accurate and contextual responses, making your chatbot considerably more useful. - -This simple example demonstrates how tools can expand your model's capabilities. You can create more complex tools to integrate with real APIs, databases, or any other external systems, allowing the model to access and process real-world data in real-time. Tools bridge the gap between the model's knowledge cutoff and current information. - -## Where to Next? - -You've built an AI chatbot using the AI SDK! From here, you have several paths to explore: - -- To learn more about the AI SDK, read through the [documentation](/docs). -- If you're interested in diving deeper with guides, check out the [RAG (retrieval-augmented generation)](/cookbook/guides/rag-chatbot) and [multi-modal chatbot](/cookbook/guides/multi-modal-chatbot) guides. -- To jumpstart your first AI project, explore available [templates](https://vercel.com/templates?type=ai). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/04-svelte.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/04-svelte.mdx deleted file mode 100644 index 5fce3b049..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/04-svelte.mdx +++ /dev/null @@ -1,627 +0,0 @@ ---- -title: Svelte -description: Learn how to build your first agent with the AI SDK and Svelte. ---- - -# Svelte Quickstart - -The AI SDK is a powerful TypeScript library designed to help developers build AI-powered applications. - -In this quickstart tutorial, you'll build a simple agent with a streaming chat user interface. Along the way, you'll learn key concepts and techniques that are fundamental to using the SDK in your own projects. - -If you are unfamiliar with the concepts of [Prompt Engineering](/docs/advanced/prompt-engineering) and [HTTP Streaming](/docs/foundations/streaming), you can optionally read these documents first. - -## Prerequisites - -To follow this quickstart, you'll need: - -- Node.js 18+ and pnpm installed on your local development machine. -- A [ Vercel AI Gateway ](https://vercel.com/ai-gateway) API key. - -If you haven't obtained your Vercel AI Gateway API key, you can do so by [signing up](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai&title=Go+to+AI+Gateway) on the Vercel website. - -## Set Up Your Application - -Start by creating a new SvelteKit application. This command will create a new directory named `my-ai-app` and set up a basic SvelteKit application inside it. - - - -Navigate to the newly created directory: - - - -### Install Dependencies - -Install `ai` and `@ai-sdk/svelte`, the AI package and AI SDK's Svelte bindings. The AI SDK's [ Vercel AI Gateway provider ](/providers/ai-sdk-providers/ai-gateway) ships with the `ai` package. You'll also install `zod`, a schema validation library used for defining tool inputs. - - - This guide uses the Vercel AI Gateway provider so you can access hundreds of - models from different providers with one API key, but you can switch to any - provider or model by installing its package. Check out available [AI SDK - providers](/providers/ai-sdk-providers) for more information. - -
- - - - - - - - - - - - - - -
- -### Configure your AI Gateway API key - -Create a `.env.local` file in your project root and add your AI Gateway API key. This key authenticates your application with the Vercel AI Gateway. - - - -Edit the `.env.local` file: - -```env filename=".env.local" -AI_GATEWAY_API_KEY=xxxxxxxxx -``` - -Replace `xxxxxxxxx` with your actual Vercel AI Gateway API key. - - - The AI SDK's Vercel AI Gateway Provider will default to using the - `AI_GATEWAY_API_KEY` environment variable. Vite does not automatically load - environment variables onto `process.env`, so you'll need to import - `AI_GATEWAY_API_KEY` from `$env/static/private` in your code (see below). - - -## Create an API route - -Create a SvelteKit Endpoint, `src/routes/api/chat/+server.ts` and add the following code: - -```tsx filename="src/routes/api/chat/+server.ts" -import { - streamText, - type UIMessage, - convertToModelMessages, - createGateway, -} from 'ai'; - -import { AI_GATEWAY_API_KEY } from '$env/static/private'; - -const gateway = createGateway({ - apiKey: AI_GATEWAY_API_KEY, -}); - -export async function POST({ request }) { - const { messages }: { messages: UIMessage[] } = await request.json(); - - const result = streamText({ - model: gateway('anthropic/claude-sonnet-4.5'), - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse(); -} -``` - - - If you see type errors with `AI_GATEWAY_API_KEY` or your `POST` function, run - the dev server. - - -Let's take a look at what is happening in this code: - -1. Create a gateway provider instance with the `createGateway` function from the `ai` package. -2. Define a `POST` request handler and extract `messages` from the body of the request. The `messages` variable contains a history of the conversation between you and the chatbot and provides the chatbot with the necessary context to make the next generation. The `messages` are of UIMessage type, which are designed for use in application UI - they contain the entire message history and associated metadata like timestamps. -3. Call [`streamText`](/docs/reference/ai-sdk-core/stream-text), which is imported from the `ai` package. This function accepts a configuration object that contains a `model` provider (defined in step 1) and `messages` (defined in step 2). You can pass additional [settings](/docs/ai-sdk-core/settings) to further customize the model's behavior. The `messages` key expects a `ModelMessage[]` array. This type is different from `UIMessage` in that it does not include metadata, such as timestamps or sender information. To convert between these types, we use the `convertToModelMessages` function, which strips the UI-specific metadata and transforms the `UIMessage[]` array into the `ModelMessage[]` format that the model expects. -4. The `streamText` function returns a [`StreamTextResult`](/docs/reference/ai-sdk-core/stream-text#result-object). This result object contains the [ `toUIMessageStreamResponse` ](/docs/reference/ai-sdk-core/stream-text#to-ui-message-stream-response) function which converts the result to a streamed response object. -5. Return the result to the client to stream the response. - -## Choosing a Provider - -The AI SDK supports dozens of model providers through [first-party](/providers/ai-sdk-providers), [OpenAI-compatible](/providers/openai-compatible-providers), and [ community ](/providers/community-providers) packages. - -This quickstart uses the [Vercel AI Gateway](https://vercel.com/ai-gateway) provider, which is the default [global provider](/docs/ai-sdk-core/provider-management#global-provider-configuration). This means you can access models using a simple string in the model configuration: - -```ts -model: __MODEL__; -``` - -You can also explicitly import and use the gateway provider in two other equivalent ways: - -```ts -// Option 1: Import from 'ai' package (included by default) -import { gateway } from 'ai'; -model: gateway('anthropic/claude-sonnet-4.5'); - -// Option 2: Install and import from '@ai-sdk/gateway' package -import { gateway } from '@ai-sdk/gateway'; -model: gateway('anthropic/claude-sonnet-4.5'); -``` - -### Using other providers - -To use a different provider, install its package and create a provider instance. For example, to use OpenAI directly: - -
- - - - - - - - - - - - - - - - -
- -```ts -import { openai } from '@ai-sdk/openai'; - -model: openai('gpt-5.1'); -``` - -#### Updating the global provider - -You can change the default global provider so string model references use your preferred provider everywhere in your application. Learn more about [provider management](/docs/ai-sdk-core/provider-management#global-provider-configuration). - -Pick the approach that best matches how you want to manage providers across your application. - -## Wire up the UI - -Now that you have an API route that can query an LLM, it's time to set up your frontend. The AI SDK's [UI](/docs/ai-sdk-ui) package abstracts the complexity of a chat interface into one class, `Chat`. -Its properties and API are largely the same as React's [`useChat`](/docs/reference/ai-sdk-ui/use-chat). - -Update your root page (`src/routes/+page.svelte`) with the following code to show a list of chat messages and provide a user message input: - -```svelte filename="src/routes/+page.svelte" - - -
-
    - {#each chat.messages as message, messageIndex (messageIndex)} -
  • -
    {message.role}
    -
    - {#each message.parts as part, partIndex (partIndex)} - {#if part.type === 'text'} -
    {part.text}
    - {/if} - {/each} -
    -
  • - {/each} -
-
- - -
-
-``` - -This page utilizes the `Chat` class, which will, by default, use the `POST` route handler you created earlier. The class provides functions and state for handling user input and form submission. The `Chat` class provides multiple utility functions and state variables: - -- `messages` - the current chat messages (an array of objects with `id`, `role`, and `parts` properties). -- `sendMessage` - a function to send a message to the chat API. - -The component uses local state to manage the input field value, and handles form submission by calling `sendMessage` with the input text and then clearing the input field. - -The LLM's response is accessed through the message `parts` array. Each message contains an ordered array of `parts` that represents everything the model generated in its response. These parts can include plain text, reasoning tokens, and more that you will see later. The `parts` array preserves the sequence of the model's outputs, allowing you to display or process each component in the order it was generated. - -## Running Your Application - -With that, you have built everything you need for your chatbot! To start your application, use the command: - - - -Head to your browser and open http://localhost:5173. You should see an input field. Test it out by entering a message and see the AI chatbot respond in real-time! The AI SDK makes it fast and easy to build AI chat interfaces with Svelte. - -## Enhance Your Chatbot with Tools - -While large language models (LLMs) have incredible generation capabilities, they struggle with discrete tasks (e.g. mathematics) and interacting with the outside world (e.g. getting the weather). This is where [tools](/docs/ai-sdk-core/tools-and-tool-calling) come in. - -Tools are actions that an LLM can invoke. The results of these actions can be reported back to the LLM to be considered in the next response. - -For example, if a user asks about the current weather, without tools, the model would only be able to provide general information based on its training data. But with a weather tool, it can fetch and provide up-to-date, location-specific weather information. - -Let's enhance your chatbot by adding a simple weather tool. - -### Update Your API Route - -Modify your `src/routes/api/chat/+server.ts` file to include the new weather tool: - -```tsx filename="src/routes/api/chat/+server.ts" highlight="2,3,17-31" -import { - createGateway, - streamText, - type UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -import { z } from 'zod'; - -import { AI_GATEWAY_API_KEY } from '$env/static/private'; - -const gateway = createGateway({ - apiKey: AI_GATEWAY_API_KEY, -}); - -export async function POST({ request }) { - const { messages }: { messages: UIMessage[] } = await request.json(); - - const result = streamText({ - model: gateway('anthropic/claude-sonnet-4.5'), - messages: await convertToModelMessages(messages), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -In this updated code: - -1. You import the `tool` function from the `ai` package and `z` from `zod` for schema validation. -2. You define a `tools` object with a `weather` tool. This tool: - - - Has a description that helps the model understand when to use it. - - Defines `inputSchema` using a Zod schema, specifying that it requires a `location` string to execute this tool. The model will attempt to extract this input from the context of the conversation. If it can't, it will ask the user for the missing information. - - Defines an `execute` function that simulates getting weather data (in this case, it returns a random temperature). This is an asynchronous function running on the server so you can fetch real data from an external API. - -Now your chatbot can "fetch" weather information for any location the user asks about. When the model determines it needs to use the weather tool, it will generate a tool call with the necessary input. The `execute` function will then be automatically run, and the tool output will be added to the `messages` as a `tool` message. - -Try asking something like "What's the weather in New York?" and see how the model uses the new tool. - -Notice the blank response in the UI? This is because instead of generating a text response, the model generated a tool call. You can access the tool call and subsequent tool result on the client via the `tool-weather` part of the `message.parts` array. - - - Tool parts are always named `tool-{toolName}`, where `{toolName}` is the key - you used when defining the tool. In this case, since we defined the tool as - `weather`, the part type is `tool-weather`. - - -### Update the UI - -To display the tool invocation in your UI, update your `src/routes/+page.svelte` file: - -```svelte filename="src/routes/+page.svelte" - - -
-
    - {#each chat.messages as message, messageIndex (messageIndex)} -
  • -
    {message.role}
    -
    - {#each message.parts as part, partIndex (partIndex)} - {#if part.type === 'text'} -
    {part.text}
    - {:else if part.type === 'tool-weather'} -
    {JSON.stringify(part, null, 2)}
    - {/if} - {/each} -
    -
  • - {/each} -
-
- - -
-
-``` - -With this change, you're updating the UI to handle different message parts. For text parts, you display the text content as before. For weather tool invocations, you display a JSON representation of the tool call and its result. - -Now, when you ask about the weather, you'll see the tool call and its result displayed in your chat interface. - -## Enabling Multi-Step Tool Calls - -You may have noticed that while the tool is now visible in the chat interface, the model isn't using this information to answer your original query. This is because once the model generates a tool call, it has technically completed its generation. - -To solve this, you can enable multi-step tool calls using `stopWhen`. By default, `stopWhen` is set to `stepCountIs(1)`, which means generation stops after the first step when there are tool results. By changing this condition, you can allow the model to automatically send tool results back to itself to trigger additional generations until your specified stopping condition is met. In this case, you want the model to continue generating so it can use the weather tool results to answer your original question. - -### Update Your API Route - -Modify your `src/routes/api/chat/+server.ts` file to include the `stopWhen` condition: - -```ts filename="src/routes/api/chat/+server.ts" highlight="15" -import { - createGateway, - streamText, - type UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -import { z } from 'zod'; - -import { AI_GATEWAY_API_KEY } from '$env/static/private'; - -const gateway = createGateway({ - apiKey: AI_GATEWAY_API_KEY, -}); - -export async function POST({ request }) { - const { messages }: { messages: UIMessage[] } = await request.json(); - - const result = streamText({ - model: gateway('anthropic/claude-sonnet-4.5'), - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -Head back to the browser and ask about the weather in a location. You should now see the model using the weather tool results to answer your question. - -By setting `stopWhen: stepCountIs(5)`, you're allowing the model to use up to 5 "steps" for any given generation. This enables more complex interactions and allows the model to gather and process information over several steps if needed. You can see this in action by adding another tool to convert the temperature from Fahrenheit to Celsius. - -### Add another tool - -Update your `src/routes/api/chat/+server.ts` file to add a new tool to convert the temperature from Fahrenheit to Celsius: - -```tsx filename="src/routes/api/chat/+server.ts" highlight="32-45" -import { - createGateway, - streamText, - type UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -import { z } from 'zod'; - -import { AI_GATEWAY_API_KEY } from '$env/static/private'; - -const gateway = createGateway({ - apiKey: AI_GATEWAY_API_KEY, -}); - -export async function POST({ request }) { - const { messages }: { messages: UIMessage[] } = await request.json(); - - const result = streamText({ - model: gateway('anthropic/claude-sonnet-4.5'), - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - convertFahrenheitToCelsius: tool({ - description: 'Convert a temperature in fahrenheit to celsius', - inputSchema: z.object({ - temperature: z - .number() - .describe('The temperature in fahrenheit to convert'), - }), - execute: async ({ temperature }) => { - const celsius = Math.round((temperature - 32) * (5 / 9)); - return { - celsius, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -### Update Your Frontend - -Update your UI to handle the new temperature conversion tool by modifying the tool part handling: - -```svelte filename="src/routes/+page.svelte" highlight="17" - - -
-
    - {#each chat.messages as message, messageIndex (messageIndex)} -
  • -
    {message.role}
    -
    - {#each message.parts as part, partIndex (partIndex)} - {#if part.type === 'text'} -
    {part.text}
    - {:else if part.type === 'tool-weather' || part.type === 'tool-convertFahrenheitToCelsius'} -
    {JSON.stringify(part, null, 2)}
    - {/if} - {/each} -
    -
  • - {/each} -
-
- - -
-
-``` - -This update handles the new `tool-convertFahrenheitToCelsius` part type, displaying the temperature conversion tool calls and results in the UI. - -Now, when you ask "What's the weather in New York in celsius?", you should see a more complete interaction: - -1. The model will call the weather tool for New York. -2. You'll see the tool output displayed. -3. It will then call the temperature conversion tool to convert the temperature from Fahrenheit to Celsius. -4. The model will then use that information to provide a natural language response about the weather in New York. - -This multi-step approach allows the model to gather information and use it to provide more accurate and contextual responses, making your chatbot considerably more useful. - -This simple example demonstrates how tools can expand your model's capabilities. You can create more complex tools to integrate with real APIs, databases, or any other external systems, allowing the model to access and process real-world data in real-time. Tools bridge the gap between the model's knowledge cutoff and current information. - -## How does `@ai-sdk/svelte` differ from `@ai-sdk/react`? - -The surface-level difference is that Svelte uses classes to manage state, whereas React uses hooks, so `useChat` in React is `Chat` in Svelte. Other than that, there are a few things to keep in mind: - -### 1. Arguments to classes aren't reactive by default - -Unlike in React, where hooks are rerun any time their containing component is invalidated, code in the `script` block of a Svelte component is only run once when the component is created. -This means that, if you want arguments to your class to be reactive, you need to make sure you pass a _reference_ into the class, rather than a value: - -```svelte - -``` - -Keep in mind that this normally doesn't matter; most parameters you'll pass into the Chat class are static (for example, you typically wouldn't expect your `onError` handler to change). - -### 2. You can't destructure class properties - -In vanilla JavaScript, destructuring class properties copies them by value and "disconnects" them from their class instance: - -```js -const classInstance = new Whatever(); -classInstance.foo = 'bar'; -const { foo } = classInstance; -classInstance.foo = 'baz'; - -console.log(foo); // 'bar' -``` - -The same is true of classes in Svelte: - -```svelte - -``` - -### 3. Instance synchronization requires context - -In React, hook instances with the same `id` are synchronized -- so two instances of `useChat` will have the same `messages`, `status`, etc. if they have the same `id`. -For most use cases, you probably don't need this behavior -- but if you do, you can create a context in your root layout file using `createAIContext`: - -```svelte - - -{@render children()} -``` - -## Where to Next? - -You've built an AI chatbot using the AI SDK! From here, you have several paths to explore: - -- To learn more about the AI SDK, read through the [documentation](/docs). -- If you're interested in diving deeper with guides, check out the [RAG (retrieval-augmented generation)](/cookbook/guides/rag-chatbot) and [multi-modal chatbot](/cookbook/guides/multi-modal-chatbot) guides. -- To jumpstart your first AI project, explore available [templates](https://vercel.com/templates?type=ai). -- To learn more about Svelte, check out the [official documentation](https://svelte.dev/docs/svelte). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/05-nuxt.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/05-nuxt.mdx deleted file mode 100644 index 450be07d5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/05-nuxt.mdx +++ /dev/null @@ -1,566 +0,0 @@ ---- -title: Vue.js (Nuxt) -description: Learn how to build your first agent with the AI SDK and Vue.js (Nuxt). ---- - -# Vue.js (Nuxt) Quickstart - -The AI SDK is a powerful TypeScript library designed to help developers build AI-powered applications. - -In this quickstart tutorial, you'll build a simple agent with a streaming chat user interface. Along the way, you'll learn key concepts and techniques that are fundamental to using the SDK in your own projects. - -If you are unfamiliar with the concepts of [Prompt Engineering](/docs/advanced/prompt-engineering) and [HTTP Streaming](/docs/foundations/streaming), you can optionally read these documents first. - -## Prerequisites - -To follow this quickstart, you'll need: - -- Node.js 18+ and pnpm installed on your local development machine. -- A [ Vercel AI Gateway ](https://vercel.com/ai-gateway) API key. - -If you haven't obtained your Vercel AI Gateway API key, you can do so by [signing up](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai&title=Go+to+AI+Gateway) on the Vercel website. - -## Setup Your Application - -Start by creating a new Nuxt application. This command will create a new directory named `my-ai-app` and set up a basic Nuxt application inside it. - - - -Navigate to the newly created directory: - - - -### Install dependencies - -Install `ai` and `@ai-sdk/vue`. The Vercel AI Gateway provider ships with the `ai` package. - - - The AI SDK is designed to be a unified interface to interact with any large - language model. This means that you can change model and providers with just - one line of code! Learn more about [available providers](/providers) and - [building custom providers](/providers/community-providers/custom-providers) - in the [providers](/providers) section. - -
- - - - - - - - - - - - - - - - -
- -### Configure Vercel AI Gateway API key - -Create a `.env` file in your project root and add your Vercel AI Gateway API Key. This key is used to authenticate your application with the Vercel AI Gateway service. - - - -Edit the `.env` file: - -```env filename=".env" -NUXT_AI_GATEWAY_API_KEY=xxxxxxxxx -``` - -Replace `xxxxxxxxx` with your actual Vercel AI Gateway API key and configure the environment variable in `nuxt.config.ts`: - -```ts filename="nuxt.config.ts" -export default defineNuxtConfig({ - // rest of your nuxt config - runtimeConfig: { - aiGatewayApiKey: '', - }, -}); -``` - - - This guide uses Nuxt's runtime config to manage the API key. The `NUXT_` - prefix in the environment variable allows Nuxt to automatically load it into - the runtime config. While the AI Gateway Provider also supports a default - `AI_GATEWAY_API_KEY` environment variable, this approach provides better - integration with Nuxt's configuration system. - - -## Create an API route - -Create an API route, `server/api/chat.ts` and add the following code: - -```typescript filename="server/api/chat.ts" -import { - streamText, - UIMessage, - convertToModelMessages, - createGateway, -} from 'ai'; - -export default defineLazyEventHandler(async () => { - const apiKey = useRuntimeConfig().aiGatewayApiKey; - if (!apiKey) throw new Error('Missing AI Gateway API key'); - const gateway = createGateway({ - apiKey: apiKey, - }); - - return defineEventHandler(async (event: any) => { - const { messages }: { messages: UIMessage[] } = await readBody(event); - - const result = streamText({ - model: gateway('anthropic/claude-sonnet-4.5'), - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse(); - }); -}); -``` - -Let's take a look at what is happening in this code: - -1. Create a gateway provider instance with the `createGateway` function from the `ai` package. -2. Define an Event Handler and extract `messages` from the body of the request. The `messages` variable contains a history of the conversation between you and the chatbot and provides the chatbot with the necessary context to make the next generation. The `messages` are of UIMessage type, which are designed for use in application UI - they contain the entire message history and associated metadata like timestamps. -3. Call [`streamText`](/docs/reference/ai-sdk-core/stream-text), which is imported from the `ai` package. This function accepts a configuration object that contains a `model` provider (defined in step 1) and `messages` (defined in step 2). You can pass additional [settings](/docs/ai-sdk-core/settings) to further customize the model's behavior. The `messages` key expects a `ModelMessage[]` array. This type is different from `UIMessage` in that it does not include metadata, such as timestamps or sender information. To convert between these types, we use the `convertToModelMessages` function, which strips the UI-specific metadata and transforms the `UIMessage[]` array into the `ModelMessage[]` format that the model expects. -4. The `streamText` function returns a [`StreamTextResult`](/docs/reference/ai-sdk-core/stream-text#result). This result object contains the [ `toUIMessageStreamResponse` ](/docs/reference/ai-sdk-core/stream-text#to-ui-message-stream-response) function which converts the result to a streamed response object. -5. Return the result to the client to stream the response. - -## Choosing a Provider - -The AI SDK supports dozens of model providers through [first-party](/providers/ai-sdk-providers), [OpenAI-compatible](/providers/openai-compatible-providers), and [ community ](/providers/community-providers) packages. - -This quickstart uses the [Vercel AI Gateway](https://vercel.com/ai-gateway) provider, which is the default [global provider](/docs/ai-sdk-core/provider-management#global-provider-configuration). This means you can access models using a simple string in the model configuration: - -```ts -model: __MODEL__; -``` - -You can also explicitly import and use the gateway provider in two other equivalent ways: - -```ts -// Option 1: Import from 'ai' package (included by default) -import { gateway } from 'ai'; -model: gateway('anthropic/claude-sonnet-4.5'); - -// Option 2: Install and import from '@ai-sdk/gateway' package -import { gateway } from '@ai-sdk/gateway'; -model: gateway('anthropic/claude-sonnet-4.5'); -``` - -### Using other providers - -To use a different provider, install its package and create a provider instance. For example, to use OpenAI directly: - -
- - - - - - - - - - - - - - - - -
- -```ts -import { openai } from '@ai-sdk/openai'; - -model: openai('gpt-5.1'); -``` - -## Wire up the UI - -Now that you have an API route that can query an LLM, it's time to setup your frontend. The AI SDK's [ UI ](/docs/ai-sdk-ui/overview) package abstract the complexity of a chat interface into one hook, [`useChat`](/docs/reference/ai-sdk-ui/use-chat). - -Update your root page (`pages/index.vue`) with the following code to show a list of chat messages and provide a user message input: - -```typescript filename="pages/index.vue" - - - -``` - - - If your project has `app.vue` instead of `pages/index.vue`, delete the - `app.vue` file and create a new `pages/index.vue` file with the code above. - - -This page utilizes the `useChat` hook, which will, by default, use the API route you created earlier (`/api/chat`). The hook provides functions and state for handling user input and form submission. The `useChat` hook provides multiple utility functions and state variables: - -- `messages` - the current chat messages (an array of objects with `id`, `role`, and `parts` properties). -- `sendMessage` - a function to send a message to the chat API. - -The component uses local state (`ref`) to manage the input field value, and handles form submission by calling `sendMessage` with the input text and then clearing the input field. - -The LLM's response is accessed through the message `parts` array. Each message contains an ordered array of `parts` that represents everything the model generated in its response. These parts can include plain text, reasoning tokens, and more that you will see later. The `parts` array preserves the sequence of the model's outputs, allowing you to display or process each component in the order it was generated. - -## Running Your Application - -With that, you have built everything you need for your chatbot! To start your application, use the command: - - - -Head to your browser and open http://localhost:3000. You should see an input field. Test it out by entering a message and see the AI chatbot respond in real-time! The AI SDK makes it fast and easy to build AI chat interfaces with Nuxt. - -## Enhance Your Chatbot with Tools - -While large language models (LLMs) have incredible generation capabilities, they struggle with discrete tasks (e.g. mathematics) and interacting with the outside world (e.g. getting the weather). This is where [tools](/docs/ai-sdk-core/tools-and-tool-calling) come in. - -Tools are actions that an LLM can invoke. The results of these actions can be reported back to the LLM to be considered in the next response. - -For example, if a user asks about the current weather, without tools, the model would only be able to provide general information based on its training data. But with a weather tool, it can fetch and provide up-to-date, location-specific weather information. - -Let's enhance your chatbot by adding a simple weather tool. - -### Update Your API Route - -Modify your `server/api/chat.ts` file to include the new weather tool: - -```typescript filename="server/api/chat.ts" highlight="1,16-32" -import { - createGateway, - streamText, - UIMessage, - convertToModelMessages, - tool, -} from 'ai'; -import { z } from 'zod'; - -export default defineLazyEventHandler(async () => { - const apiKey = useRuntimeConfig().aiGatewayApiKey; - if (!apiKey) throw new Error('Missing AI Gateway API key'); - const gateway = createGateway({ - apiKey: apiKey, - }); - - return defineEventHandler(async (event: any) => { - const { messages }: { messages: UIMessage[] } = await readBody(event); - - const result = streamText({ - model: gateway('anthropic/claude-sonnet-4.5'), - messages: await convertToModelMessages(messages), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z - .string() - .describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); - }); -}); -``` - -In this updated code: - -1. You import the `tool` function from the `ai` package and `z` from `zod` for schema validation. -2. You define a `tools` object with a `weather` tool. This tool: - - - Has a description that helps the model understand when to use it. - - Defines `inputSchema` using a Zod schema, specifying that it requires a `location` string to execute this tool. The model will attempt to extract this input from the context of the conversation. If it can't, it will ask the user for the missing information. - - Defines an `execute` function that simulates getting weather data (in this case, it returns a random temperature). This is an asynchronous function running on the server so you can fetch real data from an external API. - -Now your chatbot can "fetch" weather information for any location the user asks about. When the model determines it needs to use the weather tool, it will generate a tool call with the necessary input. The `execute` function will then be automatically run, and the tool output will be added to the `messages` as a `tool` message. - -Try asking something like "What's the weather in New York?" and see how the model uses the new tool. - -Notice the blank response in the UI? This is because instead of generating a text response, the model generated a tool call. You can access the tool call and subsequent tool result on the client via the `tool-weather` part of the `message.parts` array. - - - Tool parts are always named `tool-{toolName}`, where `{toolName}` is the key - you used when defining the tool. In this case, since we defined the tool as - `weather`, the part type is `tool-weather`. - - -### Update the UI - -To display the tool invocation in your UI, update your `pages/index.vue` file: - -```typescript filename="pages/index.vue" highlight="16-18" - - - -``` - -With this change, you're updating the UI to handle different message parts. For text parts, you display the text content as before. For weather tool invocations, you display a JSON representation of the tool call and its result. - -Now, when you ask about the weather, you'll see the tool call and its result displayed in your chat interface. - -## Enabling Multi-Step Tool Calls - -You may have noticed that while the tool is now visible in the chat interface, the model isn't using this information to answer your original query. This is because once the model generates a tool call, it has technically completed its generation. - -To solve this, you can enable multi-step tool calls using `stopWhen`. By default, `stopWhen` is set to `stepCountIs(1)`, which means generation stops after the first step when there are tool results. By changing this condition, you can allow the model to automatically send tool results back to itself to trigger additional generations until your specified stopping condition is met. In this case, you want the model to continue generating so it can use the weather tool results to answer your original question. - -### Update Your API Route - -Modify your `server/api/chat.ts` file to include the `stopWhen` condition: - -```typescript filename="server/api/chat.ts" highlight="22" -import { - createGateway, - streamText, - UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -import { z } from 'zod'; - -export default defineLazyEventHandler(async () => { - const apiKey = useRuntimeConfig().aiGatewayApiKey; - if (!apiKey) throw new Error('Missing AI Gateway API key'); - const gateway = createGateway({ - apiKey: apiKey, - }); - - return defineEventHandler(async (event: any) => { - const { messages }: { messages: UIMessage[] } = await readBody(event); - - const result = streamText({ - model: gateway('anthropic/claude-sonnet-4.5'), - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z - .string() - .describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); - }); -}); -``` - -Head back to the browser and ask about the weather in a location. You should now see the model using the weather tool results to answer your question. - -By setting `stopWhen: stepCountIs(5)`, you're allowing the model to use up to 5 "steps" for any given generation. This enables more complex interactions and allows the model to gather and process information over several steps if needed. You can see this in action by adding another tool to convert the temperature from Fahrenheit to Celsius. - -### Add another tool - -Update your `server/api/chat.ts` file to add a new tool to convert the temperature from Fahrenheit to Celsius: - -```typescript filename="server/api/chat.ts" highlight="32-45" -import { - createGateway, - streamText, - UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -import { z } from 'zod'; - -export default defineLazyEventHandler(async () => { - const apiKey = useRuntimeConfig().aiGatewayApiKey; - if (!apiKey) throw new Error('Missing AI Gateway API key'); - const gateway = createGateway({ - apiKey: apiKey, - }); - - return defineEventHandler(async (event: any) => { - const { messages }: { messages: UIMessage[] } = await readBody(event); - - const result = streamText({ - model: gateway('anthropic/claude-sonnet-4.5'), - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z - .string() - .describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - convertFahrenheitToCelsius: tool({ - description: 'Convert a temperature in fahrenheit to celsius', - inputSchema: z.object({ - temperature: z - .number() - .describe('The temperature in fahrenheit to convert'), - }), - execute: async ({ temperature }) => { - const celsius = Math.round((temperature - 32) * (5 / 9)); - return { - celsius, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); - }); -}); -``` - -### Update Your Frontend - -Update your UI to handle the new temperature conversion tool by modifying the tool part handling: - -```typescript filename="pages/index.vue" highlight="24" - - - -``` - -This update handles the new `tool-convertFahrenheitToCelsius` part type, displaying the temperature conversion tool calls and results in the UI. - -Now, when you ask "What's the weather in New York in celsius?", you should see a more complete interaction: - -1. The model will call the weather tool for New York. -2. You'll see the tool output displayed. -3. It will then call the temperature conversion tool to convert the temperature from Fahrenheit to Celsius. -4. The model will then use that information to provide a natural language response about the weather in New York. - -This multi-step approach allows the model to gather information and use it to provide more accurate and contextual responses, making your chatbot considerably more useful. - -This simple example demonstrates how tools can expand your model's capabilities. You can create more complex tools to integrate with real APIs, databases, or any other external systems, allowing the model to access and process real-world data in real-time. Tools bridge the gap between the model's knowledge cutoff and current information. - -## Where to Next? - -You've built an AI chatbot using the AI SDK! From here, you have several paths to explore: - -- To learn more about the AI SDK, read through the [documentation](/docs). -- If you're interested in diving deeper with guides, check out the [RAG (retrieval-augmented generation)](/cookbook/guides/rag-chatbot) and [multi-modal chatbot](/cookbook/guides/multi-modal-chatbot) guides. -- To jumpstart your first AI project, explore available [templates](https://vercel.com/templates?type=ai). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/06-nodejs.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/06-nodejs.mdx deleted file mode 100644 index defe541ef..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/06-nodejs.mdx +++ /dev/null @@ -1,512 +0,0 @@ ---- -title: Node.js -description: Learn how to build your first agent with the AI SDK and Node.js. ---- - -# Node.js Quickstart - -The AI SDK is a powerful TypeScript library designed to help developers build AI-powered applications. - -In this quickstart tutorial, you'll build a simple agent with a streaming chat user interface. Along the way, you'll learn key concepts and techniques that are fundamental to using the SDK in your own projects. - -If you are unfamiliar with the concepts of [Prompt Engineering](/docs/advanced/prompt-engineering) and [HTTP Streaming](/docs/foundations/streaming), you can optionally read these documents first. - -## Prerequisites - -To follow this quickstart, you'll need: - -- Node.js 18+ and pnpm installed on your local development machine. -- A [ Vercel AI Gateway ](https://vercel.com/ai-gateway) API key. - -If you haven't obtained your Vercel AI Gateway API key, you can do so by [signing up](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai&title=Go+to+AI+Gateway) on the Vercel website. - -## Setup Your Application - -Start by creating a new directory using the `mkdir` command. Change into your new directory and then run the `pnpm init` command. This will create a `package.json` in your new directory. - -```bash -mkdir my-ai-app -cd my-ai-app -pnpm init -``` - -### Install Dependencies - -Install `ai`, the AI SDK, along with other necessary dependencies. - - - The AI SDK is designed to be a unified interface to interact with any large - language model. This means that you can change model and providers with just - one line of code! Learn more about [available providers](/providers) and - [building custom providers](/providers/community-providers/custom-providers) - in the [providers](/providers) section. - - -```bash -pnpm add ai zod dotenv -pnpm add -D @types/node tsx typescript -``` - -The `ai` package contains the AI SDK. You will use `zod` to define type-safe schemas that you will pass to the large language model (LLM). You will use `dotenv` to access environment variables (your Vercel AI Gateway key) within your application. There are also three development dependencies, installed with the `-D` flag, that are necessary to run your TypeScript code. - -### Configure Vercel AI Gateway API key - -Create a `.env` file in your project's root directory and add your Vercel AI Gateway API Key. This key is used to authenticate your application with the Vercel AI Gateway service. - - - -Edit the `.env` file: - -```env filename=".env" -AI_GATEWAY_API_KEY=xxxxxxxxx -``` - -Replace `xxxxxxxxx` with your actual Vercel AI Gateway API key. - - - The AI SDK will use the `AI_GATEWAY_API_KEY` environment variable to - authenticate with Vercel AI Gateway. - - -## Create Your Application - -Create an `index.ts` file in the root of your project and add the following code: - -```ts filename="index.ts" -import { ModelMessage, streamText } from 'ai'; -__PROVIDER_IMPORT__; -import 'dotenv/config'; -import * as readline from 'node:readline/promises'; - -const terminal = readline.createInterface({ - input: process.stdin, - output: process.stdout, -}); - -const messages: ModelMessage[] = []; - -async function main() { - while (true) { - const userInput = await terminal.question('You: '); - - messages.push({ role: 'user', content: userInput }); - - const result = streamText({ - model: __MODEL__, - messages, - }); - - let fullResponse = ''; - process.stdout.write('\nAssistant: '); - for await (const delta of result.textStream) { - fullResponse += delta; - process.stdout.write(delta); - } - process.stdout.write('\n\n'); - - messages.push({ role: 'assistant', content: fullResponse }); - } -} - -main().catch(console.error); -``` - -Let's take a look at what is happening in this code: - -1. Set up a readline interface to take input from the terminal, enabling interactive sessions directly from the command line. -2. Initialize an array called `messages` to store the history of your conversation. This history allows the agent to maintain context in ongoing dialogues. -3. In the `main` function: - -- Prompt for and capture user input, storing it in `userInput`. -- Add user input to the `messages` array as a user message. -- Call [`streamText`](/docs/reference/ai-sdk-core/stream-text), which is imported from the `ai` package. This function accepts a configuration object that contains a `model` provider and `messages`. -- Iterate over the text stream returned by the `streamText` function (`result.textStream`) and print the contents of the stream to the terminal. -- Add the assistant's response to the `messages` array. - -## Running Your Application - -With that, you have built everything you need for your agent! To start your application, use the command: - - - -You should see a prompt in your terminal. Test it out by entering a message and see the AI agent respond in real-time! The AI SDK makes it fast and easy to build AI chat interfaces with Node.js. - -## Choosing a Provider - -The AI SDK supports dozens of model providers through [first-party](/providers/ai-sdk-providers), [OpenAI-compatible](/providers/openai-compatible-providers), and [ community ](/providers/community-providers) packages. - -This quickstart uses the [Vercel AI Gateway](https://vercel.com/ai-gateway) provider, which is the default [global provider](/docs/ai-sdk-core/provider-management#global-provider-configuration). This means you can access models using a simple string in the model configuration: - -```ts -model: __MODEL__; -``` - -You can also explicitly import and use the gateway provider in two other equivalent ways: - -```ts -// Option 1: Import from 'ai' package (included by default) -import { gateway } from 'ai'; -model: gateway('anthropic/claude-sonnet-4.5'); - -// Option 2: Install and import from '@ai-sdk/gateway' package -import { gateway } from '@ai-sdk/gateway'; -model: gateway('anthropic/claude-sonnet-4.5'); -``` - -### Using other providers - -To use a different provider, install its package and create a provider instance. For example, to use OpenAI directly: - -
- - - - - - - - - - - - - - - - -
- -```ts -import { openai } from '@ai-sdk/openai'; - -model: openai('gpt-5.1'); -``` - -## Enhance Your Agent with Tools - -While large language models (LLMs) have incredible generation capabilities, they struggle with discrete tasks (e.g. mathematics) and interacting with the outside world (e.g. getting the weather). This is where [tools](/docs/ai-sdk-core/tools-and-tool-calling) come in. - -Tools are actions that an LLM can invoke. The results of these actions can be reported back to the LLM to be considered in the next response. - -For example, if a user asks about the current weather, without tools, the agent would only be able to provide general information based on its training data. But with a weather tool, it can fetch and provide up-to-date, location-specific weather information. - -Let's enhance your agent by adding a simple weather tool. - -### Update Your Application - -Modify your `index.ts` file to include the new weather tool: - -```ts filename="index.ts" highlight="2,4,24-37" -import { ModelMessage, streamText, tool } from 'ai'; -__PROVIDER_IMPORT__; -import 'dotenv/config'; -import { z } from 'zod'; -import * as readline from 'node:readline/promises'; - -const terminal = readline.createInterface({ - input: process.stdin, - output: process.stdout, -}); - -const messages: ModelMessage[] = []; - -async function main() { - while (true) { - const userInput = await terminal.question('You: '); - - messages.push({ role: 'user', content: userInput }); - - const result = streamText({ - model: __MODEL__, - messages, - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z - .string() - .describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - let fullResponse = ''; - process.stdout.write('\nAssistant: '); - for await (const delta of result.textStream) { - fullResponse += delta; - process.stdout.write(delta); - } - process.stdout.write('\n\n'); - - messages.push({ role: 'assistant', content: fullResponse }); - } -} - -main().catch(console.error); -``` - -In this updated code: - -1. You import the `tool` function from the `ai` package. -2. You define a `tools` object with a `weather` tool. This tool: - - - Has a description that helps the agent understand when to use it. - - Defines `inputSchema` using a Zod schema, specifying that it requires a `location` string to execute this tool. The agent will attempt to extract this input from the context of the conversation. If it can't, it will ask the user for the missing information. - - Defines an `execute` function that simulates getting weather data (in this case, it returns a random temperature). This is an asynchronous function running on the server so you can fetch real data from an external API. - -Now your agent can "fetch" weather information for any location the user asks about. When the agent determines it needs to use the weather tool, it will generate a tool call with the necessary parameters. The `execute` function will then be automatically run, and the results will be used by the agent to generate its response. - -Try asking something like "What's the weather in New York?" and see how the agent uses the new tool. - -Notice the blank "assistant" response? This is because instead of generating a text response, the agent generated a tool call. You can access the tool call and subsequent tool result in the `toolCall` and `toolResult` keys of the result object. - -```typescript highlight="46-47" -import { ModelMessage, streamText, tool } from 'ai'; -__PROVIDER_IMPORT__; -import 'dotenv/config'; -import { z } from 'zod'; -import * as readline from 'node:readline/promises'; - -const terminal = readline.createInterface({ - input: process.stdin, - output: process.stdout, -}); - -const messages: ModelMessage[] = []; - -async function main() { - while (true) { - const userInput = await terminal.question('You: '); - - messages.push({ role: 'user', content: userInput }); - - const result = streamText({ - model: __MODEL__, - messages, - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z - .string() - .describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - let fullResponse = ''; - process.stdout.write('\nAssistant: '); - for await (const delta of result.textStream) { - fullResponse += delta; - process.stdout.write(delta); - } - process.stdout.write('\n\n'); - - console.log(await result.toolCalls); - console.log(await result.toolResults); - messages.push({ role: 'assistant', content: fullResponse }); - } -} - -main().catch(console.error); -``` - -Now, when you ask about the weather, you'll see the tool call and its result displayed in your chat interface. - -## Enabling Multi-Step Tool Calls - -You may have noticed that while the tool results are visible in the chat interface, the agent isn't using this information to answer your original query. This is because once the agent generates a tool call, it has technically completed its generation. - -To solve this, you can enable multi-step tool calls using `stopWhen`. This feature will automatically send tool results back to the agent to trigger an additional generation until the stopping condition you define is met. In this case, you want the agent to answer your question using the results from the weather tool. - -### Update Your Application - -Modify your `index.ts` file to configure stopping conditions with `stopWhen`: - -```ts filename="index.ts" highlight="38-41" -import { ModelMessage, streamText, tool, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; -import 'dotenv/config'; -import { z } from 'zod'; -import * as readline from 'node:readline/promises'; - -const terminal = readline.createInterface({ - input: process.stdin, - output: process.stdout, -}); - -const messages: ModelMessage[] = []; - -async function main() { - while (true) { - const userInput = await terminal.question('You: '); - - messages.push({ role: 'user', content: userInput }); - - const result = streamText({ - model: __MODEL__, - messages, - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z - .string() - .describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - stopWhen: stepCountIs(5), - onStepFinish: async ({ toolResults }) => { - if (toolResults.length) { - console.log(JSON.stringify(toolResults, null, 2)); - } - }, - }); - - let fullResponse = ''; - process.stdout.write('\nAssistant: '); - for await (const delta of result.textStream) { - fullResponse += delta; - process.stdout.write(delta); - } - process.stdout.write('\n\n'); - - messages.push({ role: 'assistant', content: fullResponse }); - } -} - -main().catch(console.error); -``` - -In this updated code: - -1. You set `stopWhen` to be when `stepCountIs` 5, allowing the agent to use up to 5 "steps" for any given generation. -2. You add an `onStepFinish` callback to log any `toolResults` from each step of the interaction, helping you understand the agent's tool usage. This means we can also delete the `toolCall` and `toolResult` `console.log` statements from the previous example. - -Now, when you ask about the weather in a location, you should see the agent using the weather tool results to answer your question. - -By setting `stopWhen: stepCountIs(5)`, you're allowing the agent to use up to 5 "steps" for any given generation. This enables more complex interactions and allows the agent to gather and process information over several steps if needed. You can see this in action by adding another tool to convert the temperature from Celsius to Fahrenheit. - -### Adding a second tool - -Update your `index.ts` file to add a new tool to convert the temperature from Celsius to Fahrenheit: - -```ts filename="index.ts" highlight="37-48" -import { ModelMessage, streamText, tool, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; -import 'dotenv/config'; -import { z } from 'zod'; -import * as readline from 'node:readline/promises'; - -const terminal = readline.createInterface({ - input: process.stdin, - output: process.stdout, -}); - -const messages: ModelMessage[] = []; - -async function main() { - while (true) { - const userInput = await terminal.question('You: '); - - messages.push({ role: 'user', content: userInput }); - - const result = streamText({ - model: __MODEL__, - messages, - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z - .string() - .describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - convertFahrenheitToCelsius: tool({ - description: 'Convert a temperature in fahrenheit to celsius', - inputSchema: z.object({ - temperature: z - .number() - .describe('The temperature in fahrenheit to convert'), - }), - execute: async ({ temperature }) => { - const celsius = Math.round((temperature - 32) * (5 / 9)); - return { - celsius, - }; - }, - }), - }, - stopWhen: stepCountIs(5), - onStepFinish: async ({ toolResults }) => { - if (toolResults.length) { - console.log(JSON.stringify(toolResults, null, 2)); - } - }, - }); - - let fullResponse = ''; - process.stdout.write('\nAssistant: '); - for await (const delta of result.textStream) { - fullResponse += delta; - process.stdout.write(delta); - } - process.stdout.write('\n\n'); - - messages.push({ role: 'assistant', content: fullResponse }); - } -} - -main().catch(console.error); -``` - -Now, when you ask "What's the weather in New York in celsius?", you should see a more complete interaction: - -1. The agent will call the weather tool for New York. -2. You'll see the tool result logged. -3. It will then call the temperature conversion tool to convert the temperature from Fahrenheit to Celsius. -4. The agent will then use that information to provide a natural language response about the weather in New York. - -This multi-step approach allows the agent to gather information and use it to provide more accurate and contextual responses, making your agent considerably more useful. - -This example demonstrates how tools can expand your agent's capabilities. You can create more complex tools to integrate with real APIs, databases, or any other external systems, allowing the agent to access and process real-world data in real-time and perform actions that interact with the outside world. Tools bridge the gap between the agent's knowledge cutoff and current information, while also enabling it to take meaningful actions beyond just generating text responses. - -## Where to Next? - -You've built an AI agent using the AI SDK! From here, you have several paths to explore: - -- To learn more about the AI SDK, read through the [documentation](/docs). -- If you're interested in diving deeper with guides, check out the [RAG (retrieval-augmented generation)](/cookbook/guides/rag-chatbot) and [multi-modal chatbot](/cookbook/guides/multi-modal-chatbot) guides. -- To jumpstart your first AI project, explore available [templates](https://vercel.com/templates?type=ai). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/07-expo.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/07-expo.mdx deleted file mode 100644 index c4bfcb8a4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/07-expo.mdx +++ /dev/null @@ -1,766 +0,0 @@ ---- -title: Expo -description: Learn how to build your first agent with the AI SDK and Expo. ---- - -# Expo Quickstart - -In this quickstart tutorial, you'll build a simple agent with a streaming chat user interface with [Expo](https://expo.dev/). Along the way, you'll learn key concepts and techniques that are fundamental to using the SDK in your own projects. - -If you are unfamiliar with the concepts of [Prompt Engineering](/docs/advanced/prompt-engineering) and [HTTP Streaming](/docs/foundations/streaming), you can optionally read these documents first. - -## Prerequisites - -To follow this quickstart, you'll need: - -- Node.js 18+ and pnpm installed on your local development machine. -- A [ Vercel AI Gateway ](https://vercel.com/ai-gateway) API key. - -If you haven't obtained your Vercel AI Gateway API key, you can do so by [signing up](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai&title=Go+to+AI+Gateway) on the Vercel website. - -## Create Your Application - -Start by creating a new Expo application. This command will create a new directory named `my-ai-app` and set up a basic Expo application inside it. - - - -Navigate to the newly created directory: - - - -This guide requires Expo 52 or higher. - -### Install dependencies - -Install `ai` and `@ai-sdk/react`, the AI package and AI SDK's React hooks. The AI SDK's [ Vercel AI Gateway provider ](/providers/ai-sdk-providers/ai-gateway) ships with the `ai` package. You'll also install `zod`, a schema validation library used for defining tool inputs. - - - This guide uses the Vercel AI Gateway provider so you can access hundreds of - models from different providers with one API key, but you can switch to any - provider or model by installing its package. Check out available [AI SDK - providers](/providers/ai-sdk-providers) for more information. - - -
- - - - - - - - - - - - - - -
- -### Configure your AI Gateway API key - -Create a `.env.local` file in your project root and add your AI Gateway API key. This key authenticates your application with the Vercel AI Gateway. - - - -Edit the `.env.local` file: - -```env filename=".env.local" -AI_GATEWAY_API_KEY=xxxxxxxxx -``` - -Replace `xxxxxxxxx` with your actual Vercel AI Gateway API key. - - - The AI SDK's Vercel AI Gateway Provider will default to using the - `AI_GATEWAY_API_KEY` environment variable. - - -## Create an API Route - -Create a route handler, `app/api/chat+api.ts` and add the following code: - -```tsx filename="app/api/chat+api.ts" -import { streamText, UIMessage, convertToModelMessages } from 'ai'; -__PROVIDER_IMPORT__; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse({ - headers: { - 'Content-Type': 'application/octet-stream', - 'Content-Encoding': 'none', - }, - }); -} -``` - -Let's take a look at what is happening in this code: - -1. Define an asynchronous `POST` request handler and extract `messages` from the body of the request. The `messages` variable contains a history of the conversation between you and the chatbot and provides the chatbot with the necessary context to make the next generation. -2. Call [`streamText`](/docs/reference/ai-sdk-core/stream-text), which is imported from the `ai` package. This function accepts a configuration object that contains a `model` provider (imported from `ai`) and `messages` (defined in step 1). You can pass additional [settings](/docs/ai-sdk-core/settings) to further customize the model's behavior. -3. The `streamText` function returns a [`StreamTextResult`](/docs/reference/ai-sdk-core/stream-text#result-object). This result object contains the [ `toUIMessageStreamResponse` ](/docs/reference/ai-sdk-core/stream-text#to-ui-message-stream-response) function which converts the result to a streamed response object. -4. Finally, return the result to the client to stream the response. - -This API route creates a POST request endpoint at `/api/chat`. - -## Choosing a Provider - -The AI SDK supports dozens of model providers through [first-party](/providers/ai-sdk-providers), [OpenAI-compatible](/providers/openai-compatible-providers), and [ community ](/providers/community-providers) packages. - -This quickstart uses the [Vercel AI Gateway](https://vercel.com/ai-gateway) provider, which is the default [global provider](/docs/ai-sdk-core/provider-management#global-provider-configuration). This means you can access models using a simple string in the model configuration: - -```ts -model: __MODEL__; -``` - -You can also explicitly import and use the gateway provider in two other equivalent ways: - -```ts -// Option 1: Import from 'ai' package (included by default) -import { gateway } from 'ai'; -model: gateway('anthropic/claude-sonnet-4.5'); - -// Option 2: Install and import from '@ai-sdk/gateway' package -import { gateway } from '@ai-sdk/gateway'; -model: gateway('anthropic/claude-sonnet-4.5'); -``` - -### Using other providers - -To use a different provider, install its package and create a provider instance. For example, to use OpenAI directly: - -
- - - - - - - - - - - - - - - - -
- -```ts -import { openai } from '@ai-sdk/openai'; - -model: openai('gpt-5.1'); -``` - -#### Updating the global provider - -You can change the default global provider so string model references use your preferred provider everywhere in your application. Learn more about [provider management](/docs/ai-sdk-core/provider-management#global-provider-configuration). - -Pick the approach that best matches how you want to manage providers across your application. - -## Wire up the UI - -Now that you have an API route that can query an LLM, it's time to setup your frontend. The AI SDK's [ UI ](/docs/ai-sdk-ui) package abstracts the complexity of a chat interface into one hook, [`useChat`](/docs/reference/ai-sdk-ui/use-chat). - -Update your root page (`app/(tabs)/index.tsx`) with the following code to show a list of chat messages and provide a user message input: - -```tsx filename="app/(tabs)/index.tsx" -import { generateAPIUrl } from '@/utils'; -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; -import { fetch as expoFetch } from 'expo/fetch'; -import { useState } from 'react'; -import { View, TextInput, ScrollView, Text, SafeAreaView } from 'react-native'; - -export default function App() { - const [input, setInput] = useState(''); - const { messages, error, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - fetch: expoFetch as unknown as typeof globalThis.fetch, - api: generateAPIUrl('/api/chat'), - }), - onError: error => console.error(error, 'ERROR'), - }); - - if (error) return {error.message}; - - return ( - - - - {messages.map(m => ( - - - {m.role} - {m.parts.map((part, i) => { - switch (part.type) { - case 'text': - return {part.text}; - } - })} - - - ))} - - - - setInput(e.nativeEvent.text)} - onSubmitEditing={e => { - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - autoFocus={true} - /> - - - - ); -} -``` - -This page utilizes the `useChat` hook, which will, by default, use the `POST` API route you created earlier (`/api/chat`). The hook provides functions and state for handling user input and form submission. The `useChat` hook provides multiple utility functions and state variables: - -- `messages` - the current chat messages (an array of objects with `id`, `role`, and `parts` properties). -- `sendMessage` - a function to send a message to the chat API. - -The component uses local state (`useState`) to manage the input field value, and handles form submission by calling `sendMessage` with the input text and then clearing the input field. - -The LLM's response is accessed through the message `parts` array. Each message contains an ordered array of `parts` that represents everything the model generated in its response. These parts can include plain text, reasoning tokens, and more that you will see later. The `parts` array preserves the sequence of the model's outputs, allowing you to display or process each component in the order it was generated. - - - You use the expo/fetch function instead of the native node fetch to enable - streaming of chat responses. This requires Expo 52 or higher. - - -### Create the API URL Generator - -Because you're using expo/fetch for streaming responses instead of the native fetch function, you'll need an API URL generator to ensure you are using the correct base url and format depending on the client environment (e.g. web or mobile). Create a new file called `utils.ts` in the root of your project and add the following code: - -```ts filename="utils.ts" -import Constants from 'expo-constants'; - -export const generateAPIUrl = (relativePath: string) => { - const origin = Constants.experienceUrl.replace('exp://', 'http://'); - - const path = relativePath.startsWith('/') ? relativePath : `/${relativePath}`; - - if (process.env.NODE_ENV === 'development') { - return origin.concat(path); - } - - if (!process.env.EXPO_PUBLIC_API_BASE_URL) { - throw new Error( - 'EXPO_PUBLIC_API_BASE_URL environment variable is not defined', - ); - } - - return process.env.EXPO_PUBLIC_API_BASE_URL.concat(path); -}; -``` - -This utility function handles URL generation for both development and production environments, ensuring your API calls work correctly across different devices and configurations. - - - Before deploying to production, you must set the `EXPO_PUBLIC_API_BASE_URL` - environment variable in your production environment. This variable should - point to the base URL of your API server. - - -## Running Your Application - -With that, you have built everything you need for your chatbot! To start your application, use the command: - - - -Head to your browser and open http://localhost:8081. You should see an input field. Test it out by entering a message and see the AI chatbot respond in real-time! The AI SDK makes it fast and easy to build AI chat interfaces with Expo. - - - If you experience "Property `structuredClone` doesn't exist" errors on mobile, - add the [polyfills described below](#polyfills). - - -## Enhance Your Chatbot with Tools - -While large language models (LLMs) have incredible generation capabilities, they struggle with discrete tasks (e.g. mathematics) and interacting with the outside world (e.g. getting the weather). This is where [tools](/docs/ai-sdk-core/tools-and-tool-calling) come in. - -Tools are actions that an LLM can invoke. The results of these actions can be reported back to the LLM to be considered in the next response. - -For example, if a user asks about the current weather, without tools, the model would only be able to provide general information based on its training data. But with a weather tool, it can fetch and provide up-to-date, location-specific weather information. - -Let's enhance your chatbot by adding a simple weather tool. - -### Update Your API route - -Modify your `app/api/chat+api.ts` file to include the new weather tool: - -```tsx filename="app/api/chat+api.ts" highlight="2,11-25" -import { streamText, UIMessage, convertToModelMessages, tool } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse({ - headers: { - 'Content-Type': 'application/octet-stream', - 'Content-Encoding': 'none', - }, - }); -} -``` - -In this updated code: - -1. You import the `tool` function from the `ai` package and `z` from `zod` for schema validation. -2. You define a `tools` object with a `weather` tool. This tool: - - - Has a description that helps the model understand when to use it. - - Defines `inputSchema` using a Zod schema, specifying that it requires a `location` string to execute this tool. The model will attempt to extract this input from the context of the conversation. If it can't, it will ask the user for the missing information. - - Defines an `execute` function that simulates getting weather data (in this case, it returns a random temperature). This is an asynchronous function running on the server so you can fetch real data from an external API. - -Now your chatbot can "fetch" weather information for any location the user asks about. When the model determines it needs to use the weather tool, it will generate a tool call with the necessary input. The `execute` function will then be automatically run, and the tool output will be added to the `messages` as a `tool` message. - - - You may need to restart your development server for the changes to take - effect. - - -Try asking something like "What's the weather in New York?" and see how the model uses the new tool. - -Notice the blank response in the UI? This is because instead of generating a text response, the model generated a tool call. You can access the tool call and subsequent tool result on the client via the `tool-weather` part of the `message.parts` array. - - - Tool parts are always named `tool-{toolName}`, where `{toolName}` is the key - you used when defining the tool. In this case, since we defined the tool as - `weather`, the part type is `tool-weather`. - - -### Update the UI - -To display the weather tool invocation in your UI, update your `app/(tabs)/index.tsx` file: - -```tsx filename="app/(tabs)/index.tsx" highlight="31-35" -import { generateAPIUrl } from '@/utils'; -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; -import { fetch as expoFetch } from 'expo/fetch'; -import { useState } from 'react'; -import { View, TextInput, ScrollView, Text, SafeAreaView } from 'react-native'; - -export default function App() { - const [input, setInput] = useState(''); - const { messages, error, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - fetch: expoFetch as unknown as typeof globalThis.fetch, - api: generateAPIUrl('/api/chat'), - }), - onError: error => console.error(error, 'ERROR'), - }); - - if (error) return {error.message}; - - return ( - - - - {messages.map(m => ( - - - {m.role} - {m.parts.map((part, i) => { - switch (part.type) { - case 'text': - return {part.text}; - case 'tool-weather': - return ( - - {JSON.stringify(part, null, 2)} - - ); - } - })} - - - ))} - - - - setInput(e.nativeEvent.text)} - onSubmitEditing={e => { - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - autoFocus={true} - /> - - - - ); -} -``` - - - You may need to restart your development server for the changes to take - effect. - - -With this change, you're updating the UI to handle different message parts. For text parts, you display the text content as before. For weather tool invocations, you display a JSON representation of the tool call and its result. - -Now, when you ask about the weather, you'll see the tool call and its result displayed in your chat interface. - -## Enabling Multi-Step Tool Calls - -You may have noticed that while the tool results are visible in the chat interface, the model isn't using this information to answer your original query. This is because once the model generates a tool call, it has technically completed its generation. - -To solve this, you can enable multi-step tool calls using `stopWhen`. By default, `stopWhen` is set to `stepCountIs(1)`, which means generation stops after the first step when there are tool results. By changing this condition, you can allow the model to automatically send tool results back to itself to trigger additional generations until your specified stopping condition is met. In this case, you want the model to continue generating so it can use the weather tool results to answer your original question. - -### Update Your API Route - -Modify your `app/api/chat+api.ts` file to include the `stopWhen` condition: - -```tsx filename="app/api/chat+api.ts" highlight="10" -import { - streamText, - UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse({ - headers: { - 'Content-Type': 'application/octet-stream', - 'Content-Encoding': 'none', - }, - }); -} -``` - - - You may need to restart your development server for the changes to take - effect. - - -Head back to the Expo app and ask about the weather in a location. You should now see the model using the weather tool results to answer your question. - -By setting `stopWhen: stepCountIs(5)`, you're allowing the model to use up to 5 "steps" for any given generation. This enables more complex interactions and allows the model to gather and process information over several steps if needed. You can see this in action by adding another tool to convert the temperature from Fahrenheit to Celsius. - -### Add More Tools - -Update your `app/api/chat+api.ts` file to add a new tool to convert the temperature from Fahrenheit to Celsius: - -```tsx filename="app/api/chat+api.ts" highlight="28-41" -import { - streamText, - UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - convertFahrenheitToCelsius: tool({ - description: 'Convert a temperature in fahrenheit to celsius', - inputSchema: z.object({ - temperature: z - .number() - .describe('The temperature in fahrenheit to convert'), - }), - execute: async ({ temperature }) => { - const celsius = Math.round((temperature - 32) * (5 / 9)); - return { - celsius, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse({ - headers: { - 'Content-Type': 'application/octet-stream', - 'Content-Encoding': 'none', - }, - }); -} -``` - - - You may need to restart your development server for the changes to take - effect. - - -### Update the UI for the new tool - -To display the temperature conversion tool invocation in your UI, update your `app/(tabs)/index.tsx` file to handle the new tool part: - -```tsx filename="app/(tabs)/index.tsx" highlight="37-42" -import { generateAPIUrl } from '@/utils'; -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; -import { fetch as expoFetch } from 'expo/fetch'; -import { useState } from 'react'; -import { View, TextInput, ScrollView, Text, SafeAreaView } from 'react-native'; - -export default function App() { - const [input, setInput] = useState(''); - const { messages, error, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - fetch: expoFetch as unknown as typeof globalThis.fetch, - api: generateAPIUrl('/api/chat'), - }), - onError: error => console.error(error, 'ERROR'), - }); - - if (error) return {error.message}; - - return ( - - - - {messages.map(m => ( - - - {m.role} - {m.parts.map((part, i) => { - switch (part.type) { - case 'text': - return {part.text}; - case 'tool-weather': - case 'tool-convertFahrenheitToCelsius': - return ( - - {JSON.stringify(part, null, 2)} - - ); - } - })} - - - ))} - - - - setInput(e.nativeEvent.text)} - onSubmitEditing={e => { - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - autoFocus={true} - /> - - - - ); -} -``` - - - You may need to restart your development server for the changes to take - effect. - - -Now, when you ask "What's the weather in New York in celsius?", you should see a more complete interaction: - -1. The model will call the weather tool for New York. -2. You'll see the tool result displayed. -3. It will then call the temperature conversion tool to convert the temperature from Fahrenheit to Celsius. -4. The model will then use that information to provide a natural language response about the weather in New York. - -This multi-step approach allows the model to gather information and use it to provide more accurate and contextual responses, making your chatbot considerably more useful. - -This simple example demonstrates how tools can expand your model's capabilities. You can create more complex tools to integrate with real APIs, databases, or any other external systems, allowing the model to access and process real-world data in real-time. Tools bridge the gap between the model's knowledge cutoff and current information. - -## Polyfills - -Several functions that are internally used by the AI SDK might not available in the Expo runtime depending on your configuration and the target platform. - -First, install the following packages: - -
- - - - - - - - - - - - - - -
- -Then create a new file in the root of your project with the following polyfills: - -```ts filename="polyfills.js" -import { Platform } from 'react-native'; -import structuredClone from '@ungap/structured-clone'; - -if (Platform.OS !== 'web') { - const setupPolyfills = async () => { - const { polyfillGlobal } = await import( - 'react-native/Libraries/Utilities/PolyfillFunctions' - ); - - const { TextEncoderStream, TextDecoderStream } = await import( - '@stardazed/streams-text-encoding' - ); - - if (!('structuredClone' in global)) { - polyfillGlobal('structuredClone', () => structuredClone); - } - - polyfillGlobal('TextEncoderStream', () => TextEncoderStream); - polyfillGlobal('TextDecoderStream', () => TextDecoderStream); - }; - - setupPolyfills(); -} - -export {}; -``` - -Finally, import the polyfills in your root `_layout.tsx`: - -```ts filename="_layout.tsx" -import '@/polyfills'; -``` - -## Where to Next? - -You've built an AI chatbot using the AI SDK! From here, you have several paths to explore: - -- To learn more about the AI SDK, read through the [documentation](/docs). -- If you're interested in diving deeper with guides, check out the [RAG (retrieval-augmented generation)](/cookbook/guides/rag-chatbot) and [multi-modal chatbot](/cookbook/guides/multi-modal-chatbot) guides. -- To jumpstart your first AI project, explore available [templates](https://vercel.com/templates?type=ai). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/08-tanstack-start.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/08-tanstack-start.mdx deleted file mode 100644 index 067097575..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/08-tanstack-start.mdx +++ /dev/null @@ -1,583 +0,0 @@ ---- -title: TanStack Start -description: Learn how to build your first agent with the AI SDK and TanStack Start. ---- - -# TanStack Start Quickstart - -The AI SDK is a powerful TypeScript library designed to help developers build AI-powered applications. - -In this quickstart tutorial, you'll build a simple agent with a streaming chat user interface. Along the way, you'll learn key concepts and techniques that are fundamental to using the AI SDK in your own projects. - -If you are unfamiliar with the concepts of [Prompt Engineering](/docs/advanced/prompt-engineering) and [HTTP Streaming](/docs/foundations/streaming), you can optionally read these documents first. - -## Prerequisites - -To follow this quickstart, you'll need: - -- Node.js 18+ and pnpm installed on your local development machine. -- A [ Vercel AI Gateway ](https://vercel.com/ai-gateway) API key. - -If you haven't obtained your Vercel AI Gateway API key, you can do so by [signing up](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai&title=Go+to+AI+Gateway) on the Vercel website. - -## Create Your Application - -Start by creating a new TanStack Start application. This command will create a new directory named `my-ai-app` and set up a basic TanStack Start application inside it. - - - -Navigate to the newly created directory: - - - -### Install dependencies - -Install `ai` and `@ai-sdk/react`, the AI package and AI SDK's React hooks. The AI SDK's [ Vercel AI Gateway provider ](/providers/ai-sdk-providers/ai-gateway) ships with the `ai` package. You'll also install `zod`, a schema validation library used for defining tool inputs. - - - This guide uses the Vercel AI Gateway provider so you can access hundreds of - models from different providers with one API key, but you can switch to any - provider or model by installing its package. Check out available [AI SDK - providers](/providers/ai-sdk-providers) for more information. - - -
- - - - - - - - - - - - - - - - -
- -### Configure your AI Gateway API key - -Create a `.env` file in your project root and add your AI Gateway API key. This key authenticates your application with Vercel AI Gateway. - - - -Edit the `.env` file: - -```env filename=".env" -AI_GATEWAY_API_KEY=xxxxxxxxx -``` - -Replace `xxxxxxxxx` with your actual Vercel AI Gateway API key. - - - The AI SDK's Vercel AI Gateway Provider will default to using the - `AI_GATEWAY_API_KEY` environment variable. - - -## Create a Route Handler - -Create a route handler, `src/routes/api/chat.ts` and add the following code: - -```tsx filename="src/routes/api/chat.ts" -import { streamText, UIMessage, convertToModelMessages } from 'ai'; -__PROVIDER_IMPORT__; -import { createFileRoute } from '@tanstack/react-router'; - -export const Route = createFileRoute('/api/chat')({ - server: { - handlers: { - POST: async ({ request }) => { - const { messages }: { messages: UIMessage[] } = await request.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse(); - }, - }, - }, -}); -``` - -Let's take a look at what is happening in this code: - -1. Define an asynchronous `POST` request handler using TanStack Start's server routes and extract `messages` from the body of the request. The `messages` variable contains a history of the conversation between you and the chatbot and provides the chatbot with the necessary context to make the next generation. The `messages` are of UIMessage type, which are designed for use in application UI - they contain the entire message history and associated metadata like timestamps. -2. Call [`streamText`](/docs/reference/ai-sdk-core/stream-text), which is imported from the `ai` package. This function accepts a configuration object that contains a `model` provider and `messages` (defined in step 1). You can pass additional [settings](/docs/ai-sdk-core/settings) to further customize the model's behavior. The `messages` key expects a `ModelMessage[]` array. This type is different from `UIMessage` in that it does not include metadata, such as timestamps or sender information. To convert between these types, we use the `convertToModelMessages` function, which strips the UI-specific metadata and transforms the `UIMessage[]` array into the `ModelMessage[]` format that the model expects. -3. The `streamText` function returns a [`StreamTextResult`](/docs/reference/ai-sdk-core/stream-text#result-object). This result object contains the [ `toUIMessageStreamResponse` ](/docs/reference/ai-sdk-core/stream-text#to-ui-message-stream-response) function which converts the result to a streamed response object. -4. Finally, return the result to the client to stream the response. - -This Route Handler creates a POST request endpoint at `/api/chat`. - -## Choosing a Provider - -The AI SDK supports dozens of model providers through [first-party](/providers/ai-sdk-providers), [OpenAI-compatible](/providers/openai-compatible-providers), and [ community ](/providers/community-providers) packages. - -This quickstart uses the [Vercel AI Gateway](https://vercel.com/ai-gateway) provider, which is the default [global provider](/docs/ai-sdk-core/provider-management#global-provider-configuration). This means you can access models using a simple string in the model configuration: - -```ts -model: __MODEL__; -``` - -You can also explicitly import and use the gateway provider in two other equivalent ways: - -```ts -// Option 1: Import from 'ai' package (included by default) -import { gateway } from 'ai'; -model: gateway('anthropic/claude-sonnet-4.5'); - -// Option 2: Install and import from '@ai-sdk/gateway' package -import { gateway } from '@ai-sdk/gateway'; -model: gateway('anthropic/claude-sonnet-4.5'); -``` - -### Using other providers - -To use a different provider, install its package and create a provider instance. For example, to use OpenAI directly: - -
- - - - - - - - - - - - - - - - -
- -```ts -import { openai } from '@ai-sdk/openai'; - -model: openai('gpt-5.1'); -``` - -#### Updating the global provider - -You can change the default global provider so string model references use your preferred provider everywhere in your application. Learn more about [provider management](/docs/ai-sdk-core/provider-management#global-provider-configuration). - -Pick the approach that best matches how you want to manage providers across your application. - -## Wire up the UI - -Now that you have a Route Handler that can query an LLM, it's time to setup your frontend. The AI SDK's [ UI ](/docs/ai-sdk-ui) package abstracts the complexity of a chat interface into one hook, [`useChat`](/docs/reference/ai-sdk-ui/use-chat). - -Update your index route (`src/routes/index.tsx`) with the following code to show a list of chat messages and provide a user message input: - -```tsx filename="src/routes/index.tsx" -import { createFileRoute } from '@tanstack/react-router'; -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export const Route = createFileRoute('/')({ - component: Chat, -}); - -function Chat() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - return ( -
- {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return
{part.text}
; - } - })} -
- ))} - -
{ - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - > - setInput(e.currentTarget.value)} - /> -
-
- ); -} -``` - -This page utilizes the `useChat` hook, which will, by default, use the `POST` API route you created earlier (`/api/chat`). The hook provides functions and state for handling user input and form submission. The `useChat` hook provides multiple utility functions and state variables: - -- `messages` - the current chat messages (an array of objects with `id`, `role`, and `parts` properties). -- `sendMessage` - a function to send a message to the chat API. - -The component uses local state (`useState`) to manage the input field value, and handles form submission by calling `sendMessage` with the input text and then clearing the input field. - -The LLM's response is accessed through the message `parts` array. Each message contains an ordered array of `parts` that represents everything the model generated in its response. These parts can include plain text, reasoning tokens, and more that you will see later. The `parts` array preserves the sequence of the model's outputs, allowing you to display or process each component in the order it was generated. - -## Running Your Application - -With that, you have built everything you need for your chatbot! To start your application, use the command: - - - -Head to your browser and open http://localhost:3000. You should see an input field. Test it out by entering a message and see the AI chatbot respond in real-time! The AI SDK makes it fast and easy to build AI chat interfaces with TanStack Start. - -## Enhance Your Chatbot with Tools - -While large language models (LLMs) have incredible generation capabilities, they struggle with discrete tasks (e.g. mathematics) and interacting with the outside world (e.g. getting the weather). This is where [tools](/docs/ai-sdk-core/tools-and-tool-calling) come in. - -Tools are actions that an LLM can invoke. The results of these actions can be reported back to the LLM to be considered in the next response. - -For example, if a user asks about the current weather, without tools, the model would only be able to provide general information based on its training data. But with a weather tool, it can fetch and provide up-to-date, location-specific weather information. - -Let's enhance your chatbot by adding a simple weather tool. - -### Update Your Route Handler - -Modify your `src/routes/api/chat.ts` file to include the new weather tool: - -```tsx filename="src/routes/api/chat.ts" highlight="2,13-27" -import { streamText, UIMessage, convertToModelMessages, tool } from 'ai'; -__PROVIDER_IMPORT__; -import { createFileRoute } from '@tanstack/react-router'; -import { z } from 'zod'; - -export const Route = createFileRoute('/api/chat')({ - server: { - handlers: { - POST: async ({ request }) => { - const { messages }: { messages: UIMessage[] } = await request.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z - .string() - .describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); - }, - }, - }, -}); -``` - -In this updated code: - -1. You import the `tool` function from the `ai` package and `z` from `zod` for schema validation. -2. You define a `tools` object with a `weather` tool. This tool: - - - Has a description that helps the model understand when to use it. - - Defines `inputSchema` using a Zod schema, specifying that it requires a `location` string to execute this tool. The model will attempt to extract this input from the context of the conversation. If it can't, it will ask the user for the missing information. - - Defines an `execute` function that simulates getting weather data (in this case, it returns a random temperature). This is an asynchronous function running on the server so you can fetch real data from an external API. - -Now your chatbot can "fetch" weather information for any location the user asks about. When the model determines it needs to use the weather tool, it will generate a tool call with the necessary input. The `execute` function will then be automatically run, and the tool output will be added to the `messages` as a `tool` message. - -Try asking something like "What's the weather in New York?" and see how the model uses the new tool. - -Notice the blank response in the UI? This is because instead of generating a text response, the model generated a tool call. You can access the tool call and subsequent tool result on the client via the `tool-weather` part of the `message.parts` array. - - - Tool parts are always named `tool-{toolName}`, where `{toolName}` is the key - you used when defining the tool. In this case, since we defined the tool as - `weather`, the part type is `tool-weather`. - - -### Update the UI - -To display the tool invocation in your UI, update your `src/routes/index.tsx` file: - -```tsx filename="src/routes/index.tsx" highlight="16-21" -import { createFileRoute } from '@tanstack/react-router'; -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export const Route = createFileRoute('/')({ - component: Chat, -}); - -function Chat() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - return ( -
- {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return
{part.text}
; - case 'tool-weather': - return ( -
-                    {JSON.stringify(part, null, 2)}
-                  
- ); - } - })} -
- ))} - -
{ - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - > - setInput(e.currentTarget.value)} - /> -
-
- ); -} -``` - -With this change, you're updating the UI to handle different message parts. For text parts, you display the text content as before. For weather tool invocations, you display a JSON representation of the tool call and its result. - -Now, when you ask about the weather, you'll see the tool call and its result displayed in your chat interface. - -## Enabling Multi-Step Tool Calls - -You may have noticed that while the tool is now visible in the chat interface, the model isn't using this information to answer your original query. This is because once the model generates a tool call, it has technically completed its generation. - -To solve this, you can enable multi-step tool calls using `stopWhen`. By default, `stopWhen` is set to `stepCountIs(1)`, which means generation stops after the first step when there are tool results. By changing this condition, you can allow the model to automatically send tool results back to itself to trigger additional generations until your specified stopping condition is met. In this case, you want the model to continue generating so it can use the weather tool results to answer your original question. - -### Update Your Route Handler - -Modify your `src/routes/api/chat.ts` file to include the `stopWhen` condition: - -```tsx filename="src/routes/api/chat.ts" -import { - streamText, - UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -__PROVIDER_IMPORT__; -import { createFileRoute } from '@tanstack/react-router'; -import { z } from 'zod'; - -export const Route = createFileRoute('/api/chat')({ - server: { - handlers: { - POST: async ({ request }) => { - const { messages }: { messages: UIMessage[] } = await request.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z - .string() - .describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); - }, - }, - }, -}); -``` - -In this updated code, you set `stopWhen` to be when `stepCountIs(5)`, allowing the model to use up to 5 "steps" for any given generation. - -Head back to the browser and ask about the weather in a location. You should now see the model using the weather tool results to answer your question. - -By setting `stopWhen: stepCountIs(5)`, you're allowing the model to use up to 5 "steps" for any given generation. This enables more complex interactions and allows the model to gather and process information over several steps if needed. You can see this in action by adding another tool to convert the temperature from Celsius to Fahrenheit. - -### Add another tool - -Update your `src/routes/api/chat.ts` file to add a new tool to convert the temperature from Fahrenheit to Celsius: - -```tsx filename="src/routes/api/chat.ts" highlight="34-47" -import { - streamText, - UIMessage, - convertToModelMessages, - tool, - stepCountIs, -} from 'ai'; -__PROVIDER_IMPORT__; -import { createFileRoute } from '@tanstack/react-router'; -import { z } from 'zod'; - -export const Route = createFileRoute('/api/chat')({ - server: { - handlers: { - POST: async ({ request }) => { - const { messages }: { messages: UIMessage[] } = await request.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z - .string() - .describe('The location to get the weather for'), - }), - execute: async ({ location }) => { - const temperature = Math.round(Math.random() * (90 - 32) + 32); - return { - location, - temperature, - }; - }, - }), - convertFahrenheitToCelsius: tool({ - description: 'Convert a temperature in fahrenheit to celsius', - inputSchema: z.object({ - temperature: z - .number() - .describe('The temperature in fahrenheit to convert'), - }), - execute: async ({ temperature }) => { - const celsius = Math.round((temperature - 32) * (5 / 9)); - return { - celsius, - }; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); - }, - }, - }, -}); -``` - -### Update Your Frontend - -update your `src/routes/index.tsx` file to render the new temperature conversion tool: - -```tsx filename="src/routes/index.tsx" highlight="21" -import { createFileRoute } from '@tanstack/react-router'; -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export const Route = createFileRoute('/')({ - component: Chat, -}); - -function Chat() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - return ( -
- {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return
{part.text}
; - case 'tool-weather': - case 'tool-convertFahrenheitToCelsius': - return ( -
-                    {JSON.stringify(part, null, 2)}
-                  
- ); - } - })} -
- ))} - -
{ - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - > - setInput(e.currentTarget.value)} - /> -
-
- ); -} -``` - -This update handles the new `tool-convertFahrenheitToCelsius` part type, displaying the temperature conversion tool calls and results in the UI. - -Now, when you ask "What's the weather in New York in celsius?", you should see a more complete interaction: - -1. The model will call the weather tool for New York. -2. You'll see the tool output displayed. -3. It will then call the temperature conversion tool to convert the temperature from Fahrenheit to Celsius. -4. The model will then use that information to provide a natural language response about the weather in New York. - -This multi-step approach allows the model to gather information and use it to provide more accurate and contextual responses, making your chatbot considerably more useful. - -This simple example demonstrates how tools can expand your model's capabilities. You can create more complex tools to integrate with real APIs, databases, or any other external systems, allowing the model to access and process real-world data in real-time. Tools bridge the gap between the model's knowledge cutoff and current information. - -## Where to Next? - -You've built an AI chatbot using the AI SDK! From here, you have several paths to explore: - -- To learn more about the AI SDK, read through the [documentation](/docs). -- If you're interested in diving deeper with guides, check out the [RAG (retrieval-augmented generation)](/cookbook/guides/rag-chatbot) and [multi-modal chatbot](/cookbook/guides/multi-modal-chatbot) guides. -- To jumpstart your first AI project, explore available [templates](https://vercel.com/templates?type=ai). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/09-coding-agents.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/09-coding-agents.mdx deleted file mode 100644 index ad8d89392..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/09-coding-agents.mdx +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: Coding Agents -description: Learn how to set up the AI SDK for use with coding agents, including installing skills, accessing bundled docs, and using DevTools. ---- - -# Getting Started with Coding Agents - -This page explains how to get the most out of the AI SDK when working inside a coding agent (such as Claude Code, Codex, OpenCode, Cursor, or any other AI-assisted development environment). - -## Install the AI SDK Skill - -The fastest way to give your coding agent deep knowledge of the AI SDK is to install the official AI SDK skill. Skills are lightweight markdown files that load specialized instructions into your agent's context on demand — so your agent knows exactly how to use the SDK without you needing to explain it. - -Install the AI SDK skill using `npx skills add`: - -```bash -npx skills add vercel/ai -``` - -This installs the skill into your agent's specific skills directory (e.g., `.claude/skills`, `.codex/skills`). If you select more than one agent, the CLI creates symlinks so each agent can discover the skill. Use `-a` to specify agents directly — for example, `-a amp` installs into the universal `.agents/skills` directory. Use `-y` for non-interactive installation. - -Once installed, any agent that supports the [Agent Skills](https://agentskills.io) format will automatically discover and load the skill when working on AI SDK tasks. - - - Agent Skills use **progressive disclosure**: your agent loads only the skill's - name and description at startup. The full instructions are only pulled into - context when the task calls for it, keeping your agent fast and focused. - - -## Docs and Source Code in `node_modules` - -Once you've installed the `ai` package, you already have the full AI SDK documentation and source code available locally inside `node_modules`. Your coding agent can read these directly — no internet access required. - -Install the `ai` package if you haven't already: - -
- - - - - - - - - - - - - - -
- -After installation, your agent can reference the bundled source code and documentation at paths like: - -``` -node_modules/ai/src/ # Full source code organized by module -node_modules/ai/docs/ # Official documentation with examples -``` - -This means your agent can look up accurate API signatures, implementations, and usage examples directly from the installed package — ensuring it always uses the version of the SDK that's actually installed in your project. - -## Install DevTools - -AI SDK DevTools gives you full visibility into your AI SDK calls during development. It captures LLM requests, responses, tool calls, token usage, and multi-step interactions, and displays them in a local web UI. - - - AI SDK DevTools is experimental and intended for local development only. Do - not use in production environments. - - -Install the DevTools package: - -
- - - - - - - - - - - - - - -
- -### Add the middleware - -Wrap your language model with the DevTools middleware using [`wrapLanguageModel`](/docs/ai-sdk-core/middleware): - -```ts -import { wrapLanguageModel, gateway } from 'ai'; -import { devToolsMiddleware } from '@ai-sdk/devtools'; - -const model = wrapLanguageModel({ - model: gateway('anthropic/claude-sonnet-4.5'), - middleware: devToolsMiddleware(), -}); -``` - -Use the wrapped model with any AI SDK Core function: - -```ts -import { generateText } from 'ai'; - -const result = await generateText({ - model, // wrapped model with DevTools middleware - prompt: 'What cities are in the United States?', -}); -``` - -### Launch the viewer - -Start the DevTools viewer in a separate terminal: - -```bash -npx @ai-sdk/devtools -``` - -Open [http://localhost:4983](http://localhost:4983) to inspect your AI SDK interactions in real time. - -## Inspecting Tool Calls and Outputs - -DevTools captures and displays the following for every call: - -- **Input parameters and prompts** — the complete input sent to your LLM -- **Output content and tool calls** — generated text and tool invocations -- **Token usage and timing** — resource consumption and latency per step -- **Raw provider data** — complete request and response payloads - -For multi-step agent interactions, DevTools groups everything into **runs** (a complete interaction) and **steps** (each individual LLM call within it), making it easy to trace exactly what your agent did and why. - -You can also log tool results directly in code during development: - -```ts -import { streamText, tool, stepCountIs } from 'ai'; -import { z } from 'zod'; - -const result = streamText({ - model, - prompt: "What's the weather in New York in celsius?", - tools: { - weather: tool({ - description: 'Get the weather in a location (fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => ({ - location, - temperature: Math.round(Math.random() * (90 - 32) + 32), - }), - }), - }, - stopWhen: stepCountIs(5), - onStepFinish: async ({ toolResults }) => { - if (toolResults.length) { - console.log(JSON.stringify(toolResults, null, 2)); - } - }, -}); -``` - -The `onStepFinish` callback fires after each LLM step and prints any tool results to your terminal — useful for quick debugging without opening the DevTools UI. - - - DevTools stores all AI interactions in a local `.devtools/generations.json` - file. It automatically adds `.devtools` to your `.gitignore` to prevent - committing sensitive interaction data. - - -## Where to Next? - -- Learn about [Agent Skills](https://agentskills.io/specification) to understand the full skill format. -- Read the [DevTools reference](/docs/ai-sdk-core/devtools) for a complete list of captured data and configuration options. -- Explore [Tools and Tool Calling](/docs/ai-sdk-core/tools-and-tool-calling) to build agents that can take real-world actions. -- Check out the [Add Skills to Your Agent](/cookbook/guides/agent-skills) cookbook guide for a step-by-step integration walkthrough. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/index.mdx deleted file mode 100644 index e1ab30273..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/02-getting-started/index.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Getting Started -description: Welcome to the AI SDK documentation! ---- - -# Getting Started - -The following guides are intended to provide you with an introduction to some of the core features provided by the AI SDK. - - - -## Backend Framework Examples - -You can also use [AI SDK Core](/docs/ai-sdk-core/overview) and [AI SDK UI](/docs/ai-sdk-ui/overview) with the following backend frameworks: - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/01-overview.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/01-overview.mdx deleted file mode 100644 index a1bcc696e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/01-overview.mdx +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Overview -description: Learn how to build agents with the AI SDK. ---- - -# Agents - -Agents are **large language models (LLMs)** that use **tools** in a **loop** to accomplish tasks. - -These components work together: - -- **LLMs** process input and decide the next action -- **Tools** extend capabilities beyond text generation (reading files, calling APIs, writing to databases) -- **Loop** orchestrates execution through: - - **Context management** - Maintaining conversation history and deciding what the model sees (input) at each step - - **Stopping conditions** - Determining when the loop (task) is complete - -## ToolLoopAgent Class - -The ToolLoopAgent class handles these three components. Here's an agent that uses multiple tools in a loop to accomplish a task: - -```ts -import { ToolLoopAgent, stepCountIs, tool } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const weatherAgent = new ToolLoopAgent({ - model: __MODEL__, - tools: { - weather: tool({ - description: 'Get the weather in a location (in Fahrenheit)', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => ({ - location, - temperature: 72 + Math.floor(Math.random() * 21) - 10, - }), - }), - convertFahrenheitToCelsius: tool({ - description: 'Convert temperature from Fahrenheit to Celsius', - inputSchema: z.object({ - temperature: z.number().describe('Temperature in Fahrenheit'), - }), - execute: async ({ temperature }) => { - const celsius = Math.round((temperature - 32) * (5 / 9)); - return { celsius }; - }, - }), - }, - // Agent's default behavior is to stop after a maximum of 20 steps - // stopWhen: stepCountIs(20), -}); - -const result = await weatherAgent.generate({ - prompt: 'What is the weather in San Francisco in celsius?', -}); - -console.log(result.text); // agent's final answer -console.log(result.steps); // steps taken by the agent -``` - -The agent automatically: - -1. Calls the `weather` tool to get the temperature in Fahrenheit -2. Calls `convertFahrenheitToCelsius` to convert it -3. Generates a final text response with the result - -The ToolLoopAgent handles the loop, context management, and stopping conditions. - -## Why Use the ToolLoopAgent? - -The ToolLoopAgent is the recommended approach for building agents with the AI SDK because it: - -- **Reduces boilerplate** - Manages loops and message arrays -- **Improves reusability** - Define once, use throughout your application -- **Simplifies maintenance** - Single place to update agent configuration - -For most use cases, start with the ToolLoopAgent. Use core functions (`generateText`, `streamText`) when you need explicit control over each step for complex structured workflows. - -## Structured Workflows - -Agents are flexible and powerful, but non-deterministic. When you need reliable, repeatable outcomes with explicit control flow, use core functions with structured workflow patterns combining: - -- Conditional statements for explicit branching -- Standard functions for reusable logic -- Error handling for robustness -- Explicit control flow for predictability - -[Explore workflow patterns](/docs/agents/workflows) to learn more about building structured, reliable systems. - -## Next Steps - -- **[Building Agents](/docs/agents/building-agents)** - Guide to creating agents with the ToolLoopAgent -- **[Workflow Patterns](/docs/agents/workflows)** - Structured patterns using core functions for complex workflows -- **[Loop Control](/docs/agents/loop-control)** - Execution control with stopWhen and prepareStep diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/02-building-agents.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/02-building-agents.mdx deleted file mode 100644 index 6efa9c686..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/02-building-agents.mdx +++ /dev/null @@ -1,407 +0,0 @@ ---- -title: Building Agents -description: Complete guide to creating agents with the ToolLoopAgent. ---- - -# Building Agents - -The ToolLoopAgent provides a structured way to encapsulate LLM configuration, tools, and behavior into reusable components. It handles the agent loop for you, allowing the LLM to call tools multiple times in sequence to accomplish complex tasks. Define agents once and use them across your application. - -## Why Use the ToolLoopAgent Class? - -When building AI applications, you often need to: - -- **Reuse configurations** - Same model settings, tools, and prompts across different parts of your application -- **Maintain consistency** - Ensure the same behavior and capabilities throughout your codebase -- **Simplify API routes** - Reduce boilerplate in your endpoints -- **Type safety** - Get full TypeScript support for your agent's tools and outputs - -The ToolLoopAgent class provides a single place to define your agent's behavior. - -## Creating an Agent - -Define an agent by instantiating the ToolLoopAgent class with your desired configuration: - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const myAgent = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are a helpful assistant.', - tools: { - // Your tools here - }, -}); -``` - -## Configuration Options - -The ToolLoopAgent accepts all the same settings as `generateText` and `streamText`. Configure: - -### Model and System Instructions - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are an expert software engineer.', -}); -``` - -### Tools - -Provide tools that the agent can use to accomplish tasks: - -```ts -import { ToolLoopAgent, tool } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const codeAgent = new ToolLoopAgent({ - model: __MODEL__, - tools: { - runCode: tool({ - description: 'Execute Python code', - inputSchema: z.object({ - code: z.string(), - }), - execute: async ({ code }) => { - // Execute code and return result - return { output: 'Code executed successfully' }; - }, - }), - }, -}); -``` - -### Loop Control - -By default, agents run for 20 steps (`stopWhen: stepCountIs(20)`). In each step, the model either generates text or calls a tool. If it generates text, the agent completes. If it calls a tool, the AI SDK executes that tool. - -To let agents call multiple tools in sequence, configure `stopWhen` to allow more steps. After each tool execution, the agent triggers a new generation where the model can call another tool or generate text: - -```ts -import { ToolLoopAgent, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - stopWhen: stepCountIs(20), // Allow up to 20 steps -}); -``` - -Each step represents one generation (which results in either text or a tool call). The loop continues until: - -- A finish reasoning other than tool-calls is returned, or -- A tool that is invoked does not have an execute function, or -- A tool call needs approval, or -- A stop condition is met - -You can combine multiple conditions: - -```ts -import { ToolLoopAgent, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - stopWhen: [ - stepCountIs(20), // Maximum 20 steps - yourCustomCondition(), // Custom logic for when to stop - ], -}); -``` - -Learn more about [loop control and stop conditions](/docs/agents/loop-control). - -### Tool Choice - -Control how the agent uses tools: - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - tools: { - // your tools here - }, - toolChoice: 'required', // Force tool use - // or toolChoice: 'none' to disable tools - // or toolChoice: 'auto' (default) to let the model decide -}); -``` - -You can also force the use of a specific tool: - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - tools: { - weather: weatherTool, - cityAttractions: attractionsTool, - }, - toolChoice: { - type: 'tool', - toolName: 'weather', // Force the weather tool to be used - }, -}); -``` - -### Structured Output - -Define structured output schemas: - -```ts -import { ToolLoopAgent, Output, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const analysisAgent = new ToolLoopAgent({ - model: __MODEL__, - output: Output.object({ - schema: z.object({ - sentiment: z.enum(['positive', 'neutral', 'negative']), - summary: z.string(), - keyPoints: z.array(z.string()), - }), - }), - stopWhen: stepCountIs(10), -}); - -const { output } = await analysisAgent.generate({ - prompt: 'Analyze customer feedback from the last quarter', -}); -``` - -## Define Agent Behavior with System Instructions - -System instructions define your agent's behavior, personality, and constraints. They set the context for all interactions and guide how the agent responds to user queries and uses tools. - -### Basic System Instructions - -Set the agent's role and expertise: - -```ts -const agent = new ToolLoopAgent({ - model: __MODEL__, - instructions: - 'You are an expert data analyst. You provide clear insights from complex data.', -}); -``` - -### Detailed Behavioral Instructions - -Provide specific guidelines for agent behavior: - -```ts -const codeReviewAgent = new ToolLoopAgent({ - model: __MODEL__, - instructions: `You are a senior software engineer conducting code reviews. - - Your approach: - - Focus on security vulnerabilities first - - Identify performance bottlenecks - - Suggest improvements for readability and maintainability - - Be constructive and educational in your feedback - - Always explain why something is an issue and how to fix it`, -}); -``` - -### Constrain Agent Behavior - -Set boundaries and ensure consistent behavior: - -```ts -const customerSupportAgent = new ToolLoopAgent({ - model: __MODEL__, - instructions: `You are a customer support specialist for an e-commerce platform. - - Rules: - - Never make promises about refunds without checking the policy - - Always be empathetic and professional - - If you don't know something, say so and offer to escalate - - Keep responses concise and actionable - - Never share internal company information`, - tools: { - checkOrderStatus, - lookupPolicy, - createTicket, - }, -}); -``` - -### Tool Usage Instructions - -Guide how the agent should use available tools: - -```ts -const researchAgent = new ToolLoopAgent({ - model: __MODEL__, - instructions: `You are a research assistant with access to search and document tools. - - When researching: - 1. Always start with a broad search to understand the topic - 2. Use document analysis for detailed information - 3. Cross-reference multiple sources before drawing conclusions - 4. Cite your sources when presenting information - 5. If information conflicts, present both viewpoints`, - tools: { - webSearch, - analyzeDocument, - extractQuotes, - }, -}); -``` - -### Format and Style Instructions - -Control the output format and communication style: - -```ts -const technicalWriterAgent = new ToolLoopAgent({ - model: __MODEL__, - instructions: `You are a technical documentation writer. - - Writing style: - - Use clear, simple language - - Avoid jargon unless necessary - - Structure information with headers and bullet points - - Include code examples where relevant - - Write in second person ("you" instead of "the user") - - Always format responses in Markdown.`, -}); -``` - -## Using an Agent - -Once defined, you can use your agent in three ways: - -### Generate Text - -Use `generate()` for one-time text generation: - -```ts -const result = await myAgent.generate({ - prompt: 'What is the weather like?', -}); - -console.log(result.text); -``` - -### Stream Text - -Use `stream()` for streaming responses: - -```ts -const result = await myAgent.stream({ - prompt: 'Tell me a story', -}); - -for await (const chunk of result.textStream) { - console.log(chunk); -} -``` - -### Respond to UI Messages - -Use `createAgentUIStreamResponse()` to create API responses for client applications: - -```ts -// In your API route (e.g., app/api/chat/route.ts) -import { createAgentUIStreamResponse } from 'ai'; - -export async function POST(request: Request) { - const { messages } = await request.json(); - - return createAgentUIStreamResponse({ - agent: myAgent, - uiMessages: messages, - }); -} -``` - -### Track Step Progress - -Use `onStepFinish` to track each step's progress, including token usage. -The callback receives a `stepNumber` (zero-based) to identify which step just completed: - -```ts -const result = await myAgent.generate({ - prompt: 'Research and summarize the latest AI trends', - onStepFinish: async ({ stepNumber, usage, finishReason, toolCalls }) => { - console.log(`Step ${stepNumber} completed:`, { - inputTokens: usage.inputTokens, - outputTokens: usage.outputTokens, - finishReason, - toolsUsed: toolCalls?.map(tc => tc.toolName), - }); - }, -}); -``` - -You can also define `onStepFinish` in the constructor for agent-wide tracking. When both constructor and method callbacks are provided, both are called (constructor first, then the method callback): - -```ts -const agent = new ToolLoopAgent({ - model: __MODEL__, - onStepFinish: async ({ stepNumber, usage }) => { - // Agent-wide logging - console.log(`Agent step ${stepNumber}:`, usage.totalTokens); - }, -}); - -// Method-level callback runs after constructor callback -const result = await agent.generate({ - prompt: 'Hello', - onStepFinish: async ({ stepNumber, usage }) => { - // Per-call tracking (e.g., for billing) - await trackUsage(stepNumber, usage); - }, -}); -``` - -## End-to-end Type Safety - -You can infer types for your agent's `UIMessage`s: - -```ts -import { ToolLoopAgent, InferAgentUIMessage } from 'ai'; - -const myAgent = new ToolLoopAgent({ - // ... configuration -}); - -// Infer the UIMessage type for UI components or persistence -export type MyAgentUIMessage = InferAgentUIMessage; -``` - -Use this type in your client components with `useChat`: - -```tsx filename="components/chat.tsx" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import type { MyAgentUIMessage } from '@/agent/my-agent'; - -export function Chat() { - const { messages } = useChat(); - // Full type safety for your messages and tools -} -``` - -## Next Steps - -Now that you understand building agents, you can: - -- Explore [workflow patterns](/docs/agents/workflows) for structured patterns using core functions -- Learn about [loop control](/docs/agents/loop-control) for advanced execution control -- See [manual loop examples](/cookbook/node/manual-agent-loop) for custom workflow implementations diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/03-workflows.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/03-workflows.mdx deleted file mode 100644 index 3f58c1d0b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/03-workflows.mdx +++ /dev/null @@ -1,386 +0,0 @@ ---- -title: Workflow Patterns -description: Learn workflow patterns for building reliable agents with the AI SDK. ---- - -# Workflow Patterns - -Combine the building blocks from the [overview](/docs/agents/overview) with these patterns to add structure and reliability to your agents: - -- [Sequential Processing](#sequential-processing-chains) - Steps executed in order -- [Parallel Processing](#parallel-processing) - Independent tasks run simultaneously -- [Evaluation/Feedback Loops](#evaluator-optimizer) - Results checked and improved iteratively -- [Orchestration](#orchestrator-worker) - Coordinating multiple components -- [Routing](#routing) - Directing work based on context - -## Choose Your Approach - -Consider these key factors: - -- **Flexibility vs Control** - How much freedom does the LLM need vs how tightly you must constrain its actions? -- **Error Tolerance** - What are the consequences of mistakes in your use case? -- **Cost Considerations** - More complex systems typically mean more LLM calls and higher costs -- **Maintenance** - Simpler architectures are easier to debug and modify - -**Start with the simplest approach that meets your needs**. Add complexity only when required by: - -1. Breaking down tasks into clear steps -2. Adding tools for specific capabilities -3. Implementing feedback loops for quality control -4. Introducing multiple agents for complex workflows - -Let's look at examples of these patterns in action. - -## Patterns with Examples - -These patterns, adapted from [Anthropic's guide on building effective agents](https://www.anthropic.com/research/building-effective-agents), serve as building blocks you can combine to create comprehensive workflows. Each pattern addresses specific aspects of task execution. Combine them thoughtfully to build reliable solutions for complex problems. - -## Sequential Processing (Chains) - -The simplest workflow pattern executes steps in a predefined order. Each step's output becomes input for the next step, creating a clear chain of operations. Use this pattern for tasks with well-defined sequences, like content generation pipelines or data transformation processes. - -```ts -import { generateText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -async function generateMarketingCopy(input: string) { - const model = __MODEL__; - - // First step: Generate marketing copy - const { text: copy } = await generateText({ - model, - prompt: `Write persuasive marketing copy for: ${input}. Focus on benefits and emotional appeal.`, - }); - - // Perform quality check on copy - const { output: qualityMetrics } = await generateText({ - model, - output: Output.object({ - schema: z.object({ - hasCallToAction: z.boolean(), - emotionalAppeal: z.number().min(1).max(10), - clarity: z.number().min(1).max(10), - }), - }), - prompt: `Evaluate this marketing copy for: - 1. Presence of call to action (true/false) - 2. Emotional appeal (1-10) - 3. Clarity (1-10) - - Copy to evaluate: ${copy}`, - }); - - // If quality check fails, regenerate with more specific instructions - if ( - !qualityMetrics.hasCallToAction || - qualityMetrics.emotionalAppeal < 7 || - qualityMetrics.clarity < 7 - ) { - const { text: improvedCopy } = await generateText({ - model, - prompt: `Rewrite this marketing copy with: - ${!qualityMetrics.hasCallToAction ? '- A clear call to action' : ''} - ${qualityMetrics.emotionalAppeal < 7 ? '- Stronger emotional appeal' : ''} - ${qualityMetrics.clarity < 7 ? '- Improved clarity and directness' : ''} - - Original copy: ${copy}`, - }); - return { copy: improvedCopy, qualityMetrics }; - } - - return { copy, qualityMetrics }; -} -``` - -## Routing - -This pattern lets the model decide which path to take through a workflow based on context and intermediate results. The model acts as an intelligent router, directing the flow of execution between different branches of your workflow. Use this when handling varied inputs that require different processing approaches. In the example below, the first LLM call's results determine the second call's model size and system prompt. - -```ts -import { generateText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -async function handleCustomerQuery(query: string) { - const model = __MODEL__; - - // First step: Classify the query type - const { output: classification } = await generateText({ - model, - output: Output.object({ - schema: z.object({ - reasoning: z.string(), - type: z.enum(['general', 'refund', 'technical']), - complexity: z.enum(['simple', 'complex']), - }), - }), - prompt: `Classify this customer query: - ${query} - - Determine: - 1. Query type (general, refund, or technical) - 2. Complexity (simple or complex) - 3. Brief reasoning for classification`, - }); - - // Route based on classification - // Set model and system prompt based on query type and complexity - const { text: response } = await generateText({ - model: - classification.complexity === 'simple' - ? 'openai/gpt-4o-mini' - : 'openai/o4-mini', - system: { - general: - 'You are an expert customer service agent handling general inquiries.', - refund: - 'You are a customer service agent specializing in refund requests. Follow company policy and collect necessary information.', - technical: - 'You are a technical support specialist with deep product knowledge. Focus on clear step-by-step troubleshooting.', - }[classification.type], - prompt: query, - }); - - return { response, classification }; -} -``` - -## Parallel Processing - -Break down tasks into independent subtasks that execute simultaneously. This pattern uses parallel execution to improve efficiency while maintaining the benefits of structured workflows. For example, analyze multiple documents or process different aspects of a single input concurrently (like code review). - -```ts -import { generateText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -// Example: Parallel code review with multiple specialized reviewers -async function parallelCodeReview(code: string) { - const model = __MODEL__; - - // Run parallel reviews - const [securityReview, performanceReview, maintainabilityReview] = - await Promise.all([ - generateText({ - model, - system: - 'You are an expert in code security. Focus on identifying security vulnerabilities, injection risks, and authentication issues.', - output: Output.object({ - schema: z.object({ - vulnerabilities: z.array(z.string()), - riskLevel: z.enum(['low', 'medium', 'high']), - suggestions: z.array(z.string()), - }), - }), - prompt: `Review this code: - ${code}`, - }), - - generateText({ - model, - system: - 'You are an expert in code performance. Focus on identifying performance bottlenecks, memory leaks, and optimization opportunities.', - output: Output.object({ - schema: z.object({ - issues: z.array(z.string()), - impact: z.enum(['low', 'medium', 'high']), - optimizations: z.array(z.string()), - }), - }), - prompt: `Review this code: - ${code}`, - }), - - generateText({ - model, - system: - 'You are an expert in code quality. Focus on code structure, readability, and adherence to best practices.', - output: Output.object({ - schema: z.object({ - concerns: z.array(z.string()), - qualityScore: z.number().min(1).max(10), - recommendations: z.array(z.string()), - }), - }), - prompt: `Review this code: - ${code}`, - }), - ]); - - const reviews = [ - { ...securityReview.output, type: 'security' }, - { ...performanceReview.output, type: 'performance' }, - { ...maintainabilityReview.output, type: 'maintainability' }, - ]; - - // Aggregate results using another model instance - const { text: summary } = await generateText({ - model, - system: 'You are a technical lead summarizing multiple code reviews.', - prompt: `Synthesize these code review results into a concise summary with key actions: - ${JSON.stringify(reviews, null, 2)}`, - }); - - return { reviews, summary }; -} -``` - -## Orchestrator-Worker - -A primary model (orchestrator) coordinates the execution of specialized workers. Each worker optimizes for a specific subtask, while the orchestrator maintains overall context and ensures coherent results. This pattern excels at complex tasks requiring different types of expertise or processing. - -```ts -import { generateText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -async function implementFeature(featureRequest: string) { - // Orchestrator: Plan the implementation - const { output: implementationPlan } = await generateText({ - model: __MODEL__, - output: Output.object({ - schema: z.object({ - files: z.array( - z.object({ - purpose: z.string(), - filePath: z.string(), - changeType: z.enum(['create', 'modify', 'delete']), - }), - ), - estimatedComplexity: z.enum(['low', 'medium', 'high']), - }), - }), - system: - 'You are a senior software architect planning feature implementations.', - prompt: `Analyze this feature request and create an implementation plan: - ${featureRequest}`, - }); - - // Workers: Execute the planned changes - const fileChanges = await Promise.all( - implementationPlan.files.map(async file => { - // Each worker is specialized for the type of change - const workerSystemPrompt = { - create: - 'You are an expert at implementing new files following best practices and project patterns.', - modify: - 'You are an expert at modifying existing code while maintaining consistency and avoiding regressions.', - delete: - 'You are an expert at safely removing code while ensuring no breaking changes.', - }[file.changeType]; - - const { output: change } = await generateText({ - model: __MODEL__, - output: Output.object({ - schema: z.object({ - explanation: z.string(), - code: z.string(), - }), - }), - system: workerSystemPrompt, - prompt: `Implement the changes for ${file.filePath} to support: - ${file.purpose} - - Consider the overall feature context: - ${featureRequest}`, - }); - - return { - file, - implementation: change, - }; - }), - ); - - return { - plan: implementationPlan, - changes: fileChanges, - }; -} -``` - -## Evaluator-Optimizer - -Add quality control to workflows with dedicated evaluation steps that assess intermediate results. Based on the evaluation, the workflow proceeds, retries with adjusted parameters, or takes corrective action. This creates robust workflows capable of self-improvement and error recovery. - -```ts -import { generateText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -async function translateWithFeedback(text: string, targetLanguage: string) { - let currentTranslation = ''; - let iterations = 0; - const MAX_ITERATIONS = 3; - - // Initial translation - const { text: translation } = await generateText({ - model: __MODEL__, - system: 'You are an expert literary translator.', - prompt: `Translate this text to ${targetLanguage}, preserving tone and cultural nuances: - ${text}`, - }); - - currentTranslation = translation; - - // Evaluation-optimization loop - while (iterations < MAX_ITERATIONS) { - // Evaluate current translation - const { output: evaluation } = await generateText({ - model: __MODEL__, - output: Output.object({ - schema: z.object({ - qualityScore: z.number().min(1).max(10), - preservesTone: z.boolean(), - preservesNuance: z.boolean(), - culturallyAccurate: z.boolean(), - specificIssues: z.array(z.string()), - improvementSuggestions: z.array(z.string()), - }), - }), - system: 'You are an expert in evaluating literary translations.', - prompt: `Evaluate this translation: - - Original: ${text} - Translation: ${currentTranslation} - - Consider: - 1. Overall quality - 2. Preservation of tone - 3. Preservation of nuance - 4. Cultural accuracy`, - }); - - // Check if quality meets threshold - if ( - evaluation.qualityScore >= 8 && - evaluation.preservesTone && - evaluation.preservesNuance && - evaluation.culturallyAccurate - ) { - break; - } - - // Generate improved translation based on feedback - const { text: improvedTranslation } = await generateText({ - model: __MODEL__, - system: 'You are an expert literary translator.', - prompt: `Improve this translation based on the following feedback: - ${evaluation.specificIssues.join('\n')} - ${evaluation.improvementSuggestions.join('\n')} - - Original: ${text} - Current Translation: ${currentTranslation}`, - }); - - currentTranslation = improvedTranslation; - iterations++; - } - - return { - finalTranslation: currentTranslation, - iterationsRequired: iterations, - }; -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/04-loop-control.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/04-loop-control.mdx deleted file mode 100644 index e293fcf03..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/04-loop-control.mdx +++ /dev/null @@ -1,394 +0,0 @@ ---- -title: Loop Control -description: Control agent execution with built-in loop management using stopWhen and prepareStep ---- - -# Loop Control - -You can control both the execution flow and the settings at each step of the agent loop. The loop continues until: - -- A finish reasoning other than tool-calls is returned, or -- A tool that is invoked does not have an execute function, or -- A tool call needs approval, or -- A stop condition is met - -The AI SDK provides built-in loop control through two parameters: `stopWhen` for defining stopping conditions and `prepareStep` for modifying settings (model, tools, messages, and more) between steps. - -## Stop Conditions - -The `stopWhen` parameter controls when to stop execution when there are tool results in the last step. By default, agents stop after 20 steps using `stepCountIs(20)`. - -When you provide `stopWhen`, the agent continues executing after tool calls until a stopping condition is met. When the condition is an array, execution stops when any of the conditions are met. - -### Use Built-in Conditions - -The AI SDK provides several built-in stopping conditions: - -```ts -import { ToolLoopAgent, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - tools: { - // your tools - }, - stopWhen: stepCountIs(20), // Default state: stop after 20 steps maximum -}); - -const result = await agent.generate({ - prompt: 'Analyze this dataset and create a summary report', -}); -``` - -### Combine Multiple Conditions - -Combine multiple stopping conditions. The loop stops when it meets any condition: - -```ts -import { ToolLoopAgent, stepCountIs, hasToolCall } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - tools: { - // your tools - }, - stopWhen: [ - stepCountIs(20), // Maximum 20 steps - hasToolCall('someTool'), // Stop after calling 'someTool' - ], -}); - -const result = await agent.generate({ - prompt: 'Research and analyze the topic', -}); -``` - -### Create Custom Conditions - -Build custom stopping conditions for specific requirements: - -```ts -import { ToolLoopAgent, StopCondition, ToolSet } from 'ai'; -__PROVIDER_IMPORT__; - -const tools = { - // your tools -} satisfies ToolSet; - -const hasAnswer: StopCondition = ({ steps }) => { - // Stop when the model generates text containing "ANSWER:" - return steps.some(step => step.text?.includes('ANSWER:')) ?? false; -}; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - tools, - stopWhen: hasAnswer, -}); - -const result = await agent.generate({ - prompt: 'Find the answer and respond with "ANSWER: [your answer]"', -}); -``` - -Custom conditions receive step information across all steps: - -```ts -const budgetExceeded: StopCondition = ({ steps }) => { - const totalUsage = steps.reduce( - (acc, step) => ({ - inputTokens: acc.inputTokens + (step.usage?.inputTokens ?? 0), - outputTokens: acc.outputTokens + (step.usage?.outputTokens ?? 0), - }), - { inputTokens: 0, outputTokens: 0 }, - ); - - const costEstimate = - (totalUsage.inputTokens * 0.01 + totalUsage.outputTokens * 0.03) / 1000; - return costEstimate > 0.5; // Stop if cost exceeds $0.50 -}; -``` - -## Prepare Step - -The `prepareStep` callback runs before each step in the loop and defaults to the initial settings if you don't return any changes. Use it to modify settings, manage context, or implement dynamic behavior based on execution history. - -### Dynamic Model Selection - -Switch models based on step requirements: - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: 'openai/gpt-4o-mini', // Default model - tools: { - // your tools - }, - prepareStep: async ({ stepNumber, messages }) => { - // Use a stronger model for complex reasoning after initial steps - if (stepNumber > 2 && messages.length > 10) { - return { - model: __MODEL__, - }; - } - // Continue with default settings - return {}; - }, -}); - -const result = await agent.generate({ - prompt: '...', -}); -``` - -### Context Management - -Manage growing conversation history in long-running loops: - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - tools: { - // your tools - }, - prepareStep: async ({ messages }) => { - // Keep only recent messages to stay within context limits - if (messages.length > 20) { - return { - messages: [ - messages[0], // Keep system instructions - ...messages.slice(-10), // Keep last 10 messages - ], - }; - } - return {}; - }, -}); - -const result = await agent.generate({ - prompt: '...', -}); -``` - -### Tool Selection - -Control which tools are available at each step: - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - tools: { - search: searchTool, - analyze: analyzeTool, - summarize: summarizeTool, - }, - prepareStep: async ({ stepNumber, steps }) => { - // Search phase (steps 0-2) - if (stepNumber <= 2) { - return { - activeTools: ['search'], - toolChoice: 'required', - }; - } - - // Analysis phase (steps 3-5) - if (stepNumber <= 5) { - return { - activeTools: ['analyze'], - }; - } - - // Summary phase (step 6+) - return { - activeTools: ['summarize'], - toolChoice: 'required', - }; - }, -}); - -const result = await agent.generate({ - prompt: '...', -}); -``` - -You can also force a specific tool to be used: - -```ts -prepareStep: async ({ stepNumber }) => { - if (stepNumber === 0) { - // Force the search tool to be used first - return { - toolChoice: { type: 'tool', toolName: 'search' }, - }; - } - - if (stepNumber === 5) { - // Force the summarize tool after analysis - return { - toolChoice: { type: 'tool', toolName: 'summarize' }, - }; - } - - return {}; -}; -``` - -### Message Modification - -Transform messages before sending them to the model: - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - tools: { - // your tools - }, - prepareStep: async ({ messages, stepNumber }) => { - // Summarize tool results to reduce token usage - const processedMessages = messages.map(msg => { - if (msg.role === 'tool' && msg.content.length > 1000) { - return { - ...msg, - content: summarizeToolResult(msg.content), - }; - } - return msg; - }); - - return { messages: processedMessages }; - }, -}); - -const result = await agent.generate({ - prompt: '...', -}); -``` - -## Access Step Information - -Both `stopWhen` and `prepareStep` receive detailed information about the current execution: - -```ts -prepareStep: async ({ - model, // Current model configuration - stepNumber, // Current step number (0-indexed) - steps, // All previous steps with their results - messages, // Messages to be sent to the model -}) => { - // Access previous tool calls and results - const previousToolCalls = steps.flatMap(step => step.toolCalls); - const previousResults = steps.flatMap(step => step.toolResults); - - // Make decisions based on execution history - if (previousToolCalls.some(call => call.toolName === 'dataAnalysis')) { - return { - toolChoice: { type: 'tool', toolName: 'reportGenerator' }, - }; - } - - return {}; -}, -``` - -## Forced Tool Calling - -You can force the agent to always use tools by combining `toolChoice: 'required'` with a `done` tool that has no `execute` function. This pattern ensures the agent uses tools for every step and stops only when it explicitly signals completion. - -```ts -import { ToolLoopAgent, tool } from 'ai'; -import { z } from 'zod'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - tools: { - search: searchTool, - analyze: analyzeTool, - done: tool({ - description: 'Signal that you have finished your work', - inputSchema: z.object({ - answer: z.string().describe('The final answer'), - }), - // No execute function - stops the agent when called - }), - }, - toolChoice: 'required', // Force tool calls at every step -}); - -const result = await agent.generate({ - prompt: 'Research and analyze this topic, then provide your answer.', -}); - -// extract answer from done tool call -const toolCall = result.staticToolCalls[0]; // tool call from final step -if (toolCall?.toolName === 'done') { - console.log(toolCall.input.answer); -} -``` - -Key aspects of this pattern: - -- **`toolChoice: 'required'`**: Forces the model to call a tool at every step instead of generating text directly. This ensures the agent follows a structured workflow. -- **`done` tool without `execute`**: A tool that has no `execute` function acts as a termination signal. When the agent calls this tool, the loop stops because there's no function to execute. -- **Accessing results**: The final answer is available in `result.staticToolCalls`, which contains tool calls that weren't executed. - -This pattern is useful when you want the agent to always use specific tools for operations (like code execution or data retrieval) rather than attempting to answer directly. - -## Manual Loop Control - -For scenarios requiring complete control over the agent loop, you can use AI SDK Core functions (`generateText` and `streamText`) to implement your own loop management instead of using `stopWhen` and `prepareStep`. This approach provides maximum flexibility for complex workflows. - -### Implementing a Manual Loop - -Build your own agent loop when you need full control over execution: - -```ts -import { generateText, ModelMessage } from 'ai'; -__PROVIDER_IMPORT__; - -const messages: ModelMessage[] = [{ role: 'user', content: '...' }]; - -let step = 0; -const maxSteps = 10; - -while (step < maxSteps) { - const result = await generateText({ - model: __MODEL__, - messages, - tools: { - // your tools here - }, - }); - - messages.push(...result.response.messages); - - if (result.text) { - break; // Stop when model generates text - } - - step++; -} -``` - -This manual approach gives you complete control over: - -- Message history management -- Step-by-step decision making -- Custom stopping conditions -- Dynamic tool and model selection -- Error handling and recovery - -[Learn more about manual agent loops in the cookbook](/cookbook/node/manual-agent-loop). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/05-configuring-call-options.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/05-configuring-call-options.mdx deleted file mode 100644 index cb6b5533a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/05-configuring-call-options.mdx +++ /dev/null @@ -1,286 +0,0 @@ ---- -title: Configuring Call Options -description: Pass type-safe runtime inputs to dynamically configure agent behavior. ---- - -# Configuring Call Options - -Call options allow you to pass type-safe structured inputs to your agent. Use them to dynamically modify any agent setting based on the specific request. - -## Why Use Call Options? - -When you need agent behavior to change based on runtime context: - -- **Add dynamic context** - Inject retrieved documents, user preferences, or session data into prompts -- **Select models dynamically** - Choose faster or more capable models based on request complexity -- **Configure tools per request** - Pass user location to search tools or adjust tool behavior -- **Customize provider options** - Set reasoning effort, temperature, or other provider-specific settings - -Without call options, you'd need to create multiple agents or handle configuration logic outside the agent. - -## How It Works - -Define call options in three steps: - -1. **Define the schema** - Specify what inputs you accept using `callOptionsSchema` -2. **Configure with `prepareCall`** - Use those inputs to modify agent settings -3. **Pass options at runtime** - Provide the options when calling `generate()` or `stream()` - -## Basic Example - -Add user context to your agent's prompt at runtime: - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const supportAgent = new ToolLoopAgent({ - model: __MODEL__, - callOptionsSchema: z.object({ - userId: z.string(), - accountType: z.enum(['free', 'pro', 'enterprise']), - }), - instructions: 'You are a helpful customer support agent.', - prepareCall: ({ options, ...settings }) => ({ - ...settings, - instructions: - settings.instructions + - `\nUser context: -- Account type: ${options.accountType} -- User ID: ${options.userId} - -Adjust your response based on the user's account level.`, - }), -}); - -// Call the agent with specific user context -const result = await supportAgent.generate({ - prompt: 'How do I upgrade my account?', - options: { - userId: 'user_123', - accountType: 'free', - }, -}); -``` - -The `options` parameter is now required and type-checked. If you don't provide it or pass incorrect types, TypeScript will error. - -## Modifying Agent Settings - -Use `prepareCall` to modify any agent setting. Return only the settings you want to change. - -### Dynamic Model Selection - -Choose models based on request characteristics: - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const agent = new ToolLoopAgent({ - model: __MODEL__, // Default model - callOptionsSchema: z.object({ - complexity: z.enum(['simple', 'complex']), - }), - prepareCall: ({ options, ...settings }) => ({ - ...settings, - model: - options.complexity === 'simple' ? 'openai/gpt-4o-mini' : 'openai/o1-mini', - }), -}); - -// Use faster model for simple queries -await agent.generate({ - prompt: 'What is 2+2?', - options: { complexity: 'simple' }, -}); - -// Use more capable model for complex reasoning -await agent.generate({ - prompt: 'Explain quantum entanglement', - options: { complexity: 'complex' }, -}); -``` - -### Dynamic Tool Configuration - -Configure tools based on runtime context: - -```ts -import { openai } from '@ai-sdk/openai'; -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const newsAgent = new ToolLoopAgent({ - model: __MODEL__, - callOptionsSchema: z.object({ - userCity: z.string().optional(), - userRegion: z.string().optional(), - }), - tools: { - web_search: openai.tools.webSearch(), - }, - prepareCall: ({ options, ...settings }) => ({ - ...settings, - tools: { - web_search: openai.tools.webSearch({ - searchContextSize: 'low', - userLocation: { - type: 'approximate', - city: options.userCity, - region: options.userRegion, - country: 'US', - }, - }), - }, - }), -}); - -await newsAgent.generate({ - prompt: 'What are the top local news stories?', - options: { - userCity: 'San Francisco', - userRegion: 'California', - }, -}); -``` - -### Provider-Specific Options - -Configure provider settings dynamically: - -```ts -import { openai, OpenAILanguageModelResponsesOptions } from '@ai-sdk/openai'; -import { ToolLoopAgent } from 'ai'; -import { z } from 'zod'; - -const agent = new ToolLoopAgent({ - model: 'openai/o3', - callOptionsSchema: z.object({ - taskDifficulty: z.enum(['low', 'medium', 'high']), - }), - prepareCall: ({ options, ...settings }) => ({ - ...settings, - providerOptions: { - openai: { - reasoningEffort: options.taskDifficulty, - } satisfies OpenAILanguageModelResponsesOptions, - }, - }), -}); - -await agent.generate({ - prompt: 'Analyze this complex scenario...', - options: { taskDifficulty: 'high' }, -}); -``` - -## Advanced Patterns - -### Retrieval Augmented Generation (RAG) - -Fetch relevant context and inject it into your prompt: - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const ragAgent = new ToolLoopAgent({ - model: __MODEL__, - callOptionsSchema: z.object({ - query: z.string(), - }), - prepareCall: async ({ options, ...settings }) => { - // Fetch relevant documents (this can be async) - const documents = await vectorSearch(options.query); - - return { - ...settings, - instructions: `Answer questions using the following context: - -${documents.map(doc => doc.content).join('\n\n')}`, - }; - }, -}); - -await ragAgent.generate({ - prompt: 'What is our refund policy?', - options: { query: 'refund policy' }, -}); -``` - -The `prepareCall` function can be async, enabling you to fetch data before configuring the agent. - -### Combining Multiple Modifications - -Modify multiple settings together: - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - callOptionsSchema: z.object({ - userRole: z.enum(['admin', 'user']), - urgency: z.enum(['low', 'high']), - }), - tools: { - readDatabase: readDatabaseTool, - writeDatabase: writeDatabaseTool, - }, - prepareCall: ({ options, ...settings }) => ({ - ...settings, - // Upgrade model for urgent requests - model: options.urgency === 'high' ? __MODEL__ : settings.model, - // Limit tools based on user role - activeTools: - options.userRole === 'admin' - ? ['readDatabase', 'writeDatabase'] - : ['readDatabase'], - // Adjust instructions - instructions: `You are a ${options.userRole} assistant. -${options.userRole === 'admin' ? 'You have full database access.' : 'You have read-only access.'}`, - }), -}); - -await agent.generate({ - prompt: 'Update the user record', - options: { - userRole: 'admin', - urgency: 'high', - }, -}); -``` - -## Using with createAgentUIStreamResponse - -Pass call options through API routes to your agent: - -```ts filename="app/api/chat/route.ts" -import { createAgentUIStreamResponse } from 'ai'; -import { myAgent } from '@/ai/agents/my-agent'; - -export async function POST(request: Request) { - const { messages, userId, accountType } = await request.json(); - - return createAgentUIStreamResponse({ - agent: myAgent, - messages, - options: { - userId, - accountType, - }, - }); -} -``` - -## Next Steps - -- Learn about [loop control](/docs/agents/loop-control) for execution management -- Explore [workflow patterns](/docs/agents/workflows) for complex multi-step processes diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/06-memory.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/06-memory.mdx deleted file mode 100644 index 3422cca72..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/06-memory.mdx +++ /dev/null @@ -1,222 +0,0 @@ ---- -title: Memory -description: Add persistent memory to your agent using provider-defined tools, memory providers, or a custom tool. ---- - -# Memory - -Memory lets your agent save information and recall it later. Without memory, every conversation starts fresh. With memory, your agent builds context over time, recalls previous interactions, and adapts to the user. - -## Three Approaches - -You can add memory to your agent with the AI SDK in three ways, each with different tradeoffs: - -| Approach | Effort | Flexibility | Provider Lock-in | -| ------------------------------------------------- | ------ | ----------- | -------------------------- | -| [Provider-Defined Tools](#provider-defined-tools) | Low | Medium | Yes | -| [Memory Providers](#memory-providers) | Low | Low | Depends on memory provider | -| [Custom Tool](#custom-tool) | High | High | No | - -## Provider-Defined Tools - -[Provider-defined tools](/docs/foundations/tools#types-of-tools) are tools where the provider specifies the tool's `inputSchema` and `description`, but you provide the `execute` function. The model has been trained to use these tools, which can result in better performance compared to custom tools. - -### Anthropic Memory Tool - -The [Anthropic Memory Tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool) gives Claude a structured interface for managing a `/memories` directory. Claude reads its memory before starting tasks, creates and updates files as it works, and references them in future conversations. - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -import { ToolLoopAgent } from 'ai'; - -const memory = anthropic.tools.memory_20250818({ - execute: async action => { - // `action` contains `command`, `path`, and other fields - // depending on the command (view, create, str_replace, - // insert, delete, rename). - // Implement your storage backend here. - // Return the result as a string. - }, -}); - -const agent = new ToolLoopAgent({ - model: 'anthropic/claude-haiku-4.5', - tools: { memory }, -}); - -const result = await agent.generate({ - prompt: 'Remember that my favorite editor is Neovim', -}); -``` - -The tool receives structured commands (`view`, `create`, `str_replace`, `insert`, `delete`, `rename`), each with a `path` scoped to `/memories`. Your `execute` function maps these to your storage backend (the filesystem, a database, or any other persistence layer). - -**When to use this**: you want memory with minimal implementation effort and are already using Anthropic models. The tradeoff is provider lock-in, since this tool only works with Claude. - -## Memory Providers - -Another approach is to use a provider that has memory built in. These providers wrap an external memory service and expose it through the AI SDK's standard interface. Memory storage, retrieval, and injection happen transparently, and you do not define any tools yourself. - -### Letta - -[Letta](https://letta.com) provides agents with persistent long-term memory. You create an agent on Letta's platform (cloud or self-hosted), configure its memory there, and use the AI SDK provider to interact with it. Letta's agent runtime handles memory management (core memory, archival memory, recall). - -```bash -pnpm add @letta-ai/vercel-ai-sdk-provider -``` - -```ts -import { lettaCloud } from '@letta-ai/vercel-ai-sdk-provider'; -import { ToolLoopAgent } from 'ai'; - -const agent = new ToolLoopAgent({ - model: lettaCloud(), - providerOptions: { - letta: { - agent: { id: 'your-agent-id' }, - }, - }, -}); - -const result = await agent.generate({ - prompt: 'Remember that my favorite editor is Neovim', -}); -``` - -You can also use Letta's built-in memory tools alongside custom tools: - -```ts -import { lettaCloud } from '@letta-ai/vercel-ai-sdk-provider'; -import { ToolLoopAgent } from 'ai'; - -const agent = new ToolLoopAgent({ - model: lettaCloud(), - tools: { - core_memory_append: lettaCloud.tool('core_memory_append'), - memory_insert: lettaCloud.tool('memory_insert'), - memory_replace: lettaCloud.tool('memory_replace'), - }, - providerOptions: { - letta: { - agent: { id: 'your-agent-id' }, - }, - }, -}); - -const stream = agent.stream({ - prompt: 'What do you remember about me?', -}); -``` - -See the [Letta provider documentation](/providers/community-providers/letta) for full setup and configuration. - -### Mem0 - -[Mem0](https://mem0.ai) adds a memory layer on top of any supported LLM provider. It automatically extracts memories from conversations, stores them, and retrieves relevant ones for future prompts. - -```bash -pnpm add @mem0/vercel-ai-provider -``` - -```ts -import { createMem0 } from '@mem0/vercel-ai-provider'; -import { ToolLoopAgent } from 'ai'; - -const mem0 = createMem0({ - provider: 'openai', - mem0ApiKey: process.env.MEM0_API_KEY, - apiKey: process.env.OPENAI_API_KEY, -}); - -const agent = new ToolLoopAgent({ - model: mem0('gpt-4.1', { user_id: 'user-123' }), -}); - -const { text } = await agent.generate({ - prompt: 'Remember that my favorite editor is Neovim', -}); -``` - -Mem0 works across multiple LLM providers (OpenAI, Anthropic, Google, Groq, Cohere). You can also manage memories explicitly: - -```ts -import { addMemories, retrieveMemories } from '@mem0/vercel-ai-provider'; - -await addMemories(messages, { user_id: 'user-123' }); -const context = await retrieveMemories(prompt, { user_id: 'user-123' }); -``` - -See the [Mem0 provider documentation](/providers/community-providers/mem0) for full setup and configuration. - -### Supermemory - -[Supermemory](https://supermemory.ai) is a long-term memory platform that adds persistent, self-growing memory to your AI applications. It provides tools that handle saving and retrieving memories automatically through semantic search. - -```bash -pnpm add @supermemory/tools -``` - -```ts -__PROVIDER_IMPORT__; -import { supermemoryTools } from '@supermemory/tools/ai-sdk'; -import { ToolLoopAgent } from 'ai'; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!), -}); - -const result = await agent.generate({ - prompt: 'Remember that my favorite editor is Neovim', -}); -``` - -Supermemory works with any AI SDK provider. The tools give the model `addMemory` and `searchMemories` operations that handle storage and retrieval. - -See the [Supermemory provider documentation](/providers/community-providers/supermemory) for full setup and configuration. - -### Hindsight - -[Hindsight](/providers/community-providers/hindsight) provides agents with persistent memory through five tools: `retain`, `recall`, `reflect`, `getMentalModel`, and `getDocument`. It can be self-hosted with Docker or used as a cloud service. - -```bash -pnpm add @vectorize-io/hindsight-ai-sdk @vectorize-io/hindsight-client -``` - -```ts -__PROVIDER_IMPORT__; -import { HindsightClient } from '@vectorize-io/hindsight-client'; -import { createHindsightTools } from '@vectorize-io/hindsight-ai-sdk'; -import { ToolLoopAgent, stepCountIs } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const client = new HindsightClient({ baseUrl: process.env.HINDSIGHT_API_URL }); - -const agent = new ToolLoopAgent({ - model: __MODEL__, - tools: createHindsightTools({ client, bankId: 'user-123' }), - stopWhen: stepCountIs(10), - instructions: 'You are a helpful assistant with long-term memory.', -}); - -const result = await agent.generate({ - prompt: 'Remember that my favorite editor is Neovim', -}); -``` - -The `bankId` identifies the memory store and is typically a user ID. In multi-user apps, call `createHindsightTools` inside your request handler so each request gets the right bank. Hindsight works with any AI SDK provider. - -See the [Hindsight provider documentation](/providers/community-providers/hindsight) for full setup and configuration. - -**When to use memory providers**: these providers are a good fit when you want memory without building any storage infrastructure. The tradeoff is that the provider controls memory behavior, so you have less visibility into what gets stored and how it is retrieved. You also take on a dependency on an external service. - -## Custom Tool - -Building your own memory tool from scratch is the most flexible approach. You control the storage format, the interface, and the retrieval logic. This requires the most upfront work but gives you full ownership of how memory works, with no provider lock-in and no external dependencies. - -There are two common patterns: - -- **Structured actions**: you define explicit operations (`view`, `create`, `update`, `search`) and handle structured input yourself. Safe by design since you control every operation. -- **Bash-backed**: you give the model a sandboxed bash environment to compose shell commands (`cat`, `grep`, `sed`, `echo`) for flexible memory access. More powerful but requires command validation for safety. - -For a full walkthrough of implementing a custom memory tool with a bash-backed interface, AST-based command validation, and filesystem persistence, see the **[Build a Custom Memory Tool](/cookbook/guides/custom-memory-tool)** recipe. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/06-subagents.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/06-subagents.mdx deleted file mode 100644 index b13c1ecaa..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/06-subagents.mdx +++ /dev/null @@ -1,362 +0,0 @@ ---- -title: Subagents -description: Delegate context-heavy tasks to specialized subagents while keeping the main agent focused. ---- - -# Subagents - -A subagent is an agent that a parent agent can invoke. The parent delegates work via a tool, and the subagent executes autonomously before returning a result. - -## How It Works - -1. **Define a subagent** with its own model, instructions, and tools -2. **Create a tool that calls it** for the main agent to use -3. **Subagent runs independently with its own context window** -4. **Return a result** (optionally streaming progress to the UI) -5. **Control what the model sees** using `toModelOutput` to summarize - -## When to Use Subagents - -Subagents add latency and complexity. Use them when the benefits outweigh the costs: - -| Use Subagents When | Avoid Subagents When | -| ----------------------------------------------- | ------------------------------ | -| Tasks require exploring large amounts of tokens | Tasks are simple and focused | -| You need to parallelize independent research | Sequential processing suffices | -| Context would grow beyond model limits | Context stays manageable | -| You want to isolate tool access by capability | All tools can safely coexist | - -## Why Use Subagents? - -### Offloading Context-Heavy Tasks - -Some tasks require exploring large amounts of information—reading files, searching codebases, or researching topics. Running these in the main agent consumes context quickly, making the agent less coherent over time. - -With subagents, you can: - -- Spin up a dedicated agent that uses hundreds of thousands of tokens -- Have it return only a focused summary (perhaps 1,000 tokens) -- Keep your main agent's context clean and coherent - -The subagent does the heavy lifting while the main agent stays focused on orchestration. - -### Parallelizing Independent Work - -For tasks like exploring a codebase, you can spawn multiple subagents to research different areas simultaneously. Each returns a summary, and the main agent synthesizes the findings—without paying the context cost of all that exploration. - -### Specialized Orchestration - -A less common but valid pattern is using a main agent purely for orchestration, delegating to specialized subagents for different types of work. For example: - -- An exploration subagent with read-only tools for researching codebases -- A coding subagent with file editing tools -- An integration subagent with tools for a specific platform or API - -This creates a clear separation of concerns, though context offloading and parallelization are the more common motivations for subagents. - -## Basic Subagent Without Streaming - -The simplest subagent pattern requires no special machinery. Your main agent has a tool that calls another agent in its `execute` function: - -```ts -import { ToolLoopAgent, tool } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -// Define a subagent for research tasks -const researchSubagent = new ToolLoopAgent({ - model: __MODEL__, - instructions: `You are a research agent. -Summarize your findings in your final response.`, - tools: { - read: readFileTool, // defined elsewhere - search: searchTool, // defined elsewhere - }, -}); - -// Create a tool that delegates to the subagent -const researchTool = tool({ - description: 'Research a topic or question in depth.', - inputSchema: z.object({ - task: z.string().describe('The research task to complete'), - }), - execute: async ({ task }, { abortSignal }) => { - const result = await researchSubagent.generate({ - prompt: task, - abortSignal, - }); - return result.text; - }, -}); - -// Main agent uses the research tool -const mainAgent = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are a helpful assistant that can delegate research tasks.', - tools: { - research: researchTool, - }, -}); -``` - -This works well when you don't need to show the subagent's progress in the UI. The tool call blocks until the subagent completes, then returns the final text response. - -### Handling Cancellation - -When the user cancels a request, the `abortSignal` propagates to the subagent. Always pass it through to ensure cleanup: - -```ts -execute: async ({ task }, { abortSignal }) => { - const result = await researchSubagent.generate({ - prompt: task, - abortSignal, // Cancels subagent if main request is aborted - }); - return result.text; -}, -``` - -If you abort the signal, the subagent stops executing and throws an `AbortError`. The main agent's tool execution fails, which stops the main loop. - -To avoid errors about incomplete tool calls in subsequent messages, use `convertToModelMessages` with `ignoreIncompleteToolCalls`: - -```ts -import { convertToModelMessages } from 'ai'; - -const modelMessages = await convertToModelMessages(messages, { - ignoreIncompleteToolCalls: true, -}); -``` - -This filters out tool calls that don't have corresponding results. Learn more in the [convertToModelMessages](/docs/reference/ai-sdk-ui/convert-to-model-messages) reference. - -## Streaming Subagent Progress - -When you want to show incremental progress as the subagent works, use [**preliminary tool results**](/docs/ai-sdk-core/tools-and-tool-calling#preliminary-tool-results). This pattern uses a generator function that yields partial updates to the UI. - -### How Preliminary Tool Results Work - -Change your `execute` function from a regular function to an async generator (`async function*`). Each `yield` sends a preliminary result to the frontend: - -```ts -execute: async function* ({ /* input */ }) { - // ... do work ... - yield partialResult; - // ... do more work ... - yield updatedResult; -} -``` - -### Building the Complete Message - -Each `yield` **replaces** the previous output entirely (it does not append). This means you need a way to accumulate the subagent's response into a complete message that grows over time. - -The `readUIMessageStream` utility handles this. It reads each chunk from the stream and builds an ever-growing `UIMessage` containing all parts received so far: - -```ts -import { readUIMessageStream, tool } from 'ai'; -import { z } from 'zod'; - -const researchTool = tool({ - description: 'Research a topic or question in depth.', - inputSchema: z.object({ - task: z.string().describe('The research task to complete'), - }), - execute: async function* ({ task }, { abortSignal }) { - // Start the subagent with streaming - const result = await researchSubagent.stream({ - prompt: task, - abortSignal, - }); - - // Each iteration yields a complete, accumulated UIMessage - for await (const message of readUIMessageStream({ - stream: result.toUIMessageStream(), - })) { - yield message; - } - }, -}); -``` - -Each yielded `message` is a complete `UIMessage` containing all the subagent's parts up to that point (text, tool calls, and tool results). The frontend simply replaces its display with each new message. - -## Controlling What the Model Sees - -Here's where subagents become powerful for context management. The full `UIMessage` with all the subagent's work is stored in the message history and displayed in the UI. But you can control what the main agent's model actually sees using `toModelOutput`. - -### How It Works - -The `toModelOutput` function maps the tool's output to the tokens sent to the model: - -```ts -const researchTool = tool({ - description: 'Research a topic or question in depth.', - inputSchema: z.object({ - task: z.string().describe('The research task to complete'), - }), - execute: async function* ({ task }, { abortSignal }) { - const result = await researchSubagent.stream({ - prompt: task, - abortSignal, - }); - - for await (const message of readUIMessageStream({ - stream: result.toUIMessageStream(), - })) { - yield message; - } - }, - toModelOutput: ({ output: message }) => { - // Extract just the final text as a summary - const lastTextPart = message?.parts.findLast(p => p.type === 'text'); - return { - type: 'text', - value: lastTextPart?.text ?? 'Task completed.', - }; - }, -}); -``` - -With this setup: - -- **Users see**: The full subagent execution—every tool call, every intermediate step -- **The model sees**: Just the final summary text - -The subagent might use 100,000 tokens exploring and reasoning, but the main agent only consumes the summary. This keeps the main agent coherent and focused. - -### Write Subagent Instructions for Summarization - -For `toModelOutput` to extract a useful summary, your subagent must produce one. Add explicit instructions like this: - -```ts -const researchSubagent = new ToolLoopAgent({ - model: __MODEL__, - instructions: `You are a research agent. Complete the task autonomously. - -IMPORTANT: When you have finished, write a clear summary of your findings as your final response. -This summary will be returned to the main agent, so include all relevant information.`, - tools: { - read: readFileTool, - search: searchTool, - }, -}); -``` - -Without this instruction, the subagent might not produce a comprehensive summary. It could simply say "Done", leaving `toModelOutput` with nothing useful to extract. - -## Rendering Subagents in the UI (with useChat) - -To display streaming progress, check the tool part's `state` and `preliminary` flag. - -### Tool Part States - -| State | Description | -| ------------------ | ------------------------------------------ | -| `input-streaming` | Tool input being generated | -| `input-available` | Tool ready to execute | -| `output-available` | Tool produced output (check `preliminary`) | -| `output-error` | Tool execution failed | - -### Detecting Streaming vs Complete - -```tsx -const hasOutput = part.state === 'output-available'; -const isStreaming = hasOutput && part.preliminary === true; -const isComplete = hasOutput && !part.preliminary; -``` - -### Type Safety for Subagent Output - -Export types alongside your agents for use in UI components: - -```ts filename="lib/agents.ts" -import { ToolLoopAgent, InferAgentUIMessage } from 'ai'; - -export const mainAgent = new ToolLoopAgent({ - // ... configuration with researchTool -}); - -// Export the main agent message type for the chat UI -export type MainAgentMessage = InferAgentUIMessage; -``` - -### Render Messages and Subagent Output - -This example uses the types defined above to render both the main agent's messages and the subagent's streamed output: - -```tsx -'use client'; - -import { useChat } from '@ai-sdk/react'; -import type { MainAgentMessage } from '@/lib/agents'; - -export function Chat() { - const { messages } = useChat(); - - return ( -
- {messages.map(message => - message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return

{part.text}

; - case 'tool-research': - return ( -
- {part.state !== 'input-streaming' && ( -
Research: {part.input.task}
- )} - {part.state === 'output-available' && ( -
- {part.output.parts.map((nestedPart, i) => { - switch (nestedPart.type) { - case 'text': - return

{nestedPart.text}

; - default: - return null; - } - })} -
- )} -
- ); - default: - return null; - } - }), - )} -
- ); -} -``` - -## Caveats - -### No Tool Approvals in Subagents - -Subagent tools cannot use `needsApproval`. All tools must execute automatically without user confirmation. - -### Subagent Context is Isolated - -Each subagent invocation starts with a fresh context window. This is one of the key benefits of subagents: they don't inherit the accumulated context from the main agent, which is exactly what allows them to do heavy exploration without bloating the main conversation. - -If you need to give a subagent access to the conversation history, the `messages` are available in the tool's execute function alongside `abortSignal`: - -```ts -execute: async ({ task }, { abortSignal, messages }) => { - const result = await researchSubagent.generate({ - messages: [ - ...messages, // The main agent's conversation history - { role: 'user', content: task }, // The specific task for this invocation - ], - abortSignal, - }); - return result.text; -}, -``` - -Use this sparingly since passing full history defeats some of the context isolation benefits. - -### Streaming Adds Complexity - -The basic pattern (no streaming) is simpler to implement and debug. Only add streaming when you need to show real-time progress in the UI. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/index.mdx deleted file mode 100644 index 156c35407..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-agents/index.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Agents -description: An overview of building agents with the AI SDK. ---- - -# Agents - -The following section shows you how to build agents with the AI SDK - systems where large language models (LLMs) use tools in a loop to accomplish tasks. - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/01-overview.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/01-overview.mdx deleted file mode 100644 index 5a3917e13..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/01-overview.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Overview -description: An overview of AI SDK Core. ---- - -# AI SDK Core - -Large Language Models (LLMs) are advanced programs that can understand, create, and engage with human language on a large scale. -They are trained on vast amounts of written material to recognize patterns in language and predict what might come next in a given piece of text. - -AI SDK Core **simplifies working with LLMs by offering a standardized way of integrating them into your app** - so you can focus on building great AI applications for your users, not waste time on technical details. - -For example, here’s how you can generate text with various models using the AI SDK: - - - -## AI SDK Core Functions - -AI SDK Core has various functions designed for [text generation](./generating-text), [structured data generation](./generating-structured-data), and [tool usage](./tools-and-tool-calling). -These functions take a standardized approach to setting up [prompts](./prompts) and [settings](./settings), making it easier to work with different models. - -- [`generateText`](/docs/ai-sdk-core/generating-text): Generates text and [tool calls](./tools-and-tool-calling). - This function is ideal for non-interactive use cases such as automation tasks where you need to write text (e.g. drafting email or summarizing web pages) and for agents that use tools. -- [`streamText`](/docs/ai-sdk-core/generating-text): Stream text and tool calls. - You can use the `streamText` function for interactive use cases such as [chat bots](/docs/ai-sdk-ui/chatbot) and [content streaming](/docs/ai-sdk-ui/completion). - -Both `generateText` and `streamText` support [structured output](/docs/ai-sdk-core/generating-structured-data) via the `output` property (e.g. `Output.object()`, `Output.array()`), allowing you to generate typed, schema-validated data for information extraction, synthetic data generation, classification tasks, and [streaming generated UIs](/docs/ai-sdk-ui/object-generation). - -## API Reference - -Please check out the [AI SDK Core API Reference](/docs/reference/ai-sdk-core) for more details on each function. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/05-generating-text.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/05-generating-text.mdx deleted file mode 100644 index e5db18021..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/05-generating-text.mdx +++ /dev/null @@ -1,707 +0,0 @@ ---- -title: Generating Text -description: Learn how to generate text with the AI SDK. ---- - -# Generating and Streaming Text - -Large language models (LLMs) can generate text in response to a prompt, which can contain instructions and information to process. -For example, you can ask a model to come up with a recipe, draft an email, or summarize a document. - -The AI SDK Core provides two functions to generate text and stream it from LLMs: - -- [`generateText`](#generatetext): Generates text for a given prompt and model. -- [`streamText`](#streamtext): Streams text from a given prompt and model. - -Advanced LLM features such as [tool calling](./tools-and-tool-calling) and [structured data generation](./generating-structured-data) are built on top of text generation. - -## `generateText` - -You can generate text using the [`generateText`](/docs/reference/ai-sdk-core/generate-text) function. This function is ideal for non-interactive use cases where you need to write text (e.g. drafting email or summarizing web pages) and for agents that use tools. - -```tsx -import { generateText } from 'ai'; -__PROVIDER_IMPORT__; - -const { text } = await generateText({ - model: __MODEL__, - prompt: 'Write a vegetarian lasagna recipe for 4 people.', -}); -``` - -You can use more [advanced prompts](./prompts) to generate text with more complex instructions and content: - -```tsx -import { generateText } from 'ai'; -__PROVIDER_IMPORT__; - -const { text } = await generateText({ - model: __MODEL__, - system: - 'You are a professional writer. ' + - 'You write simple, clear, and concise content.', - prompt: `Summarize the following article in 3-5 sentences: ${article}`, -}); -``` - -The result object of `generateText` contains several promises that resolve when all required data is available: - -- `result.content`: The content that was generated in the last step. -- `result.text`: The generated text. -- `result.reasoning`: The full reasoning that the model has generated in the last step. -- `result.reasoningText`: The reasoning text of the model (only available for some models). -- `result.files`: The files that were generated in the last step. -- `result.sources`: Sources that have been used as references in the last step (only available for some models). -- `result.toolCalls`: The tool calls that were made in the last step. -- `result.toolResults`: The results of the tool calls from the last step. -- `result.finishReason`: The reason the model finished generating text. -- `result.rawFinishReason`: The raw reason why the generation finished (from the provider). -- `result.usage`: The usage of the model during the final step of text generation. -- `result.totalUsage`: The total usage across all steps (for multi-step generations). -- `result.warnings`: Warnings from the model provider (e.g. unsupported settings). -- `result.request`: Additional request information. -- `result.response`: Additional response information, including response messages and body. -- `result.providerMetadata`: Additional provider-specific metadata. -- `result.steps`: Details for all steps, useful for getting information about intermediate steps. -- `result.output`: The generated structured output using the `output` specification. - -### Accessing response headers & body - -Sometimes you need access to the full response from the model provider, -e.g. to access some provider-specific headers or body content. - -You can access the raw response headers and body using the `response` property: - -```ts -import { generateText } from 'ai'; - -const result = await generateText({ - // ... -}); - -console.log(JSON.stringify(result.response.headers, null, 2)); -console.log(JSON.stringify(result.response.body, null, 2)); -``` - -### `onFinish` callback - -When using `generateText`, you can provide an `onFinish` callback that is triggered after the last step is finished ( -[API Reference](/docs/reference/ai-sdk-core/generate-text#on-finish) -). -It contains the text, usage information, finish reason, messages, steps, total usage, and more: - -```tsx highlight="6-8" -import { generateText } from 'ai'; -__PROVIDER_IMPORT__; - -const result = await generateText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', - onFinish({ text, finishReason, usage, response, steps, totalUsage }) { - // your own logic, e.g. for saving the chat history or recording usage - - const messages = response.messages; // messages that were generated - }, -}); -``` - -### Lifecycle callbacks (experimental) - - - Experimental callbacks are subject to breaking changes in incremental package - releases. - - -`generateText` provides several experimental lifecycle callbacks that let you hook into different phases of the generation process. -These are useful for logging, observability, debugging, and custom telemetry. -Errors thrown inside these callbacks are silently caught and do not break the generation flow. - -```tsx -import { generateText } from 'ai'; -__PROVIDER_IMPORT__; - -const result = await generateText({ - model: __MODEL__, - prompt: 'What is the weather in San Francisco?', - tools: { - // ... your tools - }, - - experimental_onStart({ model, settings, functionId }) { - console.log('Generation started', { model, functionId }); - }, - - experimental_onStepStart({ stepNumber, model, promptMessages }) { - console.log(`Step ${stepNumber} starting`, { model: model.modelId }); - }, - - experimental_onToolCallStart({ toolName, toolCallId, input }) { - console.log(`Tool call starting: ${toolName}`, { toolCallId }); - }, - - experimental_onToolCallFinish({ toolName, durationMs, error }) { - console.log(`Tool call finished: ${toolName} (${durationMs}ms)`, { - success: !error, - }); - }, - - onStepFinish({ stepNumber, finishReason, usage }) { - console.log(`Step ${stepNumber} finished`, { finishReason, usage }); - }, -}); -``` - -The available lifecycle callbacks are: - -- **`experimental_onStart`**: Called once when the `generateText` operation begins, before any LLM calls. Receives model info, prompt, settings, and telemetry metadata. -- **`experimental_onStepStart`**: Called before each step (LLM call). Receives the step number, model, prompt messages being sent, tools, and prior steps. -- **`experimental_onToolCallStart`**: Called right before a tool's `execute` function runs. Receives the tool name, call ID, and input. -- **`experimental_onToolCallFinish`**: Called right after a tool's `execute` function completes or errors. Receives the tool name, call ID, input, output (or undefined on error), error (or undefined on success), and `durationMs`. -- **`onStepFinish`**: Called after each step finishes. Now also includes `stepNumber` (zero-based index of the completed step). - -## `streamText` - -Depending on your model and prompt, it can take a large language model (LLM) up to a minute to finish generating its response. This delay can be unacceptable for interactive use cases such as chatbots or real-time applications, where users expect immediate responses. - -AI SDK Core provides the [`streamText`](/docs/reference/ai-sdk-core/stream-text) function which simplifies streaming text from LLMs: - -```ts -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const result = streamText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', -}); - -// example: use textStream as an async iterable -for await (const textPart of result.textStream) { - console.log(textPart); -} -``` - - - `result.textStream` is both a `ReadableStream` and an `AsyncIterable`. - - - - `streamText` immediately starts streaming and suppresses errors to prevent - server crashes. Use the `onError` callback to log errors. - - -You can use `streamText` on its own or in combination with [AI SDK -UI](/examples/next-pages/basics/streaming-text-generation) and [AI SDK -RSC](/examples/next-app/basics/streaming-text-generation). -The result object contains several helper functions to make the integration into [AI SDK UI](/docs/ai-sdk-ui) easier: - -- `result.toUIMessageStreamResponse()`: Creates a UI Message stream HTTP response (with tool calls etc.) that can be used in a Next.js App Router API route. -- `result.pipeUIMessageStreamToResponse()`: Writes UI Message stream delta output to a Node.js response-like object. -- `result.toTextStreamResponse()`: Creates a simple text stream HTTP response. -- `result.pipeTextStreamToResponse()`: Writes text delta output to a Node.js response-like object. - - - `streamText` is using backpressure and only generates tokens as they are - requested. You need to consume the stream in order for it to finish. - - -It also provides several promises that resolve when the stream is finished: - -- `result.content`: The content that was generated in the last step. -- `result.text`: The generated text. -- `result.reasoning`: The full reasoning that the model has generated. -- `result.reasoningText`: The reasoning text of the model (only available for some models). -- `result.files`: Files that have been generated by the model in the last step. -- `result.sources`: Sources that have been used as references in the last step (only available for some models). -- `result.toolCalls`: The tool calls that have been executed in the last step. -- `result.toolResults`: The tool results that have been generated in the last step. -- `result.finishReason`: The reason the model finished generating text. -- `result.rawFinishReason`: The raw reason why the generation finished (from the provider). -- `result.usage`: The usage of the model during the final step of text generation. -- `result.totalUsage`: The total usage across all steps (for multi-step generations). -- `result.warnings`: Warnings from the model provider (e.g. unsupported settings). -- `result.steps`: Details for all steps, useful for getting information about intermediate steps. -- `result.request`: Additional request information from the last step. -- `result.response`: Additional response information from the last step. -- `result.providerMetadata`: Additional provider-specific metadata from the last step. - -### `onError` callback - -`streamText` immediately starts streaming to enable sending data without waiting for the model. -Errors become part of the stream and are not thrown to prevent e.g. servers from crashing. - -To log errors, you can provide an `onError` callback that is triggered when an error occurs. - -```tsx highlight="6-8" -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const result = streamText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', - onError({ error }) { - console.error(error); // your error logging logic here - }, -}); -``` - -### `onChunk` callback - -When using `streamText`, you can provide an `onChunk` callback that is triggered for each chunk of the stream. - -It receives the following chunk types: - -- `text` -- `reasoning` -- `source` -- `tool-call` -- `tool-input-start` -- `tool-input-delta` -- `tool-result` -- `raw` - -```tsx highlight="6-11" -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const result = streamText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', - onChunk({ chunk }) { - // implement your own logic here, e.g.: - if (chunk.type === 'text') { - console.log(chunk.text); - } - }, -}); -``` - -### `onFinish` callback - -When using `streamText`, you can provide an `onFinish` callback that is triggered when the stream is finished ( -[API Reference](/docs/reference/ai-sdk-core/stream-text#on-finish) -). -It contains the text, usage information, finish reason, messages, steps, total usage, and more: - -```tsx highlight="6-8" -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const result = streamText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', - onFinish({ text, finishReason, usage, response, steps, totalUsage }) { - // your own logic, e.g. for saving the chat history or recording usage - - const messages = response.messages; // messages that were generated - }, -}); -``` - -### Lifecycle callbacks (experimental) - - - Experimental callbacks are subject to breaking changes in incremental package - releases. - - -`streamText` provides several experimental lifecycle callbacks that let you hook into different phases of the streaming process. -These are useful for logging, observability, debugging, and custom telemetry. -Errors thrown inside these callbacks are silently caught and do not break the streaming flow. - -```tsx -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const result = streamText({ - model: __MODEL__, - prompt: 'What is the weather in San Francisco?', - tools: { - // ... your tools - }, - - experimental_onStart({ model, system, prompt, messages }) { - console.log('Streaming started', { model, prompt }); - }, - - experimental_onStepStart({ stepNumber, model, messages }) { - console.log(`Step ${stepNumber} starting`, { model: model.modelId }); - }, - - experimental_onToolCallStart({ toolCall }) { - console.log(`Tool call starting: ${toolCall.toolName}`, { - toolCallId: toolCall.toolCallId, - }); - }, - - experimental_onToolCallFinish({ toolCall, durationMs, success, error }) { - console.log(`Tool call finished: ${toolCall.toolName} (${durationMs}ms)`, { - success, - }); - }, - - onStepFinish({ finishReason, usage }) { - console.log('Step finished', { finishReason, usage }); - }, -}); -``` - -The available lifecycle callbacks are: - -- **`experimental_onStart`**: Called once when the `streamText` operation begins, before any LLM calls. Receives model info, prompt, settings, and telemetry metadata. -- **`experimental_onStepStart`**: Called before each step (LLM call). Receives the step number, model, messages being sent, tools, and prior steps. -- **`experimental_onToolCallStart`**: Called right before a tool's `execute` function runs. Receives the tool call object, messages, and context. -- **`experimental_onToolCallFinish`**: Called right after a tool's `execute` function completes or errors. Receives the tool call object, `durationMs`, and a discriminated union with `success`/`output` or `success`/`error`. -- **`onStepFinish`**: Called after each step finishes. Receives the finish reason, usage, and other step details. - -### `fullStream` property - -You can read a stream with all events using the `fullStream` property. -This can be useful if you want to implement your own UI or handle the stream in a different way. -Here is an example of how to use the `fullStream` property: - -```tsx -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const result = streamText({ - model: __MODEL__, - tools: { - cityAttractions: { - inputSchema: z.object({ city: z.string() }), - execute: async ({ city }) => ({ - attractions: ['attraction1', 'attraction2', 'attraction3'], - }), - }, - }, - prompt: 'What are some San Francisco tourist attractions?', -}); - -for await (const part of result.fullStream) { - switch (part.type) { - case 'start': { - // handle start of stream - break; - } - case 'start-step': { - // handle start of step - break; - } - case 'text-start': { - // handle text start - break; - } - case 'text-delta': { - // handle text delta here - break; - } - case 'text-end': { - // handle text end - break; - } - case 'reasoning-start': { - // handle reasoning start - break; - } - case 'reasoning-delta': { - // handle reasoning delta here - break; - } - case 'reasoning-end': { - // handle reasoning end - break; - } - case 'source': { - // handle source here - break; - } - case 'file': { - // handle file here - break; - } - case 'tool-call': { - switch (part.toolName) { - case 'cityAttractions': { - // handle tool call here - break; - } - } - break; - } - case 'tool-input-start': { - // handle tool input start - break; - } - case 'tool-input-delta': { - // handle tool input delta - break; - } - case 'tool-input-end': { - // handle tool input end - break; - } - case 'tool-result': { - switch (part.toolName) { - case 'cityAttractions': { - // handle tool result here - break; - } - } - break; - } - case 'tool-error': { - // handle tool error - break; - } - case 'finish-step': { - // handle finish step - break; - } - case 'finish': { - // handle finish here - break; - } - case 'error': { - // handle error here - break; - } - case 'raw': { - // handle raw value - break; - } - } -} -``` - -### Stream transformation - -You can use the `experimental_transform` option to transform the stream. -This is useful for e.g. filtering, changing, or smoothing the text stream. - -The transformations are applied before the callbacks are invoked and the promises are resolved. -If you e.g. have a transformation that changes all text to uppercase, the `onFinish` callback will receive the transformed text. - -#### Smoothing streams - -The AI SDK Core provides a [`smoothStream` function](/docs/reference/ai-sdk-core/smooth-stream) that -can be used to smooth out text and reasoning streaming. - -```tsx highlight="6" -import { smoothStream, streamText } from 'ai'; - -const result = streamText({ - model, - prompt, - experimental_transform: smoothStream(), -}); -``` - -#### Custom transformations - -You can also implement your own custom transformations. -The transformation function receives the tools that are available to the model, -and returns a function that is used to transform the stream. -Tools can either be generic or limited to the tools that you are using. - -Here is an example of how to implement a custom transformation that converts -all text to uppercase: - -```ts -import { streamText, type TextStreamPart, type ToolSet } from 'ai'; - -const upperCaseTransform = - () => - (options: { tools: TOOLS; stopStream: () => void }) => - new TransformStream, TextStreamPart>({ - transform(chunk, controller) { - controller.enqueue( - // for text-delta chunks, convert the text to uppercase: - chunk.type === 'text-delta' - ? { ...chunk, text: chunk.text.toUpperCase() } - : chunk, - ); - }, - }); -``` - -You can also stop the stream using the `stopStream` function. -This is e.g. useful if you want to stop the stream when model guardrails are violated, e.g. by generating inappropriate content. - -When you invoke `stopStream`, it is important to simulate the `finish-step` and `finish` events to guarantee that a well-formed stream is returned -and all callbacks are invoked. - -```ts -import { streamText, type TextStreamPart, type ToolSet } from 'ai'; - -const stopWordTransform = - () => - ({ stopStream }: { stopStream: () => void }) => - new TransformStream, TextStreamPart>({ - // note: this is a simplified transformation for testing; - // in a real-world version more there would need to be - // stream buffering and scanning to correctly emit prior text - // and to detect all STOP occurrences. - transform(chunk, controller) { - if (chunk.type !== 'text-delta') { - controller.enqueue(chunk); - return; - } - - if (chunk.text.includes('STOP')) { - // stop the stream - stopStream(); - - // simulate the finish-step event - controller.enqueue({ - type: 'finish-step', - finishReason: 'stop', - rawFinishReason: 'stop', - usage: { - completionTokens: NaN, - promptTokens: NaN, - totalTokens: NaN, - }, - response: { - id: 'response-id', - modelId: 'mock-model-id', - timestamp: new Date(0), - }, - providerMetadata: undefined, - }); - - // simulate the finish event - controller.enqueue({ - type: 'finish', - finishReason: 'stop', - rawFinishReason: 'stop', - totalUsage: { - completionTokens: NaN, - promptTokens: NaN, - totalTokens: NaN, - }, - }); - - return; - } - - controller.enqueue(chunk); - }, - }); -``` - -#### Multiple transformations - -You can also provide multiple transformations. They are applied in the order they are provided. - -```tsx highlight="4" -const result = streamText({ - model, - prompt, - experimental_transform: [firstTransform, secondTransform], -}); -``` - -## Sources - -Some providers such as [Perplexity](/providers/ai-sdk-providers/perplexity#sources) and -[Google Generative AI](/providers/ai-sdk-providers/google-generative-ai#sources) include sources in the response. - -Currently sources are limited to web pages that ground the response. -You can access them using the `sources` property of the result. - -Each `url` source contains the following properties: - -- `id`: The ID of the source. -- `url`: The URL of the source. -- `title`: The optional title of the source. -- `providerMetadata`: Provider metadata for the source. - -When you use `generateText`, you can access the sources using the `sources` property: - -```ts -const result = await generateText({ - model: 'google/gemini-2.5-flash', - tools: { - google_search: google.tools.googleSearch({}), - }, - prompt: 'List the top 5 San Francisco news from the past week.', -}); - -for (const source of result.sources) { - if (source.sourceType === 'url') { - console.log('ID:', source.id); - console.log('Title:', source.title); - console.log('URL:', source.url); - console.log('Provider metadata:', source.providerMetadata); - console.log(); - } -} -``` - -When you use `streamText`, you can access the sources using the `fullStream` property: - -```tsx -const result = streamText({ - model: 'google/gemini-2.5-flash', - tools: { - google_search: google.tools.googleSearch({}), - }, - prompt: 'List the top 5 San Francisco news from the past week.', -}); - -for await (const part of result.fullStream) { - if (part.type === 'source' && part.sourceType === 'url') { - console.log('ID:', part.id); - console.log('Title:', part.title); - console.log('URL:', part.url); - console.log('Provider metadata:', part.providerMetadata); - console.log(); - } -} -``` - -The sources are also available in the `result.sources` promise. - -## Examples - -You can see `generateText` and `streamText` in action using various frameworks in the following examples: - -### `generateText` - - - -### `streamText` - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/10-generating-structured-data.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/10-generating-structured-data.mdx deleted file mode 100644 index 1bc827bfa..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/10-generating-structured-data.mdx +++ /dev/null @@ -1,498 +0,0 @@ ---- -title: Generating Structured Data -description: Learn how to generate structured data with the AI SDK. ---- - -# Generating Structured Data - -While text generation can be useful, your use case will likely call for generating structured data. -For example, you might want to extract information from text, classify data, or generate synthetic data. - -Many language models are capable of generating structured data, often defined as using "JSON modes" or "tools". -However, you need to manually provide schemas and then validate the generated data as LLMs can produce incorrect or incomplete structured data. - -The AI SDK standardises structured object generation across model providers -using the `output` property on [`generateText`](/docs/reference/ai-sdk-core/generate-text) -and [`streamText`](/docs/reference/ai-sdk-core/stream-text). -You can use [Zod schemas](/docs/reference/ai-sdk-core/zod-schema), [Valibot](/docs/reference/ai-sdk-core/valibot-schema), or [JSON schemas](/docs/reference/ai-sdk-core/json-schema) to specify the shape of the data that you want, -and the AI model will generate data that conforms to that structure. - - - Structured output generation is part of the `generateText` and `streamText` - flow. This means you can combine it with tool calling in the same request. - - -## Generating Structured Outputs - -Use `generateText` with `Output.object()` to generate structured data from a prompt. -The schema is also used to validate the generated data, ensuring type safety and correctness. - -```ts -import { generateText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const { output } = await generateText({ - model: __MODEL__, - output: Output.object({ - schema: z.object({ - recipe: z.object({ - name: z.string(), - ingredients: z.array( - z.object({ name: z.string(), amount: z.string() }), - ), - steps: z.array(z.string()), - }), - }), - }), - prompt: 'Generate a lasagna recipe.', -}); -``` - - - Structured output generation counts as a step in the AI SDK's multi-turn - execution model (where each model call or tool execution is one step). When - combining with tools, account for this in your `stopWhen` configuration. - - -### Accessing response headers & body - -Sometimes you need access to the full response from the model provider, -e.g. to access some provider-specific headers or body content. - -You can access the raw response headers and body using the `response` property: - -```ts -import { generateText, Output } from 'ai'; - -const result = await generateText({ - // ... - output: Output.object({ schema }), -}); - -console.log(JSON.stringify(result.response.headers, null, 2)); -console.log(JSON.stringify(result.response.body, null, 2)); -``` - -## Stream Structured Outputs - -Given the added complexity of returning structured data, model response time can be unacceptable for your interactive use case. -With `streamText` and `output`, you can stream the model's structured response as it is generated. - -```ts -import { streamText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const { partialOutputStream } = streamText({ - model: __MODEL__, - output: Output.object({ - schema: z.object({ - recipe: z.object({ - name: z.string(), - ingredients: z.array( - z.object({ name: z.string(), amount: z.string() }), - ), - steps: z.array(z.string()), - }), - }), - }), - prompt: 'Generate a lasagna recipe.', -}); - -// use partialOutputStream as an async iterable -for await (const partialObject of partialOutputStream) { - console.log(partialObject); -} -``` - -You can consume the structured output on the client with the [`useObject`](/docs/reference/ai-sdk-ui/use-object) hook. - -### Error Handling in Streams - -`streamText` starts streaming immediately. When errors occur during streaming, they become part of the stream rather than thrown exceptions (to prevent stream crashes). - -To handle errors, provide an `onError` callback: - -```tsx highlight="5-7" -import { streamText, Output } from 'ai'; - -const result = streamText({ - // ... - output: Output.object({ schema }), - onError({ error }) { - console.error(error); // log to your error tracking service - }, -}); -``` - -For non-streaming error handling with `generateText`, see the [Error Handling](#error-handling) section below. - -## Output Types - -The AI SDK supports multiple ways of specifying the expected structure of generated data via the `Output` object. You can select from various strategies for structured/text generation and validation. - -### `Output.text()` - -Use `Output.text()` to generate plain text from a model. This option doesn't enforce any schema on the result: you simply receive the model's text as a string. This is the default behavior when no `output` is specified. - -```ts -import { generateText, Output } from 'ai'; - -const { output } = await generateText({ - // ... - output: Output.text(), - prompt: 'Tell me a joke.', -}); -// output will be a string (the joke) -``` - -### `Output.object()` - -Use `Output.object({ schema })` to generate a structured object based on a schema (for example, a Zod schema). The output is type-validated to ensure the returned result matches the schema. - -```ts -import { generateText, Output } from 'ai'; -import { z } from 'zod'; - -const { output } = await generateText({ - // ... - output: Output.object({ - schema: z.object({ - name: z.string(), - age: z.number().nullable(), - labels: z.array(z.string()), - }), - }), - prompt: 'Generate information for a test user.', -}); -// output will be an object matching the schema above -``` - - - Partial outputs streamed via `streamText` cannot be validated against your - provided schema, as incomplete data may not yet conform to the expected - structure. - - -### `Output.array()` - -Use `Output.array({ element })` to specify that you expect an array of typed objects from the model, where each element should conform to a schema (defined in the `element` property). - -```ts -import { generateText, Output } from 'ai'; -import { z } from 'zod'; - -const { output } = await generateText({ - // ... - output: Output.array({ - element: z.object({ - location: z.string(), - temperature: z.number(), - condition: z.string(), - }), - }), - prompt: 'List the weather for San Francisco and Paris.', -}); -// output will be an array of objects like: -// [ -// { location: 'San Francisco', temperature: 70, condition: 'Sunny' }, -// { location: 'Paris', temperature: 65, condition: 'Cloudy' }, -// ] -``` - -When streaming arrays with `streamText`, you can use `elementStream` to receive each completed element as it is generated: - -```ts -import { streamText, Output } from 'ai'; -import { z } from 'zod'; - -const { elementStream } = streamText({ - // ... - output: Output.array({ - element: z.object({ - name: z.string(), - class: z.string(), - description: z.string(), - }), - }), - prompt: 'Generate 3 hero descriptions for a fantasy role playing game.', -}); - -for await (const hero of elementStream) { - console.log(hero); // Each hero is complete and validated -} -``` - - - Each element emitted by `elementStream` is complete and validated against your - element schema. This differs from `partialOutputStream`, which streams the - entire partial array including incomplete elements. - - -### `Output.choice()` - -Use `Output.choice({ options })` when you expect the model to choose from a specific set of string options, such as for classification or fixed-enum answers. - -```ts -import { generateText, Output } from 'ai'; - -const { output } = await generateText({ - // ... - output: Output.choice({ - options: ['sunny', 'rainy', 'snowy'], - }), - prompt: 'Is the weather sunny, rainy, or snowy today?', -}); -// output will be one of: 'sunny', 'rainy', or 'snowy' -``` - -You can provide any set of string options, and the output will always be a single string value that matches one of the specified options. The AI SDK validates that the result matches one of your options, and will throw if the model returns something invalid. - -This is especially useful for making classification-style generations or forcing valid values for API compatibility. - -### `Output.json()` - -Use `Output.json()` when you want to generate and parse unstructured JSON values from the model, without enforcing a specific schema. This is useful if you want to capture arbitrary objects, flexible structures, or when you want to rely on the model's natural output rather than rigid validation. - -```ts -import { generateText, Output } from 'ai'; - -const { output } = await generateText({ - // ... - output: Output.json(), - prompt: - 'For each city, return the current temperature and weather condition as a JSON object.', -}); - -// output could be any valid JSON, for example: -// { -// "San Francisco": { "temperature": 70, "condition": "Sunny" }, -// "Paris": { "temperature": 65, "condition": "Cloudy" } -// } -``` - -With `Output.json`, the AI SDK only checks that the response is valid JSON; it doesn't validate the structure or types of the values. If you need schema validation, use the `.object` or `.array` outputs instead. - -For more advanced validation or different structures, see [the Output API reference](/docs/reference/ai-sdk-core/output). - -## Generating Structured Outputs with Tools - -One of the key advantages of using structured output with `generateText` and `streamText` is the ability to combine it with tool calling. - -```ts -import { generateText, Output, tool, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const { output } = await generateText({ - model: __MODEL__, - tools: { - weather: tool({ - description: 'Get the weather for a location', - inputSchema: z.object({ location: z.string() }), - execute: async ({ location }) => { - // fetch weather data - return { temperature: 72, condition: 'sunny' }; - }, - }), - }, - output: Output.object({ - schema: z.object({ - summary: z.string(), - recommendation: z.string(), - }), - }), - stopWhen: stepCountIs(5), - prompt: 'What should I wear in San Francisco today?', -}); -``` - - - When using tools with structured output, remember that generating the - structured output counts as a step. Configure `stopWhen` to allow enough steps - for both tool execution and output generation. - - -## Property Descriptions - -You can add `.describe("...")` to individual schema properties to give the model hints about what each property is for. This helps improve the quality and accuracy of generated structured data: - -```ts highlight="5,9" -import { generateText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const { output } = await generateText({ - model: __MODEL__, - output: Output.object({ - schema: z.object({ - name: z.string().describe('The name of the recipe'), - ingredients: z - .array( - z.object({ - name: z.string(), - amount: z - .string() - .describe('The amount of the ingredient (grams or ml)'), - }), - ) - .describe('List of ingredients with amounts'), - steps: z.array(z.string()).describe('Step-by-step cooking instructions'), - }), - }), - prompt: 'Generate a lasagna recipe.', -}); -``` - -Property descriptions are particularly useful for: - -- Clarifying ambiguous property names -- Specifying expected formats or conventions -- Providing context for complex nested structures - -## Output Name and Description - -You can optionally specify a `name` and `description` for the output. These are used by some providers for additional LLM guidance, e.g. via tool or schema name. - -```ts highlight="6-7" -import { generateText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const { output } = await generateText({ - model: __MODEL__, - output: Output.object({ - name: 'Recipe', - description: 'A recipe for a dish.', - schema: z.object({ - name: z.string(), - ingredients: z.array(z.object({ name: z.string(), amount: z.string() })), - steps: z.array(z.string()), - }), - }), - prompt: 'Generate a lasagna recipe.', -}); -``` - -This works with all output types that support structured generation: - -- `Output.object({ name, description, schema })` -- `Output.array({ name, description, element })` -- `Output.choice({ name, description, options })` -- `Output.json({ name, description })` - -## Accessing Reasoning - -You can access the reasoning used by the language model to generate the object via the `reasoning` property on the result. This property contains a string with the model's thought process, if available. - -```ts -import { generateText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const result = await generateText({ - model: __MODEL__, // must be a reasoning model - output: Output.object({ - schema: z.object({ - recipe: z.object({ - name: z.string(), - ingredients: z.array( - z.object({ - name: z.string(), - amount: z.string(), - }), - ), - steps: z.array(z.string()), - }), - }), - }), - prompt: 'Generate a lasagna recipe.', -}); - -console.log(result.reasoningText); -``` - -## Error Handling - -When `generateText` with structured output cannot generate a valid object, it throws a [`AI_NoObjectGeneratedError`](/docs/reference/ai-sdk-errors/ai-no-object-generated-error). - -This error occurs when the AI provider fails to generate a parsable object that conforms to the schema. -It can arise due to the following reasons: - -- The model failed to generate a response. -- The model generated a response that could not be parsed. -- The model generated a response that could not be validated against the schema. - -The error preserves the following information to help you log the issue: - -- `text`: The text that was generated by the model. This can be the raw text or the tool call text, depending on the object generation mode. -- `response`: Metadata about the language model response, including response id, timestamp, and model. -- `usage`: Request token usage. -- `cause`: The cause of the error (e.g. a JSON parsing error). You can use this for more detailed error handling. - -```ts -import { generateText, Output, NoObjectGeneratedError } from 'ai'; - -try { - await generateText({ - model, - output: Output.object({ schema }), - prompt, - }); -} catch (error) { - if (NoObjectGeneratedError.isInstance(error)) { - console.log('NoObjectGeneratedError'); - console.log('Cause:', error.cause); - console.log('Text:', error.text); - console.log('Response:', error.response); - console.log('Usage:', error.usage); - } -} -``` - -## More Examples - -You can see structured output generation in action using various frameworks in the following examples: - -### `generateText` with Output - - - -### `streamText` with Output - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx deleted file mode 100644 index eb340ad24..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +++ /dev/null @@ -1,1148 +0,0 @@ ---- -title: Tool Calling -description: Learn about tool calling and multi-step calls (using stopWhen) with AI SDK Core. ---- - -# Tool Calling - -As covered under Foundations, [tools](/docs/foundations/tools) are objects that can be called by the model to perform a specific task. -AI SDK Core tools contain several core elements: - -- **`description`**: An optional description of the tool that can influence when the tool is picked. -- **`inputSchema`**: A [Zod schema](/docs/foundations/tools#schemas) or a [JSON schema](/docs/reference/ai-sdk-core/json-schema) that defines the input parameters. The schema is consumed by the LLM, and also used to validate the LLM tool calls. -- **`execute`**: An optional async function that is called with the inputs from the tool call. It produces a value of type `RESULT` (generic type). It is optional because you might want to forward tool calls to the client or to a queue instead of executing them in the same process. -- **`strict`**: _(optional, boolean)_ Enables strict tool calling when supported by the provider - - - You can use the [`tool`](/docs/reference/ai-sdk-core/tool) helper function to - infer the types of the `execute` parameters. - - -The `tools` parameter of `generateText` and `streamText` is an object that has the tool names as keys and the tools as values: - -```ts highlight="6-17" -import { z } from 'zod'; -import { generateText, tool, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; - -const result = await generateText({ - model: __MODEL__, - tools: { - weather: tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => ({ - location, - temperature: 72 + Math.floor(Math.random() * 21) - 10, - }), - }), - }, - stopWhen: stepCountIs(5), - prompt: 'What is the weather in San Francisco?', -}); -``` - - - When a model uses a tool, it is called a "tool call" and the output of the - tool is called a "tool result". - - -Tool calling is not restricted to only text generation. -You can also use it to render user interfaces (Generative UI). - -## Strict Mode - -When enabled, language model providers that support strict tool calling will only generate tool calls that are valid according to your defined `inputSchema`. -This increases the reliability of tool calling. -However, not all schemas may be supported in strict mode, and what is supported depends on the specific provider. - -By default, strict mode is disabled. You can enable it per-tool by setting `strict: true`: - -```ts -tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ - location: z.string(), - }), - strict: true, // Enable strict validation for this tool - execute: async ({ location }) => ({ - // ... - }), -}); -``` - - - Not all providers or models support strict mode. For those that do not, this - option is ignored. - - -## Input Examples - -You can specify example inputs for your tools to help guide the model on how input data should be structured. -When supported by providers, input examples can help when JSON schema itself does not fully specify the intended -usage or when there are optional values. - -```ts -tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - inputExamples: [ - { input: { location: 'San Francisco' } }, - { input: { location: 'London' } }, - ], - execute: async ({ location }) => { - // ... - }, -}); -``` - - - Only the Anthropic providers supports tool input examples natively. Other - providers ignore the setting. - - -## Tool Execution Approval - -By default, tools with an `execute` function run automatically as the model calls them. You can require approval before execution by setting `needsApproval`: - -```ts highlight="13" -import { tool } from 'ai'; -import { z } from 'zod'; - -const runCommand = tool({ - description: 'Run a shell command', - inputSchema: z.object({ - command: z.string().describe('The shell command to execute'), - }), - needsApproval: true, - execute: async ({ command }) => { - // your command execution logic here - }, -}); -``` - -This is useful for tools that perform sensitive operations like executing commands, processing payments, modifying data, and more potentially dangerous actions. - -### How It Works - -When a tool requires approval, `generateText` and `streamText` don't pause execution. Instead, they complete and return `tool-approval-request` parts in the result content. This means the approval flow requires two calls to the model: the first returns the approval request, and the second (after receiving the approval response) either executes the tool or informs the model that approval was denied. - -Here's the complete flow: - -1. Call `generateText` with a tool that has `needsApproval: true` -2. Model generates a tool call -3. `generateText` returns with `tool-approval-request` parts in `result.content` -4. Your app requests an approval and collects the user's decision -5. Add a `tool-approval-response` to the messages array -6. Call `generateText` again with the updated messages -7. If approved, the tool runs and returns a result. If denied, the model sees the denial and responds accordingly. - -### Handling Approval Requests - -After calling `generateText` or `streamText`, check `result.content` for `tool-approval-request` parts: - -```ts -import { type ModelMessage, generateText } from 'ai'; - -const messages: ModelMessage[] = [ - { role: 'user', content: 'Remove the most recent file' }, -]; -const result = await generateText({ - model: __MODEL__, - tools: { runCommand }, - messages, -}); - -messages.push(...result.response.messages); - -for (const part of result.content) { - if (part.type === 'tool-approval-request') { - console.log(part.approvalId); // Unique ID for this approval request - console.log(part.toolCall); // Contains toolName, input, etc. - } -} -``` - -To respond, create a `tool-approval-response` and add it to your messages: - -```ts -import { type ToolApprovalResponse } from 'ai'; - -const approvals: ToolApprovalResponse[] = []; - -for (const part of result.content) { - if (part.type === 'tool-approval-request') { - const response: ToolApprovalResponse = { - type: 'tool-approval-response', - approvalId: part.approvalId, - approved: true, // or false to deny - reason: 'User confirmed the command', // Optional context for the model - }; - approvals.push(response); - } -} - -// add approvals to messages -messages.push({ role: 'tool', content: approvals }); -``` - -Then call `generateText` again with the updated messages. If approved, the tool executes. If denied, the model receives the denial and can respond accordingly. - - - When a tool execution is denied, consider adding a system instruction like - "When a tool execution is not approved, do not retry it" to prevent the model - from attempting the same call again. - - -### Dynamic Approval - -You can make approval decisions based on tool input by providing an async function: - -```ts -const paymentTool = tool({ - description: 'Process a payment', - inputSchema: z.object({ - amount: z.number(), - recipient: z.string(), - }), - needsApproval: async ({ amount }) => amount > 1000, - execute: async ({ amount, recipient }) => { - return await processPayment(amount, recipient); - }, -}); -``` - -In this example, only transactions over $1000 require approval. Smaller transactions execute automatically. - -### Tool Execution Approval with useChat - -When using `useChat`, the approval flow is handled through UI state. See [Chatbot Tool Usage](/docs/ai-sdk-ui/chatbot-tool-usage#tool-execution-approval) for details on handling approvals in your UI with `addToolApprovalResponse`. - -## Multi-Step Calls (using stopWhen) - -With the `stopWhen` setting, you can enable multi-step calls in `generateText` and `streamText`. When `stopWhen` is set and the model generates a tool call, the AI SDK will trigger a new generation passing in the tool result until there are no further tool calls or the stopping condition is met. - - - The `stopWhen` conditions are only evaluated when the last step contains tool - results. - - -By default, when you use `generateText` or `streamText`, it triggers a single generation. This works well for many use cases where you can rely on the model's training data to generate a response. However, when you provide tools, the model now has the choice to either generate a normal text response, or generate a tool call. If the model generates a tool call, its generation is complete and that step is finished. - -You may want the model to generate text after the tool has been executed, either to summarize the tool results in the context of the users query. In many cases, you may also want the model to use multiple tools in a single response. This is where multi-step calls come in. - -You can think of multi-step calls in a similar way to a conversation with a human. When you ask a question, if the person does not have the requisite knowledge in their common knowledge (a model's training data), the person may need to look up information (use a tool) before they can provide you with an answer. In the same way, the model may need to call a tool to get the information it needs to answer your question where each generation (tool call or text generation) is a step. - -### Example - -In the following example, there are two steps: - -1. **Step 1** - 1. The prompt `'What is the weather in San Francisco?'` is sent to the model. - 1. The model generates a tool call. - 1. The tool call is executed. -1. **Step 2** - 1. The tool result is sent to the model. - 1. The model generates a response considering the tool result. - -```ts highlight="18-19" -import { z } from 'zod'; -import { generateText, tool, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; - -const { text, steps } = await generateText({ - model: __MODEL__, - tools: { - weather: tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => ({ - location, - temperature: 72 + Math.floor(Math.random() * 21) - 10, - }), - }), - }, - stopWhen: stepCountIs(5), // stop after a maximum of 5 steps if tools were called - prompt: 'What is the weather in San Francisco?', -}); -``` - -You can use `streamText` in a similar way. - -### Steps - -To access intermediate tool calls and results, you can use the `steps` property in the result object -or the `streamText` `onFinish` callback. -It contains all the text, tool calls, tool results, and more from each step. - -#### Example: Extract tool results from all steps - -```ts highlight="3,9-10" -import { generateText } from 'ai'; -__PROVIDER_IMPORT__; - -const { steps } = await generateText({ - model: __MODEL__, - stopWhen: stepCountIs(10), - // ... -}); - -// extract all tool calls from the steps: -const allToolCalls = steps.flatMap(step => step.toolCalls); -``` - -### `onStepFinish` callback - -When using `generateText` or `streamText`, you can provide an `onStepFinish` callback that -is triggered when a step is finished, -i.e. all text deltas, tool calls, and tool results for the step are available. -When you have multiple steps, the callback is triggered for each step. - -The callback receives a `stepNumber` (zero-based) to identify which step just completed: - -```tsx highlight="5-8" -import { generateText } from 'ai'; - -const result = await generateText({ - // ... - onStepFinish({ - stepNumber, - text, - toolCalls, - toolResults, - finishReason, - usage, - }) { - console.log(`Step ${stepNumber} finished (${finishReason})`); - // your own logic, e.g. for saving the chat history or recording usage - }, -}); -``` - -### Tool execution lifecycle callbacks - -You can use `experimental_onToolCallStart` and `experimental_onToolCallFinish` to observe tool execution. -These callbacks are called right before and after each tool's `execute` function, giving you -visibility into tool execution timing, inputs, outputs, and errors: - -```tsx highlight="5-14" -import { generateText } from 'ai'; - -const result = await generateText({ - // ... model, tools, prompt - experimental_onToolCallStart({ toolName, toolCallId, input }) { - console.log(`Calling tool: ${toolName}`, { toolCallId, input }); - }, - experimental_onToolCallFinish({ - toolName, - toolCallId, - output, - error, - durationMs, - }) { - if (error) { - console.error(`Tool ${toolName} failed after ${durationMs}ms:`, error); - } else { - console.log(`Tool ${toolName} completed in ${durationMs}ms`, { output }); - } - }, -}); -``` - -Errors thrown inside these callbacks are silently caught and do not break the generation flow. - -### `prepareStep` callback - -The `prepareStep` callback is called before a step is started. - -It is called with the following parameters: - -- `model`: The model that was passed into `generateText`. -- `stopWhen`: The stopping condition that was passed into `generateText`. -- `stepNumber`: The number of the step that is being executed. -- `steps`: The steps that have been executed so far. -- `messages`: The messages that will be sent to the model for the current step. -- `experimental_context`: The context passed via the `experimental_context` setting (experimental). - -You can use it to provide different settings for a step, including modifying the input messages. - -```tsx highlight="5-7" -import { generateText } from 'ai'; - -const result = await generateText({ - // ... - prepareStep: async ({ model, stepNumber, steps, messages }) => { - if (stepNumber === 0) { - return { - // use a different model for this step: - model: modelForThisParticularStep, - // force a tool choice for this step: - toolChoice: { type: 'tool', toolName: 'tool1' }, - // limit the tools that are available for this step: - activeTools: ['tool1'], - }; - } - - // when nothing is returned, the default settings are used - }, -}); -``` - -#### Message Modification for Longer Agentic Loops - -In longer agentic loops, you can use the `messages` parameter to modify the input messages for each step. This is particularly useful for prompt compression: - -```tsx -prepareStep: async ({ stepNumber, steps, messages }) => { - // Compress conversation history for longer loops - if (messages.length > 20) { - return { - messages: messages.slice(-10), - }; - } - - return {}; -}, -``` - -#### Provider Options for Step Configuration - -You can use `providerOptions` in `prepareStep` to pass provider-specific configuration for each step. This is useful for features like Anthropic's code execution container persistence: - -```tsx -import { forwardAnthropicContainerIdFromLastStep } from '@ai-sdk/anthropic'; - -// Propagate container ID from previous step for code execution continuity -prepareStep: forwardAnthropicContainerIdFromLastStep, -``` - -## Response Messages - -Adding the generated assistant and tool messages to your conversation history is a common task, -especially if you are using multi-step tool calls. - -Both `generateText` and `streamText` have a `response.messages` property that you can use to -add the assistant and tool messages to your conversation history. -It is also available in the `onFinish` callback of `streamText`. - -The `response.messages` property contains an array of `ModelMessage` objects that you can add to your conversation history: - -```ts -import { generateText, ModelMessage } from 'ai'; - -const messages: ModelMessage[] = [ - // ... -]; - -const { response } = await generateText({ - // ... - messages, -}); - -// add the response messages to your conversation history: -messages.push(...response.messages); // streamText: ...((await response).messages) -``` - -## Dynamic Tools - -AI SDK Core supports dynamic tools for scenarios where tool schemas are not known at compile time. This is useful for: - -- MCP (Model Context Protocol) tools without schemas -- User-defined functions at runtime -- Tools loaded from external sources - -### Using dynamicTool - -The `dynamicTool` helper creates tools with unknown input/output types: - -```ts -import { dynamicTool } from 'ai'; -import { z } from 'zod'; - -const customTool = dynamicTool({ - description: 'Execute a custom function', - inputSchema: z.object({}), - execute: async input => { - // input is typed as 'unknown' - // You need to validate/cast it at runtime - const { action, parameters } = input as any; - - // Execute your dynamic logic - return { result: `Executed ${action}` }; - }, -}); -``` - -### Type-Safe Handling - -When using both static and dynamic tools, use the `dynamic` flag for type narrowing: - -```ts -const result = await generateText({ - model: __MODEL__, - tools: { - // Static tool with known types - weather: weatherTool, - // Dynamic tool - custom: dynamicTool({ - /* ... */ - }), - }, - onStepFinish: ({ toolCalls, toolResults }) => { - // Type-safe iteration - for (const toolCall of toolCalls) { - if (toolCall.dynamic) { - // Dynamic tool: input is 'unknown' - console.log('Dynamic:', toolCall.toolName, toolCall.input); - continue; - } - - // Static tool: full type inference - switch (toolCall.toolName) { - case 'weather': - console.log(toolCall.input.location); // typed as string - break; - } - } - }, -}); -``` - -## Preliminary Tool Results - -You can return an `AsyncIterable` over multiple results. -In this case, the last value from the iterable is the final tool result. - -This can be used in combination with generator functions to e.g. stream status information -during the tool execution: - -```ts -tool({ - description: 'Get the current weather.', - inputSchema: z.object({ - location: z.string(), - }), - async *execute({ location }) { - yield { - status: 'loading' as const, - text: `Getting weather for ${location}`, - weather: undefined, - }; - - await new Promise(resolve => setTimeout(resolve, 3000)); - - const temperature = 72 + Math.floor(Math.random() * 21) - 10; - - yield { - status: 'success' as const, - text: `The weather in ${location} is ${temperature}°F`, - temperature, - }; - }, -}); -``` - -## Tool Choice - -You can use the `toolChoice` setting to influence when a tool is selected. -It supports the following settings: - -- `auto` (default): the model can choose whether and which tools to call. -- `required`: the model must call a tool. It can choose which tool to call. -- `none`: the model must not call tools -- `{ type: 'tool', toolName: string (typed) }`: the model must call the specified tool - -```ts highlight="18" -import { z } from 'zod'; -import { generateText, tool } from 'ai'; -__PROVIDER_IMPORT__; - -const result = await generateText({ - model: __MODEL__, - tools: { - weather: tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => ({ - location, - temperature: 72 + Math.floor(Math.random() * 21) - 10, - }), - }), - }, - toolChoice: 'required', // force the model to call a tool - prompt: 'What is the weather in San Francisco?', -}); -``` - -## Tool Execution Options - -When tools are called, they receive additional options as a second parameter. - -### Tool Call ID - -The ID of the tool call is forwarded to the tool execution. -You can use it e.g. when sending tool-call related information with stream data. - -```ts highlight="14-20" -import { - streamText, - tool, - createUIMessageStream, - createUIMessageStreamResponse, -} from 'ai'; - -export async function POST(req: Request) { - const { messages } = await req.json(); - - const stream = createUIMessageStream({ - execute: ({ writer }) => { - const result = streamText({ - // ... - messages, - tools: { - myTool: tool({ - // ... - execute: async (args, { toolCallId }) => { - // return e.g. custom status for tool call - writer.write({ - type: 'data-tool-status', - id: toolCallId, - data: { - name: 'myTool', - status: 'in-progress', - }, - }); - // ... - }, - }), - }, - }); - - writer.merge(result.toUIMessageStream()); - }, - }); - - return createUIMessageStreamResponse({ stream }); -} -``` - -### Messages - -The messages that were sent to the language model to initiate the response that contained the tool call are forwarded to the tool execution. -You can access them in the second parameter of the `execute` function. -In multi-step calls, the messages contain the text, tool calls, and tool results from all previous steps. - -```ts highlight="8-9" -import { generateText, tool } from 'ai'; - -const result = await generateText({ - // ... - tools: { - myTool: tool({ - // ... - execute: async (args, { messages }) => { - // use the message history in e.g. calls to other language models - return { ... }; - }, - }), - }, -}); -``` - -### Abort Signals - -The abort signals from `generateText` and `streamText` are forwarded to the tool execution. -You can access them in the second parameter of the `execute` function and e.g. abort long-running computations or forward them to fetch calls inside tools. - -```ts highlight="6,11,14" -import { z } from 'zod'; -import { generateText, tool } from 'ai'; -__PROVIDER_IMPORT__; - -const result = await generateText({ - model: __MODEL__, - abortSignal: myAbortSignal, // signal that will be forwarded to tools - tools: { - weather: tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ location: z.string() }), - execute: async ({ location }, { abortSignal }) => { - return fetch( - `https://api.weatherapi.com/v1/current.json?q=${location}`, - { signal: abortSignal }, // forward the abort signal to fetch - ); - }, - }), - }, - prompt: 'What is the weather in San Francisco?', -}); -``` - -### Context (experimental) - -You can pass in arbitrary context from `generateText` or `streamText` via the `experimental_context` setting. -This context is available in the `experimental_context` tool execution option. - -```ts -const result = await generateText({ - // ... - tools: { - someTool: tool({ - // ... - execute: async (input, { experimental_context: context }) => { - const typedContext = context as { example: string }; // or use type validation library - // ... - }, - }), - }, - experimental_context: { example: '123' }, -}); -``` - -## Tool Input Lifecycle Hooks - -The following tool input lifecycle hooks are available: - -- **`onInputStart`**: Called when the model starts generating the input (arguments) for the tool call -- **`onInputDelta`**: Called for each chunk of text as the input is streamed -- **`onInputAvailable`**: Called when the complete input is available and validated - -`onInputStart` and `onInputDelta` are only called in streaming contexts (when using `streamText`). They are not called when using `generateText`. - -### Example - -```ts highlight="15-23" -import { streamText, tool } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const result = streamText({ - model: __MODEL__, - tools: { - getWeather: tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => ({ - temperature: 72 + Math.floor(Math.random() * 21) - 10, - }), - onInputStart: () => { - console.log('Tool call starting'); - }, - onInputDelta: ({ inputTextDelta }) => { - console.log('Received input chunk:', inputTextDelta); - }, - onInputAvailable: ({ input }) => { - console.log('Complete input:', input); - }, - }), - }, - prompt: 'What is the weather in San Francisco?', -}); -``` - -## Types - -Modularizing your code often requires defining types to ensure type safety and reusability. -To enable this, the AI SDK provides several helper types for tools, tool calls, and tool results. - -You can use them to strongly type your variables, function parameters, and return types -in parts of the code that are not directly related to `streamText` or `generateText`. - -Each tool call is typed with `ToolCall`, depending -on the tool that has been invoked. -Similarly, the tool results are typed with `ToolResult`. - -The tools in `streamText` and `generateText` are defined as a `ToolSet`. -The type inference helpers `TypedToolCall` -and `TypedToolResult` can be used to -extract the tool call and tool result types from the tools. - -```ts highlight="18-19,23-24" -import { TypedToolCall, TypedToolResult, generateText, tool } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const myToolSet = { - firstTool: tool({ - description: 'Greets the user', - inputSchema: z.object({ name: z.string() }), - execute: async ({ name }) => `Hello, ${name}!`, - }), - secondTool: tool({ - description: 'Tells the user their age', - inputSchema: z.object({ age: z.number() }), - execute: async ({ age }) => `You are ${age} years old!`, - }), -}; - -type MyToolCall = TypedToolCall; -type MyToolResult = TypedToolResult; - -async function generateSomething(prompt: string): Promise<{ - text: string; - toolCalls: Array; // typed tool calls - toolResults: Array; // typed tool results -}> { - return generateText({ - model: __MODEL__, - tools: myToolSet, - prompt, - }); -} -``` - -## Handling Errors - -The AI SDK has three tool-call related errors: - -- [`NoSuchToolError`](/docs/reference/ai-sdk-errors/ai-no-such-tool-error): the model tries to call a tool that is not defined in the tools object -- [`InvalidToolInputError`](/docs/reference/ai-sdk-errors/ai-invalid-tool-input-error): the model calls a tool with inputs that do not match the tool's input schema -- [`ToolCallRepairError`](/docs/reference/ai-sdk-errors/ai-tool-call-repair-error): an error that occurred during tool call repair - -When tool execution fails (errors thrown by your tool's `execute` function), the AI SDK adds them as `tool-error` content parts to enable automated LLM roundtrips in multi-step scenarios. - -### `generateText` - -`generateText` throws errors for tool schema validation issues and other errors, and can be handled using a `try`/`catch` block. Tool execution errors appear as `tool-error` parts in the result steps: - -```ts -try { - const result = await generateText({ - //... - }); -} catch (error) { - if (NoSuchToolError.isInstance(error)) { - // handle the no such tool error - } else if (InvalidToolInputError.isInstance(error)) { - // handle the invalid tool inputs error - } else { - // handle other errors - } -} -``` - -Tool execution errors are available in the result steps: - -```ts -const { steps } = await generateText({ - // ... -}); - -// check for tool errors in the steps -const toolErrors = steps.flatMap(step => - step.content.filter(part => part.type === 'tool-error'), -); - -toolErrors.forEach(toolError => { - console.log('Tool error:', toolError.error); - console.log('Tool name:', toolError.toolName); - console.log('Tool input:', toolError.input); -}); -``` - -### `streamText` - -`streamText` sends errors as part of the full stream. Tool execution errors appear as `tool-error` parts, while other errors appear as `error` parts. - -When using `toUIMessageStreamResponse`, you can pass an `onError` function to extract the error message from the error part and forward it as part of the stream response: - -```ts -const result = streamText({ - // ... -}); - -return result.toUIMessageStreamResponse({ - onError: error => { - if (NoSuchToolError.isInstance(error)) { - return 'The model tried to call a unknown tool.'; - } else if (InvalidToolInputError.isInstance(error)) { - return 'The model called a tool with invalid inputs.'; - } else { - return 'An unknown error occurred.'; - } - }, -}); -``` - -## Tool Call Repair - - - The tool call repair feature is experimental and may change in the future. - - -Language models sometimes fail to generate valid tool calls, -especially when the input schema is complex or the model is smaller. - -If you use multiple steps, those failed tool calls will be sent back to the LLM -in the next step to give it an opportunity to fix it. -However, you may want to control how invalid tool calls are repaired without requiring -additional steps that pollute the message history. - -You can use the `experimental_repairToolCall` function to attempt to repair the tool call -with a custom function. - -You can use different strategies to repair the tool call: - -- Use a model with structured outputs to generate the inputs. -- Send the messages, system prompt, and tool schema to a stronger model to generate the inputs. -- Provide more specific repair instructions based on which tool was called. - -### Example: Use a model with structured outputs for repair - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText, NoSuchToolError, Output, tool } from 'ai'; - -const result = await generateText({ - model, - tools, - prompt, - - experimental_repairToolCall: async ({ - toolCall, - tools, - inputSchema, - error, - }) => { - if (NoSuchToolError.isInstance(error)) { - return null; // do not attempt to fix invalid tool names - } - - const tool = tools[toolCall.toolName as keyof typeof tools]; - - const { output: repairedArgs } = await generateText({ - model: __MODEL__, - output: Output.object({ schema: tool.inputSchema }), - prompt: [ - `The model tried to call the tool "${toolCall.toolName}"` + - ` with the following inputs:`, - JSON.stringify(toolCall.input), - `The tool accepts the following schema:`, - JSON.stringify(inputSchema(toolCall)), - 'Please fix the inputs.', - ].join('\n'), - }); - - return { ...toolCall, input: JSON.stringify(repairedArgs) }; - }, -}); -``` - -### Example: Use the re-ask strategy for repair - -```ts -import { openai } from '@ai-sdk/openai'; -import { generateText, NoSuchToolError, tool } from 'ai'; - -const result = await generateText({ - model, - tools, - prompt, - - experimental_repairToolCall: async ({ - toolCall, - tools, - error, - messages, - system, - }) => { - const result = await generateText({ - model, - system, - messages: [ - ...messages, - { - role: 'assistant', - content: [ - { - type: 'tool-call', - toolCallId: toolCall.toolCallId, - toolName: toolCall.toolName, - input: toolCall.input, - }, - ], - }, - { - role: 'tool' as const, - content: [ - { - type: 'tool-result', - toolCallId: toolCall.toolCallId, - toolName: toolCall.toolName, - output: error.message, - }, - ], - }, - ], - tools, - }); - - const newToolCall = result.toolCalls.find( - newToolCall => newToolCall.toolName === toolCall.toolName, - ); - - return newToolCall != null - ? { - type: 'tool-call' as const, - toolCallId: toolCall.toolCallId, - toolName: toolCall.toolName, - input: JSON.stringify(newToolCall.input), - } - : null; - }, -}); -``` - -## Active Tools - -Language models can only handle a limited number of tools at a time, depending on the model. -To allow for static typing using a large number of tools and limiting the available tools to the model at the same time, -the AI SDK provides the `activeTools` property. - -It is an array of tool names that are currently active. -By default, the value is `undefined` and all tools are active. - -```ts highlight="7" -import { openai } from '@ai-sdk/openai'; -import { generateText } from 'ai'; -__PROVIDER_IMPORT__; - -const { text } = await generateText({ - model: __MODEL__, - tools: myToolSet, - activeTools: ['firstTool'], -}); -``` - -## Multi-modal Tool Results - - - Multi-modal tool results are experimental and supported by Anthropic, OpenAI, - and Google (Gemini 3 models). - - -For Google, use base64 media parts (`image-data` / `file-data`) or base64 -`data:` URLs in URL-style parts. Remote HTTP(S) URLs in tool-result URL parts -are not supported. - -In order to send multi-modal tool results, e.g. screenshots, back to the model, -they need to be converted into a specific format. - -AI SDK Core tools have an optional `toModelOutput` function -that converts the tool result into a content part. - -Here is an example for converting a screenshot into a content part: - -```ts highlight="22-27" -const result = await generateText({ - model: __MODEL__, - tools: { - computer: anthropic.tools.computer_20241022({ - // ... - async execute({ action, coordinate, text }) { - switch (action) { - case 'screenshot': { - return { - type: 'image', - data: fs - .readFileSync('./data/screenshot-editor.png') - .toString('base64'), - }; - } - default: { - return `executed ${action}`; - } - } - }, - - // map to tool result content for LLM consumption: - toModelOutput({ output }) { - return { - type: 'content', - value: - typeof output === 'string' - ? [{ type: 'text', text: output }] - : [{ type: 'media', data: output.data, mediaType: 'image/png' }], - }; - }, - }), - }, - // ... -}); -``` - -## Extracting Tools - -Once you start having many tools, you might want to extract them into separate files. -The `tool` helper function is crucial for this, because it ensures correct type inference. - -Here is an example of an extracted tool: - -```ts filename="tools/weather-tool.ts" highlight="1,4-5" -import { tool } from 'ai'; -import { z } from 'zod'; - -// the `tool` helper function ensures correct type inference: -export const weatherTool = tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }) => ({ - location, - temperature: 72 + Math.floor(Math.random() * 21) - 10, - }), -}); -``` - -## MCP Tools - -The AI SDK supports connecting to Model Context Protocol (MCP) servers to access their tools. -MCP enables your AI applications to discover and use tools across various services through a standardized interface. - -For detailed information about MCP tools, including initialization, transport options, and usage patterns, see the [MCP Tools documentation](/docs/ai-sdk-core/mcp-tools). - -### AI SDK Tools vs MCP Tools - -In most cases, you should define your own AI SDK tools for production applications. They provide full control, type safety, and optimal performance. MCP tools are best suited for rapid development iteration and scenarios where users bring their own tools. - -| Aspect | AI SDK Tools | MCP Tools | -| ---------------------- | --------------------------------------------------------- | ----------------------------------------------------- | -| **Type Safety** | Full static typing end-to-end | Dynamic discovery at runtime | -| **Execution** | Same process as your request (low latency) | Separate server (network overhead) | -| **Prompt Control** | Full control over descriptions and schemas | Controlled by MCP server owner | -| **Schema Control** | You define and optimize for your model | Controlled by MCP server owner | -| **Version Management** | Full visibility over updates | Can update independently (version skew risk) | -| **Authentication** | Same process, no additional auth required | Separate server introduces additional auth complexity | -| **Best For** | Production applications requiring control and performance | Development iteration, user-provided tools | - -## Examples - -You can see tools in action using various frameworks in the following examples: - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/16-mcp-tools.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/16-mcp-tools.mdx deleted file mode 100644 index cbe7d7284..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/16-mcp-tools.mdx +++ /dev/null @@ -1,383 +0,0 @@ ---- -title: Model Context Protocol (MCP) -description: Learn how to connect to Model Context Protocol (MCP) servers and use their tools with AI SDK Core. ---- - -# Model Context Protocol (MCP) - -The AI SDK supports connecting to [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers to access their tools, resources, and prompts. -This enables your AI applications to discover and use capabilities across various services through a standardized interface. - - - If you're using OpenAI's Responses API, you can also use the built-in - `openai.tools.mcp` tool, which provides direct MCP server integration without - needing to convert tools. See the [OpenAI provider - documentation](/providers/ai-sdk-providers/openai#mcp-tool) for details. - - -## Initializing an MCP Client - -We recommend using HTTP transport (like `StreamableHTTPClientTransport`) for production deployments. The stdio transport should only be used for connecting to local servers as it cannot be deployed to production environments. - -Create an MCP client using one of the following transport options: - -- **HTTP transport (Recommended)**: Either configure HTTP directly via the client using `transport: { type: 'http', ... }`, or use MCP's official TypeScript SDK `StreamableHTTPClientTransport` -- SSE (Server-Sent Events): An alternative HTTP-based transport -- `stdio`: For local development only. Uses standard input/output streams for local MCP servers - -### HTTP Transport (Recommended) - -For production deployments, we recommend using the HTTP transport. You can configure it directly on the client: - -```typescript -import { createMCPClient } from '@ai-sdk/mcp'; - -const mcpClient = await createMCPClient({ - transport: { - type: 'http', - url: 'https://your-server.com/mcp', - - // optional: configure HTTP headers - headers: { Authorization: 'Bearer my-api-key' }, - - // optional: provide an OAuth client provider for automatic authorization - authProvider: myOAuthClientProvider, - - // optional: reject redirect responses to prevent SSRF - redirect: 'error', - }, -}); -``` - -Alternatively, you can use `StreamableHTTPClientTransport` from MCP's official TypeScript SDK: - -```typescript -import { createMCPClient } from '@ai-sdk/mcp'; -import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; - -const url = new URL('https://your-server.com/mcp'); -const mcpClient = await createMCPClient({ - transport: new StreamableHTTPClientTransport(url, { - sessionId: 'session_123', - }), -}); -``` - -### SSE Transport - -SSE provides an alternative HTTP-based transport option. Configure it with a `type` and `url` property. You can also provide an `authProvider` for OAuth: - -```typescript -import { createMCPClient } from '@ai-sdk/mcp'; - -const mcpClient = await createMCPClient({ - transport: { - type: 'sse', - url: 'https://my-server.com/sse', - - // optional: configure HTTP headers - headers: { Authorization: 'Bearer my-api-key' }, - - // optional: provide an OAuth client provider for automatic authorization - authProvider: myOAuthClientProvider, - - // optional: reject redirect responses to prevent SSRF - redirect: 'error', - }, -}); -``` - -### Stdio Transport (Local Servers) - - - The stdio transport should only be used for local servers. - - -The Stdio transport can be imported from either the MCP SDK or the AI SDK: - -```typescript -import { createMCPClient } from '@ai-sdk/mcp'; -import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; -// Or use the AI SDK's stdio transport: -// import { Experimental_StdioMCPTransport as StdioClientTransport } from '@ai-sdk/mcp/mcp-stdio'; - -const mcpClient = await createMCPClient({ - transport: new StdioClientTransport({ - command: 'node', - args: ['src/stdio/dist/server.js'], - }), -}); -``` - -### Custom Transport - -You can also bring your own transport by implementing the `MCPTransport` interface for specific requirements not covered by the standard transports. - - - The client returned by the `createMCPClient` function is a - lightweight client intended for use in tool conversion. It currently does not - support all features of the full MCP client, such as: session - management, resumable streams, and receiving notifications. - -Authorization via OAuth is supported when using the AI SDK MCP HTTP or SSE -transports by providing an `authProvider`. - - - -### Closing the MCP Client - -After initialization, you should close the MCP client based on your usage pattern: - -- For short-lived usage (e.g., single requests), close the client when the response is finished -- For long-running clients (e.g., command line apps), keep the client open but ensure it's closed when the application terminates - -When streaming responses, you can close the client when the LLM response has finished. For example, when using `streamText`, you should use the `onFinish` callback: - -```typescript -const mcpClient = await createMCPClient({ - // ... -}); - -const tools = await mcpClient.tools(); - -const result = await streamText({ - model: __MODEL__, - tools, - prompt: 'What is the weather in Brooklyn, New York?', - onFinish: async () => { - await mcpClient.close(); - }, -}); -``` - -When generating responses without streaming, you can use try/finally or cleanup functions in your framework: - -```typescript -import { createMCPClient, type MCPClient } from '@ai-sdk/mcp'; - -let mcpClient: MCPClient | undefined; - -try { - mcpClient = await createMCPClient({ - // ... - }); -} finally { - await mcpClient?.close(); -} -``` - -## Using MCP Tools - -The client's `tools` method acts as an adapter between MCP tools and AI SDK tools. It supports two approaches for working with tool schemas: - -### Schema Discovery - -With schema discovery, all tools offered by the server are automatically listed, and input parameter types are inferred based on the schemas provided by the server: - -```typescript -const tools = await mcpClient.tools(); -``` - -This approach is simpler to implement and automatically stays in sync with server changes. However, you won't have TypeScript type safety during development, and all tools from the server will be loaded - -### Schema Definition - -For better type safety and control, you can define the tools and their input schemas explicitly in your client code: - -```typescript -import { z } from 'zod'; - -const tools = await mcpClient.tools({ - schemas: { - 'get-data': { - inputSchema: z.object({ - query: z.string().describe('The data query'), - format: z.enum(['json', 'text']).optional(), - }), - }, - // For tools with zero inputs, you should use an empty object: - 'tool-with-no-args': { - inputSchema: z.object({}), - }, - }, -}); -``` - -This approach provides full TypeScript type safety and IDE autocompletion, letting you catch parameter mismatches during development. When you define `schemas`, the client only pulls the explicitly defined tools, keeping your application focused on the tools it needs - -### Typed Tool Outputs - -When MCP servers return `structuredContent` (per the [MCP specification](https://modelcontextprotocol.io/specification/2025-06-18/server/tools#structured-content)), you can define an `outputSchema` to get typed tool results: - -```typescript -import { z } from 'zod'; - -const tools = await mcpClient.tools({ - schemas: { - 'get-weather': { - inputSchema: z.object({ - location: z.string(), - }), - // Define outputSchema for typed results - outputSchema: z.object({ - temperature: z.number(), - conditions: z.string(), - humidity: z.number(), - }), - }, - }, -}); - -const result = await tools['get-weather'].execute( - { location: 'New York' }, - { messages: [], toolCallId: 'weather-1' }, -); - -console.log(`Temperature: ${result.temperature}°C`); -``` - -When `outputSchema` is provided: - -- The client extracts `structuredContent` from the tool result -- The output is validated against your schema at runtime -- You get full TypeScript type safety for the result - -If the server doesn't return `structuredContent`, the client falls back to parsing JSON from the text content. If neither is available or validation fails, an error is thrown. - - - Without `outputSchema`, the tool returns the raw `CallToolResult` object - containing `content` and optional `isError` fields. - - -## Using MCP Resources - -According to the [MCP specification](https://modelcontextprotocol.io/docs/learn/server-concepts#resources), resources are **application-driven** data sources that provide context to the model. Unlike tools (which are model-controlled), your application decides when to fetch and pass resources as context. - -The MCP client provides three methods for working with resources: - -### Listing Resources - -List all available resources from the MCP server: - -```typescript -const resources = await mcpClient.listResources(); -``` - -### Reading Resource Contents - -Read the contents of a specific resource by its URI: - -```typescript -const resourceData = await mcpClient.readResource({ - uri: 'file:///example/document.txt', -}); -``` - -### Listing Resource Templates - -Resource templates are dynamic URI patterns that allow flexible queries. List all available templates: - -```typescript -const templates = await mcpClient.listResourceTemplates(); -``` - -## Using MCP Prompts - - - MCP Prompts is an experimental feature and may change in the future. - - -According to the MCP specification, prompts are user-controlled templates that servers expose for clients to list and retrieve with optional arguments. - -### Listing Prompts - -```typescript -const prompts = await mcpClient.experimental_listPrompts(); -``` - -### Getting a Prompt - -Retrieve prompt messages, optionally passing arguments defined by the server: - -```typescript -const prompt = await mcpClient.experimental_getPrompt({ - name: 'code_review', - arguments: { code: 'function add(a, b) { return a + b; }' }, -}); -``` - -## Handling Elicitation Requests - -Elicitation is a mechanism where MCP servers can request additional information from the client during tool execution. For example, a server might need user input to complete a registration form or confirmation for a sensitive operation. - - - It is up to the client application to handle elicitation requests properly. - The MCP client simply surfaces these requests from the server to your - application code. - - -### Enabling Elicitation Support - -To enable elicitation, you need to advertise the capability when creating the MCP client: - -```typescript -const mcpClient = await createMCPClient({ - transport: { - type: 'sse', - url: 'https://your-server.com/sse', - }, - capabilities: { - elicitation: {}, - }, -}); -``` - -### Registering an Elicitation Handler - -Use the `onElicitationRequest` method to register a handler that will be called when the server requests input: - -```typescript -import { ElicitationRequestSchema } from '@ai-sdk/mcp'; - -mcpClient.onElicitationRequest(ElicitationRequestSchema, async request => { - // request.params.message: A message describing what input is needed - // request.params.requestedSchema: JSON schema defining the expected input structure - - // Get input from the user (implement according to your application's needs) - const userInput = await getInputFromUser( - request.params.message, - request.params.requestedSchema, - ); - - // Return the result with one of three actions: - return { - action: 'accept', // or 'decline' or 'cancel' - content: userInput, // only required when action is 'accept' - }; -}); -``` - -### Elicitation Response Actions - -Your handler must return an object with an `action` field that can be one of: - -- `'accept'`: User provided the requested information. Must include `content` with the data. -- `'decline'`: User chose not to provide the information. -- `'cancel'`: User cancelled the operation entirely. - -## Examples - -You can see MCP in action in the following examples: - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/20-prompt-engineering.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/20-prompt-engineering.mdx deleted file mode 100644 index 29c4deed2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/20-prompt-engineering.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Prompt Engineering -description: Learn how to develop prompts with AI SDK Core. ---- - -# Prompt Engineering - -## Tips - -### Prompts for Tools - -When you create prompts that include tools, getting good results can be tricky as the number and complexity of your tools increases. - -Here are a few tips to help you get the best results: - -1. Use a model that is strong at tool calling, such as `gpt-5` or `gpt-4.1`. Weaker models will often struggle to call tools effectively and flawlessly. -1. Keep the number of tools low, e.g. to 5 or less. -1. Keep the complexity of the tool parameters low. Complex Zod schemas with many nested and optional elements, unions, etc. can be challenging for the model to work with. -1. Use semantically meaningful names for your tools, parameters, parameter properties, etc. The more information you pass to the model, the better it can understand what you want. -1. Add `.describe("...")` to your Zod schema properties to give the model hints about what a particular property is for. -1. When the output of a tool might be unclear to the model and there are dependencies between tools, use the `description` field of a tool to provide information about the output of the tool execution. -1. You can include example input/outputs of tool calls in your prompt to help the model understand how to use the tools. Keep in mind that the tools work with JSON objects, so the examples should use JSON. - -In general, the goal should be to give the model all information it needs in a clear way. - -### Tool & Structured Data Schemas - -The mapping from Zod schemas to LLM inputs (typically JSON schema) is not always straightforward, since the mapping is not one-to-one. - -#### Zod Dates - -Zod expects JavaScript Date objects, but models return dates as strings. -You can specify and validate the date format using `z.string().datetime()` or `z.string().date()`, -and then use a Zod transformer to convert the string to a Date object. - -```ts highlight="8-11" -const result = await generateText({ - model: __MODEL__, - output: Output.object({ - schema: z.object({ - events: z.array( - z.object({ - event: z.string(), - date: z - .string() - .date() - .transform(value => new Date(value)), - }), - ), - }), - }), - prompt: 'List 5 important events from the year 2000.', -}); -``` - -#### Optional Parameters - -When working with tools that have optional parameters, you may encounter compatibility issues with certain providers that use strict schema validation. - - - This is particularly relevant for OpenAI models with structured outputs - (strict mode). - - -For maximum compatibility, optional parameters should use `.nullable()` instead of `.optional()`: - -```ts highlight="6,7,16,17" -// This may fail with strict schema validation -const failingTool = tool({ - description: 'Execute a command', - inputSchema: z.object({ - command: z.string(), - workdir: z.string().optional(), // This can cause errors - timeout: z.string().optional(), - }), -}); - -// This works with strict schema validation -const workingTool = tool({ - description: 'Execute a command', - inputSchema: z.object({ - command: z.string(), - workdir: z.string().nullable(), // Use nullable instead - timeout: z.string().nullable(), - }), -}); -``` - -#### Temperature Settings - -For tool calls and object generation, it's recommended to use `temperature: 0` to ensure deterministic and consistent results: - -```ts highlight="3" -const result = await generateText({ - model: __MODEL__, - temperature: 0, // Recommended for tool calls - tools: { - myTool: tool({ - description: 'Execute a command', - inputSchema: z.object({ - command: z.string(), - }), - }), - }, - prompt: 'Execute the ls command', -}); -``` - -Lower temperature values reduce randomness in model outputs, which is particularly important when the model needs to: - -- Generate structured data with specific formats -- Make precise tool calls with correct parameters -- Follow strict schemas consistently - -## Debugging - -### Inspecting Warnings - -Not all providers support all AI SDK features. -Providers either throw exceptions or return warnings when they do not support a feature. -To check if your prompt, tools, and settings are handled correctly by the provider, you can check the call warnings: - -```ts -const result = await generateText({ - model: __MODEL__, - prompt: 'Hello, world!', -}); - -console.log(result.warnings); -``` - -### HTTP Request Bodies - -You can inspect the raw HTTP request bodies for models that expose them, e.g. [OpenAI](/providers/ai-sdk-providers/openai). -This allows you to inspect the exact payload that is sent to the model provider in the provider-specific way. - -Request bodies are available via the `request.body` property of the response: - -```ts highlight="6" -const result = await generateText({ - model: __MODEL__, - prompt: 'Hello, world!', -}); - -console.log(result.request.body); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/25-settings.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/25-settings.mdx deleted file mode 100644 index f19eb3e8d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/25-settings.mdx +++ /dev/null @@ -1,198 +0,0 @@ ---- -title: Settings -description: Learn how to configure the AI SDK. ---- - -# Settings - -Large language models (LLMs) typically provide settings to augment their output. - -All AI SDK functions support the following common settings in addition to the model, the [prompt](./prompts), and additional provider-specific settings: - -```ts highlight="3-5" -const result = await generateText({ - model: __MODEL__, - maxOutputTokens: 512, - temperature: 0.3, - maxRetries: 5, - prompt: 'Invent a new holiday and describe its traditions.', -}); -``` - - - Some providers do not support all common settings. If you use a setting with a - provider that does not support it, a warning will be generated. You can check - the `warnings` property in the result object to see if any warnings were - generated. - - -### `maxOutputTokens` - -Maximum number of tokens to generate. - -### `temperature` - -Temperature setting. - -The value is passed through to the provider. The range depends on the provider and model. -For most providers, `0` means almost deterministic results, and higher values mean more randomness. - -It is recommended to set either `temperature` or `topP`, but not both. - -In AI SDK 5.0, temperature is no longer set to `0` by default. - -### `topP` - -Nucleus sampling. - -The value is passed through to the provider. The range depends on the provider and model. -For most providers, nucleus sampling is a number between 0 and 1. -E.g. 0.1 would mean that only tokens with the top 10% probability mass are considered. - -It is recommended to set either `temperature` or `topP`, but not both. - -### `topK` - -Only sample from the top K options for each subsequent token. - -Used to remove "long tail" low probability responses. -Recommended for advanced use cases only. You usually only need to use `temperature`. - -### `presencePenalty` - -The presence penalty affects the likelihood of the model to repeat information that is already in the prompt. - -The value is passed through to the provider. The range depends on the provider and model. -For most providers, `0` means no penalty. - -### `frequencyPenalty` - -The frequency penalty affects the likelihood of the model to repeatedly use the same words or phrases. - -The value is passed through to the provider. The range depends on the provider and model. -For most providers, `0` means no penalty. - -### `stopSequences` - -The stop sequences to use for stopping the text generation. - -If set, the model will stop generating text when one of the stop sequences is generated. -Providers may have limits on the number of stop sequences. - -### `seed` - -It is the seed (integer) to use for random sampling. -If set and supported by the model, calls will generate deterministic results. - -### `maxRetries` - -Maximum number of retries. Set to 0 to disable retries. Default: `2`. - -### `abortSignal` - -An optional abort signal that can be used to cancel the call. - -The abort signal can e.g. be forwarded from a user interface to cancel the call, -or to define a timeout using `AbortSignal.timeout`. - -#### Example: AbortSignal.timeout - -```ts -const result = await generateText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', - abortSignal: AbortSignal.timeout(5000), // 5 seconds -}); -``` - -### `timeout` - -An optional timeout in milliseconds. The call will be aborted if it takes longer than the specified duration. - -This is a convenience parameter that creates an abort signal internally. It can be used alongside `abortSignal` - if both are provided, the call will abort when either condition is met. - -You can specify the timeout either as a number (milliseconds) or as an object with `totalMs`, `stepMs`, and/or `chunkMs` properties: - -- `totalMs`: The total timeout for the entire call including all steps. -- `stepMs`: The timeout for each individual step (LLM call). This is useful for multi-step generations where you want to limit the time spent on each step independently. -- `chunkMs`: The timeout between stream chunks (streaming only). The call will abort if no new chunk is received within this duration. This is useful for detecting stalled streams. - -#### Example: 5 second timeout (number format) - -```ts -const result = await generateText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', - timeout: 5000, // 5 seconds -}); -``` - -#### Example: 5 second total timeout (object format) - -```ts -const result = await generateText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', - timeout: { totalMs: 5000 }, // 5 seconds -}); -``` - -#### Example: 10 second step timeout - -```ts -const result = await generateText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', - timeout: { stepMs: 10000 }, // 10 seconds per step -}); -``` - -#### Example: Combined total and step timeout - -```ts -const result = await generateText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', - timeout: { - totalMs: 60000, // 60 seconds total - stepMs: 10000, // 10 seconds per step - }, -}); -``` - -#### Example: Per-chunk timeout for streaming (streamText only) - -```ts -const result = streamText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', - timeout: { chunkMs: 5000 }, // abort if no chunk received for 5 seconds -}); -``` - -### `headers` - -Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers. - -You can use the request headers to provide additional information to the provider, -depending on what the provider supports. For example, some observability providers support -headers such as `Prompt-Id`. - -```ts -import { generateText } from 'ai'; -__PROVIDER_IMPORT__; - -const result = await generateText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', - headers: { - 'Prompt-Id': 'my-prompt-id', - }, -}); -``` - - - The `headers` setting is for request-specific headers. You can also set - `headers` in the provider configuration. These headers will be sent with every - request made by the provider. - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/30-embeddings.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/30-embeddings.mdx deleted file mode 100644 index fabf47b99..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/30-embeddings.mdx +++ /dev/null @@ -1,246 +0,0 @@ ---- -title: Embeddings -description: Learn how to embed values with the AI SDK. ---- - -# Embeddings - -Embeddings are a way to represent words, phrases, or images as vectors in a high-dimensional space. -In this space, similar words are close to each other, and the distance between words can be used to measure their similarity. - -## Embedding a Single Value - -The AI SDK provides the [`embed`](/docs/reference/ai-sdk-core/embed) function to embed single values, which is useful for tasks such as finding similar words -or phrases or clustering text. -You can use it with embeddings models, e.g. `openai.embeddingModel('text-embedding-3-large')` or `mistral.embeddingModel('mistral-embed')`. - -```tsx -import { embed } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -// 'embedding' is a single embedding object (number[]) -const { embedding } = await embed({ - model: 'openai/text-embedding-3-small', - value: 'sunny day at the beach', -}); -``` - -## Embedding Many Values - -When loading data, e.g. when preparing a data store for retrieval-augmented generation (RAG), -it is often useful to embed many values at once (batch embedding). - -The AI SDK provides the [`embedMany`](/docs/reference/ai-sdk-core/embed-many) function for this purpose. -Similar to `embed`, you can use it with embeddings models, -e.g. `openai.embeddingModel('text-embedding-3-large')` or `mistral.embeddingModel('mistral-embed')`. - -```tsx -import { openai } from '@ai-sdk/openai'; -import { embedMany } from 'ai'; - -// 'embeddings' is an array of embedding objects (number[][]). -// It is sorted in the same order as the input values. -const { embeddings } = await embedMany({ - model: 'openai/text-embedding-3-small', - values: [ - 'sunny day at the beach', - 'rainy afternoon in the city', - 'snowy night in the mountains', - ], -}); -``` - -## Embedding Similarity - -After embedding values, you can calculate the similarity between them using the [`cosineSimilarity`](/docs/reference/ai-sdk-core/cosine-similarity) function. -This is useful to e.g. find similar words or phrases in a dataset. -You can also rank and filter related items based on their similarity. - -```ts highlight={"2,10"} -import { openai } from '@ai-sdk/openai'; -import { cosineSimilarity, embedMany } from 'ai'; - -const { embeddings } = await embedMany({ - model: 'openai/text-embedding-3-small', - values: ['sunny day at the beach', 'rainy afternoon in the city'], -}); - -console.log( - `cosine similarity: ${cosineSimilarity(embeddings[0], embeddings[1])}`, -); -``` - -## Token Usage - -Many providers charge based on the number of tokens used to generate embeddings. -Both `embed` and `embedMany` provide token usage information in the `usage` property of the result object: - -```ts highlight={"4,9"} -import { openai } from '@ai-sdk/openai'; -import { embed } from 'ai'; - -const { embedding, usage } = await embed({ - model: 'openai/text-embedding-3-small', - value: 'sunny day at the beach', -}); - -console.log(usage); // { tokens: 10 } -``` - -## Settings - -### Provider Options - -Embedding model settings can be configured using `providerOptions` for provider-specific parameters: - -```ts highlight={"5-9"} -import { openai } from '@ai-sdk/openai'; -import { embed } from 'ai'; - -const { embedding } = await embed({ - model: 'openai/text-embedding-3-small', - value: 'sunny day at the beach', - providerOptions: { - openai: { - dimensions: 512, // Reduce embedding dimensions - }, - }, -}); -``` - -### Parallel Requests - -The `embedMany` function now supports parallel processing with configurable `maxParallelCalls` to optimize performance: - -```ts highlight={"4"} -import { openai } from '@ai-sdk/openai'; -import { embedMany } from 'ai'; - -const { embeddings, usage } = await embedMany({ - maxParallelCalls: 2, // Limit parallel requests - model: 'openai/text-embedding-3-small', - values: [ - 'sunny day at the beach', - 'rainy afternoon in the city', - 'snowy night in the mountains', - ], -}); -``` - -### Retries - -Both `embed` and `embedMany` accept an optional `maxRetries` parameter of type `number` -that you can use to set the maximum number of retries for the embedding process. -It defaults to `2` retries (3 attempts in total). You can set it to `0` to disable retries. - -```ts highlight={"7"} -import { openai } from '@ai-sdk/openai'; -import { embed } from 'ai'; - -const { embedding } = await embed({ - model: 'openai/text-embedding-3-small', - value: 'sunny day at the beach', - maxRetries: 0, // Disable retries -}); -``` - -### Abort Signals and Timeouts - -Both `embed` and `embedMany` accept an optional `abortSignal` parameter of -type [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) -that you can use to abort the embedding process or set a timeout. - -```ts highlight={"7"} -import { openai } from '@ai-sdk/openai'; -import { embed } from 'ai'; - -const { embedding } = await embed({ - model: 'openai/text-embedding-3-small', - value: 'sunny day at the beach', - abortSignal: AbortSignal.timeout(1000), // Abort after 1 second -}); -``` - -### Custom Headers - -Both `embed` and `embedMany` accept an optional `headers` parameter of type `Record` -that you can use to add custom headers to the embedding request. - -```ts highlight={"7"} -import { openai } from '@ai-sdk/openai'; -import { embed } from 'ai'; - -const { embedding } = await embed({ - model: 'openai/text-embedding-3-small', - value: 'sunny day at the beach', - headers: { 'X-Custom-Header': 'custom-value' }, -}); -``` - -## Response Information - -Both `embed` and `embedMany` return response information that includes the raw provider response: - -```ts highlight={"4,9"} -import { openai } from '@ai-sdk/openai'; -import { embed } from 'ai'; - -const { embedding, response } = await embed({ - model: 'openai/text-embedding-3-small', - value: 'sunny day at the beach', -}); - -console.log(response); // Raw provider response -``` - -## Embedding Middleware - -You can enhance embedding models, e.g. to set default values, using -`wrapEmbeddingModel` and `EmbeddingModelMiddleware`. - -Here is an example that uses the built-in `defaultEmbeddingSettingsMiddleware`: - -```ts -import { - defaultEmbeddingSettingsMiddleware, - embed, - wrapEmbeddingModel, - gateway, -} from 'ai'; - -const embeddingModelWithDefaults = wrapEmbeddingModel({ - model: gateway.embeddingModel('google/gemini-embedding-001'), - middleware: defaultEmbeddingSettingsMiddleware({ - settings: { - providerOptions: { - google: { - outputDimensionality: 256, - taskType: 'CLASSIFICATION', - }, - }, - }, - }), -}); -``` - -## Embedding Providers & Models - -Several providers offer embedding models: - -| Provider | Model | Embedding Dimensions | Multimodal | -| ----------------------------------------------------------------------------------------- | ------------------------------- | -------------------- | ------------------- | -| [OpenAI](/providers/ai-sdk-providers/openai#embedding-models) | `text-embedding-3-large` | 3072 | | -| [OpenAI](/providers/ai-sdk-providers/openai#embedding-models) | `text-embedding-3-small` | 1536 | | -| [OpenAI](/providers/ai-sdk-providers/openai#embedding-models) | `text-embedding-ada-002` | 1536 | | -| [Google Generative AI](/providers/ai-sdk-providers/google-generative-ai#embedding-models) | `gemini-embedding-001` | 3072 | | -| [Google Generative AI](/providers/ai-sdk-providers/google-generative-ai#embedding-models) | `gemini-embedding-2-preview` | 3072 | | -| [Mistral](/providers/ai-sdk-providers/mistral#embedding-models) | `mistral-embed` | 1024 | | -| [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-english-v3.0` | 1024 | | -| [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-multilingual-v3.0` | 1024 | | -| [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-english-light-v3.0` | 384 | | -| [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-multilingual-light-v3.0` | 384 | | -| [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-english-v2.0` | 4096 | | -| [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-english-light-v2.0` | 1024 | | -| [Cohere](/providers/ai-sdk-providers/cohere#embedding-models) | `embed-multilingual-v2.0` | 768 | | -| [Amazon Bedrock](/providers/ai-sdk-providers/amazon-bedrock#embedding-models) | `amazon.titan-embed-text-v1` | 1536 | | -| [Amazon Bedrock](/providers/ai-sdk-providers/amazon-bedrock#embedding-models) | `amazon.titan-embed-text-v2:0` | 1024 | | diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/31-reranking.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/31-reranking.mdx deleted file mode 100644 index 533e0a956..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/31-reranking.mdx +++ /dev/null @@ -1,218 +0,0 @@ ---- -title: Reranking -description: Learn how to rerank documents with the AI SDK. ---- - -# Reranking - -Reranking is a technique used to improve search relevance by reordering a set of documents based on their relevance to a query. -Unlike embedding-based similarity search, reranking models are specifically trained to understand the relationship between queries and documents, -often producing more accurate relevance scores. - -## Reranking Documents - -The AI SDK provides the [`rerank`](/docs/reference/ai-sdk-core/rerank) function to rerank documents based on their relevance to a query. -You can use it with reranking models, e.g. `cohere.reranking('rerank-v3.5')` or `bedrock.reranking('cohere.rerank-v3-5:0')`. - -```tsx -import { rerank } from 'ai'; -import { cohere } from '@ai-sdk/cohere'; - -const documents = [ - 'sunny day at the beach', - 'rainy afternoon in the city', - 'snowy night in the mountains', -]; - -const { ranking } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents, - query: 'talk about rain', - topN: 2, // Return top 2 most relevant documents -}); - -console.log(ranking); -// [ -// { originalIndex: 1, score: 0.9, document: 'rainy afternoon in the city' }, -// { originalIndex: 0, score: 0.3, document: 'sunny day at the beach' } -// ] -``` - -## Working with Object Documents - -Reranking also supports structured documents (JSON objects), making it ideal for searching through databases, emails, or other structured content: - -```tsx -import { rerank } from 'ai'; -import { cohere } from '@ai-sdk/cohere'; - -const documents = [ - { - from: 'Paul Doe', - subject: 'Follow-up', - text: 'We are happy to give you a discount of 20% on your next order.', - }, - { - from: 'John McGill', - subject: 'Missing Info', - text: 'Sorry, but here is the pricing information from Oracle: $5000/month', - }, -]; - -const { ranking, rerankedDocuments } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents, - query: 'Which pricing did we get from Oracle?', - topN: 1, -}); - -console.log(rerankedDocuments[0]); -// { from: 'John McGill', subject: 'Missing Info', text: '...' } -``` - -## Understanding the Results - -The `rerank` function returns a comprehensive result object: - -```ts -import { cohere } from '@ai-sdk/cohere'; -import { rerank } from 'ai'; - -const { ranking, rerankedDocuments, originalDocuments } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents: ['sunny day at the beach', 'rainy afternoon in the city'], - query: 'talk about rain', -}); - -// ranking: sorted array of { originalIndex, score, document } -// rerankedDocuments: documents sorted by relevance (convenience property) -// originalDocuments: original documents array -``` - -Each item in the `ranking` array contains: - -- `originalIndex`: Position in the original documents array -- `score`: Relevance score (typically 0-1, where higher is more relevant) -- `document`: The original document - -## Settings - -### Top-N Results - -Use `topN` to limit the number of results returned. This is useful for retrieving only the most relevant documents: - -```ts highlight={"7"} -import { cohere } from '@ai-sdk/cohere'; -import { rerank } from 'ai'; - -const { ranking } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents: ['doc1', 'doc2', 'doc3', 'doc4', 'doc5'], - query: 'relevant information', - topN: 3, // Return only top 3 most relevant documents -}); -``` - -### Provider Options - -Reranking model settings can be configured using `providerOptions` for provider-specific parameters: - -```ts highlight={"8-12"} -import { cohere } from '@ai-sdk/cohere'; -import { rerank } from 'ai'; - -const { ranking } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents: ['sunny day at the beach', 'rainy afternoon in the city'], - query: 'talk about rain', - providerOptions: { - cohere: { - maxTokensPerDoc: 1000, // Limit tokens per document - }, - }, -}); -``` - -### Retries - -The `rerank` function accepts an optional `maxRetries` parameter of type `number` -that you can use to set the maximum number of retries for the reranking process. -It defaults to `2` retries (3 attempts in total). You can set it to `0` to disable retries. - -```ts highlight={"7"} -import { cohere } from '@ai-sdk/cohere'; -import { rerank } from 'ai'; - -const { ranking } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents: ['sunny day at the beach', 'rainy afternoon in the city'], - query: 'talk about rain', - maxRetries: 0, // Disable retries -}); -``` - -### Abort Signals and Timeouts - -The `rerank` function accepts an optional `abortSignal` parameter of -type [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) -that you can use to abort the reranking process or set a timeout. - -```ts highlight={"7"} -import { cohere } from '@ai-sdk/cohere'; -import { rerank } from 'ai'; - -const { ranking } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents: ['sunny day at the beach', 'rainy afternoon in the city'], - query: 'talk about rain', - abortSignal: AbortSignal.timeout(5000), // Abort after 5 seconds -}); -``` - -### Custom Headers - -The `rerank` function accepts an optional `headers` parameter of type `Record` -that you can use to add custom headers to the reranking request. - -```ts highlight={"7"} -import { cohere } from '@ai-sdk/cohere'; -import { rerank } from 'ai'; - -const { ranking } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents: ['sunny day at the beach', 'rainy afternoon in the city'], - query: 'talk about rain', - headers: { 'X-Custom-Header': 'custom-value' }, -}); -``` - -## Response Information - -The `rerank` function returns response information that includes the raw provider response: - -```ts highlight={"4,10"} -import { cohere } from '@ai-sdk/cohere'; -import { rerank } from 'ai'; - -const { ranking, response } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents: ['sunny day at the beach', 'rainy afternoon in the city'], - query: 'talk about rain', -}); - -console.log(response); // { id, timestamp, modelId, headers, body } -``` - -## Reranking Providers & Models - -Several providers offer reranking models: - -| Provider | Model | -| ----------------------------------------------------------------------------- | ------------------------------------- | -| [Cohere](/providers/ai-sdk-providers/cohere#reranking-models) | `rerank-v3.5` | -| [Cohere](/providers/ai-sdk-providers/cohere#reranking-models) | `rerank-english-v3.0` | -| [Cohere](/providers/ai-sdk-providers/cohere#reranking-models) | `rerank-multilingual-v3.0` | -| [Amazon Bedrock](/providers/ai-sdk-providers/amazon-bedrock#reranking-models) | `amazon.rerank-v1:0` | -| [Amazon Bedrock](/providers/ai-sdk-providers/amazon-bedrock#reranking-models) | `cohere.rerank-v3-5:0` | -| [Together.ai](/providers/ai-sdk-providers/togetherai#reranking-models) | `Salesforce/Llama-Rank-v1` | -| [Together.ai](/providers/ai-sdk-providers/togetherai#reranking-models) | `mixedbread-ai/Mxbai-Rerank-Large-V2` | diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/35-image-generation.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/35-image-generation.mdx deleted file mode 100644 index 0b1f99acb..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/35-image-generation.mdx +++ /dev/null @@ -1,341 +0,0 @@ ---- -title: Image Generation -description: Learn how to generate images with the AI SDK. ---- - -# Image Generation - -The AI SDK provides the [`generateImage`](/docs/reference/ai-sdk-core/generate-image) -function to generate images based on a given prompt using an image model. - -```tsx -import { generateImage } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const { image } = await generateImage({ - model: openai.image('dall-e-3'), - prompt: 'Santa Claus driving a Cadillac', -}); -``` - -You can access the image data using the `base64` or `uint8Array` properties: - -```tsx -const base64 = image.base64; // base64 image data -const uint8Array = image.uint8Array; // Uint8Array image data -``` - -## Settings - -### Size and Aspect Ratio - -Depending on the model, you can either specify the size or the aspect ratio. - -##### Size - -The size is specified as a string in the format `{width}x{height}`. -Models only support a few sizes, and the supported sizes are different for each model and provider. - -```tsx highlight={"7"} -import { generateImage } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const { image } = await generateImage({ - model: openai.image('dall-e-3'), - prompt: 'Santa Claus driving a Cadillac', - size: '1024x1024', -}); -``` - -##### Aspect Ratio - -The aspect ratio is specified as a string in the format `{width}:{height}`. -Models only support a few aspect ratios, and the supported aspect ratios are different for each model and provider. - -```tsx highlight={"7"} -import { generateImage } from 'ai'; -import { vertex } from '@ai-sdk/google-vertex'; - -const { image } = await generateImage({ - model: vertex.image('imagen-4.0-generate-001'), - prompt: 'Santa Claus driving a Cadillac', - aspectRatio: '16:9', -}); -``` - -### Generating Multiple Images - -`generateImage` also supports generating multiple images at once: - -```tsx highlight={"7"} -import { generateImage } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const { images } = await generateImage({ - model: openai.image('dall-e-2'), - prompt: 'Santa Claus driving a Cadillac', - n: 4, // number of images to generate -}); -``` - - - `generateImage` will automatically call the model as often as needed (in - parallel) to generate the requested number of images. - - -Each image model has an internal limit on how many images it can generate in a single API call. The AI SDK manages this automatically by batching requests appropriately when you request multiple images using the `n` parameter. By default, the SDK uses provider-documented limits (for example, DALL-E 3 can only generate 1 image per call, while DALL-E 2 supports up to 10). - -If needed, you can override this behavior using the `maxImagesPerCall` setting when generating your image. This is particularly useful when working with new or custom models where the default batch size might not be optimal: - -```tsx -const { images } = await generateImage({ - model: openai.image('dall-e-2'), - prompt: 'Santa Claus driving a Cadillac', - maxImagesPerCall: 5, // Override the default batch size - n: 10, // Will make 2 calls of 5 images each -}); -``` - -### Providing a Seed - -You can provide a seed to the `generateImage` function to control the output of the image generation process. -If supported by the model, the same seed will always produce the same image. - -```tsx highlight={"7"} -import { generateImage } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const { image } = await generateImage({ - model: openai.image('dall-e-3'), - prompt: 'Santa Claus driving a Cadillac', - seed: 1234567890, -}); -``` - -### Provider-specific Settings - -Image models often have provider- or even model-specific settings. -You can pass such settings to the `generateImage` function -using the `providerOptions` parameter. The options for the provider -(`openai` in the example below) become request body properties. - -```tsx highlight={"9"} -import { generateImage } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const { image } = await generateImage({ - model: openai.image('dall-e-3'), - prompt: 'Santa Claus driving a Cadillac', - size: '1024x1024', - providerOptions: { - openai: { style: 'vivid', quality: 'hd' }, - }, -}); -``` - -### Abort Signals and Timeouts - -`generateImage` accepts an optional `abortSignal` parameter of -type [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) -that you can use to abort the image generation process or set a timeout. - -```ts highlight={"7"} -import { openai } from '@ai-sdk/openai'; -import { generateImage } from 'ai'; - -const { image } = await generateImage({ - model: openai.image('dall-e-3'), - prompt: 'Santa Claus driving a Cadillac', - abortSignal: AbortSignal.timeout(1000), // Abort after 1 second -}); -``` - -### Custom Headers - -`generateImage` accepts an optional `headers` parameter of type `Record` -that you can use to add custom headers to the image generation request. - -```ts highlight={"7"} -import { openai } from '@ai-sdk/openai'; -import { generateImage } from 'ai'; - -const { image } = await generateImage({ - model: openai.image('dall-e-3'), - prompt: 'Santa Claus driving a Cadillac', - headers: { 'X-Custom-Header': 'custom-value' }, -}); -``` - -### Warnings - -If the model returns warnings, e.g. for unsupported parameters, they will be available in the `warnings` property of the response. - -```tsx -const { image, warnings } = await generateImage({ - model: openai.image('dall-e-3'), - prompt: 'Santa Claus driving a Cadillac', -}); -``` - -### Additional provider-specific meta data - -Some providers expose additional meta data for the result overall or per image. - -```tsx -const prompt = 'Santa Claus driving a Cadillac'; - -const { image, providerMetadata } = await generateImage({ - model: openai.image('dall-e-3'), - prompt, -}); - -const revisedPrompt = providerMetadata.openai.images[0]?.revisedPrompt; - -console.log({ - prompt, - revisedPrompt, -}); -``` - -The outer key of the returned `providerMetadata` is the provider name. The inner values are the metadata. An `images` key is always present in the metadata and is an array with the same length as the top level `images` key. - -### Error Handling - -When `generateImage` cannot generate a valid image, it throws a [`AI_NoImageGeneratedError`](/docs/reference/ai-sdk-errors/ai-no-image-generated-error). - -This error occurs when the AI provider fails to generate an image. It can arise due to the following reasons: - -- The model failed to generate a response -- The model generated a response that could not be parsed - -The error preserves the following information to help you log the issue: - -- `responses`: Metadata about the image model responses, including timestamp, model, and headers. -- `cause`: The cause of the error. You can use this for more detailed error handling - -```ts -import { generateImage, NoImageGeneratedError } from 'ai'; - -try { - await generateImage({ model, prompt }); -} catch (error) { - if (NoImageGeneratedError.isInstance(error)) { - console.log('NoImageGeneratedError'); - console.log('Cause:', error.cause); - console.log('Responses:', error.responses); - } -} -``` - -## Image Middleware - -You can enhance image models, e.g. to set default values or implement logging, using -`wrapImageModel` and `ImageModelV3Middleware`. - -Here is an example that sets a default size when none is provided: - -```ts -import { generateImage, wrapImageModel } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const model = wrapImageModel({ - model: openai.image('gpt-image-1'), - middleware: { - specificationVersion: 'v3', - transformParams: async ({ params }) => ({ - ...params, - size: params.size ?? '1024x1024', - }), - }, -}); - -const { image } = await generateImage({ - model, - prompt: 'Santa Claus driving a Cadillac', -}); -``` - -## Generating Images with Language Models - -Some language models such as Google `gemini-2.5-flash-image` support multi-modal outputs including images. -With such models, you can access the generated images using the `files` property of the response. - -```ts -import { google } from '@ai-sdk/google'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: google('gemini-2.5-flash-image'), - prompt: 'Generate an image of a comic cat', -}); - -for (const file of result.files) { - if (file.mediaType.startsWith('image/')) { - // The file object provides multiple data formats: - // Access images as base64 string, Uint8Array binary data, or check type - // - file.base64: string (data URL format) - // - file.uint8Array: Uint8Array (binary data) - // - file.mediaType: string (e.g. "image/png") - } -} -``` - -## Image Models - -| Provider | Model | Support sizes (`width x height`) or aspect ratios (`width : height`) | -| ------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [xAI Grok](/providers/ai-sdk-providers/xai#image-models) | `grok-imagine-image` | `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2`, `2:3`, `2:1`, `1:2`, `19.5:9`, `9:19.5`, `20:9`, `9:20`, `auto` | -| [OpenAI](/providers/ai-sdk-providers/openai#image-models) | `gpt-image-1` | 1024x1024, 1536x1024, 1024x1536 | -| [OpenAI](/providers/ai-sdk-providers/openai#image-models) | `dall-e-3` | 1024x1024, 1792x1024, 1024x1792 | -| [OpenAI](/providers/ai-sdk-providers/openai#image-models) | `dall-e-2` | 256x256, 512x512, 1024x1024 | -| [Amazon Bedrock](/providers/ai-sdk-providers/amazon-bedrock#image-models) | `amazon.nova-canvas-v1:0` | 320-4096 (multiples of 16), 1:4 to 4:1, max 4.2M pixels | -| [Fal](/providers/ai-sdk-providers/fal#image-models) | `fal-ai/flux/dev` | 1:1, 3:4, 4:3, 9:16, 16:9, 9:21, 21:9 | -| [Fal](/providers/ai-sdk-providers/fal#image-models) | `fal-ai/flux-lora` | 1:1, 3:4, 4:3, 9:16, 16:9, 9:21, 21:9 | -| [Fal](/providers/ai-sdk-providers/fal#image-models) | `fal-ai/fast-sdxl` | 1:1, 3:4, 4:3, 9:16, 16:9, 9:21, 21:9 | -| [Fal](/providers/ai-sdk-providers/fal#image-models) | `fal-ai/flux-pro/v1.1-ultra` | 1:1, 3:4, 4:3, 9:16, 16:9, 9:21, 21:9 | -| [Fal](/providers/ai-sdk-providers/fal#image-models) | `fal-ai/ideogram/v2` | 1:1, 3:4, 4:3, 9:16, 16:9, 9:21, 21:9 | -| [Fal](/providers/ai-sdk-providers/fal#image-models) | `fal-ai/recraft-v3` | 1:1, 3:4, 4:3, 9:16, 16:9, 9:21, 21:9 | -| [Fal](/providers/ai-sdk-providers/fal#image-models) | `fal-ai/stable-diffusion-3.5-large` | 1:1, 3:4, 4:3, 9:16, 16:9, 9:21, 21:9 | -| [Fal](/providers/ai-sdk-providers/fal#image-models) | `fal-ai/hyper-sdxl` | 1:1, 3:4, 4:3, 9:16, 16:9, 9:21, 21:9 | -| [DeepInfra](/providers/ai-sdk-providers/deepinfra#image-models) | `stabilityai/sd3.5` | 1:1, 16:9, 1:9, 3:2, 2:3, 4:5, 5:4, 9:16, 9:21 | -| [DeepInfra](/providers/ai-sdk-providers/deepinfra#image-models) | `black-forest-labs/FLUX-1.1-pro` | 256-1440 (multiples of 32) | -| [DeepInfra](/providers/ai-sdk-providers/deepinfra#image-models) | `black-forest-labs/FLUX-1-schnell` | 256-1440 (multiples of 32) | -| [DeepInfra](/providers/ai-sdk-providers/deepinfra#image-models) | `black-forest-labs/FLUX-1-dev` | 256-1440 (multiples of 32) | -| [DeepInfra](/providers/ai-sdk-providers/deepinfra#image-models) | `black-forest-labs/FLUX-pro` | 256-1440 (multiples of 32) | -| [DeepInfra](/providers/ai-sdk-providers/deepinfra#image-models) | `stabilityai/sd3.5-medium` | 1:1, 16:9, 1:9, 3:2, 2:3, 4:5, 5:4, 9:16, 9:21 | -| [DeepInfra](/providers/ai-sdk-providers/deepinfra#image-models) | `stabilityai/sdxl-turbo` | 1:1, 16:9, 1:9, 3:2, 2:3, 4:5, 5:4, 9:16, 9:21 | -| [Replicate](/providers/ai-sdk-providers/replicate) | `black-forest-labs/flux-schnell` | 1:1, 2:3, 3:2, 4:5, 5:4, 16:9, 9:16, 9:21, 21:9 | -| [Replicate](/providers/ai-sdk-providers/replicate) | `recraft-ai/recraft-v3` | 1024x1024, 1365x1024, 1024x1365, 1536x1024, 1024x1536, 1820x1024, 1024x1820, 1024x2048, 2048x1024, 1434x1024, 1024x1434, 1024x1280, 1280x1024, 1024x1707, 1707x1024 | -| [Google](/providers/ai-sdk-providers/google-generative-ai#image-models) | `imagen-4.0-generate-001` | 1:1, 3:4, 4:3, 9:16, 16:9 | -| [Google](/providers/ai-sdk-providers/google-generative-ai#image-models) | `imagen-4.0-fast-generate-001` | 1:1, 3:4, 4:3, 9:16, 16:9 | -| [Google](/providers/ai-sdk-providers/google-generative-ai#image-models) | `imagen-4.0-ultra-generate-001` | 1:1, 3:4, 4:3, 9:16, 16:9 | -| [Google Vertex](/providers/ai-sdk-providers/google-vertex#image-models) | `imagen-4.0-generate-001` | 1:1, 3:4, 4:3, 9:16, 16:9 | -| [Google Vertex](/providers/ai-sdk-providers/google-vertex#image-models) | `imagen-4.0-fast-generate-001` | 1:1, 3:4, 4:3, 9:16, 16:9 | -| [Google Vertex](/providers/ai-sdk-providers/google-vertex#image-models) | `imagen-4.0-ultra-generate-001` | 1:1, 3:4, 4:3, 9:16, 16:9 | -| [Google Vertex](/providers/ai-sdk-providers/google-vertex#image-models) | `imagen-3.0-fast-generate-001` | 1:1, 3:4, 4:3, 9:16, 16:9 | -| [Fireworks](/providers/ai-sdk-providers/fireworks#image-models) | `accounts/fireworks/models/flux-1-dev-fp8` | 1:1, 2:3, 3:2, 4:5, 5:4, 16:9, 9:16, 9:21, 21:9 | -| [Fireworks](/providers/ai-sdk-providers/fireworks#image-models) | `accounts/fireworks/models/flux-1-schnell-fp8` | 1:1, 2:3, 3:2, 4:5, 5:4, 16:9, 9:16, 9:21, 21:9 | -| [Fireworks](/providers/ai-sdk-providers/fireworks#image-models) | `accounts/fireworks/models/playground-v2-5-1024px-aesthetic` | 640x1536, 768x1344, 832x1216, 896x1152, 1024x1024, 1152x896, 1216x832, 1344x768, 1536x640 | -| [Fireworks](/providers/ai-sdk-providers/fireworks#image-models) | `accounts/fireworks/models/japanese-stable-diffusion-xl` | 640x1536, 768x1344, 832x1216, 896x1152, 1024x1024, 1152x896, 1216x832, 1344x768, 1536x640 | -| [Fireworks](/providers/ai-sdk-providers/fireworks#image-models) | `accounts/fireworks/models/playground-v2-1024px-aesthetic` | 640x1536, 768x1344, 832x1216, 896x1152, 1024x1024, 1152x896, 1216x832, 1344x768, 1536x640 | -| [Fireworks](/providers/ai-sdk-providers/fireworks#image-models) | `accounts/fireworks/models/SSD-1B` | 640x1536, 768x1344, 832x1216, 896x1152, 1024x1024, 1152x896, 1216x832, 1344x768, 1536x640 | -| [Fireworks](/providers/ai-sdk-providers/fireworks#image-models) | `accounts/fireworks/models/stable-diffusion-xl-1024-v1-0` | 640x1536, 768x1344, 832x1216, 896x1152, 1024x1024, 1152x896, 1216x832, 1344x768, 1536x640 | -| [Luma](/providers/ai-sdk-providers/luma#image-models) | `photon-1` | 1:1, 3:4, 4:3, 9:16, 16:9, 9:21, 21:9 | -| [Luma](/providers/ai-sdk-providers/luma#image-models) | `photon-flash-1` | 1:1, 3:4, 4:3, 9:16, 16:9, 9:21, 21:9 | -| [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `stabilityai/stable-diffusion-xl-base-1.0` | 512x512, 768x768, 1024x1024 | -| [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `black-forest-labs/FLUX.1-dev` | 512x512, 768x768, 1024x1024 | -| [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `black-forest-labs/FLUX.1-dev-lora` | 512x512, 768x768, 1024x1024 | -| [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `black-forest-labs/FLUX.1-schnell` | 512x512, 768x768, 1024x1024 | -| [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `black-forest-labs/FLUX.1-canny` | 512x512, 768x768, 1024x1024 | -| [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `black-forest-labs/FLUX.1-depth` | 512x512, 768x768, 1024x1024 | -| [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `black-forest-labs/FLUX.1-redux` | 512x512, 768x768, 1024x1024 | -| [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `black-forest-labs/FLUX.1.1-pro` | 512x512, 768x768, 1024x1024 | -| [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `black-forest-labs/FLUX.1-pro` | 512x512, 768x768, 1024x1024 | -| [Together.ai](/providers/ai-sdk-providers/togetherai#image-models) | `black-forest-labs/FLUX.1-schnell-Free` | 512x512, 768x768, 1024x1024 | -| [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-kontext-pro` | From 3:7 (portrait) to 7:3 (landscape) | -| [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-kontext-max` | From 3:7 (portrait) to 7:3 (landscape) | -| [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-pro-1.1-ultra` | From 3:7 (portrait) to 7:3 (landscape) | -| [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-pro-1.1` | From 3:7 (portrait) to 7:3 (landscape) | -| [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs#image-models) | `flux-pro-1.0-fill` | From 3:7 (portrait) to 7:3 (landscape) | - -Above are a small subset of the image models supported by the AI SDK providers. For more, see the respective provider documentation. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/36-transcription.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/36-transcription.mdx deleted file mode 100644 index cb09365b8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/36-transcription.mdx +++ /dev/null @@ -1,227 +0,0 @@ ---- -title: Transcription -description: Learn how to transcribe audio with the AI SDK. ---- - -# Transcription - -Transcription is an experimental feature. - -The AI SDK provides the [`transcribe`](/docs/reference/ai-sdk-core/transcribe) -function to transcribe audio using a transcription model. - -```ts -import { experimental_transcribe as transcribe } from 'ai'; -import { openai } from '@ai-sdk/openai'; -import { readFile } from 'fs/promises'; - -const transcript = await transcribe({ - model: openai.transcription('whisper-1'), - audio: await readFile('audio.mp3'), -}); -``` - -The `audio` property can be a `Uint8Array`, `ArrayBuffer`, `Buffer`, `string` (base64 encoded audio data), or a `URL`. - -To access the generated transcript: - -```ts -const text = transcript.text; // transcript text e.g. "Hello, world!" -const segments = transcript.segments; // array of segments with start and end times, if available -const language = transcript.language; // language of the transcript e.g. "en", if available -const durationInSeconds = transcript.durationInSeconds; // duration of the transcript in seconds, if available -``` - -## Settings - -### Provider-Specific settings - -Transcription models often have provider or model-specific settings which you can set using the `providerOptions` parameter. - -```ts highlight="8-12" -import { experimental_transcribe as transcribe } from 'ai'; -import { openai } from '@ai-sdk/openai'; -import { readFile } from 'fs/promises'; - -const transcript = await transcribe({ - model: openai.transcription('whisper-1'), - audio: await readFile('audio.mp3'), - providerOptions: { - openai: { - timestampGranularities: ['word'], - }, - }, -}); -``` - -### Download Size Limits - -When `audio` is a URL, the SDK downloads the file with a default **2 GiB** size limit. -You can customize this using `createDownload`: - -```ts highlight="1,8" -import { experimental_transcribe as transcribe, createDownload } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const transcript = await transcribe({ - model: openai.transcription('whisper-1'), - audio: new URL('https://example.com/audio.mp3'), - download: createDownload({ maxBytes: 50 * 1024 * 1024 }), // 50 MB limit -}); -``` - -You can also provide a fully custom download function: - -```ts highlight="6-12" -import { experimental_transcribe as transcribe } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const transcript = await transcribe({ - model: openai.transcription('whisper-1'), - audio: new URL('https://example.com/audio.mp3'), - download: async ({ url }) => { - const res = await myAuthenticatedFetch(url); - return { - data: new Uint8Array(await res.arrayBuffer()), - mediaType: res.headers.get('content-type') ?? undefined, - }; - }, -}); -``` - -If a download exceeds the size limit, a `DownloadError` is thrown: - -```ts -import { experimental_transcribe as transcribe, DownloadError } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -try { - await transcribe({ - model: openai.transcription('whisper-1'), - audio: new URL('https://example.com/audio.mp3'), - }); -} catch (error) { - if (DownloadError.isInstance(error)) { - console.log('Download failed:', error.message); - } -} -``` - -### Abort Signals and Timeouts - -`transcribe` accepts an optional `abortSignal` parameter of -type [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) -that you can use to abort the transcription process or set a timeout. - -This is particularly useful when combined with URL downloads to prevent long-running requests: - -```ts highlight="8" -import { openai } from '@ai-sdk/openai'; -import { experimental_transcribe as transcribe } from 'ai'; - -const transcript = await transcribe({ - model: openai.transcription('whisper-1'), - audio: new URL('https://example.com/audio.mp3'), - abortSignal: AbortSignal.timeout(5000), // Abort after 5 seconds -}); -``` - -### Custom Headers - -`transcribe` accepts an optional `headers` parameter of type `Record` -that you can use to add custom headers to the transcription request. - -```ts highlight="8" -import { openai } from '@ai-sdk/openai'; -import { experimental_transcribe as transcribe } from 'ai'; -import { readFile } from 'fs/promises'; - -const transcript = await transcribe({ - model: openai.transcription('whisper-1'), - audio: await readFile('audio.mp3'), - headers: { 'X-Custom-Header': 'custom-value' }, -}); -``` - -### Warnings - -Warnings (e.g. unsupported parameters) are available on the `warnings` property. - -```ts -import { openai } from '@ai-sdk/openai'; -import { experimental_transcribe as transcribe } from 'ai'; -import { readFile } from 'fs/promises'; - -const transcript = await transcribe({ - model: openai.transcription('whisper-1'), - audio: await readFile('audio.mp3'), -}); - -const warnings = transcript.warnings; -``` - -### Error Handling - -When `transcribe` cannot generate a valid transcript, it throws a [`AI_NoTranscriptGeneratedError`](/docs/reference/ai-sdk-errors/ai-no-transcript-generated-error). - -This error can arise for any of the following reasons: - -- The model failed to generate a response -- The model generated a response that could not be parsed - -The error preserves the following information to help you log the issue: - -- `responses`: Metadata about the transcription model responses, including timestamp, model, and headers. -- `cause`: The cause of the error. You can use this for more detailed error handling. - -```ts -import { - experimental_transcribe as transcribe, - NoTranscriptGeneratedError, -} from 'ai'; -import { openai } from '@ai-sdk/openai'; -import { readFile } from 'fs/promises'; - -try { - await transcribe({ - model: openai.transcription('whisper-1'), - audio: await readFile('audio.mp3'), - }); -} catch (error) { - if (NoTranscriptGeneratedError.isInstance(error)) { - console.log('NoTranscriptGeneratedError'); - console.log('Cause:', error.cause); - console.log('Responses:', error.responses); - } -} -``` - -## Transcription Models - -| Provider | Model | -| ------------------------------------------------------------------------- | ------------------------ | -| [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `whisper-1` | -| [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-transcribe` | -| [OpenAI](/providers/ai-sdk-providers/openai#transcription-models) | `gpt-4o-mini-transcribe` | -| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `scribe_v1` | -| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#transcription-models) | `scribe_v1_experimental` | -| [Groq](/providers/ai-sdk-providers/groq#transcription-models) | `whisper-large-v3-turbo` | -| [Groq](/providers/ai-sdk-providers/groq#transcription-models) | `whisper-large-v3` | -| [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `whisper-1` | -| [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `gpt-4o-transcribe` | -| [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `gpt-4o-mini-transcribe` | -| [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `machine` | -| [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `low_cost` | -| [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `fusion` | -| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `base` (+ variants) | -| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `enhanced` (+ variants) | -| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova` (+ variants) | -| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova-2` (+ variants) | -| [Deepgram](/providers/ai-sdk-providers/deepgram#transcription-models) | `nova-3` (+ variants) | -| [Gladia](/providers/ai-sdk-providers/gladia#transcription-models) | `default` | -| [AssemblyAI](/providers/ai-sdk-providers/assemblyai#transcription-models) | `best` | -| [AssemblyAI](/providers/ai-sdk-providers/assemblyai#transcription-models) | `nano` | -| [Fal](/providers/ai-sdk-providers/fal#transcription-models) | `whisper` | -| [Fal](/providers/ai-sdk-providers/fal#transcription-models) | `wizper` | - -Above are a small subset of the transcription models supported by the AI SDK providers. For more, see the respective provider documentation. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/37-speech.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/37-speech.mdx deleted file mode 100644 index 94aa47aad..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/37-speech.mdx +++ /dev/null @@ -1,169 +0,0 @@ ---- -title: Speech -description: Learn how to generate speech from text with the AI SDK. ---- - -# Speech - -Speech is an experimental feature. - -The AI SDK provides the [`generateSpeech`](/docs/reference/ai-sdk-core/generate-speech) -function to generate speech from text using a speech model. - -```ts -import { experimental_generateSpeech as generateSpeech } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const audio = await generateSpeech({ - model: openai.speech('tts-1'), - text: 'Hello, world!', - voice: 'alloy', -}); -``` - -### Language Setting - -You can specify the language for speech generation (provider support varies): - -```ts -import { experimental_generateSpeech as generateSpeech } from 'ai'; -import { lmnt } from '@ai-sdk/lmnt'; - -const audio = await generateSpeech({ - model: lmnt.speech('aurora'), - text: 'Hola, mundo!', - language: 'es', // Spanish -}); -``` - -To access the generated audio: - -```ts -const audioData = result.audio.uint8Array; // audio data as Uint8Array -// or -const audioBase64 = result.audio.base64; // audio data as base64 string -``` - -## Settings - -### Provider-Specific settings - -You can set model-specific settings with the `providerOptions` parameter. - -```ts highlight="7-11" -import { experimental_generateSpeech as generateSpeech } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const audio = await generateSpeech({ - model: openai.speech('tts-1'), - text: 'Hello, world!', - providerOptions: { - openai: { - // ... - }, - }, -}); -``` - -### Abort Signals and Timeouts - -`generateSpeech` accepts an optional `abortSignal` parameter of -type [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) -that you can use to abort the speech generation process or set a timeout. - -```ts highlight="7" -import { openai } from '@ai-sdk/openai'; -import { experimental_generateSpeech as generateSpeech } from 'ai'; - -const audio = await generateSpeech({ - model: openai.speech('tts-1'), - text: 'Hello, world!', - abortSignal: AbortSignal.timeout(1000), // Abort after 1 second -}); -``` - -### Custom Headers - -`generateSpeech` accepts an optional `headers` parameter of type `Record` -that you can use to add custom headers to the speech generation request. - -```ts highlight="7" -import { openai } from '@ai-sdk/openai'; -import { experimental_generateSpeech as generateSpeech } from 'ai'; - -const audio = await generateSpeech({ - model: openai.speech('tts-1'), - text: 'Hello, world!', - headers: { 'X-Custom-Header': 'custom-value' }, -}); -``` - -### Warnings - -Warnings (e.g. unsupported parameters) are available on the `warnings` property. - -```ts -import { openai } from '@ai-sdk/openai'; -import { experimental_generateSpeech as generateSpeech } from 'ai'; - -const audio = await generateSpeech({ - model: openai.speech('tts-1'), - text: 'Hello, world!', -}); - -const warnings = audio.warnings; -``` - -### Error Handling - -When `generateSpeech` cannot generate a valid audio, it throws a [`AI_NoSpeechGeneratedError`](/docs/reference/ai-sdk-errors/ai-no-speech-generated-error). - -This error can arise for any of the following reasons: - -- The model failed to generate a response -- The model generated a response that could not be parsed - -The error preserves the following information to help you log the issue: - -- `responses`: Metadata about the speech model responses, including timestamp, model, and headers. -- `cause`: The cause of the error. You can use this for more detailed error handling. - -```ts -import { - experimental_generateSpeech as generateSpeech, - NoSpeechGeneratedError, -} from 'ai'; -import { openai } from '@ai-sdk/openai'; - -try { - await generateSpeech({ - model: openai.speech('tts-1'), - text: 'Hello, world!', - }); -} catch (error) { - if (NoSpeechGeneratedError.isInstance(error)) { - console.log('AI_NoSpeechGeneratedError'); - console.log('Cause:', error.cause); - console.log('Responses:', error.responses); - } -} -``` - -## Speech Models - -| Provider | Model | -| ------------------------------------------------------------------ | ------------------------ | -| [OpenAI](/providers/ai-sdk-providers/openai#speech-models) | `tts-1` | -| [OpenAI](/providers/ai-sdk-providers/openai#speech-models) | `tts-1-hd` | -| [OpenAI](/providers/ai-sdk-providers/openai#speech-models) | `gpt-4o-mini-tts` | -| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#speech-models) | `eleven_v3` | -| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#speech-models) | `eleven_multilingual_v2` | -| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#speech-models) | `eleven_flash_v2_5` | -| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#speech-models) | `eleven_flash_v2` | -| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#speech-models) | `eleven_turbo_v2_5` | -| [ElevenLabs](/providers/ai-sdk-providers/elevenlabs#speech-models) | `eleven_turbo_v2` | -| [LMNT](/providers/ai-sdk-providers/lmnt#speech-models) | `aurora` | -| [LMNT](/providers/ai-sdk-providers/lmnt#speech-models) | `blizzard` | -| [Hume](/providers/ai-sdk-providers/hume#speech-models) | `default` | - -Above are a small subset of the speech models supported by the AI SDK providers. For more, see the respective provider documentation. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/38-video-generation.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/38-video-generation.mdx deleted file mode 100644 index 18abd7137..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/38-video-generation.mdx +++ /dev/null @@ -1,366 +0,0 @@ ---- -title: Video Generation -description: Learn how to generate videos with the AI SDK. ---- - -# Video Generation - - - Video generation is an experimental feature. The API may change in future - versions. - - -The AI SDK provides the [`experimental_generateVideo`](/docs/reference/ai-sdk-core/generate-video) -function to generate videos based on a given prompt using a video model. - -```tsx -import { experimental_generateVideo as generateVideo } from 'ai'; -import { fal } from '@ai-sdk/fal'; - -const { video } = await generateVideo({ - model: fal.video('luma-dream-machine/ray-2'), - prompt: 'A cat walking on a treadmill', -}); -``` - -You can access the video data using the `base64` or `uint8Array` properties: - -```tsx -const base64 = video.base64; // base64 video data -const uint8Array = video.uint8Array; // Uint8Array video data -``` - -## Settings - -### Aspect Ratio - -The aspect ratio is specified as a string in the format `{width}:{height}`. -Models only support a few aspect ratios, and the supported aspect ratios are different for each model and provider. - -```tsx highlight={"7"} -import { experimental_generateVideo as generateVideo } from 'ai'; -import { fal } from '@ai-sdk/fal'; - -const { video } = await generateVideo({ - model: fal.video('luma-dream-machine/ray-2'), - prompt: 'A cat walking on a treadmill', - aspectRatio: '16:9', -}); -``` - -### Resolution - -The resolution is specified as a string in the format `{width}x{height}`. -Models only support specific resolutions, and the supported resolutions are different for each model and provider. - -```tsx highlight={"7"} -import { experimental_generateVideo as generateVideo } from 'ai'; -import { google } from '@ai-sdk/google'; - -const { video } = await generateVideo({ - model: google.video('veo-2.0-generate-001'), - prompt: 'A serene mountain landscape at sunset', - resolution: '1280x720', -}); -``` - -### Duration - -Some video models support specifying the duration of the generated video in seconds. - -```tsx highlight={"7"} -import { experimental_generateVideo as generateVideo } from 'ai'; -import { fal } from '@ai-sdk/fal'; - -const { video } = await generateVideo({ - model: fal.video('luma-dream-machine/ray-2'), - prompt: 'A timelapse of clouds moving across the sky', - duration: 5, -}); -``` - -### Frames Per Second (FPS) - -Some video models allow you to specify the frames per second for the generated video. - -```tsx highlight={"7"} -import { experimental_generateVideo as generateVideo } from 'ai'; -import { fal } from '@ai-sdk/fal'; - -const { video } = await generateVideo({ - model: fal.video('luma-dream-machine/ray-2'), - prompt: 'A hummingbird in slow motion', - fps: 24, -}); -``` - -### Generating Multiple Videos - -`experimental_generateVideo` supports generating multiple videos at once: - -```tsx highlight={"7"} -import { experimental_generateVideo as generateVideo } from 'ai'; -import { google } from '@ai-sdk/google'; - -const { videos } = await generateVideo({ - model: google.video('veo-2.0-generate-001'), - prompt: 'A rocket launching into space', - n: 3, // number of videos to generate -}); -``` - - - `experimental_generateVideo` will automatically call the model as often as - needed (in parallel) to generate the requested number of videos. - - -Each video model has an internal limit on how many videos it can generate in a single API call. The AI SDK manages this automatically by batching requests appropriately when you request multiple videos using the `n` parameter. Most video models only support generating 1 video per call due to computational cost. - -If needed, you can override this behavior using the `maxVideosPerCall` setting: - -```tsx -const { videos } = await generateVideo({ - model: google.video('veo-2.0-generate-001'), - prompt: 'A rocket launching into space', - maxVideosPerCall: 2, // Override the default batch size - n: 4, // Will make 2 calls of 2 videos each -}); -``` - -### Image-to-Video Generation - -Some video models support generating videos from an input image. You can provide an image using the prompt object: - -```tsx highlight={"7-10"} -import { experimental_generateVideo as generateVideo } from 'ai'; -import { fal } from '@ai-sdk/fal'; - -const { video } = await generateVideo({ - model: fal.video('hunyuan-video'), - prompt: { - image: 'https://example.com/my-image.png', - text: 'Animate this image with gentle motion', - }, -}); -``` - -You can also provide the image as a base64-encoded string or `Uint8Array`: - -```tsx -const { video } = await generateVideo({ - model: fal.video('hunyuan-video'), - prompt: { - image: imageBase64String, // or imageUint8Array - text: 'Animate this image', - }, -}); -``` - -### Providing a Seed - -You can provide a seed to the `experimental_generateVideo` function to control the output of the video generation process. -If supported by the model, the same seed will always produce the same video. - -```tsx highlight={"7"} -import { experimental_generateVideo as generateVideo } from 'ai'; -import { fal } from '@ai-sdk/fal'; - -const { video } = await generateVideo({ - model: fal.video('luma-dream-machine/ray-2'), - prompt: 'A cat walking on a treadmill', - seed: 1234567890, -}); -``` - -### Provider-specific Settings - -Video models often have provider- or even model-specific settings. -You can pass such settings to the `experimental_generateVideo` function -using the `providerOptions` parameter. The options for the provider -become request body properties. - -```tsx highlight={"8-10"} -import { experimental_generateVideo as generateVideo } from 'ai'; -import { fal } from '@ai-sdk/fal'; - -const { video } = await generateVideo({ - model: fal.video('luma-dream-machine/ray-2'), - prompt: 'A cat walking on a treadmill', - aspectRatio: '16:9', - providerOptions: { - fal: { loop: true, motionStrength: 0.8 }, - }, -}); -``` - -### Abort Signals and Timeouts - -`experimental_generateVideo` accepts an optional `abortSignal` parameter of -type [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) -that you can use to abort the video generation process or set a timeout. - -```ts highlight={"7"} -import { fal } from '@ai-sdk/fal'; -import { experimental_generateVideo as generateVideo } from 'ai'; - -const { video } = await generateVideo({ - model: fal.video('luma-dream-machine/ray-2'), - prompt: 'A cat walking on a treadmill', - abortSignal: AbortSignal.timeout(60000), // Abort after 60 seconds -}); -``` - - - Video generation typically takes longer than image generation. Consider using - longer timeouts (60 seconds or more) depending on the model and video length. - - -### Polling Timeout - -Video generation is an asynchronous process that can take several minutes to complete. Most providers use a polling mechanism where the SDK periodically checks if the video is ready. The default polling timeout is typically 5 minutes, which may not be sufficient for longer videos or certain models. - -You can configure the polling timeout using provider-specific options. Each provider exports a type for its options that you can use with `satisfies` for type safety: - -```tsx highlight={"10-12"} -import { experimental_generateVideo as generateVideo } from 'ai'; -import { fal, type FalVideoModelOptions } from '@ai-sdk/fal'; - -const { video } = await generateVideo({ - model: fal.video('luma-dream-machine/ray-2'), - prompt: 'A cinematic timelapse of a city from dawn to dusk', - duration: 10, - providerOptions: { - fal: { - pollTimeoutMs: 600000, // 10 minutes - } satisfies FalVideoModelOptions, - }, -}); -``` - - - For production use, we recommend setting `pollTimeoutMs` to at least 10 - minutes (600000ms) to account for varying generation times across different - models and video lengths. - - -### Custom Headers - -`experimental_generateVideo` accepts an optional `headers` parameter of type `Record` -that you can use to add custom headers to the video generation request. - -```ts highlight={"7"} -import { fal } from '@ai-sdk/fal'; -import { experimental_generateVideo as generateVideo } from 'ai'; - -const { video } = await generateVideo({ - model: fal.video('luma-dream-machine/ray-2'), - prompt: 'A cat walking on a treadmill', - headers: { 'X-Custom-Header': 'custom-value' }, -}); -``` - -### Warnings - -If the model returns warnings, e.g. for unsupported parameters, they will be available in the `warnings` property of the response. - -```tsx -const { video, warnings } = await generateVideo({ - model: fal.video('luma-dream-machine/ray-2'), - prompt: 'A cat walking on a treadmill', -}); -``` - -### Additional Provider-specific Metadata - -Some providers expose additional metadata for the result overall or per video. - -```tsx -const prompt = 'A cat walking on a treadmill'; - -const { video, providerMetadata } = await generateVideo({ - model: fal.video('luma-dream-machine/ray-2'), - prompt, -}); - -// Access provider-specific metadata -const videoMetadata = providerMetadata.fal?.videos[0]; -console.log({ - duration: videoMetadata?.duration, - fps: videoMetadata?.fps, - width: videoMetadata?.width, - height: videoMetadata?.height, -}); -``` - -The outer key of the returned `providerMetadata` is the provider name. The inner values are the metadata. A `videos` key is typically present in the metadata and is an array with the same length as the top level `videos` key. - -When generating multiple videos with `n > 1`, you can also access per-call metadata through the `responses` array: - -```tsx -const { videos, responses } = await generateVideo({ - model: google.video('veo-2.0-generate-001'), - prompt: 'A rocket launching into space', - n: 5, // May require multiple API calls -}); - -// Access metadata from each individual API call -for (const response of responses) { - console.log({ - timestamp: response.timestamp, - modelId: response.modelId, - // Per-call provider metadata (lossless) - providerMetadata: response.providerMetadata, - }); -} -``` - -### Error Handling - -When `experimental_generateVideo` cannot generate a valid video, it throws a [`AI_NoVideoGeneratedError`](/docs/reference/ai-sdk-errors/ai-no-video-generated-error). - -This error occurs when the AI provider fails to generate a video. It can arise due to the following reasons: - -- The model failed to generate a response -- The model generated a response that could not be parsed - -The error preserves the following information to help you log the issue: - -- `responses`: Metadata about the video model responses, including timestamp, model, and headers. -- `cause`: The cause of the error. You can use this for more detailed error handling - -```ts -import { - experimental_generateVideo as generateVideo, - NoVideoGeneratedError, -} from 'ai'; - -try { - await generateVideo({ model, prompt }); -} catch (error) { - if (NoVideoGeneratedError.isInstance(error)) { - console.log('NoVideoGeneratedError'); - console.log('Cause:', error.cause); - console.log('Responses:', error.responses); - } -} -``` - -## Video Models - -| Provider | Model | Features | -| ----------------------------------------------------------------------- | --------------------------- | -------------------------------------- | -| [FAL](/providers/ai-sdk-providers/fal#video-models) | `luma-dream-machine/ray-2` | Text-to-video, image-to-video | -| [FAL](/providers/ai-sdk-providers/fal#video-models) | `minimax-video` | Text-to-video | -| [Google](/providers/ai-sdk-providers/google-generative-ai#video-models) | `veo-2.0-generate-001` | Text-to-video, up to 4 videos per call | -| [Google Vertex](/providers/ai-sdk-providers/google-vertex#video-models) | `veo-3.1-generate-001` | Text-to-video, audio generation | -| [Google Vertex](/providers/ai-sdk-providers/google-vertex#video-models) | `veo-3.1-fast-generate-001` | Text-to-video, audio generation | -| [Google Vertex](/providers/ai-sdk-providers/google-vertex#video-models) | `veo-3.0-generate-001` | Text-to-video, audio generation | -| [Google Vertex](/providers/ai-sdk-providers/google-vertex#video-models) | `veo-3.0-fast-generate-001` | Text-to-video, audio generation | -| [Google Vertex](/providers/ai-sdk-providers/google-vertex#video-models) | `veo-2.0-generate-001` | Text-to-video, up to 4 videos per call | -| [Kling AI](/providers/ai-sdk-providers/klingai#video-models) | `kling-v2.6-t2v` | Text-to-video | -| [Kling AI](/providers/ai-sdk-providers/klingai#video-models) | `kling-v2.6-i2v` | Image-to-video | -| [Kling AI](/providers/ai-sdk-providers/klingai#video-models) | `kling-v2.6-motion-control` | Motion control | -| [Replicate](/providers/ai-sdk-providers/replicate#video-models) | `minimax/video-01` | Text-to-video | -| [xAI](/providers/ai-sdk-providers/xai#video-models) | `grok-imagine-video` | Text-to-video, image-to-video, editing | - -Above are a small subset of the video models supported by the AI SDK providers. For more, see the respective provider documentation. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/40-middleware.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/40-middleware.mdx deleted file mode 100644 index 0f6c1346e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/40-middleware.mdx +++ /dev/null @@ -1,485 +0,0 @@ ---- -title: Language Model Middleware -description: Learn how to use middleware to enhance the behavior of language models ---- - -# Language Model Middleware - -Language model middleware is a way to enhance the behavior of language models -by intercepting and modifying the calls to the language model. - -It can be used to add features like guardrails, RAG, caching, and logging -in a language model agnostic way. Such middleware can be developed and -distributed independently from the language models that they are applied to. - -## Using Language Model Middleware - -You can use language model middleware with the `wrapLanguageModel` function. -It takes a language model and a language model middleware and returns a new -language model that incorporates the middleware. - -```ts -import { wrapLanguageModel, streamText } from 'ai'; - -const wrappedLanguageModel = wrapLanguageModel({ - model: yourModel, - middleware: yourLanguageModelMiddleware, -}); -``` - -The wrapped language model can be used just like any other language model, e.g. in `streamText`: - -```ts highlight="2" -const result = streamText({ - model: wrappedLanguageModel, - prompt: 'What cities are in the United States?', -}); -``` - -## Multiple middlewares - -You can provide multiple middlewares to the `wrapLanguageModel` function. -The middlewares will be applied in the order they are provided. - -```ts -const wrappedLanguageModel = wrapLanguageModel({ - model: yourModel, - middleware: [firstMiddleware, secondMiddleware], -}); - -// applied as: firstMiddleware(secondMiddleware(yourModel)) -``` - -## Built-in Middleware - -The AI SDK comes with several built-in middlewares that you can use to configure language models: - -- `extractReasoningMiddleware`: Extracts reasoning information from the generated text and exposes it as a `reasoning` property on the result. -- `extractJsonMiddleware`: Extracts JSON from text content by stripping markdown code fences. Useful when using `Output.object()` with models that wrap JSON responses in code blocks. -- `simulateStreamingMiddleware`: Simulates streaming behavior with responses from non-streaming language models. -- `defaultSettingsMiddleware`: Applies default settings to a language model. -- `addToolInputExamplesMiddleware`: Adds tool input examples to tool descriptions for providers that don't natively support the `inputExamples` property. - -### Extract Reasoning - -Some providers and models expose reasoning information in the generated text using special tags, -e.g. <think> and </think>. - -The `extractReasoningMiddleware` function can be used to extract this reasoning information and expose it as a `reasoning` property on the result. - -```ts -import { wrapLanguageModel, extractReasoningMiddleware } from 'ai'; - -const model = wrapLanguageModel({ - model: yourModel, - middleware: extractReasoningMiddleware({ tagName: 'think' }), -}); -``` - -You can then use that enhanced model in functions like `generateText` and `streamText`. - -The `extractReasoningMiddleware` function also includes a `startWithReasoning` option. -When set to `true`, the reasoning tag will be prepended to the generated text. -This is useful for models that do not include the reasoning tag at the beginning of the response. -For more details, see the [DeepSeek R1 guide](/cookbook/guides/r1#deepseek-r1-middleware). - -### Extract JSON - -Some models wrap JSON responses in markdown code fences (e.g., ` ```json ... ``` `) even when you request structured output. - -The `extractJsonMiddleware` function strips these code fences from the response, making it compatible with `Output.object()`. - -```ts -import { - wrapLanguageModel, - extractJsonMiddleware, - Output, - generateText, -} from 'ai'; -import { z } from 'zod'; - -const model = wrapLanguageModel({ - model: yourModel, - middleware: extractJsonMiddleware(), -}); - -const result = await generateText({ - model, - output: Output.object({ - schema: z.object({ - name: z.string(), - ingredients: z.array(z.string()), - }), - }), - prompt: 'Generate a recipe.', -}); -``` - -You can also provide a custom transform function for models that use different formatting: - -```ts -const model = wrapLanguageModel({ - model: yourModel, - middleware: extractJsonMiddleware({ - transform: text => text.replace(/^PREFIX/, '').replace(/SUFFIX$/, ''), - }), -}); -``` - -### Simulate Streaming - -The `simulateStreamingMiddleware` function can be used to simulate streaming behavior with responses from non-streaming language models. -This is useful when you want to maintain a consistent streaming interface even when using models that only provide complete responses. - -```ts -import { wrapLanguageModel, simulateStreamingMiddleware } from 'ai'; - -const model = wrapLanguageModel({ - model: yourModel, - middleware: simulateStreamingMiddleware(), -}); -``` - -### Default Settings - -The `defaultSettingsMiddleware` function can be used to apply default settings to a language model. - -```ts -import { wrapLanguageModel, defaultSettingsMiddleware } from 'ai'; - -const model = wrapLanguageModel({ - model: yourModel, - middleware: defaultSettingsMiddleware({ - settings: { - temperature: 0.5, - maxOutputTokens: 800, - providerOptions: { openai: { store: false } }, - }, - }), -}); -``` - -### Add Tool Input Examples - -The `addToolInputExamplesMiddleware` function adds tool input examples to tool descriptions. -This is useful for providers that don't natively support the `inputExamples` property on tools. -The middleware serializes the examples into the tool's description text so models can still benefit from seeing example inputs. - -```ts -import { wrapLanguageModel, addToolInputExamplesMiddleware } from 'ai'; - -const model = wrapLanguageModel({ - model: yourModel, - middleware: addToolInputExamplesMiddleware({ - prefix: 'Input Examples:', - }), -}); -``` - -When you define a tool with `inputExamples`, the middleware will append them to the tool's description: - -```ts -import { generateText, tool } from 'ai'; -import { z } from 'zod'; - -const result = await generateText({ - model, // wrapped model from above - tools: { - weather: tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ - location: z.string(), - }), - inputExamples: [ - { input: { location: 'San Francisco' } }, - { input: { location: 'London' } }, - ], - }), - }, - prompt: 'What is the weather in Tokyo?', -}); -``` - -The tool description will be transformed to: - -``` -Get the weather in a location - -Input Examples: -{"location":"San Francisco"} -{"location":"London"} -``` - -#### Options - -- `prefix` (optional): A prefix text to prepend before the examples. Default: `'Input Examples:'`. -- `format` (optional): A custom formatter function for each example. Receives the example object and its index. Default: `JSON.stringify(example.input)`. -- `remove` (optional): Whether to remove the `inputExamples` property from the tool after adding them to the description. Default: `true`. - -```ts -const model = wrapLanguageModel({ - model: yourModel, - middleware: addToolInputExamplesMiddleware({ - prefix: 'Input Examples:', - format: (example, index) => - `${index + 1}. ${JSON.stringify(example.input)}`, - remove: true, - }), -}); -``` - -## Community Middleware - -The AI SDK provides a Language Model Middleware specification. Community members can develop middleware that adheres to this specification, making it compatible with the AI SDK ecosystem. - -Here are some community middlewares that you can explore: - -### Custom tool call parser - -The [Custom tool call parser](https://github.com/minpeter/ai-sdk-tool-call-middleware) middleware extends tool call capabilities to models that don't natively support the OpenAI-style `tools` parameter. This includes many self-hosted and third-party models that lack native function calling features. - - - Using this middleware on models that support native function calls may result - in unintended performance degradation, so check whether your model supports - native function calls before deciding to use it. - - -This middleware enables function calling capabilities by converting function schemas into prompt instructions and parsing the model's responses into structured function calls. It works by transforming the JSON function definitions into natural language instructions the model can understand, then analyzing the generated text to extract function call attempts. This approach allows developers to use the same function calling API across different model providers, even with models that don't natively support the OpenAI-style function calling format, providing a consistent function calling experience regardless of the underlying model implementation. - -The `@ai-sdk-tool/parser` package offers three middleware variants: - -- `createToolMiddleware`: A flexible function for creating custom tool call middleware tailored to specific models -- `hermesToolMiddleware`: Ready-to-use middleware for Hermes & Qwen format function calls -- `gemmaToolMiddleware`: Pre-configured middleware for Gemma 3 model series function call format - -Here's how you can enable function calls with Gemma models that don't support them natively: - -```ts -import { wrapLanguageModel } from 'ai'; -import { gemmaToolMiddleware } from '@ai-sdk-tool/parser'; - -const model = wrapLanguageModel({ - model: openrouter('google/gemma-3-27b-it'), - middleware: gemmaToolMiddleware, -}); -``` - -Find more examples at this [link](https://github.com/minpeter/ai-sdk-tool-call-middleware/tree/main/examples/core/src). - -## Implementing Language Model Middleware - - - Implementing language model middleware is advanced functionality and requires - a solid understanding of the [language model - specification](https://github.com/vercel/ai/blob/v5/packages/provider/src/language-model/v2/language-model-v2.ts). - - -You can implement any of the following three function to modify the behavior of the language model: - -1. `transformParams`: Transforms the parameters before they are passed to the language model, for both `doGenerate` and `doStream`. -2. `wrapGenerate`: Wraps the `doGenerate` method of the [language model](https://github.com/vercel/ai/blob/v5/packages/provider/src/language-model/v2/language-model-v2.ts). - You can modify the parameters, call the language model, and modify the result. -3. `wrapStream`: Wraps the `doStream` method of the [language model](https://github.com/vercel/ai/blob/v5/packages/provider/src/language-model/v2/language-model-v2.ts). - You can modify the parameters, call the language model, and modify the result. - -Here are some examples of how to implement language model middleware: - -## Examples - - - These examples are not meant to be used in production. They are just to show - how you can use middleware to enhance the behavior of language models. - - -### Logging - -This example shows how to log the parameters and generated text of a language model call. - -```ts -import type { - LanguageModelV3Middleware, - LanguageModelV3StreamPart, -} from '@ai-sdk/provider'; - -export const yourLogMiddleware: LanguageModelV3Middleware = { - wrapGenerate: async ({ doGenerate, params }) => { - console.log('doGenerate called'); - console.log(`params: ${JSON.stringify(params, null, 2)}`); - - const result = await doGenerate(); - - console.log('doGenerate finished'); - console.log(`generated text: ${result.text}`); - - return result; - }, - - wrapStream: async ({ doStream, params }) => { - console.log('doStream called'); - console.log(`params: ${JSON.stringify(params, null, 2)}`); - - const { stream, ...rest } = await doStream(); - - let generatedText = ''; - const textBlocks = new Map(); - - const transformStream = new TransformStream< - LanguageModelV3StreamPart, - LanguageModelV3StreamPart - >({ - transform(chunk, controller) { - switch (chunk.type) { - case 'text-start': { - textBlocks.set(chunk.id, ''); - break; - } - case 'text-delta': { - const existing = textBlocks.get(chunk.id) || ''; - textBlocks.set(chunk.id, existing + chunk.delta); - generatedText += chunk.delta; - break; - } - case 'text-end': { - console.log( - `Text block ${chunk.id} completed:`, - textBlocks.get(chunk.id), - ); - break; - } - } - - controller.enqueue(chunk); - }, - - flush() { - console.log('doStream finished'); - console.log(`generated text: ${generatedText}`); - }, - }); - - return { - stream: stream.pipeThrough(transformStream), - ...rest, - }; - }, -}; -``` - -### Caching - -This example shows how to build a simple cache for the generated text of a language model call. - -```ts -import type { LanguageModelV3Middleware } from '@ai-sdk/provider'; - -const cache = new Map(); - -export const yourCacheMiddleware: LanguageModelV3Middleware = { - wrapGenerate: async ({ doGenerate, params }) => { - const cacheKey = JSON.stringify(params); - - if (cache.has(cacheKey)) { - return cache.get(cacheKey); - } - - const result = await doGenerate(); - - cache.set(cacheKey, result); - - return result; - }, - - // here you would implement the caching logic for streaming -}; -``` - -### Retrieval Augmented Generation (RAG) - -This example shows how to use RAG as middleware. - - - Helper functions like `getLastUserMessageText` and `findSources` are not part - of the AI SDK. They are just used in this example to illustrate the concept of - RAG. - - -```ts -import type { LanguageModelV3Middleware } from '@ai-sdk/provider'; - -export const yourRagMiddleware: LanguageModelV3Middleware = { - transformParams: async ({ params }) => { - const lastUserMessageText = getLastUserMessageText({ - prompt: params.prompt, - }); - - if (lastUserMessageText == null) { - return params; // do not use RAG (send unmodified parameters) - } - - const instruction = - 'Use the following information to answer the question:\n' + - findSources({ text: lastUserMessageText }) - .map(chunk => JSON.stringify(chunk)) - .join('\n'); - - return addToLastUserMessage({ params, text: instruction }); - }, -}; -``` - -### Guardrails - -Guard rails are a way to ensure that the generated text of a language model call -is safe and appropriate. This example shows how to use guardrails as middleware. - -```ts -import type { LanguageModelV3Middleware } from '@ai-sdk/provider'; - -export const yourGuardrailMiddleware: LanguageModelV3Middleware = { - wrapGenerate: async ({ doGenerate }) => { - const { text, ...rest } = await doGenerate(); - - // filtering approach, e.g. for PII or other sensitive information: - const cleanedText = text?.replace(/badword/g, ''); - - return { text: cleanedText, ...rest }; - }, - - // here you would implement the guardrail logic for streaming - // Note: streaming guardrails are difficult to implement, because - // you do not know the full content of the stream until it's finished. -}; -``` - -## Configuring Per Request Custom Metadata - -To send and access custom metadata in Middleware, you can use `providerOptions`. This is useful when building logging middleware where you want to pass additional context like user IDs, timestamps, or other contextual data that can help with tracking and debugging. - -```ts -import { generateText, wrapLanguageModel } from 'ai'; -__PROVIDER_IMPORT__; -import type { LanguageModelV3Middleware } from '@ai-sdk/provider'; - -export const yourLogMiddleware: LanguageModelV3Middleware = { - wrapGenerate: async ({ doGenerate, params }) => { - console.log('METADATA', params?.providerMetadata?.yourLogMiddleware); - const result = await doGenerate(); - return result; - }, -}; - -const { text } = await generateText({ - model: wrapLanguageModel({ - model: __MODEL__, - middleware: yourLogMiddleware, - }), - prompt: 'Invent a new holiday and describe its traditions.', - providerOptions: { - yourLogMiddleware: { - hello: 'world', - }, - }, -}); - -console.log(text); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/45-provider-management.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/45-provider-management.mdx deleted file mode 100644 index cea3b0339..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/45-provider-management.mdx +++ /dev/null @@ -1,349 +0,0 @@ ---- -title: Provider & Model Management -description: Learn how to work with multiple providers and models ---- - -# Provider & Model Management - -When you work with multiple providers and models, it is often desirable to manage them in a central place -and access the models through simple string ids. - -The AI SDK offers [custom providers](/docs/reference/ai-sdk-core/custom-provider) and -a [provider registry](/docs/reference/ai-sdk-core/provider-registry) for this purpose: - -- With **custom providers**, you can pre-configure model settings, provide model name aliases, - and limit the available models. -- The **provider registry** lets you mix multiple providers and access them through simple string ids. - -You can mix and match custom providers, the provider registry, and [middleware](/docs/ai-sdk-core/middleware) in your application. - -## Custom Providers - -You can create a [custom provider](/docs/reference/ai-sdk-core/custom-provider) using `customProvider`. - -### Example: custom model settings - -You might want to override the default model settings for a provider or provide model name aliases -with pre-configured settings. - -```ts -import { - gateway, - customProvider, - defaultSettingsMiddleware, - wrapLanguageModel, -} from 'ai'; - -// custom provider with different provider options: -export const openai = customProvider({ - languageModels: { - // replacement model with custom provider options: - 'gpt-5.1': wrapLanguageModel({ - model: gateway('openai/gpt-5.1'), - middleware: defaultSettingsMiddleware({ - settings: { - providerOptions: { - openai: { - reasoningEffort: 'high', - }, - }, - }, - }), - }), - // alias model with custom provider options: - 'gpt-5.1-high-reasoning': wrapLanguageModel({ - model: gateway('openai/gpt-5.1'), - middleware: defaultSettingsMiddleware({ - settings: { - providerOptions: { - openai: { - reasoningEffort: 'high', - }, - }, - }, - }), - }), - }, - fallbackProvider: gateway, -}); -``` - -### Example: model name alias - -You can also provide model name aliases, so you can update the model version in one place in the future: - -```ts -import { customProvider, gateway } from 'ai'; - -// custom provider with alias names: -export const anthropic = customProvider({ - languageModels: { - opus: gateway('anthropic/claude-opus-4.1'), - sonnet: gateway('anthropic/claude-sonnet-4.5'), - haiku: gateway('anthropic/claude-haiku-4.5'), - }, - fallbackProvider: gateway, -}); -``` - -### Example: limit available models - -You can limit the available models in the system, even if you have multiple providers. - -```ts -import { - customProvider, - defaultSettingsMiddleware, - wrapLanguageModel, - gateway, -} from 'ai'; - -export const myProvider = customProvider({ - languageModels: { - 'text-medium': gateway('anthropic/claude-3-5-sonnet-20240620'), - 'text-small': gateway('openai/gpt-5-mini'), - 'reasoning-medium': wrapLanguageModel({ - model: gateway('openai/gpt-5.1'), - middleware: defaultSettingsMiddleware({ - settings: { - providerOptions: { - openai: { - reasoningEffort: 'high', - }, - }, - }, - }), - }), - 'reasoning-fast': wrapLanguageModel({ - model: gateway('openai/gpt-5.1'), - middleware: defaultSettingsMiddleware({ - settings: { - providerOptions: { - openai: { - reasoningEffort: 'low', - }, - }, - }, - }), - }), - }, - embeddingModels: { - embedding: gateway.embeddingModel('openai/text-embedding-3-small'), - }, - // no fallback provider -}); -``` - -## Provider Registry - -You can create a [provider registry](/docs/reference/ai-sdk-core/provider-registry) with multiple providers and models using `createProviderRegistry`. - -### Setup - -```ts filename={"registry.ts"} -import { anthropic } from '@ai-sdk/anthropic'; -import { openai } from '@ai-sdk/openai'; -import { createProviderRegistry, gateway } from 'ai'; - -export const registry = createProviderRegistry({ - // register provider with prefix and default setup using gateway: - gateway, - - // register provider with prefix and direct provider import: - anthropic, - openai, -}); -``` - -### Setup with Custom Separator - -By default, the registry uses `:` as the separator between provider and model IDs. You can customize this separator: - -```ts filename={"registry.ts"} -import { anthropic } from '@ai-sdk/anthropic'; -import { openai } from '@ai-sdk/openai'; -import { createProviderRegistry, gateway } from 'ai'; - -export const customSeparatorRegistry = createProviderRegistry( - { - gateway, - anthropic, - openai, - }, - { separator: ' > ' }, -); -``` - -### Example: Use language models - -You can access language models by using the `languageModel` method on the registry. -The provider id will become the prefix of the model id: `providerId:modelId`. - -```ts highlight={"5"} -import { generateText } from 'ai'; -import { registry } from './registry'; - -const { text } = await generateText({ - model: registry.languageModel('openai:gpt-5.1'), // default separator - // or with custom separator: - // model: customSeparatorRegistry.languageModel('openai > gpt-5.1'), - prompt: 'Invent a new holiday and describe its traditions.', -}); -``` - -### Example: Use text embedding models - -You can access text embedding models by using the `.embeddingModel` method on the registry. -The provider id will become the prefix of the model id: `providerId:modelId`. - -```ts highlight={"5"} -import { embed } from 'ai'; -import { registry } from './registry'; - -const { embedding } = await embed({ - model: registry.embeddingModel('openai:text-embedding-3-small'), - value: 'sunny day at the beach', -}); -``` - -### Example: Use image models - -You can access image models by using the `imageModel` method on the registry. -The provider id will become the prefix of the model id: `providerId:modelId`. - -```ts highlight={"5"} -import { generateImage } from 'ai'; -import { registry } from './registry'; - -const { image } = await generateImage({ - model: registry.imageModel('openai:dall-e-3'), - prompt: 'A beautiful sunset over a calm ocean', -}); -``` - -## Combining Custom Providers, Provider Registry, and Middleware - -The central idea of provider management is to set up a file that contains all the providers and models you want to use. -You may want to pre-configure model settings, provide model name aliases, limit the available models, and more. - -Here is an example that implements the following concepts: - -- pass through gateway with a namespace prefix (here: `gateway > *`) -- pass through a full provider with a namespace prefix (here: `xai > *`) -- setup an OpenAI-compatible provider with custom api key and base URL (here: `custom > *`) -- setup model name aliases (here: `anthropic > fast`, `anthropic > writing`, `anthropic > reasoning`) -- pre-configure model settings (here: `anthropic > reasoning`) -- validate the provider-specific options (here: `AnthropicLanguageModelOptions`) -- use a fallback provider (here: `anthropic > *`) -- limit a provider to certain models without a fallback (here: `groq > gemma2-9b-it`, `groq > qwen-qwq-32b`) -- define a custom separator for the provider registry (here: `>`) - -```ts -import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; -import { createOpenAICompatible } from '@ai-sdk/openai-compatible'; -import { xai } from '@ai-sdk/xai'; -import { groq } from '@ai-sdk/groq'; -import { - createProviderRegistry, - customProvider, - defaultSettingsMiddleware, - gateway, - wrapLanguageModel, -} from 'ai'; - -export const registry = createProviderRegistry( - { - // pass through gateway with a namespace prefix - gateway, - - // pass through full providers with namespace prefixes - xai, - - // access an OpenAI-compatible provider with custom setup - custom: createOpenAICompatible({ - name: 'provider-name', - apiKey: process.env.CUSTOM_API_KEY, - baseURL: 'https://api.custom.com/v1', - }), - - // setup model name aliases - anthropic: customProvider({ - languageModels: { - fast: anthropic('claude-haiku-4-5'), - - // simple model - writing: anthropic('claude-sonnet-4-5'), - - // extended reasoning model configuration: - reasoning: wrapLanguageModel({ - model: anthropic('claude-sonnet-4-5'), - middleware: defaultSettingsMiddleware({ - settings: { - maxOutputTokens: 100000, // example default setting - providerOptions: { - anthropic: { - thinking: { - type: 'enabled', - budgetTokens: 32000, - }, - } satisfies AnthropicLanguageModelOptions, - }, - }, - }), - }), - }, - fallbackProvider: anthropic, - }), - - // limit a provider to certain models without a fallback - groq: customProvider({ - languageModels: { - 'gemma2-9b-it': groq('gemma2-9b-it'), - 'qwen-qwq-32b': groq('qwen-qwq-32b'), - }, - }), - }, - { separator: ' > ' }, -); - -// usage: -const model = registry.languageModel('anthropic > reasoning'); -``` - -## Global Provider Configuration - -The AI SDK 5 includes a global provider feature that allows you to specify a model using just a plain model ID string: - -```ts -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const result = await streamText({ - model: __MODEL__, // Uses the global provider (defaults to gateway) - prompt: 'Invent a new holiday and describe its traditions.', -}); -``` - -By default, the global provider is set to the Vercel AI Gateway. - -### Customizing the Global Provider - -You can set your own preferred global provider: - -```ts filename="setup.ts" -import { openai } from '@ai-sdk/openai'; - -// Initialize once during startup: -globalThis.AI_SDK_DEFAULT_PROVIDER = openai; -``` - -```ts filename="app.ts" -import { streamText } from 'ai'; - -const result = await streamText({ - model: 'gpt-5.1', // Uses OpenAI provider without prefix - prompt: 'Invent a new holiday and describe its traditions.', -}); -``` - -This simplifies provider usage and makes it easier to switch between providers without changing your model references throughout your codebase. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/50-error-handling.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/50-error-handling.mdx deleted file mode 100644 index 2d62e395b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/50-error-handling.mdx +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Error Handling -description: Learn how to handle errors in the AI SDK Core ---- - -# Error Handling - -## Handling regular errors - -Regular errors are thrown and can be handled using the `try/catch` block. - -```ts highlight="3,8-10" -import { generateText } from 'ai'; -__PROVIDER_IMPORT__; - -try { - const { text } = await generateText({ - model: __MODEL__, - prompt: 'Write a vegetarian lasagna recipe for 4 people.', - }); -} catch (error) { - // handle error -} -``` - -See [Error Types](/docs/reference/ai-sdk-errors) for more information on the different types of errors that may be thrown. - -## Handling streaming errors (simple streams) - -When errors occur during streams that do not support error chunks, -the error is thrown as a regular error. -You can handle these errors using the `try/catch` block. - -```ts highlight="3,12-14" -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -try { - const { textStream } = streamText({ - model: __MODEL__, - prompt: 'Write a vegetarian lasagna recipe for 4 people.', - }); - - for await (const textPart of textStream) { - process.stdout.write(textPart); - } -} catch (error) { - // handle error -} -``` - -## Handling streaming errors (streaming with `error` support) - -Full streams support error parts. -You can handle those parts similar to other parts. -It is recommended to also add a try-catch block for errors that -happen outside of the streaming. - -```ts highlight="13-21" -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -try { - const { fullStream } = streamText({ - model: __MODEL__, - prompt: 'Write a vegetarian lasagna recipe for 4 people.', - }); - - for await (const part of fullStream) { - switch (part.type) { - // ... handle other part types - - case 'error': { - const error = part.error; - // handle error - break; - } - - case 'abort': { - // handle stream abort - break; - } - - case 'tool-error': { - const error = part.error; - // handle error - break; - } - } - } -} catch (error) { - // handle error -} -``` - -## Handling stream aborts - -When streams are aborted (e.g., via chat stop button), you may want to perform cleanup operations like updating stored messages in your UI. Use the `onAbort` callback to handle these cases. - -The `onAbort` callback is called when a stream is aborted via `AbortSignal`, but `onFinish` is not called. This ensures you can still update your UI state appropriately. - -```ts highlight="5-9" -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const { textStream } = streamText({ - model: __MODEL__, - prompt: 'Write a vegetarian lasagna recipe for 4 people.', - onAbort: ({ steps }) => { - // Update stored messages or perform cleanup - console.log('Stream aborted after', steps.length, 'steps'); - }, - onFinish: ({ steps, totalUsage }) => { - // This is called on normal completion - console.log('Stream completed normally'); - }, -}); - -for await (const textPart of textStream) { - process.stdout.write(textPart); -} -``` - -The `onAbort` callback receives: - -- `steps`: An array of all completed steps before the abort - -You can also handle abort events directly in the stream: - -```ts highlight="10-13" -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const { fullStream } = streamText({ - model: __MODEL__, - prompt: 'Write a vegetarian lasagna recipe for 4 people.', -}); - -for await (const chunk of fullStream) { - switch (chunk.type) { - case 'abort': { - // Handle abort directly in stream - console.log('Stream was aborted'); - break; - } - // ... handle other part types - } -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/55-testing.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/55-testing.mdx deleted file mode 100644 index ef1fc703f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/55-testing.mdx +++ /dev/null @@ -1,219 +0,0 @@ ---- -title: Testing -description: Learn how to use AI SDK Core mock providers for testing. ---- - -# Testing - -Testing language models can be challenging, because they are non-deterministic -and calling them is slow and expensive. - -To enable you to unit test your code that uses the AI SDK, the AI SDK Core -includes mock providers and test helpers. You can import the following helpers from `ai/test`: - -- `MockEmbeddingModelV3`: A mock embedding model using the [embedding model v3 specification](https://github.com/vercel/ai/blob/main/packages/provider/src/embedding-model/v3/embedding-model-v3.ts). -- `MockLanguageModelV3`: A mock language model using the [language model v3 specification](https://github.com/vercel/ai/blob/main/packages/provider/src/language-model/v3/language-model-v3.ts). -- `mockId`: Provides an incrementing integer ID. -- `mockValues`: Iterates over an array of values with each call. Returns the last value when the array is exhausted. - -You can also import [`simulateReadableStream`](/docs/reference/ai-sdk-core/simulate-readable-stream) from `ai` to simulate a readable stream with delays. - -With mock providers and test helpers, you can control the output of the AI SDK -and test your code in a repeatable and deterministic way without actually calling -a language model provider. - -## Examples - -You can use the test helpers with the AI Core functions in your unit tests: - -### generateText - -```ts -import { generateText } from 'ai'; -import { MockLanguageModelV3 } from 'ai/test'; - -const result = await generateText({ - model: new MockLanguageModelV3({ - doGenerate: async () => ({ - content: [{ type: 'text', text: `Hello, world!` }], - finishReason: { unified: 'stop', raw: undefined }, - usage: { - inputTokens: { - total: 10, - noCache: 10, - cacheRead: undefined, - cacheWrite: undefined, - }, - outputTokens: { - total: 20, - text: 20, - reasoning: undefined, - }, - }, - warnings: [], - }), - }), - prompt: 'Hello, test!', -}); -``` - -### streamText - -```ts -import { streamText, simulateReadableStream } from 'ai'; -import { MockLanguageModelV3 } from 'ai/test'; - -const result = streamText({ - model: new MockLanguageModelV3({ - doStream: async () => ({ - stream: simulateReadableStream({ - chunks: [ - { type: 'text-start', id: 'text-1' }, - { type: 'text-delta', id: 'text-1', delta: 'Hello' }, - { type: 'text-delta', id: 'text-1', delta: ', ' }, - { type: 'text-delta', id: 'text-1', delta: 'world!' }, - { type: 'text-end', id: 'text-1' }, - { - type: 'finish', - finishReason: { unified: 'stop', raw: undefined }, - logprobs: undefined, - usage: { - inputTokens: { - total: 3, - noCache: 3, - cacheRead: undefined, - cacheWrite: undefined, - }, - outputTokens: { - total: 10, - text: 10, - reasoning: undefined, - }, - }, - }, - ], - }), - }), - }), - prompt: 'Hello, test!', -}); -``` - -### generateText with Output - -```ts -import { generateText, Output } from 'ai'; -import { MockLanguageModelV3 } from 'ai/test'; -import { z } from 'zod'; - -const result = await generateText({ - model: new MockLanguageModelV3({ - doGenerate: async () => ({ - content: [{ type: 'text', text: `{"content":"Hello, world!"}` }], - finishReason: { unified: 'stop', raw: undefined }, - usage: { - inputTokens: { - total: 10, - noCache: 10, - cacheRead: undefined, - cacheWrite: undefined, - }, - outputTokens: { - total: 20, - text: 20, - reasoning: undefined, - }, - }, - warnings: [], - }), - }), - output: Output.object({ schema: z.object({ content: z.string() }) }), - prompt: 'Hello, test!', -}); -``` - -### streamText with Output - -```ts -import { streamText, Output, simulateReadableStream } from 'ai'; -import { MockLanguageModelV3 } from 'ai/test'; -import { z } from 'zod'; - -const result = streamText({ - model: new MockLanguageModelV3({ - doStream: async () => ({ - stream: simulateReadableStream({ - chunks: [ - { type: 'text-start', id: 'text-1' }, - { type: 'text-delta', id: 'text-1', delta: '{ ' }, - { type: 'text-delta', id: 'text-1', delta: '"content": ' }, - { type: 'text-delta', id: 'text-1', delta: `"Hello, ` }, - { type: 'text-delta', id: 'text-1', delta: `world` }, - { type: 'text-delta', id: 'text-1', delta: `!"` }, - { type: 'text-delta', id: 'text-1', delta: ' }' }, - { type: 'text-end', id: 'text-1' }, - { - type: 'finish', - finishReason: { unified: 'stop', raw: undefined }, - logprobs: undefined, - usage: { - inputTokens: { - total: 3, - noCache: 3, - cacheRead: undefined, - cacheWrite: undefined, - }, - outputTokens: { - total: 10, - text: 10, - reasoning: undefined, - }, - }, - }, - ], - }), - }), - }), - output: Output.object({ schema: z.object({ content: z.string() }) }), - prompt: 'Hello, test!', -}); -``` - -### Simulate UI Message Stream Responses - -You can also simulate [UI Message Stream](/docs/ai-sdk-ui/stream-protocol#ui-message-stream) responses for testing, -debugging, or demonstration purposes. - -Here is a Next example: - -```ts filename="route.ts" -import { simulateReadableStream } from 'ai'; - -export async function POST(req: Request) { - return new Response( - simulateReadableStream({ - initialDelayInMs: 1000, // Delay before the first chunk - chunkDelayInMs: 300, // Delay between chunks - chunks: [ - `data: {"type":"start","messageId":"msg-123"}\n\n`, - `data: {"type":"text-start","id":"text-1"}\n\n`, - `data: {"type":"text-delta","id":"text-1","delta":"This"}\n\n`, - `data: {"type":"text-delta","id":"text-1","delta":" is an"}\n\n`, - `data: {"type":"text-delta","id":"text-1","delta":" example."}\n\n`, - `data: {"type":"text-end","id":"text-1"}\n\n`, - `data: {"type":"finish"}\n\n`, - `data: [DONE]\n\n`, - ], - }).pipeThrough(new TextEncoderStream()), - { - status: 200, - headers: { - 'Content-Type': 'text/event-stream', - 'Cache-Control': 'no-cache', - Connection: 'keep-alive', - 'x-vercel-ai-ui-message-stream': 'v1', - }, - }, - ); -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/60-telemetry.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/60-telemetry.mdx deleted file mode 100644 index 9d020df00..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/60-telemetry.mdx +++ /dev/null @@ -1,391 +0,0 @@ ---- -title: Telemetry -description: Using OpenTelemetry with AI SDK Core ---- - -# Telemetry - - - AI SDK Telemetry is experimental and may change in the future. - - -The AI SDK uses [OpenTelemetry](https://opentelemetry.io/) to collect telemetry data. -OpenTelemetry is an open-source observability framework designed to provide -standardized instrumentation for collecting telemetry data. - -Check out the [AI SDK Observability Integrations](/providers/observability) -to see providers that offer monitoring and tracing for AI SDK applications. - -## Enabling telemetry - -For Next.js applications, please follow the [Next.js OpenTelemetry guide](https://nextjs.org/docs/app/building-your-application/optimizing/open-telemetry) to enable telemetry first. - -You can then use the `experimental_telemetry` option to enable telemetry on specific function calls while the feature is experimental: - -```ts highlight="4" -const result = await generateText({ - model: __MODEL__, - prompt: 'Write a short story about a cat.', - experimental_telemetry: { isEnabled: true }, -}); -``` - -When telemetry is enabled, you can also control if you want to record the input values and the output values for the function. -By default, both are enabled. You can disable them by setting the `recordInputs` and `recordOutputs` options to `false`. - -Disabling the recording of inputs and outputs can be useful for privacy, data transfer, and performance reasons. -You might for example want to disable recording inputs if they contain sensitive information. - -## Telemetry Metadata - -You can provide a `functionId` to identify the function that the telemetry data is for, -and `metadata` to include additional information in the telemetry data. - -```ts highlight="6-10" -const result = await generateText({ - model: __MODEL__, - prompt: 'Write a short story about a cat.', - experimental_telemetry: { - isEnabled: true, - functionId: 'my-awesome-function', - metadata: { - something: 'custom', - someOtherThing: 'other-value', - }, - }, -}); -``` - -## Custom Tracer - -You may provide a `tracer` which must return an OpenTelemetry `Tracer`. This is useful in situations where -you want your traces to use a `TracerProvider` other than the one provided by the `@opentelemetry/api` singleton. - -```ts highlight="7" -const tracerProvider = new NodeTracerProvider(); -const result = await generateText({ - model: __MODEL__, - prompt: 'Write a short story about a cat.', - experimental_telemetry: { - isEnabled: true, - tracer: tracerProvider.getTracer('ai'), - }, -}); -``` - -## Telemetry Integrations - -Telemetry integrations let you hook into the generation lifecycle to build custom observability — logging, analytics, DevTools, or any other monitoring system. Instead of wiring up individual callbacks on every call, you implement a `TelemetryIntegration` once and pass it via `experimental_telemetry.integrations`. - -### Using an integration - -Pass one or more integrations to any `generateText` or `streamText` call: - -```ts highlight="6-8" -import { streamText } from 'ai'; -import { devToolsIntegration } from '@ai-sdk/devtools'; - -const result = streamText({ - model: openai('gpt-4o'), - prompt: 'Hello!', - experimental_telemetry: { - isEnabled: true, - integrations: [devToolsIntegration()], - }, -}); -``` - -You can combine multiple integrations — they all receive the same lifecycle events: - -```ts -experimental_telemetry: { - isEnabled: true, - integrations: [devToolsIntegration(), otelIntegration(), customLogger()], -}, -``` - -Errors inside integrations are caught and do not break the generation flow. - -### Building a custom integration - -Implement the `TelemetryIntegration` interface from the `ai` package. All methods are optional — implement only the lifecycle events you care about: - -```ts -import type { TelemetryIntegration } from 'ai'; -import { bindTelemetryIntegration } from 'ai'; - -class MyIntegration implements TelemetryIntegration { - async onStart(event) { - console.log('Generation started:', event.model.modelId); - } - - async onStepFinish(event) { - console.log( - `Step ${event.stepNumber} done:`, - event.usage.totalTokens, - 'tokens', - ); - } - - async onToolCallFinish(event) { - if (event.success) { - console.log( - `Tool "${event.toolCall.toolName}" took ${event.durationMs}ms`, - ); - } else { - console.error(`Tool "${event.toolCall.toolName}" failed:`, event.error); - } - } - - async onFinish(event) { - console.log('Done. Total tokens:', event.totalUsage.totalTokens); - } -} - -export function myIntegration(): TelemetryIntegration { - return bindTelemetryIntegration(new MyIntegration()); -} -``` - -Use `bindTelemetryIntegration` for class-based integrations to ensure `this` is correctly bound when methods are extracted and called as callbacks. - -### Available lifecycle methods - - void | PromiseLike', - description: - 'Called when the generation operation begins, before any LLM calls.', - }, - { - name: 'onStepStart', - type: '(event: OnStepStartEvent) => void | PromiseLike', - description: - 'Called when a step (LLM call) begins, before the provider is called.', - }, - { - name: 'onToolCallStart', - type: '(event: OnToolCallStartEvent) => void | PromiseLike', - description: "Called when a tool's execute function is about to run.", - }, - { - name: 'onToolCallFinish', - type: '(event: OnToolCallFinishEvent) => void | PromiseLike', - description: "Called when a tool's execute function completes or errors.", - }, - { - name: 'onStepFinish', - type: '(event: OnStepFinishEvent) => void | PromiseLike', - description: 'Called when a step (LLM call) completes.', - }, - { - name: 'onFinish', - type: '(event: OnFinishEvent) => void | PromiseLike', - description: - 'Called when the entire generation completes (all steps finished).', - }, - ]} -/> - -The event types for each method are the same as the corresponding [event callbacks](/docs/ai-sdk-core/event-listeners). See the event callbacks documentation for the full property reference of each event. - -## Collected Data - -### generateText function - -`generateText` records 3 types of spans: - -- `ai.generateText` (span): the full length of the generateText call. It contains 1 or more `ai.generateText.doGenerate` spans. - It contains the [basic LLM span information](#basic-llm-span-information) and the following attributes: - - - `operation.name`: `ai.generateText` and the functionId that was set through `telemetry.functionId` - - `ai.operationId`: `"ai.generateText"` - - `ai.prompt`: the prompt that was used when calling `generateText` - - `ai.response.text`: the text that was generated - - `ai.response.toolCalls`: the tool calls that were made as part of the generation (stringified JSON) - - `ai.response.finishReason`: the reason why the generation finished - - `ai.settings.maxOutputTokens`: the maximum number of output tokens that were set - -- `ai.generateText.doGenerate` (span): a provider doGenerate call. It can contain `ai.toolCall` spans. - It contains the [call LLM span information](#call-llm-span-information) and the following attributes: - - - `operation.name`: `ai.generateText.doGenerate` and the functionId that was set through `telemetry.functionId` - - `ai.operationId`: `"ai.generateText.doGenerate"` - - `ai.prompt.messages`: the messages that were passed into the provider - - `ai.prompt.tools`: array of stringified tool definitions. The tools can be of type `function` or `provider-defined-client`. - Function tools have a `name`, `description` (optional), and `inputSchema` (JSON schema). - Provider-defined-client tools have a `name`, `id`, and `input` (Record). - - `ai.prompt.toolChoice`: the stringified tool choice setting (JSON). It has a `type` property - (`auto`, `none`, `required`, `tool`), and if the type is `tool`, a `toolName` property with the specific tool. - - `ai.response.text`: the text that was generated - - `ai.response.toolCalls`: the tool calls that were made as part of the generation (stringified JSON) - - `ai.response.finishReason`: the reason why the generation finished - -- `ai.toolCall` (span): a tool call that is made as part of the generateText call. See [Tool call spans](#tool-call-spans) for more details. - -### streamText function - -`streamText` records 3 types of spans and 2 types of events: - -- `ai.streamText` (span): the full length of the streamText call. It contains a `ai.streamText.doStream` span. - It contains the [basic LLM span information](#basic-llm-span-information) and the following attributes: - - - `operation.name`: `ai.streamText` and the functionId that was set through `telemetry.functionId` - - `ai.operationId`: `"ai.streamText"` - - `ai.prompt`: the prompt that was used when calling `streamText` - - `ai.response.text`: the text that was generated - - `ai.response.toolCalls`: the tool calls that were made as part of the generation (stringified JSON) - - `ai.response.finishReason`: the reason why the generation finished - - `ai.settings.maxOutputTokens`: the maximum number of output tokens that were set - -- `ai.streamText.doStream` (span): a provider doStream call. - This span contains an `ai.stream.firstChunk` event and `ai.toolCall` spans. - It contains the [call LLM span information](#call-llm-span-information) and the following attributes: - - - `operation.name`: `ai.streamText.doStream` and the functionId that was set through `telemetry.functionId` - - `ai.operationId`: `"ai.streamText.doStream"` - - `ai.prompt.messages`: the messages that were passed into the provider - - `ai.prompt.tools`: array of stringified tool definitions. The tools can be of type `function` or `provider-defined-client`. - Function tools have a `name`, `description` (optional), and `inputSchema` (JSON schema). - Provider-defined-client tools have a `name`, `id`, and `input` (Record). - - `ai.prompt.toolChoice`: the stringified tool choice setting (JSON). It has a `type` property - (`auto`, `none`, `required`, `tool`), and if the type is `tool`, a `toolName` property with the specific tool. - - `ai.response.text`: the text that was generated - - `ai.response.toolCalls`: the tool calls that were made as part of the generation (stringified JSON) - - `ai.response.msToFirstChunk`: the time it took to receive the first chunk in milliseconds - - `ai.response.msToFinish`: the time it took to receive the finish part of the LLM stream in milliseconds - - `ai.response.avgCompletionTokensPerSecond`: the average number of completion tokens per second - - `ai.response.finishReason`: the reason why the generation finished - -- `ai.toolCall` (span): a tool call that is made as part of the generateText call. See [Tool call spans](#tool-call-spans) for more details. - -- `ai.stream.firstChunk` (event): an event that is emitted when the first chunk of the stream is received. - - - `ai.response.msToFirstChunk`: the time it took to receive the first chunk - -- `ai.stream.finish` (event): an event that is emitted when the finish part of the LLM stream is received. - -It also records a `ai.stream.firstChunk` event when the first chunk of the stream is received. - -### Deprecated object APIs - - - `generateObject` and `streamObject` are deprecated. Use `generateText` and - `streamText` with the `output` property instead. - - -If you still run deprecated object APIs, you will see legacy span names: - -- `generateObject`: `ai.generateObject`, `ai.generateObject.doGenerate` -- `streamObject`: `ai.streamObject`, `ai.streamObject.doStream`, `ai.stream.firstChunk` - -Legacy object spans include the same core metadata as other LLM spans, plus -object-specific attributes such as `ai.schema.*`, `ai.response.object`, and -`ai.settings.output`. - -### embed function - -`embed` records 2 types of spans: - -- `ai.embed` (span): the full length of the embed call. It contains 1 `ai.embed.doEmbed` spans. - It contains the [basic embedding span information](#basic-embedding-span-information) and the following attributes: - - - `operation.name`: `ai.embed` and the functionId that was set through `telemetry.functionId` - - `ai.operationId`: `"ai.embed"` - - `ai.value`: the value that was passed into the `embed` function - - `ai.embedding`: a JSON-stringified embedding - -- `ai.embed.doEmbed` (span): a provider doEmbed call. - It contains the [basic embedding span information](#basic-embedding-span-information) and the following attributes: - - - `operation.name`: `ai.embed.doEmbed` and the functionId that was set through `telemetry.functionId` - - `ai.operationId`: `"ai.embed.doEmbed"` - - `ai.values`: the values that were passed into the provider (array) - - `ai.embeddings`: an array of JSON-stringified embeddings - -### embedMany function - -`embedMany` records 2 types of spans: - -- `ai.embedMany` (span): the full length of the embedMany call. It contains 1 or more `ai.embedMany.doEmbed` spans. - It contains the [basic embedding span information](#basic-embedding-span-information) and the following attributes: - - - `operation.name`: `ai.embedMany` and the functionId that was set through `telemetry.functionId` - - `ai.operationId`: `"ai.embedMany"` - - `ai.values`: the values that were passed into the `embedMany` function - - `ai.embeddings`: an array of JSON-stringified embedding - -- `ai.embedMany.doEmbed` (span): a provider doEmbed call. - It contains the [basic embedding span information](#basic-embedding-span-information) and the following attributes: - - - `operation.name`: `ai.embedMany.doEmbed` and the functionId that was set through `telemetry.functionId` - - `ai.operationId`: `"ai.embedMany.doEmbed"` - - `ai.values`: the values that were sent to the provider - - `ai.embeddings`: an array of JSON-stringified embeddings for each value - -## Span Details - -### Basic LLM span information - -Many spans that use LLMs (`ai.generateText`, `ai.generateText.doGenerate`, `ai.streamText`, `ai.streamText.doStream`) contain the following attributes: - -- `resource.name`: the functionId that was set through `telemetry.functionId` -- `ai.model.id`: the id of the model -- `ai.model.provider`: the provider of the model -- `ai.request.headers.*`: the request headers that were passed in through `headers` -- `ai.response.providerMetadata`: provider specific metadata returned with the generation response -- `ai.settings.maxRetries`: the maximum number of retries that were set -- `ai.telemetry.functionId`: the functionId that was set through `telemetry.functionId` -- `ai.telemetry.metadata.*`: the metadata that was passed in through `telemetry.metadata` -- `ai.usage.completionTokens`: the number of completion tokens that were used -- `ai.usage.promptTokens`: the number of prompt tokens that were used - -### Call LLM span information - -Spans that correspond to individual LLM calls (`ai.generateText.doGenerate`, `ai.streamText.doStream`) contain -[basic LLM span information](#basic-llm-span-information) and the following attributes: - -- `ai.response.model`: the model that was used to generate the response. This can be different from the model that was requested if the provider supports aliases. -- `ai.response.id`: the id of the response. Uses the ID from the provider when available. -- `ai.response.timestamp`: the timestamp of the response. Uses the timestamp from the provider when available. -- [Semantic Conventions for GenAI operations](https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/) - - `gen_ai.system`: the provider that was used - - `gen_ai.request.model`: the model that was requested - - `gen_ai.request.temperature`: the temperature that was set - - `gen_ai.request.max_tokens`: the maximum number of tokens that were set - - `gen_ai.request.frequency_penalty`: the frequency penalty that was set - - `gen_ai.request.presence_penalty`: the presence penalty that was set - - `gen_ai.request.top_k`: the topK parameter value that was set - - `gen_ai.request.top_p`: the topP parameter value that was set - - `gen_ai.request.stop_sequences`: the stop sequences - - `gen_ai.response.finish_reasons`: the finish reasons that were returned by the provider - - `gen_ai.response.model`: the model that was used to generate the response. This can be different from the model that was requested if the provider supports aliases. - - `gen_ai.response.id`: the id of the response. Uses the ID from the provider when available. - - `gen_ai.usage.input_tokens`: the number of prompt tokens that were used - - `gen_ai.usage.output_tokens`: the number of completion tokens that were used - -### Basic embedding span information - -Many spans that use embedding models (`ai.embed`, `ai.embed.doEmbed`, `ai.embedMany`, `ai.embedMany.doEmbed`) contain the following attributes: - -- `ai.model.id`: the id of the model -- `ai.model.provider`: the provider of the model -- `ai.request.headers.*`: the request headers that were passed in through `headers` -- `ai.settings.maxRetries`: the maximum number of retries that were set -- `ai.telemetry.functionId`: the functionId that was set through `telemetry.functionId` -- `ai.telemetry.metadata.*`: the metadata that was passed in through `telemetry.metadata` -- `ai.usage.tokens`: the number of tokens that were used -- `resource.name`: the functionId that was set through `telemetry.functionId` - -### Tool call spans - -Tool call spans (`ai.toolCall`) contain the following attributes: - -- `operation.name`: `"ai.toolCall"` -- `ai.operationId`: `"ai.toolCall"` -- `ai.toolCall.name`: the name of the tool -- `ai.toolCall.id`: the id of the tool call -- `ai.toolCall.args`: the input parameters of the tool call -- `ai.toolCall.result`: the output result of the tool call. Only available if the tool call is successful and the result is serializable. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/65-devtools.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/65-devtools.mdx deleted file mode 100644 index 451265af8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/65-devtools.mdx +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: DevTools -description: Debug and inspect AI SDK applications with DevTools ---- - -# DevTools - - - AI SDK DevTools is experimental and intended for local development only. Do - not use in production environments. - - -AI SDK DevTools gives you full visibility over your AI SDK calls with [`generateText`](/docs/reference/ai-sdk-core/generate-text), [`streamText`](/docs/reference/ai-sdk-core/stream-text), and [`ToolLoopAgent`](/docs/reference/ai-sdk-core/tool-loop-agent). It helps you debug and inspect LLM requests, responses, tool calls, and multi-step interactions through a web-based UI. - -DevTools is composed of two parts: - -1. **Middleware**: Captures runs and steps from your AI SDK calls -2. **Viewer**: A web UI to inspect the captured data - -## Installation - -Install the DevTools package: - -```bash -pnpm add @ai-sdk/devtools -``` - -## Requirements - -- AI SDK v6 beta (`ai@^6.0.0-beta.0`) -- Node.js compatible runtime - -## Using DevTools - -### Add the middleware - -Wrap your language model with the DevTools middleware using [`wrapLanguageModel`](/docs/ai-sdk-core/middleware): - -```ts -import { wrapLanguageModel, gateway } from 'ai'; -import { devToolsMiddleware } from '@ai-sdk/devtools'; - -const model = wrapLanguageModel({ - model: gateway('anthropic/claude-sonnet-4.5'), - middleware: devToolsMiddleware(), -}); -``` - -The wrapped model can be used with any AI SDK Core function: - -```ts highlight="4" -import { generateText } from 'ai'; - -const result = await generateText({ - model, // wrapped model with DevTools - prompt: 'What cities are in the United States?', -}); -``` - -### Launch the viewer - -Start the DevTools viewer: - -```bash -npx @ai-sdk/devtools -``` - -Open [http://localhost:4983](http://localhost:4983) to view your AI SDK interactions. - -## Captured data - -The DevTools middleware captures the following information from your AI SDK calls: - -- **Input parameters and prompts**: View the complete input sent to your LLM -- **Output content and tool calls**: Inspect generated text and tool invocations -- **Token usage and timing**: Monitor resource consumption and performance -- **Raw provider data**: Access complete request and response payloads - -### Runs and steps - -DevTools organizes captured data into runs and steps: - -- **Run**: A complete multi-step AI interaction, grouped by the initial prompt -- **Step**: A single LLM call within a run (e.g., one `generateText` or `streamText` call) - -Multi-step interactions, such as those created by tool calling or agent loops, are grouped together as a single run with multiple steps. - -## How it works - -The DevTools middleware intercepts all `generateText` and `streamText` calls through the [language model middleware](/docs/ai-sdk-core/middleware) system. Captured data is stored locally in a JSON file (`.devtools/generations.json`) and served through a web UI built with Hono and React. - - - The middleware automatically adds `.devtools` to your `.gitignore` file. - Verify that `.devtools` is in your `.gitignore` to ensure you don't commit - sensitive AI interaction data to your repository. - - -## Security considerations - -DevTools stores all AI interactions locally in plain text files, including: - -- User prompts and messages -- LLM responses -- Tool call arguments and results -- API request and response data - -**Only use DevTools in local development environments.** Do not enable DevTools in production or when handling sensitive data. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/65-event-listeners.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/65-event-listeners.mdx deleted file mode 100644 index 1b161418c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/65-event-listeners.mdx +++ /dev/null @@ -1,915 +0,0 @@ ---- -title: Event Callbacks -description: Subscribe to lifecycle events in generateText and streamText calls ---- - -# Event Callbacks - -The AI SDK provides per-call event callbacks that you can pass to `generateText` and `streamText` to observe lifecycle events. This is useful for building observability tools, logging systems, analytics, and debugging utilities. - -## Basic Usage - -Pass callbacks directly to `generateText` or `streamText`: - -```ts -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-4o'), - prompt: 'What is the weather in San Francisco?', - experimental_onStart: event => { - console.log('Generation started:', event.model.modelId); - }, - onFinish: event => { - console.log('Generation finished:', event.totalUsage); - }, -}); -``` - -## Available Callbacks - - void | Promise', - description: 'Called when generation begins, before any LLM calls.', - }, - { - name: 'experimental_onStepStart', - type: '(event: OnStepStartEvent) => void | Promise', - description: - 'Called when a step (LLM call) begins, before the provider is called.', - }, - { - name: 'experimental_onToolCallStart', - type: '(event: OnToolCallStartEvent) => void | Promise', - description: "Called when a tool's execute function is about to run.", - }, - { - name: 'experimental_onToolCallFinish', - type: '(event: OnToolCallFinishEvent) => void | Promise', - description: "Called when a tool's execute function completes or errors.", - }, - { - name: 'onStepFinish', - type: '(event: OnStepFinishEvent) => void | Promise', - description: 'Called when a step (LLM call) completes.', - }, - { - name: 'onFinish', - type: '(event: OnFinishEvent) => void | Promise', - description: - 'Called when the entire generation completes (all steps finished).', - }, - ]} -/> - -## Event Reference - -### `experimental_onStart` - -Called when the generation operation begins, before any LLM calls are made. - -```ts -const result = await generateText({ - model: openai('gpt-4o'), - prompt: 'Hello!', - experimental_onStart: event => { - console.log('Model:', event.model.modelId); - console.log('Temperature:', event.temperature); - }, -}); -``` - - | undefined', - description: 'The system message(s) provided to the model.', - }, - { - name: 'prompt', - type: 'string | Array | undefined', - description: - 'The prompt string or array of messages if using the prompt option.', - }, - { - name: 'messages', - type: 'Array | undefined', - description: 'The messages array if using the messages option.', - }, - { - name: 'tools', - type: 'ToolSet | undefined', - description: 'The tools available for this generation.', - }, - { - name: 'toolChoice', - type: 'ToolChoice | undefined', - description: 'The tool choice strategy for this generation.', - }, - { - name: 'activeTools', - type: 'Array | undefined', - description: 'Limits which tools are available for the model to call.', - }, - { - name: 'maxOutputTokens', - type: 'number | undefined', - description: 'Maximum number of tokens to generate.', - }, - { - name: 'temperature', - type: 'number | undefined', - description: 'Sampling temperature for generation.', - }, - { - name: 'topP', - type: 'number | undefined', - description: 'Top-p (nucleus) sampling parameter.', - }, - { - name: 'topK', - type: 'number | undefined', - description: 'Top-k sampling parameter.', - }, - { - name: 'presencePenalty', - type: 'number | undefined', - description: 'Presence penalty for generation.', - }, - { - name: 'frequencyPenalty', - type: 'number | undefined', - description: 'Frequency penalty for generation.', - }, - { - name: 'stopSequences', - type: 'string[] | undefined', - description: 'Sequences that will stop generation.', - }, - { - name: 'seed', - type: 'number | undefined', - description: 'Random seed for reproducible generation.', - }, - { - name: 'maxRetries', - type: 'number', - description: 'Maximum number of retries for failed requests.', - }, - { - name: 'timeout', - type: 'TimeoutConfiguration | undefined', - description: 'Timeout configuration for the generation.', - }, - { - name: 'headers', - type: 'Record | undefined', - description: 'Additional HTTP headers sent with the request.', - }, - { - name: 'providerOptions', - type: 'ProviderOptions | undefined', - description: 'Additional provider-specific options.', - }, - { - name: 'stopWhen', - type: 'StopCondition | Array | undefined', - description: 'Condition(s) for stopping the generation.', - }, - { - name: 'output', - type: 'Output | undefined', - description: 'The output specification for structured outputs.', - }, - { - name: 'abortSignal', - type: 'AbortSignal | undefined', - description: 'Abort signal for cancelling the operation.', - }, - { - name: 'include', - type: '{ requestBody?: boolean; responseBody?: boolean } | undefined', - description: - 'Settings for controlling what data is included in step results.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata passed to the generation.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object that flows through the entire generation lifecycle.', - }, - ]} -/> - -### `experimental_onStepStart` - -Called before each step (LLM call) begins. Useful for tracking multi-step generations. - -```ts -const result = await generateText({ - model: openai('gpt-4o'), - prompt: 'Hello!', - experimental_onStepStart: event => { - console.log('Step:', event.stepNumber); - console.log('Messages:', event.messages.length); - }, -}); -``` - - | undefined', - description: 'The system message for this step.', - }, - { - name: 'messages', - type: 'Array', - description: 'The messages that will be sent to the model for this step.', - }, - { - name: 'tools', - type: 'ToolSet | undefined', - description: 'The tools available for this generation.', - }, - { - name: 'toolChoice', - type: 'LanguageModelV3ToolChoice | undefined', - description: 'The tool choice configuration for this step.', - }, - { - name: 'activeTools', - type: 'Array | undefined', - description: 'Limits which tools are available for this step.', - }, - { - name: 'steps', - type: 'ReadonlyArray', - description: - 'Array of results from previous steps (empty for first step).', - }, - { - name: 'providerOptions', - type: 'ProviderOptions | undefined', - description: 'Additional provider-specific options for this step.', - }, - { - name: 'timeout', - type: 'TimeoutConfiguration | undefined', - description: 'Timeout configuration for the generation.', - }, - { - name: 'headers', - type: 'Record | undefined', - description: 'Additional HTTP headers sent with the request.', - }, - { - name: 'stopWhen', - type: 'StopCondition | Array | undefined', - description: 'Condition(s) for stopping the generation.', - }, - { - name: 'output', - type: 'Output | undefined', - description: 'The output specification for structured outputs.', - }, - { - name: 'abortSignal', - type: 'AbortSignal | undefined', - description: 'Abort signal for cancelling the operation.', - }, - { - name: 'include', - type: '{ requestBody?: boolean; responseBody?: boolean } | undefined', - description: - 'Settings for controlling what data is included in step results.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object. May be updated from prepareStep between steps.', - }, - ]} -/> - -### `experimental_onToolCallStart` - -Called before a tool's `execute` function runs. - -```ts -const result = await generateText({ - model: openai('gpt-4o'), - prompt: 'What is the weather?', - tools: { getWeather }, - experimental_onToolCallStart: event => { - console.log('Tool:', event.toolCall.toolName); - console.log('Input:', event.toolCall.input); - }, -}); -``` - -', - description: - 'The conversation messages available at tool execution time.', - }, - { - name: 'abortSignal', - type: 'AbortSignal | undefined', - description: 'Signal for cancelling the operation.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object flowing through the generation.', - }, - ]} -/> - -### `experimental_onToolCallFinish` - -Called after a tool's `execute` function completes or errors. Uses a discriminated union on the `success` field. - -```ts -const result = await generateText({ - model: openai('gpt-4o'), - prompt: 'What is the weather?', - tools: { getWeather }, - experimental_onToolCallFinish: event => { - console.log('Tool:', event.toolCall.toolName); - console.log('Duration:', event.durationMs, 'ms'); - - if (event.success) { - console.log('Output:', event.output); - } else { - console.error('Error:', event.error); - } - }, -}); -``` - -', - description: - 'The conversation messages available at tool execution time.', - }, - { - name: 'abortSignal', - type: 'AbortSignal | undefined', - description: 'Signal for cancelling the operation.', - }, - { - name: 'durationMs', - type: 'number', - description: 'Execution time of the tool call in milliseconds.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object flowing through the generation.', - }, - { - name: 'success', - type: 'boolean', - description: - 'Discriminator indicating whether the tool call succeeded. When true, output is available. When false, error is available.', - }, - { - name: 'output', - type: 'unknown', - description: - "The tool's return value (only present when success is true).", - }, - { - name: 'error', - type: 'unknown', - description: - 'The error that occurred during tool execution (only present when success is false).', - }, - ]} -/> - -### `onStepFinish` - -Called after each step (LLM call) completes. Provides the full `StepResult`. - -```ts -const result = await generateText({ - model: openai('gpt-4o'), - prompt: 'Hello!', - onStepFinish: event => { - console.log('Step:', event.stepNumber); - console.log('Finish reason:', event.finishReason); - console.log('Tokens:', event.usage.totalTokens); - }, -}); -``` - -', - description: 'The tool calls that were made during the generation.', - }, - { - name: 'toolResults', - type: 'Array', - description: 'The results of the tool calls.', - }, - { - name: 'content', - type: 'Array', - description: 'The content that was generated in this step.', - }, - { - name: 'reasoning', - type: 'Array', - description: 'The reasoning that was generated during the generation.', - }, - { - name: 'reasoningText', - type: 'string | undefined', - description: 'The reasoning text that was generated.', - }, - { - name: 'files', - type: 'Array', - description: 'The files that were generated during the generation.', - }, - { - name: 'sources', - type: 'Array', - description: 'The sources that were used to generate the text.', - }, - { - name: 'warnings', - type: 'CallWarning[] | undefined', - description: 'Warnings from the model provider.', - }, - { - name: 'request', - type: 'LanguageModelRequestMetadata', - description: 'Additional request information.', - }, - { - name: 'response', - type: 'LanguageModelResponseMetadata', - description: - 'Additional response information including id, modelId, timestamp, headers, and messages.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object flowing through the generation.', - }, - { - name: 'providerMetadata', - type: 'ProviderMetadata | undefined', - description: 'Additional provider-specific metadata.', - }, - ]} -/> - -### `onFinish` - -Called when the entire generation completes (all steps finished). Includes aggregated data. - -```ts -const result = await generateText({ - model: openai('gpt-4o'), - prompt: 'Hello!', - onFinish: event => { - console.log('Total steps:', event.steps.length); - console.log('Total tokens:', event.totalUsage.totalTokens); - console.log('Final text:', event.text); - }, -}); -``` - -', - description: 'Array containing results from all steps in the generation.', - }, - { - name: 'totalUsage', - type: 'LanguageModelUsage', - description: 'Aggregated token usage across all steps.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: - 'The total number of input tokens used across all steps.', - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: - 'The total number of output tokens used across all steps.', - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used across all steps.', - }, - ], - }, - ], - }, - { - name: 'stepNumber', - type: 'number', - description: 'Zero-based index of the final step.', - }, - { - name: 'model', - type: '{ provider: string; modelId: string }', - description: 'Information about the model that produced the final step.', - }, - { - name: 'finishReason', - type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'", - description: 'The unified reason why the generation finished.', - }, - { - name: 'usage', - type: 'LanguageModelUsage', - description: 'The token usage from the final step only (not aggregated).', - }, - { - name: 'text', - type: 'string', - description: 'The full text that has been generated.', - }, - { - name: 'toolCalls', - type: 'Array', - description: 'The tool calls that were made in the final step.', - }, - { - name: 'toolResults', - type: 'Array', - description: 'The results of the tool calls from the final step.', - }, - { - name: 'content', - type: 'Array', - description: 'The content that was generated in the final step.', - }, - { - name: 'reasoning', - type: 'Array', - description: 'The reasoning that was generated.', - }, - { - name: 'reasoningText', - type: 'string | undefined', - description: 'The reasoning text that was generated.', - }, - { - name: 'files', - type: 'Array', - description: 'Files that were generated in the final step.', - }, - { - name: 'sources', - type: 'Array', - description: - 'Sources that have been used as input to generate the response.', - }, - { - name: 'warnings', - type: 'CallWarning[] | undefined', - description: 'Warnings from the model provider.', - }, - { - name: 'request', - type: 'LanguageModelRequestMetadata', - description: 'Additional request information from the final step.', - }, - { - name: 'response', - type: 'LanguageModelResponseMetadata', - description: 'Additional response information from the final step.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: 'The final state of the user-defined context object.', - }, - { - name: 'providerMetadata', - type: 'ProviderMetadata | undefined', - description: 'Additional provider-specific metadata from the final step.', - }, - ]} -/> - -## Use Cases - -### Logging and Debugging - -```ts -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-4o'), - prompt: 'Hello!', - experimental_onStart: event => { - console.log(`[${new Date().toISOString()}] Generation started`, { - model: event.model.modelId, - provider: event.model.provider, - }); - }, - onStepFinish: event => { - console.log( - `[${new Date().toISOString()}] Step ${event.stepNumber} finished`, - { - finishReason: event.finishReason, - tokens: event.usage.totalTokens, - }, - ); - }, - onFinish: event => { - console.log(`[${new Date().toISOString()}] Generation complete`, { - totalSteps: event.steps.length, - totalTokens: event.totalUsage.totalTokens, - }); - }, -}); -``` - -### Tool Execution Monitoring - -```ts -import { generateText } from 'ai'; - -const result = await generateText({ - model: openai('gpt-4o'), - prompt: 'What is the weather?', - tools: { getWeather }, - experimental_onToolCallStart: event => { - console.log(`Tool "${event.toolCall.toolName}" starting...`); - }, - experimental_onToolCallFinish: event => { - if (event.success) { - console.log( - `Tool "${event.toolCall.toolName}" completed in ${event.durationMs}ms`, - ); - } else { - console.error(`Tool "${event.toolCall.toolName}" failed:`, event.error); - } - }, -}); -``` - -## Error Handling - -Errors thrown inside callbacks are caught and do not break the generation flow. This ensures that monitoring code cannot disrupt your application: - -```ts -const result = await generateText({ - model: openai('gpt-4o'), - prompt: 'Hello!', - experimental_onStart: () => { - throw new Error('This error is caught internally'); - // Generation continues normally - }, -}); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/index.mdx deleted file mode 100644 index 1fbebbd49..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/03-ai-sdk-core/index.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: AI SDK Core -description: Learn about AI SDK Core. ---- - -# AI SDK Core - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/01-overview.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/01-overview.mdx deleted file mode 100644 index 4e141fae7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/01-overview.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Overview -description: An overview of AI SDK UI. ---- - -# AI SDK UI - -AI SDK UI is designed to help you build interactive chat, completion, and assistant applications with ease. It is a **framework-agnostic toolkit**, streamlining the integration of advanced AI functionalities into your applications. - -AI SDK UI provides robust abstractions that simplify the complex tasks of managing chat streams and UI updates on the frontend, enabling you to develop dynamic AI-driven interfaces more efficiently. With three main hooks — **`useChat`**, **`useCompletion`**, and **`useObject`** — you can incorporate real-time chat capabilities, text completions, streamed JSON, and interactive assistant features into your app. - -- **[`useChat`](/docs/ai-sdk-ui/chatbot)** offers real-time streaming of chat messages, abstracting state management for inputs, messages, loading, and errors, allowing for seamless integration into any UI design. -- **[`useCompletion`](/docs/ai-sdk-ui/completion)** enables you to handle text completions in your applications, managing the prompt input and automatically updating the UI as new completions are streamed. -- **[`useObject`](/docs/ai-sdk-ui/object-generation)** is a hook that allows you to consume streamed JSON objects, providing a simple way to handle and display structured data in your application. - -These hooks are designed to reduce the complexity and time required to implement AI interactions, letting you focus on creating exceptional user experiences. - -## UI Framework Support - -AI SDK UI supports the following frameworks: [React](https://react.dev/), [Svelte](https://svelte.dev/), [Vue.js](https://vuejs.org/), -[Angular](https://angular.dev/), and [SolidJS](https://www.solidjs.com/). - -Here is a comparison of the supported functions across these frameworks: - -| | [useChat](/docs/reference/ai-sdk-ui/use-chat) | [useCompletion](/docs/reference/ai-sdk-ui/use-completion) | [useObject](/docs/reference/ai-sdk-ui/use-object) | -| --------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------- | -| React `@ai-sdk/react` | | | | -| Vue.js `@ai-sdk/vue` | | | | -| Svelte `@ai-sdk/svelte` | Chat | Completion | StructuredObject | -| Angular `@ai-sdk/angular` | Chat | Completion | StructuredObject | -| [SolidJS](https://github.com/kodehort/ai-sdk-solid) (community) | | | | - -## Framework Examples - -Explore these example implementations for different frameworks: - -- [**Next.js**](https://github.com/vercel/ai/tree/main/examples/next-openai) -- [**Nuxt**](https://github.com/vercel/ai/tree/main/examples/nuxt-openai) -- [**SvelteKit**](https://github.com/vercel/ai/tree/main/examples/sveltekit-openai) -- [**Angular**](https://github.com/vercel/ai/tree/main/examples/angular) - -## API Reference - -Please check out the [AI SDK UI API Reference](/docs/reference/ai-sdk-ui) for more details on each function. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/02-chatbot.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/02-chatbot.mdx deleted file mode 100644 index 58a17743e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/02-chatbot.mdx +++ /dev/null @@ -1,1313 +0,0 @@ ---- -title: Chatbot -description: Learn how to use the useChat hook. ---- - -# Chatbot - -The `useChat` hook makes it effortless to create a conversational user interface for your chatbot application. It enables the streaming of chat messages from your AI provider, manages the chat state, and updates the UI automatically as new messages arrive. - -To summarize, the `useChat` hook provides the following features: - -- **Message Streaming**: All the messages from the AI provider are streamed to the chat UI in real-time. -- **Managed States**: The hook manages the states for input, messages, status, error and more for you. -- **Seamless Integration**: Easily integrate your chat AI into any design or layout with minimal effort. - -In this guide, you will learn how to use the `useChat` hook to create a chatbot application with real-time message streaming. -Check out our [chatbot with tools guide](/docs/ai-sdk-ui/chatbot-tool-usage) to learn how to use tools in your chatbot. -Let's start with the following example first. - -## Example - -```tsx filename='app/page.tsx' -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; -import { useState } from 'react'; - -export default function Page() { - const { messages, sendMessage, status } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - }), - }); - const [input, setInput] = useState(''); - - return ( - <> - {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, index) => - part.type === 'text' ? {part.text} : null, - )} -
- ))} - -
{ - e.preventDefault(); - if (input.trim()) { - sendMessage({ text: input }); - setInput(''); - } - }} - > - setInput(e.target.value)} - disabled={status !== 'ready'} - placeholder="Say something..." - /> - -
- - ); -} -``` - -```ts filename='app/api/chat/route.ts' -import { convertToModelMessages, streamText, UIMessage } from 'ai'; -__PROVIDER_IMPORT__; - -// Allow streaming responses up to 30 seconds -export const maxDuration = 30; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - system: 'You are a helpful assistant.', - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse(); -} -``` - - - The UI messages have a new `parts` property that contains the message parts. - We recommend rendering the messages using the `parts` property instead of the - `content` property. The parts property supports different message types, - including text, tool invocation, and tool result, and allows for more flexible - and complex chat UIs. - - -In the `Page` component, the `useChat` hook will request to your AI provider endpoint whenever the user sends a message using `sendMessage`. -The messages are then streamed back in real-time and displayed in the chat UI. - -This enables a seamless chat experience where the user can see the AI response as soon as it is available, -without having to wait for the entire response to be received. - -## Customized UI - -`useChat` also provides ways to manage the chat message states via code, show status, and update messages without being triggered by user interactions. - -### Status - -The `useChat` hook returns a `status`. It has the following possible values: - -- `submitted`: The message has been sent to the API and we're awaiting the start of the response stream. -- `streaming`: The response is actively streaming in from the API, receiving chunks of data. -- `ready`: The full response has been received and processed; a new user message can be submitted. -- `error`: An error occurred during the API request, preventing successful completion. - -You can use `status` for e.g. the following purposes: - -- To show a loading spinner while the chatbot is processing the user's message. -- To show a "Stop" button to abort the current message. -- To disable the submit button. - -```tsx filename='app/page.tsx' highlight="6,22-29,36" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; -import { useState } from 'react'; - -export default function Page() { - const { messages, sendMessage, status, stop } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - }), - }); - const [input, setInput] = useState(''); - - return ( - <> - {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, index) => - part.type === 'text' ? {part.text} : null, - )} -
- ))} - - {(status === 'submitted' || status === 'streaming') && ( -
- {status === 'submitted' && } - -
- )} - -
{ - e.preventDefault(); - if (input.trim()) { - sendMessage({ text: input }); - setInput(''); - } - }} - > - setInput(e.target.value)} - disabled={status !== 'ready'} - placeholder="Say something..." - /> - -
- - ); -} -``` - -### Error State - -Similarly, the `error` state reflects the error object thrown during the fetch request. -It can be used to display an error message, disable the submit button, or show a retry button: - - - We recommend showing a generic error message to the user, such as "Something - went wrong." This is a good practice to avoid leaking information from the - server. - - -```tsx file="app/page.tsx" highlight="6,20-27,33" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; -import { useState } from 'react'; - -export default function Chat() { - const { messages, sendMessage, error, regenerate } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - }), - }); - const [input, setInput] = useState(''); - - return ( -
- {messages.map(m => ( -
- {m.role}:{' '} - {m.parts.map((part, index) => - part.type === 'text' ? {part.text} : null, - )} -
- ))} - - {error && ( - <> -
An error occurred.
- - - )} - -
{ - e.preventDefault(); - if (input.trim()) { - sendMessage({ text: input }); - setInput(''); - } - }} - > - setInput(e.target.value)} - disabled={error != null} - /> -
-
- ); -} -``` - -Please also see the [error handling](/docs/ai-sdk-ui/error-handling) guide for more information. - -### Modify messages - -Sometimes, you may want to directly modify some existing messages. For example, a delete button can be added to each message to allow users to remove them from the chat history. - -The `setMessages` function can help you achieve these tasks: - -```tsx -const { messages, setMessages } = useChat() - -const handleDelete = (id) => { - setMessages(messages.filter(message => message.id !== id)) -} - -return <> - {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, index) => ( - part.type === 'text' ? ( - {part.text} - ) : null - ))} - -
- ))} - ... -``` - -You can think of `messages` and `setMessages` as a pair of `state` and `setState` in React. - -### Cancellation and regeneration - -It's also a common use case to abort the response message while it's still streaming back from the AI provider. You can do this by calling the `stop` function returned by the `useChat` hook. - -```tsx -const { stop, status } = useChat() - -return <> - - ... -``` - -When the user clicks the "Stop" button, the fetch request will be aborted. This avoids consuming unnecessary resources and improves the UX of your chatbot application. - -Similarly, you can also request the AI provider to reprocess the last message by calling the `regenerate` function returned by the `useChat` hook: - -```tsx -const { regenerate, status } = useChat(); - -return ( - <> - - ... - -); -``` - -When the user clicks the "Regenerate" button, the AI provider will regenerate the last message and replace the current one correspondingly. - -### Throttling UI Updates - -This feature is currently only available for React. - -By default, the `useChat` hook will trigger a render every time a new chunk is received. -You can throttle the UI updates with the `experimental_throttle` option. - -```tsx filename="page.tsx" highlight="2-3" -const { messages, ... } = useChat({ - // Throttle the messages and data updates to 50ms: - experimental_throttle: 50 -}) -``` - -## Event Callbacks - -`useChat` provides optional event callbacks that you can use to handle different stages of the chatbot lifecycle: - -- `onFinish`: Called when the assistant response is completed. The event includes the response message, all messages, and flags for abort, disconnect, and errors. -- `onError`: Called when an error occurs during the fetch request. -- `onData`: Called whenever a data part is received. - -These callbacks can be used to trigger additional actions, such as logging, analytics, or custom UI updates. - -```tsx -import { UIMessage } from 'ai'; - -const { - /* ... */ -} = useChat({ - onFinish: ({ message, messages, isAbort, isDisconnect, isError }) => { - // use information to e.g. update other UI states - }, - onError: error => { - console.error('An error occurred:', error); - }, - onData: data => { - console.log('Received data part from server:', data); - }, -}); -``` - -It's worth noting that you can abort the processing by throwing an error in the `onData` callback. This will trigger the `onError` callback and stop the message from being appended to the chat UI. This can be useful for handling unexpected responses from the AI provider. - -## Request Configuration - -### Custom headers, body, and credentials - -By default, the `useChat` hook sends a HTTP POST request to the `/api/chat` endpoint with the message list as the request body. You can customize the request in two ways: - -#### Hook-Level Configuration (Applied to all requests) - -You can configure transport-level options that will be applied to all requests made by the hook: - -```tsx -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; - -const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/custom-chat', - headers: { - Authorization: 'your_token', - }, - body: { - user_id: '123', - }, - credentials: 'same-origin', - }), -}); -``` - -#### Dynamic Hook-Level Configuration - -You can also provide functions that return configuration values. This is useful for authentication tokens that need to be refreshed, or for configuration that depends on runtime conditions: - -```tsx -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; - -const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/custom-chat', - headers: () => ({ - Authorization: `Bearer ${getAuthToken()}`, - 'X-User-ID': getCurrentUserId(), - }), - body: () => ({ - sessionId: getCurrentSessionId(), - preferences: getUserPreferences(), - }), - credentials: () => 'include', - }), -}); -``` - - - For component state that changes over time, use `useRef` to store the current - value and reference `ref.current` in your configuration function, or prefer - request-level options (see next section) for better reliability. - - -#### Request-Level Configuration (Recommended) - - - **Recommended**: Use request-level options for better flexibility and control. - Request-level options take precedence over hook-level options and allow you to - customize each request individually. - - -```tsx -// Pass options as the second parameter to sendMessage -sendMessage( - { text: input }, - { - headers: { - Authorization: 'Bearer token123', - 'X-Custom-Header': 'custom-value', - }, - body: { - temperature: 0.7, - max_tokens: 100, - user_id: '123', - }, - metadata: { - userId: 'user123', - sessionId: 'session456', - }, - }, -); -``` - -The request-level options are merged with hook-level options, with request-level options taking precedence. On your server side, you can handle the request with this additional information. - -### Setting custom body fields per request - -You can configure custom `body` fields on a per-request basis using the second parameter of the `sendMessage` function. -This is useful if you want to pass in additional information to your backend that is not part of the message list. - -```tsx filename="app/page.tsx" highlight="20-25" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export default function Chat() { - const { messages, sendMessage } = useChat(); - const [input, setInput] = useState(''); - - return ( -
- {messages.map(m => ( -
- {m.role}:{' '} - {m.parts.map((part, index) => - part.type === 'text' ? {part.text} : null, - )} -
- ))} - -
{ - event.preventDefault(); - if (input.trim()) { - sendMessage( - { text: input }, - { - body: { - customKey: 'customValue', - }, - }, - ); - setInput(''); - } - }} - > - setInput(e.target.value)} /> -
-
- ); -} -``` - -You can retrieve these custom fields on your server side by destructuring the request body: - -```ts filename="app/api/chat/route.ts" highlight="3,4" -export async function POST(req: Request) { - // Extract additional information ("customKey") from the body of the request: - const { messages, customKey }: { messages: UIMessage[]; customKey: string } = - await req.json(); - //... -} -``` - -## Message Metadata - -You can attach custom metadata to messages for tracking information like timestamps, model details, and token usage. - -```ts -// Server: Send metadata about the message -return result.toUIMessageStreamResponse({ - messageMetadata: ({ part }) => { - if (part.type === 'start') { - return { - createdAt: Date.now(), - model: 'gpt-5.1', - }; - } - - if (part.type === 'finish') { - return { - totalTokens: part.totalUsage.totalTokens, - }; - } - }, -}); -``` - -```tsx -// Client: Access metadata via message.metadata -{ - messages.map(message => ( -
- {message.role}:{' '} - {message.metadata?.createdAt && - new Date(message.metadata.createdAt).toLocaleTimeString()} - {/* Render message content */} - {message.parts.map((part, index) => - part.type === 'text' ? {part.text} : null, - )} - {/* Show token count if available */} - {message.metadata?.totalTokens && ( - {message.metadata.totalTokens} tokens - )} -
- )); -} -``` - -For complete examples with type safety and advanced use cases, see the [Message Metadata documentation](/docs/ai-sdk-ui/message-metadata). - -## Transport Configuration - -You can configure custom transport behavior using the `transport` option to customize how messages are sent to your API: - -```tsx filename="app/page.tsx" -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; - -export default function Chat() { - const { messages, sendMessage } = useChat({ - id: 'my-chat', - transport: new DefaultChatTransport({ - prepareSendMessagesRequest: ({ id, messages }) => { - return { - body: { - id, - message: messages[messages.length - 1], - }, - }; - }, - }), - }); - - // ... rest of your component -} -``` - -The corresponding API route receives the custom request format: - -```ts filename="app/api/chat/route.ts" -export async function POST(req: Request) { - const { id, message } = await req.json(); - - // Load existing messages and add the new one - const messages = await loadMessages(id); - messages.push(message); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse(); -} -``` - -### Advanced: Trigger-based routing - -For more complex scenarios like message regeneration, you can use trigger-based routing: - -```tsx filename="app/page.tsx" -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; - -export default function Chat() { - const { messages, sendMessage, regenerate } = useChat({ - id: 'my-chat', - transport: new DefaultChatTransport({ - prepareSendMessagesRequest: ({ id, messages, trigger, messageId }) => { - if (trigger === 'submit-user-message') { - return { - body: { - trigger: 'submit-user-message', - id, - message: messages[messages.length - 1], - messageId, - }, - }; - } else if (trigger === 'regenerate-assistant-message') { - return { - body: { - trigger: 'regenerate-assistant-message', - id, - messageId, - }, - }; - } - throw new Error(`Unsupported trigger: ${trigger}`); - }, - }), - }); - - // ... rest of your component -} -``` - -The corresponding API route would handle different triggers: - -```ts filename="app/api/chat/route.ts" -export async function POST(req: Request) { - const { trigger, id, message, messageId } = await req.json(); - - const chat = await readChat(id); - let messages = chat.messages; - - if (trigger === 'submit-user-message') { - // Handle new user message - messages = [...messages, message]; - } else if (trigger === 'regenerate-assistant-message') { - // Handle message regeneration - remove messages after messageId - const messageIndex = messages.findIndex(m => m.id === messageId); - if (messageIndex !== -1) { - messages = messages.slice(0, messageIndex); - } - } - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse(); -} -``` - -To learn more about building custom transports, refer to the [Transport API documentation](/docs/ai-sdk-ui/transport). - -### Direct Agent Transport - -For scenarios where you want to communicate directly with an Agent without going through HTTP, you can use `DirectChatTransport`. This is useful for: - -- Server-side rendering scenarios -- Testing without network -- Single-process applications - -```tsx filename="app/page.tsx" -import { useChat } from '@ai-sdk/react'; -import { DirectChatTransport, ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are a helpful assistant.', -}); - -export default function Chat() { - const { messages, sendMessage, status } = useChat({ - transport: new DirectChatTransport({ agent }), - }); - - return ( - <> - {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, index) => - part.type === 'text' ? {part.text} : null, - )} -
- ))} - - - - ); -} -``` - -The `DirectChatTransport` invokes the agent's `stream()` method directly, converting UI messages to model messages and streaming the response back as UI message chunks. - -For more details, see the [DirectChatTransport reference](/docs/reference/ai-sdk-ui/direct-chat-transport). - -## Controlling the response stream - -With `streamText`, you can control how error messages and usage information are sent back to the client. - -### Error Messages - -By default, the error message is masked for security reasons. -The default error message is "An error occurred." -You can forward error messages or send your own error message by providing a `getErrorMessage` function: - -```ts filename="app/api/chat/route.ts" highlight="13-27" -import { convertToModelMessages, streamText, UIMessage } from 'ai'; -__PROVIDER_IMPORT__; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse({ - onError: error => { - if (error == null) { - return 'unknown error'; - } - - if (typeof error === 'string') { - return error; - } - - if (error instanceof Error) { - return error.message; - } - - return JSON.stringify(error); - }, - }); -} -``` - -### Usage Information - -Track token consumption and resource usage with [message metadata](/docs/ai-sdk-ui/message-metadata): - -1. Define a custom metadata type with usage fields (optional, for type safety) -2. Attach usage data using `messageMetadata` in your response -3. Display usage metrics in your UI components - -Usage data is attached as metadata to messages and becomes available once the model completes its response generation. - -```ts -import { openai } from '@ai-sdk/openai'; -import { - convertToModelMessages, - streamText, - UIMessage, - type LanguageModelUsage, -} from 'ai'; -__PROVIDER_IMPORT__; - -// Create a new metadata type (optional for type-safety) -type MyMetadata = { - totalUsage: LanguageModelUsage; -}; - -// Create a new custom message type with your own metadata -export type MyUIMessage = UIMessage; - -export async function POST(req: Request) { - const { messages }: { messages: MyUIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse({ - originalMessages: messages, - messageMetadata: ({ part }) => { - // Send total usage when generation is finished - if (part.type === 'finish') { - return { totalUsage: part.totalUsage }; - } - }, - }); -} -``` - -Then, on the client, you can access the message-level metadata. - -```tsx -'use client'; - -import { useChat } from '@ai-sdk/react'; -import type { MyUIMessage } from './api/chat/route'; -import { DefaultChatTransport } from 'ai'; - -export default function Chat() { - // Use custom message type defined on the server (optional for type-safety) - const { messages } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - }), - }); - - return ( -
- {messages.map(m => ( -
- {m.role === 'user' ? 'User: ' : 'AI: '} - {m.parts.map(part => { - if (part.type === 'text') { - return part.text; - } - })} - {/* Render usage via metadata */} - {m.metadata?.totalUsage && ( -
Total usage: {m.metadata?.totalUsage.totalTokens} tokens
- )} -
- ))} -
- ); -} -``` - -You can also access your metadata from the `onFinish` callback of `useChat`: - -```tsx -'use client'; - -import { useChat } from '@ai-sdk/react'; -import type { MyUIMessage } from './api/chat/route'; -import { DefaultChatTransport } from 'ai'; - -export default function Chat() { - // Use custom message type defined on the server (optional for type-safety) - const { messages } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - }), - onFinish: ({ message }) => { - // Access message metadata via onFinish callback - console.log(message.metadata?.totalUsage); - }, - }); -} -``` - -### Text Streams - -`useChat` can handle plain text streams by setting the `streamProtocol` option to `text`: - -```tsx filename="app/page.tsx" highlight="7" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { TextStreamChatTransport } from 'ai'; - -export default function Chat() { - const { messages } = useChat({ - transport: new TextStreamChatTransport({ - api: '/api/chat', - }), - }); - - return <>...; -} -``` - -This configuration also works with other backend servers that stream plain text. -Check out the [stream protocol guide](/docs/ai-sdk-ui/stream-protocol) for more information. - - - When using `TextStreamChatTransport`, tool calls, usage information and finish - reasons are not available. - - -## Reasoning - -Some models such as DeepSeek `deepseek-r1` -and Anthropic `claude-sonnet-4-5-20250929` support reasoning tokens. -These tokens are typically sent before the message content. -You can forward them to the client with the `sendReasoning` option: - -```ts filename="app/api/chat/route.ts" highlight="13" -import { convertToModelMessages, streamText, UIMessage } from 'ai'; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: 'deepseek/deepseek-r1', - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse({ - sendReasoning: true, - }); -} -``` - -On the client side, you can access the reasoning parts of the message object. - -Reasoning parts have a `text` property that contains the reasoning content. - -```tsx filename="app/page.tsx" -messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, index) => { - // text parts: - if (part.type === 'text') { - return
{part.text}
; - } - - // reasoning parts: - if (part.type === 'reasoning') { - return
{part.text}
; - } - })} -
-)); -``` - -## Sources - -Some providers such as [Perplexity](/providers/ai-sdk-providers/perplexity#sources) and -[Google Generative AI](/providers/ai-sdk-providers/google-generative-ai#sources) include sources in the response. - -Currently sources are limited to web pages that ground the response. -You can forward them to the client with the `sendSources` option: - -```ts filename="app/api/chat/route.ts" highlight="13" -import { convertToModelMessages, streamText, UIMessage } from 'ai'; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: 'perplexity/sonar-pro', - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse({ - sendSources: true, - }); -} -``` - -On the client side, you can access source parts of the message object. -There are two types of sources: `source-url` for web pages and `source-document` for documents. -Here is an example that renders both types of sources: - -```tsx filename="app/page.tsx" -messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - - {/* Render URL sources */} - {message.parts - .filter(part => part.type === 'source-url') - .map(part => ( - - [ - - {part.title ?? new URL(part.url).hostname} - - ] - - ))} - - {/* Render document sources */} - {message.parts - .filter(part => part.type === 'source-document') - .map(part => ( - - [{part.title ?? `Document ${part.id}`}] - - ))} -
-)); -``` - -## Image Generation - -Some models such as Google `gemini-2.5-flash-image` support image generation. -When images are generated, they are exposed as files to the client. -On the client side, you can access file parts of the message object -and render them as images. - -```tsx filename="app/page.tsx" -messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, index) => { - if (part.type === 'text') { - return
{part.text}
; - } else if (part.type === 'file' && part.mediaType.startsWith('image/')) { - return Generated image; - } - })} -
-)); -``` - -## Attachments - -The `useChat` hook supports sending file attachments along with a message as well as rendering them on the client. This can be useful for building applications that involve sending images, files, or other media content to the AI provider. - -There are two ways to send files with a message: using a `FileList` object from file inputs or using an array of file objects. - -### FileList - -By using `FileList`, you can send multiple files as attachments along with a message using the file input element. The `useChat` hook will automatically convert them into data URLs and send them to the AI provider. - - - Currently, only `image/*` and `text/*` content types get automatically - converted into [multi-modal content - parts](/docs/foundations/prompts#multi-modal-messages). You will need to - handle other content types manually. - - -```tsx filename="app/page.tsx" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useRef, useState } from 'react'; - -export default function Page() { - const { messages, sendMessage, status } = useChat(); - - const [input, setInput] = useState(''); - const [files, setFiles] = useState(undefined); - const fileInputRef = useRef(null); - - return ( -
-
- {messages.map(message => ( -
-
{`${message.role}: `}
- -
- {message.parts.map((part, index) => { - if (part.type === 'text') { - return {part.text}; - } - - if ( - part.type === 'file' && - part.mediaType?.startsWith('image/') - ) { - return {part.filename}; - } - - return null; - })} -
-
- ))} -
- -
{ - event.preventDefault(); - if (input.trim()) { - sendMessage({ - text: input, - files, - }); - setInput(''); - setFiles(undefined); - - if (fileInputRef.current) { - fileInputRef.current.value = ''; - } - } - }} - > - { - if (event.target.files) { - setFiles(event.target.files); - } - }} - multiple - ref={fileInputRef} - /> - setInput(e.target.value)} - disabled={status !== 'ready'} - /> -
-
- ); -} -``` - -### File Objects - -You can also send files as objects along with a message. This can be useful for sending pre-uploaded files or data URLs. - -```tsx filename="app/page.tsx" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; -import { FileUIPart } from 'ai'; - -export default function Page() { - const { messages, sendMessage, status } = useChat(); - - const [input, setInput] = useState(''); - const [files] = useState([ - { - type: 'file', - filename: 'earth.png', - mediaType: 'image/png', - url: 'https://example.com/earth.png', - }, - { - type: 'file', - filename: 'moon.png', - mediaType: 'image/png', - url: 'data:image/png;base64,iVBORw0KGgo...', - }, - ]); - - return ( -
-
- {messages.map(message => ( -
-
{`${message.role}: `}
- -
- {message.parts.map((part, index) => { - if (part.type === 'text') { - return {part.text}; - } - - if ( - part.type === 'file' && - part.mediaType?.startsWith('image/') - ) { - return {part.filename}; - } - - return null; - })} -
-
- ))} -
- -
{ - event.preventDefault(); - if (input.trim()) { - sendMessage({ - text: input, - files, - }); - setInput(''); - } - }} - > - setInput(e.target.value)} - disabled={status !== 'ready'} - /> -
-
- ); -} -``` - -## Type Inference for Tools - -When working with tools in TypeScript, AI SDK UI provides type inference helpers to ensure type safety for your tool inputs and outputs. - -### InferUITool - -The `InferUITool` type helper infers the input and output types of a single tool for use in UI messages: - -```tsx -import { InferUITool } from 'ai'; -import { z } from 'zod'; - -const weatherTool = { - description: 'Get the current weather', - inputSchema: z.object({ - location: z.string().describe('The city and state'), - }), - execute: async ({ location }) => { - return `The weather in ${location} is sunny.`; - }, -}; - -// Infer the types from the tool -type WeatherUITool = InferUITool; -// This creates a type with: -// { -// input: { location: string }; -// output: string; -// } -``` - -### InferUITools - -The `InferUITools` type helper infers the input and output types of a `ToolSet`: - -```tsx -import { InferUITools, ToolSet } from 'ai'; -import { z } from 'zod'; - -const tools = { - weather: { - description: 'Get the current weather', - inputSchema: z.object({ - location: z.string().describe('The city and state'), - }), - execute: async ({ location }) => { - return `The weather in ${location} is sunny.`; - }, - }, - calculator: { - description: 'Perform basic arithmetic', - inputSchema: z.object({ - operation: z.enum(['add', 'subtract', 'multiply', 'divide']), - a: z.number(), - b: z.number(), - }), - execute: async ({ operation, a, b }) => { - switch (operation) { - case 'add': - return a + b; - case 'subtract': - return a - b; - case 'multiply': - return a * b; - case 'divide': - return a / b; - } - }, - }, -} satisfies ToolSet; - -// Infer the types from the tool set -type MyUITools = InferUITools; -// This creates a type with: -// { -// weather: { input: { location: string }; output: string }; -// calculator: { input: { operation: 'add' | 'subtract' | 'multiply' | 'divide'; a: number; b: number }; output: number }; -// } -``` - -### Using Inferred Types - -You can use these inferred types to create a custom UIMessage type and pass it to various AI SDK UI functions: - -```tsx -import { InferUITools, UIMessage, UIDataTypes } from 'ai'; - -type MyUITools = InferUITools; -type MyUIMessage = UIMessage; -``` - -Pass the custom type to `useChat` or `createUIMessageStream`: - -```tsx -import { useChat } from '@ai-sdk/react'; -import { createUIMessageStream } from 'ai'; -import type { MyUIMessage } from './types'; - -// With useChat -const { messages } = useChat(); - -// With createUIMessageStream -const stream = createUIMessageStream(/* ... */); -``` - -This provides full type safety for tool inputs and outputs on the client and server. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/03-chatbot-message-persistence.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/03-chatbot-message-persistence.mdx deleted file mode 100644 index 9b6186492..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/03-chatbot-message-persistence.mdx +++ /dev/null @@ -1,535 +0,0 @@ ---- -title: Chatbot Message Persistence -description: Learn how to store and load chat messages in a chatbot. ---- - -# Chatbot Message Persistence - -Being able to store and load chat messages is crucial for most AI chatbots. -In this guide, we'll show how to implement message persistence with `useChat` and `streamText`. - - - This guide does not cover authorization, error handling, or other real-world - considerations. It is intended to be a simple example of how to implement - message persistence. - - -## Starting a new chat - -When the user navigates to the chat page without providing a chat ID, -we need to create a new chat and redirect to the chat page with the new chat ID. - -```tsx filename="app/chat/page.tsx" -import { redirect } from 'next/navigation'; -import { createChat } from '@util/chat-store'; - -export default async function Page() { - const id = await createChat(); // create a new chat - redirect(`/chat/${id}`); // redirect to chat page, see below -} -``` - -Our example chat store implementation uses files to store the chat messages. -In a real-world application, you would use a database or a cloud storage service, -and get the chat ID from the database. -That being said, the function interfaces are designed to be easily replaced with other implementations. - -```tsx filename="util/chat-store.ts" -import { generateId } from 'ai'; -import { existsSync, mkdirSync } from 'fs'; -import { writeFile } from 'fs/promises'; -import path from 'path'; - -export async function createChat(): Promise { - const id = generateId(); // generate a unique chat ID - await writeFile(getChatFile(id), '[]'); // create an empty chat file - return id; -} - -function getChatFile(id: string): string { - const chatDir = path.join(process.cwd(), '.chats'); - if (!existsSync(chatDir)) mkdirSync(chatDir, { recursive: true }); - return path.join(chatDir, `${id}.json`); -} -``` - -## Loading an existing chat - -When the user navigates to the chat page with a chat ID, we need to load the chat messages from storage. - -The `loadChat` function in our file-based chat store is implemented as follows: - -```tsx filename="util/chat-store.ts" -import { UIMessage } from 'ai'; -import { readFile } from 'fs/promises'; - -export async function loadChat(id: string): Promise { - return JSON.parse(await readFile(getChatFile(id), 'utf8')); -} - -// ... rest of the file -``` - -## Validating messages on the server - -When processing messages on the server that contain tool calls, custom metadata, or data parts, you should validate them using `validateUIMessages` before sending them to the model. - -### Validation with tools - -When your messages include tool calls, validate them against your tool definitions: - -```tsx filename="app/api/chat/route.ts" highlight="7-25,32-37" -import { - convertToModelMessages, - streamText, - UIMessage, - validateUIMessages, - tool, -} from 'ai'; -import { z } from 'zod'; -import { loadChat, saveChat } from '@util/chat-store'; -import { openai } from '@ai-sdk/openai'; -import { dataPartsSchema, metadataSchema } from '@util/schemas'; - -// Define your tools -const tools = { - weather: tool({ - description: 'Get weather information', - parameters: z.object({ - location: z.string(), - units: z.enum(['celsius', 'fahrenheit']), - }), - execute: async ({ location, units }) => { - /* tool implementation */ - }, - }), - // other tools -}; - -export async function POST(req: Request) { - const { message, id } = await req.json(); - - // Load previous messages from database - const previousMessages = await loadChat(id); - - // Append new message to previousMessages messages - const messages = [...previousMessages, message]; - - // Validate loaded messages against - // tools, data parts schema, and metadata schema - const validatedMessages = await validateUIMessages({ - messages, - tools, // Ensures tool calls in messages match current schemas - dataPartsSchema, - metadataSchema, - }); - - const result = streamText({ - model: 'openai/gpt-5-mini', - messages: convertToModelMessages(validatedMessages), - tools, - }); - - return result.toUIMessageStreamResponse({ - originalMessages: messages, - onFinish: ({ messages }) => { - saveChat({ chatId: id, messages }); - }, - }); -} -``` - -### Handling validation errors - -Handle validation errors gracefully when messages from the database don't match current schemas: - -```tsx filename="app/api/chat/route.ts" highlight="3,10-24" -import { - convertToModelMessages, - streamText, - validateUIMessages, - TypeValidationError, -} from 'ai'; -import { type MyUIMessage } from '@/types'; - -export async function POST(req: Request) { - const { message, id } = await req.json(); - - // Load and validate messages from database - let validatedMessages: MyUIMessage[]; - - try { - const previousMessages = await loadMessagesFromDB(id); - validatedMessages = await validateUIMessages({ - // append the new message to the previous messages: - messages: [...previousMessages, message], - tools, - metadataSchema, - }); - } catch (error) { - if (error instanceof TypeValidationError) { - // Log validation error for monitoring - console.error('Database messages validation failed:', error); - // Could implement message migration or filtering here - // For now, start with empty history - validatedMessages = []; - } else { - throw error; - } - } - - // Continue with validated messages... -} -``` - -## Displaying the chat - -Once messages are loaded from storage, you can display them in your chat UI. Here's how to set up the page component and the chat display: - -```tsx filename="app/chat/[id]/page.tsx" -import { loadChat } from '@util/chat-store'; -import Chat from '@ui/chat'; - -export default async function Page(props: { params: Promise<{ id: string }> }) { - const { id } = await props.params; - const messages = await loadChat(id); - return ; -} -``` - -The chat component uses the `useChat` hook to manage the conversation: - -```tsx filename="ui/chat.tsx" highlight="10-16" -'use client'; - -import { UIMessage, useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; -import { useState } from 'react'; - -export default function Chat({ - id, - initialMessages, -}: { id?: string | undefined; initialMessages?: UIMessage[] } = {}) { - const [input, setInput] = useState(''); - const { sendMessage, messages } = useChat({ - id, // use the provided chat ID - messages: initialMessages, // load initial messages - transport: new DefaultChatTransport({ - api: '/api/chat', - }), - }); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - if (input.trim()) { - sendMessage({ text: input }); - setInput(''); - } - }; - - // simplified rendering code, extend as needed: - return ( -
- {messages.map(m => ( -
- {m.role === 'user' ? 'User: ' : 'AI: '} - {m.parts - .map(part => (part.type === 'text' ? part.text : '')) - .join('')} -
- ))} - -
- setInput(e.target.value)} - placeholder="Type a message..." - /> - -
-
- ); -} -``` - -## Storing messages - -`useChat` sends the chat id and the messages to the backend. - - - The `useChat` message format is different from the `ModelMessage` format. The - `useChat` message format is designed for frontend display, and contains - additional fields such as `id` and `createdAt`. We recommend storing the - messages in the `useChat` message format. - -When loading messages from storage that contain tools, metadata, or custom data -parts, validate them using `validateUIMessages` before processing (see the -[validation section](#validating-messages-from-database) above). - - - -Storing messages is done in the `onFinish` callback of the `toUIMessageStreamResponse` function. -`onFinish` receives the complete messages including the new AI response as `UIMessage[]`. - -```tsx filename="app/api/chat/route.ts" highlight="6,11-17" -import { openai } from '@ai-sdk/openai'; -import { saveChat } from '@util/chat-store'; -import { convertToModelMessages, streamText, UIMessage } from 'ai'; - -export async function POST(req: Request) { - const { messages, chatId }: { messages: UIMessage[]; chatId: string } = - await req.json(); - - const result = streamText({ - model: 'openai/gpt-5-mini', - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse({ - originalMessages: messages, - onFinish: ({ messages }) => { - saveChat({ chatId, messages }); - }, - }); -} -``` - -The actual storage of the messages is done in the `saveChat` function, which in -our file-based chat store is implemented as follows: - -```tsx filename="util/chat-store.ts" -import { UIMessage } from 'ai'; -import { writeFile } from 'fs/promises'; - -export async function saveChat({ - chatId, - messages, -}: { - chatId: string; - messages: UIMessage[]; -}): Promise { - const content = JSON.stringify(messages, null, 2); - await writeFile(getChatFile(chatId), content); -} - -// ... rest of the file -``` - -## Message IDs - -In addition to a chat ID, each message has an ID. -You can use this message ID to e.g. manipulate individual messages. - -### Client-side vs Server-side ID Generation - -By default, message IDs are generated client-side: - -- User message IDs are generated by the `useChat` hook on the client -- AI response message IDs are generated by `streamText` on the server - -For applications without persistence, client-side ID generation works perfectly. -However, **for persistence, you need server-side generated IDs** to ensure consistency across sessions and prevent ID conflicts when messages are stored and retrieved. - -### Setting Up Server-side ID Generation - -When implementing persistence, you have two options for generating server-side IDs: - -1. **Using `generateMessageId` in `toUIMessageStreamResponse`** -2. **Setting IDs in your start message part with `createUIMessageStream`** - -#### Option 1: Using `generateMessageId` in `toUIMessageStreamResponse` - -You can control the ID format by providing ID generators using [`createIdGenerator()`](/docs/reference/ai-sdk-core/create-id-generator): - -```tsx filename="app/api/chat/route.ts" highlight="7-11" -import { createIdGenerator, streamText } from 'ai'; - -export async function POST(req: Request) { - // ... - const result = streamText({ - // ... - }); - - return result.toUIMessageStreamResponse({ - originalMessages: messages, - // Generate consistent server-side IDs for persistence: - generateMessageId: createIdGenerator({ - prefix: 'msg', - size: 16, - }), - onFinish: ({ messages }) => { - saveChat({ chatId, messages }); - }, - }); -} -``` - -#### Option 2: Setting IDs with `createUIMessageStream` - -Alternatively, you can use `createUIMessageStream` to control the message ID by writing a start message part: - -```tsx filename="app/api/chat/route.ts" highlight="8-18" -import { - generateId, - streamText, - createUIMessageStream, - createUIMessageStreamResponse, -} from 'ai'; - -export async function POST(req: Request) { - const { messages, chatId } = await req.json(); - - const stream = createUIMessageStream({ - execute: ({ writer }) => { - // Write start message part with custom ID - writer.write({ - type: 'start', - messageId: generateId(), // Generate server-side ID for persistence - }); - - const result = streamText({ - model: 'openai/gpt-5-mini', - messages: await convertToModelMessages(messages), - }); - - writer.merge(result.toUIMessageStream({ sendStart: false })); // omit start message part - }, - originalMessages: messages, - onFinish: ({ responseMessage }) => { - // save your chat here - }, - }); - - return createUIMessageStreamResponse({ stream }); -} -``` - - - For client-side applications that don't require persistence, you can still customize client-side ID generation: - -```tsx filename="ui/chat.tsx" -import { createIdGenerator } from 'ai'; -import { useChat } from '@ai-sdk/react'; - -const { ... } = useChat({ - generateId: createIdGenerator({ - prefix: 'msgc', - size: 16, - }), - // ... -}); -``` - - - -## Sending only the last message - -Once you have implemented message persistence, you might want to send only the last message to the server. -This reduces the amount of data sent to the server on each request and can improve performance. - -To achieve this, you can provide a `prepareSendMessagesRequest` function to the transport. -This function receives the messages and the chat ID, and returns the request body to be sent to the server. - -```tsx filename="ui/chat.tsx" highlight="7-12" -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; - -const { - // ... -} = useChat({ - // ... - transport: new DefaultChatTransport({ - api: '/api/chat', - // only send the last message to the server: - prepareSendMessagesRequest({ messages, id }) { - return { body: { message: messages[messages.length - 1], id } }; - }, - }), -}); -``` - -On the server, you can then load the previous messages and append the new message to the previous messages. If your messages contain tools, metadata, or custom data parts, you should validate them: - -```tsx filename="app/api/chat/route.ts" highlight="2-11,14-18" -import { convertToModelMessages, UIMessage, validateUIMessages } from 'ai'; -// import your tools and schemas - -export async function POST(req: Request) { - // get the last message from the client: - const { message, id } = await req.json(); - - // load the previous messages from the server: - const previousMessages = await loadChat(id); - - // validate messages if they contain tools, metadata, or data parts: - const validatedMessages = await validateUIMessages({ - // append the new message to the previous messages: - messages: [...previousMessages, message], - tools, // if using tools - metadataSchema, // if using custom metadata - dataSchemas, // if using custom data parts - }); - - const result = streamText({ - // ... - messages: convertToModelMessages(validatedMessages), - }); - - return result.toUIMessageStreamResponse({ - originalMessages: validatedMessages, - onFinish: ({ messages }) => { - saveChat({ chatId: id, messages }); - }, - }); -} -``` - -## Handling client disconnects - -By default, the AI SDK `streamText` function uses backpressure to the language model provider to prevent -the consumption of tokens that are not yet requested. - -However, this means that when the client disconnects, e.g. by closing the browser tab or because of a network issue, -the stream from the LLM will be aborted and the conversation may end up in a broken state. - -Assuming that you have a [storage solution](#storing-messages) in place, you can use the `consumeStream` method to consume the stream on the backend, -and then save the result as usual. -`consumeStream` effectively removes the backpressure, -meaning that the result is stored even when the client has already disconnected. - -```tsx filename="app/api/chat/route.ts" highlight="19-21" -import { convertToModelMessages, streamText, UIMessage } from 'ai'; -import { saveChat } from '@util/chat-store'; - -export async function POST(req: Request) { - const { messages, chatId }: { messages: UIMessage[]; chatId: string } = - await req.json(); - - const result = streamText({ - model, - messages: await convertToModelMessages(messages), - }); - - // consume the stream to ensure it runs to completion & triggers onFinish - // even when the client response is aborted: - result.consumeStream(); // no await - - return result.toUIMessageStreamResponse({ - originalMessages: messages, - onFinish: ({ messages }) => { - saveChat({ chatId, messages }); - }, - }); -} -``` - -When the client reloads the page after a disconnect, the chat will be restored from the storage solution. - - - In production applications, you would also track the state of the request (in - progress, complete) in your stored messages and use it on the client to cover - the case where the client reloads the page after a disconnection, but the - streaming is not yet complete. - - -For more robust handling of disconnects, you may want to add resumability on disconnects. Check out the [Chatbot Resume Streams](/docs/ai-sdk-ui/chatbot-resume-streams) documentation to learn more. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/03-chatbot-resume-streams.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/03-chatbot-resume-streams.mdx deleted file mode 100644 index e2d981236..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/03-chatbot-resume-streams.mdx +++ /dev/null @@ -1,263 +0,0 @@ ---- -title: Chatbot Resume Streams -description: Learn how to resume chatbot streams after client disconnects. ---- - -# Chatbot Resume Streams - -`useChat` supports resuming ongoing streams after page reloads. Use this feature to build applications with long-running generations. - - - Stream resumption is not compatible with abort functionality. Closing a tab or - refreshing the page triggers an abort signal that will break the resumption - mechanism. Do not use `resume: true` if you need abort functionality in your - application. See - [troubleshooting](/docs/troubleshooting/abort-breaks-resumable-streams) for - more details. - - -## How stream resumption works - -Stream resumption requires persistence for messages and active streams in your application. The AI SDK provides tools to connect to storage, but you need to set up the storage yourself. - -**The AI SDK provides:** - -- A `resume` option in `useChat` that automatically reconnects to active streams -- Access to the outgoing stream through the `consumeSseStream` callback -- Automatic HTTP requests to your resume endpoints - -**You build:** - -- Storage to track which stream belongs to each chat -- Redis to store the UIMessage stream -- Two API endpoints: POST to create streams, GET to resume them -- Integration with [`resumable-stream`](https://www.npmjs.com/package/resumable-stream) to manage Redis storage - -## Prerequisites - -To implement resumable streams in your chat application, you need: - -1. **The `resumable-stream` package** - Handles the publisher/subscriber mechanism for streams -2. **A Redis instance** - Stores stream data (e.g. [Redis through Vercel](https://vercel.com/marketplace/redis)) -3. **A persistence layer** - Tracks which stream ID is active for each chat (e.g. database) - -## Implementation - -### 1. Client-side: Enable stream resumption - -Use the `resume` option in the `useChat` hook to enable stream resumption. When `resume` is true, the hook automatically attempts to reconnect to any active stream for the chat on mount: - -```tsx filename="app/chat/[chatId]/chat.tsx" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport, type UIMessage } from 'ai'; - -export function Chat({ - chatData, - resume = false, -}: { - chatData: { id: string; messages: UIMessage[] }; - resume?: boolean; -}) { - const { messages, sendMessage, status } = useChat({ - id: chatData.id, - messages: chatData.messages, - resume, // Enable automatic stream resumption - transport: new DefaultChatTransport({ - // You must send the id of the chat - prepareSendMessagesRequest: ({ id, messages }) => { - return { - body: { - id, - message: messages[messages.length - 1], - }, - }; - }, - }), - }); - - return
{/* Your chat UI */}
; -} -``` - - - You must send the chat ID with each request (see - `prepareSendMessagesRequest`). - - -When you enable `resume`, the `useChat` hook makes a `GET` request to `/api/chat/[id]/stream` on mount to check for and resume any active streams. - -Let's start by creating the POST handler to create the resumable stream. - -### 2. Create the POST handler - -The POST handler creates resumable streams using the `consumeSseStream` callback: - -```ts filename="app/api/chat/route.ts" -import { openai } from '@ai-sdk/openai'; -import { readChat, saveChat } from '@util/chat-store'; -import { - convertToModelMessages, - generateId, - streamText, - type UIMessage, -} from 'ai'; -import { after } from 'next/server'; -import { createResumableStreamContext } from 'resumable-stream'; - -export async function POST(req: Request) { - const { - message, - id, - }: { - message: UIMessage | undefined; - id: string; - } = await req.json(); - - const chat = await readChat(id); - let messages = chat.messages; - - messages = [...messages, message!]; - - // Clear any previous active stream and save the user message - saveChat({ id, messages, activeStreamId: null }); - - const result = streamText({ - model: 'openai/gpt-5-mini', - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse({ - originalMessages: messages, - generateMessageId: generateId, - onFinish: ({ messages }) => { - // Clear the active stream when finished - saveChat({ id, messages, activeStreamId: null }); - }, - async consumeSseStream({ stream }) { - const streamId = generateId(); - - // Create a resumable stream from the SSE stream - const streamContext = createResumableStreamContext({ waitUntil: after }); - await streamContext.createNewResumableStream(streamId, () => stream); - - // Update the chat with the active stream ID - saveChat({ id, activeStreamId: streamId }); - }, - }); -} -``` - -### 3. Implement the GET handler - -Create a GET handler at `/api/chat/[id]/stream` that: - -1. Reads the chat ID from the route params -2. Loads the chat data to check for an active stream -3. Returns 204 (No Content) if no stream is active -4. Resumes the existing stream if one is found - -```ts filename="app/api/chat/[id]/stream/route.ts" -import { readChat } from '@util/chat-store'; -import { UI_MESSAGE_STREAM_HEADERS } from 'ai'; -import { after } from 'next/server'; -import { createResumableStreamContext } from 'resumable-stream'; - -export async function GET( - _: Request, - { params }: { params: Promise<{ id: string }> }, -) { - const { id } = await params; - - const chat = await readChat(id); - - if (chat.activeStreamId == null) { - // no content response when there is no active stream - return new Response(null, { status: 204 }); - } - - const streamContext = createResumableStreamContext({ - waitUntil: after, - }); - - return new Response( - await streamContext.resumeExistingStream(chat.activeStreamId), - { headers: UI_MESSAGE_STREAM_HEADERS }, - ); -} -``` - - - The `after` function from Next.js allows work to continue after the response - has been sent. This ensures that the resumable stream persists in Redis even - after the initial response is returned to the client, enabling reconnection - later. - - -## How it works - -### Request lifecycle - -![Diagram showing the architecture and lifecycle of resumable stream requests](https://e742qlubrjnjqpp0.public.blob.vercel-storage.com/resume-stream-diagram.png) - -The diagram above shows the complete lifecycle of a resumable stream: - -1. **Stream creation**: When you send a new message, the POST handler uses `streamText` to generate the response. The `consumeSseStream` callback creates a resumable stream with a unique ID and stores it in Redis through the `resumable-stream` package -2. **Stream tracking**: Your persistence layer saves the `activeStreamId` in the chat data -3. **Client reconnection**: When the client reconnects (page reload), the `resume` option triggers a GET request to `/api/chat/[id]/stream` -4. **Stream recovery**: The GET handler checks for an `activeStreamId` and uses `resumeExistingStream` to reconnect. If no active stream exists, it returns a 204 (No Content) response -5. **Completion cleanup**: When the stream finishes, the `onFinish` callback clears the `activeStreamId` by setting it to `null` - -## Customize the resume endpoint - -By default, the `useChat` hook makes a GET request to `/api/chat/[id]/stream` when resuming. Customize this endpoint, credentials, and headers, using the `prepareReconnectToStreamRequest` option in `DefaultChatTransport`: - -```tsx filename="app/chat/[chatId]/chat.tsx" -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; - -export function Chat({ chatData, resume }) { - const { messages, sendMessage } = useChat({ - id: chatData.id, - messages: chatData.messages, - resume, - transport: new DefaultChatTransport({ - // Customize reconnect settings (optional) - prepareReconnectToStreamRequest: ({ id }) => { - return { - api: `/api/chat/${id}/stream`, // Default pattern - // Or use a different pattern: - // api: `/api/streams/${id}/resume`, - // api: `/api/resume-chat?id=${id}`, - credentials: 'include', // Include cookies/auth - headers: { - Authorization: 'Bearer token', - 'X-Custom-Header': 'value', - }, - }; - }, - }), - }); - - return
{/* Your chat UI */}
; -} -``` - -This lets you: - -- Match your existing API route structure -- Add query parameters or custom paths -- Integrate with different backend architectures - -## Important considerations - -- **Incompatibility with abort**: Stream resumption is not compatible with abort functionality. Closing a tab or refreshing the page triggers an abort signal that will break the resumption mechanism. Do not use `resume: true` if you need abort functionality in your application -- **Stream expiration**: Streams in Redis expire after a set time (configurable in the `resumable-stream` package) -- **Multiple clients**: Multiple clients can connect to the same stream simultaneously -- **Error handling**: When no active stream exists, the GET handler returns a 204 (No Content) status code -- **Security**: Ensure proper authentication and authorization for both creating and resuming streams -- **Race conditions**: Clear the `activeStreamId` when starting a new stream to prevent resuming outdated streams - -
- diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/03-chatbot-tool-usage.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/03-chatbot-tool-usage.mdx deleted file mode 100644 index 3c06b2e4a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/03-chatbot-tool-usage.mdx +++ /dev/null @@ -1,682 +0,0 @@ ---- -title: Chatbot Tool Usage -description: Learn how to use tools with the useChat hook. ---- - -# Chatbot Tool Usage - -With [`useChat`](/docs/reference/ai-sdk-ui/use-chat) and [`streamText`](/docs/reference/ai-sdk-core/stream-text), you can use tools in your chatbot application. -The AI SDK supports three types of tools in this context: - -1. Automatically executed server-side tools -2. Automatically executed client-side tools -3. Tools that require user interaction, such as confirmation dialogs - -The flow is as follows: - -1. The user enters a message in the chat UI. -1. The message is sent to the API route. -1. In your server side route, the language model generates tool calls during the `streamText` call. -1. All tool calls are forwarded to the client. -1. Server-side tools are executed using their `execute` method and their results are forwarded to the client. -1. Client-side tools that should be automatically executed are handled with the `onToolCall` callback. - You must call `addToolOutput` to provide the tool result. -1. Client-side tool that require user interactions can be displayed in the UI. - The tool calls and results are available as tool invocation parts in the `parts` property of the last assistant message. -1. When the user interaction is done, `addToolOutput` can be used to add the tool result to the chat. -1. The chat can be configured to automatically submit when all tool results are available using `sendAutomaticallyWhen`. - This triggers another iteration of this flow. - -The tool calls and tool executions are integrated into the assistant message as typed tool parts. -A tool part is at first a tool call, and then it becomes a tool result when the tool is executed. -The tool result contains all information about the tool call as well as the result of the tool execution. - - - Tool result submission can be configured using the `sendAutomaticallyWhen` - option. You can use the `lastAssistantMessageIsCompleteWithToolCalls` helper - to automatically submit when all tool results are available. This simplifies - the client-side code while still allowing full control when needed. - - -## Example - -In this example, we'll use three tools: - -- `getWeatherInformation`: An automatically executed server-side tool that returns the weather in a given city. -- `askForConfirmation`: A user-interaction client-side tool that asks the user for confirmation. -- `getLocation`: An automatically executed client-side tool that returns a random city. - -### API route - -```tsx filename='app/api/chat/route.ts' -import { convertToModelMessages, streamText, UIMessage } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -// Allow streaming responses up to 30 seconds -export const maxDuration = 30; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - tools: { - // server-side tool with execute function: - getWeatherInformation: { - description: 'show the weather in a given city to the user', - inputSchema: z.object({ city: z.string() }), - execute: async ({}: { city: string }) => { - const weatherOptions = ['sunny', 'cloudy', 'rainy', 'snowy', 'windy']; - return weatherOptions[ - Math.floor(Math.random() * weatherOptions.length) - ]; - }, - }, - // client-side tool that starts user interaction: - askForConfirmation: { - description: 'Ask the user for confirmation.', - inputSchema: z.object({ - message: z.string().describe('The message to ask for confirmation.'), - }), - }, - // client-side tool that is automatically executed on the client: - getLocation: { - description: - 'Get the user location. Always ask for confirmation before using this tool.', - inputSchema: z.object({}), - }, - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -### Client-side page - -The client-side page uses the `useChat` hook to create a chatbot application with real-time message streaming. -Tool calls are displayed in the chat UI as typed tool parts. -Please make sure to render the messages using the `parts` property of the message. - -There are three things worth mentioning: - -1. The [`onToolCall`](/docs/reference/ai-sdk-ui/use-chat#on-tool-call) callback is used to handle client-side tools that should be automatically executed. - In this example, the `getLocation` tool is a client-side tool that returns a random city. - You call `addToolOutput` to provide the result (without `await` to avoid potential deadlocks). - - - Always check `if (toolCall.dynamic)` first in your `onToolCall` handler. - Without this check, TypeScript will throw an error like: `Type 'string' is - not assignable to type '"toolName1" | "toolName2"'` when you try to use - `toolCall.toolName` in `addToolOutput`. - - -2. The [`sendAutomaticallyWhen`](/docs/reference/ai-sdk-ui/use-chat#send-automatically-when) option with `lastAssistantMessageIsCompleteWithToolCalls` helper automatically submits when all tool results are available. - -3. The `parts` array of assistant messages contains tool parts with typed names like `tool-askForConfirmation`. - The client-side tool `askForConfirmation` is displayed in the UI. - It asks the user for confirmation and displays the result once the user confirms or denies the execution. - The result is added to the chat using `addToolOutput` with the `tool` parameter for type safety. - -```tsx filename='app/page.tsx' highlight="2,6,10,14-20" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { - DefaultChatTransport, - lastAssistantMessageIsCompleteWithToolCalls, -} from 'ai'; -import { useState } from 'react'; - -export default function Chat() { - const { messages, sendMessage, addToolOutput } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - }), - - sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls, - - // run client-side tools that are automatically executed: - async onToolCall({ toolCall }) { - // Check if it's a dynamic tool first for proper type narrowing - if (toolCall.dynamic) { - return; - } - - if (toolCall.toolName === 'getLocation') { - const cities = ['New York', 'Los Angeles', 'Chicago', 'San Francisco']; - - // No await - avoids potential deadlocks - addToolOutput({ - tool: 'getLocation', - toolCallId: toolCall.toolCallId, - output: cities[Math.floor(Math.random() * cities.length)], - }); - } - }, - }); - const [input, setInput] = useState(''); - - return ( - <> - {messages?.map(message => ( -
- {`${message.role}: `} - {message.parts.map(part => { - switch (part.type) { - // render text parts as simple text: - case 'text': - return part.text; - - // for tool parts, use the typed tool part names: - case 'tool-askForConfirmation': { - const callId = part.toolCallId; - - switch (part.state) { - case 'input-streaming': - return ( -
Loading confirmation request...
- ); - case 'input-available': - return ( -
- {part.input.message} -
- - -
-
- ); - case 'output-available': - return ( -
- Location access allowed: {part.output} -
- ); - case 'output-error': - return
Error: {part.errorText}
; - } - break; - } - - case 'tool-getLocation': { - const callId = part.toolCallId; - - switch (part.state) { - case 'input-streaming': - return ( -
Preparing location request...
- ); - case 'input-available': - return
Getting location...
; - case 'output-available': - return
Location: {part.output}
; - case 'output-error': - return ( -
- Error getting location: {part.errorText} -
- ); - } - break; - } - - case 'tool-getWeatherInformation': { - const callId = part.toolCallId; - - switch (part.state) { - // example of pre-rendering streaming tool inputs: - case 'input-streaming': - return ( -
{JSON.stringify(part, null, 2)}
- ); - case 'input-available': - return ( -
- Getting weather information for {part.input.city}... -
- ); - case 'output-available': - return ( -
- Weather in {part.input.city}: {part.output} -
- ); - case 'output-error': - return ( -
- Error getting weather for {part.input.city}:{' '} - {part.errorText} -
- ); - } - break; - } - } - })} -
-
- ))} - -
{ - e.preventDefault(); - if (input.trim()) { - sendMessage({ text: input }); - setInput(''); - } - }} - > - setInput(e.target.value)} /> -
- - ); -} -``` - -### Error handling - -Sometimes an error may occur during client-side tool execution. Use the `addToolOutput` method with a `state` of `output-error` and `errorText` value instead of `output` record the error. - -```tsx filename='app/page.tsx' highlight="19,36-41" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { - DefaultChatTransport, - lastAssistantMessageIsCompleteWithToolCalls, -} from 'ai'; -import { useState } from 'react'; - -export default function Chat() { - const { messages, sendMessage, addToolOutput } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - }), - - sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls, - - // run client-side tools that are automatically executed: - async onToolCall({ toolCall }) { - // Check if it's a dynamic tool first for proper type narrowing - if (toolCall.dynamic) { - return; - } - - if (toolCall.toolName === 'getWeatherInformation') { - try { - const weather = await getWeatherInformation(toolCall.input); - - // No await - avoids potential deadlocks - addToolOutput({ - tool: 'getWeatherInformation', - toolCallId: toolCall.toolCallId, - output: weather, - }); - } catch (err) { - addToolOutput({ - tool: 'getWeatherInformation', - toolCallId: toolCall.toolCallId, - state: 'output-error', - errorText: 'Unable to get the weather information', - }); - } - } - }, - }); -} -``` - -## Tool Execution Approval - -Tool execution approval lets you require user confirmation before a server-side tool runs. Unlike [client-side tools](#example) that execute in the browser, tools with approval still execute on the server—but only after the user approves. - -Use tool execution approval when you want to: - -- Confirm sensitive operations (payments, deletions, external API calls) -- Let users review tool inputs before execution -- Add human oversight to automated workflows - -For tools that need to run in the browser (updating UI state, accessing browser APIs), use client-side tools instead. - -### Server Setup - -Enable approval by setting `needsApproval` on your tool. See [Tool Execution Approval](/docs/ai-sdk-core/tools-and-tool-calling#tool-execution-approval) for configuration options including dynamic approval based on input. - -```tsx filename='app/api/chat/route.ts' -import { streamText, tool } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -export async function POST(req: Request) { - const { messages } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages, - tools: { - getWeather: tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ - city: z.string(), - }), - needsApproval: true, - execute: async ({ city }) => { - const weather = await fetchWeather(city); - return weather; - }, - }), - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -### Client-Side Approval UI - -When a tool requires approval, the tool part state is `approval-requested`. Use `addToolApprovalResponse` to approve or deny: - -```tsx filename='app/page.tsx' -'use client'; - -import { useChat } from '@ai-sdk/react'; - -export default function Chat() { - const { messages, addToolApprovalResponse } = useChat(); - - return ( - <> - {messages.map(message => ( -
- {message.parts.map(part => { - if (part.type === 'tool-getWeather') { - switch (part.state) { - case 'approval-requested': - return ( -
-

Get weather for {part.input.city}?

- - -
- ); - case 'output-available': - return ( -
- Weather in {part.input.city}: {part.output} -
- ); - } - } - // Handle other part types... - })} -
- ))} - - ); -} -``` - -### Auto-Submit After Approval - - - If nothing happens after you approve a tool execution, make sure you either - call `sendMessage` manually or configure `sendAutomaticallyWhen` on the - `useChat` hook. - - -Use `lastAssistantMessageIsCompleteWithApprovalResponses` to automatically continue the conversation after approvals: - -```tsx -import { useChat } from '@ai-sdk/react'; -import { lastAssistantMessageIsCompleteWithApprovalResponses } from 'ai'; - -const { messages, addToolApprovalResponse } = useChat({ - sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses, -}); -``` - -## Dynamic Tools - -When using dynamic tools (tools with unknown types at compile time), the UI parts use a generic `dynamic-tool` type instead of specific tool types: - -```tsx filename='app/page.tsx' -{ - message.parts.map((part, index) => { - switch (part.type) { - // Static tools with specific (`tool-${toolName}`) types - case 'tool-getWeatherInformation': - return ; - - // Dynamic tools use generic `dynamic-tool` type - case 'dynamic-tool': - return ( -
-

Tool: {part.toolName}

- {part.state === 'input-streaming' && ( -
{JSON.stringify(part.input, null, 2)}
- )} - {part.state === 'output-available' && ( -
{JSON.stringify(part.output, null, 2)}
- )} - {part.state === 'output-error' && ( -
Error: {part.errorText}
- )} -
- ); - } - }); -} -``` - -Dynamic tools are useful when integrating with: - -- MCP (Model Context Protocol) tools without schemas -- User-defined functions loaded at runtime -- External tool providers - -## Tool call streaming - -Tool call streaming is **enabled by default** in AI SDK 5.0, allowing you to stream tool calls while they are being generated. This provides a better user experience by showing tool inputs as they are generated in real-time. - -```tsx filename='app/api/chat/route.ts' -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - // toolCallStreaming is enabled by default in v5 - // ... - }); - - return result.toUIMessageStreamResponse(); -} -``` - -With tool call streaming enabled, partial tool calls are streamed as part of the data stream. -They are available through the `useChat` hook. -The typed tool parts of assistant messages will also contain partial tool calls. -You can use the `state` property of the tool part to render the correct UI. - -```tsx filename='app/page.tsx' highlight="9,10" -export default function Chat() { - // ... - return ( - <> - {messages?.map(message => ( -
- {message.parts.map(part => { - switch (part.type) { - case 'tool-askForConfirmation': - case 'tool-getLocation': - case 'tool-getWeatherInformation': - switch (part.state) { - case 'input-streaming': - return
{JSON.stringify(part.input, null, 2)}
; - case 'input-available': - return
{JSON.stringify(part.input, null, 2)}
; - case 'output-available': - return
{JSON.stringify(part.output, null, 2)}
; - case 'output-error': - return
Error: {part.errorText}
; - } - } - })} -
- ))} - - ); -} -``` - -## Step start parts - -When you are using multi-step tool calls, the AI SDK will add step start parts to the assistant messages. -If you want to display boundaries between tool calls, you can use the `step-start` parts as follows: - -```tsx filename='app/page.tsx' -// ... -// where you render the message parts: -message.parts.map((part, index) => { - switch (part.type) { - case 'step-start': - // show step boundaries as horizontal lines: - return index > 0 ? ( -
-
-
- ) : null; - case 'text': - // ... - case 'tool-askForConfirmation': - case 'tool-getLocation': - case 'tool-getWeatherInformation': - // ... - } -}); -// ... -``` - -## Server-side Multi-Step Calls - -You can also use multi-step calls on the server-side with `streamText`. -This works when all invoked tools have an `execute` function on the server side. - -```tsx filename='app/api/chat/route.ts' highlight="15-21,24" -import { convertToModelMessages, streamText, UIMessage, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - tools: { - getWeatherInformation: { - description: 'show the weather in a given city to the user', - inputSchema: z.object({ city: z.string() }), - // tool has execute function: - execute: async ({}: { city: string }) => { - const weatherOptions = ['sunny', 'cloudy', 'rainy', 'snowy', 'windy']; - return weatherOptions[ - Math.floor(Math.random() * weatherOptions.length) - ]; - }, - }, - }, - stopWhen: stepCountIs(5), - }); - - return result.toUIMessageStreamResponse(); -} -``` - -## Errors - -Language models can make errors when calling tools. -By default, these errors are masked for security reasons, and show up as "An error occurred" in the UI. - -To surface the errors, you can use the `onError` function when calling `toUIMessageResponse`. - -```tsx -export function errorHandler(error: unknown) { - if (error == null) { - return 'unknown error'; - } - - if (typeof error === 'string') { - return error; - } - - if (error instanceof Error) { - return error.message; - } - - return JSON.stringify(error); -} -``` - -```tsx -const result = streamText({ - // ... -}); - -return result.toUIMessageStreamResponse({ - onError: errorHandler, -}); -``` - -In case you are using `createUIMessageResponse`, you can use the `onError` function when calling `toUIMessageResponse`: - -```tsx -const response = createUIMessageResponse({ - // ... - async execute(dataStream) { - // ... - }, - onError: error => `Custom error: ${error.message}`, -}); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/04-generative-user-interfaces.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/04-generative-user-interfaces.mdx deleted file mode 100644 index 33355da27..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/04-generative-user-interfaces.mdx +++ /dev/null @@ -1,389 +0,0 @@ ---- -title: Generative User Interfaces -description: Learn how to build Generative UI with AI SDK UI. ---- - -# Generative User Interfaces - -Generative user interfaces (generative UI) is the process of allowing a large language model (LLM) to go beyond text and "generate UI". This creates a more engaging and AI-native experience for users. - - - -At the core of generative UI are [ tools ](/docs/ai-sdk-core/tools-and-tool-calling), which are functions you provide to the model to perform specialized tasks like getting the weather in a location. The model can decide when and how to use these tools based on the context of the conversation. - -Generative UI is the process of connecting the results of a tool call to a React component. Here's how it works: - -1. You provide the model with a prompt or conversation history, along with a set of tools. -2. Based on the context, the model may decide to call a tool. -3. If a tool is called, it will execute and return data. -4. This data can then be passed to a React component for rendering. - -By passing the tool results to React components, you can create a generative UI experience that's more engaging and adaptive to your needs. - -## Build a Generative UI Chat Interface - -Let's create a chat interface that handles text-based conversations and incorporates dynamic UI elements based on model responses. - -### Basic Chat Implementation - -Start with a basic chat implementation using the `useChat` hook: - -```tsx filename="app/page.tsx" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export default function Page() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }; - - return ( -
- {messages.map(message => ( -
-
{message.role === 'user' ? 'User: ' : 'AI: '}
-
- {message.parts.map((part, index) => { - if (part.type === 'text') { - return {part.text}; - } - return null; - })} -
-
- ))} - -
- setInput(e.target.value)} - placeholder="Type a message..." - /> - -
-
- ); -} -``` - -To handle the chat requests and model responses, set up an API route: - -```ts filename="app/api/chat/route.ts" -import { streamText, convertToModelMessages, UIMessage, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; - -export async function POST(request: Request) { - const { messages }: { messages: UIMessage[] } = await request.json(); - - const result = streamText({ - model: __MODEL__, - system: 'You are a friendly assistant!', - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - }); - - return result.toUIMessageStreamResponse(); -} -``` - -This API route uses the `streamText` function to process chat messages and stream the model's responses back to the client. - -### Create a Tool - -Before enhancing your chat interface with dynamic UI elements, you need to create a tool and corresponding React component. A tool will allow the model to perform a specific action, such as fetching weather information. - -Create a new file called `ai/tools.ts` with the following content: - -```ts filename="ai/tools.ts" -import { tool as createTool } from 'ai'; -import { z } from 'zod'; - -export const weatherTool = createTool({ - description: 'Display the weather for a location', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async function ({ location }) { - await new Promise(resolve => setTimeout(resolve, 2000)); - return { weather: 'Sunny', temperature: 75, location }; - }, -}); - -export const tools = { - displayWeather: weatherTool, -}; -``` - -In this file, you've created a tool called `weatherTool`. This tool simulates fetching weather information for a given location. This tool will return simulated data after a 2-second delay. In a real-world application, you would replace this simulation with an actual API call to a weather service. - -### Update the API Route - -Update the API route to include the tool you've defined: - -```ts filename="app/api/chat/route.ts" highlight="3,8,14" -import { streamText, convertToModelMessages, UIMessage, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; -import { tools } from '@/ai/tools'; - -export async function POST(request: Request) { - const { messages }: { messages: UIMessage[] } = await request.json(); - - const result = streamText({ - model: __MODEL__, - system: 'You are a friendly assistant!', - messages: await convertToModelMessages(messages), - stopWhen: stepCountIs(5), - tools, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -Now that you've defined the tool and added it to your `streamText` call, let's build a React component to display the weather information it returns. - -### Create UI Components - -Create a new file called `components/weather.tsx`: - -```tsx filename="components/weather.tsx" -type WeatherProps = { - temperature: number; - weather: string; - location: string; -}; - -export const Weather = ({ temperature, weather, location }: WeatherProps) => { - return ( -
-

Current Weather for {location}

-

Condition: {weather}

-

Temperature: {temperature}°C

-
- ); -}; -``` - -This component will display the weather information for a given location. It takes three props: `temperature`, `weather`, and `location` (exactly what the `weatherTool` returns). - -### Render the Weather Component - -Now that you have your tool and corresponding React component, let's integrate them into your chat interface. You'll render the Weather component when the model calls the weather tool. - -To check if the model has called a tool, you can check the `parts` array of the UIMessage object for tool-specific parts. In AI SDK 5.0, tool parts use typed naming: `tool-${toolName}` instead of generic types. - -Update your `page.tsx` file: - -```tsx filename="app/page.tsx" highlight="4,9,14-15,19-46" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; -import { Weather } from '@/components/weather'; - -export default function Page() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }; - - return ( -
- {messages.map(message => ( -
-
{message.role === 'user' ? 'User: ' : 'AI: '}
-
- {message.parts.map((part, index) => { - if (part.type === 'text') { - return {part.text}; - } - - if (part.type === 'tool-displayWeather') { - switch (part.state) { - case 'input-available': - return
Loading weather...
; - case 'output-available': - return ( -
- -
- ); - case 'output-error': - return
Error: {part.errorText}
; - default: - return null; - } - } - - return null; - })} -
-
- ))} - -
- setInput(e.target.value)} - placeholder="Type a message..." - /> - -
-
- ); -} -``` - -In this updated code snippet, you: - -1. Use manual input state management with `useState` instead of the built-in `input` and `handleInputChange`. -2. Use `sendMessage` instead of `handleSubmit` to send messages. -3. Check the `parts` array of each message for different content types. -4. Handle tool parts with type `tool-displayWeather` and their different states (`input-available`, `output-available`, `output-error`). - -This approach allows you to dynamically render UI components based on the model's responses, creating a more interactive and context-aware chat experience. - -## Expanding Your Generative UI Application - -You can enhance your chat application by adding more tools and components, creating a richer and more versatile user experience. Here's how you can expand your application: - -### Adding More Tools - -To add more tools, simply define them in your `ai/tools.ts` file: - -```ts -// Add a new stock tool -export const stockTool = createTool({ - description: 'Get price for a stock', - inputSchema: z.object({ - symbol: z.string().describe('The stock symbol to get the price for'), - }), - execute: async function ({ symbol }) { - // Simulated API call - await new Promise(resolve => setTimeout(resolve, 2000)); - return { symbol, price: 100 }; - }, -}); - -// Update the tools object -export const tools = { - displayWeather: weatherTool, - getStockPrice: stockTool, -}; -``` - -Now, create a new file called `components/stock.tsx`: - -```tsx -type StockProps = { - price: number; - symbol: string; -}; - -export const Stock = ({ price, symbol }: StockProps) => { - return ( -
-

Stock Information

-

Symbol: {symbol}

-

Price: ${price}

-
- ); -}; -``` - -Finally, update your `page.tsx` file to include the new Stock component: - -```tsx -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; -import { Weather } from '@/components/weather'; -import { Stock } from '@/components/stock'; - -export default function Page() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }; - - return ( -
- {messages.map(message => ( -
-
{message.role}
-
- {message.parts.map((part, index) => { - if (part.type === 'text') { - return {part.text}; - } - - if (part.type === 'tool-displayWeather') { - switch (part.state) { - case 'input-available': - return
Loading weather...
; - case 'output-available': - return ( -
- -
- ); - case 'output-error': - return
Error: {part.errorText}
; - default: - return null; - } - } - - if (part.type === 'tool-getStockPrice') { - switch (part.state) { - case 'input-available': - return
Loading stock price...
; - case 'output-available': - return ( -
- -
- ); - case 'output-error': - return
Error: {part.errorText}
; - default: - return null; - } - } - - return null; - })} -
-
- ))} - -
- setInput(e.target.value)} - /> - -
-
- ); -} -``` - -By following this pattern, you can continue to add more tools and components, expanding the capabilities of your Generative UI application. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/05-completion.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/05-completion.mdx deleted file mode 100644 index 808e8fbbc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/05-completion.mdx +++ /dev/null @@ -1,181 +0,0 @@ ---- -title: Completion -description: Learn how to use the useCompletion hook. ---- - -# Completion - -The `useCompletion` hook allows you to create a user interface to handle text completions in your application. It enables the streaming of text completions from your AI provider, manages the state for chat input, and updates the UI automatically as new messages are received. - - - The `useCompletion` hook is now part of the `@ai-sdk/react` package. - - -In this guide, you will learn how to use the `useCompletion` hook in your application to generate text completions and stream them in real-time to your users. - -## Example - -```tsx filename='app/page.tsx' -'use client'; - -import { useCompletion } from '@ai-sdk/react'; - -export default function Page() { - const { completion, input, handleInputChange, handleSubmit } = useCompletion({ - api: '/api/completion', - }); - - return ( -
- - -
{completion}
-
- ); -} -``` - -```ts filename='app/api/completion/route.ts' -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -// Allow streaming responses up to 30 seconds -export const maxDuration = 30; - -export async function POST(req: Request) { - const { prompt }: { prompt: string } = await req.json(); - - const result = streamText({ - model: __MODEL__, - prompt, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -In the `Page` component, the `useCompletion` hook will request to your AI provider endpoint whenever the user submits a message. The completion is then streamed back in real-time and displayed in the UI. - -This enables a seamless text completion experience where the user can see the AI response as soon as it is available, without having to wait for the entire response to be received. - -## Customized UI - -`useCompletion` also provides ways to manage the prompt via code, show loading and error states, and update messages without being triggered by user interactions. - -### Loading and error states - -To show a loading spinner while the chatbot is processing the user's message, you can use the `isLoading` state returned by the `useCompletion` hook: - -```tsx -const { isLoading, ... } = useCompletion() - -return( - <> - {isLoading ? : null} - -) -``` - -Similarly, the `error` state reflects the error object thrown during the fetch request. It can be used to display an error message, or show a toast notification: - -```tsx -const { error, ... } = useCompletion() - -useEffect(() => { - if (error) { - toast.error(error.message) - } -}, [error]) - -// Or display the error message in the UI: -return ( - <> - {error ?
{error.message}
: null} - -) -``` - -### Controlled input - -In the initial example, we have `handleSubmit` and `handleInputChange` callbacks that manage the input changes and form submissions. These are handy for common use cases, but you can also use uncontrolled APIs for more advanced scenarios such as form validation or customized components. - -The following example demonstrates how to use more granular APIs like `setInput` with your custom input and submit button components: - -```tsx -const { input, setInput } = useCompletion(); - -return ( - <> - setInput(value)} /> - -); -``` - -### Cancelation - -It's also a common use case to abort the response message while it's still streaming back from the AI provider. You can do this by calling the `stop` function returned by the `useCompletion` hook. - -```tsx -const { stop, isLoading, ... } = useCompletion() - -return ( - <> - - -) -``` - -When the user clicks the "Stop" button, the fetch request will be aborted. This avoids consuming unnecessary resources and improves the UX of your application. - -### Throttling UI Updates - -This feature is currently only available for React. - -By default, the `useCompletion` hook will trigger a render every time a new chunk is received. -You can throttle the UI updates with the `experimental_throttle` option. - -```tsx filename="page.tsx" highlight="2-3" -const { completion, ... } = useCompletion({ - // Throttle the completion and data updates to 50ms: - experimental_throttle: 50 -}) -``` - -## Event Callbacks - -`useCompletion` also provides optional event callbacks that you can use to handle different stages of the chatbot lifecycle. These callbacks can be used to trigger additional actions, such as logging, analytics, or custom UI updates. - -```tsx -const { ... } = useCompletion({ - onFinish: (prompt: string, completion: string) => { - console.log('Finished streaming completion:', completion) - }, - onError: (error: Error) => { - console.error('An error occurred:', error) - }, -}) -``` - -## Configure Request Options - -By default, the `useCompletion` hook sends a HTTP POST request to the `/api/completion` endpoint with the prompt as part of the request body. You can customize the request by passing additional options to the `useCompletion` hook: - -```tsx -const { messages, input, handleInputChange, handleSubmit } = useCompletion({ - api: '/api/custom-completion', - headers: { - Authorization: 'your_token', - }, - body: { - user_id: '123', - }, - credentials: 'same-origin', -}); -``` - -In this example, the `useCompletion` hook sends a POST request to the `/api/completion` endpoint with the specified headers, additional body fields, and credentials for that fetch request. On your server side, you can handle the request with these additional information. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/08-object-generation.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/08-object-generation.mdx deleted file mode 100644 index 164d3eb14..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/08-object-generation.mdx +++ /dev/null @@ -1,344 +0,0 @@ ---- -title: Object Generation -description: Learn how to use the useObject hook. ---- - -# Object Generation - - - `useObject` is an experimental feature and only available in React, Svelte, - and Vue. - - -The [`useObject`](/docs/reference/ai-sdk-ui/use-object) hook allows you to create interfaces that represent a structured JSON object that is being streamed. - -In this guide, you will learn how to use the `useObject` hook in your application to generate UIs for structured data on the fly. - -## Example - -The example shows a small notifications demo app that generates fake notifications in real-time. - -### Schema - -It is helpful to set up the schema in a separate file that is imported on both the client and server. - -```ts filename='app/api/notifications/schema.ts' -import { z } from 'zod'; - -// define a schema for the notifications -export const notificationSchema = z.object({ - notifications: z.array( - z.object({ - name: z.string().describe('Name of a fictional person.'), - message: z.string().describe('Message. Do not use emojis or links.'), - }), - ), -}); -``` - -### Client - -The client uses [`useObject`](/docs/reference/ai-sdk-ui/use-object) to stream the object generation process. - -The results are partial and are displayed as they are received. -Please note the code for handling `undefined` values in the JSX. - -```tsx filename='app/page.tsx' -'use client'; - -import { experimental_useObject as useObject } from '@ai-sdk/react'; -import { notificationSchema } from './api/notifications/schema'; - -export default function Page() { - const { object, submit } = useObject({ - api: '/api/notifications', - schema: notificationSchema, - }); - - return ( - <> - - - {object?.notifications?.map((notification, index) => ( -
-

{notification?.name}

-

{notification?.message}

-
- ))} - - ); -} -``` - -### Server - -On the server, we use [`streamText`](/docs/reference/ai-sdk-core/stream-text) with [`Output.object()`](/docs/reference/ai-sdk-core/output#output-object) to stream the object generation process. - -```typescript filename='app/api/notifications/route.ts' -import { streamText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { notificationSchema } from './schema'; - -// Allow streaming responses up to 30 seconds -export const maxDuration = 30; - -export async function POST(req: Request) { - const context = await req.json(); - - const result = streamText({ - model: __MODEL__, - output: Output.object({ schema: notificationSchema }), - prompt: - `Generate 3 notifications for a messages app in this context:` + context, - }); - - return result.toTextStreamResponse(); -} -``` - -## Enum Output Mode - -When you need to classify or categorize input into predefined options, you can use the `enum` output mode with `useObject`. This requires a specific schema structure where the object has `enum` as a key with `z.enum` containing your possible values. - -### Example: Text Classification - -This example shows how to build a simple text classifier that categorizes statements as true or false. - -#### Client - -When using `useObject` with enum output mode, your schema must be an object with `enum` as the key: - -```tsx filename='app/classify/page.tsx' -'use client'; - -import { experimental_useObject as useObject } from '@ai-sdk/react'; -import { z } from 'zod'; - -export default function ClassifyPage() { - const { object, submit, isLoading } = useObject({ - api: '/api/classify', - schema: z.object({ enum: z.enum(['true', 'false']) }), - }); - - return ( - <> - - - {object &&
Classification: {object.enum}
} - - ); -} -``` - -#### Server - -On the server, use `streamText` with `Output.choice()` to stream the classification result: - -```typescript filename='app/api/classify/route.ts' -import { streamText, Output } from 'ai'; -__PROVIDER_IMPORT__; - -export async function POST(req: Request) { - const context = await req.json(); - - const result = streamText({ - model: __MODEL__, - output: Output.choice({ options: ['true', 'false'] }), - prompt: `Classify this statement as true or false: ${context}`, - }); - - return result.toTextStreamResponse(); -} -``` - -## Customized UI - -`useObject` also provides ways to show loading and error states: - -### Loading State - -The `isLoading` state returned by the `useObject` hook can be used for several -purposes: - -- To show a loading spinner while the object is generated. -- To disable the submit button. - -```tsx filename='app/page.tsx' highlight="6,13-20,24" -'use client'; - -import { experimental_useObject as useObject } from '@ai-sdk/react'; - -export default function Page() { - const { isLoading, object, submit } = useObject({ - api: '/api/notifications', - schema: notificationSchema, - }); - - return ( - <> - {isLoading && } - - - - {object?.notifications?.map((notification, index) => ( -
-

{notification?.name}

-

{notification?.message}

-
- ))} - - ); -} -``` - -### Stop Handler - -The `stop` function can be used to stop the object generation process. This can be useful if the user wants to cancel the request or if the server is taking too long to respond. - -```tsx filename='app/page.tsx' highlight="6,14-16" -'use client'; - -import { experimental_useObject as useObject } from '@ai-sdk/react'; - -export default function Page() { - const { isLoading, stop, object, submit } = useObject({ - api: '/api/notifications', - schema: notificationSchema, - }); - - return ( - <> - {isLoading && ( - - )} - - - - {object?.notifications?.map((notification, index) => ( -
-

{notification?.name}

-

{notification?.message}

-
- ))} - - ); -} -``` - -### Error State - -Similarly, the `error` state reflects the error object thrown during the fetch request. -It can be used to display an error message, or to disable the submit button: - - - We recommend showing a generic error message to the user, such as "Something - went wrong." This is a good practice to avoid leaking information from the - server. - - -```tsx file="app/page.tsx" highlight="6,13" -'use client'; - -import { experimental_useObject as useObject } from '@ai-sdk/react'; - -export default function Page() { - const { error, object, submit } = useObject({ - api: '/api/notifications', - schema: notificationSchema, - }); - - return ( - <> - {error &&
An error occurred.
} - - - - {object?.notifications?.map((notification, index) => ( -
-

{notification?.name}

-

{notification?.message}

-
- ))} - - ); -} -``` - -## Event Callbacks - -`useObject` provides optional event callbacks that you can use to handle life-cycle events. - -- `onFinish`: Called when the object generation is completed. -- `onError`: Called when an error occurs during the fetch request. - -These callbacks can be used to trigger additional actions, such as logging, analytics, or custom UI updates. - -```tsx filename='app/page.tsx' highlight="10-20" -'use client'; - -import { experimental_useObject as useObject } from '@ai-sdk/react'; -import { notificationSchema } from './api/notifications/schema'; - -export default function Page() { - const { object, submit } = useObject({ - api: '/api/notifications', - schema: notificationSchema, - onFinish({ object, error }) { - // typed object, undefined if schema validation fails: - console.log('Object generation completed:', object); - - // error, undefined if schema validation succeeds: - console.log('Schema validation error:', error); - }, - onError(error) { - // error during fetch request: - console.error('An error occurred:', error); - }, - }); - - return ( -
- - - {object?.notifications?.map((notification, index) => ( -
-

{notification?.name}

-

{notification?.message}

-
- ))} -
- ); -} -``` - -## Configure Request Options - -You can configure the API endpoint, optional headers and credentials using the `api`, `headers` and `credentials` settings. - -```tsx highlight="2-5" -const { submit, object } = useObject({ - api: '/api/use-object', - headers: { - 'X-Custom-Header': 'CustomValue', - }, - credentials: 'include', - schema: yourSchema, -}); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/20-streaming-data.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/20-streaming-data.mdx deleted file mode 100644 index c85e678c2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/20-streaming-data.mdx +++ /dev/null @@ -1,397 +0,0 @@ ---- -title: Streaming Custom Data -description: Learn how to stream custom data from the server to the client. ---- - -# Streaming Custom Data - -It is often useful to send additional data alongside the model's response. -For example, you may want to send status information, the message ids after storing them, -or references to content that the language model is referring to. - -The AI SDK provides several helpers that allows you to stream additional data to the client -and attach it to the `UIMessage` parts array: - -- `createUIMessageStream`: creates a data stream -- `createUIMessageStreamResponse`: creates a response object that streams data -- `pipeUIMessageStreamToResponse`: pipes a data stream to a server response object - -The data is streamed as part of the response stream using Server-Sent Events. - -## Setting Up Type-Safe Data Streaming - -First, define your custom message type with data part schemas for type safety: - -```tsx filename="ai/types.ts" -import { UIMessage } from 'ai'; - -// Define your custom message type with data part schemas -export type MyUIMessage = UIMessage< - never, // metadata type - { - weather: { - city: string; - weather?: string; - status: 'loading' | 'success'; - }; - notification: { - message: string; - level: 'info' | 'warning' | 'error'; - }; - } // data parts type ->; -``` - -## Streaming Data from the Server - -In your server-side route handler, you can create a `UIMessageStream` and then pass it to `createUIMessageStreamResponse`: - -```tsx filename="route.ts" -import { openai } from '@ai-sdk/openai'; -import { - createUIMessageStream, - createUIMessageStreamResponse, - streamText, - convertToModelMessages, -} from 'ai'; -__PROVIDER_IMPORT__; -import type { MyUIMessage } from '@/ai/types'; - -export async function POST(req: Request) { - const { messages } = await req.json(); - - const stream = createUIMessageStream({ - execute: ({ writer }) => { - // 1. Send initial status (transient - won't be added to message history) - writer.write({ - type: 'data-notification', - data: { message: 'Processing your request...', level: 'info' }, - transient: true, // This part won't be added to message history - }); - - // 2. Send sources (useful for RAG use cases) - writer.write({ - type: 'source', - value: { - type: 'source', - sourceType: 'url', - id: 'source-1', - url: 'https://weather.com', - title: 'Weather Data Source', - }, - }); - - // 3. Send data parts with loading state - writer.write({ - type: 'data-weather', - id: 'weather-1', - data: { city: 'San Francisco', status: 'loading' }, - }); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - onFinish() { - // 4. Update the same data part (reconciliation) - writer.write({ - type: 'data-weather', - id: 'weather-1', // Same ID = update existing part - data: { - city: 'San Francisco', - weather: 'sunny', - status: 'success', - }, - }); - - // 5. Send completion notification (transient) - writer.write({ - type: 'data-notification', - data: { message: 'Request completed', level: 'info' }, - transient: true, // Won't be added to message history - }); - }, - }); - - writer.merge(result.toUIMessageStream()); - }, - }); - - return createUIMessageStreamResponse({ stream }); -} -``` - - - You can also send stream data from custom backends, e.g. Python / FastAPI, - using the [UI Message Stream - Protocol](/docs/ai-sdk-ui/stream-protocol#ui-message-stream-protocol). - - -## Types of Streamable Data - -### Data Parts (Persistent) - -Regular data parts are added to the message history and appear in `message.parts`: - -```tsx -writer.write({ - type: 'data-weather', - id: 'weather-1', // Optional: enables reconciliation - data: { city: 'San Francisco', status: 'loading' }, -}); -``` - -### Sources - -Sources are useful for RAG implementations where you want to show which documents or URLs were referenced: - -```tsx -writer.write({ - type: 'source', - value: { - type: 'source', - sourceType: 'url', - id: 'source-1', - url: 'https://example.com', - title: 'Example Source', - }, -}); -``` - -### Transient Data Parts (Ephemeral) - -Transient parts are sent to the client but not added to the message history. They are only accessible via the `onData` useChat handler: - -```tsx -// server -writer.write({ - type: 'data-notification', - data: { message: 'Processing...', level: 'info' }, - transient: true, // Won't be added to message history -}); - -// client -const [notification, setNotification] = useState(); - -const { messages } = useChat({ - onData: ({ data, type }) => { - if (type === 'data-notification') { - setNotification({ message: data.message, level: data.level }); - } - }, -}); -``` - -## Data Part Reconciliation - -When you write to a data part with the same ID, the client automatically reconciles and updates that part. This enables powerful dynamic experiences like: - -- **Collaborative artifacts** - Update code, documents, or designs in real-time -- **Progressive data loading** - Show loading states that transform into final results -- **Live status updates** - Update progress bars, counters, or status indicators -- **Interactive components** - Build UI elements that evolve based on user interaction - -The reconciliation happens automatically - simply use the same `id` when writing to the stream. - -## Processing Data on the Client - -### Using the onData Callback - -The `onData` callback is essential for handling streaming data, especially transient parts: - -```tsx filename="page.tsx" -import { useChat } from '@ai-sdk/react'; -import type { MyUIMessage } from '@/ai/types'; - -const { messages } = useChat({ - api: '/api/chat', - onData: dataPart => { - // Handle all data parts as they arrive (including transient parts) - console.log('Received data part:', dataPart); - - // Handle different data part types - if (dataPart.type === 'data-weather') { - console.log('Weather update:', dataPart.data); - } - - // Handle transient notifications (ONLY available here, not in message.parts) - if (dataPart.type === 'data-notification') { - showToast(dataPart.data.message, dataPart.data.level); - } - }, -}); -``` - -**Important:** Transient data parts are **only** available through the `onData` callback. They will not appear in the `message.parts` array since they're not added to message history. - -### Rendering Persistent Data Parts - -You can filter and render data parts from the message parts array: - -```tsx filename="page.tsx" -const result = ( - <> - {messages?.map(message => ( -
- {/* Render weather data parts */} - {message.parts - .filter(part => part.type === 'data-weather') - .map((part, index) => ( -
- {part.data.status === 'loading' ? ( - <>Getting weather for {part.data.city}... - ) : ( - <> - Weather in {part.data.city}: {part.data.weather} - - )} -
- ))} - - {/* Render text content */} - {message.parts - .filter(part => part.type === 'text') - .map((part, index) => ( -
{part.text}
- ))} - - {/* Render sources */} - {message.parts - .filter(part => part.type === 'source') - .map((part, index) => ( -
- Source: {part.title} -
- ))} -
- ))} - -); -``` - -### Complete Example - -```tsx filename="page.tsx" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; -import type { MyUIMessage } from '@/ai/types'; - -export default function Chat() { - const [input, setInput] = useState(''); - - const { messages, sendMessage } = useChat({ - api: '/api/chat', - onData: dataPart => { - // Handle transient notifications - if (dataPart.type === 'data-notification') { - console.log('Notification:', dataPart.data.message); - } - }, - }); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }; - - return ( - <> - {messages?.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - - {/* Render weather data */} - {message.parts - .filter(part => part.type === 'data-weather') - .map((part, index) => ( - - {part.data.status === 'loading' ? ( - <>Getting weather for {part.data.city}... - ) : ( - <> - Weather in {part.data.city}: {part.data.weather} - - )} - - ))} - - {/* Render text content */} - {message.parts - .filter(part => part.type === 'text') - .map((part, index) => ( -
{part.text}
- ))} -
- ))} - -
- setInput(e.target.value)} - placeholder="Ask about the weather..." - /> - -
- - ); -} -``` - -## Use Cases - -- **RAG Applications** - Stream sources and retrieved documents -- **Real-time Status** - Show loading states and progress updates -- **Collaborative Tools** - Stream live updates to shared artifacts -- **Analytics** - Send usage data without cluttering message history -- **Notifications** - Display temporary alerts and status messages - -## Message Metadata vs Data Parts - -Both [message metadata](/docs/ai-sdk-ui/message-metadata) and data parts allow you to send additional information alongside messages, but they serve different purposes: - -### Message Metadata - -Message metadata is best for **message-level information** that describes the message as a whole: - -- Attached at the message level via `message.metadata` -- Sent using the `messageMetadata` callback in `toUIMessageStreamResponse` -- Ideal for: timestamps, model info, token usage, user context -- Type-safe with custom metadata types - -```ts -// Server: Send metadata about the message -return result.toUIMessageStreamResponse({ - messageMetadata: ({ part }) => { - if (part.type === 'finish') { - return { - model: part.response.modelId, - totalTokens: part.totalUsage.totalTokens, - createdAt: Date.now(), - }; - } - }, -}); -``` - -### Data Parts - -Data parts are best for streaming **dynamic arbitrary data**: - -- Added to the message parts array via `message.parts` -- Streamed using `createUIMessageStream` and `writer.write()` -- Can be reconciled/updated using the same ID -- Support transient parts that don't persist -- Ideal for: dynamic content, loading states, interactive components - -```ts -// Server: Stream data as part of message content -writer.write({ - type: 'data-weather', - id: 'weather-1', - data: { city: 'San Francisco', status: 'loading' }, -}); -``` - -For more details on message metadata, see the [Message Metadata documentation](/docs/ai-sdk-ui/message-metadata). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/21-error-handling.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/21-error-handling.mdx deleted file mode 100644 index 4eb32374a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/21-error-handling.mdx +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: Error Handling -description: Learn how to handle errors in the AI SDK UI ---- - -# Error Handling and warnings - -## Warnings - -The AI SDK shows warnings when something might not work as expected. -These warnings help you fix problems before they cause errors. - -### When Warnings Appear - -Warnings are shown in the browser console when: - -- **Unsupported features**: You use a feature or setting that is not supported by the AI model (e.g., certain options or parameters). -- **Compatibility warnings**: A feature is used in a compatibility mode, which might work differently or less optimally than intended. -- **Other warnings**: The AI model reports another type of issue, such as general problems or advisory messages. - -### Warning Messages - -All warnings start with "AI SDK Warning:" so you can easily find them. For example: - -``` -AI SDK Warning: The feature "temperature" is not supported by this model -``` - -### Turning Off Warnings - -By default, warnings are shown in the console. You can control this behavior: - -#### Turn Off All Warnings - -Set a global variable to turn off warnings completely: - -```ts -globalThis.AI_SDK_LOG_WARNINGS = false; -``` - -#### Custom Warning Handler - -You can also provide your own function to handle warnings. -It receives provider id, model id, and a list of warnings. - -```ts -globalThis.AI_SDK_LOG_WARNINGS = ({ warnings, provider, model }) => { - // Handle warnings your own way -}; -``` - -## Error Handling - -### Error Helper Object - -Each AI SDK UI hook also returns an [error](/docs/reference/ai-sdk-ui/use-chat#error) object that you can use to render the error in your UI. -You can use the error object to show an error message, disable the submit button, or show a retry button. - - - We recommend showing a generic error message to the user, such as "Something - went wrong." This is a good practice to avoid leaking information from the - server. - - -```tsx file="app/page.tsx" highlight="7,18-25,31" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export default function Chat() { - const [input, setInput] = useState(''); - const { messages, sendMessage, error, regenerate } = useChat(); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }; - - return ( -
- {messages.map(m => ( -
- {m.role}:{' '} - {m.parts - .filter(part => part.type === 'text') - .map(part => part.text) - .join('')} -
- ))} - - {error && ( - <> -
An error occurred.
- - - )} - -
- setInput(e.target.value)} - disabled={error != null} - /> -
-
- ); -} -``` - -#### Alternative: replace last message - -Alternatively you can write a custom submit handler that replaces the last message when an error is present. - -```tsx file="app/page.tsx" highlight="17-23,35" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export default function Chat() { - const [input, setInput] = useState(''); - const { sendMessage, error, messages, setMessages } = useChat(); - - function customSubmit(event: React.FormEvent) { - event.preventDefault(); - - if (error != null) { - setMessages(messages.slice(0, -1)); // remove last message - } - - sendMessage({ text: input }); - setInput(''); - } - - return ( -
- {messages.map(m => ( -
- {m.role}:{' '} - {m.parts - .filter(part => part.type === 'text') - .map(part => part.text) - .join('')} -
- ))} - - {error &&
An error occurred.
} - -
- setInput(e.target.value)} /> -
-
- ); -} -``` - -### Error Handling Callback - -Errors can be processed by passing an [`onError`](/docs/reference/ai-sdk-ui/use-chat#on-error) callback function as an option to the [`useChat`](/docs/reference/ai-sdk-ui/use-chat) or [`useCompletion`](/docs/reference/ai-sdk-ui/use-completion) hooks. -The callback function receives an error object as an argument. - -```tsx file="app/page.tsx" highlight="6-9" -import { useChat } from '@ai-sdk/react'; - -export default function Page() { - const { - /* ... */ - } = useChat({ - // handle error: - onError: error => { - console.error(error); - }, - }); -} -``` - -### Injecting Errors for Testing - -You might want to create errors for testing. -You can easily do so by throwing an error in your route handler: - -```ts file="app/api/chat/route.ts" -export async function POST(req: Request) { - throw new Error('This is a test error'); -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/21-transport.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/21-transport.mdx deleted file mode 100644 index c3a6d0e6b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/21-transport.mdx +++ /dev/null @@ -1,174 +0,0 @@ ---- -title: Transport -description: Learn how to use custom transports with useChat. ---- - -# Transport - -The `useChat` transport system provides fine-grained control over how messages are sent to your API endpoints and how responses are processed. This is particularly useful for alternative communication protocols like WebSockets, custom authentication patterns, or specialized backend integrations. - -## Default Transport - -By default, `useChat` uses HTTP POST requests to send messages to `/api/chat`: - -```tsx -import { useChat } from '@ai-sdk/react'; - -// Uses default HTTP transport -const { messages, sendMessage } = useChat(); -``` - -This is equivalent to: - -```tsx -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; - -const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - }), -}); -``` - -## Custom Transport Configuration - -Configure the default transport with custom options: - -```tsx -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; - -const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/custom-chat', - headers: { - Authorization: 'Bearer your-token', - 'X-API-Version': '2024-01', - }, - credentials: 'include', - }), -}); -``` - -### Dynamic Configuration - -You can also provide functions that return configuration values. This is useful for authentication tokens that need to be refreshed, or for configuration that depends on runtime conditions: - -```tsx -const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - headers: () => ({ - Authorization: `Bearer ${getAuthToken()}`, - 'X-User-ID': getCurrentUserId(), - }), - body: () => ({ - sessionId: getCurrentSessionId(), - preferences: getUserPreferences(), - }), - credentials: () => 'include', - }), -}); -``` - -### Request Transformation - -Transform requests before sending to your API: - -```tsx -const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - prepareSendMessagesRequest: ({ id, messages, trigger, messageId }) => { - return { - headers: { - 'X-Session-ID': id, - }, - body: { - messages: messages.slice(-10), // Only send last 10 messages - trigger, - messageId, - }, - }; - }, - }), -}); -``` - -## Direct Agent Transport - -For scenarios where you want to communicate directly with an [Agent](/docs/reference/ai-sdk-core/agent) without going through HTTP, you can use `DirectChatTransport`. This transport invokes the agent's `stream()` method directly in-process. - -This is useful for: - -- **Server-side rendering**: Run the agent on the server without an API endpoint -- **Testing**: Test chat functionality without network requests -- **Single-process applications**: Desktop or CLI apps where client and agent run together - -```tsx -import { useChat } from '@ai-sdk/react'; -import { DirectChatTransport, ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are a helpful assistant.', - tools: { - weather: weatherTool, - }, -}); - -const { messages, sendMessage } = useChat({ - transport: new DirectChatTransport({ agent }), -}); -``` - -### How It Works - -Unlike `DefaultChatTransport` which sends HTTP requests: - -1. `DirectChatTransport` validates incoming UI messages -2. Converts them to model messages using `convertToModelMessages` -3. Calls the agent's `stream()` method directly -4. Returns the result as a UI message stream via `toUIMessageStream()` - -### Configuration Options - -You can pass additional options to customize the stream output: - -```tsx -const transport = new DirectChatTransport({ - agent, - // Pass options to the agent - options: { customOption: 'value' }, - // Configure what's sent to the client - sendReasoning: true, - sendSources: true, -}); -``` - - - `DirectChatTransport` does not support stream reconnection since there is no - persistent server-side stream. The `reconnectToStream()` method always returns - `null`. - - -For complete API details, see the [DirectChatTransport reference](/docs/reference/ai-sdk-ui/direct-chat-transport). - -## Building Custom Transports - -To understand how to build your own transport, refer to the source code of the default implementation: - -- **[DefaultChatTransport](https://github.com/vercel/ai/blob/main/packages/ai/src/ui/default-chat-transport.ts)** - The complete default HTTP transport implementation -- **[HttpChatTransport](https://github.com/vercel/ai/blob/main/packages/ai/src/ui/http-chat-transport.ts)** - Base HTTP transport with request handling -- **[ChatTransport Interface](https://github.com/vercel/ai/blob/main/packages/ai/src/ui/chat-transport.ts)** - The transport interface you need to implement - -These implementations show you exactly how to: - -- Handle the `sendMessages` method -- Process UI message streams -- Transform requests and responses -- Handle errors and connection management - -The transport system gives you complete control over how your chat application communicates, enabling integration with any backend protocol or service. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/24-reading-ui-message-streams.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/24-reading-ui-message-streams.mdx deleted file mode 100644 index b9949c235..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/24-reading-ui-message-streams.mdx +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Reading UIMessage Streams -description: Learn how to read UIMessage streams. ---- - -# Reading UI Message Streams - -`UIMessage` streams are useful outside of traditional chat use cases. You can consume them for terminal UIs, custom stream processing on the client, or React Server Components (RSC). - -The `readUIMessageStream` helper transforms a stream of `UIMessageChunk` objects into an `AsyncIterableStream` of `UIMessage` objects, allowing you to process messages as they're being constructed. - -## Basic Usage - -```tsx -import { readUIMessageStream, streamText } from 'ai'; -__PROVIDER_IMPORT__; - -async function main() { - const result = streamText({ - model: __MODEL__, - prompt: 'Write a short story about a robot.', - }); - - for await (const uiMessage of readUIMessageStream({ - stream: result.toUIMessageStream(), - })) { - console.log('Current message state:', uiMessage); - } -} -``` - -## Tool Calls Integration - -Handle streaming responses that include tool calls: - -```tsx -import { readUIMessageStream, streamText, tool } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -async function handleToolCalls() { - const result = streamText({ - model: __MODEL__, - tools: { - weather: tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: ({ location }) => ({ - location, - temperature: 72 + Math.floor(Math.random() * 21) - 10, - }), - }), - }, - prompt: 'What is the weather in Tokyo?', - }); - - for await (const uiMessage of readUIMessageStream({ - stream: result.toUIMessageStream(), - })) { - // Handle different part types - uiMessage.parts.forEach(part => { - switch (part.type) { - case 'text': - console.log('Text:', part.text); - break; - case 'tool-call': - console.log('Tool called:', part.toolName, 'with args:', part.args); - break; - case 'tool-result': - console.log('Tool result:', part.result); - break; - } - }); - } -} -``` - -## Resuming Conversations - -Resume streaming from a previous message state: - -```tsx -import { readUIMessageStream, streamText } from 'ai'; -__PROVIDER_IMPORT__; - -async function resumeConversation(lastMessage: UIMessage) { - const result = streamText({ - model: __MODEL__, - messages: [ - { role: 'user', content: 'Continue our previous conversation.' }, - ], - }); - - // Resume from the last message - for await (const uiMessage of readUIMessageStream({ - stream: result.toUIMessageStream(), - message: lastMessage, // Resume from this message - })) { - console.log('Resumed message:', uiMessage); - } -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/25-message-metadata.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/25-message-metadata.mdx deleted file mode 100644 index 151f047cb..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/25-message-metadata.mdx +++ /dev/null @@ -1,152 +0,0 @@ ---- -title: Message Metadata -description: Learn how to attach and use metadata with messages in AI SDK UI ---- - -# Message Metadata - -Message metadata allows you to attach custom information to messages at the message level. This is useful for tracking timestamps, model information, token usage, user context, and other message-level data. - -## Overview - -Message metadata differs from [data parts](/docs/ai-sdk-ui/streaming-data) in that it's attached at the message level rather than being part of the message content. While data parts are ideal for dynamic content that forms part of the message, metadata is perfect for information about the message itself. - -## Getting Started - -Here's a simple example of using message metadata to track timestamps and model information: - -### Defining Metadata Types - -First, define your metadata type for type safety: - -```tsx filename="app/types.ts" -import { UIMessage } from 'ai'; -import { z } from 'zod'; - -// Define your metadata schema -export const messageMetadataSchema = z.object({ - createdAt: z.number().optional(), - model: z.string().optional(), - totalTokens: z.number().optional(), -}); - -export type MessageMetadata = z.infer; - -// Create a typed UIMessage -export type MyUIMessage = UIMessage; -``` - -### Sending Metadata from the Server - -Use the `messageMetadata` callback in `toUIMessageStreamResponse` to send metadata at different streaming stages: - -```ts filename="app/api/chat/route.ts" highlight="11-20" -import { convertToModelMessages, streamText } from 'ai'; -__PROVIDER_IMPORT__; -import type { MyUIMessage } from '@/types'; - -export async function POST(req: Request) { - const { messages }: { messages: MyUIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse({ - originalMessages: messages, // pass this in for type-safe return objects - messageMetadata: ({ part }) => { - // Send metadata when streaming starts - if (part.type === 'start') { - return { - createdAt: Date.now(), - model: 'your-model-id', - }; - } - - // Send additional metadata when streaming completes - if (part.type === 'finish') { - return { - totalTokens: part.totalUsage.totalTokens, - }; - } - }, - }); -} -``` - - - To enable type-safe metadata return object in `messageMetadata`, pass in the - `originalMessages` parameter typed to your UIMessage type. - - -### Accessing Metadata on the Client - -Access metadata through the `message.metadata` property: - -```tsx filename="app/page.tsx" highlight="8,18-23" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; -import type { MyUIMessage } from '@/types'; - -export default function Chat() { - const { messages } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - }), - }); - - return ( -
- {messages.map(message => ( -
-
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.metadata?.createdAt && ( - - {new Date(message.metadata.createdAt).toLocaleTimeString()} - - )} -
- - {/* Render message content */} - {message.parts.map((part, index) => - part.type === 'text' ?
{part.text}
: null, - )} - - {/* Display additional metadata */} - {message.metadata?.totalTokens && ( -
- {message.metadata.totalTokens} tokens -
- )} -
- ))} -
- ); -} -``` - - - For streaming arbitrary data that changes during generation, consider using - [data parts](/docs/ai-sdk-ui/streaming-data) instead. - - -## Common Use Cases - -Message metadata is ideal for: - -- **Timestamps**: When messages were created or completed -- **Model Information**: Which AI model was used -- **Token Usage**: Track costs and usage limits -- **User Context**: User IDs, session information -- **Performance Metrics**: Generation time, time to first token -- **Quality Indicators**: Finish reason, confidence scores - -## See Also - -- [Chatbot Guide](/docs/ai-sdk-ui/chatbot#message-metadata) - Message metadata in the context of building chatbots -- [Streaming Data](/docs/ai-sdk-ui/streaming-data#message-metadata-vs-data-parts) - Comparison with data parts -- [UIMessage Reference](/docs/reference/ai-sdk-core/ui-message) - Complete UIMessage type reference diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/50-stream-protocol.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/50-stream-protocol.mdx deleted file mode 100644 index a9a343da5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/50-stream-protocol.mdx +++ /dev/null @@ -1,477 +0,0 @@ ---- -title: Stream Protocols -description: Learn more about the supported stream protocols in the AI SDK. ---- - -# Stream Protocols - -AI SDK UI functions such as `useChat` and `useCompletion` support both text streams and data streams. -The stream protocol defines how the data is streamed to the frontend on top of the HTTP protocol. - -This page describes both protocols and how to use them in the backend and frontend. - -You can use this information to develop custom backends and frontends for your use case, e.g., -to provide compatible API endpoints that are implemented in a different language such as Python. - -For instance, here's an example using [FastAPI](https://github.com/vercel/ai/tree/main/examples/next-fastapi) as a backend. - -## Text Stream Protocol - -A text stream contains chunks in plain text, that are streamed to the frontend. -Each chunk is then appended together to form a full text response. - -Text streams are supported by `useChat`, `useCompletion`, and `useObject`. -When you use `useChat` or `useCompletion`, you need to enable text streaming -by setting the `streamProtocol` options to `text`. - -You can generate text streams with `streamText` in the backend. -When you call `toTextStreamResponse()` on the result object, -a streaming HTTP response is returned. - - - Text streams only support basic text data. If you need to stream other types - of data such as tool calls, use data streams. - - -### Text Stream Example - -Here is a Next.js example that uses the text stream protocol: - -```tsx filename='app/page.tsx' -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { TextStreamChatTransport } from 'ai'; -import { useState } from 'react'; - -export default function Chat() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat({ - transport: new TextStreamChatTransport({ api: '/api/chat' }), - }); - - return ( -
- {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return
{part.text}
; - } - })} -
- ))} - -
{ - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - > - setInput(e.currentTarget.value)} - /> -
-
- ); -} -``` - -```ts filename='app/api/chat/route.ts' -import { streamText, UIMessage, convertToModelMessages } from 'ai'; -__PROVIDER_IMPORT__; - -// Allow streaming responses up to 30 seconds -export const maxDuration = 30; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toTextStreamResponse(); -} -``` - -## Data Stream Protocol - -A data stream follows a special protocol that the AI SDK provides to send information to the frontend. - -The data stream protocol uses Server-Sent Events (SSE) format for improved standardization, keep-alive through ping, reconnect capabilities, and better cache handling. - - - When you provide data streams from a custom backend, you need to set the - `x-vercel-ai-ui-message-stream` header to `v1`. - - -The following stream parts are currently supported: - -### Message Start Part - -Indicates the beginning of a new message with metadata. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"start","messageId":"..."} - -``` - -### Text Parts - -Text content is streamed using a start/delta/end pattern with unique IDs for each text block. - -#### Text Start Part - -Indicates the beginning of a text block. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"text-start","id":"msg_68679a454370819ca74c8eb3d04379630dd1afb72306ca5d"} - -``` - -#### Text Delta Part - -Contains incremental text content for the text block. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"text-delta","id":"msg_68679a454370819ca74c8eb3d04379630dd1afb72306ca5d","delta":"Hello"} - -``` - -#### Text End Part - -Indicates the completion of a text block. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"text-end","id":"msg_68679a454370819ca74c8eb3d04379630dd1afb72306ca5d"} - -``` - -### Reasoning Parts - -Reasoning content is streamed using a start/delta/end pattern with unique IDs for each reasoning block. - -#### Reasoning Start Part - -Indicates the beginning of a reasoning block. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"reasoning-start","id":"reasoning_123"} - -``` - -#### Reasoning Delta Part - -Contains incremental reasoning content for the reasoning block. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"reasoning-delta","id":"reasoning_123","delta":"This is some reasoning"} - -``` - -#### Reasoning End Part - -Indicates the completion of a reasoning block. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"reasoning-end","id":"reasoning_123"} - -``` - -### Source Parts - -Source parts provide references to external content sources. - -#### Source URL Part - -References to external URLs. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"source-url","sourceId":"https://example.com","url":"https://example.com"} - -``` - -#### Source Document Part - -References to documents or files. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"source-document","sourceId":"https://example.com","mediaType":"file","title":"Title"} - -``` - -### File Part - -The file parts contain references to files with their media type. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"file","url":"https://example.com/file.png","mediaType":"image/png"} - -``` - -### Data Parts - -Custom data parts allow streaming of arbitrary structured data with type-specific handling. - -Format: Server-Sent Event with JSON object where the type includes a custom suffix - -Example: - -``` -data: {"type":"data-weather","data":{"location":"SF","temperature":100}} - -``` - -The `data-*` type pattern allows you to define custom data types that your frontend can handle specifically. - -### Error Part - -The error parts are appended to the message as they are received. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"error","errorText":"error message"} - -``` - -### Tool Input Start Part - -Indicates the beginning of tool input streaming. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"tool-input-start","toolCallId":"call_fJdQDqnXeGxTmr4E3YPSR7Ar","toolName":"getWeatherInformation"} - -``` - -### Tool Input Delta Part - -Incremental chunks of tool input as it's being generated. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"tool-input-delta","toolCallId":"call_fJdQDqnXeGxTmr4E3YPSR7Ar","inputTextDelta":"San Francisco"} - -``` - -### Tool Input Available Part - -Indicates that tool input is complete and ready for execution. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"tool-input-available","toolCallId":"call_fJdQDqnXeGxTmr4E3YPSR7Ar","toolName":"getWeatherInformation","input":{"city":"San Francisco"}} - -``` - -### Tool Output Available Part - -Contains the result of tool execution. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"tool-output-available","toolCallId":"call_fJdQDqnXeGxTmr4E3YPSR7Ar","output":{"city":"San Francisco","weather":"sunny"}} - -``` - -### Start Step Part - -A part indicating the start of a step. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"start-step"} - -``` - -### Finish Step Part - -A part indicating that a step (i.e., one LLM API call in the backend) has been completed. - -This part is necessary to correctly process multiple stitched assistant calls, e.g. when calling tools in the backend, and using steps in `useChat` at the same time. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"finish-step"} - -``` - -### Finish Message Part - -A part indicating the completion of a message. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"finish"} - -``` - -### Abort Part - -Indicates the stream was aborted. - -Format: Server-Sent Event with JSON object - -Example: - -``` -data: {"type":"abort","reason":"user cancelled"} - -``` - -### Stream Termination - -The stream ends with a special `[DONE]` marker. - -Format: Server-Sent Event with literal `[DONE]` - -Example: - -``` -data: [DONE] - -``` - -The data stream protocol is supported -by `useChat` and `useCompletion` on the frontend and used by default. -`useCompletion` only supports the `text` and `data` stream parts. - -On the backend, you can use `toUIMessageStreamResponse()` from the `streamText` result object to return a streaming HTTP response. - -### UI Message Stream Example - -Here is a Next.js example that uses the UI message stream protocol: - -```tsx filename='app/page.tsx' -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { useState } from 'react'; - -export default function Chat() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat(); - - return ( -
- {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return
{part.text}
; - } - })} -
- ))} - -
{ - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }} - > - setInput(e.currentTarget.value)} - /> -
-
- ); -} -``` - -```ts filename='app/api/chat/route.ts' -import { streamText, UIMessage, convertToModelMessages } from 'ai'; -__PROVIDER_IMPORT__; - -// Allow streaming responses up to 30 seconds -export const maxDuration = 30; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse(); -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/index.mdx deleted file mode 100644 index cd7333342..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/04-ai-sdk-ui/index.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: AI SDK UI -description: Learn about the AI SDK UI. ---- - -# AI SDK UI - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/01-overview.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/01-overview.mdx deleted file mode 100644 index bbd221ff7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/01-overview.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Overview -description: An overview of AI SDK RSC. ---- - -# AI SDK RSC - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - - - The `@ai-sdk/rsc` package is compatible with frameworks that support React - Server Components. - - -[React Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components) (RSC) allow you to write UI that can be rendered on the server and streamed to the client. RSCs enable [ Server Actions ](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#with-client-components), a new way to call server-side code directly from the client just like any other function with end-to-end type-safety. This combination opens the door to a new way of building AI applications, allowing the large language model (LLM) to generate and stream UI directly from the server to the client. - -## AI SDK RSC Functions - -AI SDK RSC has various functions designed to help you build AI-native applications with React Server Components. These functions: - -1. Provide abstractions for building Generative UI applications. - - [`streamUI`](/docs/reference/ai-sdk-rsc/stream-ui): calls a model and allows it to respond with React Server Components. - - [`useUIState`](/docs/reference/ai-sdk-rsc/use-ui-state): returns the current UI state and a function to update the UI State (like React's `useState`). UI State is the visual representation of the AI state. - - [`useAIState`](/docs/reference/ai-sdk-rsc/use-ai-state): returns the current AI state and a function to update the AI State (like React's `useState`). The AI state is intended to contain context and information shared with the AI model, such as system messages, function responses, and other relevant data. - - [`useActions`](/docs/reference/ai-sdk-rsc/use-actions): provides access to your Server Actions from the client. This is particularly useful for building interfaces that require user interactions with the server. - - [`createAI`](/docs/reference/ai-sdk-rsc/create-ai): creates a client-server context provider that can be used to wrap parts of your application tree to easily manage both UI and AI states of your application. -2. Make it simple to work with streamable values between the server and client. - - [`createStreamableValue`](/docs/reference/ai-sdk-rsc/create-streamable-value): creates a stream that sends values from the server to the client. The value can be any serializable data. - - [`readStreamableValue`](/docs/reference/ai-sdk-rsc/read-streamable-value): reads a streamable value from the client that was originally created using `createStreamableValue`. - - [`createStreamableUI`](/docs/reference/ai-sdk-rsc/create-streamable-ui): creates a stream that sends UI from the server to the client. - - [`useStreamableValue`](/docs/reference/ai-sdk-rsc/use-streamable-value): accepts a streamable value created using `createStreamableValue` and returns the current value, error, and pending state. - -## Templates - -Check out the following templates to see AI SDK RSC in action. - - - -## API Reference - -Please check out the [AI SDK RSC API Reference](/docs/reference/ai-sdk-rsc) for more details on each function. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/02-streaming-react-components.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/02-streaming-react-components.mdx deleted file mode 100644 index 1dc6ff5d2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/02-streaming-react-components.mdx +++ /dev/null @@ -1,209 +0,0 @@ ---- -title: Streaming React Components -description: Overview of streaming RSCs ---- - -import { UIPreviewCard, Card } from '@/components/home/card'; -import { EventPlanning } from '@/components/home/event-planning'; -import { Searching } from '@/components/home/searching'; -import { Weather } from '@/components/home/weather'; - -# Streaming React Components - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -The RSC API allows you to stream React components from the server to the client with the [`streamUI`](/docs/reference/ai-sdk-rsc/stream-ui) function. This is useful when you want to go beyond raw text and stream components to the client in real-time. - -Similar to [ AI SDK Core ](/docs/ai-sdk-core/overview) APIs (like [ `streamText` ](/docs/reference/ai-sdk-core/stream-text)), `streamUI` provides a single function to call a model and allow it to respond with React Server Components. -It supports the same model interfaces as AI SDK Core APIs. - -### Concepts - -To give the model the ability to respond to a user's prompt with a React component, you can leverage [tools](/docs/ai-sdk-core/tools-and-tool-calling). - - - Remember, tools are like programs you can give to the model, and the model can - decide as and when to use based on the context of the conversation. - - -With the `streamUI` function, **you provide tools that return React components**. With the ability to stream components, the model is akin to a dynamic router that is able to understand the user's intention and display relevant UI. - -At a high level, the `streamUI` works like other AI SDK Core functions: you can provide the model with a prompt or some conversation history and, optionally, some tools. If the model decides, based on the context of the conversation, to call a tool, it will generate a tool call. The `streamUI` function will then run the respective tool, returning a React component. If the model doesn't have a relevant tool to use, it will return a text generation, which will be passed to the `text` function, for you to handle (render and return as a React component). - -Remember, the `streamUI` function must return a React component. - -```tsx -const result = await streamUI({ - model: openai('gpt-4o'), - prompt: 'Get the weather for San Francisco', - text: ({ content }) =>
{content}
, - tools: {}, -}); -``` - -This example calls the `streamUI` function using OpenAI's `gpt-4o` model, passes a prompt, specifies how the model's plain text response (`content`) should be rendered, and then provides an empty object for tools. Even though this example does not define any tools, it will stream the model's response as a `div` rather than plain text. - -### Adding A Tool - -Using tools with `streamUI` is similar to how you use tools with `generateText` and `streamText`. -A tool is an object that has: - -- `description`: a string telling the model what the tool does and when to use it -- `inputSchema`: a Zod schema describing what the tool needs in order to run -- `generate`: an asynchronous function that will be run if the model calls the tool. This must return a React component - -Let's expand the previous example to add a tool. - -```tsx highlight="6-14" -const result = await streamUI({ - model: openai('gpt-4o'), - prompt: 'Get the weather for San Francisco', - text: ({ content }) =>
{content}
, - tools: { - getWeather: { - description: 'Get the weather for a location', - inputSchema: z.object({ location: z.string() }), - generate: async function* ({ location }) { - yield ; - const weather = await getWeather(location); - return ; - }, - }, - }, -}); -``` - -This tool would be run if the user asks for the weather for their location. If the user hasn't specified a location, the model will ask for it before calling the tool. When the model calls the tool, the generate function will initially return a loading component. This component will show until the awaited call to `getWeather` is resolved, at which point, the model will stream the `` to the user. - - - Note: This example uses a [ generator function - ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) - (`function*`), which allows you to pause its execution and return a value, - then resume from where it left off on the next call. This is useful for - handling data streams, as you can fetch and return data from an asynchronous - source like an API, then resume the function to fetch the next chunk when - needed. By yielding values one at a time, generator functions enable efficient - processing of streaming data without blocking the main thread. - - -## Using `streamUI` with Next.js - -Let's see how you can use the example above in a Next.js application. - -To use `streamUI` in a Next.js application, you will need two things: - -1. A Server Action (where you will call `streamUI`) -2. A page to call the Server Action and render the resulting components - -### Step 1: Create a Server Action - - - Server Actions are server-side functions that you can call directly from the - frontend. For more info, see [the - documentation](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#with-client-components). - - -Create a Server Action at `app/actions.tsx` and add the following code: - -```tsx filename="app/actions.tsx" -'use server'; - -import { streamUI } from '@ai-sdk/rsc'; -import { openai } from '@ai-sdk/openai'; -import { z } from 'zod'; - -const LoadingComponent = () => ( -
getting weather...
-); - -const getWeather = async (location: string) => { - await new Promise(resolve => setTimeout(resolve, 2000)); - return '82°F️ ☀️'; -}; - -interface WeatherProps { - location: string; - weather: string; -} - -const WeatherComponent = (props: WeatherProps) => ( -
- The weather in {props.location} is {props.weather} -
-); - -export async function streamComponent() { - const result = await streamUI({ - model: openai('gpt-4o'), - prompt: 'Get the weather for San Francisco', - text: ({ content }) =>
{content}
, - tools: { - getWeather: { - description: 'Get the weather for a location', - inputSchema: z.object({ - location: z.string(), - }), - generate: async function* ({ location }) { - yield ; - const weather = await getWeather(location); - return ; - }, - }, - }, - }); - - return result.value; -} -``` - -The `getWeather` tool should look familiar as it is identical to the example in the previous section. In order for this tool to work: - -1. First define a `LoadingComponent`, which renders a pulsing `div` that will show some loading text. -2. Next, define a `getWeather` function that will timeout for 2 seconds (to simulate fetching the weather externally) before returning the "weather" for a `location`. Note: you could run any asynchronous TypeScript code here. -3. Finally, define a `WeatherComponent` which takes in `location` and `weather` as props, which are then rendered within a `div`. - -Your Server Action is an asynchronous function called `streamComponent` that takes no inputs, and returns a `ReactNode`. Within the action, you call the `streamUI` function, specifying the model (`gpt-4o`), the prompt, the component that should be rendered if the model chooses to return text, and finally, your `getWeather` tool. Last but not least, you return the resulting component generated by the model with `result.value`. - -To call this Server Action and display the resulting React Component, you will need a page. - -### Step 2: Create a Page - -Create or update your root page (`app/page.tsx`) with the following code: - -```tsx filename="app/page.tsx" -'use client'; - -import { useState } from 'react'; -import { Button } from '@/components/ui/button'; -import { streamComponent } from './actions'; - -export default function Page() { - const [component, setComponent] = useState(); - - return ( -
-
{ - e.preventDefault(); - setComponent(await streamComponent()); - }} - > - -
-
{component}
-
- ); -} -``` - -This page is first marked as a client component with the `"use client";` directive given it will be using hooks and interactivity. On the page, you render a form. When that form is submitted, you call the `streamComponent` action created in the previous step (just like any other function). The `streamComponent` action returns a `ReactNode` that you can then render on the page using React state (`setComponent`). - -## Going beyond a single prompt - -You can now allow the model to respond to your prompt with a React component. However, this example is limited to a static prompt that is set within your Server Action. You could make this example interactive by turning it into a chatbot. - -Learn how to stream React components with the Next.js App Router using `streamUI` with this [example](/examples/next-app/interface/route-components). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/03-generative-ui-state.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/03-generative-ui-state.mdx deleted file mode 100644 index b8bb3cb09..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/03-generative-ui-state.mdx +++ /dev/null @@ -1,279 +0,0 @@ ---- -title: Managing Generative UI State -description: Overview of the AI and UI states ---- - -# Managing Generative UI State - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -State is an essential part of any application. State is particularly important in AI applications as it is passed to large language models (LLMs) on each request to ensure they have the necessary context to produce a great generation. Traditional chatbots are text-based and have a structure that mirrors that of any chat application. - -For example, in a chatbot, state is an array of `messages` where each `message` has: - -- `id`: a unique identifier -- `role`: who sent the message (user/assistant/system/tool) -- `content`: the content of the message - -This state can be rendered in the UI and sent to the model without any modifications. - -With Generative UI, the model can now return a React component, rather than a plain text message. The client can render that component without issue, but that state can't be sent back to the model because React components aren't serialisable. So, what can you do? - -**The solution is to split the state in two, where one (AI State) becomes a proxy for the other (UI State)**. - -One way to understand this concept is through a Lego analogy. Imagine a 10,000 piece Lego model that, once built, cannot be easily transported because it is fragile. By taking the model apart, it can be easily transported, and then rebuilt following the steps outlined in the instructions pamphlet. In this way, the instructions pamphlet is a proxy to the physical structure. Similarly, AI State provides a serialisable (JSON) representation of your UI that can be passed back and forth to the model. - -## What is AI and UI State? - -The RSC API simplifies how you manage AI State and UI State, providing a robust way to keep them in sync between your database, server and client. - -### AI State - -AI State refers to the state of your application in a serialisable format that will be used on the server and can be shared with the language model. - -For a chat app, the AI State is the conversation history (messages) between the user and the assistant. Components generated by the model would be represented in a JSON format as a tool alongside any necessary props. AI State can also be used to store other values and meta information such as `createdAt` for each message and `chatId` for each conversation. The LLM reads this history so it can generate the next message. This state serves as the source of truth for the current application state. - - - **Note**: AI state can be accessed/modified from both the server and the - client. - - -### UI State - -UI State refers to the state of your application that is rendered on the client. It is a fully client-side state (similar to `useState`) that can store anything from JavaScript values to React elements. UI state is a list of actual UI elements that are rendered on the client. - -**Note**: UI State can only be accessed client-side. - -## Using AI / UI State - -### Creating the AI Context - -AI SDK RSC simplifies managing AI and UI state across your application by providing several hooks. These hooks are powered by [ React context ](https://react.dev/reference/react/hooks#context-hooks) under the hood. - -Notably, this means you do not have to pass the message history to the server explicitly for each request. You also can access and update your application state in any child component of the context provider. As you begin building [multistep generative interfaces](/docs/ai-sdk-rsc/multistep-interfaces), this will be particularly helpful. - -To use `@ai-sdk/rsc` to manage AI and UI State in your application, you can create a React context using [`createAI`](/docs/reference/ai-sdk-rsc/create-ai): - -```tsx filename='app/actions.tsx' -// Define the AI state and UI state types -export type ServerMessage = { - role: 'user' | 'assistant'; - content: string; -}; - -export type ClientMessage = { - id: string; - role: 'user' | 'assistant'; - display: ReactNode; -}; - -export const sendMessage = async (input: string): Promise => { - "use server" - ... -} -``` - -```tsx filename='app/ai.ts' -import { createAI } from '@ai-sdk/rsc'; -import { ClientMessage, ServerMessage, sendMessage } from './actions'; - -export type AIState = ServerMessage[]; -export type UIState = ClientMessage[]; - -// Create the AI provider with the initial states and allowed actions -export const AI = createAI({ - initialAIState: [], - initialUIState: [], - actions: { - sendMessage, - }, -}); -``` - -You must pass Server Actions to the `actions` object. - -In this example, you define types for AI State and UI State, respectively. - -Next, wrap your application with your newly created context. With that, you can get and set AI and UI State across your entire application. - -```tsx filename='app/layout.tsx' -import { type ReactNode } from 'react'; -import { AI } from './ai'; - -export default function RootLayout({ - children, -}: Readonly<{ children: ReactNode }>) { - return ( - - - {children} - - - ); -} -``` - -## Reading UI State in Client - -The UI state can be accessed in Client Components using the [`useUIState`](/docs/reference/ai-sdk-rsc/use-ui-state) hook provided by the RSC API. The hook returns the current UI state and a function to update the UI state like React's `useState`. - -```tsx filename='app/page.tsx' -'use client'; - -import { useUIState } from '@ai-sdk/rsc'; - -export default function Page() { - const [messages, setMessages] = useUIState(); - - return ( -
    - {messages.map(message => ( -
  • {message.display}
  • - ))} -
- ); -} -``` - -## Reading AI State in Client - -The AI state can be accessed in Client Components using the [`useAIState`](/docs/reference/ai-sdk-rsc/use-ai-state) hook provided by the RSC API. The hook returns the current AI state. - -```tsx filename='app/page.tsx' -'use client'; - -import { useAIState } from '@ai-sdk/rsc'; - -export default function Page() { - const [messages, setMessages] = useAIState(); - - return ( -
    - {messages.map(message => ( -
  • {message.content}
  • - ))} -
- ); -} -``` - -## Reading AI State on Server - -The AI State can be accessed within any Server Action provided to the `createAI` context using the [`getAIState`](/docs/reference/ai-sdk-rsc/get-ai-state) function. It returns the current AI state as a read-only value: - -```tsx filename='app/actions.ts' -import { getAIState } from '@ai-sdk/rsc'; - -export async function sendMessage(message: string) { - 'use server'; - - const history = getAIState(); - - const response = await generateText({ - model: __MODEL__, - messages: [...history, { role: 'user', content: message }], - }); - - return response; -} -``` - - - Remember, you can only access state within actions that have been passed to - the `createAI` context within the `actions` key. - - -## Updating AI State on Server - -The AI State can also be updated from within your Server Action with the [`getMutableAIState`](/docs/reference/ai-sdk-rsc/get-mutable-ai-state) function. This function is similar to `getAIState`, but it returns the state with methods to read and update it: - -```tsx filename='app/actions.ts' -import { getMutableAIState } from '@ai-sdk/rsc'; - -export async function sendMessage(message: string) { - 'use server'; - - const history = getMutableAIState(); - - // Update the AI state with the new user message. - history.update([...history.get(), { role: 'user', content: message }]); - - const response = await generateText({ - model: __MODEL__, - messages: history.get(), - }); - - // Update the AI state again with the response from the model. - history.done([...history.get(), { role: 'assistant', content: response }]); - - return response; -} -``` - - - It is important to update the AI State with new responses using `.update()` - and `.done()` to keep the conversation history in sync. - - -## Calling Server Actions from the Client - -To call the `sendMessage` action from the client, you can use the [`useActions`](/docs/reference/ai-sdk-rsc/use-actions) hook. The hook returns all the available Actions that were provided to `createAI`: - -```tsx filename='app/page.tsx' -'use client'; - -import { useActions, useUIState } from '@ai-sdk/rsc'; -import { AI } from './ai'; - -export default function Page() { - const { sendMessage } = useActions(); - const [messages, setMessages] = useUIState(); - - const handleSubmit = async event => { - event.preventDefault(); - - setMessages([ - ...messages, - { id: Date.now(), role: 'user', display: event.target.message.value }, - ]); - - const response = await sendMessage(event.target.message.value); - - setMessages([ - ...messages, - { id: Date.now(), role: 'assistant', display: response }, - ]); - }; - - return ( - <> -
    - {messages.map(message => ( -
  • {message.display}
  • - ))} -
-
- - -
- - ); -} -``` - -When the user submits a message, the `sendMessage` action is called with the message content. The response from the action is then added to the UI state, updating the displayed messages. - - - Important! Don't forget to update the UI State after you call your Server - Action otherwise the streamed component will not show in the UI. - - -To learn more, check out this [example](/examples/next-app/state-management/ai-ui-states) on managing AI and UI state using `@ai-sdk/rsc`. - ---- - -Next, you will learn how you can save and restore state with `@ai-sdk/rsc`. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/03-saving-and-restoring-states.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/03-saving-and-restoring-states.mdx deleted file mode 100644 index 8e9462ba1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/03-saving-and-restoring-states.mdx +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Saving and Restoring States -description: Saving and restoring AI and UI states with onGetUIState and onSetAIState ---- - -# Saving and Restoring States - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -AI SDK RSC provides convenient methods for saving and restoring AI and UI state. This is useful for saving the state of your application after every model generation, and restoring it when the user revisits the generations. - -## AI State - -### Saving AI state - -The AI state can be saved using the [`onSetAIState`](/docs/reference/ai-sdk-rsc/create-ai#on-set-ai-state) callback, which gets called whenever the AI state is updated. In the following example, you save the chat history to a database whenever the generation is marked as done. - -```tsx filename='app/ai.ts' -export const AI = createAI({ - actions: { - continueConversation, - }, - onSetAIState: async ({ state, done }) => { - 'use server'; - - if (done) { - saveChatToDB(state); - } - }, -}); -``` - -### Restoring AI state - -The AI state can be restored using the [`initialAIState`](/docs/reference/ai-sdk-rsc/create-ai#initial-ai-state) prop passed to the context provider created by the [`createAI`](/docs/reference/ai-sdk-rsc/create-ai) function. In the following example, you restore the chat history from a database when the component is mounted. - -```tsx file='app/layout.tsx' -import { ReactNode } from 'react'; -import { AI } from './ai'; - -export default async function RootLayout({ - children, -}: Readonly<{ children: ReactNode }>) { - const chat = await loadChatFromDB(); - - return ( - - - {children} - - - ); -} -``` - -## UI State - -### Saving UI state - -The UI state cannot be saved directly, since the contents aren't yet serializable. Instead, you can use the AI state as proxy to store details about the UI state and use it to restore the UI state when needed. - -### Restoring UI state - -The UI state can be restored using the AI state as a proxy. In the following example, you restore the chat history from the AI state when the component is mounted. You use the [`onGetUIState`](/docs/reference/ai-sdk-rsc/create-ai#on-get-ui-state) callback to listen for SSR events and restore the UI state. - -```tsx filename='app/ai.ts' -export const AI = createAI({ - actions: { - continueConversation, - }, - onGetUIState: async () => { - 'use server'; - - const historyFromDB: ServerMessage[] = await loadChatFromDB(); - const historyFromApp: ServerMessage[] = getAIState(); - - // If the history from the database is different from the - // history in the app, they're not in sync so return the UIState - // based on the history from the database - - if (historyFromDB.length !== historyFromApp.length) { - return historyFromDB.map(({ role, content }) => ({ - id: generateId(), - role, - display: - role === 'function' ? ( - - ) : ( - content - ), - })); - } - }, -}); -``` - -To learn more, check out this [example](/examples/next-app/state-management/save-and-restore-states) that persists and restores states in your Next.js application. - ---- - -Next, you will learn how you can use `@ai-sdk/rsc` functions like `useActions` and `useUIState` to create interactive, multistep interfaces. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/04-multistep-interfaces.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/04-multistep-interfaces.mdx deleted file mode 100644 index 6634f8ce4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/04-multistep-interfaces.mdx +++ /dev/null @@ -1,282 +0,0 @@ ---- -title: Multistep Interfaces -description: Overview of Building Multistep Interfaces with AI SDK RSC ---- - -# Designing Multistep Interfaces - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -Multistep interfaces refer to user interfaces that require multiple independent steps to be executed in order to complete a specific task. - -For example, if you wanted to build a Generative UI chatbot capable of booking flights, it could have three steps: - -- Search all flights -- Pick flight -- Check availability - -To build this kind of application you will leverage two concepts, **tool composition** and **application context**. - -**Tool composition** is the process of combining multiple [tools](/docs/ai-sdk-core/tools-and-tool-calling) to create a new tool. This is a powerful concept that allows you to break down complex tasks into smaller, more manageable steps. In the example above, _"search all flights"_, _"pick flight"_, and _"check availability"_ come together to create a holistic _"book flight"_ tool. - -**Application context** refers to the state of the application at any given point in time. This includes the user's input, the output of the language model, and any other relevant information. In the example above, the flight selected in _"pick flight"_ would be used as context necessary to complete the _"check availability"_ task. - -## Overview - -In order to build a multistep interface with `@ai-sdk/rsc`, you will need a few things: - -- A Server Action that calls and returns the result from the `streamUI` function -- Tool(s) (sub-tasks necessary to complete your overall task) -- React component(s) that should be rendered when the tool is called -- A page to render your chatbot - -The general flow that you will follow is: - -- User sends a message (calls your Server Action with `useActions`, passing the message as an input) -- Message is appended to the AI State and then passed to the model alongside a number of tools -- Model can decide to call a tool, which will render the `` component -- Within that component, you can add interactivity by using `useActions` to call the model with your Server Action and `useUIState` to append the model's response (``) to the UI State -- And so on... - -## Implementation - -The turn-by-turn implementation is the simplest form of multistep interfaces. In this implementation, the user and the model take turns during the conversation. For every user input, the model generates a response, and the conversation continues in this turn-by-turn fashion. - -In the following example, you specify two tools (`searchFlights` and `lookupFlight`) that the model can use to search for flights and lookup details for a specific flight. - -```tsx filename="app/actions.tsx" -import { streamUI } from '@ai-sdk/rsc'; -import { openai } from '@ai-sdk/openai'; -import { z } from 'zod'; - -const searchFlights = async ( - source: string, - destination: string, - date: string, -) => { - return [ - { - id: '1', - flightNumber: 'AA123', - }, - { - id: '2', - flightNumber: 'AA456', - }, - ]; -}; - -const lookupFlight = async (flightNumber: string) => { - return { - flightNumber: flightNumber, - departureTime: '10:00 AM', - arrivalTime: '12:00 PM', - }; -}; - -export async function submitUserMessage(input: string) { - 'use server'; - - const ui = await streamUI({ - model: openai('gpt-4o'), - system: 'you are a flight booking assistant', - prompt: input, - text: async ({ content }) =>
{content}
, - tools: { - searchFlights: { - description: 'search for flights', - inputSchema: z.object({ - source: z.string().describe('The origin of the flight'), - destination: z.string().describe('The destination of the flight'), - date: z.string().describe('The date of the flight'), - }), - generate: async function* ({ source, destination, date }) { - yield `Searching for flights from ${source} to ${destination} on ${date}...`; - const results = await searchFlights(source, destination, date); - - return ( -
- {results.map(result => ( -
-
{result.flightNumber}
-
- ))} -
- ); - }, - }, - lookupFlight: { - description: 'lookup details for a flight', - inputSchema: z.object({ - flightNumber: z.string().describe('The flight number'), - }), - generate: async function* ({ flightNumber }) { - yield `Looking up details for flight ${flightNumber}...`; - const details = await lookupFlight(flightNumber); - - return ( -
-
Flight Number: {details.flightNumber}
-
Departure Time: {details.departureTime}
-
Arrival Time: {details.arrivalTime}
-
- ); - }, - }, - }, - }); - - return ui.value; -} -``` - -Next, create an AI context that will hold the UI State and AI State. - -```ts filename='app/ai.ts' -import { createAI } from '@ai-sdk/rsc'; -import { submitUserMessage } from './actions'; - -export const AI = createAI({ - initialUIState: [], - initialAIState: [], - actions: { - submitUserMessage, - }, -}); -``` - -Next, wrap your application with your newly created context. - -```tsx filename='app/layout.tsx' -import { type ReactNode } from 'react'; -import { AI } from './ai'; - -export default function RootLayout({ - children, -}: Readonly<{ children: ReactNode }>) { - return ( - - - {children} - - - ); -} -``` - -To call your Server Action, update your root page with the following: - -```tsx filename="app/page.tsx" -'use client'; - -import { useState } from 'react'; -import { AI } from './ai'; -import { useActions, useUIState } from '@ai-sdk/rsc'; - -export default function Page() { - const [input, setInput] = useState(''); - const [conversation, setConversation] = useUIState(); - const { submitUserMessage } = useActions(); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - setInput(''); - setConversation(currentConversation => [ - ...currentConversation, -
{input}
, - ]); - const message = await submitUserMessage(input); - setConversation(currentConversation => [...currentConversation, message]); - }; - - return ( -
-
- {conversation.map((message, i) => ( -
{message}
- ))} -
-
-
- setInput(e.target.value)} - /> - -
-
-
- ); -} -``` - -This page pulls in the current UI State using the `useUIState` hook, which is then mapped over and rendered in the UI. To access the Server Action, you use the `useActions` hook which will return all actions that were passed to the `actions` key of the `createAI` function in your `actions.tsx` file. Finally, you call the `submitUserMessage` function like any other TypeScript function. This function returns a React component (`message`) that is then rendered in the UI by updating the UI State with `setConversation`. - -In this example, to call the next tool, the user must respond with plain text. **Given you are streaming a React component, you can add a button to trigger the next step in the conversation**. - -To add user interaction, you will have to convert the component into a client component and use the `useAction` hook to trigger the next step in the conversation. - -```tsx filename="components/flights.tsx" -'use client'; - -import { useActions, useUIState } from '@ai-sdk/rsc'; -import { ReactNode } from 'react'; - -interface FlightsProps { - flights: { id: string; flightNumber: string }[]; -} - -export const Flights = ({ flights }: FlightsProps) => { - const { submitUserMessage } = useActions(); - const [_, setMessages] = useUIState(); - - return ( -
- {flights.map(result => ( -
-
{ - const display = await submitUserMessage( - `lookupFlight ${result.flightNumber}`, - ); - - setMessages((messages: ReactNode[]) => [...messages, display]); - }} - > - {result.flightNumber} -
-
- ))} -
- ); -}; -``` - -Now, update your `searchFlights` tool to render the new `` component. - -```tsx filename="actions.tsx" -... -searchFlights: { - description: 'search for flights', - inputSchema: z.object({ - source: z.string().describe('The origin of the flight'), - destination: z.string().describe('The destination of the flight'), - date: z.string().describe('The date of the flight'), - }), - generate: async function* ({ source, destination, date }) { - yield `Searching for flights from ${source} to ${destination} on ${date}...`; - const results = await searchFlights(source, destination, date); - return (); - }, -} -... -``` - -In the above example, the `Flights` component is used to display the search results. When the user clicks on a flight number, the `lookupFlight` tool is called with the flight number as a parameter. The `submitUserMessage` action is then called to trigger the next step in the conversation. - -Learn more about tool calling in Next.js App Router by checking out examples [here](/examples/next-app/tools). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/05-streaming-values.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/05-streaming-values.mdx deleted file mode 100644 index ff7614a9c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/05-streaming-values.mdx +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: Streaming Values -description: Overview of streaming RSCs ---- - -import { UIPreviewCard, Card } from '@/components/home/card'; -import { EventPlanning } from '@/components/home/event-planning'; -import { Searching } from '@/components/home/searching'; -import { Weather } from '@/components/home/weather'; - -# Streaming Values - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -The RSC API provides several utility functions to allow you to stream values from the server to the client. This is useful when you need more granular control over what you are streaming and how you are streaming it. - - - These utilities can also be paired with [AI SDK Core](/docs/ai-sdk-core) - functions like [`streamText`](/docs/reference/ai-sdk-core/stream-text) to - easily stream LLM generations from the server to the client. - - -There are two functions provided by the RSC API that allow you to create streamable values: - -- [`createStreamableValue`](/docs/reference/ai-sdk-rsc/create-streamable-value) - creates a streamable (serializable) value, with full control over how you create, update, and close the stream. -- [`createStreamableUI`](/docs/reference/ai-sdk-rsc/create-streamable-ui) - creates a streamable React component, with full control over how you create, update, and close the stream. - -## `createStreamableValue` - -The RSC API allows you to stream serializable JavaScript values from the server to the client using [`createStreamableValue`](/docs/reference/ai-sdk-rsc/create-streamable-value), such as strings, numbers, objects, and arrays. - -This is useful when you want to stream: - -- Text generations from the language model in real-time. -- Buffer values of image and audio generations from multi-modal models. -- Progress updates from multi-step agent runs. - -## Creating a Streamable Value - -You can import `createStreamableValue` from `@ai-sdk/rsc` and use it to create a streamable value. - -```tsx file='app/actions.ts' -'use server'; - -import { createStreamableValue } from '@ai-sdk/rsc'; - -export const runThread = async () => { - const streamableStatus = createStreamableValue('thread.init'); - - setTimeout(() => { - streamableStatus.update('thread.run.create'); - streamableStatus.update('thread.run.update'); - streamableStatus.update('thread.run.end'); - streamableStatus.done('thread.end'); - }, 1000); - - return { - status: streamableStatus.value, - }; -}; -``` - -## Reading a Streamable Value - -You can read streamable values on the client using `readStreamableValue`. It returns an async iterator that yields the value of the streamable as it is updated: - -```tsx file='app/page.tsx' -import { readStreamableValue } from '@ai-sdk/rsc'; -import { runThread } from '@/actions'; - -export default function Page() { - return ( - - ); -} -``` - -Learn how to stream a text generation (with `streamText`) using the Next.js App Router and `createStreamableValue` in this [example](/examples/next-app/basics/streaming-text-generation). - -## `createStreamableUI` - -`createStreamableUI` creates a stream that holds a React component. Unlike AI SDK Core APIs, this function does not call a large language model. Instead, it provides a primitive that can be used to have granular control over streaming a React component. - -## Using `createStreamableUI` - -Let's look at how you can use the `createStreamableUI` function with a Server Action. - -```tsx filename='app/actions.tsx' -'use server'; - -import { createStreamableUI } from '@ai-sdk/rsc'; - -export async function getWeather() { - const weatherUI = createStreamableUI(); - - weatherUI.update(
Loading...
); - - setTimeout(() => { - weatherUI.done(
It's a sunny day!
); - }, 1000); - - return weatherUI.value; -} -``` - -First, you create a streamable UI with an empty state and then update it with a loading message. After 1 second, you mark the stream as done passing in the actual weather information as its final value. The `.value` property contains the actual UI that can be sent to the client. - -## Reading a Streamable UI - -On the client side, you can call the `getWeather` Server Action and render the returned UI like any other React component. - -```tsx filename='app/page.tsx' -'use client'; - -import { useState } from 'react'; -import { readStreamableValue } from '@ai-sdk/rsc'; -import { getWeather } from '@/actions'; - -export default function Page() { - const [weather, setWeather] = useState(null); - - return ( -
- - - {weather} -
- ); -} -``` - -When the button is clicked, the `getWeather` function is called, and the returned UI is set to the `weather` state and rendered on the page. Users will see the loading message first and then the actual weather information after 1 second. - -Learn more about handling multiple streams in a single request in the [Multiple Streamables](/docs/advanced/multiple-streamables) guide. - -Learn more about handling state for more complex use cases with [ AI/UI State ](/docs/ai-sdk-rsc/generative-ui-state). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/06-loading-state.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/06-loading-state.mdx deleted file mode 100644 index bd3e31d78..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/06-loading-state.mdx +++ /dev/null @@ -1,273 +0,0 @@ ---- -title: Handling Loading State -description: Overview of handling loading state with AI SDK RSC ---- - -# Handling Loading State - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -Given that responses from language models can often take a while to complete, it's crucial to be able to show loading state to users. This provides visual feedback that the system is working on their request and helps maintain a positive user experience. - -There are three approaches you can take to handle loading state with the AI SDK RSC: - -- Managing loading state similar to how you would in a traditional Next.js application. This involves setting a loading state variable in the client and updating it when the response is received. -- Streaming loading state from the server to the client. This approach allows you to track loading state on a more granular level and provide more detailed feedback to the user. -- Streaming loading component from the server to the client. This approach allows you to stream a React Server Component to the client while awaiting the model's response. - -## Handling Loading State on the Client - -### Client - -Let's create a simple Next.js page that will call the `generateResponse` function when the form is submitted. The function will take in the user's prompt (`input`) and then generate a response (`response`). To handle the loading state, use the `loading` state variable. When the form is submitted, set `loading` to `true`, and when the response is received, set it back to `false`. While the response is being streamed, the input field will be disabled. - -```tsx filename='app/page.tsx' -'use client'; - -import { useState } from 'react'; -import { generateResponse } from './actions'; -import { readStreamableValue } from '@ai-sdk/rsc'; - -// Force the page to be dynamic and allow streaming responses up to 30 seconds -export const maxDuration = 30; - -export default function Home() { - const [input, setInput] = useState(''); - const [generation, setGeneration] = useState(''); - const [loading, setLoading] = useState(false); - - return ( -
-
{generation}
-
{ - e.preventDefault(); - setLoading(true); - const response = await generateResponse(input); - - let textContent = ''; - - for await (const delta of readStreamableValue(response)) { - textContent = `${textContent}${delta}`; - setGeneration(textContent); - } - setInput(''); - setLoading(false); - }} - > - { - setInput(event.target.value); - }} - /> - -
-
- ); -} -``` - -### Server - -Now let's implement the `generateResponse` function. Use the `streamText` function to generate a response to the input. - -```typescript filename='app/actions.ts' -'use server'; - -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; -import { createStreamableValue } from '@ai-sdk/rsc'; - -export async function generateResponse(prompt: string) { - const stream = createStreamableValue(); - - (async () => { - const { textStream } = streamText({ - model: __MODEL__, - prompt, - }); - - for await (const text of textStream) { - stream.update(text); - } - - stream.done(); - })(); - - return stream.value; -} -``` - -## Streaming Loading State from the Server - -If you are looking to track loading state on a more granular level, you can create a new streamable value to store a custom variable and then read this on the frontend. Let's update the example to create a new streamable value for tracking loading state: - -### Server - -```typescript filename='app/actions.ts' highlight='9,22,25' -'use server'; - -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; -import { createStreamableValue } from '@ai-sdk/rsc'; - -export async function generateResponse(prompt: string) { - const stream = createStreamableValue(); - const loadingState = createStreamableValue({ loading: true }); - - (async () => { - const { textStream } = streamText({ - model: __MODEL__, - prompt, - }); - - for await (const text of textStream) { - stream.update(text); - } - - stream.done(); - loadingState.done({ loading: false }); - })(); - - return { response: stream.value, loadingState: loadingState.value }; -} -``` - -### Client - -```tsx filename='app/page.tsx' highlight="22,30-34" -'use client'; - -import { useState } from 'react'; -import { generateResponse } from './actions'; -import { readStreamableValue } from '@ai-sdk/rsc'; - -// Force the page to be dynamic and allow streaming responses up to 30 seconds -export const maxDuration = 30; - -export default function Home() { - const [input, setInput] = useState(''); - const [generation, setGeneration] = useState(''); - const [loading, setLoading] = useState(false); - - return ( -
-
{generation}
-
{ - e.preventDefault(); - setLoading(true); - const { response, loadingState } = await generateResponse(input); - - let textContent = ''; - - for await (const responseDelta of readStreamableValue(response)) { - textContent = `${textContent}${responseDelta}`; - setGeneration(textContent); - } - for await (const loadingDelta of readStreamableValue(loadingState)) { - if (loadingDelta) { - setLoading(loadingDelta.loading); - } - } - setInput(''); - setLoading(false); - }} - > - { - setInput(event.target.value); - }} - /> - -
-
- ); -} -``` - -This allows you to provide more detailed feedback about the generation process to your users. - -## Streaming Loading Components with `streamUI` - -If you are using the [ `streamUI` ](/docs/reference/ai-sdk-rsc/stream-ui) function, you can stream the loading state to the client in the form of a React component. `streamUI` supports the usage of [ JavaScript generator functions ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*), which allow you to yield some value (in this case a React component) while some other blocking work completes. - -## Server - -```ts -'use server'; - -import { openai } from '@ai-sdk/openai'; -import { streamUI } from '@ai-sdk/rsc'; - -export async function generateResponse(prompt: string) { - const result = await streamUI({ - model: openai('gpt-4o'), - prompt, - text: async function* ({ content }) { - yield
loading...
; - return
{content}
; - }, - }); - - return result.value; -} -``` - - - Remember to update the file from `.ts` to `.tsx` because you are defining a - React component in the `streamUI` function. - - -## Client - -```tsx -'use client'; - -import { useState } from 'react'; -import { generateResponse } from './actions'; -import { readStreamableValue } from '@ai-sdk/rsc'; - -// Force the page to be dynamic and allow streaming responses up to 30 seconds -export const maxDuration = 30; - -export default function Home() { - const [input, setInput] = useState(''); - const [generation, setGeneration] = useState(); - - return ( -
-
{generation}
-
{ - e.preventDefault(); - const result = await generateResponse(input); - setGeneration(result); - setInput(''); - }} - > - { - setInput(event.target.value); - }} - /> - -
-
- ); -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/08-error-handling.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/08-error-handling.mdx deleted file mode 100644 index d8f158214..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/08-error-handling.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Error Handling -description: Learn how to handle errors with the AI SDK. ---- - -# Error Handling - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -Two categories of errors can occur when working with the RSC API: errors while streaming user interfaces and errors while streaming other values. - -## Handling UI Errors - -To handle errors while generating UI, the [`streamableUI`](/docs/reference/ai-sdk-rsc/create-streamable-ui) object exposes an `error()` method. - -```tsx filename='app/actions.tsx' -'use server'; - -import { createStreamableUI } from '@ai-sdk/rsc'; - -export async function getStreamedUI() { - const ui = createStreamableUI(); - - (async () => { - ui.update(
loading
); - const data = await fetchData(); - ui.done(
{data}
); - })().catch(e => { - ui.error(
Error: {e.message}
); - }); - - return ui.value; -} -``` - -With this method, you can catch any error with the stream, and return relevant UI. On the client, you can also use a [React Error Boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) to wrap the streamed component and catch any additional errors. - -```tsx filename='app/page.tsx' -import { getStreamedUI } from '@/actions'; -import { useState } from 'react'; -import { ErrorBoundary } from './ErrorBoundary'; - -export default function Page() { - const [streamedUI, setStreamedUI] = useState(null); - - return ( -
- - {streamedUI} -
- ); -} -``` - -## Handling Other Errors - -To handle other errors while streaming, you can return an error object that the receiver can use to determine why the failure occurred. - -```tsx filename='app/actions.tsx' -'use server'; - -import { createStreamableValue } from '@ai-sdk/rsc'; -import { fetchData, emptyData } from '../utils/data'; - -export const getStreamedData = async () => { - const streamableData = createStreamableValue(emptyData); - - (async () => { - const data1 = await fetchData(); - streamableData.update(data1); - - const data2 = await fetchData(); - streamableData.update(data2); - - const data3 = await fetchData(); - streamableData.done(data3); - })().catch(e => { - streamableData.error(e); - }); - - return { data: streamableData.value }; -}; -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/09-authentication.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/09-authentication.mdx deleted file mode 100644 index 82f0403ee..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/09-authentication.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Handling Authentication -description: Learn how to authenticate with the AI SDK. ---- - -# Authentication - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -The RSC API makes extensive use of [`Server Actions`](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations) to power streaming values and UI from the server. - -Server Actions are exposed as public, unprotected endpoints. As a result, you should treat Server Actions as you would public-facing API endpoints and ensure that the user is authorized to perform the action before returning any data. - -```tsx filename="app/actions.tsx" -'use server'; - -import { cookies } from 'next/headers'; -import { createStreamableUI } from '@ai-sdk/rsc'; -import { validateToken } from '../utils/auth'; - -export const getWeather = async () => { - const token = cookies().get('token'); - - if (!token || !validateToken(token)) { - return { - error: 'This action requires authentication', - }; - } - const streamableDisplay = createStreamableUI(null); - - streamableDisplay.update(); - streamableDisplay.done(); - - return { - display: streamableDisplay.value, - }; -}; -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/10-migrating-to-ui.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/10-migrating-to-ui.mdx deleted file mode 100644 index cee2eee26..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/10-migrating-to-ui.mdx +++ /dev/null @@ -1,722 +0,0 @@ ---- -title: Migrating from RSC to UI -description: Learn how to migrate from AI SDK RSC to AI SDK UI. ---- - -# Migrating from RSC to UI - -This guide helps you migrate from AI SDK RSC to AI SDK UI. - -## Background - -The AI SDK has two packages that help you build the frontend for your applications – [AI SDK UI](/docs/ai-sdk-ui) and [AI SDK RSC](/docs/ai-sdk-rsc). - -We introduced support for using [React Server Components](https://react.dev/reference/rsc/server-components) (RSC) within the AI SDK to simplify building generative user interfaces for frameworks that support RSC. - -However, given we're pushing the boundaries of this technology, AI SDK RSC currently faces significant limitations that make it unsuitable for stable production use. - -- It is not possible to abort a stream using server actions. This will be improved in future releases of React and Next.js [(1122)](https://github.com/vercel/ai/issues/1122). -- When using `createStreamableUI` and `streamUI`, components remount on `.done()`, causing them to flicker [(2939)](https://github.com/vercel/ai/issues/2939). -- Many suspense boundaries can lead to crashes [(2843)](https://github.com/vercel/ai/issues/2843). -- Using `createStreamableUI` can lead to quadratic data transfer. You can avoid this using createStreamableValue instead, and rendering the component client-side. -- Closed RSC streams cause update issues [(3007)](https://github.com/vercel/ai/issues/3007). - -Due to these limitations, AI SDK RSC is marked as experimental, and we do not recommend using it for stable production environments. - -As a result, we strongly recommend migrating to AI SDK UI, which has undergone extensive development to provide a more stable and production grade experience. - -In building [v0](https://v0.dev), we have invested considerable time exploring how to create the best chat experience on the web. AI SDK UI ships with many of these best practices and commonly used patterns like [language model middleware](/docs/ai-sdk-core/middleware), [multi-step tool calls](/docs/ai-sdk-core/tools-and-tool-calling#multi-step-calls), [attachments](/docs/ai-sdk-ui/chatbot#attachments-experimental), [telemetry](/docs/ai-sdk-core/telemetry), [provider registry](/docs/ai-sdk-core/provider-management#provider-registry), and many more. These features have been considerately designed into a neat abstraction that you can use to reliably integrate AI into your applications. - -## Streaming Chat Completions - -### Basic Setup - -The `streamUI` function executes as part of a server action as illustrated below. - -#### Before: Handle generation and rendering in a single server action - -```tsx filename="@/app/actions.tsx" -import { openai } from '@ai-sdk/openai'; -import { getMutableAIState, streamUI } from '@ai-sdk/rsc'; - -export async function sendMessage(message: string) { - 'use server'; - - const messages = getMutableAIState('messages'); - - messages.update([...messages.get(), { role: 'user', content: message }]); - - const { value: stream } = await streamUI({ - model: openai('gpt-4o'), - system: 'you are a friendly assistant!', - messages: messages.get(), - text: async function* ({ content, done }) { - // process text - }, - tools: { - // tool definitions - }, - }); - - return stream; -} -``` - -#### Before: Call server action and update UI state - -The chat interface calls the server action. The response is then saved using the `useUIState` hook. - -```tsx filename="@/app/page.tsx" -'use client'; - -import { useState, ReactNode } from 'react'; -import { useActions, useUIState } from '@ai-sdk/rsc'; - -export default function Page() { - const { sendMessage } = useActions(); - const [input, setInput] = useState(''); - const [messages, setMessages] = useUIState(); - - return ( -
- {messages.map(message => message)} - -
{ - const response: ReactNode = await sendMessage(input); - setMessages(msgs => [...msgs, response]); - }} - > - - -
-
- ); -} -``` - -The `streamUI` function combines generating text and rendering the user interface. To migrate to AI SDK UI, you need to **separate these concerns** – streaming generations with `streamText` and rendering the UI with `useChat`. - -#### After: Replace server action with route handler - -The `streamText` function executes as part of a route handler and streams the response to the client. The `useChat` hook on the client decodes this stream and renders the response within the chat interface. - -```ts filename="@/app/api/chat/route.ts" -import { streamText } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -export async function POST(request) { - const { messages } = await request.json(); - - const result = streamText({ - model: __MODEL__, - system: 'you are a friendly assistant!', - messages, - tools: { - // tool definitions - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -#### After: Update client to use chat hook - -```tsx filename="@/app/page.tsx" -'use client'; - -import { useChat } from '@ai-sdk/react'; - -export default function Page() { - const { messages, input, setInput, handleSubmit } = useChat(); - - return ( -
- {messages.map(message => ( -
-
{message.role}
-
{message.content}
-
- ))} - -
- { - setInput(event.target.value); - }} - /> - -
-
- ); -} -``` - -### Parallel Tool Calls - -In AI SDK RSC, `streamUI` does not support parallel tool calls. You will have to use a combination of `streamText`, `createStreamableUI` and `createStreamableValue`. - -With AI SDK UI, `useChat` comes with built-in support for parallel tool calls. You can define multiple tools in the `streamText` and have them called them in parallel. The `useChat` hook will then handle the parallel tool calls for you automatically. - -### Multi-Step Tool Calls - -In AI SDK RSC, `streamUI` does not support multi-step tool calls. You will have to use a combination of `streamText`, `createStreamableUI` and `createStreamableValue`. - -With AI SDK UI, `useChat` comes with built-in support for multi-step tool calls. You can set `maxSteps` in the `streamText` function to define the number of steps the language model can make in a single call. The `useChat` hook will then handle the multi-step tool calls for you automatically. - -### Generative User Interfaces - -The `streamUI` function uses `tools` as a way to execute functions based on user input and renders React components based on the function output to go beyond text in the chat interface. - -#### Before: Render components within the server action and stream to client - -```tsx filename="@/app/actions.tsx" -import { z } from 'zod'; -import { streamUI } from '@ai-sdk/rsc'; -import { openai } from '@ai-sdk/openai'; -import { getWeather } from '@/utils/queries'; -import { Weather } from '@/components/weather'; - -const { value: stream } = await streamUI({ - model: openai('gpt-4o'), - system: 'you are a friendly assistant!', - messages, - text: async function* ({ content, done }) { - // process text - }, - tools: { - displayWeather: { - description: 'Display the weather for a location', - inputSchema: z.object({ - latitude: z.number(), - longitude: z.number(), - }), - generate: async function* ({ latitude, longitude }) { - yield
Loading weather...
; - - const { value, unit } = await getWeather({ latitude, longitude }); - - return ; - }, - }, - }, -}); -``` - -As mentioned earlier, `streamUI` generates text and renders the React component in a single server action call. - -#### After: Replace with route handler and stream props data to client - -The `streamText` function streams the props data as response to the client, while `useChat` decode the stream as `toolInvocations` and renders the chat interface. - -```ts filename="@/app/api/chat/route.ts" -import { z } from 'zod'; -import { openai } from '@ai-sdk/openai'; -import { getWeather } from '@/utils/queries'; -import { streamText } from 'ai'; - -export async function POST(request) { - const { messages } = await request.json(); - - const result = streamText({ - model: __MODEL__, - system: 'you are a friendly assistant!', - messages, - tools: { - displayWeather: { - description: 'Display the weather for a location', - parameters: z.object({ - latitude: z.number(), - longitude: z.number(), - }), - execute: async function ({ latitude, longitude }) { - const props = await getWeather({ latitude, longitude }); - return props; - }, - }, - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -#### After: Update client to use chat hook and render components using tool invocations - -```tsx filename="@/app/page.tsx" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import { Weather } from '@/components/weather'; - -export default function Page() { - const { messages, input, setInput, handleSubmit } = useChat(); - - return ( -
- {messages.map(message => ( -
-
{message.role}
-
{message.content}
- -
- {message.toolInvocations.map(toolInvocation => { - const { toolName, toolCallId, state } = toolInvocation; - - if (state === 'result') { - const { result } = toolInvocation; - - return ( -
- {toolName === 'displayWeather' ? ( - - ) : null} -
- ); - } else { - return ( -
- {toolName === 'displayWeather' ? ( -
Loading weather...
- ) : null} -
- ); - } - })} -
-
- ))} - -
- { - setInput(event.target.value); - }} - /> - -
-
- ); -} -``` - -### Handling Client Interactions - -With AI SDK RSC, components streamed to the client can trigger subsequent generations by calling the relevant server action using the `useActions` hooks. This is possible as long as the component is a descendant of the `` context provider. - -#### Before: Use actions hook to send messages - -```tsx filename="@/app/components/list-flights.tsx" -'use client'; - -import { useActions, useUIState } from '@ai-sdk/rsc'; - -export function ListFlights({ flights }) { - const { sendMessage } = useActions(); - const [_, setMessages] = useUIState(); - - return ( -
- {flights.map(flight => ( -
{ - const response = await sendMessage( - `I would like to choose flight ${flight.id}!`, - ); - - setMessages(msgs => [...msgs, response]); - }} - > - {flight.name} -
- ))} -
- ); -} -``` - -#### After: Use another chat hook with same ID from the component - -After switching to AI SDK UI, these messages are synced by initializing the `useChat` hook in the component with the same `id` as the parent component. - -```tsx filename="@/app/components/list-flights.tsx" -'use client'; - -import { useChat } from '@ai-sdk/react'; - -export function ListFlights({ chatId, flights }) { - const { append } = useChat({ - id: chatId, - body: { id: chatId }, - maxSteps: 5, - }); - - return ( -
- {flights.map(flight => ( -
{ - await append({ - role: 'user', - content: `I would like to choose flight ${flight.id}!`, - }); - }} - > - {flight.name} -
- ))} -
- ); -} -``` - -### Loading Indicators - -In AI SDK RSC, you can use the `initial` parameter of `streamUI` to define the component to display while the generation is in progress. - -#### Before: Use `loading` to show loading indicator - -```tsx filename="@/app/actions.tsx" -import { openai } from '@ai-sdk/openai'; -import { streamUI } from '@ai-sdk/rsc'; - -const { value: stream } = await streamUI({ - model: openai('gpt-4o'), - system: 'you are a friendly assistant!', - messages, - initial:
Loading...
, - text: async function* ({ content, done }) { - // process text - }, - tools: { - // tool definitions - }, -}); - -return stream; -``` - -With AI SDK UI, you can use the tool invocation state to show a loading indicator while the tool is executing. - -#### After: Use tool invocation state to show loading indicator - -```tsx filename="@/app/components/message.tsx" -'use client'; - -export function Message({ role, content, toolInvocations }) { - return ( -
-
{role}
-
{content}
- - {toolInvocations && ( -
- {toolInvocations.map(toolInvocation => { - const { toolName, toolCallId, state } = toolInvocation; - - if (state === 'result') { - const { result } = toolInvocation; - - return ( -
- {toolName === 'getWeather' ? ( - - ) : null} -
- ); - } else { - return ( -
- {toolName === 'getWeather' ? ( - - ) : ( -
Loading...
- )} -
- ); - } - })} -
- )} -
- ); -} -``` - -### Saving Chats - -Before implementing `streamUI` as a server action, you should create an `` provider and wrap your application at the root layout to sync the AI and UI states. During initialization, you typically use the `onSetAIState` callback function to track updates to the AI state and save it to the database when `done(...)` is called. - -#### Before: Save chats using callback function of context provider - -```ts filename="@/app/actions.ts" -import { createAI } from '@ai-sdk/rsc'; -import { saveChat } from '@/utils/queries'; - -export const AI = createAI({ - initialAIState: {}, - initialUIState: {}, - actions: { - // server actions - }, - onSetAIState: async ({ state, done }) => { - 'use server'; - - if (done) { - await saveChat(state); - } - }, -}); -``` - -#### After: Save chats using callback function of `streamText` - -With AI SDK UI, you will save chats using the `onFinish` callback function of `streamText` in your route handler. - -```ts filename="@/app/api/chat/route.ts" -import { openai } from '@ai-sdk/openai'; -import { saveChat } from '@/utils/queries'; -import { streamText, convertToModelMessages } from 'ai'; - -export async function POST(request) { - const { id, messages } = await request.json(); - - const coreMessages = await convertToModelMessages(messages); - - const result = streamText({ - model: __MODEL__, - system: 'you are a friendly assistant!', - messages: coreMessages, - onFinish: async ({ response }) => { - try { - await saveChat({ - id, - messages: [...coreMessages, ...response.messages], - }); - } catch (error) { - console.error('Failed to save chat'); - } - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -### Restoring Chats - -When using AI SDK RSC, the `useUIState` hook contains the UI state of the chat. When restoring a previously saved chat, the UI state needs to be loaded with messages. - -Similar to how you typically save chats in AI SDK RSC, you should use the `onGetUIState` callback function to retrieve the chat from the database, convert it into UI state, and return it to be accessible through `useUIState`. - -#### Before: Load chat from database using callback function of context provider - -```ts filename="@/app/actions.ts" -import { createAI } from '@ai-sdk/rsc'; -import { loadChatFromDB, convertToUIState } from '@/utils/queries'; - -export const AI = createAI({ - actions: { - // server actions - }, - onGetUIState: async () => { - 'use server'; - - const chat = await loadChatFromDB(); - const uiState = convertToUIState(chat); - - return uiState; - }, -}); -``` - -AI SDK UI uses the `messages` field of `useChat` to store messages. To load messages when `useChat` is mounted, you should use `initialMessages`. - -As messages are typically loaded from the database, we can use a server actions inside a Page component to fetch an older chat from the database during static generation and pass the messages as props to the `` component. - -#### After: Load chat from database during static generation of page - -```tsx filename="@/app/chat/[id]/page.tsx" -import { Chat } from '@/app/components/chat'; -import { getChatById } from '@/utils/queries'; - -// link to example implementation: https://github.com/vercel/ai-chatbot/blob/00b125378c998d19ef60b73fe576df0fe5a0e9d4/lib/utils.ts#L87-L127 -import { convertToUIMessages } from '@/utils/functions'; - -export default async function Page({ params }: { params: any }) { - const { id } = params; - const chatFromDb = await getChatById({ id }); - - const chat: Chat = { - ...chatFromDb, - messages: convertToUIMessages(chatFromDb.messages), - }; - - return ; -} -``` - -#### After: Pass chat messages as props and load into chat hook - -```tsx filename="@/app/components/chat.tsx" -'use client'; - -import { Message } from 'ai'; -import { useChat } from '@ai-sdk/react'; - -export function Chat({ - id, - initialMessages, -}: { - id; - initialMessages: Array; -}) { - const { messages } = useChat({ - id, - initialMessages, - }); - - return ( -
- {messages.map(message => ( -
-
{message.role}
-
{message.content}
-
- ))} -
- ); -} -``` - -## Streaming Object Generation - -The `createStreamableValue` function streams any serializable data from the server to the client. As a result, this function allows you to stream object generations from the server to the client when paired with `streamText` and `Output`. - -#### Before: Use streamable value to stream object generations - -```ts filename="@/app/actions.ts" -import { Output, streamText } from 'ai'; -import { openai } from '@ai-sdk/openai'; -import { createStreamableValue } from '@ai-sdk/rsc'; -import { notificationsSchema } from '@/utils/schemas'; - -export async function generateSampleNotifications() { - 'use server'; - - const stream = createStreamableValue(); - - (async () => { - const { partialOutputStream } = streamText({ - model: __MODEL__, - system: 'generate sample ios messages for testing', - prompt: 'messages from a family group chat during diwali, max 4', - output: Output.object({ schema: notificationsSchema }), - }); - - for await (const partialObject of partialOutputStream) { - stream.update(partialObject); - } - })(); - - stream.done(); - - return { partialNotificationsStream: stream.value }; -} -``` - -#### Before: Read streamable value and update object - -```tsx filename="@/app/page.tsx" -'use client'; - -import { useState } from 'react'; -import { readStreamableValue } from '@ai-sdk/rsc'; -import { generateSampleNotifications } from '@/app/actions'; - -export default function Page() { - const [notifications, setNotifications] = useState(null); - - return ( -
- -
- ); -} -``` - -To migrate to AI SDK UI, you should use the `useObject` hook and implement `streamText` with `Output` within your route handler. - -#### After: Replace with route handler and stream text response - -```ts filename="@/app/api/object/route.ts" -import { Output, streamText } from 'ai'; -import { openai } from '@ai-sdk/openai'; -import { notificationSchema } from '@/utils/schemas'; - -export async function POST(req: Request) { - const context = await req.json(); - - const result = streamText({ - model: __MODEL__, - output: Output.object({ schema: notificationSchema }), - prompt: - `Generate 3 notifications for a messages app in this context:` + context, - }); - - return result.toTextStreamResponse(); -} -``` - -#### After: Use object hook to decode stream and update object - -```tsx filename="@/app/page.tsx" -'use client'; - -import { useObject } from '@ai-sdk/react'; -import { notificationSchema } from '@/utils/schemas'; - -export default function Page() { - const { object, submit } = useObject({ - api: '/api/object', - schema: notificationSchema, - }); - - return ( -
- - - {object?.notifications?.map((notification, index) => ( -
-

{notification?.name}

-

{notification?.message}

-
- ))} -
- ); -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/index.mdx deleted file mode 100644 index 7713bbdbe..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/05-ai-sdk-rsc/index.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: AI SDK RSC -description: Learn about AI SDK RSC. -collapsed: true ---- - -# AI SDK RSC - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/01-prompt-engineering.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/01-prompt-engineering.mdx deleted file mode 100644 index 1ce6c2e79..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/01-prompt-engineering.mdx +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Prompt Engineering -description: Learn how to engineer prompts for LLMs with the AI SDK ---- - -# Prompt Engineering - -## What is a Large Language Model (LLM)? - -A Large Language Model is essentially a prediction engine that takes a sequence of words as input and aims to predict the most likely sequence to follow. It does this by assigning probabilities to potential next sequences and then selecting one. The model continues to generate sequences until it meets a specified stopping criterion. - -These models learn by training on massive text corpuses, which means they will be better suited to some use cases than others. For example, a model trained on GitHub data would understand the probabilities of sequences in source code particularly well. However, it's crucial to understand that the generated sequences, while often seeming plausible, can sometimes be random and not grounded in reality. As these models become more accurate, many surprising abilities and applications emerge. - -## What is a prompt? - -Prompts are the starting points for LLMs. They are the inputs that trigger the model to generate text. The scope of prompt engineering involves not just crafting these prompts but also understanding related concepts such as hidden prompts, tokens, token limits, and the potential for prompt hacking, which includes phenomena like jailbreaks and leaks. - -## Why is prompt engineering needed? - -Prompt engineering currently plays a pivotal role in shaping the responses of LLMs. It allows us to tweak the model to respond more effectively to a broader range of queries. This includes the use of techniques like semantic search, command grammars, and the ReActive model architecture. The performance, context window, and cost of LLMs varies between models and model providers which adds further constraints to the mix. For example, the GPT-4 model is more expensive than GPT-3.5-turbo and significantly slower, but it can also be more effective at certain tasks. And so, like many things in software engineering, there is a trade-offs between cost and performance. - -To assist with comparing and tweaking LLMs, we've built an AI playground that allows you to compare the performance of different models side-by-side online. When you're ready, you can even generate code with the AI SDK to quickly use your prompt and your selected model into your own applications. - -## Example: Build a Slogan Generator - -### Start with an instruction - -Imagine you want to build a slogan generator for marketing campaigns. Creating catchy slogans isn't always straightforward! - -First, you'll need a prompt that makes it clear what you want. Let's start with an instruction. Submit this prompt to generate your first completion. - - - -Not bad! Now, try making your instruction more specific. - - - -Introducing a single descriptive term to our prompt influences the completion. Essentially, crafting your prompt is the means by which you "instruct" or "program" the model. - -### Include examples - -Clear instructions are key for quality outcomes, but that might not always be enough. Let's try to enhance your instruction further. - - - -These slogans are fine, but could be even better. It appears the model overlooked the 'live' part in our prompt. Let's change it slightly to generate more appropriate suggestions. - -Often, it's beneficial to both demonstrate and tell the model your requirements. Incorporating examples in your prompt can aid in conveying patterns or subtleties. Test this prompt that carries a few examples. - - - -Great! Incorporating examples of expected output for a certain input prompted the model to generate the kind of names we aimed for. - -### Tweak your settings - -Apart from designing prompts, you can influence completions by tweaking model settings. A crucial setting is the **temperature**. - -You might have seen that the same prompt, when repeated, yielded the same or nearly the same completions. This happens when your temperature is at 0. - -Attempt to re-submit the identical prompt a few times with temperature set to 1. - - - -Notice the difference? With a temperature above 0, the same prompt delivers varied completions each time. - -Keep in mind that the model forecasts the text most likely to follow the preceding text. Temperature, a value from 0 to 1, essentially governs the model's confidence level in making these predictions. A lower temperature implies lesser risks, leading to more precise and deterministic completions. A higher temperature yields a broader range of completions. - -For your slogan generator, you might want a large pool of name suggestions. A moderate temperature of 0.6 should serve well. - -## Recommended Resources - -Prompt Engineering is evolving rapidly, with new methods and research papers surfacing every week. Here are some resources that we've found useful for learning about and experimenting with prompt engineering: - -- [The Vercel AI Playground](/playground) -- [Brex Prompt Engineering](https://github.com/brexhq/prompt-engineering) -- [Prompt Engineering Guide by Dair AI](https://www.promptingguide.ai/) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/02-stopping-streams.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/02-stopping-streams.mdx deleted file mode 100644 index ef6dec443..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/02-stopping-streams.mdx +++ /dev/null @@ -1,184 +0,0 @@ ---- -title: Stopping Streams -description: Learn how to cancel streams with the AI SDK ---- - -# Stopping Streams - -Canceling ongoing streams is often needed. -For example, users might want to stop a stream when they realize that the response is not what they want. - -The different parts of the AI SDK support canceling streams in different ways. - -## AI SDK Core - -The AI SDK functions have an `abortSignal` argument that you can use to cancel a stream. -You would use this if you want to cancel a stream from the server side to the LLM API, e.g. by -forwarding the `abortSignal` from the request. - -```tsx highlight="10,11,12-16" -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -export async function POST(req: Request) { - const { prompt } = await req.json(); - - const result = streamText({ - model: __MODEL__, - prompt, - // forward the abort signal: - abortSignal: req.signal, - onAbort: ({ steps }) => { - // Handle cleanup when stream is aborted - console.log('Stream aborted after', steps.length, 'steps'); - // Persist partial results to database - }, - }); - - return result.toTextStreamResponse(); -} -``` - -## AI SDK UI - -The hooks, e.g. `useChat` or `useCompletion`, provide a `stop` helper function that can be used to cancel a stream. -This will cancel the stream from the client side to the server. - - - Stream abort functionality is not compatible with stream resumption. If you're - using `resume: true` in `useChat`, the abort functionality will break the - resumption mechanism. Choose either abort or resume functionality, but not - both. - - -```tsx file="app/page.tsx" highlight="9,18-20" -'use client'; - -import { useCompletion } from '@ai-sdk/react'; - -export default function Chat() { - const { input, completion, stop, status, handleSubmit, handleInputChange } = - useCompletion(); - - return ( -
- {(status === 'submitted' || status === 'streaming') && ( - - )} - {completion} -
- -
-
- ); -} -``` - -## Handling stream abort cleanup - -When streams are aborted, you may need to perform cleanup operations such as persisting partial results or cleaning up resources. The `onAbort` callback provides a way to handle these scenarios on the server side. - -Unlike `onFinish`, which is called when a stream completes normally, `onAbort` is specifically called when a stream is aborted via `AbortSignal`. This distinction allows you to handle normal completion and aborted streams differently. - - - For UI message streams (`toUIMessageStreamResponse`), the `onFinish` callback - also receives an `isAborted` parameter that indicates whether the stream was - aborted. This allows you to handle both completion and abort scenarios in a - single callback. - - -```tsx highlight="8-12" -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const result = streamText({ - model: __MODEL__, - prompt: 'Write a long story...', - abortSignal: controller.signal, - onAbort: ({ steps }) => { - // Called when stream is aborted - persist partial results - await savePartialResults(steps); - await logAbortEvent(steps.length); - }, - onFinish: ({ steps, totalUsage }) => { - // Called when stream completes normally - await saveFinalResults(steps, totalUsage); - }, -}); -``` - -The `onAbort` callback receives: - -- `steps`: Array of all completed steps before the abort occurred - -This is particularly useful for: - -- Persisting partial conversation history to database -- Saving partial progress for later continuation -- Cleaning up server-side resources or connections -- Logging abort events for analytics - -You can also handle abort events directly in the stream using the `abort` stream part: - -```tsx highlight="8-12" -for await (const part of result.fullStream) { - switch (part.type) { - case 'text-delta': - // Handle text delta content - break; - case 'abort': - // Handle abort event directly in stream - console.log('Stream was aborted'); - break; - // ... other cases - } -} -``` - -## UI Message Streams - -When using `toUIMessageStreamResponse`, you need to handle stream abortion slightly differently. The `onFinish` callback receives an `isAborted` parameter, and you should pass the `consumeStream` function to ensure proper abort handling: - -```tsx highlight="5,19,20-24,26" -import { openai } from '@ai-sdk/openai'; -import { - consumeStream, - convertToModelMessages, - streamText, - UIMessage, -} from 'ai'; -__PROVIDER_IMPORT__; - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - abortSignal: req.signal, - }); - - return result.toUIMessageStreamResponse({ - onFinish: async ({ isAborted }) => { - if (isAborted) { - console.log('Stream was aborted'); - // Handle abort-specific cleanup - } else { - console.log('Stream completed normally'); - // Handle normal completion - } - }, - consumeSseStream: consumeStream, - }); -} -``` - -The `consumeStream` function is necessary for proper abort handling in UI message streams. It ensures that the stream is properly consumed even when aborted, preventing potential memory leaks or hanging connections. - -## AI SDK RSC - - - The AI SDK RSC does not currently support stopping streams. - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/03-backpressure.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/03-backpressure.mdx deleted file mode 100644 index 1b512d36b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/03-backpressure.mdx +++ /dev/null @@ -1,173 +0,0 @@ ---- -title: Backpressure -description: How to handle backpressure and cancellation when working with the AI SDK ---- - -# Stream Back-pressure and Cancellation - -This page focuses on understanding back-pressure and cancellation when working with streams. You do not need to know this information to use the AI SDK, but for those interested, it offers a deeper dive on why and how the SDK optimally streams responses. - -In the following sections, we'll explore back-pressure and cancellation in the context of a simple example program. We'll discuss the issues that can arise from an eager approach and demonstrate how a lazy approach can resolve them. - -## Back-pressure and Cancellation with Streams - -Let's begin by setting up a simple example program: - -```jsx -// A generator that will yield positive integers -async function* integers() { - let i = 1; - while (true) { - console.log(`yielding ${i}`); - yield i++; - - await sleep(100); - } -} -function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -// Wraps a generator into a ReadableStream -function createStream(iterator) { - return new ReadableStream({ - async start(controller) { - for await (const v of iterator) { - controller.enqueue(v); - } - controller.close(); - }, - }); -} - -// Collect data from stream -async function run() { - // Set up a stream of integers - const stream = createStream(integers()); - - // Read values from our stream - const reader = stream.getReader(); - for (let i = 0; i < 10_000; i++) { - // we know our stream is infinite, so there's no need to check `done`. - const { value } = await reader.read(); - console.log(`read ${value}`); - - await sleep(1_000); - } -} -run(); -``` - -In this example, we create an async-generator that yields positive integers, a `ReadableStream` that wraps our integer generator, and a reader which will read values out of our stream. Notice, too, that our integer generator logs out `"yielding ${i}"`, and our reader logs out `"read ${value}"`. Both take an arbitrary amount of time to process data, represented with a 100ms sleep in our generator, and a 1sec sleep in our reader. - -## Back-pressure - -If you were to run this program, you'd notice something funny. We'll see roughly 10 "yield" logs for every "read" log. This might seem obvious, the generator can push values 10x faster than the reader can pull them out. But it represents a problem, our `stream` has to maintain an ever expanding queue of items that have been pushed in but not pulled out. - -The problem stems from the way we wrap our generator into a stream. Notice the use of `for await (…)` inside our `start` handler. This is an **eager** for-loop, and it is constantly running to get the next value from our generator to be enqueued in our stream. This means our stream does not respect back-pressure, the signal from the consumer to the producer that more values aren't needed _yet_. We've essentially spawned a thread that will perpetually push more data into the stream, one that runs as fast as possible to push new data immediately. Worse, there's no way to signal to this thread to stop running when we don't need additional data. - -To fix this, `ReadableStream` allows a `pull` handler. `pull` is called every time the consumer attempts to read more data from our stream (if there's no data already queued internally). But it's not enough to just move the `for await(…)` into `pull`, we also need to convert from an eager enqueuing to a **lazy** one. By making these 2 changes, we'll be able to react to the consumer. If they need more data, we can easily produce it, and if they don't, then we don't need to spend any time doing unnecessary work. - -```jsx -function createStream(iterator) { - return new ReadableStream({ - async pull(controller) { - const { value, done } = await iterator.next(); - - if (done) { - controller.close(); - } else { - controller.enqueue(value); - } - }, - }); -} -``` - -Our `createStream` is a little more verbose now, but the new code is important. First, we need to manually call our `iterator.next()` method. This returns a `Promise` for an object with the type signature `{ done: boolean, value: T }`. If `done` is `true`, then we know that our iterator won't yield any more values and we must `close` the stream (this allows the consumer to know that the stream is also finished producing values). Else, we need to `enqueue` our newly produced value. - -When we run this program, we see that our "yield" and "read" logs are now paired. We're no longer yielding 10x integers for every read! And, our stream now only needs to maintain 1 item in its internal buffer. We've essentially given control to the consumer, so that it's responsible for producing new values as it needs it. Neato! - -## Cancellation - -Let's go back to our initial eager example, with 1 small edit. Now instead of reading 10,000 integers, we're only going to read 3: - -```jsx -// A generator that will yield positive integers -async function* integers() { - let i = 1; - while (true) { - console.log(`yielding ${i}`); - yield i++; - - await sleep(100); - } -} -function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -// Wraps a generator into a ReadableStream -function createStream(iterator) { - return new ReadableStream({ - async start(controller) { - for await (const v of iterator) { - controller.enqueue(v); - } - controller.close(); - }, - }); -} -// Collect data from stream -async function run() { - // Set up a stream that of integers - const stream = createStream(integers()); - - // Read values from our stream - const reader = stream.getReader(); - // We're only reading 3 items this time: - for (let i = 0; i < 3; i++) { - // we know our stream is infinite, so there's no need to check `done`. - const { value } = await reader.read(); - console.log(`read ${value}`); - - await sleep(1000); - } -} -run(); -``` - -We're back to yielding 10x the number of values read. But notice now, after we've read 3 values, we're continuing to yield new values. We know that our reader will never read another value, but our stream doesn't! The eager `for await (…)` will continue forever, loudly enqueuing new values into our stream's buffer and increasing our memory usage until it consumes all available program memory. - -The fix to this is exactly the same: use `pull` and manual iteration. By producing values _**lazily**_, we tie the lifetime of our integer generator to the lifetime of the reader. Once the reads stop, the yields will stop too: - -```jsx -// Wraps a generator into a ReadableStream -function createStream(iterator) { - return new ReadableStream({ - async pull(controller) { - const { value, done } = await iterator.next(); - - if (done) { - controller.close(); - } else { - controller.enqueue(value); - } - }, - }); -} -``` - -Since the solution is the same as implementing back-pressure, it shows that they're just 2 facets of the same problem: Pushing values into a stream should be done **lazily**, and doing it eagerly results in expected problems. - -## Tying Stream Laziness to AI Responses - -Now let's imagine you're integrating AIBot service into your product. Users will be able to prompt "count from 1 to infinity", the browser will fetch your AI API endpoint, and your servers connect to AIBot to get a response. But "infinity" is, well, infinite. The response will never end! - -After a few seconds, the user gets bored and navigates away. Or maybe you're doing local development and a hot-module reload refreshes your page. The browser will have ended its connection to the API endpoint, but will your server end its connection with AIBot? - -If you used the eager `for await (...)` approach, then the connection is still running and your server is asking for more and more data from AIBot. Our server spawned a "thread" and there's no signal when we can end the eager pulls. Eventually, the server is going to run out of memory (remember, there's no active fetch connection to read the buffering responses and free them). - -{/* When we started writing the streaming code for the AI SDK, we confirm aborting a fetch will end a streamed response from Next.js */} - -With the lazy approach, this is taken care of for you. Because the stream will only request new data from AIBot when the consumer requests it, navigating away from the page naturally frees all resources. The fetch connection aborts and the server can clean up the response. The `ReadableStream` tied to that response can now be garbage collected. When that happens, the connection it holds to AIBot can then be freed. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/04-caching.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/04-caching.mdx deleted file mode 100644 index 0ba3dc3cc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/04-caching.mdx +++ /dev/null @@ -1,169 +0,0 @@ ---- -title: Caching -description: How to handle caching when working with the AI SDK ---- - -# Caching Responses - -Depending on the type of application you're building, you may want to cache the responses you receive from your AI provider, at least temporarily. - -## Using Language Model Middleware (Recommended) - -The recommended approach to caching responses is using [language model middleware](/docs/ai-sdk-core/middleware) -and the [`simulateReadableStream`](/docs/reference/ai-sdk-core/simulate-readable-stream) function. - -Language model middleware is a way to enhance the behavior of language models by intercepting and modifying the calls to the language model. -Let's see how you can use language model middleware to cache responses. - -```ts filename="ai/middleware.ts" -import { Redis } from '@upstash/redis'; -import { - type LanguageModelV3, - type LanguageModelV3Middleware, - type LanguageModelV3StreamPart, - simulateReadableStream, -} from 'ai'; - -const redis = new Redis({ - url: process.env.KV_URL, - token: process.env.KV_TOKEN, -}); - -export const cacheMiddleware: LanguageModelV3Middleware = { - wrapGenerate: async ({ doGenerate, params }) => { - const cacheKey = JSON.stringify(params); - - const cached = (await redis.get(cacheKey)) as Awaited< - ReturnType - > | null; - - if (cached !== null) { - return { - ...cached, - response: { - ...cached.response, - timestamp: cached?.response?.timestamp - ? new Date(cached?.response?.timestamp) - : undefined, - }, - }; - } - - const result = await doGenerate(); - - redis.set(cacheKey, result); - - return result; - }, - wrapStream: async ({ doStream, params }) => { - const cacheKey = JSON.stringify(params); - - // Check if the result is in the cache - const cached = await redis.get(cacheKey); - - // If cached, return a simulated ReadableStream that yields the cached result - if (cached !== null) { - // Format the timestamps in the cached response - const formattedChunks = (cached as LanguageModelV3StreamPart[]).map(p => { - if (p.type === 'response-metadata' && p.timestamp) { - return { ...p, timestamp: new Date(p.timestamp) }; - } else return p; - }); - return { - stream: simulateReadableStream({ - initialDelayInMs: 0, - chunkDelayInMs: 10, - chunks: formattedChunks, - }), - }; - } - - // If not cached, proceed with streaming - const { stream, ...rest } = await doStream(); - - const fullResponse: LanguageModelV3StreamPart[] = []; - - const transformStream = new TransformStream< - LanguageModelV3StreamPart, - LanguageModelV3StreamPart - >({ - transform(chunk, controller) { - fullResponse.push(chunk); - controller.enqueue(chunk); - }, - flush() { - // Store the full response in the cache after streaming is complete - redis.set(cacheKey, fullResponse); - }, - }); - - return { - stream: stream.pipeThrough(transformStream), - ...rest, - }; - }, -}; -``` - - - This example uses `@upstash/redis` to store and retrieve the assistant's - responses but you can use any KV storage provider you would like. - - -`LanguageModelV3Middleware` has two methods: `wrapGenerate` and `wrapStream`. `wrapGenerate` is called when using [`generateText`](/docs/reference/ai-sdk-core/generate-text), while `wrapStream` is called when using [`streamText`](/docs/reference/ai-sdk-core/stream-text). - -For `wrapGenerate`, you can cache the response directly. Instead, for `wrapStream`, you cache an array of the stream parts, which can then be used with [`simulateReadableStream`](/docs/ai-sdk-core/testing#simulate-data-stream-protocol-responses) function to create a simulated `ReadableStream` that returns the cached response. In this way, the cached response is returned chunk-by-chunk as if it were being generated by the model. You can control the initial delay and delay between chunks by adjusting the `initialDelayInMs` and `chunkDelayInMs` parameters of `simulateReadableStream`. - -You can see a full example of caching with Redis in a Next.js application in our [Caching Middleware Recipe](/cookbook/next/caching-middleware). - -## Using Lifecycle Callbacks - -Alternatively, each AI SDK Core function has special lifecycle callbacks you can use. The one of interest is likely `onFinish`, which is called when the generation is complete. This is where you can cache the full response. - -Here's an example of how you can implement caching using Vercel KV and Next.js to cache the OpenAI response for 1 hour: - -This example uses [Upstash Redis](https://upstash.com/docs/redis/overall/getstarted) and Next.js to cache the response for 1 hour. - -```tsx filename="app/api/chat/route.ts" -import { convertToModelMessages, streamText, UIMessage } from 'ai'; -__PROVIDER_IMPORT__; -import { Redis } from '@upstash/redis'; - -// Allow streaming responses up to 30 seconds -export const maxDuration = 30; - -const redis = new Redis({ - url: process.env.KV_URL, - token: process.env.KV_TOKEN, -}); - -export async function POST(req: Request) { - const { messages }: { messages: UIMessage[] } = await req.json(); - - // come up with a key based on the request: - const key = JSON.stringify(messages); - - // Check if we have a cached response - const cached = (await redis.get(key)) as string | null; - if (cached != null) { - return new Response(cached, { - status: 200, - headers: { 'Content-Type': 'text/plain' }, - }); - } - - // Call the language model: - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - async onFinish({ text }) { - // Cache the response text: - await redis.set(key, text); - await redis.expire(key, 60 * 60); - }, - }); - - // Respond with the stream - return result.toUIMessageStreamResponse(); -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/05-multiple-streamables.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/05-multiple-streamables.mdx deleted file mode 100644 index bcad57613..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/05-multiple-streamables.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Multiple Streamables -description: Learn to handle multiple streamables in your application. ---- - -# Multiple Streams - -## Multiple Streamable UIs - -The AI SDK RSC APIs allow you to compose and return any number of streamable UIs, along with other data, in a single request. This can be useful when you want to decouple the UI into smaller components and stream them separately. - -```tsx file='app/actions.tsx' -'use server'; - -import { createStreamableUI } from '@ai-sdk/rsc'; - -export async function getWeather() { - const weatherUI = createStreamableUI(); - const forecastUI = createStreamableUI(); - - weatherUI.update(
Loading weather...
); - forecastUI.update(
Loading forecast...
); - - getWeatherData().then(weatherData => { - weatherUI.done(
{weatherData}
); - }); - - getForecastData().then(forecastData => { - forecastUI.done(
{forecastData}
); - }); - - // Return both streamable UIs and other data fields. - return { - requestedAt: Date.now(), - weather: weatherUI.value, - forecast: forecastUI.value, - }; -} -``` - -The client side code is similar to the previous example, but the [tool call](/docs/ai-sdk-core/tools-and-tool-calling) will return the new data structure with the weather and forecast UIs. Depending on the speed of getting weather and forecast data, these two components might be updated independently. - -## Nested Streamable UIs - -You can stream UI components within other UI components. This allows you to create complex UIs that are built up from smaller, reusable components. In the example below, we pass a `historyChart` streamable as a prop to a `StockCard` component. The StockCard can render the `historyChart` streamable, and it will automatically update as the server responds with new data. - -```tsx file='app/actions.tsx' -async function getStockHistoryChart({ symbol: string }) { - 'use server'; - - const ui = createStreamableUI(); - - // We need to wrap this in an async IIFE to avoid blocking. - (async () => { - const price = await getStockPrice({ symbol }); - - // Show a spinner as the history chart for now. - const historyChart = createStreamableUI(); - ui.done(); - - // Getting the history data and then update that part of the UI. - const historyData = await fetch('https://my-stock-data-api.com'); - historyChart.done(); - })(); - - return ui; -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/06-rate-limiting.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/06-rate-limiting.mdx deleted file mode 100644 index 03d7825e8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/06-rate-limiting.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Rate Limiting -description: Learn how to rate limit your application. ---- - -# Rate Limiting - -Rate limiting helps you protect your APIs from abuse. It involves setting a -maximum threshold on the number of requests a client can make within a -specified timeframe. This simple technique acts as a gatekeeper, -preventing excessive usage that can degrade service performance and incur -unnecessary costs. - -## Rate Limiting with Vercel KV and Upstash Ratelimit - -In this example, you will protect an API endpoint using [Vercel KV](https://vercel.com/storage/kv) -and [Upstash Ratelimit](https://github.com/upstash/ratelimit). - -```tsx filename='app/api/generate/route.ts' -import kv from '@vercel/kv'; -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; -import { Ratelimit } from '@upstash/ratelimit'; -import { NextRequest } from 'next/server'; - -// Allow streaming responses up to 30 seconds -export const maxDuration = 30; - -// Create Rate limit -const ratelimit = new Ratelimit({ - redis: kv, - limiter: Ratelimit.fixedWindow(5, '30s'), -}); - -export async function POST(req: NextRequest) { - // call ratelimit with request ip - const ip = req.ip ?? 'ip'; - const { success, remaining } = await ratelimit.limit(ip); - - // block the request if unsuccessful - if (!success) { - return new Response('Ratelimited!', { status: 429 }); - } - - const { messages } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -## Simplify API Protection - -With Vercel KV and Upstash Ratelimit, it is possible to protect your APIs -from such attacks with ease. To learn more about how Ratelimit works and -how it can be configured to your needs, see [Ratelimit Documentation](https://upstash.com/docs/oss/sdks/ts/ratelimit/overview). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/07-rendering-ui-with-language-models.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/07-rendering-ui-with-language-models.mdx deleted file mode 100644 index 08549d2c4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/07-rendering-ui-with-language-models.mdx +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: Rendering UI with Language Models -description: Rendering UI with Language Models ---- - -# Rendering User Interfaces with Language Models - -Language models generate text, so at first it may seem like you would only need to render text in your application. - -```tsx highlight="16" filename="app/actions.tsx" -const text = generateText({ - model: __MODEL__, - system: 'You are a friendly assistant', - prompt: 'What is the weather in SF?', - tools: { - getWeather: { - description: 'Get the weather for a location', - inputSchema: z.object({ - city: z.string().describe('The city to get the weather for'), - unit: z - .enum(['C', 'F']) - .describe('The unit to display the temperature in'), - }), - execute: async ({ city, unit }) => { - const weather = getWeather({ city, unit }); - return `It is currently ${weather.value}°${unit} and ${weather.description} in ${city}!`; - }, - }, - }, -}); -``` - -Above, the language model is passed a [tool](/docs/ai-sdk-core/tools-and-tool-calling) called `getWeather` that returns the weather information as text. However, instead of returning text, if you return a JSON object that represents the weather information, you can use it to render a React component instead. - -```tsx highlight="18-23" filename="app/action.ts" -const text = generateText({ - model: __MODEL__, - system: 'You are a friendly assistant', - prompt: 'What is the weather in SF?', - tools: { - getWeather: { - description: 'Get the weather for a location', - inputSchema: z.object({ - city: z.string().describe('The city to get the weather for'), - unit: z - .enum(['C', 'F']) - .describe('The unit to display the temperature in'), - }), - execute: async ({ city, unit }) => { - const weather = getWeather({ city, unit }); - const { temperature, unit, description, forecast } = weather; - - return { - temperature, - unit, - description, - forecast, - }; - }, - }, - }, -}); -``` - -Now you can use the object returned by the `getWeather` function to conditionally render a React component `` that displays the weather information by passing the object as props. - -```tsx filename="app/page.tsx" -return ( -
- {messages.map(message => { - // Check assistant message parts for tool results - if (message.role === 'assistant') { - return message.parts.map(part => { - if ( - part.type === 'tool-weather' && - part.state === 'output-available' - ) { - const { temperature, unit, description, forecast } = part.output; - - return ( - - ); - } - }); - } - })} -
-); -``` - -Here's a little preview of what that might look like. - -
- -
- -Rendering interfaces as part of language model generations elevates the user experience of your application, allowing people to interact with language models beyond text. - -They also make it easier for you to interpret [sequential tool calls](/docs/ai-sdk-rsc/multistep-interfaces) that take place in multiple steps and help identify and debug where the model reasoned incorrectly. - -## Rendering Multiple User Interfaces - -To recap, an application has to go through the following steps to render user interfaces as part of model generations: - -1. The user prompts the language model. -2. The language model generates a response that includes a tool call. -3. The tool call returns a JSON object that represents the user interface. -4. The response is sent to the client. -5. The client receives the response and checks if the latest message was a tool call. -6. If it was a tool call, the client renders the user interface based on the JSON object returned by the tool call. - -Most applications have multiple tools that are called by the language model, and each tool can return a different user interface. - -For example, a tool that searches for courses can return a list of courses, while a tool that searches for people can return a list of people. As this list grows, the complexity of your application will grow as well and it can become increasingly difficult to manage these user interfaces. - -```tsx filename='app/page.tsx' -{ - message.parts.map(part => { - if (part.state !== 'output-available') return null; - - switch (part.type) { - case 'tool-api-search-course': - return ; - case 'tool-api-search-profile': - return ; - case 'tool-api-meetings': - return ; - case 'tool-api-search-building': - return ; - case 'tool-api-events': - return ; - case 'tool-api-meals': - return ; - case 'text': - return
{part.text}
; - default: - return null; - } - }); -} -``` - -## Rendering User Interfaces on the Server - -The **AI SDK RSC (`@ai-sdk/rsc`)** takes advantage of RSCs to solve the problem of managing all your React components on the client side, allowing you to render React components on the server and stream them to the client. - -Rather than conditionally rendering user interfaces on the client based on the data returned by the language model, you can directly stream them from the server during a model generation. - -```tsx highlight="3,22-31,38" filename="app/action.ts" -import { createStreamableUI } from '@ai-sdk/rsc' - -const uiStream = createStreamableUI(); - -const text = generateText({ - model: __MODEL__, - system: 'you are a friendly assistant' - prompt: 'what is the weather in SF?' - tools: { - getWeather: { - description: 'Get the weather for a location', - inputSchema: z.object({ - city: z.string().describe('The city to get the weather for'), - unit: z - .enum(['C', 'F']) - .describe('The unit to display the temperature in') - }), - execute: async ({ city, unit }) => { - const weather = getWeather({ city, unit }) - const { temperature, unit, description, forecast } = weather - - uiStream.done( - - ) - } - } - } -}) - -return { - display: uiStream.value -} -``` - -The [`createStreamableUI`](/docs/reference/ai-sdk-rsc/create-streamable-ui) function belongs to the `@ai-sdk/rsc` module and creates a stream that can send React components to the client. - -On the server, you render the `` component with the props passed to it, and then stream it to the client. On the client side, you only need to render the UI that is streamed from the server. - -```tsx filename="app/page.tsx" highlight="4" -return ( -
- {messages.map(message => ( -
{message.display}
- ))} -
-); -``` - -Now the steps involved are simplified: - -1. The user prompts the language model. -2. The language model generates a response that includes a tool call. -3. The tool call renders a React component along with relevant props that represent the user interface. -4. The response is streamed to the client and rendered directly. - -> **Note:** You can also render text on the server and stream it to the client using React Server Components. This way, all operations from language model generation to UI rendering can be done on the server, while the client only needs to render the UI that is streamed from the server. - -Check out this [example](/examples/next-app/interface/stream-component-updates) for a full illustration of how to stream component updates with React Server Components in Next.js App Router. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/08-model-as-router.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/08-model-as-router.mdx deleted file mode 100644 index f19aea1b2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/08-model-as-router.mdx +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Language Models as Routers -description: Generative User Interfaces and Language Models as Routers ---- - -# Generative User Interfaces - -Since language models can render user interfaces as part of their generations, the resulting model generations are referred to as generative user interfaces. - -In this section we will learn more about generative user interfaces and their impact on the way AI applications are built. - -## Deterministic Routes and Probabilistic Routing - -Generative user interfaces are not deterministic in nature because they depend on the model's generation output. Since these generations are probabilistic in nature, it is possible for every user query to result in a different user interface. - -Users expect their experience using your application to be predictable, so non-deterministic user interfaces can sound like a bad idea at first. However, language models can be set up to limit their generations to a particular set of outputs using their ability to call functions. - -When language models are provided with a set of function definitions and instructed to execute any of them based on user query, they do either one of the following things: - -- Execute a function that is most relevant to the user query. -- Not execute any function if the user query is out of bounds of the set of functions available to them. - -```tsx filename='app/actions.ts' -const sendMessage = (prompt: string) => - generateText({ - model: __MODEL__, - system: 'you are a friendly weather assistant!', - prompt, - tools: { - getWeather: { - description: 'Get the weather in a location', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - execute: async ({ location }: { location: string }) => ({ - location, - temperature: 72 + Math.floor(Math.random() * 21) - 10, - }), - }, - }, - }); - -sendMessage('What is the weather in San Francisco?'); // getWeather is called -sendMessage('What is the weather in New York?'); // getWeather is called -sendMessage('What events are happening in London?'); // No function is called -``` - -This way, it is possible to ensure that the generations result in deterministic outputs, while the choice a model makes still remains to be probabilistic. - -This emergent ability exhibited by a language model to choose whether a function needs to be executed or not based on a user query is believed to be models emulating "reasoning". - -As a result, the combination of language models being able to reason which function to execute as well as render user interfaces at the same time gives you the ability to build applications where language models can be used as a router. - -## Language Models as Routers - -Historically, developers had to write routing logic that connected different parts of an application to be navigable by a user and complete a specific task. - -In web applications today, most of the routing logic takes place in the form of routes: - -- `/login` would navigate you to a page with a login form. -- `/user/john` would navigate you to a page with profile details about John. -- `/api/events?limit=5` would display the five most recent events from an events database. - -While routes help you build web applications that connect different parts of an application into a seamless user experience, it can also be a burden to manage them as the complexity of applications grow. - -Next.js has helped reduce complexity in developing with routes by introducing: - -- File-based routing system -- Dynamic routing -- API routes -- Middleware -- App router, and so on... - -With language models becoming better at reasoning, we believe that there is a future where developers only write core application specific components while models take care of routing them based on the user's state in an application. - -With generative user interfaces, the language model decides which user interface to render based on the user's state in the application, giving users the flexibility to interact with your application in a conversational manner instead of navigating through a series of predefined routes. - -### Routing by parameters - -For routes like: - -- `/profile/[username]` -- `/search?q=[query]` -- `/media/[id]` - -that have segments dependent on dynamic data, the language model can generate the correct parameters and render the user interface. - -For example, when you're in a search application, you can ask the language model to search for artworks from different artists. The language model will call the search function with the artist's name as a parameter and render the search results. - -
- -
- -### Routing by sequence - -For actions that require a sequence of steps to be completed by navigating through different routes, the language model can generate the correct sequence of routes to complete in order to fulfill the user's request. - -For example, when you're in a calendar application, you can ask the language model to schedule a happy hour evening with your friends. The language model will then understand your request and will perform the right sequence of [tool calls](/docs/ai-sdk-core/tools-and-tool-calling) to: - -1. Lookup your calendar -2. Lookup your friends' calendars -3. Determine the best time for everyone -4. Search for nearby happy hour spots -5. Create an event and send out invites to your friends - -
- -
- -Just by defining functions to lookup contacts, pull events from a calendar, and search for nearby locations, the model is able to sequentially navigate the routes for you. - -To learn more, check out these [examples](/examples/next-app/interface) using the `streamUI` function to stream generative user interfaces to the client based on the response from the language model. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/09-multistep-interfaces.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/09-multistep-interfaces.mdx deleted file mode 100644 index a43daa846..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/09-multistep-interfaces.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: Multistep Interfaces -description: Concepts behind building multistep interfaces ---- - -# Multistep Interfaces - -Multistep interfaces refer to user interfaces that require multiple independent steps to be executed in order to complete a specific task. - -In order to understand multistep interfaces, it is important to understand two concepts: - -- Tool composition -- Application context - -**Tool composition** is the process of combining multiple [tools](/docs/ai-sdk-core/tools-and-tool-calling) to create a new tool. This is a powerful concept that allows you to break down complex tasks into smaller, more manageable steps. - -**Application context** refers to the state of the application at any given point in time. This includes the user's input, the output of the language model, and any other relevant information. - -When designing multistep interfaces, you need to consider how the tools in your application can be composed together to form a coherent user experience as well as how the application context changes as the user progresses through the interface. - -## Application Context - -The application context can be thought of as the conversation history between the user and the language model. The richer the context, the more information the model has to generate relevant responses. - -In the context of multistep interfaces, the application context becomes even more important. This is because **the user's input in one step may affect the output of the model in the next step**. - -For example, consider a meal logging application that helps users track their daily food intake. The language model is provided with the following tools: - -- `log_meal` takes in parameters like the name of the food, the quantity, and the time of consumption to log a meal. -- `delete_meal` takes in the name of the meal to be deleted. - -When the user logs a meal, the model generates a response confirming the meal has been logged. - -```txt highlight="2" -User: Log a chicken shawarma for lunch. -Tool: log_meal("chicken shawarma", "250g", "12:00 PM") -Model: Chicken shawarma has been logged for lunch. -``` - -Now when the user decides to delete the meal, the model should be able to reference the previous step to identify the meal to be deleted. - -```txt highlight="7" -User: Log a chicken shawarma for lunch. -Tool: log_meal("chicken shawarma", "250g", "12:00 PM") -Model: Chicken shawarma has been logged for lunch. -... -... -User: I skipped lunch today, can you update my log? -Tool: delete_meal("chicken shawarma") -Model: Chicken shawarma has been deleted from your log. -``` - -In this example, managing the application context is important for the model to generate the correct response. The model needs to have information about the previous actions in order for it to use generate the parameters for the `delete_meal` tool. - -## Tool Composition - -Tool composition is the process of combining multiple tools to create a new tool. This involves defining the inputs and outputs of each tool, as well as how they interact with each other. - -The design of how these tools can be composed together to form a multistep interface is crucial to both the user experience of your application and the model's ability to generate the correct output. - -For example, consider a flight booking assistant that can help users book flights. The assistant can be designed to have the following tools: - -- `searchFlights`: Searches for flights based on the user's query. -- `lookupFlight`: Looks up details of a specific flight based on the flight number. -- `bookFlight`: Books a flight based on the user's selection. - -The `searchFlights` tool is called when the user wants to lookup flights for a specific route. This would typically mean the tool should be able to take in parameters like the origin and destination of the flight. - -The `lookupFlight` tool is called when the user wants to get more details about a specific flight. This would typically mean the tool should be able to take in parameters like the flight number and return information about seat availability. - -The `bookFlight` tool is called when the user decides to book a flight. In order to identify the flight to book, the tool should be able to take in parameters like the flight number, trip date, and passenger details. - -So the conversation between the user and the model could look like this: - -```txt highlight="8" -User: I want to book a flight from New York to London. -Tool: searchFlights("New York", "London") -Model: Here are the available flights from New York to London. -User: I want to book flight number BA123 on 12th December for myself and my wife. -Tool: lookupFlight("BA123") -> "4 seats available" -Model: Sure, there are seats available! Can you provide the names of the passengers? -User: John Doe and Jane Doe. -Tool: bookFlight("BA123", "12th December", ["John Doe", "Jane Doe"]) -Model: Your flight has been booked! -``` - -In the last tool call, the `bookFlight` tool does not include passenger details as it is not available in the application context. As a result, it requests the user to provide the passenger details before proceeding with the booking. - -Looking up passenger information could've been another tool that the model could've called before calling the `bookFlight` tool assuming that the user is logged into the application. This way, the model does not have to ask the user for the passenger details and can proceed with the booking. - -```txt highlight="5,6" -User: I want to book a flight from New York to London. -Tool: searchFlights("New York", "London") -Model: Here are the available flights from New York to London. -User: I want to book flight number BA123 on 12th December for myself and my wife. -Tool: lookupContacts() -> ["John Doe", "Jane Doe"] -Tool: bookFlight("BA123", "12th December", ["John Doe", "Jane Doe"]) -Model: Your flight has been booked! -``` - -The `lookupContacts` tool is called before the `bookFlight` tool to ensure that the passenger details are available in the application context when booking the flight. This way, the model can reduce the number of steps required from the user and use its ability to call tools that populate its context and use that information to complete the booking process. - -Now, let's introduce another tool called `lookupBooking` that can be used to show booking details by taking in the name of the passenger as parameter. This tool can be composed with the existing tools to provide a more complete user experience. - -```txt highlight="2-4" -User: What's the status of my wife's upcoming flight? -Tool: lookupContacts() -> ["John Doe", "Jane Doe"] -Tool: lookupBooking("Jane Doe") -> "BA123 confirmed" -Tool: lookupFlight("BA123") -> "Flight BA123 is scheduled to depart on 12th December." -Model: Your wife's flight BA123 is confirmed and scheduled to depart on 12th December. -``` - -In this example, the `lookupBooking` tool is used to provide the user with the status of their wife's upcoming flight. By composing this tool with the existing tools, the model is able to generate a response that includes the booking status and the departure date of the flight without requiring the user to provide additional information. - -As a result, the more tools you design that can be composed together, the more complex and powerful your application can become. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/09-sequential-generations.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/09-sequential-generations.mdx deleted file mode 100644 index 6fd140a7e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/09-sequential-generations.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Sequential Generations -description: Learn how to implement sequential generations ("chains") with the AI SDK ---- - -# Sequential Generations - -When working with the AI SDK, you may want to create sequences of generations (often referred to as "chains" or "pipes"), where the output of one becomes the input for the next. This can be useful for creating more complex AI-powered workflows or for breaking down larger tasks into smaller, more manageable steps. - -## Example - -In a sequential chain, the output of one generation is directly used as input for the next generation. This allows you to create a series of dependent generations, where each step builds upon the previous one. - -Here's an example of how you can implement sequential actions: - -```typescript -import { generateText } from 'ai'; -__PROVIDER_IMPORT__; - -async function sequentialActions() { - // Generate blog post ideas - const ideasGeneration = await generateText({ - model: __MODEL__, - prompt: 'Generate 10 ideas for a blog post about making spaghetti.', - }); - - console.log('Generated Ideas:\n', ideasGeneration); - - // Pick the best idea - const bestIdeaGeneration = await generateText({ - model: __MODEL__, - prompt: `Here are some blog post ideas about making spaghetti: -${ideasGeneration} - -Pick the best idea from the list above and explain why it's the best.`, - }); - - console.log('\nBest Idea:\n', bestIdeaGeneration); - - // Generate an outline - const outlineGeneration = await generateText({ - model: __MODEL__, - prompt: `We've chosen the following blog post idea about making spaghetti: -${bestIdeaGeneration} - -Create a detailed outline for a blog post based on this idea.`, - }); - - console.log('\nBlog Post Outline:\n', outlineGeneration); -} - -sequentialActions().catch(console.error); -``` - -In this example, we first generate ideas for a blog post, then pick the best idea, and finally create an outline based on that idea. Each step uses the output from the previous step as input for the next generation. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/10-vercel-deployment-guide.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/10-vercel-deployment-guide.mdx deleted file mode 100644 index ecca31146..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/10-vercel-deployment-guide.mdx +++ /dev/null @@ -1,117 +0,0 @@ ---- -title: Vercel Deployment Guide -description: Learn how to deploy an AI application to production on Vercel ---- - -# Vercel Deployment Guide - -In this guide, you will deploy an AI application to [Vercel](https://vercel.com) using [Next.js](https://nextjs.org) (App Router). - -Vercel is a platform for developers that provides the tools, workflows, and infrastructure you need to build and deploy your web apps faster, without the need for additional configuration. - -Vercel allows for automatic deployments on every branch push and merges onto the production branch of your GitHub, GitLab, and Bitbucket projects. It is a great option for deploying your AI application. - -## Before You Begin - -To follow along with this guide, you will need: - -- a Vercel account -- an account with a Git provider (this tutorial will use [Github](https://github.com)) -- an OpenAI API key - -This guide will teach you how to deploy the application you built in the Next.js (App Router) quickstart tutorial to Vercel. If you haven’t completed the quickstart guide, you can start with [this repo](https://github.com/vercel-labs/ai-sdk-deployment-guide). - -## Commit Changes - -Vercel offers a powerful git-centered workflow that automatically deploys your application to production every time you push to your repository’s main branch. - -Before committing your local changes, make sure that you have a `.gitignore`. Within your `.gitignore`, ensure that you are excluding your environment variables (`.env`) and your node modules (`node_modules`). - -If you have any local changes, you can commit them by running the following commands: - -```bash -git add . -git commit -m "init" -``` - -## Create Git Repo - -You can create a GitHub repository from within your terminal, or on [github.com](https://github.com/). For this tutorial, you will use the GitHub CLI ([more info here](https://cli.github.com/)). - -To create your GitHub repository: - -1. Navigate to [github.com](http://github.com/) -2. In the top right corner, click the "plus" icon and select "New repository" -3. Pick a name for your repository (this can be anything) -4. Click "Create repository" - -Once you have created your repository, GitHub will redirect you to your new repository. - -1. Scroll down the page and copy the commands under the title "...or push an existing repository from the command line" -2. Go back to the terminal, paste and then run the commands - -Note: if you run into the error "error: remote origin already exists.", this is because your local repository is still linked to the repository you cloned. To "unlink", you can run the following command: - -```bash -rm -rf .git -git init -git add . -git commit -m "init" -``` - -Rerun the code snippet from the previous step. - -## Import Project in Vercel - -On the [New Project](https://vercel.com/new) page, under the **Import Git Repository** section, select the Git provider that you would like to import your project from. Follow the prompts to sign in to your GitHub account. - -Once you have signed in, you should see your newly created repository from the previous step in the "Import Git Repository" section. Click the "Import" button next to that project. - -### Add Environment Variables - -Your application uses environment secrets to store your OpenAI API key using a `.env.local` file locally in development. To add this API key to your production deployment, expand the "Environment Variables" section and paste in your `.env.local` file. Vercel will automatically parse your variables and enter them in the appropriate `key:value` format. - -### Deploy - -Press the **Deploy** button. Vercel will create the Project and deploy it based on the chosen configurations. - -### Enjoy the confetti! - -To view your deployment, select the Project in the dashboard and then select the **Domain**. This page is now visible to anyone who has the URL. - -## Considerations - -When deploying an AI application, there are infrastructure-related considerations to be aware of. - -### Function Duration - -In most cases, you will call the large language model (LLM) on the server. By default, Vercel serverless functions have a maximum duration of 10 seconds on the Hobby Tier. Depending on your prompt, it can take an LLM more than this limit to complete a response. If the response is not resolved within this limit, the server will throw an error. - -You can specify the maximum duration of your Vercel function using [route segment config](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config). To update your maximum duration, add the following route segment config to the top of your route handler or the page which is calling your server action. - -```ts -export const maxDuration = 30; -``` - -You can increase the max duration to 60 seconds on the Hobby Tier. For other tiers, [see the documentation](https://vercel.com/docs/functions/runtimes#max-duration) for limits. - -## Security Considerations - -Given the high cost of calling an LLM, it's important to have measures in place that can protect your application from abuse. - -### Rate Limit - -Rate limiting is a method used to regulate network traffic by defining a maximum number of requests that a client can send to a server within a given time frame. - -Follow [this guide](https://vercel.com/guides/securing-ai-app-rate-limiting) to add rate limiting to your application. - -### Firewall - -A firewall helps protect your applications and websites from DDoS attacks and unauthorized access. - -[Vercel Firewall](https://vercel.com/docs/security/vercel-firewall) is a set of tools and infrastructure, created specifically with security in mind. It automatically mitigates DDoS attacks and Enterprise teams can get further customization for their site, including dedicated support and custom rules for IP blocking. - -## Troubleshooting - -- Streaming not working when [proxied](/docs/troubleshooting/streaming-not-working-when-proxied) -- Experiencing [Timeouts](/docs/troubleshooting/timeout-on-vercel) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/index.mdx deleted file mode 100644 index 897d26702..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/06-advanced/index.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Advanced -description: Learn how to use advanced functionality within the AI SDK and RSC API. -collapsed: true ---- - -# Advanced - -This section covers advanced topics and concepts for the AI SDK and RSC API. Working with LLMs often requires a different mental model compared to traditional software development. - -After these concepts, you should have a better understanding of the paradigms behind the AI SDK and RSC API, and how to use them to build more AI applications. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx deleted file mode 100644 index b810f307a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +++ /dev/null @@ -1,2715 +0,0 @@ ---- -title: generateText -description: API Reference for generateText. ---- - -# `generateText()` - -Generates text and calls tools for a given prompt using a language model. - -It is ideal for non-interactive use cases such as automation tasks where you need to write text (e.g. drafting email or summarizing web pages) and for agents that use tools. - -```ts -import { generateText } from 'ai'; -__PROVIDER_IMPORT__; - -const { text } = await generateText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', -}); - -console.log(text); -``` - -To see `generateText` in action, check out [these examples](#examples). - -## Import - - - -## API Signature - -### Parameters - -', - description: 'The input prompt to generate the text from.', - }, - { - name: 'messages', - type: 'Array', - description: - 'A list of messages that represent a conversation. Automatically converts UI messages from the useChat hook.', - properties: [ - { - type: 'SystemModelMessage', - parameters: [ - { - name: 'role', - type: "'system'", - description: 'The role for the system message.', - }, - { - name: 'content', - type: 'string', - description: 'The content of the message.', - }, - ], - }, - { - type: 'UserModelMessage', - parameters: [ - { - name: 'role', - type: "'user'", - description: 'The role for the user message.', - }, - { - name: 'content', - type: 'string | Array', - description: 'The content of the message.', - properties: [ - { - type: 'TextPart', - parameters: [ - { - name: 'type', - type: "'text'", - description: 'The type of the message part.', - }, - { - name: 'text', - type: 'string', - description: 'The text content of the message part.', - }, - ], - }, - { - type: 'ImagePart', - parameters: [ - { - name: 'type', - type: "'image'", - description: 'The type of the message part.', - }, - { - name: 'image', - type: 'string | Uint8Array | Buffer | ArrayBuffer | URL', - description: - 'The image content of the message part. String are either base64 encoded content, base64 data URLs, or http(s) URLs.', - }, - { - name: 'mediaType', - type: 'string', - description: - 'The IANA media type of the image. Optional.', - isOptional: true, - }, - ], - }, - { - type: 'FilePart', - parameters: [ - { - name: 'type', - type: "'file'", - description: 'The type of the message part.', - }, - { - name: 'data', - type: 'string | Uint8Array | Buffer | ArrayBuffer | URL', - description: - 'The file content of the message part. String are either base64 encoded content, base64 data URLs, or http(s) URLs.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - ], - }, - ], - }, - ], - }, - { - type: 'AssistantModelMessage', - parameters: [ - { - name: 'role', - type: "'assistant'", - description: 'The role for the assistant message.', - }, - { - name: 'content', - type: 'string | Array', - description: 'The content of the message.', - properties: [ - { - type: 'TextPart', - parameters: [ - { - name: 'type', - type: "'text'", - description: 'The type of the message part.', - }, - { - name: 'text', - type: 'string', - description: 'The text content of the message part.', - }, - ], - }, - { - type: 'ReasoningPart', - parameters: [ - { - name: 'type', - type: "'reasoning'", - description: 'The type of the message part.', - }, - { - name: 'text', - type: 'string', - description: 'The reasoning text.', - }, - ], - }, - { - type: 'FilePart', - parameters: [ - { - name: 'type', - type: "'file'", - description: 'The type of the message part.', - }, - { - name: 'data', - type: 'string | Uint8Array | Buffer | ArrayBuffer | URL', - description: - 'The file content of the message part. String are either base64 encoded content, base64 data URLs, or http(s) URLs.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - { - name: 'filename', - type: 'string', - description: 'The name of the file.', - isOptional: true, - }, - ], - }, - { - type: 'ToolCallPart', - parameters: [ - { - name: 'type', - type: "'tool-call'", - description: 'The type of the message part.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool, which typically would be the name of the function.', - }, - { - name: 'input', - type: 'object based on zod schema', - description: - 'Input (parameters) generated by the model to be used by the tool.', - }, - ], - }, - ], - }, - ], - }, - { - type: 'ToolModelMessage', - parameters: [ - { - name: 'role', - type: "'tool'", - description: 'The role for the assistant message.', - }, - { - name: 'content', - type: 'Array', - description: 'The content of the message.', - properties: [ - { - type: 'ToolResultPart', - parameters: [ - { - name: 'type', - type: "'tool-result'", - description: 'The type of the message part.', - }, - { - name: 'toolCallId', - type: 'string', - description: - 'The id of the tool call the result corresponds to.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool the result corresponds to.', - }, - { - name: 'output', - type: 'unknown', - description: - 'The result returned by the tool after execution.', - }, - { - name: 'isError', - type: 'boolean', - isOptional: true, - description: - 'Whether the result is an error or an error message.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - name: 'tools', - type: 'ToolSet', - description: - 'Tools that are accessible to and can be called by the model. The model needs to support calling tools.', - properties: [ - { - type: 'Tool', - parameters: [ - { - name: 'description', - isOptional: true, - type: 'string', - description: - 'Information about the purpose of the tool including details on how and when it can be used by the model.', - }, - { - name: 'inputSchema', - type: 'Zod Schema | JSON Schema', - description: - 'The schema of the input that the tool expects. The language model will use this to generate the input. It is also used to validate the output of the language model. Use descriptions to make the input understandable for the language model. You can either pass in a Zod schema or a JSON schema (using the `jsonSchema` function).', - }, - { - name: 'execute', - isOptional: true, - type: 'async (parameters: T, options: ToolExecutionOptions) => RESULT', - description: - 'An async function that is called with the arguments from the tool call and produces a result. If not provided, the tool will not be executed automatically.', - properties: [ - { - type: 'ToolExecutionOptions', - parameters: [ - { - name: 'toolCallId', - type: 'string', - description: - 'The ID of the tool call. You can use it e.g. when sending tool-call related information with stream data.', - }, - { - name: 'messages', - type: 'ModelMessage[]', - description: - 'Messages that were sent to the language model to initiate the response that contained the tool call. The messages do not include the system prompt nor the assistant response that contained the tool call.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - description: - 'An optional abort signal that indicates that the overall operation should be aborted.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - name: 'toolChoice', - isOptional: true, - type: '"auto" | "none" | "required" | { "type": "tool", "toolName": string }', - description: - 'The tool choice setting. It specifies how tools are selected for execution. The default is "auto". "none" disables tool execution. "required" requires tools to be executed. { "type": "tool", "toolName": string } specifies a specific tool to execute.', - }, - { - name: 'maxOutputTokens', - type: 'number', - isOptional: true, - description: 'Maximum number of tokens to generate.', - }, - { - name: 'temperature', - type: 'number', - isOptional: true, - description: - 'Temperature setting. The value is passed through to the provider. The range depends on the provider and model. It is recommended to set either `temperature` or `topP`, but not both.', - }, - { - name: 'topP', - type: 'number', - isOptional: true, - description: - 'Nucleus sampling. The value is passed through to the provider. The range depends on the provider and model. It is recommended to set either `temperature` or `topP`, but not both.', - }, - { - name: 'topK', - type: 'number', - isOptional: true, - description: - 'Only sample from the top K options for each subsequent token. Used to remove "long tail" low probability responses. Recommended for advanced use cases only. You usually only need to use temperature.', - }, - { - name: 'presencePenalty', - type: 'number', - isOptional: true, - description: - 'Presence penalty setting. It affects the likelihood of the model to repeat information that is already in the prompt. The value is passed through to the provider. The range depends on the provider and model.', - }, - { - name: 'frequencyPenalty', - type: 'number', - isOptional: true, - description: - 'Frequency penalty setting. It affects the likelihood of the model to repeatedly use the same words or phrases. The value is passed through to the provider. The range depends on the provider and model.', - }, - { - name: 'stopSequences', - type: 'string[]', - isOptional: true, - description: - 'Sequences that will stop the generation of the text. If the model generates any of these sequences, it will stop generating further text.', - }, - { - name: 'seed', - type: 'number', - isOptional: true, - description: - 'The seed (integer) to use for random sampling. If set and supported by the model, calls will generate deterministic results.', - }, - { - name: 'maxRetries', - type: 'number', - isOptional: true, - description: - 'Maximum number of retries. Set to 0 to disable retries. Default: 2.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - isOptional: true, - description: - 'An optional abort signal that can be used to cancel the call.', - }, - { - name: 'timeout', - type: 'number | { totalMs?: number; stepMs?: number }', - isOptional: true, - description: - 'Timeout in milliseconds. Can be specified as a number or as an object with totalMs and/or stepMs properties. totalMs sets the total timeout for the entire call. stepMs sets the timeout for each individual step (LLM call), useful for multi-step generations. Can be used alongside abortSignal.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: - 'Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.', - }, - { - name: 'experimental_telemetry', - type: 'TelemetrySettings', - isOptional: true, - description: 'Telemetry configuration. Experimental feature.', - properties: [ - { - type: 'TelemetrySettings', - parameters: [ - { - name: 'isEnabled', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable telemetry. Disabled by default while experimental.', - }, - { - name: 'recordInputs', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable input recording. Enabled by default.', - }, - { - name: 'recordOutputs', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable output recording. Enabled by default.', - }, - { - name: 'functionId', - type: 'string', - isOptional: true, - description: - 'Identifier for this function. Used to group telemetry data by function.', - }, - { - name: 'metadata', - isOptional: true, - type: 'Record | Array | Array>', - description: - 'Additional information to include in the telemetry data.', - }, - ], - }, - ], - }, - { - name: 'providerOptions', - type: 'Record | undefined', - isOptional: true, - description: - 'Provider-specific options. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - { - name: 'activeTools', - type: 'Array', - isOptional: true, - description: - 'Limits the tools that are available for the model to call without changing the tool call and result types in the result. All tools are active by default.', - }, - { - name: 'stopWhen', - type: 'StopCondition | Array>', - isOptional: true, - description: - 'Condition for stopping the generation when there are tool results in the last step. When the condition is an array, any of the conditions can be met to stop the generation. Default: stepCountIs(1).', - }, - { - name: 'prepareStep', - type: '(options: PrepareStepOptions) => PrepareStepResult | Promise>', - isOptional: true, - description: - 'Optional function that you can use to provide different settings for a step. You can modify the model, tool choices, active tools, system prompt, and input messages for each step.', - properties: [ - { - type: 'PrepareStepFunction', - parameters: [ - { - name: 'options', - type: 'object', - description: 'The options for the step.', - properties: [ - { - type: 'PrepareStepOptions', - parameters: [ - { - name: 'steps', - type: 'Array>', - description: 'The steps that have been executed so far.', - }, - { - name: 'stepNumber', - type: 'number', - description: - 'The number of the step that is being executed.', - }, - { - name: 'model', - type: 'LanguageModel', - description: 'The model that is being used.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The messages that will be sent to the model for the current step.', - }, - { - name: 'experimental_context', - type: 'unknown', - isOptional: true, - description: - 'The context passed via the experimental_context setting (experimental).', - }, - ], - }, - ], - }, - ], - }, - { - type: 'PrepareStepResult', - description: - 'Return value that can modify settings for the current step.', - parameters: [ - { - name: 'model', - type: 'LanguageModel', - isOptional: true, - description: - 'Optionally override which LanguageModel instance is used for this step.', - }, - { - name: 'toolChoice', - type: 'ToolChoice', - isOptional: true, - description: - 'Optionally set which tool the model must call, or provide tool call configuration for this step.', - }, - { - name: 'activeTools', - type: 'Array', - isOptional: true, - description: - 'If provided, only these tools are enabled/available for this step.', - }, - { - name: 'system', - type: 'string | SystemModelMessage | SystemModelMessage[]', - isOptional: true, - description: - 'Optionally override the system message(s) sent to the model for this step.', - }, - { - name: 'messages', - type: 'Array', - isOptional: true, - description: - 'Optionally override the full set of messages sent to the model for this step.', - }, - { - name: 'experimental_context', - type: 'unknown', - isOptional: true, - description: - 'Context that is passed into tool execution. Experimental. Changing the context will affect the context in this step and all subsequent steps.', - }, - { - name: 'providerOptions', - type: 'ProviderOptions', - isOptional: true, - description: - 'Additional provider-specific options for this step. Can be used to pass provider-specific configuration such as container IDs for Anthropic code execution.', - }, - ], - }, - ], - }, - { - name: 'experimental_context', - type: 'unknown', - isOptional: true, - description: - 'Context that is passed into tool execution. Experimental (can break in patch releases).', - }, - { - name: 'experimental_download', - type: '(requestedDownloads: Array<{ url: URL; isUrlSupportedByModel: boolean }>) => Promise>', - isOptional: true, - description: - 'Custom download function to control how URLs are fetched when they appear in prompts. By default, files are downloaded if the model does not support the URL for the given media type. Experimental feature. Return null to pass the URL directly to the model (when supported), or return downloaded content with data and media type.', - }, - { - name: 'experimental_include', - type: '{ requestBody?: boolean; responseBody?: boolean }', - isOptional: true, - description: - 'Controls inclusion of request and response bodies in step results. By default, bodies are included. When processing many large payloads (e.g., images), set requestBody and/or responseBody to false to reduce memory usage. Experimental feature.', - properties: [ - { - type: 'Object', - parameters: [ - { - name: 'requestBody', - type: 'boolean', - isOptional: true, - description: - 'Whether to include the request body in step results. The request body can be large when sending images or files. Default: true.', - }, - { - name: 'responseBody', - type: 'boolean', - isOptional: true, - description: - 'Whether to include the response body in step results. Default: true.', - }, - ], - }, - ], - }, - { - name: 'experimental_repairToolCall', - type: '(options: ToolCallRepairOptions) => Promise', - isOptional: true, - description: - 'A function that attempts to repair a tool call that failed to parse. Return either a repaired tool call or null if the tool call cannot be repaired.', - properties: [ - { - type: 'ToolCallRepairOptions', - parameters: [ - { - name: 'system', - type: 'string | SystemModelMessage | SystemModelMessage[] | undefined', - description: 'The system prompt.', - }, - { - name: 'messages', - type: 'ModelMessage[]', - description: 'The messages in the current generation step.', - }, - { - name: 'toolCall', - type: 'LanguageModelV3ToolCall', - description: 'The tool call that failed to parse.', - }, - { - name: 'tools', - type: 'TOOLS', - description: 'The tools that are available.', - }, - { - name: 'parameterSchema', - type: '(options: { toolName: string }) => JSONSchema7', - description: - 'A function that returns the JSON Schema for a tool.', - }, - { - name: 'error', - type: 'NoSuchToolError | InvalidToolInputError', - description: - 'The error that occurred while parsing the tool call.', - }, - ], - }, - ], - }, - { - name: 'output', - type: 'Output', - isOptional: true, - description: - 'Specification for parsing structured outputs from the LLM response.', - properties: [ - { - type: 'Output', - parameters: [ - { - name: 'Output.text()', - type: 'Output', - description: - 'Output specification for text generation (default).', - }, - { - name: 'Output.object()', - type: 'Output', - description: - 'Output specification for typed object generation using schemas. When the model generates a text response, it will return an object that matches the schema.', - properties: [ - { - type: 'Options', - parameters: [ - { - name: 'schema', - type: 'Schema', - description: 'The schema of the object to generate.', - }, - { - name: 'name', - type: 'string', - isOptional: true, - description: - 'Optional name of the output. Used by some providers for additional LLM guidance.', - }, - { - name: 'description', - type: 'string', - isOptional: true, - description: - 'Optional description of the output. Used by some providers for additional LLM guidance.', - }, - ], - }, - ], - }, - { - name: 'Output.array()', - type: 'Output', - description: - 'Output specification for array generation. When the model generates a text response, it will return an array of elements.', - properties: [ - { - type: 'Options', - parameters: [ - { - name: 'element', - type: 'Schema', - description: - 'The schema of the array elements to generate.', - }, - { - name: 'name', - type: 'string', - isOptional: true, - description: - 'Optional name of the output. Used by some providers for additional LLM guidance.', - }, - { - name: 'description', - type: 'string', - isOptional: true, - description: - 'Optional description of the output. Used by some providers for additional LLM guidance.', - }, - ], - }, - ], - }, - { - name: 'Output.choice()', - type: 'Output', - description: - 'Output specification for choice generation. When the model generates a text response, it will return a one of the choice options.', - properties: [ - { - type: 'Options', - parameters: [ - { - name: 'options', - type: 'Array', - description: 'The available choices.', - }, - { - name: 'name', - type: 'string', - isOptional: true, - description: - 'Optional name of the output. Used by some providers for additional LLM guidance.', - }, - { - name: 'description', - type: 'string', - isOptional: true, - description: - 'Optional description of the output. Used by some providers for additional LLM guidance.', - }, - ], - }, - ], - }, - { - name: 'Output.json()', - type: 'Output', - description: - 'Output specification for unstructured JSON generation. When the model generates a text response, it will return a JSON object.', - properties: [ - { - type: 'Options', - parameters: [ - { - name: 'name', - type: 'string', - isOptional: true, - description: - 'Optional name of the output. Used by some providers for additional LLM guidance.', - }, - { - name: 'description', - type: 'string', - isOptional: true, - description: - 'Optional description of the output. Used by some providers for additional LLM guidance.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - name: 'experimental_onStart', - type: '(event: OnStartEvent) => PromiseLike | void', - isOptional: true, - description: - 'Callback that is called when the generateText operation begins, before any LLM calls are made. Errors thrown in this callback are silently caught and do not break the generation flow. Experimental (can break in patch releases).', - properties: [ - { - type: 'OnStartEvent', - parameters: [ - { - name: 'model', - type: '{ provider: string; modelId: string }', - description: 'The model being used for the generation.', - }, - { - name: 'system', - type: 'string | SystemModelMessage | Array | undefined', - description: 'The system message(s) provided to the model.', - }, - { - name: 'prompt', - type: 'string | Array | undefined', - description: - 'The prompt string or array of messages if using the prompt option.', - }, - { - name: 'messages', - type: 'Array | undefined', - description: 'The messages array if using the messages option.', - }, - { - name: 'tools', - type: 'TOOLS | undefined', - description: 'The tools available for this generation.', - }, - { - name: 'toolChoice', - type: 'ToolChoice | undefined', - description: 'The tool choice strategy for this generation.', - }, - { - name: 'activeTools', - type: 'Array | undefined', - description: - 'Limits which tools are available for the model to call.', - }, - { - name: 'maxOutputTokens', - type: 'number | undefined', - description: 'Maximum number of tokens to generate.', - }, - { - name: 'temperature', - type: 'number | undefined', - description: 'Sampling temperature for generation.', - }, - { - name: 'topP', - type: 'number | undefined', - description: 'Top-p (nucleus) sampling parameter.', - }, - { - name: 'topK', - type: 'number | undefined', - description: 'Top-k sampling parameter.', - }, - { - name: 'presencePenalty', - type: 'number | undefined', - description: 'Presence penalty for generation.', - }, - { - name: 'frequencyPenalty', - type: 'number | undefined', - description: 'Frequency penalty for generation.', - }, - { - name: 'stopSequences', - type: 'string[] | undefined', - description: 'Sequences that will stop generation.', - }, - { - name: 'seed', - type: 'number | undefined', - description: 'Random seed for reproducible generation.', - }, - { - name: 'maxRetries', - type: 'number', - description: 'Maximum number of retries for failed requests.', - }, - { - name: 'timeout', - type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number } | undefined', - description: - 'Timeout configuration for the generation. Can be a number (milliseconds) or an object with totalMs, stepMs, chunkMs.', - }, - { - name: 'headers', - type: 'Record | undefined', - description: 'Additional HTTP headers sent with the request.', - }, - { - name: 'providerOptions', - type: 'ProviderOptions | undefined', - description: 'Additional provider-specific options.', - }, - { - name: 'stopWhen', - type: 'StopCondition | Array> | undefined', - description: - 'Condition(s) for stopping the generation. When the condition is an array, any of the conditions can be met to stop.', - }, - { - name: 'output', - type: 'OUTPUT | undefined', - description: - 'The output specification for structured outputs, if configured.', - }, - { - name: 'abortSignal', - type: 'AbortSignal | undefined', - description: 'Abort signal for cancelling the operation.', - }, - { - name: 'include', - type: '{ requestBody?: boolean; responseBody?: boolean } | undefined', - description: - 'Settings for controlling what data is included in step results.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata passed to the generation.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object that flows through the entire generation lifecycle.', - }, - ], - }, - ], - }, - { - name: 'experimental_onStepStart', - type: '(event: OnStepStartEvent) => PromiseLike | void', - isOptional: true, - description: - 'Callback that is called when a step (LLM call) begins, before the provider is called. Errors thrown in this callback are silently caught and do not break the generation flow. Experimental (can break in patch releases).', - properties: [ - { - type: 'OnStepStartEvent', - parameters: [ - { - name: 'stepNumber', - type: 'number', - description: 'Zero-based index of the current step.', - }, - { - name: 'model', - type: '{ provider: string; modelId: string }', - description: 'The model being used for this step.', - }, - { - name: 'system', - type: 'string | SystemModelMessage | Array | undefined', - description: 'The system message for this step.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The messages that will be sent to the model for this step. Uses the user-facing ModelMessage format. May be overridden by prepareStep.', - }, - { - name: 'tools', - type: 'TOOLS | undefined', - description: 'The tools available for this generation.', - }, - { - name: 'toolChoice', - type: 'LanguageModelV3ToolChoice | undefined', - description: 'The tool choice configuration for this step.', - }, - { - name: 'activeTools', - type: 'Array | undefined', - description: 'Limits which tools are available for this step.', - }, - { - name: 'steps', - type: 'ReadonlyArray>', - description: - 'Array of results from previous steps (empty for first step).', - }, - { - name: 'providerOptions', - type: 'ProviderOptions | undefined', - description: - 'Additional provider-specific options for this step.', - }, - { - name: 'timeout', - type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number } | undefined', - description: - 'Timeout configuration for the generation. Can be a number (milliseconds) or an object with totalMs, stepMs, chunkMs.', - }, - { - name: 'headers', - type: 'Record | undefined', - description: 'Additional HTTP headers sent with the request.', - }, - { - name: 'stopWhen', - type: 'StopCondition | Array> | undefined', - description: - 'Condition(s) for stopping the generation. When the condition is an array, any of the conditions can be met to stop.', - }, - { - name: 'output', - type: 'OUTPUT | undefined', - description: - 'The output specification for structured outputs, if configured.', - }, - { - name: 'abortSignal', - type: 'AbortSignal | undefined', - description: 'Abort signal for cancelling the operation.', - }, - { - name: 'include', - type: '{ requestBody?: boolean; responseBody?: boolean } | undefined', - description: - 'Settings for controlling what data is included in step results.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object. May be updated from prepareStep between steps.', - }, - ], - }, - ], - }, - { - name: 'experimental_onToolCallStart', - type: '(event: OnToolCallStartEvent) => PromiseLike | void', - isOptional: true, - description: - "Callback that is called right before a tool's execute function runs. Errors thrown in this callback are silently caught and do not break the generation flow. Experimental (can break in patch releases).", - properties: [ - { - type: 'OnToolCallStartEvent', - parameters: [ - { - name: 'stepNumber', - type: 'number | undefined', - description: - 'The zero-based index of the current step where this tool call occurs. May be undefined in streaming contexts.', - }, - { - name: 'model', - type: '{ provider: string; modelId: string } | undefined', - description: - 'Information about the model being used. May be undefined in streaming contexts.', - }, - { - name: 'toolCall', - type: 'TypedToolCall', - description: - 'The full tool call object containing toolName, toolCallId, input, and metadata.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The conversation messages available at tool execution time.', - }, - { - name: 'abortSignal', - type: 'AbortSignal | undefined', - description: 'Signal for cancelling the operation.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object flowing through the generation.', - }, - ], - }, - ], - }, - { - name: 'experimental_onToolCallFinish', - type: '(event: OnToolCallFinishEvent) => PromiseLike | void', - isOptional: true, - description: - "Callback that is called right after a tool's execute function completes (or errors). Uses a discriminated union on the `success` field: when `success: true`, `output` contains the tool result; when `success: false`, `error` contains the error. Errors thrown in this callback are silently caught and do not break the generation flow. Experimental (can break in patch releases).", - properties: [ - { - type: 'OnToolCallFinishEvent', - parameters: [ - { - name: 'stepNumber', - type: 'number | undefined', - description: - 'The zero-based index of the current step where this tool call occurred. May be undefined in streaming contexts.', - }, - { - name: 'model', - type: '{ provider: string; modelId: string } | undefined', - description: - 'Information about the model being used. May be undefined in streaming contexts.', - }, - { - name: 'toolCall', - type: 'TypedToolCall', - description: - 'The full tool call object containing toolName, toolCallId, input, and metadata.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The conversation messages available at tool execution time.', - }, - { - name: 'abortSignal', - type: 'AbortSignal | undefined', - description: 'Signal for cancelling the operation.', - }, - { - name: 'durationMs', - type: 'number', - description: - 'The wall-clock duration of the tool execution in milliseconds.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object flowing through the generation.', - }, - { - name: 'success', - type: 'boolean', - description: - 'Discriminator indicating whether the tool call succeeded. When true, output is available. When false, error is available.', - }, - { - name: 'output', - type: 'unknown', - description: - "The tool's return value (only present when `success: true`).", - }, - { - name: 'error', - type: 'unknown', - description: - 'The error that occurred during tool execution (only present when `success: false`).', - }, - ], - }, - ], - }, - { - name: 'onStepFinish', - type: '(stepResult: StepResult) => Promise | void', - isOptional: true, - description: - 'Callback that is called when a step is finished. Receives a StepResult object.', - properties: [ - { - type: 'StepResult', - parameters: [ - { - name: 'stepNumber', - type: 'number', - description: 'Zero-based index of this step.', - }, - { - name: 'model', - type: '{ provider: string; modelId: string }', - description: - 'Information about the model that produced this step.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object flowing through the generation.', - }, - { - name: 'content', - type: 'Array>', - description: 'The content that was generated in this step.', - }, - { - name: 'text', - type: 'string', - description: 'The generated text.', - }, - { - name: 'reasoning', - type: 'Array', - description: - 'The reasoning that was generated during the generation.', - }, - { - name: 'reasoningText', - type: 'string | undefined', - description: - 'The reasoning text that was generated during the generation.', - }, - { - name: 'files', - type: 'Array', - description: - 'The files that were generated during the generation.', - }, - { - name: 'sources', - type: 'Array', - description: 'The sources that were used to generate the text.', - }, - { - name: 'toolCalls', - type: 'Array>', - description: - 'The tool calls that were made during the generation.', - }, - { - name: 'staticToolCalls', - type: 'Array>', - description: 'The static tool calls that were made in this step.', - }, - { - name: 'dynamicToolCalls', - type: 'Array', - description: - 'The dynamic tool calls that were made in this step.', - }, - { - name: 'toolResults', - type: 'Array>', - description: 'The results of the tool calls.', - }, - { - name: 'staticToolResults', - type: 'Array>', - description: - 'The static tool results that were made in this step.', - }, - { - name: 'dynamicToolResults', - type: 'Array', - description: - 'The dynamic tool results that were made in this step.', - }, - { - name: 'finishReason', - type: '"stop" | "length" | "content-filter" | "tool-calls" | "error" | "other"', - description: 'The unified reason why the generation finished.', - }, - { - name: 'rawFinishReason', - type: 'string | undefined', - description: - 'The raw reason why the generation finished (from the provider).', - }, - { - name: 'usage', - type: 'LanguageModelUsage', - description: 'The token usage of the generated text.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: - 'The total number of input (prompt) tokens used.', - }, - { - name: 'inputTokenDetails', - type: 'LanguageModelInputTokenDetails', - description: - 'Detailed information about the input (prompt) tokens.', - properties: [ - { - type: 'LanguageModelInputTokenDetails', - parameters: [ - { - name: 'noCacheTokens', - type: 'number | undefined', - description: - 'The number of non-cached input (prompt) tokens used.', - }, - { - name: 'cacheReadTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens read.', - }, - { - name: 'cacheWriteTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens written.', - }, - ], - }, - ], - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: - 'The number of total output (completion) tokens used.', - }, - { - name: 'outputTokenDetails', - type: 'LanguageModelOutputTokenDetails', - description: - 'Detailed information about the output (completion) tokens.', - properties: [ - { - type: 'LanguageModelOutputTokenDetails', - parameters: [ - { - name: 'textTokens', - type: 'number | undefined', - description: 'The number of text tokens used.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - description: - 'The number of reasoning tokens used.', - }, - ], - }, - ], - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used.', - }, - { - name: 'raw', - type: 'object | undefined', - isOptional: true, - description: - "Raw usage information from the provider. This is the provider's original usage information and may include additional fields.", - }, - ], - }, - ], - }, - { - name: 'warnings', - type: 'CallWarning[] | undefined', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'request', - type: 'LanguageModelRequestMetadata', - description: 'Additional request information.', - }, - { - name: 'response', - type: 'LanguageModelResponseMetadata & { messages: Array; body?: unknown }', - description: 'Additional response information.', - properties: [ - { - type: 'Response', - parameters: [ - { - name: 'id', - type: 'string', - description: - 'The response identifier. The AI SDK uses the ID from the provider response when available, and generates an ID otherwise.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The model that was used to generate the response.', - }, - { - name: 'timestamp', - type: 'Date', - description: 'The timestamp of the response.', - }, - { - name: 'headers', - isOptional: true, - type: 'Record', - description: 'Optional response headers.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The response messages that were generated during the call.', - }, - { - name: 'body', - isOptional: true, - type: 'unknown', - description: - 'Response body (available only for providers that use HTTP requests).', - }, - ], - }, - ], - }, - { - name: 'providerMetadata', - type: 'ProviderMetadata | undefined', - isOptional: true, - description: - 'Additional provider-specific metadata. They are passed through from the provider to the AI SDK and enable provider-specific results that can be fully encapsulated in the provider.', - }, - ], - }, - ], - }, - { - name: 'onFinish', - type: '(event: StepResult & { steps: StepResult[]; totalUsage: LanguageModelUsage }) => PromiseLike | void', - isOptional: true, - description: - 'Callback that is called when the entire generation completes (all steps finished). The event includes the final step result properties along with aggregated data from all steps.', - properties: [ - { - type: 'OnFinishEvent', - parameters: [ - { - name: 'stepNumber', - type: 'number', - description: 'Zero-based index of the final step.', - }, - { - name: 'model', - type: '{ provider: string; modelId: string }', - description: - 'Information about the model that produced the final step.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'finishReason', - type: '"stop" | "length" | "content-filter" | "tool-calls" | "error" | "other"', - description: 'The unified reason why the generation finished.', - }, - { - name: 'rawFinishReason', - type: 'string | undefined', - description: - 'The raw reason why the generation finished (from the provider).', - }, - { - name: 'usage', - type: 'LanguageModelUsage', - description: - 'The token usage from the final step only (not aggregated).', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: - 'The total number of input (prompt) tokens used.', - }, - { - name: 'inputTokenDetails', - type: 'LanguageModelInputTokenDetails', - description: - 'Detailed information about the input (prompt) tokens.', - properties: [ - { - type: 'LanguageModelInputTokenDetails', - parameters: [ - { - name: 'noCacheTokens', - type: 'number | undefined', - description: - 'The number of non-cached input (prompt) tokens used.', - }, - { - name: 'cacheReadTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens read.', - }, - { - name: 'cacheWriteTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens written.', - }, - ], - }, - ], - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: - 'The number of total output (completion) tokens used.', - }, - { - name: 'outputTokenDetails', - type: 'LanguageModelOutputTokenDetails', - description: - 'Detailed information about the output (completion) tokens.', - properties: [ - { - type: 'LanguageModelOutputTokenDetails', - parameters: [ - { - name: 'textTokens', - type: 'number | undefined', - description: 'The number of text tokens used.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - description: - 'The number of reasoning tokens used.', - }, - ], - }, - ], - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used.', - }, - { - name: 'raw', - type: 'object | undefined', - isOptional: true, - description: - "Raw usage information from the provider. This is the provider's original usage information and may include additional fields.", - }, - ], - }, - ], - }, - { - name: 'totalUsage', - type: 'LanguageModelUsage', - description: - 'Aggregated token usage across all steps. This is the sum of the usage from each individual step.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: - 'The total number of input (prompt) tokens used across all steps.', - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: - 'The total number of output (completion) tokens used across all steps.', - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: - 'The total number of tokens used across all steps.', - }, - ], - }, - ], - }, - { - name: 'content', - type: 'Array>', - description: 'The content that was generated in the final step.', - }, - { - name: 'providerMetadata', - type: 'ProviderMetadata | undefined', - description: - 'Additional provider-specific metadata from the final step.', - }, - { - name: 'text', - type: 'string', - description: 'The full text that has been generated.', - }, - { - name: 'reasoningText', - type: 'string | undefined', - description: - 'The reasoning text of the model (only available for some models).', - }, - { - name: 'reasoning', - type: 'Array', - description: - 'The reasoning details of the model (only available for some models).', - properties: [ - { - type: 'ReasoningDetail', - parameters: [ - { - name: 'type', - type: "'text'", - description: 'The type of the reasoning detail.', - }, - { - name: 'text', - type: 'string', - description: 'The text content (only for type "text").', - }, - { - name: 'signature', - type: 'string', - isOptional: true, - description: 'Optional signature (only for type "text").', - }, - ], - }, - { - type: 'ReasoningDetail', - parameters: [ - { - name: 'type', - type: "'redacted'", - description: 'The type of the reasoning detail.', - }, - { - name: 'data', - type: 'string', - description: - 'The redacted data content (only for type "redacted").', - }, - ], - }, - ], - }, - { - name: 'sources', - type: 'Array', - description: - 'Sources that have been used as input to generate the response. For multi-step generation, the sources are accumulated from all steps.', - properties: [ - { - type: 'Source', - parameters: [ - { - name: 'sourceType', - type: "'url'", - description: - 'A URL source. This is return by web search RAG models.', - }, - { - name: 'id', - type: 'string', - description: 'The ID of the source.', - }, - { - name: 'url', - type: 'string', - description: 'The URL of the source.', - }, - { - name: 'title', - type: 'string', - isOptional: true, - description: 'The title of the source.', - }, - { - name: 'providerMetadata', - type: 'SharedV2ProviderMetadata', - isOptional: true, - description: - 'Additional provider metadata for the source.', - }, - ], - }, - ], - }, - { - name: 'files', - type: 'Array', - description: 'Files that were generated in the final step.', - properties: [ - { - type: 'GeneratedFile', - parameters: [ - { - name: 'base64', - type: 'string', - description: 'File as a base64 encoded string.', - }, - { - name: 'uint8Array', - type: 'Uint8Array', - description: 'File as a Uint8Array.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - ], - }, - ], - }, - { - name: 'toolCalls', - type: 'Array>', - description: - 'The tool calls that were made during the generation.', - }, - { - name: 'staticToolCalls', - type: 'Array>', - description: - 'The static tool calls that were made in the final step.', - }, - { - name: 'dynamicToolCalls', - type: 'Array', - description: - 'The dynamic tool calls that were made in the final step.', - }, - { - name: 'toolResults', - type: 'Array>', - description: 'The results of the tool calls.', - }, - { - name: 'staticToolResults', - type: 'Array>', - description: - 'The static tool results that were made in the final step.', - }, - { - name: 'dynamicToolResults', - type: 'Array', - description: - 'The dynamic tool results that were made in the final step.', - }, - { - name: 'warnings', - type: 'CallWarning[] | undefined', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'request', - type: 'LanguageModelRequestMetadata', - description: - 'Additional request information from the final step.', - }, - { - name: 'response', - type: 'LanguageModelResponseMetadata & { messages: Array; body?: unknown }', - description: - 'Additional response information from the final step.', - properties: [ - { - type: 'Response', - parameters: [ - { - name: 'id', - type: 'string', - description: - 'The response identifier. The AI SDK uses the ID from the provider response when available, and generates an ID otherwise.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The model that was used to generate the response. The AI SDK uses the response model from the provider response when available, and the model from the function call otherwise.', - }, - { - name: 'timestamp', - type: 'Date', - description: - 'The timestamp of the response. The AI SDK uses the response timestamp from the provider response when available, and creates a timestamp otherwise.', - }, - { - name: 'headers', - isOptional: true, - type: 'Record', - description: 'Optional response headers.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The response messages that were generated during the call. It consists of an assistant message, potentially containing tool calls. When there are tool results, there is an additional tool message with the tool results that are available. If there are tools that do not have execute functions, they are not included in the tool results and need to be added separately.', - }, - ], - }, - ], - }, - { - name: 'steps', - type: 'Array', - description: - 'Response information for every step. You can use this to get information about intermediate steps, such as the tool calls or the response headers.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'The final state of the user-defined context object. This reflects any modifications made during the generation lifecycle via prepareStep or tool execution.', - }, - ], - }, - ], - }, - ]} -/> - -### Returns - ->', - description: 'The content that was generated in the last step.', - }, - { - name: 'text', - type: 'string', - description: 'The generated text by the model.', - }, - { - name: 'reasoning', - type: 'Array', - description: - 'The full reasoning that the model has generated in the last step.', - properties: [ - { - type: 'ReasoningOutput', - parameters: [ - { - name: 'type', - type: "'reasoning'", - description: 'The type of the message part.', - }, - { - name: 'text', - type: 'string', - description: 'The reasoning text.', - }, - { - name: 'providerMetadata', - type: 'SharedV2ProviderMetadata', - isOptional: true, - description: 'Additional provider metadata for the source.', - }, - ], - }, - ], - }, - { - name: 'reasoningText', - type: 'string | undefined', - description: - 'The reasoning text that the model has generated in the last step. Can be undefined if the model has only generated text.', - }, - { - name: 'sources', - type: 'Array', - description: - 'Sources that have been used as input to generate the response. For multi-step generation, the sources are accumulated from all steps.', - properties: [ - { - type: 'Source', - parameters: [ - { - name: 'sourceType', - type: "'url'", - description: - 'A URL source. This is return by web search RAG models.', - }, - { - name: 'id', - type: 'string', - description: 'The ID of the source.', - }, - { - name: 'url', - type: 'string', - description: 'The URL of the source.', - }, - { - name: 'title', - type: 'string', - isOptional: true, - description: 'The title of the source.', - }, - { - name: 'providerMetadata', - type: 'SharedV2ProviderMetadata', - isOptional: true, - description: 'Additional provider metadata for the source.', - }, - ], - }, - ], - }, - { - name: 'files', - type: 'Array', - description: 'Files that were generated in the final step.', - properties: [ - { - type: 'GeneratedFile', - parameters: [ - { - name: 'base64', - type: 'string', - description: 'File as a base64 encoded string.', - }, - { - name: 'uint8Array', - type: 'Uint8Array', - description: 'File as a Uint8Array.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - ], - }, - ], - }, - { - name: 'toolCalls', - type: 'ToolCallArray', - description: 'The tool calls that were made in the last step.', - }, - { - name: 'toolResults', - type: 'ToolResultArray', - description: 'The results of the tool calls from the last step.', - }, - { - name: 'staticToolCalls', - type: 'Array>', - description: - 'The static tool calls that have been executed in the last step.', - }, - { - name: 'dynamicToolCalls', - type: 'Array', - description: - 'The dynamic tool calls that have been executed in the last step.', - }, - { - name: 'staticToolResults', - type: 'Array>', - description: - 'The static tool results that have been generated in the last step.', - }, - { - name: 'dynamicToolResults', - type: 'Array', - description: - 'The dynamic tool results that have been generated in the last step.', - }, - { - name: 'finishReason', - type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'", - description: 'The reason the model finished generating the text.', - }, - { - name: 'rawFinishReason', - type: 'string | undefined', - description: - 'The raw reason why the generation finished (from the provider).', - }, - { - name: 'usage', - type: 'LanguageModelUsage', - description: 'The token usage of the last step.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: 'The total number of input (prompt) tokens used.', - }, - { - name: 'inputTokenDetails', - type: 'LanguageModelInputTokenDetails', - description: - 'Detailed information about the input (prompt) tokens. See also: cached tokens and non-cached tokens.', - properties: [ - { - type: 'LanguageModelInputTokenDetails', - parameters: [ - { - name: 'noCacheTokens', - type: 'number | undefined', - description: - 'The number of non-cached input (prompt) tokens used.', - }, - { - name: 'cacheReadTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens read.', - }, - { - name: 'cacheWriteTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens written.', - }, - ], - }, - ], - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: - 'The number of total output (completion) tokens used.', - }, - { - name: 'outputTokenDetails', - type: 'LanguageModelOutputTokenDetails', - description: - 'Detailed information about the output (completion) tokens.', - properties: [ - { - type: 'LanguageModelOutputTokenDetails', - parameters: [ - { - name: 'textTokens', - type: 'number | undefined', - description: 'The number of text tokens used.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - description: 'The number of reasoning tokens used.', - }, - ], - }, - ], - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used.', - }, - { - name: 'raw', - type: 'object | undefined', - isOptional: true, - description: - "Raw usage information from the provider. This is the provider's original usage information and may include additional fields.", - }, - ], - }, - ], - }, - { - name: 'totalUsage', - type: 'LanguageModelUsage', - description: - 'The total token usage of all steps. When there are multiple steps, the usage is the sum of all step usages.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: 'The number of input (prompt) tokens used.', - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: 'The number of output (completion) tokens used.', - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: - 'The total number of tokens as reported by the provider. This number might be different from the sum of inputTokens and outputTokens and e.g. include reasoning tokens or other overhead.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - isOptional: true, - description: 'The number of reasoning tokens used.', - }, - { - name: 'cachedInputTokens', - type: 'number | undefined', - isOptional: true, - description: 'The number of cached input tokens.', - }, - ], - }, - ], - }, - { - name: 'request', - type: 'LanguageModelRequestMetadata', - isOptional: true, - description: 'Request metadata.', - properties: [ - { - type: 'LanguageModelRequestMetadata', - parameters: [ - { - name: 'body', - type: 'string', - description: - 'Raw request HTTP body that was sent to the provider API as a string (JSON should be stringified).', - }, - ], - }, - ], - }, - { - name: 'response', - type: 'LanguageModelResponseMetadata', - isOptional: true, - description: 'Response metadata.', - properties: [ - { - type: 'LanguageModelResponseMetadata', - parameters: [ - { - name: 'id', - type: 'string', - description: - 'The response identifier. The AI SDK uses the ID from the provider response when available, and generates an ID otherwise.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The model that was used to generate the response. The AI SDK uses the response model from the provider response when available, and the model from the function call otherwise.', - }, - { - name: 'timestamp', - type: 'Date', - description: - 'The timestamp of the response. The AI SDK uses the response timestamp from the provider response when available, and creates a timestamp otherwise.', - }, - { - name: 'headers', - isOptional: true, - type: 'Record', - description: 'Optional response headers.', - }, - { - name: 'body', - isOptional: true, - type: 'unknown', - description: 'Optional response body.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The response messages that were generated during the call. It consists of an assistant message, potentially containing tool calls. When there are tool results, there is an additional tool message with the tool results that are available. If there are tools that do not have execute functions, they are not included in the tool results and need to be added separately.', - }, - ], - }, - ], - }, - { - name: 'warnings', - type: 'Warning[] | undefined', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'providerMetadata', - type: 'ProviderMetadata | undefined', - description: - 'Optional metadata from the provider. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - { - name: 'output', - type: 'Output', - isOptional: true, - description: 'Experimental setting for generating structured outputs.', - }, - { - name: 'steps', - type: 'Array>', - description: - 'Response information for every step. You can use this to get information about intermediate steps, such as the tool calls or the response headers.', - properties: [ - { - type: 'StepResult', - parameters: [ - { - name: 'stepNumber', - type: 'number', - description: 'The zero-based index of this step.', - }, - { - name: 'model', - type: '{ provider: string; modelId: string }', - description: - 'Information about the model that produced this step.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object flowing through the generation.', - }, - { - name: 'content', - type: 'Array>', - description: 'The content that was generated in the last step.', - }, - { - name: 'text', - type: 'string', - description: 'The generated text.', - }, - { - name: 'reasoning', - type: 'Array', - description: - 'The reasoning that was generated during the generation.', - properties: [ - { - type: 'ReasoningPart', - parameters: [ - { - name: 'type', - type: "'reasoning'", - description: 'The type of the message part.', - }, - { - name: 'text', - type: 'string', - description: 'The reasoning text.', - }, - ], - }, - ], - }, - { - name: 'reasoningText', - type: 'string | undefined', - description: - 'The reasoning text that was generated during the generation.', - }, - { - name: 'files', - type: 'Array', - description: - 'The files that were generated during the generation.', - properties: [ - { - type: 'GeneratedFile', - parameters: [ - { - name: 'base64', - type: 'string', - description: 'File as a base64 encoded string.', - }, - { - name: 'uint8Array', - type: 'Uint8Array', - description: 'File as a Uint8Array.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - ], - }, - ], - }, - { - name: 'sources', - type: 'Array', - description: 'The sources that were used to generate the text.', - properties: [ - { - type: 'Source', - parameters: [ - { - name: 'sourceType', - type: "'url'", - description: - 'A URL source. This is return by web search RAG models.', - }, - { - name: 'id', - type: 'string', - description: 'The ID of the source.', - }, - { - name: 'url', - type: 'string', - description: 'The URL of the source.', - }, - { - name: 'title', - type: 'string', - isOptional: true, - description: 'The title of the source.', - }, - { - name: 'providerMetadata', - type: 'SharedV2ProviderMetadata', - isOptional: true, - description: - 'Additional provider metadata for the source.', - }, - ], - }, - ], - }, - { - name: 'toolCalls', - type: 'ToolCallArray', - description: - 'The tool calls that were made during the generation.', - }, - { - name: 'toolResults', - type: 'ToolResultArray', - description: 'The results of the tool calls.', - }, - { - name: 'finishReason', - type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'", - description: 'The reason why the generation finished.', - }, - { - name: 'rawFinishReason', - type: 'string | undefined', - description: - 'The raw reason why the generation finished (from the provider).', - }, - { - name: 'usage', - type: 'LanguageModelUsage', - description: 'The token usage of the generated text.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: - 'The total number of input (prompt) tokens used.', - }, - { - name: 'inputTokenDetails', - type: 'LanguageModelInputTokenDetails', - description: - 'Detailed information about the input (prompt) tokens. See also: cached tokens and non-cached tokens.', - properties: [ - { - type: 'LanguageModelInputTokenDetails', - parameters: [ - { - name: 'noCacheTokens', - type: 'number | undefined', - description: - 'The number of non-cached input (prompt) tokens used.', - }, - { - name: 'cacheReadTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens read.', - }, - { - name: 'cacheWriteTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens written.', - }, - ], - }, - ], - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: - 'The number of total output (completion) tokens used.', - }, - { - name: 'outputTokenDetails', - type: 'LanguageModelOutputTokenDetails', - description: - 'Detailed information about the output (completion) tokens.', - properties: [ - { - type: 'LanguageModelOutputTokenDetails', - parameters: [ - { - name: 'textTokens', - type: 'number | undefined', - description: 'The number of text tokens used.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - description: - 'The number of reasoning tokens used.', - }, - ], - }, - ], - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used.', - }, - { - name: 'raw', - type: 'object | undefined', - isOptional: true, - description: - "Raw usage information from the provider. This is the provider's original usage information and may include additional fields.", - }, - ], - }, - ], - }, - { - name: 'warnings', - type: 'Warning[] | undefined', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'request', - type: 'LanguageModelRequestMetadata', - description: 'Additional request information.', - properties: [ - { - type: 'LanguageModelRequestMetadata', - parameters: [ - { - name: 'body', - type: 'string', - description: - 'Raw request HTTP body that was sent to the provider API as a string (JSON should be stringified).', - }, - ], - }, - ], - }, - { - name: 'response', - type: 'LanguageModelResponseMetadata', - description: 'Additional response information.', - properties: [ - { - type: 'LanguageModelResponseMetadata', - parameters: [ - { - name: 'id', - type: 'string', - description: - 'The response identifier. The AI SDK uses the ID from the provider response when available, and generates an ID otherwise.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The model that was used to generate the response. The AI SDK uses the response model from the provider response when available, and the model from the function call otherwise.', - }, - { - name: 'timestamp', - type: 'Date', - description: - 'The timestamp of the response. The AI SDK uses the response timestamp from the provider response when available, and creates a timestamp otherwise.', - }, - { - name: 'headers', - isOptional: true, - type: 'Record', - description: 'Optional response headers.', - }, - { - name: 'body', - isOptional: true, - type: 'unknown', - description: - 'Response body (available only for providers that use HTTP requests).', - }, - { - name: 'messages', - type: 'Array', - description: - 'The response messages that were generated during the call. Response messages can be either assistant messages or tool messages. They contain a generated id.', - }, - ], - }, - ], - }, - { - name: 'providerMetadata', - type: 'ProviderMetadata | undefined', - description: - 'Additional provider-specific metadata. They are passed through from the provider to the AI SDK and enable provider-specific results that can be fully encapsulated in the provider.', - }, - ], - }, - ], - }, - ]} -/> - -## Examples - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx deleted file mode 100644 index 7b4f9ba23..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +++ /dev/null @@ -1,3656 +0,0 @@ ---- -title: streamText -description: API Reference for streamText. ---- - -# `streamText()` - -Streams text generations from a language model. - -You can use the streamText function for interactive use cases such as chat bots and other real-time applications. You can also generate UI components with tools. - -```ts -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const { textStream } = streamText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', -}); - -for await (const textPart of textStream) { - process.stdout.write(textPart); -} -``` - -To see `streamText` in action, check out [these examples](#examples). - -## Import - - - -## API Signature - -### Parameters - -', - description: 'The input prompt to generate the text from.', - }, - { - name: 'messages', - type: 'Array', - description: - 'A list of messages that represent a conversation. Automatically converts UI messages from the useChat hook.', - properties: [ - { - type: 'SystemModelMessage', - parameters: [ - { - name: 'role', - type: "'system'", - description: 'The role for the system message.', - }, - { - name: 'content', - type: 'string', - description: 'The content of the message.', - }, - ], - }, - { - type: 'UserModelMessage', - parameters: [ - { - name: 'role', - type: "'user'", - description: 'The role for the user message.', - }, - { - name: 'content', - type: 'string | Array', - description: 'The content of the message.', - properties: [ - { - type: 'TextPart', - parameters: [ - { - name: 'type', - type: "'text'", - description: 'The type of the message part.', - }, - { - name: 'text', - type: 'string', - description: 'The text content of the message part.', - }, - ], - }, - { - type: 'ImagePart', - parameters: [ - { - name: 'type', - type: "'image'", - description: 'The type of the message part.', - }, - { - name: 'image', - type: 'string | Uint8Array | Buffer | ArrayBuffer | URL', - description: - 'The image content of the message part. String are either base64 encoded content, base64 data URLs, or http(s) URLs.', - }, - { - name: 'mediaType', - type: 'string', - isOptional: true, - description: 'The IANA media type of the image.', - }, - ], - }, - { - type: 'FilePart', - parameters: [ - { - name: 'type', - type: "'file'", - description: 'The type of the message part.', - }, - { - name: 'data', - type: 'string | Uint8Array | Buffer | ArrayBuffer | URL', - description: - 'The file content of the message part. String are either base64 encoded content, base64 data URLs, or http(s) URLs.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - ], - }, - ], - }, - ], - }, - { - type: 'AssistantModelMessage', - parameters: [ - { - name: 'role', - type: "'assistant'", - description: 'The role for the assistant message.', - }, - { - name: 'content', - type: 'string | Array', - description: 'The content of the message.', - properties: [ - { - type: 'TextPart', - parameters: [ - { - name: 'type', - type: "'text'", - description: 'The type of the message part.', - }, - { - name: 'text', - type: 'string', - description: 'The text content of the message part.', - }, - ], - }, - { - type: 'ReasoningPart', - parameters: [ - { - name: 'type', - type: "'reasoning'", - description: 'The type of the reasoning part.', - }, - { - name: 'text', - type: 'string', - description: 'The reasoning text.', - }, - ], - }, - { - type: 'FilePart', - parameters: [ - { - name: 'type', - type: "'file'", - description: 'The type of the message part.', - }, - { - name: 'data', - type: 'string | Uint8Array | Buffer | ArrayBuffer | URL', - description: - 'The file content of the message part. String are either base64 encoded content, base64 data URLs, or http(s) URLs.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - { - name: 'filename', - type: 'string', - description: 'The name of the file.', - isOptional: true, - }, - ], - }, - { - type: 'ToolCallPart', - parameters: [ - { - name: 'type', - type: "'tool-call'", - description: 'The type of the message part.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool, which typically would be the name of the function.', - }, - { - name: 'input', - type: 'object based on zod schema', - description: - 'Parameters generated by the model to be used by the tool.', - }, - ], - }, - ], - }, - ], - }, - { - type: 'ToolModelMessage', - parameters: [ - { - name: 'role', - type: "'tool'", - description: 'The role for the assistant message.', - }, - { - name: 'content', - type: 'Array', - description: 'The content of the message.', - properties: [ - { - type: 'ToolResultPart', - parameters: [ - { - name: 'type', - type: "'tool-result'", - description: 'The type of the message part.', - }, - { - name: 'toolCallId', - type: 'string', - description: - 'The id of the tool call the result corresponds to.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool the result corresponds to.', - }, - { - name: 'result', - type: 'unknown', - description: - 'The result returned by the tool after execution.', - }, - { - name: 'isError', - type: 'boolean', - isOptional: true, - description: - 'Whether the result is an error or an error message.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - name: 'tools', - type: 'ToolSet', - description: - 'Tools that are accessible to and can be called by the model. The model needs to support calling tools.', - properties: [ - { - type: 'Tool', - parameters: [ - { - name: 'description', - isOptional: true, - type: 'string', - description: - 'Information about the purpose of the tool including details on how and when it can be used by the model.', - }, - { - name: 'inputSchema', - type: 'Zod Schema | JSON Schema', - description: - 'The schema of the input that the tool expects. The language model will use this to generate the input. It is also used to validate the output of the language model. Use descriptions to make the input understandable for the language model. You can either pass in a Zod schema or a JSON schema (using the `jsonSchema` function).', - }, - { - name: 'execute', - isOptional: true, - type: 'async (parameters: T, options: ToolExecutionOptions) => RESULT', - description: - 'An async function that is called with the arguments from the tool call and produces a result. If not provided, the tool will not be executed automatically.', - properties: [ - { - type: 'ToolExecutionOptions', - parameters: [ - { - name: 'toolCallId', - type: 'string', - description: - 'The ID of the tool call. You can use it e.g. when sending tool-call related information with stream data.', - }, - { - name: 'messages', - type: 'ModelMessage[]', - description: - 'Messages that were sent to the language model to initiate the response that contained the tool call. The messages do not include the system prompt nor the assistant response that contained the tool call.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - description: - 'An optional abort signal that indicates that the overall operation should be aborted.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - name: 'toolChoice', - isOptional: true, - type: '"auto" | "none" | "required" | { "type": "tool", "toolName": string }', - description: - 'The tool choice setting. It specifies how tools are selected for execution. The default is "auto". "none" disables tool execution. "required" requires tools to be executed. { "type": "tool", "toolName": string } specifies a specific tool to execute.', - }, - { - name: 'maxOutputTokens', - type: 'number', - isOptional: true, - description: 'Maximum number of tokens to generate.', - }, - { - name: 'temperature', - type: 'number', - isOptional: true, - description: - 'Temperature setting. The value is passed through to the provider. The range depends on the provider and model. It is recommended to set either `temperature` or `topP`, but not both.', - }, - { - name: 'topP', - type: 'number', - isOptional: true, - description: - 'Nucleus sampling. The value is passed through to the provider. The range depends on the provider and model. It is recommended to set either `temperature` or `topP`, but not both.', - }, - { - name: 'topK', - type: 'number', - isOptional: true, - description: - 'Only sample from the top K options for each subsequent token. Used to remove "long tail" low probability responses. Recommended for advanced use cases only. You usually only need to use temperature.', - }, - { - name: 'presencePenalty', - type: 'number', - isOptional: true, - description: - 'Presence penalty setting. It affects the likelihood of the model to repeat information that is already in the prompt. The value is passed through to the provider. The range depends on the provider and model.', - }, - { - name: 'frequencyPenalty', - type: 'number', - isOptional: true, - description: - 'Frequency penalty setting. It affects the likelihood of the model to repeatedly use the same words or phrases. The value is passed through to the provider. The range depends on the provider and model.', - }, - { - name: 'stopSequences', - type: 'string[]', - isOptional: true, - description: - 'Sequences that will stop the generation of the text. If the model generates any of these sequences, it will stop generating further text.', - }, - { - name: 'seed', - type: 'number', - isOptional: true, - description: - 'The seed (integer) to use for random sampling. If set and supported by the model, calls will generate deterministic results.', - }, - { - name: 'maxRetries', - type: 'number', - isOptional: true, - description: - 'Maximum number of retries. Set to 0 to disable retries. Default: 2.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - isOptional: true, - description: - 'An optional abort signal that can be used to cancel the call.', - }, - { - name: 'timeout', - type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number }', - isOptional: true, - description: - 'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, and/or chunkMs properties. totalMs sets the total timeout for the entire call. stepMs sets the timeout for each individual step (LLM call), useful for multi-step generations. chunkMs sets the timeout between stream chunks - the call will abort if no new chunk is received within this duration, useful for detecting stalled streams. Can be used alongside abortSignal.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: - 'Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.', - }, - { - name: 'experimental_telemetry', - type: 'TelemetrySettings', - isOptional: true, - description: 'Telemetry configuration. Experimental feature.', - properties: [ - { - type: 'TelemetrySettings', - parameters: [ - { - name: 'isEnabled', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable telemetry. Disabled by default while experimental.', - }, - { - name: 'recordInputs', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable input recording. Enabled by default.', - }, - { - name: 'recordOutputs', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable output recording. Enabled by default.', - }, - { - name: 'functionId', - type: 'string', - isOptional: true, - description: - 'Identifier for this function. Used to group telemetry data by function.', - }, - { - name: 'metadata', - isOptional: true, - type: 'Record | Array | Array>', - description: - 'Additional information to include in the telemetry data.', - }, - ], - }, - ], - }, - { - name: 'experimental_transform', - type: 'StreamTextTransform | Array', - isOptional: true, - description: - 'Optional stream transformations. They are applied in the order they are provided. The stream transformations must maintain the stream structure for streamText to work correctly.', - properties: [ - { - type: 'StreamTextTransform', - parameters: [ - { - name: 'transform', - type: '(options: TransformOptions) => TransformStream, TextStreamPart>', - description: 'A transformation that is applied to the stream.', - properties: [ - { - type: 'TransformOptions', - parameters: [ - { - name: 'stopStream', - type: '() => void', - description: 'A function that stops the stream.', - }, - { - name: 'tools', - type: 'TOOLS', - description: 'The tools that are available.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - name: 'includeRawChunks', - type: 'boolean', - isOptional: true, - description: - 'Whether to include raw chunks from the provider in the stream. When enabled, you will receive raw chunks with type "raw" that contain the unprocessed data from the provider. This allows access to cutting-edge provider features not yet wrapped by the AI SDK. Defaults to false.', - }, - { - name: 'providerOptions', - type: 'Record | undefined', - isOptional: true, - description: - 'Provider-specific options. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - { - name: 'activeTools', - type: 'Array | undefined', - isOptional: true, - description: - 'The tools that are currently active. All tools are active by default.', - }, - { - name: 'stopWhen', - type: 'StopCondition | Array>', - isOptional: true, - description: - 'Condition for stopping the generation when there are tool results in the last step. When the condition is an array, any of the conditions can be met to stop the generation. Default: stepCountIs(1).', - }, - { - name: 'prepareStep', - type: '(options: PrepareStepOptions) => PrepareStepResult | Promise>', - isOptional: true, - description: - 'Optional function that you can use to provide different settings for a step. You can modify the model, tool choices, active tools, system prompt, and input messages for each step.', - properties: [ - { - type: 'PrepareStepFunction', - parameters: [ - { - name: 'options', - type: 'object', - description: 'The options for the step.', - properties: [ - { - type: 'PrepareStepOptions', - parameters: [ - { - name: 'steps', - type: 'Array>', - description: 'The steps that have been executed so far.', - }, - { - name: 'stepNumber', - type: 'number', - description: - 'The number of the step that is being executed.', - }, - { - name: 'model', - type: 'LanguageModel', - description: 'The model that is being used.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The messages that will be sent to the model for the current step.', - }, - { - name: 'experimental_context', - type: 'unknown', - isOptional: true, - description: - 'The context passed via the experimental_context setting (experimental).', - }, - ], - }, - ], - }, - ], - }, - { - type: 'PrepareStepResult', - description: - 'Return value that can modify settings for the current step.', - parameters: [ - { - name: 'model', - type: 'LanguageModel', - isOptional: true, - description: - 'Optionally override which LanguageModel instance is used for this step.', - }, - { - name: 'toolChoice', - type: 'ToolChoice', - isOptional: true, - description: - 'Optionally set which tool the model must call, or provide tool call configuration for this step.', - }, - { - name: 'activeTools', - type: 'Array', - isOptional: true, - description: - 'If provided, only these tools are enabled/available for this step.', - }, - { - name: 'system', - type: 'string | SystemModelMessage | SystemModelMessage[]', - isOptional: true, - description: - 'Optionally override the system message(s) sent to the model for this step.', - }, - { - name: 'messages', - type: 'Array', - isOptional: true, - description: - 'Optionally override the full set of messages sent to the model for this step.', - }, - { - name: 'experimental_context', - type: 'unknown', - isOptional: true, - description: - 'Context that is passed into tool execution. Experimental. Changing the context will affect the context in this step and all subsequent steps.', - }, - { - name: 'providerOptions', - type: 'ProviderOptions', - isOptional: true, - description: - 'Additional provider-specific options for this step. Can be used to pass provider-specific configuration such as container IDs for Anthropic code execution.', - }, - ], - }, - ], - }, - { - name: 'experimental_context', - type: 'unknown', - isOptional: true, - description: - 'Context that is passed into tool execution. Experimental (can break in patch releases).', - }, - { - name: 'experimental_download', - type: '(requestedDownloads: Array<{ url: URL; isUrlSupportedByModel: boolean }>) => Promise>', - isOptional: true, - description: - 'Custom download function to control how URLs are fetched when they appear in prompts. By default, files are downloaded if the model does not support the URL for the given media type. Experimental feature. Return null to pass the URL directly to the model (when supported), or return downloaded content with data and media type.', - }, - { - name: 'experimental_include', - type: '{ requestBody?: boolean }', - isOptional: true, - description: - 'Controls inclusion of request body in step results. By default, the body is included. When processing many large payloads (e.g., images), set requestBody to false to reduce memory usage. Experimental feature.', - properties: [ - { - type: 'Object', - parameters: [ - { - name: 'requestBody', - type: 'boolean', - isOptional: true, - description: - 'Whether to include the request body in step results. The request body can be large when sending images or files. Default: true.', - }, - ], - }, - ], - }, - { - name: 'experimental_repairToolCall', - type: '(options: ToolCallRepairOptions) => Promise', - isOptional: true, - description: - 'A function that attempts to repair a tool call that failed to parse. Return either a repaired tool call or null if the tool call cannot be repaired.', - properties: [ - { - type: 'ToolCallRepairOptions', - parameters: [ - { - name: 'system', - type: 'string | SystemModelMessage | SystemModelMessage[] | undefined', - description: 'The system prompt.', - }, - { - name: 'messages', - type: 'ModelMessage[]', - description: 'The messages in the current generation step.', - }, - { - name: 'toolCall', - type: 'LanguageModelV3ToolCall', - description: 'The tool call that failed to parse.', - }, - { - name: 'tools', - type: 'TOOLS', - description: 'The tools that are available.', - }, - { - name: 'parameterSchema', - type: '(options: { toolName: string }) => JSONSchema7', - description: - 'A function that returns the JSON Schema for a tool.', - }, - { - name: 'error', - type: 'NoSuchToolError | InvalidToolInputError', - description: - 'The error that occurred while parsing the tool call.', - }, - ], - }, - ], - }, - { - name: 'onChunk', - type: '(event: OnChunkResult) => Promise |void', - isOptional: true, - description: - 'Callback that is called for each chunk of the stream. The stream processing will pause until the callback promise is resolved.', - properties: [ - { - type: 'OnChunkResult', - parameters: [ - { - name: 'chunk', - type: 'TextStreamPart', - description: 'The chunk of the stream.', - properties: [ - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'text'", - description: - 'The type to identify the object as text delta.', - }, - { - name: 'text', - type: 'string', - description: 'The text delta.', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'reasoning'", - description: - 'The type to identify the object as reasoning.', - }, - { - name: 'text', - type: 'string', - description: 'The reasoning text delta.', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'source'", - description: 'The type to identify the object as source.', - }, - { - name: 'source', - type: 'Source', - description: 'The source.', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'tool-call'", - description: - 'The type to identify the object as tool call.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool, which typically would be the name of the function.', - }, - { - name: 'input', - type: 'object based on zod schema', - description: - 'Parameters generated by the model to be used by the tool.', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'tool-call-streaming-start'", - description: - 'Indicates the start of a tool call streaming. Only available when streaming tool calls.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool, which typically would be the name of the function.', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'tool-call-delta'", - description: - 'The type to identify the object as tool call delta. Only available when streaming tool calls.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool, which typically would be the name of the function.', - }, - { - name: 'argsTextDelta', - type: 'string', - description: 'The text delta of the tool call arguments.', - }, - ], - }, - { - type: 'TextStreamPart', - description: 'The result of a tool call execution.', - parameters: [ - { - name: 'type', - type: "'tool-result'", - description: - 'The type to identify the object as tool result.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool, which typically would be the name of the function.', - }, - { - name: 'input', - type: 'object based on zod schema', - description: - 'Parameters generated by the model to be used by the tool.', - }, - { - name: 'output', - type: 'any', - description: - 'The result returned by the tool after execution has completed.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - name: 'onError', - type: '(event: OnErrorResult) => Promise |void', - isOptional: true, - description: - 'Callback that is called when an error occurs during streaming. You can use it to log errors.', - properties: [ - { - type: 'OnErrorResult', - parameters: [ - { - name: 'error', - type: 'unknown', - description: 'The error that occurred.', - }, - ], - }, - ], - }, - { - name: 'output', - type: 'Output', - isOptional: true, - description: - 'Specification for parsing structured outputs from the LLM response.', - properties: [ - { - type: 'Output', - parameters: [ - { - name: 'Output.text()', - type: 'Output', - description: - 'Output specification for text generation (default).', - }, - { - name: 'Output.object()', - type: 'Output', - description: - 'Output specification for typed object generation using schemas. When the model generates a text response, it will return an object that matches the schema.', - properties: [ - { - type: 'Options', - parameters: [ - { - name: 'schema', - type: 'Schema', - description: 'The schema of the object to generate.', - }, - { - name: 'name', - type: 'string', - isOptional: true, - description: - 'Optional name of the output. Used by some providers for additional LLM guidance.', - }, - { - name: 'description', - type: 'string', - isOptional: true, - description: - 'Optional description of the output. Used by some providers for additional LLM guidance.', - }, - ], - }, - ], - }, - { - name: 'Output.array()', - type: 'Output', - description: - 'Output specification for array generation. When the model generates a text response, it will return an array of elements.', - properties: [ - { - type: 'Options', - parameters: [ - { - name: 'element', - type: 'Schema', - description: - 'The schema of the array elements to generate.', - }, - { - name: 'name', - type: 'string', - isOptional: true, - description: - 'Optional name of the output. Used by some providers for additional LLM guidance.', - }, - { - name: 'description', - type: 'string', - isOptional: true, - description: - 'Optional description of the output. Used by some providers for additional LLM guidance.', - }, - ], - }, - ], - }, - { - name: 'Output.choice()', - type: 'Output', - description: - 'Output specification for choice generation. When the model generates a text response, it will return a one of the choice options.', - properties: [ - { - type: 'Options', - parameters: [ - { - name: 'options', - type: 'Array', - description: 'The available choices.', - }, - { - name: 'name', - type: 'string', - isOptional: true, - description: - 'Optional name of the output. Used by some providers for additional LLM guidance.', - }, - { - name: 'description', - type: 'string', - isOptional: true, - description: - 'Optional description of the output. Used by some providers for additional LLM guidance.', - }, - ], - }, - ], - }, - { - name: 'Output.json()', - type: 'Output', - description: - 'Output specification for unstructured JSON generation. When the model generates a text response, it will return a JSON object.', - properties: [ - { - type: 'Options', - parameters: [ - { - name: 'name', - type: 'string', - isOptional: true, - description: - 'Optional name of the output. Used by some providers for additional LLM guidance.', - }, - { - name: 'description', - type: 'string', - isOptional: true, - description: - 'Optional description of the output. Used by some providers for additional LLM guidance.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - name: 'onStepFinish', - type: '(result: onStepFinishResult) => Promise | void', - isOptional: true, - description: 'Callback that is called when a step is finished.', - properties: [ - { - type: 'onStepFinishResult', - parameters: [ - { - name: 'stepType', - type: '"initial" | "continue" | "tool-result"', - description: - 'The type of step. The first step is always an "initial" step, and subsequent steps are either "continue" steps or "tool-result" steps.', - }, - { - name: 'finishReason', - type: '"stop" | "length" | "content-filter" | "tool-calls" | "error" | "other"', - description: - 'The unified finish reason why the generation finished.', - }, - { - name: 'rawFinishReason', - type: 'string | undefined', - description: - 'The raw reason why the generation finished (from the provider).', - }, - { - name: 'usage', - type: 'LanguageModelUsage', - description: 'The token usage of the step.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: - 'The total number of input (prompt) tokens used.', - }, - { - name: 'inputTokenDetails', - type: 'LanguageModelInputTokenDetails', - description: - 'Detailed information about the input (prompt) tokens. See also: cached tokens and non-cached tokens.', - properties: [ - { - type: 'LanguageModelInputTokenDetails', - parameters: [ - { - name: 'noCacheTokens', - type: 'number | undefined', - description: - 'The number of non-cached input (prompt) tokens used.', - }, - { - name: 'cacheReadTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens read.', - }, - { - name: 'cacheWriteTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens written.', - }, - ], - }, - ], - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: - 'The number of total output (completion) tokens used.', - }, - { - name: 'outputTokenDetails', - type: 'LanguageModelOutputTokenDetails', - description: - 'Detailed information about the output (completion) tokens.', - properties: [ - { - type: 'LanguageModelOutputTokenDetails', - parameters: [ - { - name: 'textTokens', - type: 'number | undefined', - description: 'The number of text tokens used.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - description: - 'The number of reasoning tokens used.', - }, - ], - }, - ], - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used.', - }, - { - name: 'raw', - type: 'object | undefined', - isOptional: true, - description: - "Raw usage information from the provider. This is the provider's original usage information and may include additional fields.", - }, - ], - }, - ], - }, - { - name: 'text', - type: 'string', - description: 'The full text that has been generated.', - }, - { - name: 'reasoningText', - type: 'string | undefined', - description: - 'The reasoning text of the model (only available for some models).', - }, - { - name: 'sources', - type: 'Array', - description: - 'Sources that have been used as input to generate the response. For multi-step generation, the sources are accumulated from all steps.', - properties: [ - { - type: 'Source', - parameters: [ - { - name: 'sourceType', - type: "'url'", - description: - 'A URL source. This is return by web search RAG models.', - }, - { - name: 'id', - type: 'string', - description: 'The ID of the source.', - }, - { - name: 'url', - type: 'string', - description: 'The URL of the source.', - }, - { - name: 'title', - type: 'string', - isOptional: true, - description: 'The title of the source.', - }, - { - name: 'providerMetadata', - type: 'SharedV2ProviderMetadata', - isOptional: true, - description: - 'Additional provider metadata for the source.', - }, - ], - }, - ], - }, - { - name: 'files', - type: 'Array', - description: 'All files that were generated in this step.', - properties: [ - { - type: 'GeneratedFile', - parameters: [ - { - name: 'base64', - type: 'string', - description: 'File as a base64 encoded string.', - }, - { - name: 'uint8Array', - type: 'Uint8Array', - description: 'File as a Uint8Array.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - ], - }, - ], - }, - { - name: 'toolCalls', - type: 'ToolCall[]', - description: 'The tool calls that have been executed.', - }, - { - name: 'toolResults', - type: 'ToolResult[]', - description: 'The tool results that have been generated.', - }, - { - name: 'warnings', - type: 'Warning[] | undefined', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'response', - type: 'Response', - isOptional: true, - description: 'Response metadata.', - properties: [ - { - type: 'Response', - parameters: [ - { - name: 'id', - type: 'string', - description: - 'The response identifier. The AI SDK uses the ID from the provider response when available, and generates an ID otherwise.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The model that was used to generate the response. The AI SDK uses the response model from the provider response when available, and the model from the function call otherwise.', - }, - { - name: 'timestamp', - type: 'Date', - description: - 'The timestamp of the response. The AI SDK uses the response timestamp from the provider response when available, and creates a timestamp otherwise.', - }, - { - name: 'headers', - isOptional: true, - type: 'Record', - description: 'Optional response headers.', - }, - ], - }, - ], - }, - { - name: 'isContinued', - type: 'boolean', - description: - 'True when there will be a continuation step with a continuation text.', - }, - { - name: 'providerMetadata', - type: 'Record | undefined', - isOptional: true, - description: - 'Optional metadata from the provider. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - ], - }, - ], - }, - { - name: 'onFinish', - type: '(result: OnFinishResult) => Promise | void', - isOptional: true, - description: - 'Callback that is called when the LLM response and all request tool executions (for tools that have an `execute` function) are finished.', - properties: [ - { - type: 'OnFinishResult', - parameters: [ - { - name: 'finishReason', - type: '"stop" | "length" | "content-filter" | "tool-calls" | "error" | "other"', - description: - 'The unified finish reason why the generation finished.', - }, - { - name: 'rawFinishReason', - type: 'string | undefined', - description: - 'The raw reason why the generation finished (from the provider).', - }, - { - name: 'usage', - type: 'LanguageModelUsage', - description: 'The token usage of last step.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: - 'The total number of input (prompt) tokens used.', - }, - { - name: 'inputTokenDetails', - type: 'LanguageModelInputTokenDetails', - description: - 'Detailed information about the input (prompt) tokens. See also: cached tokens and non-cached tokens.', - properties: [ - { - type: 'LanguageModelInputTokenDetails', - parameters: [ - { - name: 'noCacheTokens', - type: 'number | undefined', - description: - 'The number of non-cached input (prompt) tokens used.', - }, - { - name: 'cacheReadTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens read.', - }, - { - name: 'cacheWriteTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens written.', - }, - ], - }, - ], - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: - 'The number of total output (completion) tokens used.', - }, - { - name: 'outputTokenDetails', - type: 'LanguageModelOutputTokenDetails', - description: - 'Detailed information about the output (completion) tokens.', - properties: [ - { - type: 'LanguageModelOutputTokenDetails', - parameters: [ - { - name: 'textTokens', - type: 'number | undefined', - description: 'The number of text tokens used.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - description: - 'The number of reasoning tokens used.', - }, - ], - }, - ], - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used.', - }, - { - name: 'raw', - type: 'object | undefined', - isOptional: true, - description: - "Raw usage information from the provider. This is the provider's original usage information and may include additional fields.", - }, - ], - }, - ], - }, - { - name: 'totalUsage', - type: 'LanguageModelUsage', - description: 'The total token usage from all steps.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: 'The number of input (prompt) tokens used.', - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: - 'The number of output (completion) tokens used.', - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: - 'The total number of tokens as reported by the provider. This number might be different from the sum of inputTokens and outputTokens and e.g. include reasoning tokens or other overhead.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - isOptional: true, - description: 'The number of reasoning tokens used.', - }, - { - name: 'cachedInputTokens', - type: 'number | undefined', - isOptional: true, - description: 'The number of cached input tokens.', - }, - ], - }, - ], - }, - { - name: 'providerMetadata', - type: 'Record | undefined', - description: - 'Optional metadata from the provider. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - { - name: 'text', - type: 'string', - description: 'The full text that has been generated.', - }, - { - name: 'reasoning', - type: 'string | undefined', - description: - 'The reasoning text of the model (only available for some models).', - }, - { - name: 'reasoning', - type: 'Array', - description: - 'The reasoning details of the model (only available for some models).', - properties: [ - { - type: 'ReasoningDetail', - parameters: [ - { - name: 'type', - type: "'text'", - description: 'The type of the reasoning detail.', - }, - { - name: 'text', - type: 'string', - description: 'The text content (only for type "text").', - }, - { - name: 'signature', - type: 'string', - isOptional: true, - description: 'Optional signature (only for type "text").', - }, - ], - }, - { - type: 'ReasoningDetail', - parameters: [ - { - name: 'type', - type: "'redacted'", - description: 'The type of the reasoning detail.', - }, - { - name: 'data', - type: 'string', - description: - 'The redacted data content (only for type "redacted").', - }, - ], - }, - ], - }, - { - name: 'sources', - type: 'Array', - description: - 'Sources that have been used as input to generate the response. For multi-step generation, the sources are accumulated from all steps.', - properties: [ - { - type: 'Source', - parameters: [ - { - name: 'sourceType', - type: "'url'", - description: - 'A URL source. This is return by web search RAG models.', - }, - { - name: 'id', - type: 'string', - description: 'The ID of the source.', - }, - { - name: 'url', - type: 'string', - description: 'The URL of the source.', - }, - { - name: 'title', - type: 'string', - isOptional: true, - description: 'The title of the source.', - }, - { - name: 'providerMetadata', - type: 'SharedV2ProviderMetadata', - isOptional: true, - description: - 'Additional provider metadata for the source.', - }, - ], - }, - ], - }, - { - name: 'files', - type: 'Array', - description: 'Files that were generated in the final step.', - properties: [ - { - type: 'GeneratedFile', - parameters: [ - { - name: 'base64', - type: 'string', - description: 'File as a base64 encoded string.', - }, - { - name: 'uint8Array', - type: 'Uint8Array', - description: 'File as a Uint8Array.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - ], - }, - ], - }, - { - name: 'toolCalls', - type: 'ToolCall[]', - description: 'The tool calls that have been executed.', - }, - { - name: 'toolResults', - type: 'ToolResult[]', - description: 'The tool results that have been generated.', - }, - { - name: 'warnings', - type: 'Warning[] | undefined', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'response', - type: 'Response', - isOptional: true, - description: 'Response metadata.', - properties: [ - { - type: 'Response', - parameters: [ - { - name: 'id', - type: 'string', - description: - 'The response identifier. The AI SDK uses the ID from the provider response when available, and generates an ID otherwise.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The model that was used to generate the response. The AI SDK uses the response model from the provider response when available, and the model from the function call otherwise.', - }, - { - name: 'timestamp', - type: 'Date', - description: - 'The timestamp of the response. The AI SDK uses the response timestamp from the provider response when available, and creates a timestamp otherwise.', - }, - { - name: 'headers', - isOptional: true, - type: 'Record', - description: 'Optional response headers.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The response messages that were generated during the call. It consists of an assistant message, potentially containing tool calls. When there are tool results, there is an additional tool message with the tool results that are available. If there are tools that do not have execute functions, they are not included in the tool results and need to be added separately.', - }, - ], - }, - ], - }, - { - name: 'steps', - type: 'Array', - description: - 'Response information for every step. You can use this to get information about intermediate steps, such as the tool calls or the response headers.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: 'The experimental context.', - }, - ], - }, - ], - }, - { - name: 'onAbort', - type: '(event: OnAbortResult) => Promise | void', - isOptional: true, - description: - 'Callback that is called when a stream is aborted via AbortSignal. You can use it to perform cleanup operations.', - properties: [ - { - type: 'OnAbortResult', - parameters: [ - { - name: 'steps', - type: 'Array', - description: 'Details for all previously finished steps.', - }, - ], - }, - ], - }, - { - name: 'experimental_onStart', - type: '(event: OnStartEvent) => PromiseLike | void', - isOptional: true, - description: - 'Callback that is called when the streamText operation begins, before any LLM calls are made. Errors thrown in this callback are silently caught and do not break the generation flow. Experimental (can break in patch releases).', - properties: [ - { - type: 'OnStartEvent', - parameters: [ - { - name: 'model', - type: '{ provider: string; modelId: string }', - description: 'The model being used for the generation.', - }, - { - name: 'system', - type: 'string | SystemModelMessage | Array | undefined', - description: 'The system message(s) provided to the model.', - }, - { - name: 'prompt', - type: 'string | Array | undefined', - description: - 'The prompt string or array of messages if using the prompt option.', - }, - { - name: 'messages', - type: 'Array | undefined', - description: 'The messages array if using the messages option.', - }, - { - name: 'tools', - type: 'TOOLS | undefined', - description: 'The tools available for this generation.', - }, - { - name: 'toolChoice', - type: 'ToolChoice | undefined', - description: 'The tool choice strategy for this generation.', - }, - { - name: 'activeTools', - type: 'Array | undefined', - description: - 'Limits which tools are available for the model to call.', - }, - { - name: 'maxOutputTokens', - type: 'number | undefined', - description: 'Maximum number of tokens to generate.', - }, - { - name: 'temperature', - type: 'number | undefined', - description: 'Sampling temperature for generation.', - }, - { - name: 'topP', - type: 'number | undefined', - description: 'Top-p (nucleus) sampling parameter.', - }, - { - name: 'topK', - type: 'number | undefined', - description: 'Top-k sampling parameter.', - }, - { - name: 'presencePenalty', - type: 'number | undefined', - description: 'Presence penalty for generation.', - }, - { - name: 'frequencyPenalty', - type: 'number | undefined', - description: 'Frequency penalty for generation.', - }, - { - name: 'stopSequences', - type: 'string[] | undefined', - description: 'Sequences that will stop generation.', - }, - { - name: 'seed', - type: 'number | undefined', - description: 'Random seed for reproducible generation.', - }, - { - name: 'maxRetries', - type: 'number', - description: 'Maximum number of retries for failed requests.', - }, - { - name: 'timeout', - type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number } | undefined', - description: - 'Timeout configuration for the generation. Can be a number (milliseconds) or an object with totalMs, stepMs, chunkMs.', - }, - { - name: 'headers', - type: 'Record | undefined', - description: 'Additional HTTP headers sent with the request.', - }, - { - name: 'providerOptions', - type: 'ProviderOptions | undefined', - description: 'Additional provider-specific options.', - }, - { - name: 'stopWhen', - type: 'StopCondition | Array> | undefined', - description: - 'Condition(s) for stopping the generation. When the condition is an array, any of the conditions can be met to stop.', - }, - { - name: 'output', - type: 'OUTPUT | undefined', - description: - 'The output specification for structured outputs, if configured.', - }, - { - name: 'abortSignal', - type: 'AbortSignal | undefined', - description: 'Abort signal for cancelling the operation.', - }, - { - name: 'include', - type: '{ requestBody?: boolean } | undefined', - description: - 'Settings for controlling what data is included in step results.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata passed to the generation.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object that flows through the entire generation lifecycle.', - }, - ], - }, - ], - }, - { - name: 'experimental_onStepStart', - type: '(event: OnStepStartEvent) => PromiseLike | void', - isOptional: true, - description: - 'Callback that is called when a step (LLM call) begins, before the provider is called. Errors thrown in this callback are silently caught and do not break the generation flow. Experimental (can break in patch releases).', - properties: [ - { - type: 'OnStepStartEvent', - parameters: [ - { - name: 'stepNumber', - type: 'number', - description: 'Zero-based index of the current step.', - }, - { - name: 'model', - type: '{ provider: string; modelId: string }', - description: 'The model being used for this step.', - }, - { - name: 'system', - type: 'string | SystemModelMessage | Array | undefined', - description: 'The system message for this step.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The messages that will be sent to the model for this step. Uses the user-facing ModelMessage format. May be overridden by prepareStep.', - }, - { - name: 'tools', - type: 'TOOLS | undefined', - description: 'The tools available for this generation.', - }, - { - name: 'toolChoice', - type: 'LanguageModelV3ToolChoice | undefined', - description: 'The tool choice configuration for this step.', - }, - { - name: 'activeTools', - type: 'Array | undefined', - description: 'Limits which tools are available for this step.', - }, - { - name: 'steps', - type: 'ReadonlyArray>', - description: - 'Array of results from previous steps (empty for the first step).', - }, - { - name: 'providerOptions', - type: 'ProviderOptions | undefined', - description: - 'Additional provider-specific options for this step.', - }, - { - name: 'timeout', - type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number } | undefined', - description: 'Timeout configuration for the generation.', - }, - { - name: 'headers', - type: 'Record | undefined', - description: 'Additional HTTP headers sent with the request.', - }, - { - name: 'stopWhen', - type: 'StopCondition | Array> | undefined', - description: 'Condition(s) for stopping the generation.', - }, - { - name: 'output', - type: 'OUTPUT | undefined', - description: - 'The output specification for structured outputs, if configured.', - }, - { - name: 'abortSignal', - type: 'AbortSignal | undefined', - description: 'Abort signal for cancelling the operation.', - }, - { - name: 'include', - type: '{ requestBody?: boolean } | undefined', - description: - 'Settings for controlling what data is included in step results.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object. May be updated from prepareStep between steps.', - }, - ], - }, - ], - }, - { - name: 'experimental_onToolCallStart', - type: '(event: OnToolCallStartEvent) => PromiseLike | void', - isOptional: true, - description: - "Callback that is called right before a tool's execute function runs. Errors thrown in this callback are silently caught and do not break the generation flow. Experimental (can break in patch releases).", - properties: [ - { - type: 'OnToolCallStartEvent', - parameters: [ - { - name: 'stepNumber', - type: 'number | undefined', - description: - 'The zero-based index of the current step where this tool call occurs. May be undefined in streaming contexts.', - }, - { - name: 'model', - type: '{ provider: string; modelId: string } | undefined', - description: - 'Information about the model being used. May be undefined in streaming contexts.', - }, - { - name: 'toolCall', - type: 'TypedToolCall', - description: - 'The full tool call object containing toolName, toolCallId, input, and metadata.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The conversation messages available at tool execution time.', - }, - { - name: 'abortSignal', - type: 'AbortSignal | undefined', - description: 'Signal for cancelling the operation.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object flowing through the generation.', - }, - ], - }, - ], - }, - { - name: 'experimental_onToolCallFinish', - type: '(event: OnToolCallFinishEvent) => PromiseLike | void', - isOptional: true, - description: - "Callback that is called right after a tool's execute function completes (or errors). Uses a discriminated union on the `success` field: when `success: true`, `output` contains the tool result; when `success: false`, `error` contains the error. Errors thrown in this callback are silently caught and do not break the generation flow. Experimental (can break in patch releases).", - properties: [ - { - type: 'OnToolCallFinishEvent', - parameters: [ - { - name: 'stepNumber', - type: 'number | undefined', - description: - 'The zero-based index of the current step where this tool call occurred. May be undefined in streaming contexts.', - }, - { - name: 'model', - type: '{ provider: string; modelId: string } | undefined', - description: - 'Information about the model being used. May be undefined in streaming contexts.', - }, - { - name: 'toolCall', - type: 'TypedToolCall', - description: - 'The full tool call object containing toolName, toolCallId, input, and metadata.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The conversation messages available at tool execution time.', - }, - { - name: 'abortSignal', - type: 'AbortSignal | undefined', - description: 'Signal for cancelling the operation.', - }, - { - name: 'durationMs', - type: 'number', - description: - 'The wall-clock duration of the tool execution in milliseconds.', - }, - { - name: 'functionId', - type: 'string | undefined', - description: - 'Identifier from telemetry settings for grouping related operations.', - }, - { - name: 'metadata', - type: 'Record | undefined', - description: 'Additional metadata from telemetry settings.', - }, - { - name: 'experimental_context', - type: 'unknown', - description: - 'User-defined context object flowing through the generation.', - }, - { - name: 'success', - type: 'boolean', - description: - 'Discriminator indicating whether the tool call succeeded. When true, output is available. When false, error is available.', - }, - { - name: 'output', - type: 'unknown', - description: - "The tool's return value (only present when `success: true`).", - }, - { - name: 'error', - type: 'unknown', - description: - 'The error that occurred during tool execution (only present when `success: false`).', - }, - ], - }, - ], - }, - ]} -/> - -### Returns - ->>', - description: 'The content that was generated in the last step. Automatically consumes the stream.', - }, - { - name: 'finishReason', - type: "PromiseLike<'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'>", - description: - 'The reason why the generation finished. Automatically consumes the stream.', - }, - { - name: 'rawFinishReason', - type: 'PromiseLike', - description: - 'The raw reason why the generation finished (from the provider).', - }, - { - name: 'usage', - type: 'Promise', - description: - 'The token usage of the last step. Automatically consumes the stream.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: 'The number of input (prompt) tokens used.', - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: 'The number of output (completion) tokens used.', - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: - 'The total number of tokens as reported by the provider. This number might be different from the sum of inputTokens and outputTokens and e.g. include reasoning tokens or other overhead.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - isOptional: true, - description: 'The number of reasoning tokens used.', - }, - { - name: 'cachedInputTokens', - type: 'number | undefined', - isOptional: true, - description: 'The number of cached input tokens.', - }, - ], - }, - ], - }, - { - name: 'totalUsage', - type: 'Promise', - description: 'The total token usage of the generated response. When there are multiple steps, the usage is the sum of all step usages. Automatically consumes the stream.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: 'The total number of input (prompt) tokens used.', - }, - { - name: 'inputTokenDetails', - type: 'LanguageModelInputTokenDetails', - description: - 'Detailed information about the input (prompt) tokens. See also: cached tokens and non-cached tokens.', - properties: [ - { - type: 'LanguageModelInputTokenDetails', - parameters: [ - { - name: 'noCacheTokens', - type: 'number | undefined', - description: - 'The number of non-cached input (prompt) tokens used.', - }, - { - name: 'cacheReadTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens read.', - }, - { - name: 'cacheWriteTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens written.', - }, - ], - }, - ], - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: 'The number of total output (completion) tokens used.', - }, - { - name: 'outputTokenDetails', - type: 'LanguageModelOutputTokenDetails', - description: - 'Detailed information about the output (completion) tokens.', - properties: [ - { - type: 'LanguageModelOutputTokenDetails', - parameters: [ - { - name: 'textTokens', - type: 'number | undefined', - description: 'The number of text tokens used.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - description: 'The number of reasoning tokens used.', - }, - ], - }, - ], - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used.', - }, - { - name: 'raw', - type: 'object | undefined', - isOptional: true, - description: 'Raw usage information from the provider. This is the provider\'s original usage information and may include additional fields.', - }, - ], - }, - ], - }, - { - name: 'providerMetadata', - type: 'Promise', - description: - 'Additional provider-specific metadata from the last step. Metadata is passed through from the provider to the AI SDK and enables provider-specific results that can be fully encapsulated in the provider.', - }, - { - name: 'text', - type: 'Promise', - description: - 'The full text that has been generated. Automatically consumes the stream.', - }, - { - name: 'reasoning', - type: 'Promise>', - description: - 'The full reasoning that the model has generated in the last step. Automatically consumes the stream.', - properties: [ - { - type: 'ReasoningOutput', - parameters: [ - { - name: 'type', - type: "'reasoning'", - description: 'The type of the message part.', - }, - { - name: 'text', - type: 'string', - description: 'The reasoning text.', - }, - { - name: 'providerMetadata', - type: 'SharedV2ProviderMetadata', - isOptional: true, - description: 'Additional provider metadata for the source.', - }, - ], - }, - ], - }, - { - name: 'reasoningText', - type: 'Promise', - description: - 'The reasoning text that the model has generated in the last step. Can be undefined if the model has only generated text. Automatically consumes the stream.', - }, - { - name: 'sources', - type: 'Promise>', - description: - 'Sources that have been used as input to generate the response. For multi-step generation, the sources are accumulated from all steps. Automatically consumes the stream.', - properties: [ - { - type: 'Source', - parameters: [ - { - name: 'sourceType', - type: "'url'", - description: - 'A URL source. This is return by web search RAG models.', - }, - { - name: 'id', - type: 'string', - description: 'The ID of the source.', - }, - { - name: 'url', - type: 'string', - description: 'The URL of the source.', - }, - { - name: 'title', - type: 'string', - isOptional: true, - description: 'The title of the source.', - }, - { - name: 'providerMetadata', - type: 'SharedV2ProviderMetadata', - isOptional: true, - description: 'Additional provider metadata for the source.', - }, - ], - }, - ], - }, - { - name: 'files', - type: 'Promise>', - description: - 'Files that were generated in the final step. Automatically consumes the stream.', - properties: [ - { - type: 'GeneratedFile', - parameters: [ - { - name: 'base64', - type: 'string', - description: 'File as a base64 encoded string.', - }, - { - name: 'uint8Array', - type: 'Uint8Array', - description: 'File as a Uint8Array.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - ], - }, - ], - }, - { - name: 'toolCalls', - type: 'Promise[]>', - description: - 'The tool calls that have been executed. Automatically consumes the stream.', - }, - { - name: 'toolResults', - type: 'Promise[]>', - description: - 'The tool results that have been generated. Resolved when the all tool executions are finished.', - }, - { - name: 'staticToolCalls', - type: 'PromiseLike>>', - description: 'The static tool calls that have been executed in the last step.', - }, - { - name: 'dynamicToolCalls', - type: 'PromiseLike>', - description: 'The dynamic tool calls that have been executed in the last step.', - }, - { - name: 'staticToolResults', - type: 'PromiseLike>>', - description: 'The static tool results that have been generated in the last step.', - }, - { - name: 'dynamicToolResults', - type: 'PromiseLike>', - description: 'The dynamic tool results that have been generated in the last step.', - }, - { - name: 'request', - type: 'Promise', - description: 'Additional request information from the last step.', - properties: [ - { - type: 'LanguageModelRequestMetadata', - parameters: [ - { - name: 'body', - type: 'string', - description: - 'Raw request HTTP body that was sent to the provider API as a string (JSON should be stringified).', - }, - ], - }, - ], - }, - { - name: 'response', - type: 'Promise; }>', - description: 'Additional response information from the last step.', - properties: [ - { - type: 'LanguageModelResponseMetadata', - parameters: [ - { - name: 'id', - type: 'string', - description: - 'The response identifier. The AI SDK uses the ID from the provider response when available, and generates an ID otherwise.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The model that was used to generate the response. The AI SDK uses the response model from the provider response when available, and the model from the function call otherwise.', - }, - { - name: 'timestamp', - type: 'Date', - description: - 'The timestamp of the response. The AI SDK uses the response timestamp from the provider response when available, and creates a timestamp otherwise.', - }, - { - name: 'headers', - isOptional: true, - type: 'Record', - description: 'Optional response headers.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The response messages that were generated during the call. It consists of an assistant message, potentially containing tool calls. When there are tool results, there is an additional tool message with the tool results that are available. If there are tools that do not have execute functions, they are not included in the tool results and need to be added separately.', - }, - ], - }, - ], - }, - { - name: 'warnings', - type: 'Promise', - description: - 'Warnings from the model provider (e.g. unsupported settings) for the first step.', - }, - { - name: 'steps', - type: 'Promise>', - description: - 'Response information for every step. You can use this to get information about intermediate steps, such as the tool calls or the response headers.', - properties: [ - { - type: 'StepResult', - parameters: [ - { - name: 'stepType', - type: '"initial" | "continue" | "tool-result"', - description: - 'The type of step. The first step is always an "initial" step, and subsequent steps are either "continue" steps or "tool-result" steps.', - }, - { - name: 'text', - type: 'string', - description: 'The generated text by the model.', - }, - { - name: 'reasoning', - type: 'string | undefined', - description: - 'The reasoning text of the model (only available for some models).', - }, - { - name: 'sources', - type: 'Array', - description: 'Sources that have been used as input.', - properties: [ - { - type: 'Source', - parameters: [ - { - name: 'sourceType', - type: "'url'", - description: - 'A URL source. This is return by web search RAG models.', - }, - { - name: 'id', - type: 'string', - description: 'The ID of the source.', - }, - { - name: 'url', - type: 'string', - description: 'The URL of the source.', - }, - { - name: 'title', - type: 'string', - isOptional: true, - description: 'The title of the source.', - }, - { - name: 'providerMetadata', - type: 'SharedV2ProviderMetadata', - isOptional: true, - description: - 'Additional provider metadata for the source.', - }, - ], - }, - ], - }, - { - name: 'files', - type: 'Array', - description: 'Files that were generated in this step.', - properties: [ - { - type: 'GeneratedFile', - parameters: [ - { - name: 'base64', - type: 'string', - description: 'File as a base64 encoded string.', - }, - { - name: 'uint8Array', - type: 'Uint8Array', - description: 'File as a Uint8Array.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - ], - }, - ], - }, - { - name: 'toolCalls', - type: 'array', - description: 'A list of tool calls made by the model.', - }, - { - name: 'toolResults', - type: 'array', - description: - 'A list of tool results returned as responses to earlier tool calls.', - }, - { - name: 'finishReason', - type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'", - description: 'The reason the model finished generating the text.', - }, - { - name: 'rawFinishReason', - type: 'string | undefined', - description: - 'The raw reason why the generation finished (from the provider).', - }, - { - name: 'usage', - type: 'LanguageModelUsage', - description: 'The token usage of the generated text.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: 'The total number of input (prompt) tokens used.', - }, - { - name: 'inputTokenDetails', - type: 'LanguageModelInputTokenDetails', - description: - 'Detailed information about the input (prompt) tokens. See also: cached tokens and non-cached tokens.', - properties: [ - { - type: 'LanguageModelInputTokenDetails', - parameters: [ - { - name: 'noCacheTokens', - type: 'number | undefined', - description: - 'The number of non-cached input (prompt) tokens used.', - }, - { - name: 'cacheReadTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens read.', - }, - { - name: 'cacheWriteTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens written.', - }, - ], - }, - ], - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: 'The number of total output (completion) tokens used.', - }, - { - name: 'outputTokenDetails', - type: 'LanguageModelOutputTokenDetails', - description: - 'Detailed information about the output (completion) tokens.', - properties: [ - { - type: 'LanguageModelOutputTokenDetails', - parameters: [ - { - name: 'textTokens', - type: 'number | undefined', - description: 'The number of text tokens used.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - description: 'The number of reasoning tokens used.', - }, - ], - }, - ], - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used.', - }, - { - name: 'raw', - type: 'object | undefined', - isOptional: true, - description: 'Raw usage information from the provider. This is the provider\'s original usage information and may include additional fields.', - }, - ], - }, - ], - }, - { - name: 'request', - type: 'RequestMetadata', - isOptional: true, - description: 'Request metadata.', - properties: [ - { - type: 'RequestMetadata', - parameters: [ - { - name: 'body', - type: 'string', - description: - 'Raw request HTTP body that was sent to the provider API as a string (JSON should be stringified).', - }, - ], - }, - ], - }, - { - name: 'response', - type: 'ResponseMetadata', - isOptional: true, - description: 'Response metadata.', - properties: [ - { - type: 'ResponseMetadata', - parameters: [ - { - name: 'id', - type: 'string', - description: - 'The response identifier. The AI SDK uses the ID from the provider response when available, and generates an ID otherwise.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The model that was used to generate the response. The AI SDK uses the response model from the provider response when available, and the model from the function call otherwise.', - }, - { - name: 'timestamp', - type: 'Date', - description: - 'The timestamp of the response. The AI SDK uses the response timestamp from the provider response when available, and creates a timestamp otherwise.', - }, - { - name: 'headers', - isOptional: true, - type: 'Record', - description: 'Optional response headers.', - }, - { - name: 'messages', - type: 'Array', - description: - 'The response messages that were generated during the call. It consists of an assistant message, potentially containing tool calls. When there are tool results, there is an additional tool message with the tool results that are available. If there are tools that do not have execute functions, they are not included in the tool results and need to be added separately.', - }, - ], - }, - ], - }, - { - name: 'warnings', - type: 'Warning[] | undefined', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'isContinued', - type: 'boolean', - description: - 'True when there will be a continuation step with a continuation text.', - }, - { - name: 'providerMetadata', - type: 'Record | undefined', - isOptional: true, - description: - 'Optional metadata from the provider. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - ], - }, - ], - }, - { - name: 'textStream', - type: 'AsyncIterableStream', - description: - 'A text stream that returns only the generated text deltas. You can use it as either an AsyncIterable or a ReadableStream. When an error occurs, the stream will throw the error.', - }, - { - name: 'fullStream', - type: 'AsyncIterable> & ReadableStream>', - description: - 'A stream with all events, including text deltas, tool calls, tool results, and errors. You can use it as either an AsyncIterable or a ReadableStream. Only errors that stop the stream, such as network errors, are thrown.', - properties: [ - { - type: 'TextStreamPart', - description: 'Text content part from ContentPart', - parameters: [ - { - name: 'type', - type: "'text'", - description: 'The type to identify the object as text.', - }, - { - name: 'text', - type: 'string', - description: 'The text content.', - }, - ], - }, - { - type: 'TextStreamPart', - description: 'Reasoning content part from ContentPart', - parameters: [ - { - name: 'type', - type: "'reasoning'", - description: 'The type to identify the object as reasoning.', - }, - { - name: 'text', - type: 'string', - description: 'The reasoning text.', - }, - { - name: 'providerMetadata', - type: 'ProviderMetadata', - isOptional: true, - description: 'Optional provider metadata for the reasoning.', - }, - ], - }, - - { - type: 'TextStreamPart', - description: 'Source content part from ContentPart', - parameters: [ - { - name: 'type', - type: "'source'", - description: 'The type to identify the object as source.', - }, - { - name: 'sourceType', - type: "'url'", - description: 'A URL source. This is returned by web search RAG models.', - }, - { - name: 'id', - type: 'string', - description: 'The ID of the source.', - }, - { - name: 'url', - type: 'string', - description: 'The URL of the source.', - }, - { - name: 'title', - type: 'string', - isOptional: true, - description: 'The title of the source.', - }, - { - name: 'providerMetadata', - type: 'ProviderMetadata', - isOptional: true, - description: 'Additional provider metadata for the source.', - }, - ], - }, - { - type: 'TextStreamPart', - description: 'File content part from ContentPart', - parameters: [ - { - name: 'type', - type: "'file'", - description: 'The type to identify the object as file.', - }, - { - name: 'file', - type: 'GeneratedFile', - description: 'The file.', - properties: [ - { - type: 'GeneratedFile', - parameters: [ - { - name: 'base64', - type: 'string', - description: 'File as a base64 encoded string.', - }, - { - name: 'uint8Array', - type: 'Uint8Array', - description: 'File as a Uint8Array.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - ], - }, - ], - }, - ], - }, - { - type: 'TextStreamPart', - description: 'Tool call from ContentPart', - parameters: [ - { - name: 'type', - type: "'tool-call'", - description: 'The type to identify the object as tool call.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool, which typically would be the name of the function.', - }, - { - name: 'input', - type: 'object based on tool parameters', - description: - 'Parameters generated by the model to be used by the tool. The type is inferred from the tool definition.', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'tool-call-streaming-start'", - description: - 'Indicates the start of a tool call streaming. Only available when streaming tool calls.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool, which typically would be the name of the function.', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'tool-call-delta'", - description: - 'The type to identify the object as tool call delta. Only available when streaming tool calls.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool, which typically would be the name of the function.', - }, - { - name: 'argsTextDelta', - type: 'string', - description: 'The text delta of the tool call arguments.', - }, - ], - }, - { - type: 'TextStreamPart', - description: 'Tool result from ContentPart', - parameters: [ - { - name: 'type', - type: "'tool-result'", - description: 'The type to identify the object as tool result.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool, which typically would be the name of the function.', - }, - { - name: 'input', - type: 'object based on tool parameters', - description: - 'Parameters that were passed to the tool. The type is inferred from the tool definition.', - }, - { - name: 'output', - type: 'tool execution return type', - description: - 'The result returned by the tool after execution has completed. The type is inferred from the tool execute function return type.', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'start-step'", - description: 'Indicates the start of a new step in the stream.', - }, - { - name: 'request', - type: 'LanguageModelRequestMetadata', - description: - 'Information about the request that was sent to the language model provider.', - properties: [ - { - type: 'LanguageModelRequestMetadata', - parameters: [ - { - name: 'body', - type: 'string', - description: - 'Raw request HTTP body that was sent to the provider API as a string.', - }, - ], - }, - ], - }, - { - name: 'warnings', - type: 'Warning[]', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'finish-step'", - description: - 'Indicates the end of the current step in the stream.', - }, - { - name: 'response', - type: 'LanguageModelResponseMetadata', - description: - 'Response metadata from the language model provider.', - properties: [ - { - type: 'LanguageModelResponseMetadata', - parameters: [ - { - name: 'id', - type: 'string', - description: - 'The response identifier. The AI SDK uses the ID from the provider response when available, and generates an ID otherwise.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The model that was used to generate the response. The AI SDK uses the response model from the provider response when available, and the model from the function call otherwise.', - }, - { - name: 'timestamp', - type: 'Date', - description: - 'The timestamp of the response. The AI SDK uses the response timestamp from the provider response when available, and creates a timestamp otherwise.', - }, - { - name: 'headers', - type: 'Record', - description: 'The response headers.', - }, - ], - }, - ], - }, - { - name: 'usage', - type: 'LanguageModelUsage', - description: 'The token usage of the generated text.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: 'The total number of input (prompt) tokens used.', - }, - { - name: 'inputTokenDetails', - type: 'LanguageModelInputTokenDetails', - description: - 'Detailed information about the input (prompt) tokens. See also: cached tokens and non-cached tokens.', - properties: [ - { - type: 'LanguageModelInputTokenDetails', - parameters: [ - { - name: 'noCacheTokens', - type: 'number | undefined', - description: - 'The number of non-cached input (prompt) tokens used.', - }, - { - name: 'cacheReadTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens read.', - }, - { - name: 'cacheWriteTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens written.', - }, - ], - }, - ], - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: 'The number of total output (completion) tokens used.', - }, - { - name: 'outputTokenDetails', - type: 'LanguageModelOutputTokenDetails', - description: - 'Detailed information about the output (completion) tokens.', - properties: [ - { - type: 'LanguageModelOutputTokenDetails', - parameters: [ - { - name: 'textTokens', - type: 'number | undefined', - description: 'The number of text tokens used.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - description: 'The number of reasoning tokens used.', - }, - ], - }, - ], - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used.', - }, - { - name: 'raw', - type: 'object | undefined', - isOptional: true, - description: 'Raw usage information from the provider. This is the provider\'s original usage information and may include additional fields.', - }, - ], - }, - ], - }, - { - name: 'finishReason', - type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'", - description: 'The reason the model finished generating the text.', - }, - { - name: 'rawFinishReason', - type: 'string | undefined', - description: - 'The raw reason why the generation finished (from the provider).', - }, - { - name: 'providerMetadata', - type: 'ProviderMetadata | undefined', - isOptional: true, - description: - 'Optional metadata from the provider. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'start'", - description: 'Indicates the start of the stream.', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'finish'", - description: 'The type to identify the object as finish.', - }, - { - name: 'finishReason', - type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'", - description: 'The reason the model finished generating the text.', - }, - { - name: 'rawFinishReason', - type: 'string | undefined', - description: - 'The raw reason why the generation finished (from the provider).', - }, - { - name: 'totalUsage', - type: 'LanguageModelUsage', - description: 'The total token usage of the generated text.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: 'The total number of input (prompt) tokens used.', - }, - { - name: 'inputTokenDetails', - type: 'LanguageModelInputTokenDetails', - description: - 'Detailed information about the input (prompt) tokens. See also: cached tokens and non-cached tokens.', - properties: [ - { - type: 'LanguageModelInputTokenDetails', - parameters: [ - { - name: 'noCacheTokens', - type: 'number | undefined', - description: - 'The number of non-cached input (prompt) tokens used.', - }, - { - name: 'cacheReadTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens read.', - }, - { - name: 'cacheWriteTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens written.', - }, - ], - }, - ], - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: 'The number of total output (completion) tokens used.', - }, - { - name: 'outputTokenDetails', - type: 'LanguageModelOutputTokenDetails', - description: - 'Detailed information about the output (completion) tokens.', - properties: [ - { - type: 'LanguageModelOutputTokenDetails', - parameters: [ - { - name: 'textTokens', - type: 'number | undefined', - description: 'The number of text tokens used.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - description: 'The number of reasoning tokens used.', - }, - ], - }, - ], - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used.', - }, - { - name: 'raw', - type: 'object | undefined', - isOptional: true, - description: 'Raw usage information from the provider. This is the provider\'s original usage information and may include additional fields.', - }, - ], - }, - ], - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'reasoning-part-finish'", - description: 'Indicates the end of a reasoning part.', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'error'", - description: 'The type to identify the object as error.', - }, - { - name: 'error', - type: 'unknown', - description: - 'Describes the error that may have occurred during execution.', - }, - ], - }, - { - type: 'TextStreamPart', - parameters: [ - { - name: 'type', - type: "'abort'", - description: 'The type to identify the object as abort.', - }, - { - name: 'reason', - type: 'unknown', - isOptional: true, - description: - 'Optional abort reason (from AbortSignal.reason) when the stream is aborted.', - }, - ], - }, - ], - }, - { - name: 'partialOutputStream', - type: 'AsyncIterableStream', - description: - 'A stream of partial parsed outputs. It uses the `output` specification. AsyncIterableStream is defined as AsyncIterable & ReadableStream.', - }, - { - name: 'elementStream', - type: 'AsyncIterableStream', - description: - 'A stream of individual array elements as they complete. Only available when using `output: Output.array()`. Each element is complete and validated against the element schema. AsyncIterableStream is defined as AsyncIterable & ReadableStream.', - }, - { - name: 'output', - type: 'Promise', - description: - 'The complete parsed output. It uses the `output` specification.', - }, - { - name: 'consumeStream', - type: '(options?: ConsumeStreamOptions) => Promise', - description: - 'Consumes the stream without processing the parts. This is useful to force the stream to finish. If an error occurs, it is passed to the optional `onError` callback.', - properties: [ - { - type: 'ConsumeStreamOptions', - parameters: [ - { - name: 'onError', - type: '(error: unknown) => void', - isOptional: true, - description: 'The error callback.', - }, - ], - }, - ], - }, - { - name: 'toUIMessageStream', - type: '(options?: UIMessageStreamOptions) => AsyncIterableStream', - description: - 'Converts the result to a UI message stream. Returns an AsyncIterableStream that can be used as both an AsyncIterable and a ReadableStream.', - properties: [ - { - type: 'UIMessageStreamOptions', - parameters: [ - { - name: 'originalMessages', - type: 'UIMessage[]', - isOptional: true, - description: 'The original messages.', - }, - { - name: 'onFinish', - type: '(options: { messages: UIMessage[]; isContinuation: boolean; responseMessage: UIMessage; isAborted: boolean; }) => void', - isOptional: true, - description: 'Callback function called when the stream finishes. Provides the updated list of UI messages, whether the response is a continuation, the response message, and whether the stream was aborted.', - }, - { - name: 'messageMetadata', - type: '(options: { part: TextStreamPart & { type: "start" | "finish" | "start-step" | "finish-step"; }; }) => unknown', - isOptional: true, - description: 'Extracts message metadata that will be sent to the client. Called on start and finish events.', - }, - { - name: 'sendReasoning', - type: 'boolean', - isOptional: true, - description: - 'Send reasoning parts to the client. Defaults to false.', - }, - { - name: 'sendSources', - type: 'boolean', - isOptional: true, - description: - 'Send source parts to the client. Defaults to false.', - }, - { - name: 'sendFinish', - type: 'boolean', - isOptional: true, - description: - 'Send the finish event to the client. Defaults to true.', - }, - { - name: 'sendStart', - type: 'boolean', - isOptional: true, - description: - 'Send the message start event to the client. Set to false if you are using additional streamText calls and the message start event has already been sent. Defaults to true.', - }, - { - name: 'onError', - type: '(error: unknown) => string', - isOptional: true, - description: - 'Process an error, e.g. to log it. Returns error message to include in the data stream. Defaults to () => "An error occurred."', - }, - { - name: 'consumeSseStream', - type: '(stream: ReadableStream) => Promise', - isOptional: true, - description: - 'Function to consume the SSE stream. Required for proper abort handling in UI message streams. Use the `consumeStream` function from the AI SDK.', - }, - ], - }, - ], - }, - { - name: 'pipeUIMessageStreamToResponse', - type: '(response: ServerResponse, options?: ResponseInit & UIMessageStreamOptions) => void', - description: - 'Writes UI message stream output to a Node.js response-like object.', - properties: [ - { - type: 'ResponseInit & UIMessageStreamOptions', - parameters: [ - { - name: 'status', - type: 'number', - isOptional: true, - description: 'The response status code.', - }, - { - name: 'statusText', - type: 'string', - isOptional: true, - description: 'The response status text.', - }, - { - name: 'headers', - type: 'HeadersInit', - isOptional: true, - description: 'The response headers.', - }, - ], - }, - ], - }, - { - name: 'pipeTextStreamToResponse', - type: '(response: ServerResponse, init?: ResponseInit) => void', - description: - 'Writes text delta output to a Node.js response-like object. It sets a `Content-Type` header to `text/plain; charset=utf-8` and writes each text delta as a separate chunk.', - properties: [ - { - type: 'ResponseInit', - parameters: [ - { - name: 'status', - type: 'number', - isOptional: true, - description: 'The response status code.', - }, - { - name: 'statusText', - type: 'string', - isOptional: true, - description: 'The response status text.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: 'The response headers.', - }, - ], - }, - ], - }, - { - name: 'toUIMessageStreamResponse', - type: '(options?: ResponseInit & UIMessageStreamOptions) => Response', - description: - 'Converts the result to a streamed response object with a UI message stream.', - properties: [ - { - type: 'ResponseInit & UIMessageStreamOptions', - parameters: [ - { - name: 'status', - type: 'number', - isOptional: true, - description: 'The response status code.', - }, - { - name: 'statusText', - type: 'string', - isOptional: true, - description: 'The response status text.', - }, - { - name: 'headers', - type: 'HeadersInit', - isOptional: true, - description: 'The response headers.', - }, - ], - }, - ], - }, - { - name: 'toTextStreamResponse', - type: '(init?: ResponseInit) => Response', - description: - 'Creates a simple text stream response. Each text delta is encoded as UTF-8 and sent as a separate chunk. Non-text-delta events are ignored.', - properties: [ - { - type: 'ResponseInit', - parameters: [ - { - name: 'status', - type: 'number', - isOptional: true, - description: 'The response status code.', - }, - { - name: 'statusText', - type: 'string', - isOptional: true, - description: 'The response status text.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: 'The response headers.', - }, - ], - }, - ], - }, - -]} -/> - -## Examples - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/05-embed.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/05-embed.mdx deleted file mode 100644 index dacd22021..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/05-embed.mdx +++ /dev/null @@ -1,197 +0,0 @@ ---- -title: embed -description: API Reference for embed. ---- - -# `embed()` - -Generate an embedding for a single value using an embedding model. - -This is ideal for use cases where you need to embed a single value to e.g. retrieve similar items or to use the embedding in a downstream task. - -```ts -import { embed } from 'ai'; - -const { embedding } = await embed({ - model: 'openai/text-embedding-3-small', - value: 'sunny day at the beach', -}); -``` - -## Import - - - -## API Signature - -### Parameters - -', - isOptional: true, - description: - 'Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.', - }, - { - name: 'providerOptions', - type: 'ProviderOptions', - isOptional: true, - description: - 'Provider-specific options that are passed through to the provider.', - }, - { - name: 'experimental_telemetry', - type: 'TelemetrySettings', - isOptional: true, - description: 'Telemetry configuration. Experimental feature.', - properties: [ - { - type: 'TelemetrySettings', - parameters: [ - { - name: 'isEnabled', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable telemetry. Disabled by default while experimental.', - }, - { - name: 'recordInputs', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable input recording. Enabled by default.', - }, - { - name: 'recordOutputs', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable output recording. Enabled by default.', - }, - { - name: 'functionId', - type: 'string', - isOptional: true, - description: - 'Identifier for this function. Used to group telemetry data by function.', - }, - { - name: 'metadata', - isOptional: true, - type: 'Record | Array | Array>', - description: - 'Additional information to include in the telemetry data.', - }, - { - name: 'tracer', - type: 'Tracer', - isOptional: true, - description: 'A custom tracer to use for the telemetry data.', - }, - ], - }, - ], - }, - ]} -/> - -### Returns - -', - description: 'Response headers.', - }, - { - name: 'body', - type: 'unknown', - isOptional: true, - description: 'The response body.', - }, - ], - }, - ], - }, - { - name: 'providerMetadata', - type: 'ProviderMetadata | undefined', - isOptional: true, - description: - 'Optional metadata from the provider. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/06-embed-many.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/06-embed-many.mdx deleted file mode 100644 index f19dbdc54..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/06-embed-many.mdx +++ /dev/null @@ -1,191 +0,0 @@ ---- -title: embedMany -description: API Reference for embedMany. ---- - -# `embedMany()` - -Embed several values using an embedding model. - -`embedMany` automatically splits large requests into smaller chunks if the model -has a limit on how many embeddings can be generated in a single call. - -```ts -import { embedMany } from 'ai'; - -const { embeddings } = await embedMany({ - model: 'openai/text-embedding-3-small', - values: [ - 'sunny day at the beach', - 'rainy afternoon in the city', - 'snowy night in the mountains', - ], -}); -``` - -## Import - - - -## API Signature - -### Parameters - -', - description: 'The values to embed.', - }, - { - name: 'maxRetries', - type: 'number', - isOptional: true, - description: - 'Maximum number of retries. Set to 0 to disable retries. Default: 2.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - isOptional: true, - description: - 'An optional abort signal that can be used to cancel the call.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: - 'Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.', - }, - { - name: 'providerOptions', - type: 'ProviderOptions', - isOptional: true, - description: - 'Provider-specific options that are passed through to the provider.', - }, - { - name: 'maxParallelCalls', - type: 'number', - isOptional: true, - description: - 'Maximum number of concurrent requests to the provider. Default: Infinity.', - }, - { - name: 'experimental_telemetry', - type: 'TelemetrySettings', - isOptional: true, - description: 'Telemetry configuration. Experimental feature.', - properties: [ - { - type: 'TelemetrySettings', - parameters: [ - { - name: 'isEnabled', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable telemetry. Disabled by default while experimental.', - }, - { - name: 'recordInputs', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable input recording. Enabled by default.', - }, - { - name: 'recordOutputs', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable output recording. Enabled by default.', - }, - { - name: 'functionId', - type: 'string', - isOptional: true, - description: - 'Identifier for this function. Used to group telemetry data by function.', - }, - { - name: 'metadata', - isOptional: true, - type: 'Record | Array | Array>', - description: - 'Additional information to include in the telemetry data.', - }, - { - name: 'tracer', - type: 'Tracer', - isOptional: true, - description: 'A custom tracer to use for the telemetry data.', - }, - ], - }, - ], - }, - ]} -/> - -### Returns - -', - description: 'The values that were embedded.', - }, - { - name: 'embeddings', - type: 'number[][]', - description: 'The embeddings. They are in the same order as the values.', - }, - { - name: 'usage', - type: 'EmbeddingModelUsage', - description: 'The token usage for generating the embeddings.', - properties: [ - { - type: 'EmbeddingModelUsage', - parameters: [ - { - name: 'tokens', - type: 'number', - description: 'The total number of input tokens.', - }, - ], - }, - ], - }, - { - name: 'warnings', - type: 'Warning[]', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'providerMetadata', - type: 'ProviderMetadata | undefined', - isOptional: true, - description: - 'Optional metadata from the provider. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - { - name: 'responses', - type: 'Array<{ headers?: Record; body?: unknown } | undefined>', - isOptional: true, - description: - 'Optional raw response data from each chunk request. There may be multiple responses if the request was split into multiple chunks.', - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/06-rerank.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/06-rerank.mdx deleted file mode 100644 index da67c99cc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/06-rerank.mdx +++ /dev/null @@ -1,309 +0,0 @@ ---- -title: rerank -description: API Reference for rerank. ---- - -# `rerank()` - -Rerank a set of documents based on their relevance to a query using a reranking model. - -This is ideal for improving search relevance by reordering documents, emails, or other content based on semantic understanding of the query and documents. - -```ts -import { cohere } from '@ai-sdk/cohere'; -import { rerank } from 'ai'; - -const { ranking } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents: ['sunny day at the beach', 'rainy afternoon in the city'], - query: 'talk about rain', -}); -``` - -## Import - - - -## API Signature - -### Parameters - -', - description: - 'The documents to rerank. Can be an array of strings or JSON objects.', - }, - { - name: 'query', - type: 'string', - description: 'The search query to rank documents against.', - }, - { - name: 'topN', - type: 'number', - isOptional: true, - description: - 'Maximum number of top documents to return. If not specified, all documents are returned.', - }, - { - name: 'maxRetries', - type: 'number', - isOptional: true, - description: - 'Maximum number of retries. Set to 0 to disable retries. Default: 2.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - isOptional: true, - description: - 'An optional abort signal that can be used to cancel the call.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: - 'Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.', - }, - { - name: 'providerOptions', - type: 'ProviderOptions', - isOptional: true, - description: 'Provider-specific options for the reranking request.', - }, - { - name: 'experimental_telemetry', - type: 'TelemetrySettings', - isOptional: true, - description: 'Telemetry configuration. Experimental feature.', - properties: [ - { - type: 'TelemetrySettings', - parameters: [ - { - name: 'isEnabled', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable telemetry. Disabled by default while experimental.', - }, - { - name: 'recordInputs', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable input recording. Enabled by default.', - }, - { - name: 'recordOutputs', - type: 'boolean', - isOptional: true, - description: - 'Enable or disable output recording. Enabled by default.', - }, - { - name: 'functionId', - type: 'string', - isOptional: true, - description: - 'Identifier for this function. Used to group telemetry data by function.', - }, - { - name: 'metadata', - isOptional: true, - type: 'Record | Array | Array>', - description: - 'Additional information to include in the telemetry data.', - }, - { - name: 'tracer', - type: 'Tracer', - isOptional: true, - description: 'A custom tracer to use for the telemetry data.', - }, - ], - }, - ], - }, - ]} -/> - -### Returns - -', - description: 'The original documents array in their original order.', - }, - { - name: 'rerankedDocuments', - type: 'Array', - description: 'The documents sorted by relevance score (descending).', - }, - { - name: 'ranking', - type: 'Array>', - description: 'Array of ranking items with scores and indices.', - properties: [ - { - type: 'RankingItem', - parameters: [ - { - name: 'originalIndex', - type: 'number', - description: - 'The index of the document in the original documents array.', - }, - { - name: 'score', - type: 'number', - description: - 'The relevance score for the document (typically 0-1, where higher is more relevant).', - }, - { - name: 'document', - type: 'VALUE', - description: 'The document itself.', - }, - ], - }, - ], - }, - { - name: 'response', - type: 'Response', - description: 'Response data.', - properties: [ - { - type: 'Response', - parameters: [ - { - name: 'id', - isOptional: true, - type: 'string', - description: 'The response ID from the provider.', - }, - { - name: 'timestamp', - type: 'Date', - description: 'The timestamp of the response.', - }, - { - name: 'modelId', - type: 'string', - description: 'The model ID used for reranking.', - }, - { - name: 'headers', - isOptional: true, - type: 'Record', - description: 'Response headers.', - }, - { - name: 'body', - type: 'unknown', - isOptional: true, - description: 'The raw response body.', - }, - ], - }, - ], - }, - { - name: 'providerMetadata', - type: 'ProviderMetadata | undefined', - isOptional: true, - description: - 'Optional metadata from the provider. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - ]} -/> - -## Examples - -### String Documents - -```ts -import { cohere } from '@ai-sdk/cohere'; -import { rerank } from 'ai'; - -const { ranking, rerankedDocuments } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents: [ - 'sunny day at the beach', - 'rainy afternoon in the city', - 'snowy night in the mountains', - ], - query: 'talk about rain', - topN: 2, -}); - -console.log(rerankedDocuments); -// ['rainy afternoon in the city', 'sunny day at the beach'] - -console.log(ranking); -// [ -// { originalIndex: 1, score: 0.9, document: 'rainy afternoon...' }, -// { originalIndex: 0, score: 0.3, document: 'sunny day...' } -// ] -``` - -### Object Documents - -```ts -import { cohere } from '@ai-sdk/cohere'; -import { rerank } from 'ai'; - -const documents = [ - { - from: 'Paul Doe', - subject: 'Follow-up', - text: 'We are happy to give you a discount of 20%.', - }, - { - from: 'John McGill', - subject: 'Missing Info', - text: 'Here is the pricing from Oracle: $5000/month', - }, -]; - -const { ranking } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents, - query: 'Which pricing did we get from Oracle?', - topN: 1, -}); - -console.log(ranking[0].document); -// { from: 'John McGill', subject: 'Missing Info', ... } -``` - -### With Provider Options - -```ts -import { cohere } from '@ai-sdk/cohere'; -import { rerank } from 'ai'; - -const { ranking } = await rerank({ - model: cohere.reranking('rerank-v3.5'), - documents: ['sunny day at the beach', 'rainy afternoon in the city'], - query: 'talk about rain', - providerOptions: { - cohere: { - maxTokensPerDoc: 1000, - }, - }, -}); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/10-generate-image.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/10-generate-image.mdx deleted file mode 100644 index b8bda5a08..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/10-generate-image.mdx +++ /dev/null @@ -1,251 +0,0 @@ ---- -title: generateImage -description: API Reference for generateImage. ---- - -# `generateImage()` - -Generates images based on a given prompt using an image model. - -It is ideal for use cases where you need to generate images programmatically, -such as creating visual content or generating images for data augmentation. - -```ts -import { generateImage } from 'ai'; - -const { images } = await generateImage({ - model: openai.image('dall-e-3'), - prompt: 'A futuristic cityscape at sunset', - n: 3, - size: '1024x1024', -}); - -console.log(images); -``` - -## Import - - - -## API Signature - -### Parameters - -', - description: - 'an image item can be one of: base64-encoded string, a `Uint8Array`, an `ArrayBuffer`, or a `Buffer`.', - }, - { - name: 'text', - type: 'string', - description: 'The text prompt.', - }, - { - name: 'mask', - type: 'DataContent', - description: - 'base64-encoded string, a `Uint8Array`, an `ArrayBuffer`, or a `Buffer`.', - }, - ], - }, - ], - }, - { - name: 'n', - type: 'number', - isOptional: true, - description: 'Number of images to generate.', - }, - { - name: 'size', - type: 'string', - isOptional: true, - description: - 'Size of the images to generate. Format: `{width}x{height}`.', - }, - { - name: 'aspectRatio', - type: 'string', - isOptional: true, - description: - 'Aspect ratio of the images to generate. Format: `{width}:{height}`.', - }, - { - name: 'seed', - type: 'number', - isOptional: true, - description: 'Seed for the image generation.', - }, - { - name: 'providerOptions', - type: 'ProviderOptions', - isOptional: true, - description: 'Additional provider-specific options.', - }, - { - name: 'maxImagesPerCall', - type: 'number', - isOptional: true, - description: - 'Maximum number of images to generate per API call. When n exceeds this value, multiple API calls will be made.', - }, - { - name: 'maxRetries', - type: 'number', - isOptional: true, - description: 'Maximum number of retries. Default: 2.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - isOptional: true, - description: 'An optional abort signal to cancel the call.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: 'Additional HTTP headers for the request.', - }, - ]} -/> - -### Returns - -', - description: 'All images that were generated.', - properties: [ - { - type: 'GeneratedFile', - parameters: [ - { - name: 'base64', - type: 'string', - description: 'Image as a base64 encoded string.', - }, - { - name: 'uint8Array', - type: 'Uint8Array', - description: 'Image as a Uint8Array.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the image.', - }, - ], - }, - ], - }, - { - name: 'warnings', - type: 'Warning[]', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'usage', - type: 'ImageModelUsage', - description: 'The usage statistics for the image generation.', - properties: [ - { - type: 'ImageModelUsage', - parameters: [ - { - name: 'imagesGenerated', - type: 'number', - description: 'The total number of images generated.', - }, - ], - }, - ], - }, - { - name: 'providerMetadata', - type: 'ImageModelProviderMetadata', - isOptional: true, - description: - 'Optional metadata from the provider. The outer key is the provider name. The inner values are the metadata. An `images` key is always present in the metadata and is an array with the same length as the top level `images` key. Details depend on the provider.', - }, - { - name: 'responses', - type: 'Array', - description: - 'Response metadata from the provider. There may be multiple responses if we made multiple calls to the model.', - properties: [ - { - type: 'ImageModelResponseMetadata', - parameters: [ - { - name: 'timestamp', - type: 'Date', - description: 'Timestamp for the start of the generated response.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The ID of the response model that was used to generate the response.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: 'Response headers.', - }, - ], - }, - ], - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/11-transcribe.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/11-transcribe.mdx deleted file mode 100644 index d17a96e7d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/11-transcribe.mdx +++ /dev/null @@ -1,152 +0,0 @@ ---- -title: transcribe -description: API Reference for transcribe. ---- - -# `transcribe()` - -`transcribe` is an experimental feature. - -Generates a transcript from an audio file. - -```ts -import { experimental_transcribe as transcribe } from 'ai'; -import { openai } from '@ai-sdk/openai'; -import { readFile } from 'fs/promises'; - -const { text: transcript } = await transcribe({ - model: openai.transcription('whisper-1'), - audio: await readFile('audio.mp3'), -}); - -console.log(transcript); -``` - -## Import - - - -## API Signature - -### Parameters - -', - isOptional: true, - description: 'Additional provider-specific options.', - }, - { - name: 'maxRetries', - type: 'number', - isOptional: true, - description: 'Maximum number of retries. Default: 2.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - isOptional: true, - description: 'An optional abort signal to cancel the call.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: 'Additional HTTP headers for the request.', - }, - { - name: 'download', - type: '(options: { url: URL; abortSignal?: AbortSignal }) => Promise<{ data: Uint8Array; mediaType: string | undefined }>', - isOptional: true, - description: - 'Custom download function for fetching audio from URLs. Use `createDownload()` from `ai` to create a download function with custom size limits, e.g. `createDownload({ maxBytes: 50 * 1024 * 1024 })`. Default: built-in download with 2 GiB limit.', - }, - ]} -/> - -### Returns - -', - description: - 'An array of transcript segments, each containing a portion of the transcribed text along with its start and end times in seconds.', - }, - { - name: 'language', - type: 'string | undefined', - description: - 'The language of the transcript in ISO-639-1 format e.g. "en" for English.', - }, - { - name: 'durationInSeconds', - type: 'number | undefined', - description: 'The duration of the transcript in seconds.', - }, - { - name: 'warnings', - type: 'Warning[]', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'providerMetadata', - type: 'Record', - isOptional: true, - description: - 'Optional metadata from the provider. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - { - name: 'responses', - type: 'Array', - description: - 'Response metadata from the provider. There may be multiple responses if we made multiple calls to the model.', - properties: [ - { - type: 'TranscriptionModelResponseMetadata', - parameters: [ - { - name: 'timestamp', - type: 'Date', - description: 'Timestamp for the start of the generated response.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The ID of the response model that was used to generate the response.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: 'Response headers.', - }, - ], - }, - ], - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/12-generate-speech.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/12-generate-speech.mdx deleted file mode 100644 index 0839e9da7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/12-generate-speech.mdx +++ /dev/null @@ -1,221 +0,0 @@ ---- -title: generateSpeech -description: API Reference for generateSpeech. ---- - -# `generateSpeech()` - -`generateSpeech` is an experimental feature. - -Generates speech audio from text. - -```ts -import { experimental_generateSpeech as generateSpeech } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const { audio } = await generateSpeech({ - model: openai.speech('tts-1'), - text: 'Hello from the AI SDK!', - voice: 'alloy', -}); - -console.log(audio); -``` - -## Examples - -### OpenAI - -```ts -import { experimental_generateSpeech as generateSpeech } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const { audio } = await generateSpeech({ - model: openai.speech('tts-1'), - text: 'Hello from the AI SDK!', - voice: 'alloy', -}); -``` - -### ElevenLabs - -```ts -import { experimental_generateSpeech as generateSpeech } from 'ai'; -import { elevenlabs } from '@ai-sdk/elevenlabs'; - -const { audio } = await generateSpeech({ - model: elevenlabs.speech('eleven_multilingual_v2'), - text: 'Hello from the AI SDK!', - voice: 'your-voice-id', // Required: get this from your ElevenLabs account -}); -``` - -## Import - - - -## API Signature - -### Parameters - -', - isOptional: true, - description: 'Additional provider-specific options.', - }, - { - name: 'maxRetries', - type: 'number', - isOptional: true, - description: 'Maximum number of retries. Default: 2.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - isOptional: true, - description: 'An optional abort signal to cancel the call.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: 'Additional HTTP headers for the request.', - }, - ]} -/> - -### Returns - -', - isOptional: true, - description: - 'Optional metadata from the provider. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - { - name: 'responses', - type: 'Array', - description: - 'Response metadata from the provider. There may be multiple responses if we made multiple calls to the model.', - properties: [ - { - type: 'SpeechModelResponseMetadata', - parameters: [ - { - name: 'timestamp', - type: 'Date', - description: 'Timestamp for the start of the generated response.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The ID of the response model that was used to generate the response.', - }, - { - name: 'body', - isOptional: true, - type: 'unknown', - description: 'Optional response body.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: 'Response headers.', - }, - ], - }, - ], - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/13-generate-video.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/13-generate-video.mdx deleted file mode 100644 index 77084e9e3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/13-generate-video.mdx +++ /dev/null @@ -1,264 +0,0 @@ ---- -title: experimental_generateVideo -description: API Reference for experimental_generateVideo. ---- - -# `experimental_generateVideo()` - - - Video generation is an experimental feature. The API may change in future - versions. - - -Generates videos based on a given prompt using a video model. - -It is ideal for use cases where you need to generate videos programmatically, -such as creating visual content, animations, or generating videos from images. - -```ts -import { experimental_generateVideo as generateVideo } from 'ai'; - -const { videos } = await generateVideo({ - model: fal.video('luma-dream-machine/ray-2'), - prompt: 'A cat walking on a treadmill', - aspectRatio: '16:9', -}); - -console.log(videos); -``` - -## Import - - - -## API Signature - -### Parameters - -', - isOptional: true, - description: 'Additional HTTP headers for the request.', - }, - { - name: 'download', - type: '(options: { url: URL; abortSignal?: AbortSignal }) => Promise<{ data: Uint8Array; mediaType: string | undefined }>', - isOptional: true, - description: - 'Custom download function for fetching videos from URLs. Use `createDownload()` from `ai` to create a download function with custom size limits, e.g. `createDownload({ maxBytes: 50 * 1024 * 1024 })`. Default: built-in download with 2 GiB limit.', - }, - ]} -/> - -### Returns - -', - description: 'All videos that were generated.', - properties: [ - { - type: 'GeneratedFile', - parameters: [ - { - name: 'base64', - type: 'string', - description: 'Video as a base64 encoded string.', - }, - { - name: 'uint8Array', - type: 'Uint8Array', - description: 'Video as a Uint8Array.', - }, - { - name: 'mediaType', - type: 'string', - description: - 'The IANA media type of the video (e.g., video/mp4).', - }, - ], - }, - ], - }, - { - name: 'warnings', - type: 'Warning[]', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'providerMetadata', - type: 'VideoModelProviderMetadata', - isOptional: true, - description: - 'Optional metadata from the provider. The outer key is the provider name. The inner values are the metadata. A `videos` key is typically present in the metadata and is an array with the same length as the top level `videos` key. Details depend on the provider.', - }, - { - name: 'responses', - type: 'Array', - description: - 'Response metadata from the provider. There may be multiple responses if we made multiple calls to the model.', - properties: [ - { - type: 'VideoModelResponseMetadata', - parameters: [ - { - name: 'timestamp', - type: 'Date', - description: 'Timestamp for the start of the generated response.', - }, - { - name: 'modelId', - type: 'string', - description: - 'The ID of the response model that was used to generate the response.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: 'Response headers.', - }, - { - name: 'providerMetadata', - type: 'VideoModelProviderMetadata', - isOptional: true, - description: - 'Provider-specific metadata for this individual API call. Useful for accessing per-call metadata when multiple calls are made.', - }, - ], - }, - ], - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/15-agent.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/15-agent.mdx deleted file mode 100644 index aed1ffc69..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/15-agent.mdx +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: Agent (Interface) -description: API Reference for the Agent interface. ---- - -# `Agent` (interface) - -The `Agent` interface defines a contract for agents that can generate or stream AI-generated responses in response to prompts. Agents may encapsulate advanced logic such as tool usage, multi-step workflows, or prompt handling, enabling both simple and autonomous AI agents. - -Implementations of the `Agent` interface—such as `ToolLoopAgent`—fulfill the same contract and integrate seamlessly with all SDK APIs and utilities that expect an agent. This design allows users to supply custom agent classes or wrappers for third-party chains, while maximizing compatibility with AI SDK features. - -## Interface Definition - -```ts -import { ModelMessage } from '@ai-sdk/provider-utils'; -import { ToolSet } from '../generate-text/tool-set'; -import { Output } from '../generate-text/output'; -import { GenerateTextResult } from '../generate-text/generate-text-result'; -import { StreamTextResult } from '../generate-text/stream-text-result'; - -export type AgentCallParameters = ([ - CALL_OPTIONS, -] extends [never] - ? { options?: never } - : { options: CALL_OPTIONS }) & - ( - | { - /** - * A prompt. It can be either a text prompt or a list of messages. - * - * You can either use `prompt` or `messages` but not both. - */ - prompt: string | Array; - - /** - * A list of messages. - * - * You can either use `prompt` or `messages` but not both. - */ - messages?: never; - } - | { - /** - * A list of messages. - * - * You can either use `prompt` or `messages` but not both. - */ - messages: Array; - - /** - * A prompt. It can be either a text prompt or a list of messages. - * - * You can either use `prompt` or `messages` but not both. - */ - prompt?: never; - } - ) & { - /** - * Abort signal. - */ - abortSignal?: AbortSignal; - /** - * Timeout in milliseconds. Can be specified as a number or as an object with a totalMs property. - * The call will be aborted if it takes longer than the specified timeout. - * Can be used alongside abortSignal. - */ - timeout?: number | { totalMs?: number }; - /** - * Callback that is called when each step (LLM call) is finished, including intermediate steps. - */ - onStepFinish?: ToolLoopAgentOnStepFinishCallback; - }; - -/** - * An Agent receives a prompt (text or messages) and generates or streams an output - * that consists of steps, tool calls, data parts, etc. - * - * You can implement your own Agent by implementing the `Agent` interface, - * or use the `ToolLoopAgent` class. - */ -export interface Agent< - CALL_OPTIONS = never, - TOOLS extends ToolSet = {}, - OUTPUT extends Output = never, -> { - /** - * The specification version of the agent interface. This will enable - * us to evolve the agent interface and retain backwards compatibility. - */ - readonly version: 'agent-v1'; - - /** - * The id of the agent. - */ - readonly id: string | undefined; - - /** - * The tools that the agent can use. - */ - readonly tools: TOOLS; - - /** - * Generates an output from the agent (non-streaming). - */ - generate( - options: AgentCallParameters, - ): PromiseLike>; - - /** - * Streams an output from the agent (streaming). - */ - stream( - options: AgentStreamParameters, - ): PromiseLike>; -} -``` - -## Core Properties & Methods - -| Name | Type | Description | -| ------------ | ------------------------------------------------ | ------------------------------------------------------------------- | -| `version` | `'agent-v1'` | Interface version for compatibility. | -| `id` | `string \| undefined` | Optional agent identifier. | -| `tools` | `ToolSet` | The set of tools available to this agent. | -| `generate()` | `PromiseLike>` | Generates full, non-streaming output for a text prompt or messages. | -| `stream()` | `PromiseLike>` | Streams output (chunks or steps) for a text prompt or messages. | - -## Generic Parameters - -| Parameter | Default | Description | -| -------------- | ------- | -------------------------------------------------------------------------- | -| `CALL_OPTIONS` | `never` | Optional type for additional call options that can be passed to the agent. | -| `TOOLS` | `{}` | The type of the tool set available to this agent. | -| `OUTPUT` | `never` | The type of additional output data that the agent can produce. | - -## Method Parameters - -Both `generate()` and `stream()` accept an `AgentCallParameters` object with: - -- `prompt` (optional): A string prompt or array of `ModelMessage` objects -- `messages` (optional): An array of `ModelMessage` objects (mutually exclusive with `prompt`) -- `options` (optional): Additional call options when `CALL_OPTIONS` is not `never` -- `abortSignal` (optional): An `AbortSignal` to cancel the operation -- `timeout` (optional): A timeout in milliseconds. Can be specified as a number or as an object with a `totalMs` property. The call will be aborted if it takes longer than the specified timeout. Can be used alongside `abortSignal`. -- `onStepFinish` (optional): A callback invoked after each agent step (LLM/tool call) completes. Useful for tracking token usage or logging. - -## Example: Custom Agent Implementation - -Here's how you might implement your own Agent: - -```ts -import { Agent, GenerateTextResult, StreamTextResult } from 'ai'; -import type { ModelMessage } from '@ai-sdk/provider-utils'; - -class MyEchoAgent implements Agent { - version = 'agent-v1' as const; - id = 'echo'; - tools = {}; - - async generate({ prompt, messages, abortSignal }) { - const text = prompt ?? JSON.stringify(messages); - return { text, steps: [] }; - } - - async stream({ prompt, messages, abortSignal }) { - const text = prompt ?? JSON.stringify(messages); - return { - textStream: (async function* () { - yield text; - })(), - }; - } -} -``` - -## Usage: Interacting with Agents - -All SDK utilities that accept an agent—including [`createAgentUIStream`](/docs/reference/ai-sdk-core/create-agent-ui-stream), [`createAgentUIStreamResponse`](/docs/reference/ai-sdk-core/create-agent-ui-stream-response), and [`pipeAgentUIStreamToResponse`](/docs/reference/ai-sdk-core/pipe-agent-ui-stream-to-response)—expect an object adhering to the `Agent` interface. - -You can use the official [`ToolLoopAgent`](/docs/reference/ai-sdk-core/tool-loop-agent) (recommended for multi-step AI workflows with tool use), or supply your own implementation: - -```ts -import { ToolLoopAgent, createAgentUIStream } from "ai"; - -const agent = new ToolLoopAgent({ ... }); - -const stream = await createAgentUIStream({ - agent, - messages: [{ role: "user", content: "What is the weather in NYC?" }] -}); - -for await (const chunk of stream) { - console.log(chunk); -} -``` - -## See Also - -- [`ToolLoopAgent`](/docs/reference/ai-sdk-core/tool-loop-agent) — Official multi-step agent implementation -- [`createAgentUIStream`](/docs/reference/ai-sdk-core/create-agent-ui-stream) -- [`GenerateTextResult`](/docs/reference/ai-sdk-core/generate-text) -- [`StreamTextResult`](/docs/reference/ai-sdk-core/stream-text) - -## Notes - -- Agents should define their `tools` property, even if empty (`{}`), for compatibility with SDK utilities. -- The interface accepts both plain prompts and message arrays as input, but only one at a time. -- The `CALL_OPTIONS` generic parameter allows agents to accept additional call-specific options when needed. -- The `abortSignal` parameter enables cancellation of agent operations. -- This design is extensible for both complex autonomous agents and simple LLM wrappers. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/16-tool-loop-agent.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/16-tool-loop-agent.mdx deleted file mode 100644 index 8fca0171c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/16-tool-loop-agent.mdx +++ /dev/null @@ -1,498 +0,0 @@ ---- -title: ToolLoopAgent -description: API Reference for the ToolLoopAgent class. ---- - -# `ToolLoopAgent` - -Creates a reusable AI agent capable of generating text, streaming responses, and using tools over multiple steps (a reasoning-and-acting loop). `ToolLoopAgent` is ideal for building autonomous, multi-step agents that can take actions, call tools, and reason over the results until a stop condition is reached. - -Unlike single-step calls like `generateText()`, an agent can iteratively invoke tools, collect tool results, and decide next actions until completion or user approval is required. - -```ts -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are a helpful assistant.', - tools: { - weather: weatherTool, - calculator: calculatorTool, - }, -}); - -const result = await agent.generate({ - prompt: 'What is the weather in NYC?', -}); - -console.log(result.text); -``` - -To see `ToolLoopAgent` in action, check out [these examples](#examples). - -## Import - - - -## Constructor - -### Parameters - -', - isOptional: true, - description: - 'A set of tools the agent can call. Keys are tool names. Tools require the underlying model to support tool calling.', - }, - { - name: 'toolChoice', - type: 'ToolChoice', - isOptional: true, - description: - "Tool call selection strategy. Options: 'auto' | 'none' | 'required' | { type: 'tool', toolName: string }. Default: 'auto'.", - }, - { - name: 'stopWhen', - type: 'StopCondition | StopCondition[]', - isOptional: true, - description: - 'Condition(s) for ending the agent loop. Default: stepCountIs(20).', - }, - { - name: 'activeTools', - type: 'Array', - isOptional: true, - description: - 'Limits the subset of tools that are available in a specific call.', - }, - { - name: 'output', - type: 'Output', - isOptional: true, - description: - 'Optional structured output specification, for parsing responses into typesafe data.', - }, - { - name: 'prepareStep', - type: 'PrepareStepFunction', - isOptional: true, - description: - 'Optional function to mutate step settings or inject state for each agent step.', - }, - { - name: 'experimental_repairToolCall', - type: 'ToolCallRepairFunction', - isOptional: true, - description: - 'Optional callback to attempt automatic recovery when a tool call cannot be parsed.', - }, - { - name: 'onStepFinish', - type: 'ToolLoopAgentOnStepFinishCallback', - isOptional: true, - description: - 'Callback invoked after each agent step (LLM/tool call) completes. If also specified in `generate()` or `stream()`, both callbacks are called (constructor first).', - }, - { - name: 'onFinish', - type: 'ToolLoopAgentOnFinishCallback', - isOptional: true, - description: - 'Callback that is called when all agent steps are finished and the response is complete. Receives step results, total usage, experimental_context, functionId, and metadata. If also specified in `generate()` or `stream()`, both callbacks are called (constructor first).', - }, - { - name: 'experimental_context', - type: 'unknown', - isOptional: true, - description: - 'Experimental: Custom context object passed to each tool call.', - }, - { - name: 'experimental_telemetry', - type: 'TelemetrySettings', - isOptional: true, - description: 'Experimental: Optional telemetry configuration.', - }, - { - name: 'experimental_download', - type: 'DownloadFunction | undefined', - isOptional: true, - description: - 'Experimental: Custom download function for fetching files/URLs for tool or model use. By default, files are downloaded if the model does not support the URL for a given media type.', - }, - { - name: 'maxOutputTokens', - type: 'number', - isOptional: true, - description: 'Maximum number of tokens the model is allowed to generate.', - }, - { - name: 'temperature', - type: 'number', - isOptional: true, - description: - 'Sampling temperature, controls randomness. Passed through to the model.', - }, - { - name: 'topP', - type: 'number', - isOptional: true, - description: - 'Top-p (nucleus) sampling parameter. Passed through to the model.', - }, - { - name: 'topK', - type: 'number', - isOptional: true, - description: 'Top-k sampling parameter. Passed through to the model.', - }, - { - name: 'presencePenalty', - type: 'number', - isOptional: true, - description: 'Presence penalty parameter. Passed through to the model.', - }, - { - name: 'frequencyPenalty', - type: 'number', - isOptional: true, - description: 'Frequency penalty parameter. Passed through to the model.', - }, - { - name: 'stopSequences', - type: 'string[]', - isOptional: true, - description: - 'Custom token sequences which stop the model output. Passed through to the model.', - }, - { - name: 'seed', - type: 'number', - isOptional: true, - description: 'Seed for deterministic generation (if supported).', - }, - { - name: 'maxRetries', - type: 'number', - isOptional: true, - description: 'How many times to retry on failure. Default: 2.', - }, - { - name: 'providerOptions', - type: 'ProviderOptions', - isOptional: true, - description: 'Additional provider-specific configuration.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: - 'Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.', - }, - { - name: 'callOptionsSchema', - type: 'FlexibleSchema', - isOptional: true, - description: - 'Optional schema for custom call options that can be passed when calling generate() or stream().', - }, - { - name: 'prepareCall', - type: 'PrepareCallFunction', - isOptional: true, - description: - 'Optional function to prepare call-specific settings based on the call options.', - }, - { - name: 'id', - type: 'string', - isOptional: true, - description: 'Custom agent identifier.', - }, - ]} -/> - -## Methods - -### `generate()` - -Generates a response and triggers tool calls as needed, running the agent loop and returning the final result. Returns a promise resolving to a `GenerateTextResult`. - -```ts -const result = await agent.generate({ - prompt: 'What is the weather like?', -}); -``` - -', - description: 'A text prompt or message array.', - }, - { - name: 'messages', - type: 'Array', - description: 'A full conversation history as a list of model messages.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - isOptional: true, - description: - 'An optional abort signal that can be used to cancel the call.', - }, - { - name: 'timeout', - type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number }', - isOptional: true, - description: - 'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, and/or chunkMs properties. The call will be aborted if it takes longer than the specified timeout. Can be used alongside abortSignal.', - }, - { - name: 'options', - type: 'CALL_OPTIONS', - isOptional: true, - description: - 'Custom call options when the agent is configured with a callOptionsSchema.', - }, - { - name: 'onStepFinish', - type: 'ToolLoopAgentOnStepFinishCallback', - isOptional: true, - description: - 'Callback invoked after each agent step (LLM/tool call) completes. If also specified in the constructor, both callbacks are called (constructor first, then this one).', - }, - ]} -/> - -#### Returns - -The `generate()` method returns a `GenerateTextResult` object (see [`generateText`](/docs/reference/ai-sdk-core/generate-text#returns) for details). - -### `stream()` - -Streams a response from the agent, including agent reasoning and tool calls, as they occur. Returns a `StreamTextResult`. - -```ts -const stream = agent.stream({ - prompt: 'Tell me a story about a robot.', -}); - -for await (const chunk of stream.textStream) { - console.log(chunk); -} -``` - -', - description: 'A text prompt or message array.', - }, - { - name: 'messages', - type: 'Array', - description: 'A full conversation history as a list of model messages.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - isOptional: true, - description: - 'An optional abort signal that can be used to cancel the call.', - }, - { - name: 'timeout', - type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number }', - isOptional: true, - description: - 'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, and/or chunkMs properties. The call will be aborted if it takes longer than the specified timeout. Can be used alongside abortSignal.', - }, - { - name: 'options', - type: 'CALL_OPTIONS', - isOptional: true, - description: - 'Custom call options when the agent is configured with a callOptionsSchema.', - }, - { - name: 'experimental_transform', - type: 'StreamTextTransform | Array', - isOptional: true, - description: - 'Optional stream transformation(s). They are applied in the order provided and must maintain the stream structure. See `streamText` docs for details.', - }, - { - name: 'onStepFinish', - type: 'ToolLoopAgentOnStepFinishCallback', - isOptional: true, - description: - 'Callback invoked after each agent step (LLM/tool call) completes. If also specified in the constructor, both callbacks are called (constructor first, then this one).', - }, - ]} -/> - -#### Returns - -The `stream()` method returns a `StreamTextResult` object (see [`streamText`](/docs/reference/ai-sdk-core/stream-text#returns) for details). - -## Types - -### `InferAgentUIMessage` - -Infers the UI message type for the given agent instance. Useful for type-safe UI and message exchanges. - -#### Basic Example - -```ts -import { ToolLoopAgent, InferAgentUIMessage } from 'ai'; - -const weatherAgent = new ToolLoopAgent({ - model: __MODEL__, - tools: { weather: weatherTool }, -}); - -type WeatherAgentUIMessage = InferAgentUIMessage; -``` - -#### Example with Message Metadata - -You can provide a second type argument to customize the metadata for each message. This is useful for tracking rich metadata returned by the agent (such as createdAt, tokens, finish reason, etc.). - -```ts -import { ToolLoopAgent, InferAgentUIMessage } from 'ai'; -import { z } from 'zod'; - -// Example schema for message metadata -const exampleMetadataSchema = z.object({ - createdAt: z.number().optional(), - model: z.string().optional(), - totalTokens: z.number().optional(), - finishReason: z.string().optional(), -}); -type ExampleMetadata = z.infer; - -// Define agent as usual -const metadataAgent = new ToolLoopAgent({ - model: __MODEL__, - // ...other options -}); - -// Type-safe UI message type with custom metadata -type MetadataAgentUIMessage = InferAgentUIMessage< - typeof metadataAgent, - ExampleMetadata ->; -``` - -## Examples - -### Basic Agent with Tools - -```ts -import { ToolLoopAgent, stepCountIs } from 'ai'; -import { weatherTool, calculatorTool } from './tools'; - -const assistant = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are a helpful assistant.', - tools: { - weather: weatherTool, - calculator: calculatorTool, - }, - stopWhen: stepCountIs(3), -}); - -const result = await assistant.generate({ - prompt: 'What is the weather in NYC and what is 100 * 25?', -}); - -console.log(result.text); -console.log(result.steps); // Array of all steps taken by the agent -``` - -### Streaming Agent Response - -```ts -const agent = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are a creative storyteller.', -}); - -const stream = agent.stream({ - prompt: 'Tell me a short story about a time traveler.', -}); - -for await (const chunk of stream.textStream) { - process.stdout.write(chunk); -} -``` - -### Agent with Output Parsing - -```ts -import { z } from 'zod'; - -const analysisAgent = new ToolLoopAgent({ - model: __MODEL__, - output: { - schema: z.object({ - sentiment: z.enum(['positive', 'negative', 'neutral']), - score: z.number(), - summary: z.string(), - }), - }, -}); - -const result = await analysisAgent.generate({ - prompt: 'Analyze this review: "The product exceeded my expectations!"', -}); - -console.log(result.output); -// Typed as { sentiment: 'positive' | 'negative' | 'neutral', score: number, summary: string } -``` - -### Example: Approved Tool Execution - -```ts -import { openai } from '@ai-sdk/openai'; -import { ToolLoopAgent } from 'ai'; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are an agent with access to a weather API.', - tools: { - weather: openai.tools.weather({ - /* ... */ - }), - }, - // Optionally require approval, etc. -}); - -const result = await agent.generate({ - prompt: 'Is it raining in Paris today?', -}); -console.log(result.text); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/17-create-agent-ui-stream.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/17-create-agent-ui-stream.mdx deleted file mode 100644 index aa47fca9c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/17-create-agent-ui-stream.mdx +++ /dev/null @@ -1,154 +0,0 @@ ---- -title: createAgentUIStream -description: API Reference for the createAgentUIStream utility. ---- - -# `createAgentUIStream` - -The `createAgentUIStream` function executes an [Agent](/docs/reference/ai-sdk-core/agent), consumes an array of UI messages, and streams the agent's output as UI message chunks via an async iterable. This enables real-time, incremental rendering of AI assistant output with full access to tool use, intermediate reasoning, and interactive UI features in your own runtime—perfect for building chat APIs, dashboards, or bots powered by agents. - -## Import - - - -## Usage - -```ts -import { ToolLoopAgent, createAgentUIStream } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are a helpful assistant.', - tools: { weather: weatherTool, calculator: calculatorTool }, -}); - -export async function* streamAgent( - uiMessages: unknown[], - abortSignal?: AbortSignal, -) { - const stream = await createAgentUIStream({ - agent, - uiMessages, - abortSignal, - // ...other options (see below) - }); - - for await (const chunk of stream) { - yield chunk; // Each chunk is a UI message output from the agent. - } -} -``` - -## Parameters - - - -## Returns - -A `Promise>`, where each yielded chunk is a UI message output from the agent (see [`UIMessage`](/docs/reference/ai-sdk-core/ui-message)). This can be consumed with any async iterator loop, or piped to a streaming HTTP response, socket, or any other sink. - -## Example - -```ts -import { createAgentUIStream } from 'ai'; - -const controller = new AbortController(); - -const stream = await createAgentUIStream({ - agent, - uiMessages: [{ role: 'user', content: 'What is the weather in SF today?' }], - abortSignal: controller.signal, - sendStart: true, - // ...other UIMessageStreamOptions -}); - -for await (const chunk of stream) { - // Each chunk is a UI message update — stream it to your client, dashboard, logs, etc. - console.log(chunk); -} - -// Call controller.abort() to cancel the agent operation early. -``` - -## How It Works - -1. **UI Message Validation:** The input `uiMessages` array is validated and normalized using the agent's `tools` definition. Any invalid messages cause an error. -2. **Conversion to Model Messages:** The validated UI messages are converted into model-specific message format, as required by the agent. -3. **Agent Streaming:** The agent's `.stream({ prompt, ... })` method is invoked with the converted model messages, optional call options, abort signal, and any experimental transforms. -4. **UI Message Stream Building:** The result stream is converted and exposed as a streaming async iterable of UI message chunks for you to consume. - -## Notes - -- The agent **must** implement the `.stream({ prompt, ... })` method and define its supported `tools` property. -- This utility returns an async iterable for maximal streaming flexibility. For HTTP responses, see [`createAgentUIStreamResponse`](/docs/reference/ai-sdk-core/create-agent-ui-stream-response) (Web) or [`pipeAgentUIStreamToResponse`](/docs/reference/ai-sdk-core/pipe-agent-ui-stream-to-response) (Node.js). -- The `uiMessages` parameter is named `uiMessages`, **not** just `messages`. -- You can provide advanced options via `UIMessageStreamOptions` (for example, to include sources or usage). -- To cancel the stream, pass an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) via the `abortSignal` parameter. - -## See Also - -- [`Agent`](/docs/reference/ai-sdk-core/agent) -- [`ToolLoopAgent`](/docs/reference/ai-sdk-core/tool-loop-agent) -- [`UIMessage`](/docs/reference/ai-sdk-core/ui-message) -- [`createAgentUIStreamResponse`](/docs/reference/ai-sdk-core/create-agent-ui-stream-response) -- [`pipeAgentUIStreamToResponse`](/docs/reference/ai-sdk-core/pipe-agent-ui-stream-to-response) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/18-create-agent-ui-stream-response.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/18-create-agent-ui-stream-response.mdx deleted file mode 100644 index 2272ad411..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/18-create-agent-ui-stream-response.mdx +++ /dev/null @@ -1,173 +0,0 @@ ---- -title: createAgentUIStreamResponse -description: API Reference for the createAgentUIStreamResponse utility. ---- - -# `createAgentUIStreamResponse` - -The `createAgentUIStreamResponse` function executes an [Agent](/docs/reference/ai-sdk-core/agent), runs its streaming output as a UI message stream, and returns an HTTP [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) object whose body is the live, streaming UI message output. This is designed for API routes that deliver real-time agent results, such as chat endpoints or streaming tool-use operations. - -## Import - - - -## Usage - -```ts -import { ToolLoopAgent, createAgentUIStreamResponse } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are a helpful assistant.', - tools: { weather: weatherTool, calculator: calculatorTool }, -}); - -export async function POST(request: Request) { - const { messages } = await request.json(); - - // Optional: support cancellation (aborts on disconnect, etc.) - const abortController = new AbortController(); - - return createAgentUIStreamResponse({ - agent, - uiMessages: messages, - abortSignal: abortController.signal, // optional - // ...other UIMessageStreamOptions like sendSources, experimental_transform, etc. - }); -} -``` - -## Parameters - - }) => PromiseLike | void', - isRequired: false, - description: - 'Optional function to consume the SSE stream. When provided, this function will be called with the SSE stream to handle consumption.', - }, - ]} -/> - -## Returns - -A `Promise` whose `body` is a streaming UI message output from the agent. Use this as the return value of API/server handlers in serverless, Next.js, Express, Hono, or edge runtime contexts. - -## Example: Next.js API Route Handler - -```ts -import { createAgentUIStreamResponse } from 'ai'; -import { MyCustomAgent } from '@/agent/my-custom-agent'; - -export async function POST(request: Request) { - const { messages } = await request.json(); - - return createAgentUIStreamResponse({ - agent: MyCustomAgent, - uiMessages: messages, - sendSources: true, // (optional) - // headers, status, abortSignal, and other UIMessageStreamOptions also supported - }); -} -``` - -## How It Works - -- 1. **UI Message Validation:** Validates the incoming `uiMessages` array according to the agent's specified tools and requirements. -- 2. **Model Message Conversion:** Converts validated UI messages into the internal model message format for the agent. -- 3. **Streaming Agent Output:** Invokes the agent’s `.stream({ prompt, ... })` to get a stream of chunks (steps/UI messages). -- 4. **HTTP Response Creation:** Wraps the output stream as a readable HTTP `Response` object that streams UI message chunks to the client. - -## Notes - -- Your agent **must** implement `.stream({ prompt, ... })` and define a `tools` property (even if it's just `{}`) to work with this function. -- **Server Only:** This API should only be called in backend/server-side contexts (API routes, edge/serverless/server route handlers, etc.). Not for browser use. -- Additional options (`headers`, `status`, UI stream options, transforms, etc.) are available for advanced scenarios. -- This leverages [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) so your platform/client must support HTTP streaming consumption. - -## See Also - -- [`Agent`](/docs/reference/ai-sdk-core/agent) -- [`ToolLoopAgent`](/docs/reference/ai-sdk-core/tool-loop-agent) -- [`UIMessage`](/docs/reference/ai-sdk-core/ui-message) -- [`createAgentUIStream`](/docs/reference/ai-sdk-core/create-agent-ui-stream) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/18-pipe-agent-ui-stream-to-response.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/18-pipe-agent-ui-stream-to-response.mdx deleted file mode 100644 index 1b2b6b494..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/18-pipe-agent-ui-stream-to-response.mdx +++ /dev/null @@ -1,150 +0,0 @@ ---- -title: pipeAgentUIStreamToResponse -description: API Reference for the pipeAgentUIStreamToResponse utility. ---- - -# `pipeAgentUIStreamToResponse` - -The `pipeAgentUIStreamToResponse` function runs an [Agent](/docs/reference/ai-sdk-core/agent) and streams the resulting UI message output directly to a Node.js [`ServerResponse`](https://nodejs.org/api/http.html#class-httpserverresponse) object. This is ideal for building real-time streaming API endpoints (for chat, tool use, etc.) in Node.js-based frameworks like Express, Hono, or custom Node servers. - -## Import - - - -## Usage - -```ts -import { pipeAgentUIStreamToResponse } from 'ai'; -import { MyAgent } from './agent'; - -export async function handler(req, res) { - const { messages } = JSON.parse(req.body); - - await pipeAgentUIStreamToResponse({ - response: res, // Node.js ServerResponse - agent: MyAgent, - uiMessages: messages, // Required: array of input UI messages - // abortSignal: optional AbortSignal for cancellation - // status: 200, - // headers: { ... }, - // ...other optional UI message stream options - }); -} -``` - -## Parameters - - - -## Returns - -A `Promise`. The function completes when the UI message stream has been fully sent to the provided ServerResponse. - -## Example: Express Route Handler - -```ts -import { pipeAgentUIStreamToResponse } from 'ai'; -import { openaiWebSearchAgent } from './openai-web-search-agent'; - -app.post('/chat', async (req, res) => { - // Use req.body.messages as input UI messages - await pipeAgentUIStreamToResponse({ - response: res, - agent: openaiWebSearchAgent, - uiMessages: req.body.messages, - // abortSignal: yourController.signal - // status: 200, - // headers: { ... }, - // ...more options - }); -}); -``` - -## How It Works - -1. **Runs the Agent:** Calls the agent’s `.stream` method with the provided UI messages and options, converting them into model messages as needed. -2. **Streams UI Message Output:** Pipes the agent output as a UI message stream to the `ServerResponse`, sending data via streaming HTTP responses (including appropriate headers). -3. **Abort Signal Handling:** If `abortSignal` is supplied, streaming is cancelled as soon as the signal is triggered (such as on client disconnect). -4. **No Response Return:** Unlike Edge/serverless APIs that return a `Response`, this function writes bytes directly to the ServerResponse and does not return a response object. - -## Notes - -- **Abort Handling:** For best robustness, use an `AbortSignal` (for example, wired to Express/Hono client disconnects) to ensure quick cancellation of agent computation and streaming. -- **Node.js Only:** Only works with Node.js [ServerResponse](https://nodejs.org/api/http.html#class-httpserverresponse) objects (e.g., in Express, Hono’s node adapter, etc.), not Edge/serverless/web Response APIs. -- **Streaming Support:** Make sure your client (and any proxies) correctly support streaming HTTP responses for full effect. -- **Parameter Names:** The property for input messages is `uiMessages` (not `messages`) for consistency with SDK agent utilities. - -## See Also - -- [`createAgentUIStreamResponse`](/docs/reference/ai-sdk-core/create-agent-ui-stream-response) -- [`Agent`](/docs/reference/ai-sdk-core/agent) -- [`UIMessage`](/docs/reference/ai-sdk-core/ui-message) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/20-tool.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/20-tool.mdx deleted file mode 100644 index c402d81c0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/20-tool.mdx +++ /dev/null @@ -1,209 +0,0 @@ ---- -title: tool -description: Helper function for tool type inference ---- - -# `tool()` - -Tool is a helper function that infers the tool input for its `execute` method. - -It does not have any runtime behavior, but it helps TypeScript infer the types of the input for the `execute` method. - -Without this helper function, TypeScript is unable to connect the `inputSchema` property to the `execute` method, -and the argument types of `execute` cannot be inferred. - -```ts highlight={"1,4,9,10"} -import { tool } from 'ai'; -import { z } from 'zod'; - -export const weatherTool = tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ - location: z.string().describe('The location to get the weather for'), - }), - // location below is inferred to be a string: - execute: async ({ location }) => ({ - location, - temperature: 72 + Math.floor(Math.random() * 21) - 10, - }), -}); -``` - -## Import - - - -## API Signature - -### Parameters - - boolean | Promise)', - description: - 'Whether the tool needs user approval before execution. Can be a boolean or a function that receives the tool arguments and returns a boolean.', - }, - { - name: 'inputSchema', - type: 'Zod Schema | JSON Schema', - description: - 'The schema of the input that the tool expects. The language model will use this to generate the input. It is also used to validate the output of the language model. Use descriptions to make the input understandable for the language model. You can either pass in a Zod schema or a JSON schema (using the `jsonSchema` function).', - }, - { - name: 'inputExamples', - isOptional: true, - type: 'Array<{ input: INPUT }>', - description: - 'An optional list of input examples that show the language model what the input should look like.', - }, - { - name: 'strict', - isOptional: true, - type: 'boolean', - description: - 'Strict mode setting for the tool. Providers that support strict mode will use this setting to determine how the input should be generated. Strict mode will always produce valid inputs, but it might limit what input schemas are supported.', - }, - { - name: 'execute', - isOptional: true, - type: 'async (input: INPUT, options: ToolExecutionOptions) => RESULT | Promise | AsyncIterable', - description: - 'An async function that is called with the arguments from the tool call and produces a result or a results iterable. If an iterable is provided, all results but the last one are considered preliminary. If not provided, the tool will not be executed automatically.', - properties: [ - { - type: 'ToolExecutionOptions', - parameters: [ - { - name: 'toolCallId', - type: 'string', - description: - 'The ID of the tool call. You can use it e.g. when sending tool-call related information with stream data.', - }, - { - name: 'messages', - type: 'ModelMessage[]', - description: - 'Messages that were sent to the language model to initiate the response that contained the tool call. The messages do not include the system prompt nor the assistant response that contained the tool call.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - isOptional: true, - description: - 'An optional abort signal that indicates that the overall operation should be aborted.', - }, - { - name: 'experimental_context', - type: 'unknown', - isOptional: true, - description: - 'Context that is passed into tool execution. Experimental (can break in patch releases).', - }, - ], - }, - ], - }, - { - name: 'outputSchema', - isOptional: true, - type: 'Zod Schema | JSON Schema', - description: - 'The schema of the output that the tool produces. Used for type inference.', - }, - { - name: 'toModelOutput', - isOptional: true, - type: '({toolCallId: string; input: INPUT; output: OUTPUT}) => ToolResultOutput | PromiseLike', - description: - 'Optional conversion function that maps the tool result to an output that can be used by the language model. If not provided, the tool result will be sent as a JSON object.', - }, - { - name: 'onInputStart', - isOptional: true, - type: '(options: ToolExecutionOptions) => void | PromiseLike', - description: - 'Optional function that is called when the argument streaming starts. Only called when the tool is used in a streaming context.', - }, - { - name: 'onInputDelta', - isOptional: true, - type: '(options: { inputTextDelta: string } & ToolExecutionOptions) => void | PromiseLike', - description: - 'Optional function that is called when an argument streaming delta is available. Only called when the tool is used in a streaming context.', - }, - { - name: 'onInputAvailable', - isOptional: true, - type: '(options: { input: INPUT } & ToolExecutionOptions) => void | PromiseLike', - description: - 'Optional function that is called when a tool call can be started, even if the execute function is not provided.', - }, - { - name: 'providerOptions', - isOptional: true, - type: 'ProviderOptions', - description: - 'Additional provider-specific metadata. They are passed through to the provider from the AI SDK and enable provider-specific functionality that can be fully encapsulated in the provider.', - }, - { - name: 'type', - isOptional: true, - type: "'function' | 'provider-defined'", - description: - 'The type of the tool. Defaults to "function" for regular tools. Use "provider-defined" for provider-specific tools.', - }, - { - name: 'id', - isOptional: true, - type: 'string', - description: - 'The ID of the tool for provider-defined tools. Should follow the format `.`. Required when type is "provider-defined".', - }, - { - name: 'name', - isOptional: true, - type: 'string', - description: - 'The name of the tool that the user must use in the tool set. Required when type is "provider-defined".', - }, - { - name: 'args', - isOptional: true, - type: 'Record', - description: - 'The arguments for configuring the tool. Must match the expected arguments defined by the provider for this tool. Required when type is "provider-defined".', - }, - ], - }, - ], - }, - ]} -/> - -### Returns - -The tool that was passed in. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/22-dynamic-tool.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/22-dynamic-tool.mdx deleted file mode 100644 index 012ce20b8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/22-dynamic-tool.mdx +++ /dev/null @@ -1,223 +0,0 @@ ---- -title: dynamicTool -description: Helper function for creating dynamic tools with unknown types ---- - -# `dynamicTool()` - -The `dynamicTool` function creates tools where the input and output types are not known at compile time. This is useful for scenarios such as: - -- MCP (Model Context Protocol) tools without schemas -- User-defined functions loaded at runtime -- Tools loaded from external sources or databases -- Dynamic tool generation based on user input - -Unlike the regular `tool` function, `dynamicTool` accepts and returns `unknown` types, allowing you to work with tools that have runtime-determined schemas. - -```ts highlight={"1,4,9,10,11"} -import { dynamicTool } from 'ai'; -import { z } from 'zod'; - -export const customTool = dynamicTool({ - description: 'Execute a custom user-defined function', - inputSchema: z.object({}), - // input is typed as 'unknown' - execute: async input => { - const { action, parameters } = input as any; - - // Execute your dynamic logic - return { - result: `Executed ${action} with ${JSON.stringify(parameters)}`, - }; - }, -}); -``` - -## Import - - - -## API Signature - -### Parameters - - boolean | Promise)', - description: - 'Whether the tool needs user approval before execution. Can be a boolean or a function that receives the tool arguments and returns a boolean.' - }, - { - name: 'inputSchema', - type: 'FlexibleSchema', - description: - 'The schema of the input that the tool expects. While the type is unknown, a schema is still required for validation. You can use Zod schemas with z.unknown() or z.any() for fully dynamic inputs.' - }, - { - name: 'execute', - type: 'ToolExecuteFunction', - description: - 'An async function that is called with the arguments from the tool call. The input is typed as unknown and must be validated/cast at runtime.', - properties: [ - { - type: "ToolExecutionOptions", - parameters: [ - { - name: 'toolCallId', - type: 'string', - description: 'The ID of the tool call.', - }, - { - name: "messages", - type: "ModelMessage[]", - description: "Messages that were sent to the language model." - }, - { - name: "abortSignal", - type: "AbortSignal", - isOptional: true, - description: "An optional abort signal." - }, - { - name: "experimental_context", - type: "unknown", - isOptional: true, - description: "Context that is passed into tool execution. Experimental (can break in patch releases)." - } - ] - } - ] - }, - { - name: 'outputSchema', - isOptional: true, - type: 'Zod Schema | JSON Schema', - description: - 'The schema of the output that the tool produces. Used for validation and type inference.' - }, - { - name: 'toModelOutput', - isOptional: true, - type: '({toolCallId: string; input: unknown; output: unknown}) => ToolResultOutput | PromiseLike', - description: 'Optional conversion function that maps the tool result to an output that can be used by the language model.' - }, - { - name: 'onInputStart', - isOptional: true, - type: '(options: ToolExecutionOptions) => void | PromiseLike', - description: - 'Optional function that is called when the argument streaming starts. Only called when the tool is used in a streaming context.' - }, - { - name: 'onInputDelta', - isOptional: true, - type: '(options: { inputTextDelta: string } & ToolExecutionOptions) => void | PromiseLike', - description: - 'Optional function that is called when an argument streaming delta is available. Only called when the tool is used in a streaming context.' - }, - { - name: 'onInputAvailable', - isOptional: true, - type: '(options: { input: unknown } & ToolExecutionOptions) => void | PromiseLike', - description: - 'Optional function that is called when a tool call can be started, even if the execute function is not provided.' - }, - { - name: 'providerOptions', - isOptional: true, - type: 'ProviderOptions', - description: 'Additional provider-specific metadata.' - } - ] - } - ] - } - -]} -/> - -### Returns - -A `Tool` with `type: 'dynamic'` that can be used with `generateText`, `streamText`, and other AI SDK functions. - -## Type-Safe Usage - -When using dynamic tools alongside static tools, you need to check the `dynamic` flag for proper type narrowing: - -```ts -const result = await generateText({ - model: __MODEL__, - tools: { - // Static tool with known types - weather: weatherTool, - // Dynamic tool with unknown types - custom: dynamicTool({ - /* ... */ - }), - }, - onStepFinish: ({ toolCalls, toolResults }) => { - for (const toolCall of toolCalls) { - if (toolCall.dynamic) { - // Dynamic tool: input/output are 'unknown' - console.log('Dynamic tool:', toolCall.toolName); - console.log('Input:', toolCall.input); - continue; - } - - // Static tools have full type inference - switch (toolCall.toolName) { - case 'weather': - // TypeScript knows the exact types - console.log(toolCall.input.location); // string - break; - } - } - }, -}); -``` - -## Usage with `useChat` - -When used with useChat (`UIMessage` format), dynamic tools appear as `dynamic-tool` parts: - -```tsx -{ - message.parts.map(part => { - switch (part.type) { - case 'dynamic-tool': - return ( -
-

Tool: {part.toolName}

-
{JSON.stringify(part.input, null, 2)}
-
- ); - // ... handle other part types - } - }); -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/23-create-mcp-client.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/23-create-mcp-client.mdx deleted file mode 100644 index 2d9009d20..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/23-create-mcp-client.mdx +++ /dev/null @@ -1,423 +0,0 @@ ---- -title: createMCPClient -description: Create a client for connecting to MCP servers ---- - -# `createMCPClient()` - -Creates a lightweight Model Context Protocol (MCP) client that connects to an MCP server. The client provides: - -- **Tools**: Automatic conversion between MCP tools and AI SDK tools -- **Resources**: Methods to list, read, and discover resource templates from MCP servers -- **Prompts**: Methods to list available prompts and retrieve prompt messages -- **Elicitation**: Support for handling server requests for additional input during tool execution - -It currently does not support accepting notifications from an MCP server, and custom configuration of the client. - -## Import - - - -## API Signature - -### Parameters - - Promise', - description: 'A method that starts the transport', - }, - { - name: 'send', - type: '(message: JSONRPCMessage) => Promise', - description: - 'A method that sends a message through the transport', - }, - { - name: 'close', - type: '() => Promise', - description: 'A method that closes the transport', - }, - { - name: 'onclose', - type: '() => void', - description: - 'A method that is called when the transport is closed', - }, - { - name: 'onerror', - type: '(error: Error) => void', - description: - 'A method that is called when the transport encounters an error', - }, - { - name: 'onmessage', - type: '(message: JSONRPCMessage) => void', - description: - 'A method that is called when the transport receives a message', - }, - ], - }, - { - type: 'MCPTransportConfig', - parameters: [ - { - name: 'type', - type: "'sse' | 'http", - description: 'Use Server-Sent Events for communication', - }, - { - name: 'url', - type: 'string', - description: 'URL of the MCP server', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: - 'Additional HTTP headers to be sent with requests.', - }, - { - name: 'authProvider', - type: 'OAuthClientProvider', - isOptional: true, - description: - 'Optional OAuth provider for authorization to access protected remote MCP servers.', - }, - { - name: 'redirect', - type: "'follow' | 'error'", - isOptional: true, - description: - "Controls how HTTP redirects are handled for transport requests. Set to 'error' to reject any redirect response, preventing servers from redirecting requests to unintended hosts. Defaults to 'follow'.", - }, - ], - }, - ], - }, - { - name: 'name', - type: 'string', - isOptional: true, - description: 'Client name. Defaults to "ai-sdk-mcp-client"', - }, - { - name: 'version', - type: 'string', - isOptional: true, - description: 'Client version. Defaults to "1.0.0"', - }, - { - name: 'onUncaughtError', - type: '(error: unknown) => void', - isOptional: true, - description: 'Handler for uncaught errors', - }, - { - name: 'capabilities', - type: 'ClientCapabilities', - isOptional: true, - description: - 'Optional client capabilities to advertise during initialization. For example, set { elicitation: {} } to enable handling elicitation requests from the server.', - }, - ], - }, - ], - }, - ]} -/> - -### Returns - -Returns a Promise that resolves to an `MCPClient` with the following methods: - - Promise>`, - description: 'Gets the tools available from the MCP server.', - properties: [ - { - type: 'options', - parameters: [ - { - name: 'schemas', - type: 'TOOL_SCHEMAS', - isOptional: true, - description: - 'Schema definitions for compile-time type checking. When not provided, schemas are inferred from the server. Each tool schema can include inputSchema for typed inputs, and optionally outputSchema for typed outputs when the server returns structuredContent.', - }, - ], - }, - { - type: 'TOOL_SCHEMAS', - parameters: [ - { - name: 'inputSchema', - type: 'FlexibleSchema', - description: - 'Zod schema or JSON schema defining the expected input parameters for the tool.', - }, - { - name: 'outputSchema', - type: 'FlexibleSchema', - isOptional: true, - description: - 'Zod schema or JSON schema defining the expected output structure. When provided, the client extracts and validates structuredContent from tool results, giving you typed outputs.', - }, - ], - }, - ], - }, - { - name: 'listResources', - type: `async (options?: { - params?: PaginatedRequest['params']; - options?: RequestOptions; - }) => Promise`, - description: 'Lists all available resources from the MCP server.', - properties: [ - { - type: 'options', - parameters: [ - { - name: 'params', - type: "PaginatedRequest['params']", - isOptional: true, - description: 'Optional pagination parameters including cursor.', - }, - { - name: 'options', - type: 'RequestOptions', - isOptional: true, - description: - 'Optional request options including signal and timeout.', - }, - ], - }, - ], - }, - { - name: 'readResource', - type: `async (args: { - uri: string; - options?: RequestOptions; - }) => Promise`, - description: 'Reads the contents of a specific resource by URI.', - properties: [ - { - type: 'args', - parameters: [ - { - name: 'uri', - type: 'string', - description: 'The URI of the resource to read.', - }, - { - name: 'options', - type: 'RequestOptions', - isOptional: true, - description: - 'Optional request options including signal and timeout.', - }, - ], - }, - ], - }, - { - name: 'listResourceTemplates', - type: `async (options?: { - options?: RequestOptions; - }) => Promise`, - description: - 'Lists all available resource templates from the MCP server.', - properties: [ - { - type: 'options', - parameters: [ - { - name: 'options', - type: 'RequestOptions', - isOptional: true, - description: - 'Optional request options including signal and timeout.', - }, - ], - }, - ], - }, - { - name: 'experimental_listPrompts', - type: `async (options?: { - params?: PaginatedRequest['params']; - options?: RequestOptions; - }) => Promise`, - description: - 'Lists available prompts from the MCP server. This method is experimental and may change in the future.', - properties: [ - { - type: 'options', - parameters: [ - { - name: 'params', - type: "PaginatedRequest['params']", - isOptional: true, - description: 'Optional pagination parameters including cursor.', - }, - { - name: 'options', - type: 'RequestOptions', - isOptional: true, - description: - 'Optional request options including signal and timeout.', - }, - ], - }, - ], - }, - { - name: 'experimental_getPrompt', - type: `async (args: { - name: string; - arguments?: Record; - options?: RequestOptions; - }) => Promise`, - description: - 'Retrieves a prompt by name, optionally passing arguments. This method is experimental and may change in the future.', - properties: [ - { - type: 'args', - parameters: [ - { - name: 'name', - type: 'string', - description: 'Prompt name to retrieve.', - }, - { - name: 'arguments', - type: 'Record', - isOptional: true, - description: 'Optional arguments to fill into the prompt.', - }, - { - name: 'options', - type: 'RequestOptions', - isOptional: true, - description: - 'Optional request options including signal and timeout.', - }, - ], - }, - ], - }, - { - name: 'onElicitationRequest', - type: `( - schema: typeof ElicitationRequestSchema, - handler: (request: ElicitationRequest) => Promise | ElicitResult - ) => void`, - description: - 'Registers a handler for elicitation requests from the MCP server. The handler receives requests when the server needs additional input during tool execution.', - properties: [ - { - type: 'parameters', - parameters: [ - { - name: 'schema', - type: 'typeof ElicitationRequestSchema', - description: - 'The schema to validate requests against. Must be ElicitationRequestSchema.', - }, - { - name: 'handler', - type: '(request: ElicitationRequest) => Promise | ElicitResult', - description: - 'A function that handles the elicitation request. The request contains a message and requestedSchema. The handler must return an object with an action ("accept", "decline", or "cancel") and optionally content when accepting.', - }, - ], - }, - ], - }, - { - name: 'close', - type: '() => Promise', - description: - 'Closes the connection to the MCP server and cleans up resources.', - }, - ]} -/> - -## Example - -```typescript -import { createMCPClient } from '@ai-sdk/mcp'; -import { generateText } from 'ai'; -import { Experimental_StdioMCPTransport } from '@ai-sdk/mcp/mcp-stdio'; - -let client; - -try { - client = await createMCPClient({ - transport: new Experimental_StdioMCPTransport({ - command: 'node server.js', - }), - }); - - const tools = await client.tools(); - - const response = await generateText({ - model: __MODEL__, - tools, - messages: [{ role: 'user', content: 'Query the data' }], - }); - - console.log(response); -} catch (error) { - console.error('Error:', error); -} finally { - // ensure the client is closed even if an error occurs - if (client) { - await client.close(); - } -} -``` - -## Error Handling - -The client throws `MCPClientError` for: - -- Client initialization failures -- Protocol version mismatches -- Missing server capabilities -- Connection failures - -For tool execution, errors are propagated as `CallToolError` errors. - -For unknown errors, the client exposes an `onUncaughtError` callback that can be used to manually log or handle errors that are not covered by known error types. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/24-mcp-stdio-transport.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/24-mcp-stdio-transport.mdx deleted file mode 100644 index 63dc5b0db..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/24-mcp-stdio-transport.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Experimental_StdioMCPTransport -description: Create a transport for Model Context Protocol (MCP) clients to communicate with MCP servers using standard input and output streams ---- - -# `Experimental_StdioMCPTransport` - -Creates a transport for Model Context Protocol (MCP) clients to communicate with MCP servers using standard input and output streams. This transport is only supported in Node.js environments. - -This feature is experimental and may change or be removed in the future. - -## Import - - - -## API Signature - -### Parameters - -', - isOptional: true, - description: - 'The environment variables to set for the MCP server.', - }, - { - name: 'stderr', - type: 'IOType | Stream | number', - isOptional: true, - description: "The stream to write the MCP server's stderr to.", - }, - { - name: 'cwd', - type: 'string', - isOptional: true, - description: 'The current working directory for the MCP server.', - }, - ], - }, - ], - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/25-json-schema.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/25-json-schema.mdx deleted file mode 100644 index 75f9e11f6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/25-json-schema.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: jsonSchema -description: Helper function for creating JSON schemas ---- - -# `jsonSchema()` - -`jsonSchema` is a helper function that creates a JSON schema object that is compatible with the AI SDK. -It takes the JSON schema and an optional validation function as inputs, and can be typed. - -You can use it to [generate structured data](/docs/ai-sdk-core/generating-structured-data) and in [tools](/docs/ai-sdk-core/tools-and-tool-calling). - -`jsonSchema` is an alternative to using Zod schemas that provides you with flexibility in dynamic situations -(e.g. when using OpenAPI definitions) or for using other validation libraries. - -```ts -import { jsonSchema } from 'ai'; - -const mySchema = jsonSchema<{ - recipe: { - name: string; - ingredients: { name: string; amount: string }[]; - steps: string[]; - }; -}>({ - type: 'object', - properties: { - recipe: { - type: 'object', - properties: { - name: { type: 'string' }, - ingredients: { - type: 'array', - items: { - type: 'object', - properties: { - name: { type: 'string' }, - amount: { type: 'string' }, - }, - required: ['name', 'amount'], - }, - }, - steps: { - type: 'array', - items: { type: 'string' }, - }, - }, - required: ['name', 'ingredients', 'steps'], - }, - }, - required: ['recipe'], -}); -``` - -## Import - - - -## API Signature - -### Parameters - - { success: true; value: OBJECT } | { success: false; error: Error };', - description: - 'A function that validates the value against the JSON schema. If the value is valid, the function should return an object with a `success` property set to `true` and a `value` property set to the validated value. If the value is invalid, the function should return an object with a `success` property set to `false` and an `error` property set to the error.', - }, - ], - }, - ], - }, - ]} -/> - -### Returns - -A JSON schema object that is compatible with the AI SDK. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/26-zod-schema.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/26-zod-schema.mdx deleted file mode 100644 index 5293083d0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/26-zod-schema.mdx +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: zodSchema -description: Helper function for creating Zod schemas ---- - -# `zodSchema()` - -`zodSchema` is a helper function that converts a Zod schema into a JSON schema object that is compatible with the AI SDK. -It takes a Zod schema and optional configuration as inputs, and returns a typed schema. - -You can use it to [generate structured data](/docs/ai-sdk-core/generating-structured-data) and in [tools](/docs/ai-sdk-core/tools-and-tool-calling). - - - You can also pass Zod objects directly to the AI SDK functions. Internally, - the AI SDK will convert the Zod schema to a JSON schema using `zodSchema()`. - However, if you want to specify options such as `useReferences`, you can pass - the `zodSchema()` helper function instead. - - - - When using `.meta()` or `.describe()` to add metadata to your Zod schemas, - make sure these methods are called **at the end** of the schema chain. - - metadata is attached to a specific schema - instance, and most schema methods (`.min()`, `.optional()`, `.extend()`, etc.) - return a new schema instance that does not inherit metadata from the previous one. - Due to Zod's immutability, metadata is only included in the JSON schema output - if `.meta()` or `.describe()` is the last method in the chain. - -```ts -// ❌ Metadata will be lost - .min() returns a new instance without metadata -z.string().meta({ describe: 'first name' }).min(1); - -// ✅ Metadata is preserved - .meta() is the final method -z.string().min(1).meta({ describe: 'first name' }); -``` - - - -## Example with recursive schemas - -```ts -import { zodSchema } from 'ai'; -import { z } from 'zod'; - -// Define a base category schema -const baseCategorySchema = z.object({ - name: z.string(), -}); - -// Define the recursive Category type -type Category = z.infer & { - subcategories: Category[]; -}; - -// Create the recursive schema using z.lazy -const categorySchema: z.ZodType = baseCategorySchema.extend({ - subcategories: z.lazy(() => categorySchema.array()), -}); - -// Create the final schema with useReferences enabled for recursive support -const mySchema = zodSchema( - z.object({ - category: categorySchema, - }), - { useReferences: true }, -); -``` - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - -A Schema object that is compatible with the AI SDK, containing both the JSON schema representation and validation functionality. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/27-valibot-schema.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/27-valibot-schema.mdx deleted file mode 100644 index 6a90e144b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/27-valibot-schema.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: valibotSchema -description: Helper function for creating Valibot schemas ---- - -# `valibotSchema()` - -`valibotSchema` is a helper function that converts a Valibot schema into a JSON schema object -that is compatible with the AI SDK. -It takes a Valibot schema as input, and returns a typed schema. - -You can use it to [generate structured data](/docs/ai-sdk-core/generating-structured-data) and -in [tools](/docs/ai-sdk-core/tools-and-tool-calling). - -## Example - -```ts -import { valibotSchema } from '@ai-sdk/valibot'; -import { object, string, array } from 'valibot'; - -const recipeSchema = valibotSchema( - object({ - name: string(), - ingredients: array( - object({ - name: string(), - amount: string(), - }), - ), - steps: array(string()), - }), -); -``` - -## Import - - - -## API Signature - -### Parameters - -', - description: 'The Valibot schema definition.', - }, - ]} -/> - -### Returns - -A Schema object that is compatible with the AI SDK, containing both the JSON schema representation and validation functionality. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/28-output.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/28-output.mdx deleted file mode 100644 index d06cf473e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/28-output.mdx +++ /dev/null @@ -1,342 +0,0 @@ ---- -title: Output -description: API Reference for Output. ---- - -# `Output` - -The `Output` object provides output specifications for structured data generation with [`generateText`](/docs/reference/ai-sdk-core/generate-text) and [`streamText`](/docs/reference/ai-sdk-core/stream-text). It allows you to specify the expected shape of the generated data and handles validation automatically. - -```ts -import { generateText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const { output } = await generateText({ - model: __MODEL__, - output: Output.object({ - schema: z.object({ - name: z.string(), - age: z.number(), - }), - }), - prompt: 'Generate a user profile.', -}); -``` - -## Import - - - -## Output Types - -### `Output.text()` - -Output specification for plain text generation. This is the default behavior when no `output` is specified. - -```ts -import { generateText, Output } from 'ai'; - -const { output } = await generateText({ - model: yourModel, - output: Output.text(), - prompt: 'Tell me a joke.', -}); -// output is a string -``` - -#### Parameters - -No parameters required. - -#### Returns - -An `Output` specification that generates plain text without schema validation. - ---- - -### `Output.object()` - -Output specification for typed object generation using schemas. The output is validated against the provided schema to ensure type safety. - -```ts -import { generateText, Output } from 'ai'; -import { z } from 'zod'; - -const { output } = await generateText({ - model: yourModel, - output: Output.object({ - schema: z.object({ - name: z.string(), - age: z.number().nullable(), - labels: z.array(z.string()), - }), - }), - prompt: 'Generate information for a test user.', -}); -// output matches the schema type -``` - -#### Parameters - -', - description: - 'The schema that defines the structure of the object to generate. Supports Zod schemas, Standard JSON schemas, and custom JSON schemas.', - }, - { - name: 'name', - type: 'string', - isOptional: true, - description: - 'Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name.', - }, - { - name: 'description', - type: 'string', - isOptional: true, - description: - 'Optional description of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema description.', - }, - ]} -/> - -#### Returns - -An `Output>` specification where: - -- Complete output is fully validated against the schema -- Partial output (during streaming) is a deep partial version of the schema type - - - Partial outputs streamed via `streamText` cannot be validated against your - provided schema, as incomplete data may not yet conform to the expected - structure. - - ---- - -### `Output.array()` - -Output specification for generating arrays of typed elements. Each element is validated against the provided element schema. - -```ts -import { generateText, Output } from 'ai'; -import { z } from 'zod'; - -const { output } = await generateText({ - model: yourModel, - output: Output.array({ - element: z.object({ - location: z.string(), - temperature: z.number(), - condition: z.string(), - }), - }), - prompt: 'List the weather for San Francisco and Paris.', -}); -// output is an array of weather objects -``` - -#### Parameters - -', - description: - 'The schema that defines the structure of each array element. Supports Zod schemas, Valibot schemas, or JSON schemas.', - }, - { - name: 'name', - type: 'string', - isOptional: true, - description: - 'Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name.', - }, - { - name: 'description', - type: 'string', - isOptional: true, - description: - 'Optional description of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema description.', - }, - ]} -/> - -#### Returns - -An `Output, Array>` specification where: - -- Complete output is an array with all elements validated -- Partial output contains only fully validated elements (incomplete elements are excluded) - -#### Streaming with `elementStream` - -When using `streamText` with `Output.array()`, you can iterate over elements as they are generated using `elementStream`: - -```ts -import { streamText, Output } from 'ai'; -import { z } from 'zod'; - -const { elementStream } = streamText({ - model: yourModel, - output: Output.array({ - element: z.object({ - name: z.string(), - class: z.string(), - description: z.string(), - }), - }), - prompt: 'Generate 3 hero descriptions for a fantasy role playing game.', -}); - -for await (const hero of elementStream) { - console.log(hero); // Each hero is complete and validated -} -``` - - - Each element emitted by `elementStream` is complete and validated against your - element schema, ensuring type safety for each item as it is generated. - - ---- - -### `Output.choice()` - -Output specification for selecting from a predefined set of string options. Useful for classification tasks or fixed-enum answers. - -```ts -import { generateText, Output } from 'ai'; - -const { output } = await generateText({ - model: yourModel, - output: Output.choice({ - options: ['sunny', 'rainy', 'snowy'] as const, - }), - prompt: 'Is the weather sunny, rainy, or snowy today?', -}); -// output is 'sunny' | 'rainy' | 'snowy' -``` - -#### Parameters - -', - description: - 'An array of string options that the model can choose from. The output will be exactly one of these values.', - }, - { - name: 'name', - type: 'string', - isOptional: true, - description: - 'Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name.', - }, - { - name: 'description', - type: 'string', - isOptional: true, - description: - 'Optional description of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema description.', - }, - ]} -/> - -#### Returns - -An `Output` specification where: - -- Complete output is validated to be exactly one of the provided options - ---- - -### `Output.json()` - -Output specification for unstructured JSON generation. Use this when you want to generate arbitrary JSON without enforcing a specific schema. - -```ts -import { generateText, Output } from 'ai'; - -const { output } = await generateText({ - model: yourModel, - output: Output.json(), - prompt: - 'For each city, return the current temperature and weather condition as a JSON object.', -}); -// output is any valid JSON value -``` - -#### Parameters - - - -#### Returns - -An `Output` specification that: - -- Validates that the output is valid JSON -- Does not enforce any specific structure - - - With `Output.json()`, the AI SDK only checks that the response is valid JSON; - it doesn't validate the structure or types of the values. If you need schema - validation, use `Output.object()` or `Output.array()` instead. - - -## Error Handling - -When `generateText` with structured output cannot generate a valid object, it throws a [`NoObjectGeneratedError`](/docs/reference/ai-sdk-errors/ai-no-object-generated-error). - -```ts -import { generateText, Output, NoObjectGeneratedError } from 'ai'; - -try { - await generateText({ - model: yourModel, - output: Output.object({ schema }), - prompt: 'Generate a user profile.', - }); -} catch (error) { - if (NoObjectGeneratedError.isInstance(error)) { - console.log('NoObjectGeneratedError'); - console.log('Cause:', error.cause); - console.log('Text:', error.text); - console.log('Response:', error.response); - console.log('Usage:', error.usage); - } -} -``` - -## See also - -- [Generating Structured Data](/docs/ai-sdk-core/generating-structured-data) -- [`generateText()`](/docs/reference/ai-sdk-core/generate-text) -- [`streamText()`](/docs/reference/ai-sdk-core/stream-text) -- [`zod-schema`](/docs/reference/ai-sdk-core/zod-schema) -- [`json-schema`](/docs/reference/ai-sdk-core/json-schema) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/30-model-message.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/30-model-message.mdx deleted file mode 100644 index 8e108ffe6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/30-model-message.mdx +++ /dev/null @@ -1,415 +0,0 @@ ---- -title: ModelMessage -description: Message types for AI SDK Core (API Reference) ---- - -# `ModelMessage` - -`ModelMessage` represents the fundamental message structure used with AI SDK Core functions. -It encompasses various message types that can be used in the `messages` field of any AI SDK Core functions. - -You can access the Zod schema for `ModelMessage` with the `modelMessageSchema` export. - -## `ModelMessage` Types - -### `SystemModelMessage` - -A system message that can contain system information. - -```typescript -type SystemModelMessage = { - role: 'system'; - content: string; -}; -``` - -You can access the Zod schema for `SystemModelMessage` with the `systemModelMessageSchema` export. - - - Using the "system" property instead of a system message is recommended to - enhance resilience against prompt injection attacks. - - -### `UserModelMessage` - -A user message that can contain text or a combination of text, images, and files. - -```typescript -type UserModelMessage = { - role: 'user'; - content: UserContent; -}; - -type UserContent = string | Array; -``` - -You can access the Zod schema for `UserModelMessage` with the `userModelMessageSchema` export. - -### `AssistantModelMessage` - -An assistant message that can contain text, tool calls, or a combination of both. - -```typescript -type AssistantModelMessage = { - role: 'assistant'; - content: AssistantContent; -}; - -type AssistantContent = string | Array; -``` - -You can access the Zod schema for `AssistantModelMessage` with the `assistantModelMessageSchema` export. - -### `ToolModelMessage` - -A tool message that contains the result of one or more tool calls. - -```typescript -type ToolModelMessage = { - role: 'tool'; - content: ToolContent; -}; - -type ToolContent = Array; -``` - -You can access the Zod schema for `ToolModelMessage` with the `toolModelMessageSchema` export. - -## `ModelMessage` Parts - -### `TextPart` - -Represents a text content part of a prompt. It contains a string of text. - -```typescript -export interface TextPart { - type: 'text'; - /** - * The text content. - */ - text: string; -} -``` - -### `ImagePart` - -Represents an image part in a user message. - -```typescript -export interface ImagePart { - type: 'image'; - - /** - * Image data. Can either be: - * - data: a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer - * - URL: a URL that points to the image - */ - image: DataContent | URL; - - /** - * Optional IANA media type of the image. - * We recommend leaving this out as it will be detected automatically. - */ - mediaType?: string; -} -``` - -### `FilePart` - -Represents a file part in a user message. - -```typescript -export interface FilePart { - type: 'file'; - - /** - * File data. Can either be: - * - data: a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer - * - URL: a URL that points to the file - */ - data: DataContent | URL; - - /** - * Optional filename of the file. - */ - filename?: string; - - /** - * IANA media type of the file. - */ - mediaType: string; -} -``` - -### `ToolCallPart` - -Represents a tool call content part of a prompt, typically generated by the AI model. - -```typescript -export interface ToolCallPart { - type: 'tool-call'; - - /** - * ID of the tool call. This ID is used to match the tool call with the tool result. - */ - toolCallId: string; - - /** - * Name of the tool that is being called. - */ - toolName: string; - - /** - * Arguments of the tool call. This is a JSON-serializable object that matches the tool's input schema. - */ - args: unknown; -} -``` - -### `ToolResultPart` - -Represents the result of a tool call in a tool message. - -```typescript -export interface ToolResultPart { - type: 'tool-result'; - - /** - * ID of the tool call that this result is associated with. - */ - toolCallId: string; - - /** - * Name of the tool that generated this result. - */ - toolName: string; - - /** - * Result of the tool call. This is a JSON-serializable object. - */ - output: LanguageModelV3ToolResultOutput; - - /** - Additional provider-specific metadata. They are passed through - to the provider from the AI SDK and enable provider-specific - functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; -} -``` - -### `LanguageModelV3ToolResultOutput` - -```ts -/** - * Output of a tool result. - */ -export type ToolResultOutput = - | { - /** - * Text tool output that should be directly sent to the API. - */ - type: 'text'; - value: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - type: 'json'; - value: JSONValue; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - /** - * Type when the user has denied the execution of the tool call. - */ - type: 'execution-denied'; - - /** - * Optional reason for the execution denial. - */ - reason?: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - type: 'error-text'; - value: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - type: 'error-json'; - value: JSONValue; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - type: 'content'; - value: Array< - | { - type: 'text'; - - /** -Text content. -*/ - text: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - /** - * @deprecated Use image-data or file-data instead. - */ - type: 'media'; - data: string; - mediaType: string; - } - | { - type: 'file-data'; - - /** -Base-64 encoded media data. -*/ - data: string; - - /** -IANA media type. -@see https://www.iana.org/assignments/media-types/media-types.xhtml -*/ - mediaType: string; - - /** - * Optional filename of the file. - */ - filename?: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - type: 'file-url'; - - /** - * URL of the file. - */ - url: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - type: 'file-id'; - - /** - * ID of the file. - * - * If you use multiple providers, you need to - * specify the provider specific ids using - * the Record option. The key is the provider - * name, e.g. 'openai' or 'anthropic'. - */ - fileId: string | Record; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - /** - * Images that are referenced using base64 encoded data. - */ - type: 'image-data'; - - /** -Base-64 encoded image data. -*/ - data: string; - - /** -IANA media type. -@see https://www.iana.org/assignments/media-types/media-types.xhtml -*/ - mediaType: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - /** - * Images that are referenced using a URL. - */ - type: 'image-url'; - - /** - * URL of the image. - */ - url: string; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - /** - * Images that are referenced using a provider file id. - */ - type: 'image-file-id'; - - /** - * Image that is referenced using a provider file id. - * - * If you use multiple providers, you need to - * specify the provider specific ids using - * the Record option. The key is the provider - * name, e.g. 'openai' or 'anthropic'. - */ - fileId: string | Record; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - | { - /** - * Custom content part. This can be used to implement - * provider-specific content parts. - */ - type: 'custom'; - - /** - * Provider-specific options. - */ - providerOptions?: ProviderOptions; - } - >; - }; -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/31-ui-message.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/31-ui-message.mdx deleted file mode 100644 index a2e9fc956..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/31-ui-message.mdx +++ /dev/null @@ -1,246 +0,0 @@ ---- -title: UIMessage -description: API Reference for UIMessage ---- - -# `UIMessage` - -`UIMessage` serves as the source of truth for your application's state, representing the complete message history including metadata, data parts, and all contextual information. In contrast to `ModelMessage`, which represents the state or context passed to the model, `UIMessage` contains the full application state needed for UI rendering and client-side functionality. - -## Type Safety - -`UIMessage` is designed to be type-safe and accepts three generic parameters to ensure proper typing throughout your application: - -1. **`METADATA`** - Custom metadata type for additional message information -2. **`DATA_PARTS`** - Custom data part types for structured data components -3. **`TOOLS`** - Tool definitions for type-safe tool interactions - -## Creating Your Own UIMessage Type - -Here's an example of how to create a custom typed UIMessage for your application: - -```typescript -import { InferUITools, ToolSet, UIMessage, tool } from 'ai'; -import z from 'zod'; - -const metadataSchema = z.object({ - someMetadata: z.string().datetime(), -}); - -type MyMetadata = z.infer; - -const dataPartSchema = z.object({ - someDataPart: z.object({}), - anotherDataPart: z.object({}), -}); - -type MyDataPart = z.infer; - -const tools = { - someTool: tool({}), -} satisfies ToolSet; - -type MyTools = InferUITools; - -export type MyUIMessage = UIMessage; -``` - -## `UIMessage` Interface - -```typescript -interface UIMessage< - METADATA = unknown, - DATA_PARTS extends UIDataTypes = UIDataTypes, - TOOLS extends UITools = UITools, -> { - /** - * A unique identifier for the message. - */ - id: string; - - /** - * The role of the message. - */ - role: 'system' | 'user' | 'assistant'; - - /** - * The metadata of the message. - */ - metadata?: METADATA; - - /** - * The parts of the message. Use this for rendering the message in the UI. - */ - parts: Array>; -} -``` - -## `UIMessagePart` Types - -### `TextUIPart` - -A text part of a message. - -```typescript -type TextUIPart = { - type: 'text'; - /** - * The text content. - */ - text: string; - /** - * The state of the text part. - */ - state?: 'streaming' | 'done'; -}; -``` - -### `ReasoningUIPart` - -A reasoning part of a message. - -```typescript -type ReasoningUIPart = { - type: 'reasoning'; - /** - * The reasoning text. - */ - text: string; - /** - * The state of the reasoning part. - */ - state?: 'streaming' | 'done'; - /** - * The provider metadata. - */ - providerMetadata?: Record; -}; -``` - -### `ToolUIPart` - -A tool part of a message that represents tool invocations and their results. - - - The type is based on the name of the tool (e.g., `tool-someTool` for a tool - named `someTool`). - - -```typescript -type ToolUIPart = ValueOf<{ - [NAME in keyof TOOLS & string]: { - type: `tool-${NAME}`; - toolCallId: string; - } & ( - | { - state: 'input-streaming'; - input: DeepPartial | undefined; - providerExecuted?: boolean; - output?: never; - errorText?: never; - } - | { - state: 'input-available'; - input: TOOLS[NAME]['input']; - providerExecuted?: boolean; - output?: never; - errorText?: never; - } - | { - state: 'output-available'; - input: TOOLS[NAME]['input']; - output: TOOLS[NAME]['output']; - errorText?: never; - providerExecuted?: boolean; - } - | { - state: 'output-error'; - input: TOOLS[NAME]['input']; - output?: never; - errorText: string; - providerExecuted?: boolean; - } - ); -}>; -``` - -### `SourceUrlUIPart` - -A source URL part of a message. - -```typescript -type SourceUrlUIPart = { - type: 'source-url'; - sourceId: string; - url: string; - title?: string; - providerMetadata?: Record; -}; -``` - -### `SourceDocumentUIPart` - -A document source part of a message. - -```typescript -type SourceDocumentUIPart = { - type: 'source-document'; - sourceId: string; - mediaType: string; - title: string; - filename?: string; - providerMetadata?: Record; -}; -``` - -### `FileUIPart` - -A file part of a message. - -```typescript -type FileUIPart = { - type: 'file'; - /** - * IANA media type of the file. - */ - mediaType: string; - /** - * Optional filename of the file. - */ - filename?: string; - /** - * The URL of the file. - * It can either be a URL to a hosted file or a Data URL. - */ - url: string; -}; -``` - -### `DataUIPart` - -A data part of a message for custom data types. - - - The type is based on the name of the data part (e.g., `data-someDataPart` for - a data part named `someDataPart`). - - -```typescript -type DataUIPart = ValueOf<{ - [NAME in keyof DATA_TYPES & string]: { - type: `data-${NAME}`; - id?: string; - data: DATA_TYPES[NAME]; - }; -}>; -``` - -### `StepStartUIPart` - -A step boundary part of a message. - -```typescript -type StepStartUIPart = { - type: 'step-start'; -}; -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/32-validate-ui-messages.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/32-validate-ui-messages.mdx deleted file mode 100644 index 1c30ff1a2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/32-validate-ui-messages.mdx +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: validateUIMessages -description: API Reference for validateUIMessages ---- - -# `validateUIMessages` - -`validateUIMessages` is an async function that validates UI messages against schemas for metadata, data parts, and tools. It ensures type safety and data integrity for your message arrays before processing or rendering. - -## Basic Usage - -Simple validation without custom schemas: - -```typescript -import { validateUIMessages } from 'ai'; - -const messages = [ - { - id: '1', - role: 'user', - parts: [{ type: 'text', text: 'Hello!' }], - }, -]; - -const validatedMessages = await validateUIMessages({ - messages, -}); -``` - -## Advanced Usage - -Comprehensive validation with custom metadata, data parts, and tools: - -```typescript -import { validateUIMessages, tool } from 'ai'; -import { z } from 'zod'; - -// Define schemas -const metadataSchema = z.object({ - timestamp: z.string().datetime(), - userId: z.string(), -}); - -const dataSchemas = { - chart: z.object({ - data: z.array(z.number()), - labels: z.array(z.string()), - }), - image: z.object({ - url: z.string().url(), - caption: z.string(), - }), -}; - -const tools = { - weather: tool({ - description: 'Get weather info', - parameters: z.object({ - location: z.string(), - }), - execute: async ({ location }) => `Weather in ${location}: sunny`, - }), -}; - -// Messages with custom parts -const messages = [ - { - id: '1', - role: 'user', - metadata: { timestamp: '2024-01-01T00:00:00Z', userId: 'user123' }, - parts: [ - { type: 'text', text: 'Show me a chart' }, - { - type: 'data-chart', - data: { data: [1, 2, 3], labels: ['A', 'B', 'C'] }, - }, - ], - }, - { - id: '2', - role: 'assistant', - parts: [ - { - type: 'tool-weather', - toolCallId: 'call_123', - state: 'output-available', - input: { location: 'San Francisco' }, - output: 'Weather in San Francisco: sunny', - }, - ], - }, -]; - -// Validate with all schemas -const validatedMessages = await validateUIMessages({ - messages, - metadataSchema, - dataSchemas, - tools, -}); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/33-safe-validate-ui-messages.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/33-safe-validate-ui-messages.mdx deleted file mode 100644 index 2a4bd4a45..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/33-safe-validate-ui-messages.mdx +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: safeValidateUIMessages -description: API Reference for safeValidateUIMessages ---- - -# `safeValidateUIMessages` - -`safeValidateUIMessages` is an async function that validates UI messages like [`validateUIMessages`](https://ai-sdk.dev/docs/reference/ai-sdk-core/validate-ui-messages), but instead of throwing it returns an object with a `success` key and either `data` or `error`. - -## Basic Usage - -Simple validation without custom schemas: - -```typescript -import { safeValidateUIMessages } from 'ai'; - -const messages = [ - { - id: '1', - role: 'user', - parts: [{ type: 'text', text: 'Hello!' }], - }, -]; - -const result = await safeValidateUIMessages({ - messages, -}); - -if (!result.success) { - console.error(result.error.message); -} else { - const validatedMessages = result.data; -} -``` - -## Advanced Usage - -Comprehensive validation with custom metadata, data parts, and tools: - -```typescript -import { safeValidateUIMessages, tool } from 'ai'; -import { z } from 'zod'; - -// Define schemas -const metadataSchema = z.object({ - timestamp: z.string().datetime(), - userId: z.string(), -}); - -const dataSchemas = { - chart: z.object({ - data: z.array(z.number()), - labels: z.array(z.string()), - }), - image: z.object({ - url: z.string().url(), - caption: z.string(), - }), -}; - -const tools = { - weather: tool({ - description: 'Get weather info', - parameters: z.object({ - location: z.string(), - }), - execute: async ({ location }) => `Weather in ${location}: sunny`, - }), -}; - -// Messages with custom parts -const messages = [ - { - id: '1', - role: 'user', - metadata: { timestamp: '2024-01-01T00:00:00Z', userId: 'user123' }, - parts: [ - { type: 'text', text: 'Show me a chart' }, - { - type: 'data-chart', - data: { data: [1, 2, 3], labels: ['A', 'B', 'C'] }, - }, - ], - }, - { - id: '2', - role: 'assistant', - parts: [ - { - type: 'tool-weather', - toolCallId: 'call_123', - state: 'output-available', - input: { location: 'San Francisco' }, - output: 'Weather in San Francisco: sunny', - }, - ], - }, -]; - -// Validate with all schemas -const result = await safeValidateUIMessages({ - messages, - metadataSchema, - dataSchemas, - tools, -}); - -if (!result.success) { - console.error(result.error.message); -} else { - const validatedMessages = result.data; -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/40-provider-registry.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/40-provider-registry.mdx deleted file mode 100644 index 4b435d495..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/40-provider-registry.mdx +++ /dev/null @@ -1,198 +0,0 @@ ---- -title: createProviderRegistry -description: Registry for managing multiple providers and models (API Reference) ---- - -# `createProviderRegistry()` - -When you work with multiple providers and models, it is often desirable to manage them -in a central place and access the models through simple string ids. - -`createProviderRegistry` lets you create a registry with multiple providers that you -can access by their ids in the format `providerId:modelId`. - -### Setup - -You can create a registry with multiple providers and models using `createProviderRegistry`. - -```ts -import { anthropic } from '@ai-sdk/anthropic'; -import { createOpenAI } from '@ai-sdk/openai'; -import { createProviderRegistry } from 'ai'; - -export const registry = createProviderRegistry({ - // register provider with prefix and default setup: - anthropic, - - // register provider with prefix and custom setup: - openai: createOpenAI({ - apiKey: process.env.OPENAI_API_KEY, - }), -}); -``` - -### Custom Separator - -By default, the registry uses `:` as the separator between provider and model IDs. You can customize this separator by passing a `separator` option: - -```ts -const registry = createProviderRegistry( - { - anthropic, - openai, - }, - { separator: ' > ' }, -); - -// Now you can use the custom separator -const model = registry.languageModel('anthropic > claude-3-opus-20240229'); -``` - -### Language models - -You can access language models by using the `languageModel` method on the registry. -The provider id will become the prefix of the model id: `providerId:modelId`. - -```ts highlight={"5"} -import { generateText } from 'ai'; -import { registry } from './registry'; - -const { text } = await generateText({ - model: registry.languageModel('openai:gpt-4.1'), - prompt: 'Invent a new holiday and describe its traditions.', -}); -``` - -### Text embedding models - -You can access text embedding models by using the `.embeddingModel` method on the registry. -The provider id will become the prefix of the model id: `providerId:modelId`. - -```ts highlight={"5"} -import { embed } from 'ai'; -import { registry } from './registry'; - -const { embedding } = await embed({ - model: registry.embeddingModel('openai:text-embedding-3-small'), - value: 'sunny day at the beach', -}); -``` - -### Image models - -You can access image models by using the `imageModel` method on the registry. -The provider id will become the prefix of the model id: `providerId:modelId`. - -```ts highlight={"5"} -import { generateImage } from 'ai'; -import { registry } from './registry'; - -const { image } = await generateImage({ - model: registry.imageModel('openai:dall-e-3'), - prompt: 'A beautiful sunset over a calm ocean', -}); -``` - -## Import - - - -## API Signature - -### Parameters - -', - description: - 'The unique identifier for the provider. It should be unique within the registry.', - properties: [ - { - type: 'Provider', - parameters: [ - { - name: 'languageModel', - type: '(id: string) => LanguageModel', - description: - 'A function that returns a language model by its id.', - }, - { - name: 'embeddingModel', - type: '(id: string) => EmbeddingModel', - description: - 'A function that returns a text embedding model by its id.', - }, - { - name: 'imageModel', - type: '(id: string) => ImageModel', - description: 'A function that returns an image model by its id.', - }, - ], - }, - ], - }, - { - name: 'options', - type: 'object', - isOptional: true, - description: 'Optional configuration for the registry.', - properties: [ - { - type: 'Options', - parameters: [ - { - name: 'separator', - type: 'string', - isOptional: true, - description: - 'Custom separator between provider and model IDs. Defaults to ":".', - }, - { - name: 'languageModelMiddleware', - type: 'LanguageModelMiddleware | LanguageModelMiddleware[]', - isOptional: true, - description: - 'Middleware to wrap all language models obtained from the registry.', - }, - { - name: 'imageModelMiddleware', - type: 'ImageModelMiddleware | ImageModelMiddleware[]', - isOptional: true, - description: - 'Middleware to wrap all image models obtained from the registry.', - }, - ], - }, - ], - }, - ]} -/> - -### Returns - -The `createProviderRegistry` function returns a `Provider` instance. It has the following methods: - - LanguageModel', - description: - 'A function that returns a language model by its id (format: providerId:modelId)', - }, - { - name: 'embeddingModel', - type: '(id: string) => EmbeddingModel', - description: - 'A function that returns a text embedding model by its id (format: providerId:modelId)', - }, - { - name: 'imageModel', - type: '(id: string) => ImageModel', - description: - 'A function that returns an image model by its id (format: providerId:modelId)', - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/42-custom-provider.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/42-custom-provider.mdx deleted file mode 100644 index 7dd300923..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/42-custom-provider.mdx +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: customProvider -description: Custom provider that uses models from a different provider (API Reference) ---- - -# `customProvider()` - -With a custom provider, you can map ids to any model. -This allows you to set up custom model configurations, alias names, and more. -The custom provider also supports a fallback provider, which is useful for -wrapping existing providers and adding additional functionality. - -### Example: custom model settings - -You can create a custom provider using `customProvider`. - -```ts -import { openai } from '@ai-sdk/openai'; -import { customProvider } from 'ai'; - -// custom provider with different model settings: -export const myOpenAI = customProvider({ - languageModels: { - // replacement model with custom settings: - 'gpt-5': wrapLanguageModel({ - model: openai('gpt-5'), - middleware: defaultSettingsMiddleware({ - settings: { - providerOptions: { - openai: { - reasoningEffort: 'high', - }, - }, - }, - }), - }), - // alias model with custom settings: - 'gpt-4o-reasoning-high': wrapLanguageModel({ - model: openai('gpt-4o'), - middleware: defaultSettingsMiddleware({ - settings: { - providerOptions: { - openai: { - reasoningEffort: 'high', - }, - }, - }, - }), - }), - }, - fallbackProvider: openai, -}); -``` - -## Import - - - -## API Signature - -### Parameters - -', - isOptional: true, - description: - 'A record of language models, where keys are model IDs and values are LanguageModel instances.', - }, - { - name: '.embeddingModels', - type: 'Record>', - isOptional: true, - description: - 'A record of text embedding models, where keys are model IDs and values are EmbeddingModel instances.', - }, - { - name: 'imageModels', - type: 'Record', - isOptional: true, - description: - 'A record of image models, where keys are model IDs and values are image model instances.', - }, - { - name: 'transcriptionModels', - type: 'Record', - isOptional: true, - description: - 'A record of transcription models, where keys are model IDs and values are TranscriptionModel instances.', - }, - { - name: 'speechModels', - type: 'Record', - isOptional: true, - description: - 'A record of speech models, where keys are model IDs and values are SpeechModel instances.', - }, - { - name: 'rerankingModels', - type: 'Record', - isOptional: true, - description: - 'A record of reranking models, where keys are model IDs and values are RerankingModel instances.', - }, - { - name: 'fallbackProvider', - type: 'Provider', - isOptional: true, - description: - 'An optional fallback provider to use when a requested model is not found in the custom provider.', - }, - ]} -/> - -### Returns - -The `customProvider` function returns a `Provider` instance. It has the following methods: - - LanguageModel', - description: - 'A function that returns a language model by its id (format: providerId:modelId)', - }, - { - name: 'embeddingModel', - type: '(id: string) => EmbeddingModel', - description: - 'A function that returns a text embedding model by its id (format: providerId:modelId)', - }, - { - name: 'imageModel', - type: '(id: string) => ImageModel', - description: - 'A function that returns an image model by its id (format: providerId:modelId)', - }, - { - name: 'transcriptionModel', - type: '(id: string) => TranscriptionModel', - description: 'A function that returns a transcription model by its id.', - }, - { - name: 'speechModel', - type: '(id: string) => SpeechModel', - description: 'A function that returns a speech model by its id.', - }, - { - name: 'rerankingModel', - type: '(id: string) => RerankingModel', - description: 'A function that returns a reranking model by its id.', - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/50-cosine-similarity.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/50-cosine-similarity.mdx deleted file mode 100644 index 0788496ff..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/50-cosine-similarity.mdx +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: cosineSimilarity -description: Calculate the cosine similarity between two vectors (API Reference) ---- - -# `cosineSimilarity()` - -When you want to compare the similarity of embeddings, standard vector similarity metrics -like cosine similarity are often used. - -`cosineSimilarity` calculates the cosine similarity between two vectors. -A high value (close to 1) indicates that the vectors are very similar, while a low value (close to -1) indicates that they are different. - -```ts -import { cosineSimilarity, embedMany } from 'ai'; - -const { embeddings } = await embedMany({ - model: 'openai/text-embedding-3-small', - values: ['sunny day at the beach', 'rainy afternoon in the city'], -}); - -console.log( - `cosine similarity: ${cosineSimilarity(embeddings[0], embeddings[1])}`, -); -``` - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - -A number between -1 and 1 representing the cosine similarity between the two vectors. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/60-wrap-language-model.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/60-wrap-language-model.mdx deleted file mode 100644 index 86a9013e7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/60-wrap-language-model.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: wrapLanguageModel -description: Function for wrapping a language model with middleware (API Reference) ---- - -# `wrapLanguageModel()` - -The `wrapLanguageModel` function provides a way to enhance the behavior of language models -by wrapping them with middleware. -See [Language Model Middleware](/docs/ai-sdk-core/middleware) for more information on middleware. - -```ts -import { wrapLanguageModel, gateway } from 'ai'; - -const wrappedLanguageModel = wrapLanguageModel({ - model: gateway('openai/gpt-4.1'), - middleware: yourLanguageModelMiddleware, -}); -``` - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - -A new `LanguageModelV3` instance with middleware applied. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/61-wrap-image-model.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/61-wrap-image-model.mdx deleted file mode 100644 index eba0ad304..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/61-wrap-image-model.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: wrapImageModel -description: Function for wrapping an image model with middleware (API Reference) ---- - -# `wrapImageModel()` - -The `wrapImageModel` function provides a way to enhance the behavior of image models -by wrapping them with middleware. - -```ts -import { generateImage, wrapImageModel } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const model = wrapImageModel({ - model: openai.image('gpt-image-1'), - middleware: yourImageModelMiddleware, -}); - -const { image } = await generateImage({ - model, - prompt: 'Santa Claus driving a Cadillac', -}); -``` - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - -A new `ImageModelV3` instance with middleware applied. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/65-language-model-v2-middleware.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/65-language-model-v2-middleware.mdx deleted file mode 100644 index 23834c72b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/65-language-model-v2-middleware.mdx +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: LanguageModelV3Middleware -description: Middleware for enhancing language model behavior (API Reference) ---- - -# `LanguageModelV3Middleware` - - - Language model middleware is an experimental feature. - - -Language model middleware provides a way to enhance the behavior of language models -by intercepting and modifying the calls to the language model. It can be used to add -features like guardrails, RAG, caching, and logging in a language model agnostic way. - -See [Language Model Middleware](/docs/ai-sdk-core/middleware) for more information. - -## Import - - - -## API Signature - - PromiseLike', - isOptional: true, - description: - 'Transforms the parameters before they are passed to the language model.', - }, - { - name: 'wrapGenerate', - type: '({ doGenerate: () => PromiseLike, doStream: () => PromiseLike, params: LanguageModelV3CallOptions, model: LanguageModelV3 }) => PromiseLike', - isOptional: true, - description: - 'Wraps the generate operation of the language model. Receives both doGenerate and doStream functions.', - }, - { - name: 'wrapStream', - type: '({ doGenerate: () => PromiseLike, doStream: () => PromiseLike, params: LanguageModelV3CallOptions, model: LanguageModelV3 }) => PromiseLike', - isOptional: true, - description: - 'Wraps the stream operation of the language model. Receives both doGenerate and doStream functions.', - }, - { - name: 'overrideProvider', - type: '(options: { model: LanguageModelV3 }) => string', - isOptional: true, - description: 'Override the provider ID of the model.', - }, - { - name: 'overrideModelId', - type: '(options: { model: LanguageModelV3 }) => string', - isOptional: true, - description: 'Override the model ID of the model.', - }, - { - name: 'overrideSupportedUrls', - type: '(options: { model: LanguageModelV3 }) => PromiseLike> | Record', - isOptional: true, - description: 'Override the supported URLs for the model.', - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/66-extract-reasoning-middleware.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/66-extract-reasoning-middleware.mdx deleted file mode 100644 index f9b1ed1d8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/66-extract-reasoning-middleware.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: extractReasoningMiddleware -description: Middleware that extracts XML-tagged reasoning sections from generated text ---- - -# `extractReasoningMiddleware()` - -`extractReasoningMiddleware` is a middleware function that extracts XML-tagged reasoning sections from generated text and exposes them separately from the main text content. This is particularly useful when you want to separate an AI model's reasoning process from its final output. - -```ts -import { extractReasoningMiddleware } from 'ai'; - -const middleware = extractReasoningMiddleware({ - tagName: 'reasoning', - separator: '\n', -}); -``` - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - -Returns a middleware object that: - -- Processes both streaming and non-streaming responses -- Extracts content between specified XML tags as reasoning -- Removes the XML tags and reasoning from the main text -- Adds a `reasoning` property to the result containing the extracted content -- Maintains proper separation between text sections using the specified separator - -### Type Parameters - -The middleware works with the `LanguageModelV3StreamPart` type for streaming responses. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/67-simulate-streaming-middleware.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/67-simulate-streaming-middleware.mdx deleted file mode 100644 index 23900c299..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/67-simulate-streaming-middleware.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: simulateStreamingMiddleware -description: Middleware that simulates streaming for non-streaming language models ---- - -# `simulateStreamingMiddleware()` - -`simulateStreamingMiddleware` is a middleware function that simulates streaming behavior with responses from non-streaming language models. This is useful when you want to maintain a consistent streaming interface even when using models that only provide complete responses. - -```ts -import { simulateStreamingMiddleware } from 'ai'; - -const middleware = simulateStreamingMiddleware(); -``` - -## Import - - - -## API Signature - -### Parameters - -This middleware doesn't accept any parameters. - -### Returns - -Returns a middleware object that: - -- Takes a complete response from a language model -- Converts it into a simulated stream of chunks -- Properly handles various response components including: - - Text content - - Reasoning (as string or array of objects) - - Tool calls - - Metadata and usage information - - Warnings - -### Usage Example - -```ts -import { streamText } from 'ai'; -import { wrapLanguageModel } from 'ai'; -import { simulateStreamingMiddleware } from 'ai'; - -// Example with a non-streaming model -const result = streamText({ - model: wrapLanguageModel({ - model: nonStreamingModel, - middleware: simulateStreamingMiddleware(), - }), - prompt: 'Your prompt here', -}); - -// Now you can use the streaming interface -for await (const chunk of result.fullStream) { - // Process streaming chunks -} -``` - -## How It Works - -The middleware: - -1. Awaits the complete response from the language model -2. Creates a `ReadableStream` that emits chunks in the correct sequence -3. Simulates streaming by breaking down the response into appropriate chunk types -4. Preserves all metadata, reasoning, tool calls, and other response properties diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/68-default-settings-middleware.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/68-default-settings-middleware.mdx deleted file mode 100644 index 35a581ab5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/68-default-settings-middleware.mdx +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: defaultSettingsMiddleware -description: Middleware that applies default settings for language models ---- - -# `defaultSettingsMiddleware()` - -`defaultSettingsMiddleware` is a middleware function that applies default settings to language model calls. This is useful when you want to establish consistent default parameters across multiple model invocations. - -```ts -import { defaultSettingsMiddleware } from 'ai'; - -const middleware = defaultSettingsMiddleware({ - settings: { - temperature: 0.7, - maxOutputTokens: 1000, - // other settings... - }, -}); -``` - -## Import - - - -## API Signature - -### Parameters - -The middleware accepts a configuration object with the following properties: - -- `settings`: An object containing default parameter values to apply to language model calls. These can include any valid `LanguageModelV3CallOptions` properties and optional provider metadata. - -### Returns - -Returns a middleware object that: - -- Merges the default settings with the parameters provided in each model call -- Ensures that explicitly provided parameters take precedence over defaults -- Merges provider metadata objects - -### Usage Example - -```ts -import { streamText, wrapLanguageModel, defaultSettingsMiddleware } from 'ai'; - -// Create a model with default settings -const modelWithDefaults = wrapLanguageModel({ - model: gateway('anthropic/claude-sonnet-4.5'), - middleware: defaultSettingsMiddleware({ - settings: { - providerOptions: { - openai: { - reasoningEffort: 'high', - }, - }, - }, - }), -}); - -// Use the model - default settings will be applied -const result = await streamText({ - model: modelWithDefaults, - prompt: 'Your prompt here', - // These parameters will override the defaults - temperature: 0.8, -}); -``` - -## How It Works - -The middleware: - -1. Takes a set of default settings as configuration -2. Merges these defaults with the parameters provided in each model call -3. Ensures that explicitly provided parameters take precedence over defaults -4. Merges provider metadata objects from both sources diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/69-add-tool-input-examples-middleware.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/69-add-tool-input-examples-middleware.mdx deleted file mode 100644 index c2fa7e2c1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/69-add-tool-input-examples-middleware.mdx +++ /dev/null @@ -1,155 +0,0 @@ ---- -title: addToolInputExamplesMiddleware -description: Middleware that appends tool input examples to tool descriptions. ---- - -# `addToolInputExamplesMiddleware` - -`addToolInputExamplesMiddleware` is a middleware function that appends input examples to tool descriptions. This is especially useful for language model providers that **do not natively support the `inputExamples` property**—the middleware serializes and injects the examples into the tool's `description` so models can learn from them. - -## Import - - - -## API - -### Signature - -```ts -function addToolInputExamplesMiddleware(options?: { - prefix?: string; - format?: (example: { input: JSONObject }, index: number) => string; - remove?: boolean; -}): LanguageModelMiddleware; -``` - -### Parameters - - string', - isOptional: true, - description: - 'Optional custom formatter for each example. Receives the example object and its index. Default: JSON.stringify(example.input).', - }, - { - name: 'remove', - type: 'boolean', - isOptional: true, - description: - 'Whether to remove the `inputExamples` property from the tool after adding them to the description. Default: true.', - }, - ]} -/> - -### Returns - -A [LanguageModelMiddleware](/docs/ai-sdk-core/middleware) that: - -- Locates function tools with an `inputExamples` property. -- Serializes each input example (by default as JSON, or using your custom formatter). -- Prepends a section at the end of the tool description containing all formatted examples, prefixed by the `prefix`. -- Removes the `inputExamples` property from the tool (unless `remove: false`). -- Passes through all other tools (including those without examples) unchanged. - -## Usage Example - -```ts -import { - generateText, - tool, - wrapLanguageModel, - addToolInputExamplesMiddleware, -} from 'ai'; -import { openai } from '@ai-sdk/openai'; -import { z } from 'zod'; - -const model = wrapLanguageModel({ - model: __MODEL__, - middleware: addToolInputExamplesMiddleware({ - prefix: 'Input Examples:', - format: (example, index) => - `${index + 1}. ${JSON.stringify(example.input)}`, - }), -}); - -const result = await generateText({ - model, - tools: { - weather: tool({ - description: 'Get the weather in a location', - inputSchema: z.object({ location: z.string() }), - inputExamples: [ - { input: { location: 'San Francisco' } }, - { input: { location: 'London' } }, - ], - }), - }, - prompt: 'What is the weather in Tokyo?', -}); -``` - -## How It Works - -1. For every function tool that defines `inputExamples`, the middleware: - - - Formats each example with the `format` function (default: JSON.stringify). - - Builds a section like: - - ``` - Input Examples: - {"location":"San Francisco"} - {"location":"London"} - ``` - - - Appends this section to the end of the tool's `description`. - -2. By default, it removes the `inputExamples` property after appending to prevent duplication (can be disabled with `remove: false`). -3. Tools without input examples or non-function tools are left unmodified. - -> **Tip:** This middleware is especially useful with providers such as OpenAI or Anthropic, where native support for `inputExamples` is not available. - -## Example effect - -If your original tool definition is: - -```ts -{ - type: 'function', - name: 'weather', - description: 'Get the weather in a location', - inputSchema: { ... }, - inputExamples: [ - { input: { location: 'San Francisco' } }, - { input: { location: 'London' } } - ] -} -``` - -After applying the middleware (with default settings), the tool passed to the model will look like: - -```ts -{ - type: 'function', - name: 'weather', - description: `Get the weather in a location - -Input Examples: -{"location":"San Francisco"} -{"location":"London"}`, - inputSchema: { ... } - // inputExamples is removed by default -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/70-extract-json-middleware.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/70-extract-json-middleware.mdx deleted file mode 100644 index ec9504c2b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/70-extract-json-middleware.mdx +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: extractJsonMiddleware -description: Middleware that extracts JSON from text content by stripping markdown code fences ---- - -# `extractJsonMiddleware()` - -`extractJsonMiddleware` is a middleware function that extracts JSON from text content by stripping markdown code fences and other formatting. This is useful when using `Output.object()` with models that wrap JSON responses in markdown code blocks (e.g., ` ```json ... ``` `). - -```ts -import { extractJsonMiddleware } from 'ai'; - -const middleware = extractJsonMiddleware(); -``` - -## Import - - - -## API Signature - -### Parameters - - string', - isOptional: true, - description: - 'Custom transform function to apply to text content. Receives the raw text and should return the transformed text. If not provided, the default transform strips markdown code fences.', - }, - ]} -/> - -### Returns - -Returns a middleware object that: - -- Processes both streaming and non-streaming responses -- Strips markdown code fences (` ```json ` and ` ``` `) from text content -- Applies custom transformations when a `transform` function is provided -- Maintains proper streaming behavior with efficient buffering - -## Usage Examples - -### Basic Usage - -Strip markdown code fences from model responses when using structured output: - -```ts -import { - generateText, - wrapLanguageModel, - extractJsonMiddleware, - Output, -} from 'ai'; -import { z } from 'zod'; - -const result = await generateText({ - model: wrapLanguageModel({ - model: yourModel, - middleware: extractJsonMiddleware(), - }), - output: Output.object({ - schema: z.object({ - recipe: z.object({ - name: z.string(), - steps: z.array(z.string()), - }), - }), - }), - prompt: 'Generate a lasagna recipe.', -}); - -console.log(result.output); -``` - -### With Streaming - -The middleware also works with streaming responses: - -```ts -import { - streamText, - wrapLanguageModel, - extractJsonMiddleware, - Output, -} from 'ai'; -import { z } from 'zod'; - -const { partialOutputStream } = streamText({ - model: wrapLanguageModel({ - model: yourModel, - middleware: extractJsonMiddleware(), - }), - output: Output.object({ - schema: z.object({ - recipe: z.object({ - ingredients: z.array(z.string()), - steps: z.array(z.string()), - }), - }), - }), - prompt: 'Generate a detailed recipe.', -}); - -for await (const partialObject of partialOutputStream) { - console.log(partialObject); -} -``` - -### Custom Transform Function - -For models that use different formatting, you can provide a custom transform: - -```ts -import { extractJsonMiddleware } from 'ai'; - -const middleware = extractJsonMiddleware({ - transform: text => - text - .replace(/^PREFIX/, '') - .replace(/SUFFIX$/, '') - .trim(), -}); -``` - -## How It Works - -The middleware handles text content in two ways: - -### Non-Streaming (generateText) - -1. Receives the complete response from the model -2. Applies the transform function to strip markdown fences (or custom formatting) -3. Returns the cleaned text content - -### Streaming (streamText) - -1. Buffers initial content to detect markdown fence prefixes (` ```json\n `) -2. If a fence is detected, strips the prefix and switches to streaming mode -3. Maintains a small suffix buffer to handle the closing fence (` \n``` `) -4. When the stream ends, strips any trailing fence from the buffer -5. For custom transforms, buffers all content and applies the transform at the end - -This approach ensures efficient streaming while correctly handling code fences that may be split across multiple chunks. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/70-step-count-is.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/70-step-count-is.mdx deleted file mode 100644 index b0fa00766..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/70-step-count-is.mdx +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: stepCountIs -description: API Reference for stepCountIs. ---- - -# `stepCountIs()` - -Creates a stop condition that stops when the number of steps reaches a specified count. - -This function is used with `stopWhen` in `generateText` and `streamText` to control when a tool-calling loop should stop based on the number of steps executed. - -```ts -import { generateText, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; - -const result = await generateText({ - model: __MODEL__, - tools: { - // your tools - }, - // Stop after 5 steps - stopWhen: stepCountIs(5), -}); -``` - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - -A `StopCondition` function that returns `true` when the step count reaches the specified number. The function can be used with the `stopWhen` parameter in `generateText` and `streamText`. - -## Examples - -### Basic Usage - -Stop after 3 steps: - -```ts -import { generateText, stepCountIs } from 'ai'; - -const result = await generateText({ - model: yourModel, - tools: yourTools, - stopWhen: stepCountIs(3), -}); -``` - -### Combining with Other Conditions - -You can combine multiple stop conditions in an array: - -```ts -import { generateText, stepCountIs, hasToolCall } from 'ai'; - -const result = await generateText({ - model: yourModel, - tools: yourTools, - // Stop after 10 steps OR when finalAnswer tool is called - stopWhen: [stepCountIs(10), hasToolCall('finalAnswer')], -}); -``` - -## See also - -- [`hasToolCall()`](/docs/reference/ai-sdk-core/has-tool-call) -- [`generateText()`](/docs/reference/ai-sdk-core/generate-text) -- [`streamText()`](/docs/reference/ai-sdk-core/stream-text) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/71-has-tool-call.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/71-has-tool-call.mdx deleted file mode 100644 index da79a656d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/71-has-tool-call.mdx +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: hasToolCall -description: API Reference for hasToolCall. ---- - -# `hasToolCall()` - -Creates a stop condition that stops when a specific tool is called. - -This function is used with `stopWhen` in `generateText` and `streamText` to control when a tool-calling loop should stop based on whether a particular tool has been invoked. - -```ts -import { generateText, hasToolCall } from 'ai'; -__PROVIDER_IMPORT__; - -const result = await generateText({ - model: __MODEL__, - tools: { - weather: weatherTool, - finalAnswer: finalAnswerTool, - }, - // Stop when the finalAnswer tool is called - stopWhen: hasToolCall('finalAnswer'), -}); -``` - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - -A `StopCondition` function that returns `true` when the specified tool is called in the current step. The function can be used with the `stopWhen` parameter in `generateText` and `streamText`. - -## Examples - -### Basic Usage - -Stop when a specific tool is called: - -```ts -import { generateText, hasToolCall } from 'ai'; - -const result = await generateText({ - model: yourModel, - tools: { - submitAnswer: submitAnswerTool, - search: searchTool, - }, - stopWhen: hasToolCall('submitAnswer'), -}); -``` - -### Combining with Other Conditions - -You can combine multiple stop conditions in an array: - -```ts -import { generateText, hasToolCall, stepCountIs } from 'ai'; - -const result = await generateText({ - model: yourModel, - tools: { - weather: weatherTool, - search: searchTool, - finalAnswer: finalAnswerTool, - }, - // Stop when weather tool is called OR finalAnswer is called OR after 5 steps - stopWhen: [ - hasToolCall('weather'), - hasToolCall('finalAnswer'), - stepCountIs(5), - ], -}); -``` - -### Agent Pattern - -Common pattern for agents that run until they provide a final answer: - -```ts -import { generateText, hasToolCall } from 'ai'; - -const result = await generateText({ - model: yourModel, - tools: { - search: searchTool, - calculate: calculateTool, - finalAnswer: { - description: 'Provide the final answer to the user', - parameters: z.object({ - answer: z.string(), - }), - execute: async ({ answer }) => answer, - }, - }, - stopWhen: hasToolCall('finalAnswer'), -}); -``` - -## See also - -- [`stepCountIs()`](/docs/reference/ai-sdk-core/step-count-is) -- [`generateText()`](/docs/reference/ai-sdk-core/generate-text) -- [`streamText()`](/docs/reference/ai-sdk-core/stream-text) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/75-simulate-readable-stream.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/75-simulate-readable-stream.mdx deleted file mode 100644 index af6069466..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/75-simulate-readable-stream.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: simulateReadableStream -description: Create a ReadableStream that emits values with configurable delays ---- - -# `simulateReadableStream()` - -`simulateReadableStream` is a utility function that creates a ReadableStream which emits provided values sequentially with configurable delays. This is particularly useful for testing streaming functionality or simulating time-delayed data streams. - -```ts -import { simulateReadableStream } from 'ai'; - -const stream = simulateReadableStream({ - chunks: ['Hello', ' ', 'World'], - initialDelayInMs: 100, - chunkDelayInMs: 50, -}); -``` - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - -Returns a `ReadableStream` that: - -- Emits each value from the provided `chunks` array sequentially -- Waits for `initialDelayInMs` before emitting the first value (if not `null`) -- Waits for `chunkDelayInMs` between emitting subsequent values (if not `null`) -- Closes automatically after all chunks have been emitted - -### Type Parameters - -- `T`: The type of values contained in the chunks array and emitted by the stream - -## Examples - -### Basic Usage - -```ts -const stream = simulateReadableStream({ - chunks: ['Hello', ' ', 'World'], -}); -``` - -### With Delays - -```ts -const stream = simulateReadableStream({ - chunks: ['Hello', ' ', 'World'], - initialDelayInMs: 1000, // Wait 1 second before first chunk - chunkDelayInMs: 500, // Wait 0.5 seconds between chunks -}); -``` - -### Without Delays - -```ts -const stream = simulateReadableStream({ - chunks: ['Hello', ' ', 'World'], - initialDelayInMs: null, // No initial delay - chunkDelayInMs: null, // No delay between chunks -}); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/80-smooth-stream.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/80-smooth-stream.mdx deleted file mode 100644 index 61230f633..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/80-smooth-stream.mdx +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: smoothStream -description: Stream transformer for smoothing text and reasoning output ---- - -# `smoothStream()` - -`smoothStream` is a utility function that creates a TransformStream -for the `streamText` `transform` option -to smooth out text and reasoning streaming by buffering and releasing complete chunks with configurable delays. -This creates a more natural reading experience when streaming text and reasoning responses. - -```ts highlight={"6-9"} -import { smoothStream, streamText } from 'ai'; - -const result = streamText({ - model, - prompt, - experimental_transform: smoothStream({ - delayInMs: 20, // optional: defaults to 10ms - chunking: 'line', // optional: defaults to 'word' - }), -}); -``` - -## Import - - - -## API Signature - -### Parameters - - string | undefined | null', - isOptional: true, - description: - 'Controls how text and reasoning content is chunked for streaming. Use "word" to stream word by word (default), "line" to stream line by line, an Intl.Segmenter for locale-aware word segmentation (recommended for CJK languages), or provide a custom callback or RegExp pattern for custom chunking.', - }, - ]} -/> - -#### Word chunking caveats with non-latin languages - -The word based chunking **does not work well** with the following languages that do not delimit words with spaces: - -- Chinese -- Japanese -- Korean -- Vietnamese -- Thai - -#### Using Intl.Segmenter (recommended) - -For these languages, we recommend using `Intl.Segmenter` for proper locale-aware word segmentation. -This is the preferred approach as it provides accurate word boundaries for CJK and other languages. - - - `Intl.Segmenter` is available in Node.js 16+ and all modern browsers (Chrome - 87+, Firefox 125+, Safari 14.1+). - - -```tsx filename="Japanese example with Intl.Segmenter" -import { smoothStream, streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const segmenter = new Intl.Segmenter('ja', { granularity: 'word' }); - -const result = streamText({ - model: __MODEL__, - prompt: 'Your prompt here', - experimental_transform: smoothStream({ - chunking: segmenter, - }), -}); -``` - -```tsx filename="Chinese example with Intl.Segmenter" -import { smoothStream, streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const segmenter = new Intl.Segmenter('zh', { granularity: 'word' }); - -const result = streamText({ - model: __MODEL__, - prompt: 'Your prompt here', - experimental_transform: smoothStream({ - chunking: segmenter, - }), -}); -``` - -#### Regex based chunking - -To use regex based chunking, pass a `RegExp` to the `chunking` option. - -```ts -// To split on underscores: -smoothStream({ - chunking: /_+/, -}); - -// Also can do it like this, same behavior -smoothStream({ - chunking: /[^_]*_/, -}); -``` - -#### Custom callback chunking - -To use a custom callback for chunking, pass a function to the `chunking` option. - -```ts -smoothStream({ - chunking: text => { - const findString = 'some string'; - const index = text.indexOf(findString); - - if (index === -1) { - return null; - } - - return text.slice(0, index) + findString; - }, -}); -``` - -### Returns - -Returns a `TransformStream` that: - -- Buffers incoming text and reasoning chunks -- Releases content when the chunking pattern is encountered -- Adds configurable delays between chunks for smooth output -- Passes through non-text/reasoning chunks (like tool calls, step-finish events) immediately diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/90-generate-id.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/90-generate-id.mdx deleted file mode 100644 index ba04219d4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/90-generate-id.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: generateId -description: Generate a unique identifier (API Reference) ---- - -# `generateId()` - -Generates a unique identifier. - -This is the same id generator used by the AI SDK. - -```ts -import { generateId } from 'ai'; - -const id = generateId(); -``` - -## Import - - - -## API Signature - -### Returns - -A string representing the generated ID. - -## See also - -- [`createIdGenerator()`](/docs/reference/ai-sdk-core/create-id-generator) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/91-create-id-generator.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/91-create-id-generator.mdx deleted file mode 100644 index 81b4286b8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/91-create-id-generator.mdx +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: createIdGenerator -description: Create a customizable unique identifier generator (API Reference) ---- - -# `createIdGenerator()` - -Creates a customizable ID generator function. You can configure the alphabet, prefix, separator, and default size of the generated IDs. - -```ts -import { createIdGenerator } from 'ai'; - -const generateCustomId = createIdGenerator({ - prefix: 'user', - separator: '_', -}); - -const id = generateCustomId(); // Example: "user_1a2b3c4d5e6f7g8h" -``` - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - -Returns a function that generates IDs based on the configured options. - -### Notes - -- The generator uses non-secure random generation and should not be used for security-critical purposes. -- The separator character must not be part of the alphabet to ensure reliable prefix checking. - -## Example - -```ts -// Create a custom ID generator for user IDs -const generateUserId = createIdGenerator({ - prefix: 'user', - separator: '_', - size: 8, -}); - -// Generate IDs -const id1 = generateUserId(); // e.g., "user_1a2b3c4d" -``` - -## See also - -- [`generateId()`](/docs/reference/ai-sdk-core/generate-id) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/92-default-generated-file.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/92-default-generated-file.mdx deleted file mode 100644 index 469a5b07d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/92-default-generated-file.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: DefaultGeneratedFile -description: API Reference for DefaultGeneratedFile. ---- - -# `DefaultGeneratedFile` - -A concrete implementation of the `GeneratedFile` interface that provides lazy conversion between base64 and Uint8Array formats. - -```ts -import { DefaultGeneratedFile } from 'ai'; - -const file = new DefaultGeneratedFile({ - data: uint8ArrayData, - mediaType: 'image/png', -}); - -console.log(file.base64); // Automatically converted to base64 -console.log(file.uint8Array); // Original Uint8Array -``` - -## Import - - - -## Constructor - -### Parameters - - - -## Properties - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/index.mdx deleted file mode 100644 index 2a7fc2b96..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/01-ai-sdk-core/index.mdx +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: AI SDK Core -description: Reference documentation for the AI SDK Core -collapsed: true ---- - -# AI SDK Core - -[AI SDK Core](/docs/ai-sdk-core) is a set of functions that allow you to interact with language models and other AI models. -These functions are designed to be easy-to-use and flexible, allowing you to generate text, structured data, -and embeddings from language models and other AI models. - -AI SDK Core contains the following main functions: - - - -It also contains the following helper functions: - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx deleted file mode 100644 index 6678afd04..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx +++ /dev/null @@ -1,493 +0,0 @@ ---- -title: useChat -description: API reference for the useChat hook. ---- - -# `useChat()` - -Allows you to easily create a conversational user interface for your chatbot application. It enables the streaming of chat messages from your AI provider, manages the chat state, and updates the UI automatically as new messages are received. - - - The `useChat` API has been significantly updated in AI SDK 5.0. It now uses a - transport-based architecture and no longer manages input state internally. See - the [migration - guide](/docs/migration-guides/migration-guide-5-0#usechat-changes) for - details. - - -## Import - - - - - - - - - - - - - - - - -## API Signature - -### Parameters - -', - isOptional: true, - description: - 'An existing Chat instance to use. If provided, other parameters are ignored.', - }, - { - name: 'transport', - type: 'ChatTransport', - isOptional: true, - description: - 'The transport to use for sending messages. Defaults to DefaultChatTransport with `/api/chat` endpoint.', - properties: [ - { - type: 'DefaultChatTransport', - parameters: [ - { - name: 'api', - type: "string = '/api/chat'", - isOptional: true, - description: 'The API endpoint for chat requests.', - }, - { - name: 'credentials', - type: 'RequestCredentials', - isOptional: true, - description: 'The credentials mode for fetch requests.', - }, - { - name: 'headers', - type: 'Record | Headers', - isOptional: true, - description: 'HTTP headers to send with requests.', - }, - { - name: 'body', - type: 'object', - isOptional: true, - description: 'Extra body object to send with requests.', - }, - { - name: 'fetch', - type: 'FetchFunction', - isOptional: true, - description: - 'Custom fetch implementation. You can use it as a middleware to intercept requests, or to provide a custom fetch implementation for e.g. testing.', - }, - { - name: 'prepareSendMessagesRequest', - type: 'PrepareSendMessagesRequest', - isOptional: true, - description: - 'A function to customize the request before chat API calls.', - properties: [ - { - type: 'PrepareSendMessagesRequest', - parameters: [ - { - name: 'options', - type: 'PrepareSendMessageRequestOptions', - description: 'Options for preparing the request', - properties: [ - { - type: 'PrepareSendMessageRequestOptions', - parameters: [ - { - name: 'id', - type: 'string', - description: 'The chat ID', - }, - { - name: 'messages', - type: 'UIMessage[]', - description: 'Current messages in the chat', - }, - { - name: 'requestMetadata', - type: 'unknown', - description: 'The request metadata', - }, - { - name: 'body', - type: 'Record | undefined', - description: 'The request body', - }, - { - name: 'credentials', - type: 'RequestCredentials | undefined', - description: 'The request credentials', - }, - { - name: 'headers', - type: 'HeadersInit | undefined', - description: 'The request headers', - }, - { - name: 'api', - type: 'string', - description: `The API endpoint to use for the request. If not specified, it defaults to the transport’s API endpoint: /api/chat.`, - }, - { - name: 'trigger', - type: "'submit-message' | 'regenerate-message'", - description: 'The trigger for the request', - }, - { - name: 'messageId', - type: 'string | undefined', - description: 'The message ID if applicable', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - name: 'prepareReconnectToStreamRequest', - type: 'PrepareReconnectToStreamRequest', - isOptional: true, - description: - 'A function to customize the request before reconnect API call.', - properties: [ - { - type: 'PrepareReconnectToStreamRequest', - parameters: [ - { - name: 'options', - type: 'PrepareReconnectToStreamRequestOptions', - description: - 'Options for preparing the reconnect request', - properties: [ - { - type: 'PrepareReconnectToStreamRequestOptions', - parameters: [ - { - name: 'id', - type: 'string', - description: 'The chat ID', - }, - { - name: 'requestMetadata', - type: 'unknown', - description: 'The request metadata', - }, - { - name: 'body', - type: 'Record | undefined', - description: 'The request body', - }, - { - name: 'credentials', - type: 'RequestCredentials | undefined', - description: 'The request credentials', - }, - { - name: 'headers', - type: 'HeadersInit | undefined', - description: 'The request headers', - }, - { - name: 'api', - type: 'string', - description: `The API endpoint to use for the request. If not specified, it defaults to the transport’s API endpoint combined with the chat ID: /api/chat/{chatId}/stream.`, - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - name: 'id', - type: 'string', - isOptional: true, - description: - 'A unique identifier for the chat. If not provided, a random one will be generated.', - }, - { - name: 'messages', - type: 'UIMessage[]', - isOptional: true, - description: 'Initial chat messages to populate the conversation with.', - }, - { - name: 'messageMetadataSchema', - type: 'FlexibleSchema', - isOptional: true, - description: 'Schema for validating message metadata.', - }, - { - name: 'dataPartSchemas', - type: 'UIDataTypesToSchemas', - isOptional: true, - description: 'Schemas for validating data parts in messages.', - }, - { - name: 'generateId', - type: 'IdGenerator', - isOptional: true, - description: - 'A function to generate unique IDs for messages and the chat. If not provided, the default AI SDK generateId is used.', - }, - { - name: 'onToolCall', - type: '({toolCall: ToolCall}) => void | Promise', - isOptional: true, - description: - 'Optional callback function that is invoked when a tool call is received. You must call addToolOutput to provide the tool result.', - }, - { - name: 'sendAutomaticallyWhen', - type: '(options: { messages: UIMessage[] }) => boolean | PromiseLike', - isOptional: true, - description: - 'When provided, this function will be called when the stream is finished or a tool call is added to determine if the current messages should be resubmitted. You can use the lastAssistantMessageIsCompleteWithToolCalls helper for common scenarios.', - }, - { - name: 'onFinish', - type: '(options: OnFinishOptions) => void', - isOptional: true, - description: 'Called when the assistant response has finished streaming.', - properties: [ - { - type: 'OnFinishOptions', - parameters: [ - { - name: 'message', - type: 'UIMessage', - description: 'The response message.', - }, - { - name: 'messages', - type: 'UIMessage[]', - description: 'All messages including the response message', - }, - { - name: 'isAbort', - type: 'boolean', - description: - 'True when the request has been aborted by the client.', - }, - { - name: 'isDisconnect', - type: 'boolean', - description: - 'True if the server has been disconnected, e.g. because of a network error.', - }, - { - name: 'isError', - type: 'boolean', - description: `True if errors during streaming caused the response to stop early.`, - }, - { - name: 'finishReason', - type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'", - isOptional: true, - description: - 'The reason why the model finished generating the response. Undefined if the finish reason was not provided by the model.', - }, - ], - }, - ], - }, - { - name: 'onError', - type: '(error: Error) => void', - isOptional: true, - description: - 'Callback function to be called when an error is encountered.', - }, - { - name: 'onData', - type: '(dataPart: DataUIPart) => void', - isOptional: true, - description: - 'Optional callback function that is called when a data part is received.', - }, - { - name: 'experimental_throttle', - type: 'number', - isOptional: true, - description: - 'Custom throttle wait in ms for the chat messages and data updates. Default is undefined, which disables throttling.', - }, - { - name: 'resume', - type: 'boolean', - isOptional: true, - description: - 'Whether to resume an ongoing chat generation stream. Defaults to false.', - }, - ]} -/> - -### Returns - - Promise', - description: - 'Function to send a new message to the chat. This will trigger an API call to generate the assistant response. If a messageId is provided, the message will be replaced (useful for editing). If no message is provided, resubmits the current messages (useful after adding tool outputs).', - properties: [ - { - type: 'ChatRequestOptions', - parameters: [ - { - name: 'headers', - type: 'Record | Headers', - isOptional: true, - description: - 'Additional headers that should be to be passed to the API endpoint.', - }, - { - name: 'body', - type: 'object', - isOptional: true, - description: - 'Additional body JSON properties that should be sent to the API endpoint.', - }, - { - name: 'metadata', - type: 'unknown', - isOptional: true, - description: 'Additional data to be sent to the API endpoint.', - }, - ], - }, - ], - }, - { - name: 'regenerate', - type: '(options?: { messageId?: string } & ChatRequestOptions) => Promise', - description: - 'Function to regenerate the last assistant message or a specific message. If no messageId is provided, regenerates the last assistant message. Accepts ChatRequestOptions for headers, body, and metadata.', - }, - { - name: 'stop', - type: '() => void', - description: - 'Function to abort the current streaming response from the assistant.', - }, - { - name: 'clearError', - type: '() => void', - description: 'Clears the error state.', - }, - { - name: 'resumeStream', - type: '() => void', - description: - 'Function to resume an interrupted streaming response. Useful when a network error occurs during streaming.', - }, - { - name: 'addToolOutput', - type: '(options: { tool: string; toolCallId: string; output: unknown } | { tool: string; toolCallId: string; state: "output-error", errorText: string }) => void', - description: - 'Function to add a tool result to the chat. This will update the chat messages with the tool result. If sendAutomaticallyWhen is configured, it may trigger an automatic submission.', - }, - { - name: 'addToolApprovalResponse', - type: '(options: { id: string; approved: boolean; reason?: string }) => void | PromiseLike', - description: - 'Function to respond to a tool approval request. The id should match the approval id from the tool call. If sendAutomaticallyWhen is configured, it may trigger an automatic submission.', - }, - { - name: 'addToolResult', - type: '(options: { tool: string; toolCallId: string; output: unknown } | { tool: string; toolCallId: string; state: "output-error", errorText: string }) => void', - description: 'Deprecated. Use addToolOutput instead.', - }, - { - name: 'setMessages', - type: '(messages: UIMessage[] | ((messages: UIMessage[]) => UIMessage[])) => void', - description: - 'Function to update the messages state locally without triggering an API call. Useful for optimistic updates.', - }, - ]} -/> - -## Learn more - -- [Chatbot](/docs/ai-sdk-ui/chatbot) -- [Chatbot with Tools](/docs/ai-sdk-ui/chatbot-tool-usage) -- [UIMessage](/docs/reference/ai-sdk-core/ui-message) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/02-use-completion.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/02-use-completion.mdx deleted file mode 100644 index 430709708..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/02-use-completion.mdx +++ /dev/null @@ -1,185 +0,0 @@ ---- -title: useCompletion -description: API reference for the useCompletion hook. ---- - -# `useCompletion()` - -Allows you to create text completion based capabilities for your application. It enables the streaming of text completions from your AI provider, manages the state for chat input, and updates the UI automatically as new messages are received. - -## Import - - - - - - - - - - - - - - - - -## API Signature - -### Parameters - - void', - description: - 'An optional callback function that is called when the completion stream ends.', - }, - { - name: 'onError', - type: '(error: Error) => void', - description: - 'An optional callback that will be called when the chat stream encounters an error.', - }, - { - name: 'headers', - type: 'Record | Headers', - description: - 'An optional object of headers to be passed to the API endpoint.', - }, - { - name: 'body', - type: 'object', - description: - 'An optional, additional body object to be passed to the API endpoint.', - }, - { - name: 'credentials', - type: "'omit' | 'same-origin' | 'include'", - description: - 'An optional literal that sets the mode of credentials to be used on the request. Defaults to same-origin.', - }, - { - name: 'streamProtocol', - type: "'text' | 'data'", - isOptional: true, - description: - 'An optional literal that sets the type of stream to be used. Defaults to `data`. If set to `text`, the stream will be treated as a text stream.', - }, - { - name: 'fetch', - type: 'FetchFunction', - isOptional: true, - description: - 'Optional. A custom fetch function to be used for the API call. Defaults to the global fetch function.', - }, - { - name: 'experimental_throttle', - type: 'number', - isOptional: true, - description: - 'React only. Custom throttle wait time in milliseconds for the completion and data updates. When specified, throttles how often the UI updates during streaming. Default is undefined, which disables throttling.', - }, - -]} -/> - -### Returns - - | Headers, body?: object }) => Promise', - description: - 'Function to execute text completion based on the provided prompt. Returns the completion result when finished.', - }, - { - name: 'error', - type: 'undefined | Error', - description: 'The error thrown during the completion process, if any.', - }, - { - name: 'setCompletion', - type: '(completion: string) => void', - description: 'Function to update the `completion` state.', - }, - { - name: 'stop', - type: '() => void', - description: 'Function to abort the current API request.', - }, - { - name: 'input', - type: 'string', - description: 'The current value of the input field.', - }, - { - name: 'setInput', - type: 'React.Dispatch>', - description: 'Function to update the input value.', - }, - { - name: 'handleInputChange', - type: '(event: any) => void', - description: - "Handler for the `onChange` event of the input field to control the input's value.", - }, - { - name: 'handleSubmit', - type: '(event?: { preventDefault?: () => void }) => void', - description: - 'Form submission handler that automatically resets the input field and appends a user message.', - }, - { - name: 'isLoading', - type: 'boolean', - description: - 'Boolean flag indicating whether a fetch operation is currently in progress.', - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/03-use-object.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/03-use-object.mdx deleted file mode 100644 index 611f36c8b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/03-use-object.mdx +++ /dev/null @@ -1,196 +0,0 @@ ---- -title: useObject -description: API reference for the useObject hook. ---- - -# `experimental_useObject()` - - - `useObject` is an experimental feature and only available in React, Svelte, - and Vue. - - -Allows you to consume text streams that represent a JSON object and parse them into a complete object based on a schema. -You can use it together with [`streamText`](/docs/reference/ai-sdk-core/stream-text) and [`Output.object()`](/docs/reference/ai-sdk-core/output#output-object) in the backend. - -```tsx -'use client'; - -import { experimental_useObject as useObject } from '@ai-sdk/react'; - -export default function Page() { - const { object, submit } = useObject({ - api: '/api/use-object', - schema: z.object({ content: z.string() }), - }); - - return ( -
- - {object?.content &&

{object.content}

} -
- ); -} -``` - -## Import - - - - - - - - - - - - - -## API Signature - -### Parameters - - | undefined', - isOptional: true, - description: 'An value for the initial object. Optional.', - }, - { - name: 'fetch', - type: 'FetchFunction', - isOptional: true, - description: - 'A custom fetch function to be used for the API call. Defaults to the global fetch function. Optional.', - }, - { - name: 'headers', - type: 'Record | Headers', - isOptional: true, - description: - 'A headers object to be passed to the API endpoint. Optional.', - }, - { - name: 'credentials', - type: 'RequestCredentials', - isOptional: true, - description: - 'The credentials mode to be used for the fetch request. Possible values are: "omit", "same-origin", "include". Optional.', - }, - { - name: 'onError', - type: '(error: Error) => void', - isOptional: true, - description: - 'Callback function to be called when an error is encountered. Optional.', - }, - { - name: 'onFinish', - type: '(result: OnFinishResult) => void', - isOptional: true, - description: 'Called when the streaming response has finished.', - properties: [ - { - type: 'OnFinishResult', - parameters: [ - { - name: 'object', - type: 'T | undefined', - description: - 'The generated object (typed according to the schema). Can be undefined if the final object does not match the schema.', - }, - { - name: 'error', - type: 'Error | undefined', - description: - 'Optional error object. This is e.g. a TypeValidationError when the final object does not match the schema.', - }, - ], - }, - ], - }, - ]} -/> - -### Returns - - void', - description: 'Calls the API with the provided input as JSON body.', - }, - { - name: 'object', - type: 'DeepPartial | undefined', - description: - 'The current value for the generated object. Updated as the API streams JSON chunks.', - }, - { - name: 'error', - type: 'Error | undefined', - description: 'The error object if the API call fails.', - }, - { - name: 'isLoading', - type: 'boolean', - description: - 'Boolean flag indicating whether a request is currently in progress.', - }, - { - name: 'stop', - type: '() => void', - description: 'Function to abort the current API request.', - }, - { - name: 'clear', - type: '() => void', - description: 'Function to clear the object state.', - }, - ]} -/> - -## Examples - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/31-convert-to-model-messages.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/31-convert-to-model-messages.mdx deleted file mode 100644 index cbf63060c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/31-convert-to-model-messages.mdx +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: convertToModelMessages -description: Convert useChat messages to ModelMessages for AI functions (API Reference) ---- - -# `convertToModelMessages()` - -The `convertToModelMessages` function is used to transform an array of UI messages from the `useChat` hook into an array of `ModelMessage` objects. These `ModelMessage` objects are compatible with AI core functions like `streamText`. - -```ts filename="app/api/chat/route.ts" -import { convertToModelMessages, streamText } from 'ai'; -__PROVIDER_IMPORT__; - -export async function POST(req: Request) { - const { messages } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse(); -} -``` - -## Import - - - -## API Signature - -### Parameters - - TextPart | FilePart | undefined }', - description: - 'Optional configuration object. Provide tools to enable multi-modal tool responses. Set ignoreIncompleteToolCalls to true to skip tool calls without results (default: false). Use convertDataPart to transform custom data parts into model-compatible content.', - }, - ]} -/> - -### Returns - -A Promise that resolves to an array of [`ModelMessage`](/docs/reference/ai-sdk-core/model-message) objects. - -', - type: 'Promise', - description: - 'A Promise that resolves to an array of ModelMessage objects', - }, - ]} -/> - -## Multi-modal Tool Responses - -The `convertToModelMessages` function supports tools that can return multi-modal content. This is useful when tools need to return non-text content like images. - -```ts -import { tool } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const screenshotTool = tool({ - inputSchema: z.object({}), - execute: async () => 'imgbase64', - toModelOutput: ({ output }) => [{ type: 'image', data: output }], -}); - -const result = streamText({ - model: __MODEL__, - messages: convertToModelMessages(messages, { - tools: { - screenshot: screenshotTool, - }, - }), -}); -``` - -Tools can implement the optional `toModelOutput` method to transform their results into multi-modal content. The content is an array of content parts, where each part has a `type` (e.g., 'text', 'image') and corresponding data. - -## Custom Data Part Conversion - -The `convertToModelMessages` function supports converting custom data parts attached to user messages. This is useful when users need to include additional context (URLs, code files, JSON configs) with their messages. - -### Basic Usage - -By default, data parts in user messages are filtered out during conversion. To include them, provide a `convertDataPart` callback that transforms data parts into text or file parts that the model can understand: - -```ts filename="app/api/chat/route.ts" -import { convertToModelMessages, streamText } from 'ai'; - -type CustomUIMessage = UIMessage< - never, - { - url: { url: string; title: string; content: string }; - 'code-file': { filename: string; code: string; language: string }; - } ->; - -export async function POST(req: Request) { - const { messages } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: convertToModelMessages(messages, { - convertDataPart: part => { - // Convert URL attachments to text - if (part.type === 'data-url') { - return { - type: 'text', - text: `[Reference: ${part.data.title}](${part.data.url})\n\n${part.data.content}`, - }; - } - - // Convert code file attachments - if (part.type === 'data-code-file') { - return { - type: 'text', - text: `\`\`\`${part.data.language}\n// ${part.data.filename}\n${part.data.code}\n\`\`\``, - }; - } - - // Other data parts are ignored - }, - }), - }); - - return result.toUIMessageStreamResponse(); -} -``` - -### Use Cases - -**Attaching URL Content** -Allow users to attach URLs to their messages, with the content fetched and formatted for the model: - -```ts -// Client side -sendMessage({ - parts: [ - { type: 'text', text: 'Analyze this article' }, - { - type: 'data-url', - data: { - url: 'https://example.com/article', - title: 'Important Article', - content: '...', - }, - }, - ], -}); -``` - -**Including Code Files as Context** -Let users reference code files in their conversations: - -```ts -convertDataPart: part => { - if (part.type === 'data-code-file') { - return { - type: 'text', - text: `\`\`\`${part.data.language}\n${part.data.code}\n\`\`\``, - }; - } -}; -``` - -**Selective Inclusion** -Only data parts for which you return a text or file model message part are included, -all other data parts are ignored. - -```ts -const result = convertToModelMessages< - UIMessage< - unknown, - { - url: { url: string; title: string }; - code: { code: string; language: string }; - note: { text: string }; - } - > ->(messages, { - convertDataPart: part => { - if (part.type === 'data-url') { - return { - type: 'text', - text: `[${part.data.title}](${part.data.url})`, - }; - } - - // data-code and data-node are ignored - }, -}); -``` - -### Type Safety - -The generic parameter ensures full type safety for your custom data parts: - -```ts -type MyUIMessage = UIMessage< - unknown, - { - url: { url: string; content: string }; - config: { key: string; value: string }; - } ->; - -// TypeScript knows the exact shape of part.data -convertToModelMessages(messages, { - convertDataPart: part => { - if (part.type === 'data-url') { - // part.data is typed as { url: string; content: string } - return { type: 'text', text: part.data.url }; - } - // Return undefined to skip this part - }, -}); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/32-prune-messages.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/32-prune-messages.mdx deleted file mode 100644 index c8bc4f8ef..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/32-prune-messages.mdx +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: pruneMessages -description: API Reference for pruneMessages. ---- - -# `pruneMessages()` - -The `pruneMessages` function is used to prune or filter an array of `ModelMessage` objects. This is useful for reducing message context (to save tokens), removing intermediate reasoning, or trimming tool calls and empty messages before sending to an LLM. - -```ts filename="app/api/chat/route.ts" -import { pruneMessages, streamText } from 'ai'; -__PROVIDER_IMPORT__; - -export async function POST(req: Request) { - const { messages } = await req.json(); - - const prunedMessages = pruneMessages({ - messages, - reasoning: 'before-last-message', - toolCalls: 'before-last-2-messages', - emptyMessages: 'remove', - }); - - const result = streamText({ - model: __MODEL__, - messages: prunedMessages, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -## Import - - - -## API Signature - -### Parameters - -`, - description: - 'How to prune tool call/results/approval content. Can specify a strategy string or an array for per-tool fine control. Default: [] (empty array, equivalent to "none").', - }, - { - name: 'emptyMessages', - type: `'keep' | 'remove'`, - description: - 'Whether to keep or remove messages whose content is empty after pruning. Default: "remove".', - }, - ]} -/> - -### Returns - -An array of [`ModelMessage`](/docs/reference/ai-sdk-core/model-message) objects, pruned according to the provided options. - - - -## Example Usage - -```ts -import { pruneMessages } from 'ai'; - -const pruned = pruneMessages({ - messages, - reasoning: 'all', // Remove all reasoning parts - toolCalls: 'before-last-message', // Remove tool calls except those in the last message -}); -``` - -## Pruning Options - -- **reasoning:** Removes reasoning parts from assistant messages. Use `'all'` to remove all, `'before-last-message'` to keep reasoning in the last message, or `'none'` to retain all reasoning. -- **toolCalls:** Prune tool-call, tool-result, and tool-approval chunks from assistant/tool messages. Default is an empty array (no pruning). Options include: - - `'all'`: Prune all such content. - - `'before-last-message'`: Prune except in the last message. - - `'before-last-N-messages'`: Prune except in the last N messages. - - `'none'`: Do not prune. - - Or provide an array for per-tool fine control, e.g., `[{ type: 'before-last-message', tools: ['search', 'calculator'] }]` to prune only specific tools. -- **emptyMessages:** Set to `'remove'` (default) to exclude messages that have no content after pruning. - -> **Tip**: `pruneMessages` is typically used prior to sending a context window to an LLM to reduce message/token count, especially after a series of tool-calls and approvals. - -For advanced usage and the full list of possible message parts, see [`ModelMessage`](/docs/reference/ai-sdk-core/model-message) and [`pruneMessages` implementation](https://github.com/vercel/ai/blob/main/packages/ai/src/generate-text/prune-messages.ts). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/40-create-ui-message-stream.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/40-create-ui-message-stream.mdx deleted file mode 100644 index fb7bcbf52..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/40-create-ui-message-stream.mdx +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: createUIMessageStream -description: API Reference for createUIMessageStream. ---- - -# `createUIMessageStream` - -The `createUIMessageStream` function allows you to create a readable stream for UI messages with advanced features like message merging, error handling, and finish callbacks. - -## Import - - - -## Example - -```tsx -const existingMessages: UIMessage[] = [ - /* ... */ -]; - -const stream = createUIMessageStream({ - async execute({ writer }) { - // Start a text message - // Note: The id must be consistent across text-start, text-delta, and text-end steps - // This allows the system to correctly identify they belong to the same text block - writer.write({ - type: 'text-start', - id: 'example-text', - }); - - // Write a message chunk - writer.write({ - type: 'text-delta', - id: 'example-text', - delta: 'Hello', - }); - - // End the text message - writer.write({ - type: 'text-end', - id: 'example-text', - }); - - // Merge another stream from streamText - const result = streamText({ - model: __MODEL__, - prompt: 'Write a haiku about AI', - }); - - writer.merge(result.toUIMessageStream()); - }, - onError: error => `Custom error: ${error.message}`, - originalMessages: existingMessages, - onFinish: ({ messages, isContinuation, responseMessage }) => { - console.log('Stream finished with messages:', messages); - }, -}); -``` - -## API Signature - -### Parameters - - Promise | void', - description: - 'A function that receives a writer instance and can use it to write UI message chunks to the stream.', - properties: [ - { - type: 'UIMessageStreamWriter', - parameters: [ - { - name: 'write', - type: '(part: UIMessageChunk) => void', - description: 'Writes a UI message chunk to the stream.', - }, - { - name: 'merge', - type: '(stream: ReadableStream) => void', - description: - 'Merges the contents of another UI message stream into this stream.', - }, - { - name: 'onError', - type: '(error: unknown) => string', - description: - 'Error handler that is used by the stream writer for handling errors in merged streams.', - }, - ], - }, - ], - }, - { - name: 'onError', - type: '(error: unknown) => string', - description: - 'A function that handles errors and returns an error message string. By default, it returns the error message.', - }, - { - name: 'originalMessages', - type: 'UIMessage[] | undefined', - description: - 'The original messages. If provided, persistence mode is assumed and a message ID is provided for the response message.', - }, - { - name: 'onFinish', - type: '(options: { messages: UIMessage[]; isContinuation: boolean; isAborted: boolean; responseMessage: UIMessage; finishReason?: FinishReason }) => PromiseLike | void', - description: - 'A callback function that is called when the stream finishes.', - properties: [ - { - type: 'FinishOptions', - parameters: [ - { - name: 'messages', - type: 'UIMessage[]', - description: 'The updated list of UI messages.', - }, - { - name: 'isContinuation', - type: 'boolean', - description: - 'Indicates whether the response message is a continuation of the last original message, or if a new message was created.', - }, - { - name: 'isAborted', - type: 'boolean', - description: 'Indicates whether the stream was aborted.', - }, - { - name: 'responseMessage', - type: 'UIMessage', - description: - 'The message that was sent to the client as a response (including the original message if it was extended).', - }, - { - name: 'finishReason', - type: 'FinishReason | undefined', - description: - "The reason why the generation finished. One of: 'stop', 'length', 'content-filter', 'tool-calls', 'error', or 'other'.", - }, - ], - }, - ], - }, - { - name: 'generateId', - type: 'IdGenerator | undefined', - description: - 'A function to generate unique IDs for messages. Uses the default ID generator if not provided.', - }, - ]} -/> - -### Returns - -`ReadableStream` - -A readable stream that emits UI message chunks. The stream automatically handles error propagation, merging of multiple streams, and proper cleanup when all operations are complete. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/41-create-ui-message-stream-response.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/41-create-ui-message-stream-response.mdx deleted file mode 100644 index c98802fc2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/41-create-ui-message-stream-response.mdx +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: createUIMessageStreamResponse -description: API Reference for createUIMessageStreamResponse. ---- - -# `createUIMessageStreamResponse` - -The `createUIMessageStreamResponse` function creates a Response object that streams UI messages to the client. - -## Import - - - -## Example - -```tsx -import { - createUIMessageStream, - createUIMessageStreamResponse, - streamText, -} from 'ai'; -__PROVIDER_IMPORT__; - -const response = createUIMessageStreamResponse({ - status: 200, - statusText: 'OK', - headers: { - 'Custom-Header': 'value', - }, - stream: createUIMessageStream({ - execute({ writer }) { - // Write custom data (type must be 'data-') - writer.write({ - type: 'data-message', - data: { content: 'Hello' }, - }); - - // Write text content using start/delta/end pattern - writer.write({ - type: 'text-start', - id: 'greeting-text', - }); - writer.write({ - type: 'text-delta', - id: 'greeting-text', - delta: 'Hello, world!', - }); - writer.write({ - type: 'text-end', - id: 'greeting-text', - }); - - // Write source information (flat properties, not nested) - writer.write({ - type: 'source-url', - sourceId: 'source-1', - url: 'https://example.com', - title: 'Example Source', - }); - - // Merge with LLM stream - const result = streamText({ - model: __MODEL__, - prompt: 'Say hello', - }); - - writer.merge(result.toUIMessageStream()); - }, - }), -}); -``` - -## API Signature - -### Parameters - -', - description: 'The UI message stream to send to the client.', - }, - { - name: 'status', - type: 'number', - isOptional: true, - description: 'The status code for the response. Defaults to 200.', - }, - { - name: 'statusText', - type: 'string', - isOptional: true, - description: 'The status text for the response.', - }, - { - name: 'headers', - type: 'Headers | Record', - isOptional: true, - description: 'Additional headers for the response.', - }, - { - name: 'consumeSseStream', - type: '(options: { stream: ReadableStream }) => PromiseLike | void', - isOptional: true, - description: - 'Optional callback to consume the Server-Sent Events stream.', - }, - ]} -/> - -### Returns - -`Response` - -A Response object that streams UI message chunks with the specified status, headers, and content. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/42-pipe-ui-message-stream-to-response.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/42-pipe-ui-message-stream-to-response.mdx deleted file mode 100644 index 39254752f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/42-pipe-ui-message-stream-to-response.mdx +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: pipeUIMessageStreamToResponse -description: Learn to use pipeUIMessageStreamToResponse helper function to pipe streaming data to a ServerResponse object. ---- - -# `pipeUIMessageStreamToResponse` - -The `pipeUIMessageStreamToResponse` function pipes streaming data to a Node.js ServerResponse object (see [Streaming Data](/docs/ai-sdk-ui/streaming-data)). - -## Import - - - -## Example - -```tsx -pipeUIMessageStreamToResponse({ - response: serverResponse, - status: 200, - statusText: 'OK', - headers: { - 'Custom-Header': 'value', - }, - stream: myUIMessageStream, - consumeSseStream: ({ stream }) => { - // Optional: consume the SSE stream independently - console.log('Consuming SSE stream:', stream); - }, -}); -``` - -## API Signature - -### Parameters - -', - description: 'The UI message stream to pipe to the response.', - }, - { - name: 'status', - type: 'number', - isOptional: true, - description: 'The status code for the response.', - }, - { - name: 'statusText', - type: 'string', - isOptional: true, - description: 'The status text for the response.', - }, - { - name: 'headers', - type: 'Headers | Record', - isOptional: true, - description: 'Additional headers for the response.', - }, - { - name: 'consumeSseStream', - type: '({ stream }: { stream: ReadableStream }) => PromiseLike | void', - isOptional: true, - description: - 'Optional function to consume the SSE stream independently. The stream is teed and this function receives a copy.', - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/43-read-ui-message-stream.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/43-read-ui-message-stream.mdx deleted file mode 100644 index d35a82415..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/43-read-ui-message-stream.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: readUIMessageStream -description: API Reference for readUIMessageStream. ---- - -# readUIMessageStream - -Transforms a stream of `UIMessageChunk`s into an `AsyncIterableStream` of `UIMessage`s. - -UI message streams are useful outside of Chat use cases, e.g. for terminal UIs, custom stream consumption on the client, or RSC (React Server Components). - -## Import - -```tsx -import { readUIMessageStream } from 'ai'; -``` - -## API Signature - -### Parameters - -', - description: 'The stream of UIMessageChunk objects to read.', - }, - { - name: 'onError', - type: '(error: unknown) => void', - isOptional: true, - description: - 'A function that is called when an error occurs during stream processing.', - }, - { - name: 'terminateOnError', - type: 'boolean', - isOptional: true, - description: - 'Whether to terminate the stream if an error occurs. Defaults to false.', - }, - ]} -/> - -### Returns - -An `AsyncIterableStream` of `UIMessage`s. Each stream part represents a different state of the same message as it is being completed. - -For comprehensive examples and use cases, see [Reading UI Message Streams](/docs/ai-sdk-ui/reading-ui-message-streams). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/46-infer-ui-tools.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/46-infer-ui-tools.mdx deleted file mode 100644 index d49b59cf0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/46-infer-ui-tools.mdx +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: InferUITools -description: API Reference for InferUITools. ---- - -# InferUITools - -Infers the input and output types of a `ToolSet`. - -This type helper is useful when working with tools in TypeScript to ensure type safety for your tool inputs and outputs in `UIMessage`s. - -## Import - -```tsx -import { InferUITools } from 'ai'; -``` - -## API Signature - -### Type Parameters - - - -### Returns - -A type that maps each tool in the tool set to its inferred input and output types. - -The resulting type has the shape: - -```typescript -{ - [NAME in keyof TOOLS & string]: { - input: InferToolInput; - output: InferToolOutput; - }; -} -``` - -## Examples - -### Basic Usage - -```tsx -import { InferUITools } from 'ai'; -import { z } from 'zod'; - -const tools = { - weather: { - description: 'Get the current weather', - inputSchema: z.object({ - location: z.string().describe('The city and state'), - }), - execute: async ({ location }) => { - return `The weather in ${location} is sunny.`; - }, - }, - calculator: { - description: 'Perform basic arithmetic', - inputSchema: z.object({ - operation: z.enum(['add', 'subtract', 'multiply', 'divide']), - a: z.number(), - b: z.number(), - }), - execute: async ({ operation, a, b }) => { - switch (operation) { - case 'add': - return a + b; - case 'subtract': - return a - b; - case 'multiply': - return a * b; - case 'divide': - return a / b; - } - }, - }, -}; - -// Infer the types from the tool set -type MyUITools = InferUITools; -// This creates a type with: -// { -// weather: { input: { location: string }; output: string }; -// calculator: { input: { operation: 'add' | 'subtract' | 'multiply' | 'divide'; a: number; b: number }; output: number }; -// } -``` - -## Related - -- [`InferUITool`](/docs/reference/ai-sdk-ui/infer-ui-tool) - Infer types for a single tool -- [`useChat`](/docs/reference/ai-sdk-ui/use-chat) - Chat hook that supports typed tools diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/47-infer-ui-tool.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/47-infer-ui-tool.mdx deleted file mode 100644 index 549154d41..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/47-infer-ui-tool.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: InferUITool -description: API Reference for InferUITool. ---- - -# InferUITool - -Infers the input and output types of a tool. - -This type helper is useful when working with individual tools to ensure type safety for your tool inputs and outputs in `UIMessage`s. - -## Import - -```tsx -import { InferUITool } from 'ai'; -``` - -## API Signature - -### Type Parameters - - - -### Returns - -A type that contains the inferred input and output types of the tool. - -The resulting type has the shape: - -```typescript -{ - input: InferToolInput; - output: InferToolOutput; -} -``` - -## Examples - -### Basic Usage - -```tsx -import { InferUITool } from 'ai'; -import { z } from 'zod'; - -const weatherTool = { - description: 'Get the current weather', - inputSchema: z.object({ - location: z.string().describe('The city and state'), - }), - execute: async ({ location }) => { - return `The weather in ${location} is sunny.`; - }, -}; - -// Infer the types from the tool -type WeatherUITool = InferUITool; -// This creates a type with: -// { -// input: { location: string }; -// output: string; -// } -``` - -## Related - -- [`InferUITools`](/docs/reference/ai-sdk-ui/infer-ui-tools) - Infer types for a tool set -- [`ToolUIPart`](/docs/reference/ai-sdk-core/ui-message#tooluipart) - Tool part type for UI messages diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/50-direct-chat-transport.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/50-direct-chat-transport.mdx deleted file mode 100644 index c7283eea7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/50-direct-chat-transport.mdx +++ /dev/null @@ -1,333 +0,0 @@ ---- -title: DirectChatTransport -description: API Reference for the DirectChatTransport class. ---- - -# `DirectChatTransport` - -A transport that directly communicates with an [Agent](/docs/reference/ai-sdk-core/agent) in-process, without going through HTTP. This is useful for: - -- Server-side rendering scenarios -- Testing without network -- Single-process applications - -Unlike `DefaultChatTransport` which sends HTTP requests to an API endpoint, `DirectChatTransport` invokes the agent's `stream()` method directly and converts the result to a UI message stream. - -```tsx -import { useChat } from '@ai-sdk/react'; -import { DirectChatTransport, ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are a helpful assistant.', -}); - -export default function Chat() { - const { messages, sendMessage, status } = useChat({ - transport: new DirectChatTransport({ agent }), - }); - - // ... render chat UI -} -``` - -## Import - - - -## Constructor - -### Parameters - - METADATA | undefined', - isOptional: true, - description: - 'Extracts message metadata that will be sent to the client. Called on `start` and `finish` events.', - }, - { - name: 'sendReasoning', - type: 'boolean', - isOptional: true, - description: 'Send reasoning parts to the client. Defaults to true.', - }, - { - name: 'sendSources', - type: 'boolean', - isOptional: true, - description: 'Send source parts to the client. Defaults to false.', - }, - { - name: 'sendFinish', - type: 'boolean', - isOptional: true, - description: - 'Send the finish event to the client. Set to false if you are using additional streamText calls that send additional data. Defaults to true.', - }, - { - name: 'sendStart', - type: 'boolean', - isOptional: true, - description: - 'Send the message start event to the client. Set to false if you are using additional streamText calls and the message start event has already been sent. Defaults to true.', - }, - { - name: 'onError', - type: '(error: unknown) => string', - isOptional: true, - description: - "Process an error, e.g. to log it. Defaults to `() => 'An error occurred.'`. Return the error message to include in the data stream.", - }, - ]} -/> - -## Methods - -### `sendMessages()` - -Sends messages to the agent and returns a streaming response. This method validates and converts UI messages to model messages, calls the agent's `stream()` method, and returns the result as a UI message stream. - -```ts -const stream = await transport.sendMessages({ - chatId: 'chat-123', - trigger: 'submit-message', - messages: [...], - abortSignal: controller.signal, -}); -``` - - | Headers', - isOptional: true, - description: 'Additional headers (ignored by DirectChatTransport).', - }, - { - name: 'body', - type: 'object', - isOptional: true, - description: - 'Additional body properties (ignored by DirectChatTransport).', - }, - { - name: 'metadata', - type: 'unknown', - isOptional: true, - description: 'Custom metadata (ignored by DirectChatTransport).', - }, - ]} -/> - -#### Returns - -Returns a `Promise>` - a stream of UI message chunks that can be processed by the chat UI. - -### `reconnectToStream()` - -Direct transport does not support reconnection since there is no persistent server-side stream to reconnect to. - -#### Returns - -Always returns `Promise`. - -## Examples - -### Basic Usage - -```tsx -import { useChat } from '@ai-sdk/react'; -import { DirectChatTransport, ToolLoopAgent } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const agent = new ToolLoopAgent({ - model: openai('gpt-4o'), - instructions: 'You are a helpful assistant.', -}); - -export default function Chat() { - const { messages, sendMessage, status } = useChat({ - transport: new DirectChatTransport({ agent }), - }); - - return ( -
- {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, index) => - part.type === 'text' ? {part.text} : null, - )} -
- ))} - -
- ); -} -``` - -### With Agent Tools - -```tsx -import { useChat } from '@ai-sdk/react'; -import { DirectChatTransport, ToolLoopAgent, tool } from 'ai'; -import { openai } from '@ai-sdk/openai'; -import { z } from 'zod'; - -const weatherTool = tool({ - description: 'Get the current weather', - parameters: z.object({ - location: z.string().describe('The city and state'), - }), - execute: async ({ location }) => { - return `The weather in ${location} is sunny and 72°F.`; - }, -}); - -const agent = new ToolLoopAgent({ - model: openai('gpt-4o'), - instructions: 'You are a helpful assistant with access to weather data.', - tools: { weather: weatherTool }, -}); - -export default function Chat() { - const { messages, sendMessage } = useChat({ - transport: new DirectChatTransport({ agent }), - }); - - // ... render chat UI with tool results -} -``` - -### With Custom Agent Options - -```tsx -import { useChat } from '@ai-sdk/react'; -import { DirectChatTransport, ToolLoopAgent } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const agent = new ToolLoopAgent<{ userId: string }>({ - model: openai('gpt-4o'), - prepareCall: ({ options, ...rest }) => ({ - ...rest, - providerOptions: { - openai: { user: options.userId }, - }, - }), -}); - -export default function Chat({ userId }: { userId: string }) { - const { messages, sendMessage } = useChat({ - transport: new DirectChatTransport({ - agent, - options: { userId }, - }), - }); - - // ... render chat UI -} -``` - -### With Reasoning - -```tsx -import { useChat } from '@ai-sdk/react'; -import { DirectChatTransport, ToolLoopAgent } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const agent = new ToolLoopAgent({ - model: openai('o1-preview'), -}); - -export default function Chat() { - const { messages, sendMessage } = useChat({ - transport: new DirectChatTransport({ - agent, - sendReasoning: true, - }), - }); - - return ( -
- {messages.map(message => ( -
- {message.parts.map((part, index) => { - if (part.type === 'text') { - return

{part.text}

; - } - if (part.type === 'reasoning') { - return ( -
-                  {part.text}
-                
- ); - } - return null; - })} -
- ))} -
- ); -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/index.mdx deleted file mode 100644 index 4fcd13c3c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/02-ai-sdk-ui/index.mdx +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: AI SDK UI -description: Reference documentation for the AI SDK UI -collapsed: true ---- - -# AI SDK UI - -[AI SDK UI](/docs/ai-sdk-ui) is designed to help you build interactive chat, completion, and assistant applications with ease. -It is a framework-agnostic toolkit, streamlining the integration of advanced AI functionalities into your applications. - -AI SDK UI contains the following hooks: - - - -## UI Framework Support - -AI SDK UI supports the following frameworks: [React](https://react.dev/), [Svelte](https://svelte.dev/), [Vue.js](https://vuejs.org/), -[Angular](https://angular.dev/), and [SolidJS](https://www.solidjs.com/). - -Here is a comparison of the supported functions across these frameworks: - -| | [useChat](/docs/reference/ai-sdk-ui/use-chat) | [useCompletion](/docs/reference/ai-sdk-ui/use-completion) | [useObject](/docs/reference/ai-sdk-ui/use-object) | -| --------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------- | -| React `@ai-sdk/react` | | | | -| Vue.js `@ai-sdk/vue` | Chat | | | -| Svelte `@ai-sdk/svelte` | Chat | Completion | StructuredObject | -| Angular `@ai-sdk/angular` | Chat | Completion | StructuredObject | -| [SolidJS](https://github.com/kodehort/ai-sdk-solid) (community) | | | | - - - [Contributions](https://github.com/vercel/ai/blob/main/CONTRIBUTING.md) are - welcome to implement missing features for non-React frameworks. - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/01-stream-ui.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/01-stream-ui.mdx deleted file mode 100644 index 14544d78f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/01-stream-ui.mdx +++ /dev/null @@ -1,767 +0,0 @@ ---- -title: streamUI -description: Reference for the streamUI function from the AI SDK RSC ---- - -# `streamUI` - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -A helper function to create a streamable UI from LLM providers. This function is similar to AI SDK Core APIs and supports the same model interfaces. - -To see `streamUI` in action, check out [these examples](#examples). - -## Import - - - -## Parameters - - | Array', - description: - 'A list of messages that represent a conversation. Automatically converts UI messages from the useChat hook.', - properties: [ - { - type: 'SystemModelMessage', - parameters: [ - { - name: 'role', - type: "'system'", - description: 'The role for the system message.', - }, - { - name: 'content', - type: 'string', - description: 'The content of the message.', - }, - ], - }, - { - type: 'UserModelMessage', - parameters: [ - { - name: 'role', - type: "'user'", - description: 'The role for the user message.', - }, - { - name: 'content', - type: 'string | Array', - description: 'The content of the message.', - properties: [ - { - type: 'TextPart', - parameters: [ - { - name: 'type', - type: "'text'", - description: 'The type of the message part.', - }, - { - name: 'text', - type: 'string', - description: 'The text content of the message part.', - }, - ], - }, - { - type: 'ImagePart', - parameters: [ - { - name: 'type', - type: "'image'", - description: 'The type of the message part.', - }, - { - name: 'image', - type: 'string | Uint8Array | Buffer | ArrayBuffer | URL', - description: - 'The image content of the message part. String are either base64 encoded content, base64 data URLs, or http(s) URLs.', - }, - { - name: 'mediaType', - type: 'string', - isOptional: true, - description: - 'The IANA media type of the image. Optional.', - }, - ], - }, - { - type: 'FilePart', - parameters: [ - { - name: 'type', - type: "'file'", - description: 'The type of the message part.', - }, - { - name: 'data', - type: 'string | Uint8Array | Buffer | ArrayBuffer | URL', - description: - 'The file content of the message part. String are either base64 encoded content, base64 data URLs, or http(s) URLs.', - }, - { - name: 'mediaType', - type: 'string', - description: 'The IANA media type of the file.', - }, - ], - }, - ], - }, - ], - }, - { - type: 'AssistantModelMessage', - parameters: [ - { - name: 'role', - type: "'assistant'", - description: 'The role for the assistant message.', - }, - { - name: 'content', - type: 'string | Array', - description: 'The content of the message.', - properties: [ - { - type: 'TextPart', - parameters: [ - { - name: 'type', - type: "'text'", - description: 'The type of the message part.', - }, - { - name: 'text', - type: 'string', - description: 'The text content of the message part.', - }, - ], - }, - { - type: 'ToolCallPart', - parameters: [ - { - name: 'type', - type: "'tool-call'", - description: 'The type of the message part.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool, which typically would be the name of the function.', - }, - { - name: 'args', - type: 'object based on zod schema', - description: - 'Parameters generated by the model to be used by the tool.', - }, - ], - }, - ], - }, - ], - }, - { - type: 'ToolModelMessage', - parameters: [ - { - name: 'role', - type: "'tool'", - description: 'The role for the assistant message.', - }, - { - name: 'content', - type: 'Array', - description: 'The content of the message.', - properties: [ - { - type: 'ToolResultPart', - parameters: [ - { - name: 'type', - type: "'tool-result'", - description: 'The type of the message part.', - }, - { - name: 'toolCallId', - type: 'string', - description: - 'The id of the tool call the result corresponds to.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool the result corresponds to.', - }, - { - name: 'result', - type: 'unknown', - description: - 'The result returned by the tool after execution.', - }, - { - name: 'isError', - type: 'boolean', - isOptional: true, - description: - 'Whether the result is an error or an error message.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - name: 'maxOutputTokens', - type: 'number', - isOptional: true, - description: 'Maximum number of tokens to generate.', - }, - { - name: 'temperature', - type: 'number', - isOptional: true, - description: - 'Temperature setting. The value is passed through to the provider. The range depends on the provider and model. It is recommended to set either `temperature` or `topP`, but not both.', - }, - { - name: 'topP', - type: 'number', - isOptional: true, - description: - 'Nucleus sampling. The value is passed through to the provider. The range depends on the provider and model. It is recommended to set either `temperature` or `topP`, but not both.', - }, - { - name: 'topK', - type: 'number', - isOptional: true, - description: - 'Only sample from the top K options for each subsequent token. Used to remove "long tail" low probability responses. Recommended for advanced use cases only. You usually only need to use temperature.', - }, - { - name: 'presencePenalty', - type: 'number', - isOptional: true, - description: - 'Presence penalty setting. It affects the likelihood of the model to repeat information that is already in the prompt. The value is passed through to the provider. The range depends on the provider and model.', - }, - { - name: 'frequencyPenalty', - type: 'number', - isOptional: true, - description: - 'Frequency penalty setting. It affects the likelihood of the model to repeatedly use the same words or phrases. The value is passed through to the provider. The range depends on the provider and model.', - }, - { - name: 'stopSequences', - type: 'string[]', - isOptional: true, - description: - 'Sequences that will stop the generation of the text. If the model generates any of these sequences, it will stop generating further text.', - }, - { - name: 'seed', - type: 'number', - isOptional: true, - description: - 'The seed (integer) to use for random sampling. If set and supported by the model, calls will generate deterministic results.', - }, - { - name: 'maxRetries', - type: 'number', - isOptional: true, - description: - 'Maximum number of retries. Set to 0 to disable retries. Default: 2.', - }, - { - name: 'abortSignal', - type: 'AbortSignal', - isOptional: true, - description: - 'An optional abort signal that can be used to cancel the call.', - }, - { - name: 'headers', - type: 'Record', - isOptional: true, - description: - 'Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.', - }, - { - name: 'tools', - type: 'ToolSet', - description: - 'Tools that are accessible to and can be called by the model.', - properties: [ - { - type: 'Tool', - parameters: [ - { - name: 'description', - isOptional: true, - type: 'string', - description: - 'Information about the purpose of the tool including details on how and when it can be used by the model.', - }, - { - name: 'inputSchema', - type: 'zod schema', - description: - 'The typed schema that describes the parameters of the tool that can also be used to validation and error handling.', - }, - { - name: 'generate', - isOptional: true, - type: '(async (parameters) => ReactNode) | AsyncGenerator', - description: - 'A function or a generator function that is called with the arguments from the tool call and yields React nodes as the UI.', - }, - ], - }, - ], - }, - { - name: 'toolChoice', - isOptional: true, - type: '"auto" | "none" | "required" | { "type": "tool", "toolName": string }', - description: - 'The tool choice setting. It specifies how tools are selected for execution. The default is "auto". "none" disables tool execution. "required" requires tools to be executed. { "type": "tool", "toolName": string } specifies a specific tool to execute.', - }, - { - name: 'text', - isOptional: true, - type: '(Text) => ReactNode', - description: 'Callback to handle the generated tokens from the model.', - properties: [ - { - type: 'Text', - parameters: [ - { - name: 'content', - type: 'string', - description: 'The full content of the completion.', - }, - { name: 'delta', type: 'string', description: 'The delta.' }, - { name: 'done', type: 'boolean', description: 'Is it done?' }, - ], - }, - ], - }, - { - name: 'providerOptions', - type: 'Record | undefined', - isOptional: true, - description: - 'Provider-specific options. The outer key is the provider name. The inner values are the metadata. Details depend on the provider.', - }, - { - name: 'onFinish', - type: '(result: OnFinishResult) => void', - isOptional: true, - description: - 'Callback that is called when the LLM response and all request tool executions (for tools that have a `generate` function) are finished.', - properties: [ - { - type: 'OnFinishResult', - parameters: [ - { - name: 'usage', - type: 'LanguageModelUsage', - description: 'The token usage of the generated text.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: 'The total number of input (prompt) tokens used.', - }, - { - name: 'inputTokenDetails', - type: 'LanguageModelInputTokenDetails', - description: - 'Detailed information about the input (prompt) tokens. See also: cached tokens and non-cached tokens.', - properties: [ - { - type: 'LanguageModelInputTokenDetails', - parameters: [ - { - name: 'noCacheTokens', - type: 'number | undefined', - description: - 'The number of non-cached input (prompt) tokens used.', - }, - { - name: 'cacheReadTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens read.', - }, - { - name: 'cacheWriteTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens written.', - }, - ], - }, - ], - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: 'The number of total output (completion) tokens used.', - }, - { - name: 'outputTokenDetails', - type: 'LanguageModelOutputTokenDetails', - description: - 'Detailed information about the output (completion) tokens.', - properties: [ - { - type: 'LanguageModelOutputTokenDetails', - parameters: [ - { - name: 'textTokens', - type: 'number | undefined', - description: 'The number of text tokens used.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - description: 'The number of reasoning tokens used.', - }, - ], - }, - ], - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used.', - }, - { - name: 'raw', - type: 'object | undefined', - isOptional: true, - description: 'Raw usage information from the provider. This is the provider\'s original usage information and may include additional fields.', - }, - ], - }, - ], - }, - { - name: 'value', - type: 'ReactNode', - description: 'The final ui node that was generated.', - }, - { - name: 'warnings', - type: 'Warning[] | undefined', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'response', - type: 'Response', - description: 'Optional response data.', - properties: [ - { - type: 'Response', - parameters: [ - { - name: 'headers', - isOptional: true, - type: 'Record', - description: 'Response headers.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - -]} -/> - -## Returns - -', - description: 'Response headers.', - }, - ], - }, - ], - }, - { - name: 'warnings', - type: 'Warning[] | undefined', - description: - 'Warnings from the model provider (e.g. unsupported settings).', - }, - { - name: 'stream', - type: 'AsyncIterable & ReadableStream', - description: - 'A stream with all events, including text deltas, tool calls, tool results, and errors. You can use it as either an AsyncIterable or a ReadableStream. When an error occurs, the stream will throw the error.', - properties: [ - { - type: 'StreamPart', - parameters: [ - { - name: 'type', - type: "'text-delta'", - description: 'The type to identify the object as text delta.', - }, - { - name: 'textDelta', - type: 'string', - description: 'The text delta.', - }, - ], - }, - { - type: 'StreamPart', - parameters: [ - { - name: 'type', - type: "'tool-call'", - description: 'The type to identify the object as tool call.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'toolName', - type: 'string', - description: - 'The name of the tool, which typically would be the name of the function.', - }, - { - name: 'args', - type: 'object based on zod schema', - description: - 'Parameters generated by the model to be used by the tool.', - }, - ], - }, - { - type: 'StreamPart', - parameters: [ - { - name: 'type', - type: "'error'", - description: 'The type to identify the object as error.', - }, - { - name: 'error', - type: 'Error', - description: - 'Describes the error that may have occurred during execution.', - }, - ], - }, - { - type: 'StreamPart', - parameters: [ - { - name: 'type', - type: "'finish'", - description: 'The type to identify the object as finish.', - }, - { - name: 'finishReason', - type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'", - description: 'The reason the model finished generating the text.', - }, - { - name: 'usage', - type: 'LanguageModelUsage', - description: 'The token usage of the generated text.', - properties: [ - { - type: 'LanguageModelUsage', - parameters: [ - { - name: 'inputTokens', - type: 'number | undefined', - description: - 'The total number of input (prompt) tokens used.', - }, - { - name: 'inputTokenDetails', - type: 'LanguageModelInputTokenDetails', - description: - 'Detailed information about the input (prompt) tokens. See also: cached tokens and non-cached tokens.', - properties: [ - { - type: 'LanguageModelInputTokenDetails', - parameters: [ - { - name: 'noCacheTokens', - type: 'number | undefined', - description: - 'The number of non-cached input (prompt) tokens used.', - }, - { - name: 'cacheReadTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens read.', - }, - { - name: 'cacheWriteTokens', - type: 'number | undefined', - description: - 'The number of cached input (prompt) tokens written.', - }, - ], - }, - ], - }, - { - name: 'outputTokens', - type: 'number | undefined', - description: - 'The number of total output (completion) tokens used.', - }, - { - name: 'outputTokenDetails', - type: 'LanguageModelOutputTokenDetails', - description: - 'Detailed information about the output (completion) tokens.', - properties: [ - { - type: 'LanguageModelOutputTokenDetails', - parameters: [ - { - name: 'textTokens', - type: 'number | undefined', - description: 'The number of text tokens used.', - }, - { - name: 'reasoningTokens', - type: 'number | undefined', - description: - 'The number of reasoning tokens used.', - }, - ], - }, - ], - }, - { - name: 'totalTokens', - type: 'number | undefined', - description: 'The total number of tokens used.', - }, - { - name: 'raw', - type: 'object | undefined', - isOptional: true, - description: - "Raw usage information from the provider. This is the provider's original usage information and may include additional fields.", - }, - ], - }, - ], - }, - ], - }, - ], - }, - ]} -/> - -## Examples - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/02-create-ai.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/02-create-ai.mdx deleted file mode 100644 index ad6508bd2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/02-create-ai.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: createAI -description: Reference for the createAI function from the AI SDK RSC ---- - -# `createAI` - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -Creates a client-server context provider that can be used to wrap parts of your application tree to easily manage both UI and AI states of your application. - -## Import - - - -## API Signature - -### Parameters - -', - description: 'Server side actions that can be called from the client.', - }, - { - name: 'initialAIState', - type: 'any', - description: 'Initial AI state to be used in the client.', - }, - { - name: 'initialUIState', - type: 'any', - description: 'Initial UI state to be used in the client.', - }, - { - name: 'onGetUIState', - type: '() => UIState', - description: 'is called during SSR to compare and update UI state.', - }, - { - name: 'onSetAIState', - type: '(Event) => void', - description: - 'is triggered whenever an update() or done() is called by the mutable AI state in your action, so you can safely store your AI state in the database.', - properties: [ - { - type: 'Event', - parameters: [ - { - name: 'state', - type: 'AIState', - description: 'The resulting AI state after the update.', - }, - { - name: 'done', - type: 'boolean', - description: - 'Whether the AI state updates have been finalized or not.', - }, - ], - }, - ], - }, - ]} -/> - -### Returns - -It returns an `` context provider. - -## Examples - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/03-create-streamable-ui.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/03-create-streamable-ui.mdx deleted file mode 100644 index fe602d330..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/03-create-streamable-ui.mdx +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: createStreamableUI -description: Reference for the createStreamableUI function from the AI SDK RSC ---- - -# `createStreamableUI` - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -Create a stream that sends UI from the server to the client. On the client side, it can be rendered as a normal React node. - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - - - -### Methods - - void', - description: - 'Updates the current UI node. It takes a new UI node and replaces the old one.', - }, - { - name: 'append', - type: '(ReactNode) => void', - description: - 'Appends a new UI node to the end of the old one. Once appended a new UI node, the previous UI node cannot be updated anymore.', - }, - { - name: 'done', - type: '(ReactNode | null) => void', - description: - 'Marks the UI node as finalized and closes the stream. Once called, the UI node cannot be updated or appended anymore. This method is always required to be called, otherwise the response will be stuck in a loading state.', - }, - { - name: 'error', - type: '(Error) => void', - description: - 'Signals that there is an error in the UI stream. It will be thrown on the client side and caught by the nearest error boundary component.', - }, - ]} -/> - -## Examples - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/04-create-streamable-value.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/04-create-streamable-value.mdx deleted file mode 100644 index 96b23f937..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/04-create-streamable-value.mdx +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: createStreamableValue -description: Reference for the createStreamableValue function from the AI SDK RSC ---- - -# `createStreamableValue` - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -Create a stream that sends values from the server to the client. The value can be any serializable data. - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - - - -### Methods - - StreamableValueWrapper', - description: 'Updates the current value with a new one.', - }, - { - name: 'append', - type: '(value: T) => StreamableValueWrapper', - description: - 'Appends a delta string to the current value. It requires the current value of the streamable to be a string.', - }, - { - name: 'done', - type: '(value?: T) => StreamableValueWrapper', - description: - 'Marks the value as finalized. You can either call it without any parameters or with a new value as the final state. Once called, the value cannot be updated or appended anymore. This method is always required to be called, otherwise the response will be stuck in a loading state.', - }, - { - name: 'error', - type: '(error: any) => StreamableValueWrapper', - description: - 'Signals that there is an error in the value stream. It will be thrown on the client side when consumed via `readStreamableValue` or `useStreamableValue`.', - }, - ]} -/> diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/05-read-streamable-value.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/05-read-streamable-value.mdx deleted file mode 100644 index 7aa784559..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/05-read-streamable-value.mdx +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: readStreamableValue -description: Reference for the readStreamableValue function from the AI SDK RSC ---- - -# `readStreamableValue` - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -It is a function that helps you read the streamable value from the client that was originally created using [`createStreamableValue`](/docs/reference/ai-sdk-rsc/create-streamable-value) on the server. - -## Import - - - -## Example - -```ts filename="app/actions.ts" -async function generate() { - 'use server'; - const streamable = createStreamableValue(''); - - streamable.append('Hello'); - streamable.append(' '); - streamable.append('World'); - streamable.done(); - - return streamable.value; -} -``` - -```tsx filename="app/page.tsx" highlight="12" -import { readStreamableValue } from '@ai-sdk/rsc'; - -export default function Page() { - const [generation, setGeneration] = useState(''); - - return ( -
- -
- ); -} -``` - -## API Signature - -### Parameters - - - -### Returns - -It returns an async iterator that contains the values emitted by the streamable value. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/06-get-ai-state.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/06-get-ai-state.mdx deleted file mode 100644 index 373c7dfd9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/06-get-ai-state.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: getAIState -description: Reference for the getAIState function from the AI SDK RSC ---- - -# `getAIState` - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -Get the current AI state. - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - -The AI state. - -## Examples - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/07-get-mutable-ai-state.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/07-get-mutable-ai-state.mdx deleted file mode 100644 index b650e7775..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/07-get-mutable-ai-state.mdx +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: getMutableAIState -description: Reference for the getMutableAIState function from the AI SDK RSC ---- - -# `getMutableAIState` - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -Get a mutable copy of the AI state. You can use this to update the state in the server. - -## Import - - - -## API Signature - -### Parameters - - - -### Returns - -The mutable AI state. - -### Methods - - void', - description: 'Updates the AI state with the new state.', - }, - { - name: 'done', - type: '(newState: any) => void', - description: - 'Updates the AI state with the new state, marks it as finalized and closes the stream.', - }, - ]} -/> - -## Examples - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/08-use-ai-state.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/08-use-ai-state.mdx deleted file mode 100644 index 2dc8fbbf4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/08-use-ai-state.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: useAIState -description: Reference for the useAIState function from the AI SDK RSC ---- - -# `useAIState` - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -It is a hook that enables you to read and update the AI state. The AI state is shared globally between all `useAIState` hooks under the same `` provider. - -The AI state is intended to contain context and information shared with the AI model, such as system messages, function responses, and other relevant data. - -## Import - - - -## API Signature - -### Returns - -Similar to useState, it is an array where the first element is the current AI state and the second element is a function to update the state. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/09-use-actions.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/09-use-actions.mdx deleted file mode 100644 index 16e084395..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/09-use-actions.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: useActions -description: Reference for the useActions function from the AI SDK RSC ---- - -# `useActions` - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -It is a hook to help you access your Server Actions from the client. This is particularly useful for building interfaces that require user interactions with the server. - -It is required to access these server actions via this hook because they are patched when passed through the context. Accessing them directly may result in a [Cannot find Client Component error](/docs/troubleshooting/server-actions-in-client-components). - -## Import - - - -## API Signature - -### Returns - -`Record`, a dictionary of server actions. - -## Examples - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/10-use-ui-state.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/10-use-ui-state.mdx deleted file mode 100644 index d9b8535f1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/10-use-ui-state.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: useUIState -description: Reference for the useUIState function from the AI SDK RSC ---- - -# `useUIState` - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -It is a hook that enables you to read and update the UI State. The state is client-side and can contain functions, React nodes, and other data. UIState is the visual representation of the AI state. - -## Import - - - -## API Signature - -### Returns - -Similar to useState, it is an array, where the first element is the current UI state and the second element is the function that updates the state. - -## Examples - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/11-use-streamable-value.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/11-use-streamable-value.mdx deleted file mode 100644 index 352ef4d55..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/11-use-streamable-value.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: useStreamableValue -description: Reference for the useStreamableValue function from the AI SDK RSC ---- - -# `useStreamableValue` - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -It is a React hook that takes a streamable value created using [`createStreamableValue`](/docs/reference/ai-sdk-rsc/create-streamable-value) and returns the current value, error, and pending state. - -## Import - - - -## Example - -This is useful for consuming streamable values received from a component's props. - -```tsx -function MyComponent({ streamableValue }) { - const [data, error, pending] = useStreamableValue(streamableValue); - - if (pending) return
Loading...
; - if (error) return
Error: {error.message}
; - - return
Data: {data}
; -} -``` - -## API Signature - -### Parameters - -It accepts a streamable value created using `createStreamableValue`. - -### Returns - -It is an array, where the first element contains the data, the second element contains an error if it is thrown anytime during the stream, and the third is a boolean indicating if the value is pending. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/20-render.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/20-render.mdx deleted file mode 100644 index 274150ee2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/20-render.mdx +++ /dev/null @@ -1,266 +0,0 @@ ---- -title: render (Removed) -description: Reference for the render function from the AI SDK RSC ---- - -# `render` (Removed) - -"render" has been removed in AI SDK 4.0. - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - -A helper function to create a streamable UI from LLM providers. This function is similar to AI SDK Core APIs and supports the same model interfaces. - -> **Note**: `render` has been deprecated in favor of [`streamUI`](/docs/reference/ai-sdk-rsc/stream-ui). During migration, please ensure that the `messages` parameter follows the updated [specification](/docs/reference/ai-sdk-rsc/stream-ui#messages). - -## Import (No longer available) - -The following import will no longer work since `render` has been removed: - - - -Use [`streamUI`](/docs/reference/ai-sdk-rsc/stream-ui) instead. - -## API Signature - -### Parameters - -', - description: 'A list of messages that represent a conversation.', - properties: [ - { - type: 'SystemMessage', - parameters: [ - { - name: 'role', - type: "'system'", - description: 'The role for the system message.', - }, - { - name: 'content', - type: 'string', - description: 'The content of the message.', - }, - ], - }, - { - type: 'UserMessage', - parameters: [ - { - name: 'role', - type: "'user'", - description: 'The role for the user message.', - }, - { - name: 'content', - type: 'string', - description: 'The content of the message.', - }, - ], - }, - { - type: 'AssistantMessage', - parameters: [ - { - name: 'role', - type: "'assistant'", - description: 'The role for the assistant message.', - }, - { - name: 'content', - type: 'string', - description: 'The content of the message.', - }, - { - name: 'tool_calls', - type: 'ToolCall[]', - description: 'A list of tool calls made by the model.', - properties: [ - { - type: 'ToolCall', - parameters: [ - { - name: 'id', - type: 'string', - description: 'The id of the tool call.', - }, - { - name: 'type', - type: "'function'", - description: 'The type of the tool call.', - }, - { - name: 'function', - type: 'Function', - description: 'The function to call.', - properties: [ - { - type: 'Function', - parameters: [ - { - name: 'name', - type: 'string', - description: 'The name of the function.', - }, - { - name: 'arguments', - type: 'string', - description: 'The arguments of the function.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - type: 'ToolMessage', - parameters: [ - { - name: 'role', - type: "'tool'", - description: 'The role for the tool message.', - }, - { - name: 'content', - type: 'string', - description: 'The content of the message.', - }, - { - name: 'toolCallId', - type: 'string', - description: 'The id of the tool call.', - }, - ], - }, - ], - }, - { - name: 'functions', - type: 'ToolSet', - isOptional: true, - description: - 'Tools that are accessible to and can be called by the model.', - properties: [ - { - type: 'Tool', - parameters: [ - { - name: 'description', - isOptional: true, - type: 'string', - description: - 'Information about the purpose of the tool including details on how and when it can be used by the model.', - }, - { - name: 'parameters', - type: 'zod schema', - description: - 'The typed schema that describes the parameters of the tool that can also be used to validation and error handling.', - }, - { - name: 'render', - isOptional: true, - type: 'async (parameters) => any', - description: - 'An async function that is called with the arguments from the tool call and produces a result.', - }, - ], - }, - ], - }, - { - name: 'tools', - type: 'ToolSet', - isOptional: true, - description: - 'Tools that are accessible to and can be called by the model.', - properties: [ - { - type: 'Tool', - parameters: [ - { - name: 'description', - isOptional: true, - type: 'string', - description: - 'Information about the purpose of the tool including details on how and when it can be used by the model.', - }, - { - name: 'parameters', - type: 'zod schema', - description: - 'The typed schema that describes the parameters of the tool that can also be used to validation and error handling.', - }, - { - name: 'render', - isOptional: true, - type: 'async (parameters) => any', - description: - 'An async function that is called with the arguments from the tool call and produces a result.', - }, - ], - }, - ], - }, - { - name: 'text', - isOptional: true, - type: '(Text) => ReactNode', - description: 'Callback to handle the generated tokens from the model.', - properties: [ - { - type: 'Text', - parameters: [ - { - name: 'content', - type: 'string', - description: 'The full content of the completion.', - }, - { name: 'delta', type: 'string', description: 'The delta.' }, - { name: 'done', type: 'boolean', description: 'Is it done?' }, - ], - }, - ], - }, - { - name: 'temperature', - isOptional: true, - type: 'number', - description: 'The temperature to use for the model.', - }, - ]} -/> - -### Returns - -It can return any valid ReactNode. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/index.mdx deleted file mode 100644 index 4fca5a9ac..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/03-ai-sdk-rsc/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: AI SDK RSC -description: Reference documentation for the AI SDK RSC -collapsed: true ---- - -# AI SDK RSC - - - AI SDK RSC is currently experimental. We recommend using [AI SDK - UI](/docs/ai-sdk-ui/overview) for production. For guidance on migrating from - RSC to UI, see our [migration guide](/docs/ai-sdk-rsc/migrating-to-ui). - - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-api-call-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-api-call-error.mdx deleted file mode 100644 index bf7ecbc33..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-api-call-error.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: AI_APICallError -description: Learn how to fix AI_APICallError ---- - -# AI_APICallError - -This error occurs when an API call fails. - -## Properties - -- `url`: The URL of the API request that failed -- `requestBodyValues`: The request body values sent to the API -- `statusCode`: The HTTP status code returned by the API (optional) -- `responseHeaders`: The response headers returned by the API (optional) -- `responseBody`: The response body returned by the API (optional) -- `isRetryable`: Whether the request can be retried based on the status code -- `data`: Any additional data associated with the error (optional) -- `cause`: The underlying error that caused the API call to fail (optional) - -## Checking for this Error - -You can check if an error is an instance of `AI_APICallError` using: - -```typescript -import { APICallError } from 'ai'; - -if (APICallError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-download-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-download-error.mdx deleted file mode 100644 index 889b3dc44..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-download-error.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: AI_DownloadError -description: Learn how to fix AI_DownloadError ---- - -# AI_DownloadError - -This error occurs when a download fails. - -## Properties - -- `url`: The URL that failed to download -- `statusCode`: The HTTP status code returned by the server (optional) -- `statusText`: The HTTP status text returned by the server (optional) -- `cause`: The underlying error that caused the download to fail (optional) -- `message`: The error message containing details about the download failure (optional, auto-generated) - -## Checking for this Error - -You can check if an error is an instance of `AI_DownloadError` using: - -```typescript -import { DownloadError } from 'ai'; - -if (DownloadError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-empty-response-body-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-empty-response-body-error.mdx deleted file mode 100644 index 9175cc458..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-empty-response-body-error.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: AI_EmptyResponseBodyError -description: Learn how to fix AI_EmptyResponseBodyError ---- - -# AI_EmptyResponseBodyError - -This error occurs when the server returns an empty response body. - -## Properties - -- `message`: The error message - -## Checking for this Error - -You can check if an error is an instance of `AI_EmptyResponseBodyError` using: - -```typescript -import { EmptyResponseBodyError } from 'ai'; - -if (EmptyResponseBodyError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-argument-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-argument-error.mdx deleted file mode 100644 index a61ddf15b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-argument-error.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: AI_InvalidArgumentError -description: Learn how to fix AI_InvalidArgumentError ---- - -# AI_InvalidArgumentError - -This error occurs when an invalid argument was provided. - -## Properties - -- `parameter`: The name of the parameter that is invalid -- `value`: The invalid value -- `message`: The error message - -## Checking for this Error - -You can check if an error is an instance of `AI_InvalidArgumentError` using: - -```typescript -import { InvalidArgumentError } from 'ai'; - -if (InvalidArgumentError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-data-content-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-data-content-error.mdx deleted file mode 100644 index d4f81ca12..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-data-content-error.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: AI_InvalidDataContentError -description: How to fix AI_InvalidDataContentError ---- - -# AI_InvalidDataContentError - -This error occurs when the data content provided in a multi-modal message part is invalid. Check out the [ prompt examples for multi-modal messages ](/docs/foundations/prompts#message-prompts). - -## Properties - -- `content`: The invalid content value -- `cause`: The underlying error that caused this error (optional) -- `message`: The error message describing the expected and received content types (optional, auto-generated) - -## Checking for this Error - -You can check if an error is an instance of `AI_InvalidDataContentError` using: - -```typescript -import { InvalidDataContentError } from 'ai'; - -if (InvalidDataContentError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-message-role-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-message-role-error.mdx deleted file mode 100644 index 47df50e8f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-message-role-error.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: AI_InvalidMessageRoleError -description: Learn how to fix AI_InvalidMessageRoleError ---- - -# AI_InvalidMessageRoleError - -This error occurs when an invalid message role is provided. - -## Properties - -- `role`: The invalid role value -- `message`: The error message (optional, auto-generated from `role`) - -## Checking for this Error - -You can check if an error is an instance of `AI_InvalidMessageRoleError` using: - -```typescript -import { InvalidMessageRoleError } from 'ai'; - -if (InvalidMessageRoleError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-prompt-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-prompt-error.mdx deleted file mode 100644 index 03f50c976..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-prompt-error.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: AI_InvalidPromptError -description: Learn how to fix AI_InvalidPromptError ---- - -# AI_InvalidPromptError - -This error occurs when the prompt provided is invalid. - -## Potential Causes - -### UI Messages - -You are passing a `UIMessage[]` as messages into e.g. `streamText`. - -You need to first convert them to a `ModelMessage[]` using `convertToModelMessages()`. - -```typescript -import { type UIMessage, generateText, convertToModelMessages } from 'ai'; - -const messages: UIMessage[] = [ - /* ... */ -]; - -const result = await generateText({ - // ... - messages: await convertToModelMessages(messages), -}); -``` - -## Properties - -- `prompt`: The invalid prompt value -- `message`: The error message (required in constructor) -- `cause`: The cause of the error (optional) - -## Checking for this Error - -You can check if an error is an instance of `AI_InvalidPromptError` using: - -```typescript -import { InvalidPromptError } from 'ai'; - -if (InvalidPromptError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-response-data-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-response-data-error.mdx deleted file mode 100644 index 3f69bdeb8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-response-data-error.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: AI_InvalidResponseDataError -description: Learn how to fix AI_InvalidResponseDataError ---- - -# AI_InvalidResponseDataError - -This error occurs when the server returns a response with invalid data content. - -## Properties - -- `data`: The invalid response data value -- `message`: The error message - -## Checking for this Error - -You can check if an error is an instance of `AI_InvalidResponseDataError` using: - -```typescript -import { InvalidResponseDataError } from 'ai'; - -if (InvalidResponseDataError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-tool-approval-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-tool-approval-error.mdx deleted file mode 100644 index 04fd96156..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-tool-approval-error.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: AI_InvalidToolApprovalError -description: Learn how to fix AI_InvalidToolApprovalError ---- - -# AI_InvalidToolApprovalError - -This error occurs when a tool approval response references an unknown `approvalId`. No matching `tool-approval-request` was found in the message history. - -## Properties - -- `approvalId`: The approval ID that was not found - -## Checking for this Error - -You can check if an error is an instance of `AI_InvalidToolApprovalError` using: - -```typescript -import { InvalidToolApprovalError } from 'ai'; - -if (InvalidToolApprovalError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-tool-input-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-tool-input-error.mdx deleted file mode 100644 index 1d48209b3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-invalid-tool-input-error.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: AI_InvalidToolInputError -description: Learn how to fix AI_InvalidToolInputError ---- - -# AI_InvalidToolInputError - -This error occurs when invalid tool input was provided. - -## Properties - -- `toolName`: The name of the tool with invalid inputs -- `toolInput`: The invalid tool inputs -- `message`: The error message -- `cause`: The cause of the error - -## Checking for this Error - -You can check if an error is an instance of `AI_InvalidToolInputError` using: - -```typescript -import { InvalidToolInputError } from 'ai'; - -if (InvalidToolInputError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-json-parse-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-json-parse-error.mdx deleted file mode 100644 index 9b04e885f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-json-parse-error.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: AI_JSONParseError -description: Learn how to fix AI_JSONParseError ---- - -# AI_JSONParseError - -This error occurs when JSON fails to parse. - -## Properties - -- `text`: The text value that could not be parsed -- `cause`: The underlying parsing error (required in constructor) - -## Checking for this Error - -You can check if an error is an instance of `AI_JSONParseError` using: - -```typescript -import { JSONParseError } from 'ai'; - -if (JSONParseError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-load-api-key-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-load-api-key-error.mdx deleted file mode 100644 index 4efc6fefa..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-load-api-key-error.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: AI_LoadAPIKeyError -description: Learn how to fix AI_LoadAPIKeyError ---- - -# AI_LoadAPIKeyError - -This error occurs when API key is not loaded successfully. - -## Properties - -- `message`: The error message - -## Checking for this Error - -You can check if an error is an instance of `AI_LoadAPIKeyError` using: - -```typescript -import { LoadAPIKeyError } from 'ai'; - -if (LoadAPIKeyError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-load-setting-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-load-setting-error.mdx deleted file mode 100644 index 0540e4a4c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-load-setting-error.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: AI_LoadSettingError -description: Learn how to fix AI_LoadSettingError ---- - -# AI_LoadSettingError - -This error occurs when a setting is not loaded successfully. - -## Properties - -- `message`: The error message - -## Checking for this Error - -You can check if an error is an instance of `AI_LoadSettingError` using: - -```typescript -import { LoadSettingError } from 'ai'; - -if (LoadSettingError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-message-conversion-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-message-conversion-error.mdx deleted file mode 100644 index 3b89c9394..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-message-conversion-error.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: AI_MessageConversionError -description: Learn how to fix AI_MessageConversionError ---- - -# AI_MessageConversionError - -This error occurs when message conversion fails. - -## Properties - -- `originalMessage`: The original message that failed conversion -- `message`: The error message - -## Checking for this Error - -You can check if an error is an instance of `AI_MessageConversionError` using: - -```typescript -import { MessageConversionError } from 'ai'; - -if (MessageConversionError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-content-generated-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-content-generated-error.mdx deleted file mode 100644 index 08985768b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-content-generated-error.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: AI_NoContentGeneratedError -description: Learn how to fix AI_NoContentGeneratedError ---- - -# AI_NoContentGeneratedError - -This error occurs when the AI provider fails to generate content. - -## Properties - -- `message`: The error message (optional, defaults to `'No content generated.'`) - -## Checking for this Error - -You can check if an error is an instance of `AI_NoContentGeneratedError` using: - -```typescript -import { NoContentGeneratedError } from 'ai'; - -if (NoContentGeneratedError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-image-generated-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-image-generated-error.mdx deleted file mode 100644 index e5f4a7c2b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-image-generated-error.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: AI_NoImageGeneratedError -description: Learn how to fix AI_NoImageGeneratedError ---- - -# AI_NoImageGeneratedError - -This error occurs when the AI provider fails to generate an image. -It can arise due to the following reasons: - -- The model failed to generate a response. -- The model generated an invalid response. - -## Properties - -- `message`: The error message (optional, defaults to `'No image generated.'`). -- `responses`: Metadata about the image model responses, including timestamp, model, and headers (optional). -- `cause`: The cause of the error. You can use this for more detailed error handling (optional). - -## Checking for this Error - -You can check if an error is an instance of `AI_NoImageGeneratedError` using: - -```typescript -import { generateImage, NoImageGeneratedError } from 'ai'; - -try { - await generateImage({ model, prompt }); -} catch (error) { - if (NoImageGeneratedError.isInstance(error)) { - console.log('NoImageGeneratedError'); - console.log('Cause:', error.cause); - console.log('Responses:', error.responses); - } -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-object-generated-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-object-generated-error.mdx deleted file mode 100644 index 3d26e08a4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-object-generated-error.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: AI_NoObjectGeneratedError -description: Learn how to fix AI_NoObjectGeneratedError ---- - -# AI_NoObjectGeneratedError - -This error occurs when the AI provider fails to generate a parsable object that conforms to the schema. -It can arise due to the following reasons: - -- The model failed to generate a response. -- The model generated a response that could not be parsed. -- The model generated a response that could not be validated against the schema. - -## Properties - -- `message`: The error message (optional, defaults to `'No object generated.'`). -- `text`: The text that was generated by the model. This can be the raw text or the tool call text, depending on the object generation mode (optional). -- `response`: Metadata about the language model response, including response id, timestamp, and model (required in constructor). -- `usage`: Request token usage (required in constructor). -- `finishReason`: Request finish reason. For example 'length' if model generated maximum number of tokens, this could result in a JSON parsing error (required in constructor). -- `cause`: The cause of the error (e.g. a JSON parsing error). You can use this for more detailed error handling (optional). - -## Checking for this Error - -You can check if an error is an instance of `AI_NoObjectGeneratedError` using: - -```typescript -import { generateText, NoObjectGeneratedError, Output } from 'ai'; - -try { - await generateText({ model, output: Output.object({ schema }), prompt }); -} catch (error) { - if (NoObjectGeneratedError.isInstance(error)) { - console.log('NoObjectGeneratedError'); - console.log('Cause:', error.cause); - console.log('Text:', error.text); - console.log('Response:', error.response); - console.log('Usage:', error.usage); - console.log('Finish Reason:', error.finishReason); - } -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-output-generated-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-output-generated-error.mdx deleted file mode 100644 index bb18a991c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-output-generated-error.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: AI_NoOutputGeneratedError -description: Learn how to fix AI_NoOutputGeneratedError ---- - -# AI_NoOutputGeneratedError - -This error is thrown when no LLM output was generated, e.g. because of errors. - -## Properties - -- `message`: The error message (optional, defaults to `'No output generated.'`) -- `cause`: The underlying error that caused no output to be generated (optional) - -## Checking for this Error - -You can check if an error is an instance of `AI_NoOutputGeneratedError` using: - -```typescript -import { NoOutputGeneratedError } from 'ai'; - -if (NoOutputGeneratedError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-speech-generated-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-speech-generated-error.mdx deleted file mode 100644 index 2b8e08f44..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-speech-generated-error.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: AI_NoSpeechGeneratedError -description: Learn how to fix AI_NoSpeechGeneratedError ---- - -# AI_NoSpeechGeneratedError - -This error occurs when no audio could be generated from the input. - -## Properties - -- `responses`: Array of speech model response metadata (required in constructor) - -## Checking for this Error - -You can check if an error is an instance of `AI_NoSpeechGeneratedError` using: - -```typescript -import { NoSpeechGeneratedError } from 'ai'; - -if (NoSpeechGeneratedError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-such-model-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-such-model-error.mdx deleted file mode 100644 index bfe1122c8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-such-model-error.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: AI_NoSuchModelError -description: Learn how to fix AI_NoSuchModelError ---- - -# AI_NoSuchModelError - -This error occurs when a model ID is not found. - -## Properties - -- `modelId`: The ID of the model that was not found -- `modelType`: The type of model (`'languageModel'`, `'embeddingModel'`, `'imageModel'`, `'transcriptionModel'`, `'speechModel'`, or `'rerankingModel'`) -- `message`: The error message (optional, auto-generated from `modelId` and `modelType`) - -## Checking for this Error - -You can check if an error is an instance of `AI_NoSuchModelError` using: - -```typescript -import { NoSuchModelError } from 'ai'; - -if (NoSuchModelError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-such-provider-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-such-provider-error.mdx deleted file mode 100644 index 0a914de89..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-such-provider-error.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: AI_NoSuchProviderError -description: Learn how to fix AI_NoSuchProviderError ---- - -# AI_NoSuchProviderError - -This error occurs when a provider ID is not found. - -## Properties - -- `providerId`: The ID of the provider that was not found -- `availableProviders`: Array of available provider IDs -- `modelId`: The ID of the model -- `modelType`: The type of model -- `message`: The error message - -## Checking for this Error - -You can check if an error is an instance of `AI_NoSuchProviderError` using: - -```typescript -import { NoSuchProviderError } from 'ai'; - -if (NoSuchProviderError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-such-tool-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-such-tool-error.mdx deleted file mode 100644 index 9eccd8dee..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-such-tool-error.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: AI_NoSuchToolError -description: Learn how to fix AI_NoSuchToolError ---- - -# AI_NoSuchToolError - -This error occurs when a model tries to call an unavailable tool. - -## Properties - -- `toolName`: The name of the tool that was not found -- `availableTools`: Array of available tool names (optional) -- `message`: The error message (optional, auto-generated from `toolName` and `availableTools`) - -## Checking for this Error - -You can check if an error is an instance of `AI_NoSuchToolError` using: - -```typescript -import { NoSuchToolError } from 'ai'; - -if (NoSuchToolError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-transcript-generated-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-transcript-generated-error.mdx deleted file mode 100644 index 83925f3d9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-transcript-generated-error.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: AI_NoTranscriptGeneratedError -description: Learn how to fix AI_NoTranscriptGeneratedError ---- - -# AI_NoTranscriptGeneratedError - -This error occurs when no transcript could be generated from the input. - -## Properties - -- `responses`: Array of transcription model response metadata (required in constructor) - -## Checking for this Error - -You can check if an error is an instance of `AI_NoTranscriptGeneratedError` using: - -```typescript -import { NoTranscriptGeneratedError } from 'ai'; - -if (NoTranscriptGeneratedError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-video-generated-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-video-generated-error.mdx deleted file mode 100644 index 5ef23b107..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-no-video-generated-error.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: AI_NoVideoGeneratedError -description: Learn how to fix AI_NoVideoGeneratedError ---- - -# AI_NoVideoGeneratedError - -This error occurs when the AI provider fails to generate a video. -It can arise due to the following reasons: - -- The model failed to generate a response. -- The model generated an invalid response. - -## Properties - -- `message`: The error message (optional, defaults to `'No video generated.'`). -- `responses`: Metadata about the video model responses, including timestamp, model, and headers (optional). -- `cause`: The cause of the error. You can use this for more detailed error handling (optional). - -## Checking for this Error - -You can check if an error is an instance of `AI_NoVideoGeneratedError` using: - -```typescript -import { - experimental_generateVideo as generateVideo, - NoVideoGeneratedError, -} from 'ai'; - -try { - await generateVideo({ model, prompt }); -} catch (error) { - if (NoVideoGeneratedError.isInstance(error)) { - console.log('NoVideoGeneratedError'); - console.log('Cause:', error.cause); - console.log('Responses:', error.responses); - } -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-retry-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-retry-error.mdx deleted file mode 100644 index 56396444c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-retry-error.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: AI_RetryError -description: Learn how to fix AI_RetryError ---- - -# AI_RetryError - -This error occurs when a retry operation fails. - -## Properties - -- `reason`: The reason for the retry failure -- `lastError`: The most recent error that occurred during retries -- `errors`: Array of all errors that occurred during retry attempts -- `message`: The error message - -## Checking for this Error - -You can check if an error is an instance of `AI_RetryError` using: - -```typescript -import { RetryError } from 'ai'; - -if (RetryError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-too-many-embedding-values-for-call-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-too-many-embedding-values-for-call-error.mdx deleted file mode 100644 index e8ee26b54..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-too-many-embedding-values-for-call-error.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: AI_TooManyEmbeddingValuesForCallError -description: Learn how to fix AI_TooManyEmbeddingValuesForCallError ---- - -# AI_TooManyEmbeddingValuesForCallError - -This error occurs when too many values are provided in a single embedding call. - -## Properties - -- `provider`: The AI provider name -- `modelId`: The ID of the embedding model -- `maxEmbeddingsPerCall`: The maximum number of embeddings allowed per call -- `values`: The array of values that was provided - -## Checking for this Error - -You can check if an error is an instance of `AI_TooManyEmbeddingValuesForCallError` using: - -```typescript -import { TooManyEmbeddingValuesForCallError } from 'ai'; - -if (TooManyEmbeddingValuesForCallError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-tool-call-not-found-for-approval-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-tool-call-not-found-for-approval-error.mdx deleted file mode 100644 index 4e6f60963..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-tool-call-not-found-for-approval-error.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: AI_ToolCallNotFoundForApprovalError -description: Learn how to fix AI_ToolCallNotFoundForApprovalError ---- - -# AI_ToolCallNotFoundForApprovalError - -This error occurs when a tool approval request references a tool call that was not found. This can happen when processing provider-emitted approval requests (e.g., MCP flows) where the referenced tool call ID does not exist. - -## Properties - -- `toolCallId`: The tool call ID that was not found -- `approvalId`: The approval request ID - -## Checking for this Error - -You can check if an error is an instance of `AI_ToolCallNotFoundForApprovalError` using: - -```typescript -import { ToolCallNotFoundForApprovalError } from 'ai'; - -if (ToolCallNotFoundForApprovalError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-tool-call-repair-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-tool-call-repair-error.mdx deleted file mode 100644 index baac4eced..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-tool-call-repair-error.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: ToolCallRepairError -description: Learn how to fix AI SDK ToolCallRepairError ---- - -# ToolCallRepairError - -This error occurs when there is a failure while attempting to repair an invalid tool call. -This typically happens when the AI attempts to fix either -a `NoSuchToolError` or `InvalidToolInputError`. - -## Properties - -- `originalError`: The original error that triggered the repair attempt (either `NoSuchToolError` or `InvalidToolInputError`) -- `message`: The error message -- `cause`: The underlying error that caused the repair to fail - -## Checking for this Error - -You can check if an error is an instance of `ToolCallRepairError` using: - -```typescript -import { ToolCallRepairError } from 'ai'; - -if (ToolCallRepairError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-type-validation-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-type-validation-error.mdx deleted file mode 100644 index 8e5b95874..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-type-validation-error.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: AI_TypeValidationError -description: Learn how to fix AI_TypeValidationError ---- - -# AI_TypeValidationError - -This error occurs when type validation fails. - -## Properties - -- `value`: The value that failed validation -- `cause`: The underlying validation error (required in constructor) - -## Checking for this Error - -You can check if an error is an instance of `AI_TypeValidationError` using: - -```typescript -import { TypeValidationError } from 'ai'; - -if (TypeValidationError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-ui-message-stream-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-ui-message-stream-error.mdx deleted file mode 100644 index f98cf9c09..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-ui-message-stream-error.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: AI_UIMessageStreamError -description: Learn how to fix AI_UIMessageStreamError ---- - -# AI_UIMessageStreamError - -This error occurs when a UI message stream contains invalid or out-of-sequence chunks. - -Common causes: - -- Receiving a `text-delta` chunk without a preceding `text-start` chunk -- Receiving a `text-end` chunk without a preceding `text-start` chunk -- Receiving a `reasoning-delta` chunk without a preceding `reasoning-start` chunk -- Receiving a `reasoning-end` chunk without a preceding `reasoning-start` chunk -- Receiving a `tool-input-delta` chunk without a preceding `tool-input-start` chunk -- Attempting to access a tool invocation that doesn't exist - -This error often surfaces when an upstream request fails **before any tokens are streamed** and a custom transport tries to write an inline error message to the UI stream without the proper start chunk. - -## Properties - -- `chunkType`: The type of chunk that caused the error (e.g., `text-delta`, `reasoning-end`, `tool-input-delta`) -- `chunkId`: The ID associated with the failing chunk (part ID or toolCallId) -- `message`: The error message with details about what went wrong - -## Checking for this Error - -You can check if an error is an instance of `AI_UIMessageStreamError` using: - -```typescript -import { UIMessageStreamError } from 'ai'; - -if (UIMessageStreamError.isInstance(error)) { - console.log('Chunk type:', error.chunkType); - console.log('Chunk ID:', error.chunkId); - // Handle the error -} -``` - -## Common Solutions - -1. **Ensure proper chunk ordering**: Always send a `*-start` chunk before any `*-delta` or `*-end` chunks for the same ID: - - ```typescript - // Correct order - writer.write({ type: 'text-start', id: 'my-text' }); - writer.write({ type: 'text-delta', id: 'my-text', delta: 'Hello' }); - writer.write({ type: 'text-end', id: 'my-text' }); - ``` - -2. **Verify IDs match**: Ensure the `id` used in `*-delta` and `*-end` chunks matches the `id` used in the corresponding `*-start` chunk. - -3. **Handle error paths correctly**: When writing error messages in custom transports, ensure you emit the full start/delta/end sequence: - - ```typescript - // When handling errors in custom transports - writer.write({ type: 'text-start', id: errorId }); - writer.write({ - type: 'text-delta', - id: errorId, - delta: 'Request failed...', - }); - writer.write({ type: 'text-end', id: errorId }); - ``` - -4. **Check stream producer logic**: Review your streaming implementation to ensure chunks are sent in the correct order, especially when dealing with concurrent operations or merged streams. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-unsupported-functionality-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-unsupported-functionality-error.mdx deleted file mode 100644 index eeebe1339..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/ai-unsupported-functionality-error.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: AI_UnsupportedFunctionalityError -description: Learn how to fix AI_UnsupportedFunctionalityError ---- - -# AI_UnsupportedFunctionalityError - -This error occurs when functionality is not supported. - -## Properties - -- `functionality`: The name of the unsupported functionality -- `message`: The error message (optional, auto-generated from `functionality`) - -## Checking for this Error - -You can check if an error is an instance of `AI_UnsupportedFunctionalityError` using: - -```typescript -import { UnsupportedFunctionalityError } from 'ai'; - -if (UnsupportedFunctionalityError.isInstance(error)) { - // Handle the error -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/index.mdx deleted file mode 100644 index 720366ff1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/05-ai-sdk-errors/index.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: AI SDK Errors -description: Troubleshooting information for common AI SDK errors. -collapsed: true ---- - -# AI SDK Errors - -- [AI_APICallError](/docs/reference/ai-sdk-errors/ai-api-call-error) -- [AI_DownloadError](/docs/reference/ai-sdk-errors/ai-download-error) -- [AI_EmptyResponseBodyError](/docs/reference/ai-sdk-errors/ai-empty-response-body-error) -- [AI_InvalidArgumentError](/docs/reference/ai-sdk-errors/ai-invalid-argument-error) -- [AI_InvalidDataContentError](/docs/reference/ai-sdk-errors/ai-invalid-data-content-error) -- [AI_InvalidMessageRoleError](/docs/reference/ai-sdk-errors/ai-invalid-message-role-error) -- [AI_InvalidPromptError](/docs/reference/ai-sdk-errors/ai-invalid-prompt-error) -- [AI_InvalidResponseDataError](/docs/reference/ai-sdk-errors/ai-invalid-response-data-error) -- [AI_InvalidToolApprovalError](/docs/reference/ai-sdk-errors/ai-invalid-tool-approval-error) -- [AI_InvalidToolInputError](/docs/reference/ai-sdk-errors/ai-invalid-tool-input-error) -- [AI_JSONParseError](/docs/reference/ai-sdk-errors/ai-json-parse-error) -- [AI_LoadAPIKeyError](/docs/reference/ai-sdk-errors/ai-load-api-key-error) -- [AI_LoadSettingError](/docs/reference/ai-sdk-errors/ai-load-setting-error) -- [AI_MessageConversionError](/docs/reference/ai-sdk-errors/ai-message-conversion-error) -- [AI_NoSpeechGeneratedError](/docs/reference/ai-sdk-errors/ai-no-speech-generated-error) -- [AI_NoContentGeneratedError](/docs/reference/ai-sdk-errors/ai-no-content-generated-error) -- [AI_NoImageGeneratedError](/docs/reference/ai-sdk-errors/ai-no-image-generated-error) -- [AI_NoTranscriptGeneratedError](/docs/reference/ai-sdk-errors/ai-no-transcript-generated-error) -- [AI_NoVideoGeneratedError](/docs/reference/ai-sdk-errors/ai-no-video-generated-error) -- [AI_NoObjectGeneratedError](/docs/reference/ai-sdk-errors/ai-no-object-generated-error) -- [AI_NoOutputGeneratedError](/docs/reference/ai-sdk-errors/ai-no-output-generated-error) -- [AI_NoSuchModelError](/docs/reference/ai-sdk-errors/ai-no-such-model-error) -- [AI_NoSuchProviderError](/docs/reference/ai-sdk-errors/ai-no-such-provider-error) -- [AI_NoSuchToolError](/docs/reference/ai-sdk-errors/ai-no-such-tool-error) -- [AI_RetryError](/docs/reference/ai-sdk-errors/ai-retry-error) -- [AI_ToolCallNotFoundForApprovalError](/docs/reference/ai-sdk-errors/ai-tool-call-not-found-for-approval-error) -- [AI_ToolCallRepairError](/docs/reference/ai-sdk-errors/ai-tool-call-repair-error) -- [AI_TooManyEmbeddingValuesForCallError](/docs/reference/ai-sdk-errors/ai-too-many-embedding-values-for-call-error) -- [AI_TypeValidationError](/docs/reference/ai-sdk-errors/ai-type-validation-error) -- [AI_UIMessageStreamError](/docs/reference/ai-sdk-errors/ai-ui-message-stream-error) -- [AI_UnsupportedFunctionalityError](/docs/reference/ai-sdk-errors/ai-unsupported-functionality-error) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/index.mdx deleted file mode 100644 index 7f0b0454c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/07-reference/index.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Reference -description: Reference documentation for the AI SDK ---- - -# API Reference - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/00-versioning.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/00-versioning.mdx deleted file mode 100644 index ab49bccc9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/00-versioning.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Versioning -description: Understand how the AI SDK approaches versioning. ---- - -# Versioning - -Each version number follows the format: `MAJOR.MINOR.PATCH` - -- **Major**: Breaking API updates that require code changes. -- **Minor**: Blog post that aggregates new features and improvements into a public release that highlights benefits. -- **Patch**: New features and bug fixes. - -## API Stability - -We communicate the stability of our APIs as follows: - -### Stable APIs - -All APIs without special prefixes are considered stable and ready for production use. We maintain backward compatibility for stable features and only introduce breaking changes in major releases. - -### Experimental APIs - -APIs prefixed with `experimental_` or `Experimental_` (e.g. `experimental_generateImage()`) are in development and can change in any releases. To use experimental APIs safely: - -1. Test them first in development, not production -2. Review release notes before upgrading -3. Prepare for potential code updates - - - If you use experimental APIs, make sure to pin your AI SDK version number - exactly (avoid using ^ or ~ version ranges) to prevent unexpected breaking - changes. - - -### Deprecated APIs - -APIs marked as `deprecated` will be removed in future major releases. You can wait until the major release to update your code. To handle deprecations: - -1. Switch to the recommended alternative API -2. Follow the migration guide (released alongside major releases) - - - For major releases, we provide automated codemods where possible to help - migrate your code to the new version. - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/24-migration-guide-6-0.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/24-migration-guide-6-0.mdx deleted file mode 100644 index e39c684e9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/24-migration-guide-6-0.mdx +++ /dev/null @@ -1,823 +0,0 @@ ---- -title: Migrate AI SDK 5.x to 6.0 -description: Learn how to upgrade AI SDK 5.x to 6.0. ---- - -# Migrate AI SDK 5.x to 6.0 - -## Recommended Migration Process - -1. Backup your project. If you use a versioning control system, make sure all previous versions are committed. -1. Upgrade to AI SDK 6.0. -1. Follow the breaking changes guide below. -1. Verify your project is working as expected. -1. Commit your changes. - -## AI SDK 6.0 Package Versions - -You need to update the following packages to the latest versions in your `package.json` file(s): - -- `ai` package: `^6.0.0` -- `@ai-sdk/provider` package: `^3.0.0` -- `@ai-sdk/provider-utils` package: `^4.0.0` -- `@ai-sdk/*` packages: `^3.0.0` - -An example upgrade command would be: - -``` -pnpm install ai@latest @ai-sdk/react@latest @ai-sdk/openai@latest -``` - -## Codemods - -The AI SDK provides Codemod transformations to help upgrade your codebase when a -feature is deprecated, removed, or otherwise changed. - -Codemods are transformations that run on your codebase automatically. They -allow you to easily apply many changes without having to manually go through -every file. - -You can run all v6 codemods (v5 → v6 migration) by running the following command -from the root of your project: - -```sh -npx @ai-sdk/codemod v6 -``` - - - There is also an `npx @ai-sdk/codemod upgrade` command, but it runs all - codemods from all versions (v4, v5, and v6). Use `v6` when upgrading from v5. - - -Individual codemods can be run by specifying the name of the codemod: - -```sh -npx @ai-sdk/codemod -``` - -For example, to run a specific v6 codemod: - -```sh -npx @ai-sdk/codemod v6/rename-text-embedding-to-embedding src/ -``` - - - Codemods are intended as a tool to help you with the upgrade process. They may - not cover all of the changes you need to make. You may need to make additional - changes manually. - - -## Codemod Table - -| Codemod Name | Description | -| -------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | -| `rename-text-embedding-to-embedding` | Renames `textEmbeddingModel` to `embeddingModel` and `textEmbedding` to `embedding` on providers | -| `rename-mock-v2-to-v3` | Renames V2 mock classes from `ai/test` to V3 (e.g., `MockLanguageModelV2` → `MockLanguageModelV3`) | -| `rename-tool-call-options-to-tool-execution-options` | Renames the `ToolCallOptions` type to `ToolExecutionOptions` | -| `rename-core-message-to-model-message` | Renames the `CoreMessage` type to `ModelMessage` | -| `rename-converttocoremessages-to-converttomodelmessages` | Renames `convertToCoreMessages` function to `convertToModelMessages` | -| `rename-vertex-provider-metadata-key` | Renames `google` to `vertex` in `providerMetadata` and `providerOptions` for Google Vertex files | -| `wrap-tomodeloutput-parameter` | Wraps `toModelOutput` parameter in object destructuring (`output` → `{ output }`) | -| `add-await-converttomodelmessages` | Adds `await` to `convertToModelMessages` calls (now async in AI SDK 6) | - -## AI SDK Core - -### `Experimental_Agent` to `ToolLoopAgent` Class - -The `Experimental_Agent` class has been replaced with the `ToolLoopAgent` class. Two key changes: - -1. The `system` parameter has been renamed to `instructions` -2. The default `stopWhen` has changed from `stepCountIs(1)` to `stepCountIs(20)` - -```tsx filename="AI SDK 5" -import { Experimental_Agent as Agent, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new Agent({ - model: __MODEL__, - system: 'You are a helpful assistant.', - tools: { - // your tools here - }, - stopWhen: stepCountIs(20), // Required for multi-step agent loops -}); - -const result = await agent.generate({ - prompt: 'What is the weather in San Francisco?', -}); -``` - -```tsx filename="AI SDK 6" -import { ToolLoopAgent } from 'ai'; -__PROVIDER_IMPORT__; - -const agent = new ToolLoopAgent({ - model: __MODEL__, - instructions: 'You are a helpful assistant.', - tools: { - // your tools here - }, - // stopWhen defaults to stepCountIs(20) -}); - -const result = await agent.generate({ - prompt: 'What is the weather in San Francisco?', -}); -``` - -Learn more about [building agents](/docs/agents/building-agents). - -### `CoreMessage` Removal - -The deprecated `CoreMessage` type and related functions have been removed ([PR #10710](https://github.com/vercel/ai/pull/10710)). Replace `convertToCoreMessages` with `convertToModelMessages`. - -```tsx filename="AI SDK 5" -import { convertToCoreMessages, type CoreMessage } from 'ai'; - -const coreMessages = convertToCoreMessages(messages); // CoreMessage[] -``` - -```tsx filename="AI SDK 6" -import { convertToModelMessages, type ModelMessage } from 'ai'; - -const modelMessages = await convertToModelMessages(messages); // ModelMessage[] -``` - - - Use the `rename-core-message-to-model-message` and - `rename-converttocoremessages-to-converttomodelmessages` codemods to - automatically update your codebase. - - -### `generateObject` and `streamObject` Deprecation - -`generateObject` and `streamObject` have been deprecated ([PR #10754](https://github.com/vercel/ai/pull/10754)). -They will be removed in a future version. -Use `generateText` and `streamText` with an `output` setting instead. - -```tsx filename="AI SDK 5" -import { generateObject } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const { object } = await generateObject({ - model: __MODEL__, - schema: z.object({ - recipe: z.object({ - name: z.string(), - ingredients: z.array(z.object({ name: z.string(), amount: z.string() })), - steps: z.array(z.string()), - }), - }), - prompt: 'Generate a lasagna recipe.', -}); -``` - -```tsx filename="AI SDK 6" -import { generateText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const { output } = await generateText({ - model: __MODEL__, - output: Output.object({ - schema: z.object({ - recipe: z.object({ - name: z.string(), - ingredients: z.array( - z.object({ name: z.string(), amount: z.string() }), - ), - steps: z.array(z.string()), - }), - }), - }), - prompt: 'Generate a lasagna recipe.', -}); -``` - -For streaming structured data, replace `streamObject` with `streamText`: - -```tsx filename="AI SDK 5" -import { streamObject } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const { partialObjectStream } = streamObject({ - model: __MODEL__, - schema: z.object({ - recipe: z.object({ - name: z.string(), - ingredients: z.array(z.object({ name: z.string(), amount: z.string() })), - steps: z.array(z.string()), - }), - }), - prompt: 'Generate a lasagna recipe.', -}); - -for await (const partialObject of partialObjectStream) { - console.log(partialObject); -} -``` - -```tsx filename="AI SDK 6" -import { streamText, Output } from 'ai'; -__PROVIDER_IMPORT__; -import { z } from 'zod'; - -const { partialOutputStream } = streamText({ - model: __MODEL__, - output: Output.object({ - schema: z.object({ - recipe: z.object({ - name: z.string(), - ingredients: z.array( - z.object({ name: z.string(), amount: z.string() }), - ), - steps: z.array(z.string()), - }), - }), - }), - prompt: 'Generate a lasagna recipe.', -}); - -for await (const partialObject of partialOutputStream) { - console.log(partialObject); -} -``` - -Learn more about [generating structured data](/docs/ai-sdk-core/generating-structured-data). - -### async `convertToModelMessages` - -`convertToModelMessages()` is async in AI SDK 6 to support async `Tool.toModelOutput()`. - -```tsx filename="AI SDK 5" -import { convertToModelMessages } from 'ai'; - -const modelMessages = convertToModelMessages(uiMessages); -``` - -```tsx filename="AI SDK 6" -import { convertToModelMessages } from 'ai'; - -const modelMessages = await convertToModelMessages(uiMessages); -``` - - - Use the `add-await-converttomodelmessages` codemod to automatically update - your codebase. - - -### `Tool.toModelOutput` changes - -`toModelOutput()` receives a parameter object with an `output` property in AI SDK 6. - -In AI SDK 5, the `output` was the arguments. - -```tsx filename="AI SDK 5" -import { tool } from 'ai'; - -const someTool = tool({ - // ... - toModelOutput: output => { - // ... - }, -}); -``` - -```tsx filename="AI SDK 6" -import { tool } from 'ai'; - -const someTool = tool({ - // ... - toModelOutput: ({ output }) => { - // ... - }, -}); -``` - - - Use the `wrap-tomodeloutput-parameter` codemod to automatically update your - codebase. - - -### `cachedInputTokens` and `reasoningTokens` in `LanguageModelUsage` Deprecation - -`cachedInputTokens` and `reasoningTokens` in `LanguageModelUsage` have been deprecated. - -You can replace `cachedInputTokens` with `inputTokenDetails.cacheReadTokens` -and `reasoningTokens` with `outputTokenDetails.reasoningTokens`. - -### `ToolCallOptions` to `ToolExecutionOptions` Rename - -The `ToolCallOptions` type has been renamed to `ToolExecutionOptions` -and is now deprecated. - - - Use the `rename-tool-call-options-to-tool-execution-options` codemod to - automatically update your codebase. - - -### Per-Tool Strict Mode - -Strict mode for tools is now controlled by setting `strict` on each tool ([PR #10817](https://github.com/vercel/ai/pull/10817)). This enables fine-grained control over strict tool calls, which is important since strict mode depends on the specific tool input schema. - -```tsx filename="AI SDK 5" -__PROVIDER_IMPORT__; -import { streamText, tool } from 'ai'; -import { z } from 'zod'; - -// Tool strict mode was controlled by strictJsonSchema -const result = streamText({ - model: __MODEL__, - tools: { - calculator: tool({ - description: 'A simple calculator', - inputSchema: z.object({ - expression: z.string(), - }), - execute: async ({ expression }) => { - const result = eval(expression); - return { result }; - }, - }), - }, - providerOptions: { - openai: { - strictJsonSchema: true, // Applied to all tools - }, - }, -}); -``` - -```tsx filename="AI SDK 6" -__PROVIDER_IMPORT__; -import { streamText, tool } from 'ai'; -import { z } from 'zod'; - -const result = streamText({ - model: __MODEL__, - tools: { - calculator: tool({ - description: 'A simple calculator', - inputSchema: z.object({ - expression: z.string(), - }), - execute: async ({ expression }) => { - const result = eval(expression); - return { result }; - }, - strict: true, // Control strict mode per tool - }), - }, -}); -``` - -### Flexible Tool Content - -AI SDK 6 introduces more flexible tool output and result content support ([PR #9605](https://github.com/vercel/ai/pull/9605)), enabling richer tool interactions and better support for complex tool execution patterns. - -### `ToolCallRepairFunction` Signature - -The `system` parameter in the `ToolCallRepairFunction` type now accepts `SystemModelMessage` in addition to `string` ([PR #10635](https://github.com/vercel/ai/pull/10635)). This allows for more flexible system message configuration, including provider-specific options like caching. - -```tsx filename="AI SDK 5" -import type { ToolCallRepairFunction } from 'ai'; - -const repairToolCall: ToolCallRepairFunction = async ({ - system, // type: string | undefined - messages, - toolCall, - tools, - inputSchema, - error, -}) => { - // ... -}; -``` - -```tsx filename="AI SDK 6" -import type { ToolCallRepairFunction, SystemModelMessage } from 'ai'; - -const repairToolCall: ToolCallRepairFunction = async ({ - system, // type: string | SystemModelMessage | undefined - messages, - toolCall, - tools, - inputSchema, - error, -}) => { - // Handle both string and SystemModelMessage - const systemText = typeof system === 'string' ? system : system?.content; - // ... -}; -``` - -### Embedding Model Method Rename - -The `textEmbeddingModel` and `textEmbedding` methods on providers have been renamed to `embeddingModel` and `embedding` respectively. Additionally, generics have been removed from `EmbeddingModel`, `embed`, and `embedMany` ([PR #10592](https://github.com/vercel/ai/pull/10592)). - -```tsx filename="AI SDK 5" -import { openai } from '@ai-sdk/openai'; -import { embed } from 'ai'; - -// Using the full method name -const model = openai.textEmbeddingModel('text-embedding-3-small'); - -// Using the shorthand -const model = openai.textEmbedding('text-embedding-3-small'); - -const { embedding } = await embed({ - model: openai.textEmbedding('text-embedding-3-small'), - value: 'sunny day at the beach', -}); -``` - -```tsx filename="AI SDK 6" -import { openai } from '@ai-sdk/openai'; -import { embed } from 'ai'; - -// Using the full method name -const model = openai.embeddingModel('text-embedding-3-small'); - -// Using the shorthand -const model = openai.embedding('text-embedding-3-small'); - -const { embedding } = await embed({ - model: openai.embedding('text-embedding-3-small'), - value: 'sunny day at the beach', -}); -``` - - - Use the `rename-text-embedding-to-embedding` codemod to automatically update - your codebase. - - -### Warning Logger - -AI SDK 6 introduces a warning logger that outputs deprecation warnings and best practice recommendations ([PR #8343](https://github.com/vercel/ai/pull/8343)). - -To disable warning logging, set the `AI_SDK_LOG_WARNINGS` environment variable to `false`: - -```bash -export AI_SDK_LOG_WARNINGS=false -``` - -### Warning Type Unification - -Separate warning types for each generation function have been consolidated into a single `Warning` type exported from the `ai` package ([PR #10631](https://github.com/vercel/ai/pull/10631)). - -```tsx filename="AI SDK 5" -// Separate warning types for each generation function -import type { - CallWarning, - ImageModelCallWarning, - SpeechWarning, - TranscriptionWarning, -} from 'ai'; -``` - -```tsx filename="AI SDK 6" -// Single Warning type for all generation functions -import type { Warning } from 'ai'; -``` - -### Finish reason "unknown" merged into "other" - -The `unknown` finish reason has been removed. It is now returned as `other`. - -## AI SDK UI - -### Tool UI Part Helper Functions Rename - -The tool UI part helper functions have been renamed to better reflect their purpose and to accommodate both static and dynamic tool parts ([PR #XXXX](https://github.com/vercel/ai/pull/XXXX)). - -#### `isToolUIPart` → `isStaticToolUIPart` - -The `isToolUIPart` function has been renamed to `isStaticToolUIPart` to clarify that it checks for static tool parts only. - -```tsx filename="AI SDK 5" -import { isToolUIPart } from 'ai'; - -// Check if a part is a tool UI part -if (isToolUIPart(part)) { - console.log(part.toolName); -} -``` - -```tsx filename="AI SDK 6" -import { isStaticToolUIPart } from 'ai'; - -// Check if a part is a static tool UI part -if (isStaticToolUIPart(part)) { - console.log(part.toolName); -} -``` - -#### `isToolOrDynamicToolUIPart` → `isToolUIPart` - -The `isToolOrDynamicToolUIPart` function has been renamed to `isToolUIPart`. The old name is deprecated but still available. - -```tsx filename="AI SDK 5" -import { isToolOrDynamicToolUIPart } from 'ai'; - -// Check if a part is either a static or dynamic tool UI part -if (isToolOrDynamicToolUIPart(part)) { - console.log('Tool part found'); -} -``` - -```tsx filename="AI SDK 6" -import { isToolUIPart } from 'ai'; - -// Check if a part is either a static or dynamic tool UI part -if (isToolUIPart(part)) { - console.log('Tool part found'); -} -``` - -#### `getToolName` → `getStaticToolName` - -The `getToolName` function has been renamed to `getStaticToolName` to clarify that it returns the tool name from static tool parts only. - -```tsx filename="AI SDK 5" -import { getToolName } from 'ai'; - -// Get the tool name from a tool part -const name = getToolName(toolPart); -``` - -```tsx filename="AI SDK 6" -import { getStaticToolName } from 'ai'; - -// Get the tool name from a static tool part -const name = getStaticToolName(toolPart); -``` - -#### `getToolOrDynamicToolName` → `getToolName` - -The `getToolOrDynamicToolName` function has been renamed to `getToolName`. The old name is deprecated but still available. - -```tsx filename="AI SDK 5" -import { getToolOrDynamicToolName } from 'ai'; - -// Get the tool name from either a static or dynamic tool part -const name = getToolOrDynamicToolName(toolPart); -``` - -```tsx filename="AI SDK 6" -import { getToolName } from 'ai'; - -// Get the tool name from either a static or dynamic tool part -const name = getToolName(toolPart); -``` - -## Providers - -### OpenAI - -#### `strictJsonSchema` Defaults to True - -The `strictJsonSchema` setting for JSON outputs and tool calls is enabled by default ([PR #10752](https://github.com/vercel/ai/pull/10752)). This improves stability and ensures valid JSON output that matches your schema. - -However, strict mode is stricter about schema requirements. If you receive schema rejection errors, adjust your schema (for example, use `null` instead of `undefined`) or disable strict mode. - -```tsx filename="AI SDK 5" -import { openai } from '@ai-sdk/openai'; -import { generateObject } from 'ai'; -import { z } from 'zod'; - -// strictJsonSchema was false by default -const result = await generateObject({ - model: openai('gpt-5.1'), - schema: z.object({ - name: z.string(), - }), - prompt: 'Generate a person', -}); -``` - -```tsx filename="AI SDK 6" -import { openai } from '@ai-sdk/openai'; -import { generateObject } from 'ai'; -import { z } from 'zod'; - -// strictJsonSchema is true by default -const result = await generateObject({ - model: openai('gpt-5.1'), - schema: z.object({ - name: z.string(), - }), - prompt: 'Generate a person', -}); - -// Disable strict mode if needed -const resultNoStrict = await generateObject({ - model: openai('gpt-5.1'), - schema: z.object({ - name: z.string(), - }), - prompt: 'Generate a person', - providerOptions: { - openai: { - strictJsonSchema: false, - } satisfies OpenAIResponsesProviderOptions, - }, -}); -``` - -#### `structuredOutputs` Option Removed from Chat Model - -The `structuredOutputs` provider option has been removed from chat models ([PR #10752](https://github.com/vercel/ai/pull/10752)). Use `strictJsonSchema` instead. - -### Azure - -#### Default Provider Uses Responses API - -The `@ai-sdk/azure` provider now uses the Responses API by default when calling `azure()` ([PR #9868](https://github.com/vercel/ai/pull/9868)). To use the previous Chat Completions API behavior, use `azure.chat()` instead. - -```tsx filename="AI SDK 5" -import { azure } from '@ai-sdk/azure'; - -// Used Chat Completions API -const model = azure('gpt-4o'); -``` - -```tsx filename="AI SDK 6" -import { azure } from '@ai-sdk/azure'; - -// Now uses Responses API by default -const model = azure('gpt-4o'); - -// Use azure.chat() for Chat Completions API -const chatModel = azure.chat('gpt-4o'); - -// Use azure.responses() explicitly for Responses API -const responsesModel = azure.responses('gpt-4o'); -``` - - - The Responses and Chat Completions APIs have different behavior and defaults. - If you depend on the Chat Completions API, switch your model instance to - `azure.chat()` and audit your configuration. - - -#### Responses API `providerMetadata` and `providerOptions` Key - -For the **Responses API**, the `@ai-sdk/azure` provider now uses `azure` as the key for `providerMetadata` and `providerOptions` instead of `openai`. The `openai` key is still supported for `providerOptions` input, but resulting `providerMetadata` output now uses `azure`. - -```tsx filename="AI SDK 5" -import { azure } from '@ai-sdk/azure'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: azure.responses('gpt-5-mini'), // use your own deployment - prompt: 'Hello', - providerOptions: { - openai: { - // AI SDK 5: use `openai` key for Responses API options - reasoningSummary: 'auto', - }, - }, -}); - -// Accessed metadata via 'openai' key -console.log(result.providerMetadata?.openai?.responseId); -``` - -```tsx filename="AI SDK 6" -import { azure } from '@ai-sdk/azure'; -import { generateText } from 'ai'; - -const result = await generateText({ - // azure() now uses the Responses API by default - model: azure('gpt-5-mini'), // use your own deployment - prompt: 'Hello', - providerOptions: { - azure: { - // AI SDK 6: use `azure` key for Responses API options - reasoningSummary: 'auto', - }, - }, -}); - -// Access metadata via 'azure' key -console.log(result.providerMetadata?.azure?.responseId); -``` - -### Anthropic - -#### Structured Outputs Mode - -Anthropic has [ introduced native structured outputs for Claude Sonnet 4.5 and later models ](https://www.claude.com/blog/structured-outputs-on-the-claude-developer-platform). The `@ai-sdk/anthropic` provider now includes a `structuredOutputMode` option to control how structured outputs are generated ([PR #10502](https://github.com/vercel/ai/pull/10502)). - -The available modes are: - -- `'outputFormat'`: Use Anthropic's native `output_format` parameter -- `'jsonTool'`: Use a special JSON tool to specify the structured output format -- `'auto'` (default): Use `'outputFormat'` when supported by the model, otherwise fall back to `'jsonTool'` - -```tsx filename="AI SDK 6" -import { anthropic } from '@ai-sdk/anthropic'; -import { generateObject } from 'ai'; -import { z } from 'zod'; - -const result = await generateObject({ - model: anthropic('claude-sonnet-4-5-20250929'), - schema: z.object({ - name: z.string(), - age: z.number(), - }), - prompt: 'Generate a person', - providerOptions: { - anthropic: { - // Explicitly set the structured output mode (optional) - structuredOutputMode: 'outputFormat', - } satisfies AnthropicProviderOptions, - }, -}); -``` - -### Google Vertex - -#### `providerMetadata` and `providerOptions` Key - -The `@ai-sdk/google-vertex` provider now uses `vertex` as the key for `providerMetadata` and `providerOptions` instead of `google`. The `google` key is still supported for `providerOptions` input, but resulting `providerMetadata` output now uses `vertex`. - -```tsx filename="AI SDK 5" -import { vertex } from '@ai-sdk/google-vertex'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: vertex('gemini-2.5-flash'), - providerOptions: { - google: { - safetySettings: [ - /* ... */ - ], - }, // Used 'google' key - }, - prompt: 'Hello', -}); - -// Accessed metadata via 'google' key -console.log(result.providerMetadata?.google?.safetyRatings); -``` - -```tsx filename="AI SDK 6" -import { vertex } from '@ai-sdk/google-vertex'; -import { generateText } from 'ai'; - -const result = await generateText({ - model: vertex('gemini-2.5-flash'), - providerOptions: { - vertex: { - safetySettings: [ - /* ... */ - ], - }, // Now uses 'vertex' key - }, - prompt: 'Hello', -}); - -// Access metadata via 'vertex' key -console.log(result.providerMetadata?.vertex?.safetyRatings); -``` - - - Use the `rename-vertex-provider-metadata-key` codemod to automatically update - your codebase. - - -## `ai/test` - -### Mock Classes - -V2 mock classes have been removed from the `ai/test` module. Use the new V3 mock classes instead for testing. - -```tsx filename="AI SDK 5" -import { - MockEmbeddingModelV2, - MockImageModelV2, - MockLanguageModelV2, - MockProviderV2, - MockSpeechModelV2, - MockTranscriptionModelV2, -} from 'ai/test'; -``` - -```tsx filename="AI SDK 6" -import { - MockEmbeddingModelV3, - MockImageModelV3, - MockLanguageModelV3, - MockProviderV3, - MockSpeechModelV3, - MockTranscriptionModelV3, -} from 'ai/test'; -``` - - - Use the `rename-mock-v2-to-v3` codemod to automatically update your codebase. - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/25-migration-guide-5-0-data.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/25-migration-guide-5-0-data.mdx deleted file mode 100644 index 428111a17..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/25-migration-guide-5-0-data.mdx +++ /dev/null @@ -1,882 +0,0 @@ ---- -title: Migrate Your Data to AI SDK 5.0 -description: Learn how to migrate your persisted messages and chat data from AI SDK 4.x to 5.0. ---- - -# Migrate Your Data to AI SDK 5.0 - -AI SDK 5.0 introduces changes to the message structure and persistence patterns. Unlike code migrations that can often be automated with codemods, data migration depends on your specific persistence approach, database schema, and application requirements. - -**This guide helps you get your application working with AI SDK 5.0 first** using a runtime conversion layer. This allows you to update your app immediately without database migrations blocking you. You can then migrate your data schema at your own pace. - -## Recommended Migration Process - -Follow this two-phase approach for a safe migration: - -### Phase 1: Get Your App Working (Runtime Conversion) - -**Goal:** Update your application to AI SDK 5.0 without touching your database. - -1. Update dependencies (install v4 types alongside v5) -2. Add conversion functions to transform between v4 and v5 message formats -3. Update data fetching logic to convert messages when reading from the database -4. Update the rest of your application code to AI SDK 5.0 (see the [main migration guide](/docs/migration-guides/migration-guide-5-0)) - -Your database schema remains unchanged during Phase 1. You're only adding a conversion layer that transforms messages at runtime. - -**Timeline:** Can be completed in hours or days. - -### Phase 2: Migrate to V5 Schema (Recommended) - -**Goal:** Migrate your data to a v5-compatible schema, eliminating the runtime conversion overhead. - -While Phase 1 gets you working immediately, migrate your schema soon after completing Phase 1. This phase uses a side-by-side migration approach with an equivalent v5 schema: - -1. Create `messages_v5` table alongside existing `messages` table -2. Start dual-writing to both tables (with conversion) -3. Run a background migration to convert existing messages -4. Switch reads to the v5 schema -5. Remove conversion from your route handlers -6. Remove dual-write (write only to v5) -7. Drop old tables - -**Timeline:** Do this soon after Phase 1. - -**Why this matters:** - -- Removes runtime conversion overhead -- Eliminates technical debt early -- Type safety with v5 message format -- Easier to maintain and extend - -## Understanding the Changes - -Before starting, understand the main persistence-related changes in AI SDK 5.0: - -**AI SDK 4.0:** - -- `content` field for text -- `reasoning` as a top-level property -- `toolInvocations` as a top-level property -- `parts` (optional) ordered array - -**AI SDK 5.0:** - -- `parts` array is the single source of truth -- `content` is removed (deprecated) and accessed via a `text` part -- `reasoning` is removed and replaced with a `reasoning` part -- `toolInvocations` is removed and replaced with `tool-${toolName}` parts with `input`/`output` (renamed from `args`/`result`) -- `data` role removed (use data parts instead) - -## Phase 1: Runtime Conversion Pattern - -This creates a conversion layer without making changes to your database schema. - -### Step 1: Update Dependencies - -To get proper TypeScript types for your v4 messages, install the v4 package alongside v5 using npm aliases: - -```json filename="package.json" -{ - "dependencies": { - "ai": "^5.0.0", - "ai-legacy": "npm:ai@^4.3.2" - } -} -``` - -Run: - -```bash -pnpm install -``` - -Import v4 types for proper type safety: - -```tsx -import type { Message as V4Message } from 'ai-legacy'; -import type { UIMessage } from 'ai'; -``` - -### Step 2: Add Conversion Functions - -Create type guards to detect which message format you're working with, and build a conversion function that handles all v4 message types: - -```tsx -import type { - ToolInvocation, - Message as V4Message, - UIMessage as LegacyUIMessage, -} from 'ai-legacy'; -import type { ToolUIPart, UIMessage, UITools } from 'ai'; - -export type MyUIMessage = UIMessage; - -type V4Part = NonNullable[number]; -type V5Part = MyUIMessage['parts'][number]; - -// Type definitions for V4 parts -type V4ToolInvocationPart = Extract; - -type V4ReasoningPart = Extract; - -type V4SourcePart = Extract; - -type V4FilePart = Extract; - -// Type guards -function isV4Message(msg: V4Message | MyUIMessage): msg is V4Message { - return ( - 'toolInvocations' in msg || - (msg?.parts?.some(p => p.type === 'tool-invocation') ?? false) || - msg?.role === 'data' || - ('reasoning' in msg && typeof msg.reasoning === 'string') || - (msg?.parts?.some(p => 'args' in p || 'result' in p) ?? false) || - (msg?.parts?.some(p => 'reasoning' in p && 'details' in p) ?? false) || - (msg?.parts?.some( - p => p.type === 'file' && 'mimeType' in p && 'data' in p, - ) ?? - false) - ); -} - -function isV4ToolInvocationPart(part: unknown): part is V4ToolInvocationPart { - return ( - typeof part === 'object' && - part !== null && - 'type' in part && - part.type === 'tool-invocation' && - 'toolInvocation' in part - ); -} - -function isV4ReasoningPart(part: unknown): part is V4ReasoningPart { - return ( - typeof part === 'object' && - part !== null && - 'type' in part && - part.type === 'reasoning' && - 'reasoning' in part - ); -} - -function isV4SourcePart(part: unknown): part is V4SourcePart { - return ( - typeof part === 'object' && - part !== null && - 'type' in part && - part.type === 'source' && - 'source' in part - ); -} - -function isV4FilePart(part: unknown): part is V4FilePart { - return ( - typeof part === 'object' && - part !== null && - 'type' in part && - part.type === 'file' && - 'mimeType' in part && - 'data' in part - ); -} - -// State mapping -const V4_TO_V5_STATE_MAP = { - 'partial-call': 'input-streaming', - call: 'input-available', - result: 'output-available', -} as const; - -function convertToolInvocationState( - v4State: ToolInvocation['state'], -): 'input-streaming' | 'input-available' | 'output-available' { - return V4_TO_V5_STATE_MAP[v4State] ?? 'output-available'; -} - -// Tool conversion -function convertV4ToolInvocationToV5ToolUIPart( - toolInvocation: ToolInvocation, -): ToolUIPart { - return { - type: `tool-${toolInvocation.toolName}`, - toolCallId: toolInvocation.toolCallId, - input: toolInvocation.args, - output: - toolInvocation.state === 'result' ? toolInvocation.result : undefined, - state: convertToolInvocationState(toolInvocation.state), - }; -} - -// Part converters -function convertV4ToolInvocationPart(part: V4ToolInvocationPart): V5Part { - return convertV4ToolInvocationToV5ToolUIPart(part.toolInvocation); -} - -function convertV4ReasoningPart(part: V4ReasoningPart): V5Part { - return { type: 'reasoning', text: part.reasoning }; -} - -function convertV4SourcePart(part: V4SourcePart): V5Part { - return { - type: 'source-url', - url: part.source.url, - sourceId: part.source.id, - title: part.source.title, - }; -} - -function convertV4FilePart(part: V4FilePart): V5Part { - return { - type: 'file', - mediaType: part.mimeType, - url: part.data, - }; -} - -function convertPart(part: V4Part | V5Part): V5Part { - if (isV4ToolInvocationPart(part)) { - return convertV4ToolInvocationPart(part); - } - if (isV4ReasoningPart(part)) { - return convertV4ReasoningPart(part); - } - if (isV4SourcePart(part)) { - return convertV4SourcePart(part); - } - if (isV4FilePart(part)) { - return convertV4FilePart(part); - } - // Already V5 format - return part; -} - -// Message conversion -function createBaseMessage( - msg: V4Message | MyUIMessage, - index: number, -): Pick { - return { - id: msg.id || `msg-${index}`, - role: msg.role === 'data' ? 'assistant' : msg.role, - }; -} - -function convertDataMessage(msg: V4Message, index: number): MyUIMessage { - return { - ...createBaseMessage(msg, index), - parts: [ - { - type: 'data-custom', - data: msg.data || msg.content, - }, - ], - }; -} - -function buildPartsFromTopLevelFields(msg: V4Message): MyUIMessage['parts'] { - const parts: MyUIMessage['parts'] = []; - - if (msg.reasoning) { - parts.push({ type: 'reasoning', text: msg.reasoning }); - } - - if (msg.toolInvocations) { - parts.push( - ...msg.toolInvocations.map(convertV4ToolInvocationToV5ToolUIPart), - ); - } - - if (msg.content && typeof msg.content === 'string') { - parts.push({ type: 'text', text: msg.content }); - } - - return parts; -} - -function convertPartsArray(parts: V4Part[]): MyUIMessage['parts'] { - return parts.map(convertPart); -} - -export function convertV4MessageToV5( - msg: V4Message | MyUIMessage, - index: number, -): MyUIMessage { - if (!isV4Message(msg)) { - return msg as MyUIMessage; - } - - if (msg.role === 'data') { - return convertDataMessage(msg, index); - } - - const base = createBaseMessage(msg, index); - const parts = msg.parts - ? convertPartsArray(msg.parts) - : buildPartsFromTopLevelFields(msg); - - return { ...base, parts }; -} - -// V5 to V4 conversion -function convertV5ToolUIPartToV4ToolInvocation( - part: ToolUIPart, -): ToolInvocation { - const state = - part.state === 'input-streaming' - ? 'partial-call' - : part.state === 'input-available' - ? 'call' - : 'result'; - - const toolName = part.type.startsWith('tool-') - ? part.type.slice(5) - : part.type; - - const base = { - toolCallId: part.toolCallId, - toolName, - args: part.input, - state, - }; - - if (state === 'result' && part.output !== undefined) { - return { ...base, state: 'result' as const, result: part.output }; - } - - return base as ToolInvocation; -} - -export function convertV5MessageToV4(msg: MyUIMessage): LegacyUIMessage { - const parts: V4Part[] = []; - - const base: LegacyUIMessage = { - id: msg.id, - role: msg.role, - content: '', - parts, - }; - - let textContent = ''; - let reasoning: string | undefined; - const toolInvocations: ToolInvocation[] = []; - - for (const part of msg.parts) { - if (part.type === 'text') { - textContent = part.text; - parts.push({ type: 'text', text: part.text }); - } else if (part.type === 'reasoning') { - reasoning = part.text; - parts.push({ - type: 'reasoning', - reasoning: part.text, - details: [{ type: 'text', text: part.text }], - }); - } else if (part.type.startsWith('tool-')) { - const toolInvocation = convertV5ToolUIPartToV4ToolInvocation( - part as ToolUIPart, - ); - parts.push({ type: 'tool-invocation', toolInvocation: toolInvocation }); - toolInvocations.push(toolInvocation); - } else if (part.type === 'source-url') { - parts.push({ - type: 'source', - source: { - id: part.sourceId, - url: part.url, - title: part.title, - sourceType: 'url', - }, - }); - } else if (part.type === 'file') { - parts.push({ - type: 'file', - mimeType: part.mediaType, - data: part.url, - }); - } else if (part.type === 'data-custom') { - base.data = part.data; - } - } - - if (textContent) { - base.content = textContent; - } - - if (reasoning) { - base.reasoning = reasoning; - } - - if (toolInvocations.length > 0) { - base.toolInvocations = toolInvocations; - } - - if (parts.length > 0) { - base.parts = parts; - } - return base; -} -``` - -### Step 3: Convert Messages When Reading - -Apply the conversion when loading messages from your database: - -Adapt this code to your specific database and ORM. - -```tsx -import { convertV4MessageToV5, type MyUIMessage } from './conversion'; - -export async function loadChat(chatId: string): Promise { - // Fetch messages from your database (pseudocode - update based on your data access layer) - const rawMessages = await db - .select() - .from(messages) - .where(eq(messages.chatId, chatId)) - .orderBy(messages.createdAt); - - // Convert on read - return rawMessages.map((msg, index) => convertV4MessageToV5(msg, index)); -} -``` - -### Step 4: Convert Messages When Saving - -In Phase 1, your application runs on v5 but your database stores v4 format. Convert messages inline in your route handlers before passing them to your database functions: - -```tsx -import { - convertV5MessageToV4, - convertV4MessageToV5, - type MyUIMessage, -} from './conversion'; -import { upsertMessage, loadChat } from './db/actions'; -import { streamText, generateId, convertToModelMessages } from 'ai'; -__PROVIDER_IMPORT__; - -export async function POST(req: Request) { - const { message, chatId }: { message: MyUIMessage; chatId: string } = - await req.json(); - - // Convert and save incoming user message (v5 to v4 inline) - await upsertMessage({ - chatId, - id: message.id, - message: convertV5MessageToV4(message), // convert to v4 - }); - - // Load previous messages (already in v5 format) - const previousMessages = await loadChat(chatId); - const messages = [...previousMessages, message]; - - const result = streamText({ - model: __MODEL__, - messages: convertToModelMessages(messages), - tools: { - // Your tools here - }, - }); - - return result.toUIMessageStreamResponse({ - generateMessageId: generateId, - originalMessages: messages, - onFinish: async ({ responseMessage }) => { - // Convert and save assistant response (v5 to v4 inline) - await upsertMessage({ - chatId, - id: responseMessage.id, - message: convertV5MessageToV4(responseMessage), - }); - }, - }); -} -``` - -Keep your `upsertMessage` (or equivalent) function unchanged to continue working with v4 messages. - -With Steps 3 and 4 complete, you have a bidirectional conversion layer: - -- **Reading:** v4 (database) → v5 (application) -- **Writing:** v5 (application) → v4 (database) - -Your database schema remains unchanged, but your application now works with v5 format. - -**What's next:** Follow the main migration guide to update the rest of your application code to AI SDK 5.0, including API routes, components, and other code that uses the AI SDK. Then proceed to Phase 2. - -See the [main migration guide](/docs/migration-guides/migration-guide-5-0) for details. - -## Phase 2: Side-by-Side Schema Migration - -Now that your application is updated to AI SDK 5.0 and working with the runtime conversion layer from Phase 1, you have a fully functional system. However, **the conversion functions are only a temporary solution**. Your database still stores messages in the v4 format, which means: - -- Every read operation requires runtime conversion overhead -- You maintain backward compatibility code indefinitely -- Future features require working with the legacy schema - -**Phase 2 migrates your message history to the v5 schema**, eliminating the conversion layer and enabling better performance and long-term maintainability. - -This phase uses a simplified approach: create a new `messages_v5` table with the same structure as your current `messages` table, but storing v5-formatted message parts. - - -**Adapt phase 2 examples to your setup** - -These code examples demonstrate migration patterns. Your implementation will differ based on your database (Postgres, MySQL, SQLite), ORM (Drizzle, Prisma, raw SQL), schema design, and data persistence patterns. - -Use these examples as a guide, then adapt them to your specific setup. - - - -### Overview: Migration Strategy - -1. **Create `messages_v5` table** alongside existing `messages` table -2. **Dual-write** new messages to both schemas (with conversion) -3. **Background migration** to convert existing messages -4. **Verify** data integrity -5. **Update read functions** to use `messages_v5` schema -6. **Remove conversion** from route handlers -7. **Remove dual-write** (write only to `messages_v5`) -8. **Clean up** old tables - -This ensures your application keeps running throughout the migration with no data loss risk. - -### Step 1: Create V5 Schema Alongside V4 - -Create a new `messages_v5` table with the same structure as your existing table, but designed to store v5 message parts: - -**Existing v4 Schema (keep running):** - -```typescript -import { UIMessage } from 'ai-legacy'; - -export const messages = pgTable('messages', { - id: varchar() - .primaryKey() - .$defaultFn(() => nanoid()), - chatId: varchar() - .references(() => chats.id, { onDelete: 'cascade' }) - .notNull(), - createdAt: timestamp().defaultNow().notNull(), - parts: jsonb().$type().notNull(), - role: text().$type().notNull(), -}); -``` - -**New v5 Schema (create alongside):** - -```typescript -import { MyUIMessage } from './conversion'; - -export const messages_v5 = pgTable('messages_v5', { - id: varchar() - .primaryKey() - .$defaultFn(() => nanoid()), - chatId: varchar() - .references(() => chats.id, { onDelete: 'cascade' }) - .notNull(), - createdAt: timestamp().defaultNow().notNull(), - parts: jsonb().$type().notNull(), - role: text().$type().notNull(), -}); -``` - -Run your migration to create the new table: - -```bash -pnpm drizzle-kit generate -pnpm drizzle-kit migrate -``` - -### Step 2: Implement Dual-Write for New Messages - -Update your save functions to write to both schemas during the migration period. This ensures new messages are available in both formats: - -```typescript -import { convertV4MessageToV5 } from './conversion'; -import { messages, messages_v5 } from './schema'; -import type { UIMessage } from 'ai-legacy'; - -export const upsertMessage = async ({ - chatId, - message, - id, -}: { - id: string; - chatId: string; - message: UIMessage; // Still accepts v4 format -}) => { - return await db.transaction(async tx => { - // Write to v4 schema (existing) - const [result] = await tx - .insert(messages) - .values({ - chatId, - parts: message.parts ?? [], - role: message.role, - id, - }) - .onConflictDoUpdate({ - target: messages.id, - set: { - parts: message.parts ?? [], - chatId, - }, - }) - .returning(); - - // Convert and write to v5 schema (new) - const v5Message = convertV4MessageToV5( - { - ...message, - content: '', - }, - 0, - ); - - await tx - .insert(messages_v5) - .values({ - chatId, - parts: v5Message.parts ?? [], - role: v5Message.role, - id, - }) - .onConflictDoUpdate({ - target: messages_v5.id, - set: { - parts: v5Message.parts ?? [], - chatId, - }, - }); - - return result; - }); -}; -``` - -### Step 3: Migrate Existing Messages - -Create a script to migrate existing messages from v4 to v5 schema: - -```typescript -import { convertV4MessageToV5 } from './conversion'; -import { db } from './db'; -import { messages, messages_v5 } from './db/schema'; - -async function migrateExistingMessages() { - console.log('Starting migration of existing messages...'); - - // Get all v4 messages that haven't been migrated yet - const migratedIds = await db.select({ id: messages_v5.id }).from(messages_v5); - - const migratedIdSet = new Set(migratedIds.map(m => m.id)); - - const allMessages = await db.select().from(messages); - const unmigrated = allMessages.filter(msg => !migratedIdSet.has(msg.id)); - - console.log(`Found ${unmigrated.length} messages to migrate`); - - let migrated = 0; - let errors = 0; - const batchSize = 100; - - for (let i = 0; i < unmigrated.length; i += batchSize) { - const batch = unmigrated.slice(i, i + batchSize); - - await db.transaction(async tx => { - for (const msg of batch) { - try { - // Convert message to v5 format - const v5Message = convertV4MessageToV5( - { - id: msg.id, - content: '', - role: msg.role, - parts: msg.parts, - createdAt: msg.createdAt, - }, - 0, - ); - - // Insert into v5 messages table - await tx.insert(messages_v5).values({ - id: v5Message.id, - chatId: msg.chatId, - role: v5Message.role, - parts: v5Message.parts, - createdAt: msg.createdAt, - }); - - migrated++; - } catch (error) { - console.error(`Error migrating message ${msg.id}:`, error); - errors++; - } - } - }); - - console.log(`Progress: ${migrated}/${unmigrated.length} messages migrated`); - } - - console.log(`Migration complete: ${migrated} migrated, ${errors} errors`); -} - -// Run migration -migrateExistingMessages().catch(console.error); -``` - -This script: - -- Only migrates messages that haven't been migrated yet -- Uses batching for better performance -- Can be run multiple times safely -- Can be stopped and resumed - -### Step 4: Verify Migration - -Create a verification script to ensure data integrity: - -```typescript -import { count } from 'drizzle-orm'; -import { db } from './db'; -import { messages, messages_v5 } from './db/schema'; - -async function verifyMigration() { - // Count messages in both schemas - const v4Count = await db.select({ count: count() }).from(messages); - const v5Count = await db.select({ count: count() }).from(messages_v5); - - console.log('Migration Status:'); - console.log(`V4 Messages: ${v4Count[0].count}`); - console.log(`V5 Messages: ${v5Count[0].count}`); - console.log( - `Migration progress: ${((v5Count[0].count / v4Count[0].count) * 100).toFixed(2)}%`, - ); -} - -verifyMigration().catch(console.error); -``` - -### Step 5: Read from V5 Schema - -Once migration is complete, update your read functions to use the new v5 schema. Since the data is now in v5 format, you don't need conversion: - -```typescript -import type { MyUIMessage } from './conversion'; - -export const loadChat = async (chatId: string): Promise => { - // Load from v5 schema - no conversion needed - const messages = await db - .select() - .from(messages_v5) - .where(eq(messages_v5.chatId, chatId)) - .orderBy(messages_v5.createdAt); - - return messages; -}; -``` - -### Step 6: Write to V5 Schema Only - -Once your read functions work with v5 and your background migration is complete, stop dual-writing and only write to v5: - -```typescript -import type { MyUIMessage } from './conversion'; - -export const upsertMessage = async ({ - chatId, - message, - id, -}: { - id: string; - chatId: string; - message: MyUIMessage; // Now accepts v5 format -}) => { - // Write to v5 schema only - const [result] = await db - .insert(messages_v5) - .values({ - chatId, - parts: message.parts ?? [], - role: message.role, - id, - }) - .onConflictDoUpdate({ - target: messages_v5.id, - set: { - parts: message.parts ?? [], - chatId, - }, - }) - .returning(); - - return result; -}; -``` - -Update your route handler to pass v5 messages directly: - -```tsx -export async function POST(req: Request) { - const { message, chatId }: { message: MyUIMessage; chatId: string } = - await req.json(); - - // Pass v5 message directly - no conversion needed - await upsertMessage({ - chatId, - id: message.id, - message, - }); - - const previousMessages = await loadChat(chatId); - const messages = [...previousMessages, message]; - - const result = streamText({ - model: __MODEL__, - messages: convertToModelMessages(messages), - tools: { - // Your tools here - }, - }); - - return result.toUIMessageStreamResponse({ - generateMessageId: generateId, - originalMessages: messages, - onFinish: async ({ responseMessage }) => { - await upsertMessage({ - chatId, - id: responseMessage.id, - message: responseMessage, // No conversion needed - }); - }, - }); -} -``` - -### Step 7: Complete the Switch - -Once verification passes and you're confident in the migration: - -1. **Remove conversion functions**: Delete the v4↔v5 conversion utilities -2. **Remove `ai-legacy` dependency**: Uninstall the v4 types package -3. **Test thoroughly**: Ensure your application works correctly with v5 schema -4. **Monitor**: Watch for issues in production -5. **Clean up**: After a safe period (1-2 weeks), drop the old table - -```sql --- After confirming everything works -DROP TABLE messages; - --- Optionally rename v5 table to standard name -ALTER TABLE messages_v5 RENAME TO messages; -``` - -**Phase 2 is now complete.** Your application is fully migrated to v5 schema with no runtime conversion overhead. - -## Community Resources - -The following community members have shared their migration experiences: - -- [AI SDK Migration: Handling Previously Saved Messages](https://jhakim.com/blog/ai-sdk-migration-handling-previously-saved-messages) - Detailed transformation function implementation -- [How we migrated Atypica.ai to AI SDK v5 without breaking 10M+ chat histories](https://blog.web3nomad.com/p/how-we-migrated-atypicaai-to-ai-sdk-v5-without-breaking-10m-chat-histories) - Runtime conversion approach for large-scale migration - -For more API change details, see the [main migration guide](/docs/migration-guides/migration-guide-5-0). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/26-migration-guide-5-0.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/26-migration-guide-5-0.mdx deleted file mode 100644 index 1bc43d198..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/26-migration-guide-5-0.mdx +++ /dev/null @@ -1,3427 +0,0 @@ ---- -title: Migrate AI SDK 4.x to 5.0 -description: Learn how to upgrade AI SDK 4.x to 5.0. ---- - -# Migrate AI SDK 4.x to 5.0 - -## Recommended Migration Process - -1. Backup your project. If you use a versioning control system, make sure all previous versions are committed. -1. Upgrade to AI SDK 5.0. -1. Automatically migrate your code using one of these approaches: - - Use the [AI SDK 5 Migration MCP Server](#ai-sdk-5-migration-mcp-server) for AI-assisted migration in Cursor or other MCP-compatible coding agents - - Use [codemods](#codemods) to automatically transform your code -1. Follow the breaking changes guide below. -1. Verify your project is working as expected. -1. Commit your changes. - -## AI SDK 5 Migration MCP Server - -The [AI SDK 5 Migration Model Context Protocol (MCP) Server](https://github.com/vercel-labs/ai-sdk-5-migration-mcp-server) provides an automated way to migrate your project using a coding agent. This server has been designed for Cursor, but should work with any coding agent that supports MCP. - -To get started, create or edit `.cursor/mcp.json` in your project: - -```json -{ - "mcpServers": { - "ai-sdk-5-migration": { - "url": "https://ai-sdk-5-migration-mcp-server.vercel.app/api/mcp" - } - } -} -``` - -After saving, open the command palette (Cmd+Shift+P on macOS, Ctrl+Shift+P on Windows/Linux) and search for "View: Open MCP Settings". Verify the new server appears and is toggled on. - -Then use this prompt: - -``` -Please migrate this project to AI SDK 5 using the ai-sdk-5-migration mcp server. Start by creating a checklist. -``` - -For more information, see the [AI SDK 5 Migration MCP Server repository](https://github.com/vercel-labs/ai-sdk-5-migration-mcp-server). - -## AI SDK 5.0 Package Versions - -You need to update the following packages to the following versions in your `package.json` file(s): - -- `ai` package: `5.0.0` -- `@ai-sdk/provider` package: `2.0.0` -- `@ai-sdk/provider-utils` package: `3.0.0` -- `@ai-sdk/*` packages: `2.0.0` (other `@ai-sdk` packages) - -Additionally, you need to update the following peer dependencies: - -- `zod` package: `4.1.8` or later (recommended to avoid TypeScript performance issues) - -An example upgrade command would be: - -``` -npm install ai @ai-sdk/react @ai-sdk/openai zod@^4.1.8 -``` - - - If you encounter TypeScript performance issues after upgrading, ensure you're - using Zod 4.1.8 or later. If the issue persists, update your `tsconfig.json` - to use `moduleResolution: "nodenext"`. See the [TypeScript performance - troubleshooting guide](/docs/troubleshooting/typescript-performance-zod) for - more details. - - -## Codemods - -The AI SDK provides Codemod transformations to help upgrade your codebase when a -feature is deprecated, removed, or otherwise changed. - -Codemods are transformations that run on your codebase automatically. They -allow you to easily apply many changes without having to manually go through -every file. - - - Codemods are intended as a tool to help you with the upgrade process. They may - not cover all of the changes you need to make. You may need to make additional - changes manually. - - -You can run all codemods provided as part of the 5.0 upgrade process by running -the following command from the root of your project: - -```sh -npx @ai-sdk/codemod upgrade -``` - -To run only the v5 codemods (v4 → v5 migration): - -```sh -npx @ai-sdk/codemod v5 -``` - -Individual codemods can be run by specifying the name of the codemod: - -```sh -npx @ai-sdk/codemod -``` - -For example, to run a specific v5 codemod: - -```sh -npx @ai-sdk/codemod v5/rename-format-stream-part src/ -``` - -See also the [table of codemods](#codemod-table). In addition, the latest set of -codemods can be found in the -[`@ai-sdk/codemod`](https://github.com/vercel/ai/tree/main/packages/codemod/src/codemods) -repository. - -## AI SDK Core Changes - -### generateText and streamText Changes - -#### Maximum Output Tokens - -The `maxTokens` parameter has been renamed to `maxOutputTokens` for clarity. - -```tsx filename="AI SDK 4.0" -const result = await generateText({ - model: __MODEL__, - maxTokens: 1024, - prompt: 'Hello, world!', -}); -``` - -```tsx filename="AI SDK 5.0" -const result = await generateText({ - model: __MODEL__, - maxOutputTokens: 1024, - prompt: 'Hello, world!', -}); -``` - -### Message and Type System Changes - -#### Core Type Renames - -##### `CoreMessage` → `ModelMessage` - -```tsx filename="AI SDK 4.0" -import { CoreMessage } from 'ai'; -``` - -```tsx filename="AI SDK 5.0" -import { ModelMessage } from 'ai'; -``` - -##### `Message` → `UIMessage` - -```tsx filename="AI SDK 4.0" -import { Message, CreateMessage } from 'ai'; -``` - -```tsx filename="AI SDK 5.0" -import { UIMessage, CreateUIMessage } from 'ai'; -``` - -##### `convertToCoreMessages` → `convertToModelMessages` - -```tsx filename="AI SDK 4.0" -import { convertToCoreMessages, streamText } from 'ai'; - -const result = await streamText({ - model: __MODEL__, - messages: convertToCoreMessages(messages), -}); -``` - -```tsx filename="AI SDK 5.0" -import { convertToModelMessages, streamText } from 'ai'; - -const result = await streamText({ - model: __MODEL__, - messages: convertToModelMessages(messages), -}); -``` - - - For more information about model messages, see the [Model Message - reference](/docs/reference/ai-sdk-core/model-message). - - -### UIMessage Changes - -#### Content → Parts Array - -For `UIMessage`s (previously called `Message`), the `.content` property has been replaced with a `parts` array structure. - -```tsx filename="AI SDK 4.0" -import { type Message } from 'ai'; // v4 Message type - -// Messages (useChat) - had content property -const message: Message = { - id: '1', - role: 'user', - content: 'Bonjour!', -}; -``` - -```tsx filename="AI SDK 5.0" -import { type UIMessage, type ModelMessage } from 'ai'; - -// UIMessages (useChat) - now use parts array -const uiMessage: UIMessage = { - id: '1', - role: 'user', - parts: [{ type: 'text', text: 'Bonjour!' }], -}; -``` - -#### Data Role Removed - -The `data` role has been removed from UI messages. - -```tsx filename="AI SDK 4.0" -const message = { - role: 'data', - content: 'Some content', - data: { customField: 'value' }, -}; -``` - -```tsx filename="AI SDK 5.0" -// V5: Use UI message streams with custom data parts -const stream = createUIMessageStream({ - execute({ writer }) { - // Write custom data instead of message annotations - writer.write({ - type: 'data-custom', - id: 'custom-1', - data: { customField: 'value' }, - }); - }, -}); -``` - -#### UIMessage Reasoning Structure - -The reasoning property on UI messages has been moved to parts. - -```tsx filename="AI SDK 4.0" -const message: Message = { - role: 'assistant', - content: 'Hello', - reasoning: 'I will greet the user', -}; -``` - -```tsx filename="AI SDK 5.0" -const message: UIMessage = { - role: 'assistant', - parts: [ - { - type: 'reasoning', - text: 'I will greet the user', - }, - { - type: 'text', - text: 'Hello', - }, - ], -}; -``` - -#### Reasoning Part Property Rename - -The `reasoning` property on reasoning UI parts has been renamed to `text`. - -```tsx filename="AI SDK 4.0" -{ - message.parts.map((part, index) => { - if (part.type === 'reasoning') { - return ( -
- {part.reasoning} -
- ); - } - }); -} -``` - -```tsx filename="AI SDK 5.0" -{ - message.parts.map((part, index) => { - if (part.type === 'reasoning') { - return ( -
- {part.text} -
- ); - } - }); -} -``` - -### File Part Changes - -File parts now use `.url` instead of `.data` and `.mimeType`. - -```tsx filename="AI SDK 4.0" -{ - messages.map(message => ( -
- {message.parts.map((part, index) => { - if (part.type === 'text') { - return
{part.text}
; - } else if (part.type === 'file' && part.mimeType.startsWith('image/')) { - return ( - - ); - } - })} -
- )); -} -``` - -```tsx filename="AI SDK 5.0" -{ - messages.map(message => ( -
- {message.parts.map((part, index) => { - if (part.type === 'text') { - return
{part.text}
; - } else if ( - part.type === 'file' && - part.mediaType.startsWith('image/') - ) { - return ; - } - })} -
- )); -} -``` - -### Stream Data Removal - -The `StreamData` class has been completely removed and replaced with UI message streams for custom data. - -```tsx filename="AI SDK 4.0" -import { StreamData } from 'ai'; - -const streamData = new StreamData(); -streamData.append('custom-data'); -streamData.close(); -``` - -```tsx filename="AI SDK 5.0" -import { createUIMessageStream, createUIMessageStreamResponse } from 'ai'; - -const stream = createUIMessageStream({ - execute({ writer }) { - // Write custom data parts - writer.write({ - type: 'data-custom', - id: 'custom-1', - data: 'custom-data', - }); - - // Can merge with LLM streams - const result = streamText({ - model: __MODEL__, - messages, - }); - - writer.merge(result.toUIMessageStream()); - }, -}); - -return createUIMessageStreamResponse({ stream }); -``` - -### Custom Data Streaming: writeMessageAnnotation/writeData Removed - -The `writeMessageAnnotation` and `writeData` methods from `DataStreamWriter` have been removed. Instead, use custom data parts with the new `UIMessage` stream architecture. - -```tsx filename="AI SDK 4.0" -import { createDataStreamResponse, streamText } from 'ai'; - -export async function POST(req: Request) { - const { messages } = await req.json(); - - return createDataStreamResponse({ - execute: dataStream => { - // Write general data - dataStream.writeData('call started'); - - const result = streamText({ - model: __MODEL__, - messages, - onChunk() { - // Write message annotations - dataStream.writeMessageAnnotation({ - status: 'streaming', - timestamp: Date.now(), - }); - }, - onFinish() { - // Write final annotations - dataStream.writeMessageAnnotation({ - id: generateId(), - completed: true, - }); - - dataStream.writeData('call completed'); - }, - }); - - result.mergeIntoDataStream(dataStream); - }, - }); -} -``` - -```tsx filename="AI SDK 5.0" -import { - createUIMessageStream, - createUIMessageStreamResponse, - streamText, - generateId, -} from 'ai'; - -export async function POST(req: Request) { - const { messages } = await req.json(); - - const stream = createUIMessageStream({ - execute: ({ writer }) => { - const statusId = generateId(); - - // Write general data (transient - not added to message history) - writer.write({ - type: 'data-status', - id: statusId, - data: { status: 'call started' }, - }); - - const result = streamText({ - model: __MODEL__, - messages, - onChunk() { - // Write data parts that update during streaming - writer.write({ - type: 'data-status', - id: statusId, - data: { - status: 'streaming', - timestamp: Date.now(), - }, - }); - }, - onFinish() { - // Write final data parts - writer.write({ - type: 'data-status', - id: statusId, - data: { - status: 'completed', - }, - }); - }, - }); - - writer.merge(result.toUIMessageStream()); - }, - }); - - return createUIMessageStreamResponse({ stream }); -} -``` - - - For more detailed information about streaming custom data in v5, see the - [Streaming Data guide](/docs/ai-sdk-ui/streaming-data). - - -##### Provider Metadata → Provider Options - -The `providerMetadata` input parameter has been renamed to `providerOptions`. Note that the returned metadata in results is still called `providerMetadata`. - -```tsx filename="AI SDK 4.0" -const result = await generateText({ - model: 'openai/gpt-5', - prompt: 'Hello', - providerMetadata: { - openai: { store: false }, - }, -}); -``` - -```tsx filename="AI SDK 5.0" -const result = await generateText({ - model: 'openai/gpt-5', - prompt: 'Hello', - providerOptions: { - // Input parameter renamed - openai: { store: false }, - }, -}); - -// Returned metadata still uses providerMetadata: -console.log(result.providerMetadata?.openai); -``` - -#### Tool Definition Changes (parameters → inputSchema) - -Tool definitions have been updated to use `inputSchema` instead of `parameters` and error classes have been renamed. - -```tsx filename="AI SDK 4.0" -import { tool } from 'ai'; - -const weatherTool = tool({ - description: 'Get the weather for a city', - parameters: z.object({ - city: z.string(), - }), - execute: async ({ city }) => { - return `Weather in ${city}`; - }, -}); -``` - -```tsx filename="AI SDK 5.0" -import { tool } from 'ai'; - -const weatherTool = tool({ - description: 'Get the weather for a city', - inputSchema: z.object({ - city: z.string(), - }), - execute: async ({ city }) => { - return `Weather in ${city}`; - }, -}); -``` - -#### Tool Result Content: experimental_toToolResultContent → toModelOutput - -The `experimental_toToolResultContent` option has been renamed to `toModelOutput` and is no longer experimental. - -```tsx filename="AI SDK 4.0" -const screenshotTool = tool({ - description: 'Take a screenshot', - parameters: z.object({}), - execute: async () => { - const imageData = await takeScreenshot(); - return imageData; // base64 string - }, - experimental_toToolResultContent: result => [{ type: 'image', data: result }], -}); -``` - -```tsx filename="AI SDK 5.0" -const screenshotTool = tool({ - description: 'Take a screenshot', - inputSchema: z.object({}), - execute: async () => { - const imageData = await takeScreenshot(); - return imageData; - }, - toModelOutput: result => ({ - type: 'content', - value: [{ type: 'media', mediaType: 'image/png', data: result }], - }), -}); -``` - -### Tool Property Changes (args/result → input/output) - -Tool call and result properties have been renamed for better consistency with schemas. - -```tsx filename="AI SDK 4.0" -// Tool calls used "args" and "result" -for await (const part of result.fullStream) { - switch (part.type) { - case 'tool-call': - console.log('Tool args:', part.args); - break; - case 'tool-result': - console.log('Tool result:', part.result); - break; - } -} -``` - -```tsx filename="AI SDK 5.0" -// Tool calls now use "input" and "output" -for await (const part of result.fullStream) { - switch (part.type) { - case 'tool-call': - console.log('Tool input:', part.input); - break; - case 'tool-result': - console.log('Tool output:', part.output); - break; - } -} -``` - -### Tool Execution Error Handling - -The `ToolExecutionError` class has been removed. Tool execution errors now appear as `tool-error` content parts in the result steps, enabling automated LLM roundtrips in multi-step scenarios. - -```tsx filename="AI SDK 4.0" -import { ToolExecutionError } from 'ai'; - -try { - const result = await generateText({ - // ... - }); -} catch (error) { - if (error instanceof ToolExecutionError) { - console.log('Tool execution failed:', error.message); - console.log('Tool name:', error.toolName); - console.log('Tool input:', error.toolInput); - } -} -``` - -```tsx filename="AI SDK 5.0" -// Tool execution errors now appear in result steps -const { steps } = await generateText({ - // ... -}); - -// check for tool errors in the steps -const toolErrors = steps.flatMap(step => - step.content.filter(part => part.type === 'tool-error'), -); - -toolErrors.forEach(toolError => { - console.log('Tool error:', toolError.error); - console.log('Tool name:', toolError.toolName); - console.log('Tool input:', toolError.input); -}); -``` - -For streaming scenarios, tool execution errors appear as `tool-error` parts in the stream, while other errors appear as `error` parts. - -### Tool Call Streaming Now Default (toolCallStreaming Removed) - -The `toolCallStreaming` option has been removed in AI SDK 5.0. Tool call streaming is now always enabled by default. - -```tsx filename="AI SDK 4.0" -const result = streamText({ - model: __MODEL__, - messages, - toolCallStreaming: true, // Optional parameter to enable streaming - tools: { - weatherTool, - searchTool, - }, -}); -``` - -```tsx filename="AI SDK 5.0" -const result = streamText({ - model: __MODEL__, - messages: convertToModelMessages(messages), - // toolCallStreaming removed - streaming is always enabled - tools: { - weatherTool, - searchTool, - }, -}); -``` - -### Tool Part Type Changes (UIMessage) - -In v5, UI tool parts use typed naming: `tool-${toolName}` instead of generic types. - -```tsx filename="AI SDK 4.0" -// Generic tool-invocation type -{ - message.parts.map(part => { - if (part.type === 'tool-invocation') { - return
{part.toolInvocation.toolName}
; - } - }); -} -``` - -```tsx filename="AI SDK 5.0" -// Type-safe tool parts with specific names -{ - message.parts.map(part => { - switch (part.type) { - case 'tool-getWeatherInformation': - return
Getting weather...
; - case 'tool-askForConfirmation': - return
Asking for confirmation...
; - } - }); -} -``` - -### Dynamic Tools Support - -AI SDK 5.0 introduces dynamic tools for handling tools with unknown types at development time, such as MCP tools without schemas or user-defined functions at runtime. - -#### New dynamicTool Helper - -The new `dynamicTool` helper function allows you to define tools where the input and output types are not known at compile time. - -```tsx filename="AI SDK 5.0" -import { dynamicTool } from 'ai'; -import { z } from 'zod'; - -// Define a dynamic tool -const runtimeTool = dynamicTool({ - description: 'A tool defined at runtime', - inputSchema: z.object({}), - execute: async input => { - // Input and output are typed as 'unknown' - return { result: `Processed: ${input.query}` }; - }, -}); -``` - -#### MCP Tools Without Schemas - -MCP tools that don't provide schemas are now automatically treated as dynamic tools: - -```tsx filename="AI SDK 5.0" -import { MCPClient } from 'ai'; - -const client = new MCPClient({ - /* ... */ -}); -const tools = await client.getTools(); - -// Tools without schemas are now 'dynamic' type -// and won't break type inference when mixed with static tools -``` - -#### Type-Safe Handling with Mixed Tools - -When using both static and dynamic tools together, use the `dynamic` flag for type narrowing: - -```tsx filename="AI SDK 5.0" -const result = await generateText({ - model: __MODEL__, - tools: { - // Static tool with known types - weather: weatherTool, - // Dynamic tool with unknown types - customDynamicTool: dynamicTool({ - /* ... */ - }), - }, - onStepFinish: step => { - // Handle tool calls with type safety - for (const toolCall of step.toolCalls) { - if (toolCall.dynamic) { - // Dynamic tool: input/output are 'unknown' - console.log('Dynamic tool called:', toolCall.toolName); - continue; - } - - // Static tools have full type inference - switch (toolCall.toolName) { - case 'weather': - // TypeScript knows the exact types - console.log(toolCall.input.location); // string - break; - } - } - }, -}); -``` - -#### New dynamic-tool UI Part - -UI messages now include a `dynamic-tool` part type for rendering dynamic tool invocations: - -```tsx filename="AI SDK 5.0" -{ - message.parts.map((part, index) => { - switch (part.type) { - // Static tools use specific types - case 'tool-weather': - return
Weather: {part.input.city}
; - - // Dynamic tools use the generic dynamic-tool type - case 'dynamic-tool': - return ( -
- Dynamic tool: {part.toolName} -
{JSON.stringify(part.input, null, 2)}
-
- ); - } - }); -} -``` - -#### Breaking Change: Type Narrowing Required for Tool Calls and Results - -When iterating over `toolCalls` and `toolResults`, you now need to check the `dynamic` flag first for proper type narrowing: - -```tsx filename="AI SDK 4.0" -// Direct type checking worked without dynamic flag -onStepFinish: step => { - for (const toolCall of step.toolCalls) { - switch (toolCall.toolName) { - case 'weather': - console.log(toolCall.input.location); // typed as string - break; - case 'search': - console.log(toolCall.input.query); // typed as string - break; - } - } -}; -``` - -```tsx filename="AI SDK 5.0" -// Must check dynamic flag first for type narrowing -onStepFinish: step => { - for (const toolCall of step.toolCalls) { - // Check if it's a dynamic tool first - if (toolCall.dynamic) { - console.log('Dynamic tool:', toolCall.toolName); - console.log('Input:', toolCall.input); // typed as unknown - continue; - } - - // Now TypeScript knows it's a static tool - switch (toolCall.toolName) { - case 'weather': - console.log(toolCall.input.location); // typed as string - break; - case 'search': - console.log(toolCall.input.query); // typed as string - break; - } - } -}; -``` - -### Tool UI Part State Changes - -Tool UI parts now use more granular states that better represent the streaming lifecycle and error handling. - -```tsx filename="AI SDK 4.0" -// Old states -{ - message.parts.map(part => { - if (part.type === 'tool-invocation') { - switch (part.toolInvocation.state) { - case 'partial-call': - return
Loading...
; - case 'call': - return ( -
- Tool called with {JSON.stringify(part.toolInvocation.args)} -
- ); - case 'result': - return
Result: {part.toolInvocation.result}
; - } - } - }); -} -``` - -```tsx filename="AI SDK 5.0" -// New granular states -{ - message.parts.map(part => { - switch (part.type) { - case 'tool-getWeatherInformation': - switch (part.state) { - case 'input-streaming': - return
{JSON.stringify(part.input, null, 2)}
; - case 'input-available': - return
Getting weather for {part.input.city}...
; - case 'output-available': - return
Weather: {part.output}
; - case 'output-error': - return
Error: {part.errorText}
; - } - } - }); -} -``` - -**State Changes:** - -- `partial-call` → `input-streaming` (tool input being streamed) -- `call` → `input-available` (tool input complete, ready to execute) -- `result` → `output-available` (tool execution successful) -- New: `output-error` (tool execution failed) - -#### Rendering Tool Invocations (Catch-All Pattern) - -In v4, you typically rendered tool invocations using a catch-all `tool-invocation` type. In v5, the **recommended approach is to handle each tool specifically using its typed part name (e.g., `tool-getWeather`)**. However, if you need a catch-all pattern for rendering all tool invocations the same way, you can use the `isToolUIPart` and `getToolName` helper functions as a fallback. - -```tsx filename="AI SDK 4.0" -{ - message.parts.map((part, index) => { - switch (part.type) { - case 'text': - return
{part.text}
; - case 'tool-invocation': - const { toolInvocation } = part; - return ( -
- - {toolInvocation.toolName} - {toolInvocation.state === 'result' ? ( - Click to expand - ) : ( - calling... - )} - - {toolInvocation.state === 'result' ? ( -
-
{JSON.stringify(toolInvocation.result, null, 2)}
-
- ) : null} -
- ); - } - }); -} -``` - -```tsx filename="AI SDK 5.0" -import { isToolUIPart, getToolName } from 'ai'; - -{ - message.parts.map((part, index) => { - switch (part.type) { - case 'text': - return
{part.text}
; - default: - if (isToolUIPart(part)) { - const toolInvocation = part; - return ( -
- - {getToolName(toolInvocation)} - {toolInvocation.state === 'output-available' ? ( - Click to expand - ) : ( - calling... - )} - - {toolInvocation.state === 'output-available' ? ( -
-
{JSON.stringify(toolInvocation.output, null, 2)}
-
- ) : null} -
- ); - } - } - }); -} -``` - -#### Media Type Standardization - -`mimeType` has been renamed to `mediaType` for consistency. Both image and file types are supported in model messages. - -```tsx filename="AI SDK 4.0" -const result = await generateText({ - model: someModel, - messages: [ - { - role: 'user', - content: [ - { type: 'text', text: 'What do you see?' }, - { - type: 'image', - image: new Uint8Array([0, 1, 2, 3]), - mimeType: 'image/png', - }, - { - type: 'file', - data: contents, - mimeType: 'application/pdf', - }, - ], - }, - ], -}); -``` - -```tsx filename="AI SDK 5.0" -const result = await generateText({ - model: someModel, - messages: [ - { - role: 'user', - content: [ - { type: 'text', text: 'What do you see?' }, - { - type: 'image', - image: new Uint8Array([0, 1, 2, 3]), - mediaType: 'image/png', - }, - { - type: 'file', - data: contents, - mediaType: 'application/pdf', - }, - ], - }, - ], -}); -``` - -### Reasoning Support - -#### Reasoning Text Property Rename - -The `.reasoning` property has been renamed to `.reasoningText` for multi-step generations. - -```tsx filename="AI SDK 4.0" -for (const step of steps) { - console.log(step.reasoning); -} -``` - -```tsx filename="AI SDK 5.0" -for (const step of steps) { - console.log(step.reasoningText); -} -``` - -#### Generate Text Reasoning Property Changes - -In `generateText()` and `streamText()` results, reasoning properties have been renamed. - -```tsx filename="AI SDK 4.0" -const result = await generateText({ - model: anthropic('claude-sonnet-4-20250514'), - prompt: 'Explain your reasoning', -}); - -console.log(result.reasoning); // String reasoning text -console.log(result.reasoningDetails); // Array of reasoning details -``` - -```tsx filename="AI SDK 5.0" -const result = await generateText({ - model: anthropic('claude-sonnet-4-20250514'), - prompt: 'Explain your reasoning', -}); - -console.log(result.reasoningText); // String reasoning text -console.log(result.reasoning); // Array of reasoning details -``` - -### Continuation Steps Removal - -The `experimental_continueSteps` option has been removed from `generateText()`. - -```tsx filename="AI SDK 4.0" -const result = await generateText({ - experimental_continueSteps: true, - // ... -}); -``` - -```tsx filename="AI SDK 5.0" -const result = await generateText({ - // experimental_continueSteps has been removed - // Use newer models with higher output token limits instead - // ... -}); -``` - -### Image Generation Changes - -Image model settings have been moved to `providerOptions`. - -```tsx filename="AI SDK 4.0" -await generateImage({ - model: luma.image('photon-flash-1', { - maxImagesPerCall: 5, - pollIntervalMillis: 500, - }), - prompt, - n: 10, -}); -``` - -```tsx filename="AI SDK 5.0" -await generateImage({ - model: luma.image('photon-flash-1'), - prompt, - n: 10, - maxImagesPerCall: 5, - providerOptions: { - luma: { pollIntervalMillis: 500 }, - }, -}); -``` - -### Step Result Changes - -#### Step Type Removal - -The `stepType` property has been removed from step results. - -```tsx filename="AI SDK 4.0" -steps.forEach(step => { - switch (step.stepType) { - case 'initial': - console.log('Initial step'); - break; - case 'tool-result': - console.log('Tool result step'); - break; - case 'done': - console.log('Final step'); - break; - } -}); -``` - -```tsx filename="AI SDK 5.0" -steps.forEach((step, index) => { - if (index === 0) { - console.log('Initial step'); - } else if (step.toolResults.length > 0) { - console.log('Tool result step'); - } else { - console.log('Final step'); - } -}); -``` - -### Step Control: maxSteps → stopWhen - -For core functions like `generateText` and `streamText`, the `maxSteps` parameter has been replaced with `stopWhen`, which provides more flexible control over multi-step execution. The `stopWhen` parameter defines conditions for stopping the generation **when the last step contains tool results**. When multiple conditions are provided as an array, the generation stops if any condition is met. - -```tsx filename="AI SDK 4.0" -// V4: Simple numeric limit -const result = await generateText({ - model: __MODEL__, - messages, - maxSteps: 5, // Stop after a maximum of 5 steps -}); - -// useChat with maxSteps -const { messages } = useChat({ - maxSteps: 3, // Stop after a maximum of 3 steps -}); -``` - -```tsx filename="AI SDK 5.0" -import { stepCountIs, hasToolCall } from 'ai'; - -// V5: Server-side - flexible stopping conditions with stopWhen -const result = await generateText({ - model: __MODEL__, - messages, - // Only triggers when last step has tool results - stopWhen: stepCountIs(5), // Stop at step 5 if tools were called -}); - -// Server-side - stop when specific tool is called -const result = await generateText({ - model: __MODEL__, - messages, - stopWhen: hasToolCall('finalizeTask'), // Stop when finalizeTask tool is called -}); -``` - -**Common stopping patterns:** - -```tsx filename="AI SDK 5.0" -// Stop after N steps (equivalent to old maxSteps) -// Note: Only applies when the last step has tool results -stopWhen: stepCountIs(5); - -// Stop when specific tool is called -stopWhen: hasToolCall('finalizeTask'); - -// Multiple conditions (stops if ANY condition is met) -stopWhen: [ - stepCountIs(10), // Maximum 10 steps - hasToolCall('submitOrder'), // Or when order is submitted -]; - -// Custom condition based on step content -stopWhen: ({ steps }) => { - const lastStep = steps[steps.length - 1]; - // Custom logic - only triggers if last step has tool results - return lastStep?.text?.includes('COMPLETE'); -}; -``` - -**Important:** The `stopWhen` conditions are only evaluated when the last step contains tool results. - -#### Usage vs Total Usage - -Usage properties now distinguish between single step and total usage. - -```tsx filename="AI SDK 4.0" -// usage contained total token usage across all steps -console.log(result.usage); -``` - -```tsx filename="AI SDK 5.0" -// usage contains token usage from the final step only -console.log(result.usage); -// totalUsage contains total token usage across all steps -console.log(result.totalUsage); -``` - -## AI SDK UI Changes - -### Package Structure Changes - -### `@ai-sdk/rsc` Package Extraction - -The `ai/rsc` export has been extracted to a separate package `@ai-sdk/rsc`. - -```tsx filename="AI SDK 4.0" -import { createStreamableValue } from 'ai/rsc'; -``` - -```tsx filename="AI SDK 5.0" -import { createStreamableValue } from '@ai-sdk/rsc'; -``` - -Don't forget to install the new package: `npm install @ai-sdk/rsc` - -### React UI Hooks Moved to `@ai-sdk/react` - -The deprecated `ai/react` export has been removed in favor of `@ai-sdk/react`. - -```tsx filename="AI SDK 4.0" -import { useChat } from 'ai/react'; -``` - -```tsx filename="AI SDK 5.0" -import { useChat } from '@ai-sdk/react'; -``` - - - Don't forget to install the new package: `npm install @ai-sdk/react` - - -### useChat Changes - -The `useChat` hook has undergone significant changes in v5, with new transport architecture, removal of managed input state, and more. - -#### maxSteps Removal - -The `maxSteps` parameter has been removed from `useChat`. You should now use server-side `stopWhen` conditions for multi-step tool execution control, and manually submit tool results and trigger new messages for client-side tool calls. - -```tsx filename="AI SDK 4.0" -const { messages, sendMessage } = useChat({ - maxSteps: 5, // Automatic tool result submission -}); -``` - -```tsx filename="AI SDK 5.0" -// Server-side: Use stopWhen for multi-step control -import { streamText, convertToModelMessages, stepCountIs } from 'ai'; -__PROVIDER_IMPORT__; - -const result = await streamText({ - model: __MODEL__, - messages: convertToModelMessages(messages), - stopWhen: stepCountIs(5), // Stop after 5 steps with tool calls -}); - -// Client-side: Configure automatic submission -import { useChat } from '@ai-sdk/react'; -import { - DefaultChatTransport, - lastAssistantMessageIsCompleteWithToolCalls, -} from 'ai'; - -const { messages, sendMessage, addToolOutput } = useChat({ - // Automatically submit when all tool results are available - sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls, - - async onToolCall({ toolCall }) { - const result = await executeToolCall(toolCall); - - // Important: Don't await addToolOutput inside onToolCall to avoid deadlocks - addToolOutput({ - tool: toolCall.toolName, - toolCallId: toolCall.toolCallId, - output: result, - }); - }, -}); -``` - - - Important: When using `sendAutomaticallyWhen`, don't use `await` with - `addToolOutput` inside `onToolCall` as it can cause deadlocks. The `await` is - useful when you're not using automatic submission and need to ensure the - messages are updated before manually calling `sendMessage()`. - - -This change provides more flexibility for handling tool calls and aligns client behavior with server-side multi-step execution patterns. - -For more details on the new tool submission approach, see the [Tool Result Submission Changes](#tool-result-submission-changes) section below. - -#### Initial Messages Renamed - -The `initialMessages` option has been renamed to `messages`. - -```tsx filename="AI SDK 4.0" -import { useChat, type Message } from '@ai-sdk/react'; - -function ChatComponent({ initialMessages }: { initialMessages: Message[] }) { - const { messages } = useChat({ - initialMessages: initialMessages, - // ... - }); - - // your component -} -``` - -```tsx filename="AI SDK 5.0" -import { useChat, type UIMessage } from '@ai-sdk/react'; - -function ChatComponent({ initialMessages }: { initialMessages: UIMessage[] }) { - const { messages } = useChat({ - messages: initialMessages, - // ... - }); - - // your component -} -``` - -#### Sharing Chat Instances - -In v4, you could share chat state between components by using the same `id` parameter in multiple `useChat` hooks. - -```tsx filename="AI SDK 4.0" -// Component A -const { messages } = useChat({ - id: 'shared-chat', - api: '/api/chat', -}); - -// Component B - would share the same chat state -const { messages } = useChat({ - id: 'shared-chat', - api: '/api/chat', -}); -``` - -In v5, you need to explicitly share chat instances by passing a shared `Chat` instance. - -```tsx filename="AI SDK 5.0" -// e.g. Store Chat instance in React Context and create a custom hook - -// Component A -const { chat } = useSharedChat(); // Custom hook that accesses shared Chat from context - -const { messages, sendMessage } = useChat({ - chat, // Pass the shared chat instance -}); - -// Component B - shares the same chat instance -const { chat } = useSharedChat(); // Same hook to access shared Chat from context - -const { messages } = useChat({ - chat, // Same shared chat instance -}); -``` - -For a complete example of sharing chat state across components, see the [Share Chat State Across Components](/cookbook/next/use-shared-chat-context) recipe. - -#### Chat Transport Architecture - -Configuration is now handled through transport objects instead of direct API options. - -```tsx filename="AI SDK 4.0" -import { useChat } from '@ai-sdk/react'; - -const { messages } = useChat({ - api: '/api/chat', - credentials: 'include', - headers: { 'Custom-Header': 'value' }, -}); -``` - -```tsx filename="AI SDK 5.0" -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; - -const { messages } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - credentials: 'include', - headers: { 'Custom-Header': 'value' }, - }), -}); -``` - -#### Removed Managed Input State - -The `useChat` hook no longer manages input state internally. You must now manage input state manually. - -```tsx filename="AI SDK 4.0" -import { useChat } from '@ai-sdk/react'; - -export default function Page() { - const { messages, input, handleInputChange, handleSubmit } = useChat({ - api: '/api/chat', - }); - - return ( -
- - -
- ); -} -``` - -```tsx filename="AI SDK 5.0" -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; -import { useState } from 'react'; - -export default function Page() { - const [input, setInput] = useState(''); - const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ api: '/api/chat' }), - }); - - const handleSubmit = e => { - e.preventDefault(); - sendMessage({ text: input }); - setInput(''); - }; - - return ( -
- setInput(e.target.value)} /> - -
- ); -} -``` - -#### Message Sending: `append` → `sendMessage` - -The `append` function has been replaced with `sendMessage` and requires structured message format. - -```tsx filename="AI SDK 4.0" -const { append } = useChat(); - -// Simple text message -append({ role: 'user', content: 'Hello' }); - -// With custom body -append( - { - role: 'user', - content: 'Hello', - }, - { body: { imageUrl: 'https://...' } }, -); -``` - -```tsx filename="AI SDK 5.0" -const { sendMessage } = useChat(); - -// Simple text message (most common usage) -sendMessage({ text: 'Hello' }); - -// Or with explicit parts array -sendMessage({ - parts: [{ type: 'text', text: 'Hello' }], -}); - -// With custom body (via request options) -sendMessage( - { role: 'user', parts: [{ type: 'text', text: 'Hello' }] }, - { body: { imageUrl: 'https://...' } }, -); -``` - -#### Message Regeneration: `reload` → `regenerate` - -The `reload` function has been renamed to `regenerate` with enhanced functionality. - -```tsx filename="AI SDK 4.0" -const { reload } = useChat(); - -// Regenerate last message -reload(); -``` - -```tsx filename="AI SDK 5.0" -const { regenerate } = useChat(); - -// Regenerate last message -regenerate(); - -// Regenerate specific message -regenerate({ messageId: 'message-123' }); -``` - -#### onResponse Removal - -The `onResponse` callback has been removed from `useChat` and `useCompletion`. - -```tsx filename="AI SDK 4.0" -const { messages } = useChat({ - onResponse(response) { - // handle response - }, -}); -``` - -```tsx filename="AI SDK 5.0" -const { messages } = useChat({ - // onResponse is no longer available -}); -``` - -#### Send Extra Message Fields Default - -The `sendExtraMessageFields` option has been removed and is now the default behavior. - -```tsx filename="AI SDK 4.0" -const { messages } = useChat({ - sendExtraMessageFields: true, -}); -``` - -```tsx filename="AI SDK 5.0" -const { messages } = useChat({ - // sendExtraMessageFields is now the default -}); -``` - -#### Keep Last Message on Error Removal - -The `keepLastMessageOnError` option has been removed as it's no longer needed. - -```tsx filename="AI SDK 4.0" -const { messages } = useChat({ - keepLastMessageOnError: true, -}); -``` - -```tsx filename="AI SDK 5.0" -const { messages } = useChat({ - // keepLastMessageOnError is no longer needed -}); -``` - -#### Chat Request Options Changes - -The `data` and `allowEmptySubmit` options have been removed from `ChatRequestOptions`. - -```tsx filename="AI SDK 4.0" -handleSubmit(e, { - data: { imageUrl: 'https://...' }, - body: { custom: 'value' }, - allowEmptySubmit: true, -}); -``` - -```tsx filename="AI SDK 5.0" -sendMessage( - { - /* yourMessage */ - }, - { - body: { - custom: 'value', - imageUrl: 'https://...', // Move data to body - }, - }, -); -``` - -#### Request Options Type Rename - -`RequestOptions` has been renamed to `CompletionRequestOptions`. - -```tsx filename="AI SDK 4.0" -import type { RequestOptions } from 'ai'; -``` - -```tsx filename="AI SDK 5.0" -import type { CompletionRequestOptions } from 'ai'; -``` - -#### addToolResult Renamed to addToolOutput - -The `addToolResult` method has been renamed to `addToolOutput`. Additionally, the `result` parameter has been renamed to `output` for consistency with other tool-related APIs. - -```tsx filename="AI SDK 4.0" -const { addToolResult } = useChat(); - -// Add tool result with 'result' parameter -addToolResult({ - toolCallId: 'tool-call-123', - result: 'Weather: 72°F, sunny', -}); -``` - -```tsx filename="AI SDK 5.0" -const { addToolOutput } = useChat(); - -// Add tool output with 'output' parameter and 'tool' name for type safety -addToolOutput({ - tool: 'getWeather', - toolCallId: 'tool-call-123', - output: 'Weather: 72°F, sunny', -}); -``` - - - `addToolResult` is still available but deprecated. It will be removed in - version 6. - - -#### Tool Result Submission Changes - -The automatic tool result submission behavior has been updated in `useChat` and the `Chat` component. You now have more control and flexibility over when tool results are submitted. - -- `onToolCall` no longer supports returning values to automatically submit tool results -- You must explicitly call `addToolOutput` to provide tool results -- Use `sendAutomaticallyWhen` with `lastAssistantMessageIsCompleteWithToolCalls` helper for automatic submission -- Important: Don't use `await` with `addToolOutput` inside `onToolCall` to avoid deadlocks -- The `maxSteps` parameter has been removed from the `Chat` component and `useChat` hook -- For multi-step tool execution, use server-side `stopWhen` conditions instead (see [maxSteps Removal](#maxsteps-removal)) - -```tsx filename="AI SDK 4.0" -const { messages, sendMessage, addToolResult } = useChat({ - maxSteps: 5, // Removed in v5 - - // Automatic submission by returning a value - async onToolCall({ toolCall }) { - if (toolCall.toolName === 'getLocation') { - const cities = ['New York', 'Los Angeles', 'Chicago', 'San Francisco']; - return cities[Math.floor(Math.random() * cities.length)]; - } - }, -}); -``` - -```tsx filename="AI SDK 5.0" -import { useChat } from '@ai-sdk/react'; -import { - DefaultChatTransport, - lastAssistantMessageIsCompleteWithToolCalls, -} from 'ai'; - -const { messages, sendMessage, addToolOutput } = useChat({ - // Automatic submission with helper - sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls, - - async onToolCall({ toolCall }) { - if (toolCall.toolName === 'getLocation') { - const cities = ['New York', 'Los Angeles', 'Chicago', 'San Francisco']; - - // Important: Don't await inside onToolCall to avoid deadlocks - addToolOutput({ - tool: 'getLocation', - toolCallId: toolCall.toolCallId, - output: cities[Math.floor(Math.random() * cities.length)], - }); - } - }, -}); -``` - -#### Loading State Changes - -The deprecated `isLoading` helper has been removed in favor of `status`. - -```tsx filename="AI SDK 4.0" -const { isLoading } = useChat(); -``` - -```tsx filename="AI SDK 5.0" -const { status } = useChat(); -// Use state instead of isLoading for more granular control -``` - -#### Resume Stream Support - -The resume functionality has been moved from `experimental_resume` to `resumeStream`. - -```tsx filename="AI SDK 4.0" -// Resume was experimental -const { messages } = useChat({ - experimental_resume: true, -}); -``` - -```tsx filename="AI SDK 5.0" -const { messages } = useChat({ - resumeStream: true, // Resume interrupted streams -}); -``` - -#### Dynamic Body Values - -In v4, the `body` option in useChat configuration would dynamically update with component state changes. In v5, the `body` value is only captured at the first render and remains static throughout the component lifecycle. - -```tsx filename="AI SDK 4.0" -const [temperature, setTemperature] = useState(0.7); - -const { messages } = useChat({ - api: '/api/chat', - body: { - temperature, // This would update dynamically in v4 - }, -}); -``` - -```tsx filename="AI SDK 5.0" -const [temperature, setTemperature] = useState(0.7); - -// Option 1: Use request-level configuration (Recommended) -const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ api: '/api/chat' }), -}); - -// Pass dynamic values at request time -sendMessage( - { text: input }, - { - body: { - temperature, // Current temperature value at request time - }, - }, -); - -// Option 2: Use function configuration with useRef -const temperatureRef = useRef(temperature); -temperatureRef.current = temperature; - -const { messages } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - body: () => ({ - temperature: temperatureRef.current, - }), - }), -}); -``` - -For more details on request configuration, see the [Chatbot guide](/docs/ai-sdk-ui/chatbot#request-configuration). - -#### Usage Information - -In v4, usage information was directly accessible through the `onFinish` callback's options parameter. In v5, usage data is attached as metadata to individual messages using the `messageMetadata` function in `toUIMessageStreamResponse`. - -```tsx filename="AI SDK 4.0" -const { messages } = useChat({ - onFinish(message, options) { - const usage = options.usage; - console.log('Usage:', usage); - }, -}); -``` - -```tsx filename="AI SDK 5.0" -import { - convertToModelMessages, - streamText, - UIMessage, - type LanguageModelUsage, -} from 'ai'; -__PROVIDER_IMPORT__; - -// Create a new metadata type (optional for type-safety) -type MyMetadata = { - totalUsage: LanguageModelUsage; -}; - -// Create a new custom message type with your own metadata -export type MyUIMessage = UIMessage; - -export async function POST(req: Request) { - const { messages }: { messages: MyUIMessage[] } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse({ - originalMessages: messages, - messageMetadata: ({ part }) => { - // Send total usage when generation is finished - if (part.type === 'finish') { - return { totalUsage: part.totalUsage }; - } - }, - }); -} -``` - -Then, on the client, you can access the message-level metadata. - -```tsx filename="AI SDK 5.0 - Client" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import type { MyUIMessage } from './api/chat/route'; -import { DefaultChatTransport } from 'ai'; - -export default function Chat() { - // Use custom message type defined on the server (optional for type-safety) - const { messages } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - }), - }); - - return ( -
- {messages.map(m => ( -
- {m.role === 'user' ? 'User: ' : 'AI: '} - {m.parts.map(part => { - if (part.type === 'text') { - return part.text; - } - })} - {/* Render usage via metadata */} - {m.metadata?.totalUsage && ( -
Total usage: {m.metadata?.totalUsage.totalTokens} tokens
- )} -
- ))} -
- ); -} -``` - -You can also access your metadata from the `onFinish` callback of `useChat`: - -```tsx filename="AI SDK 5.0 - onFinish" -'use client'; - -import { useChat } from '@ai-sdk/react'; -import type { MyUIMessage } from './api/chat/route'; -import { DefaultChatTransport } from 'ai'; - -export default function Chat() { - // Use custom message type defined on the server (optional for type-safety) - const { messages } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - }), - onFinish: ({ message }) => { - // Access message metadata via onFinish callback - console.log(message.metadata?.totalUsage); - }, - }); -} -``` - -#### Request Body Preparation: experimental_prepareRequestBody → prepareSendMessagesRequest - -The `experimental_prepareRequestBody` option has been replaced with `prepareSendMessagesRequest` in the transport configuration. - -```tsx filename="AI SDK 4.0" -import { useChat } from '@ai-sdk/react'; - -const { messages } = useChat({ - api: '/api/chat', - // Only send the last message to the server: - experimental_prepareRequestBody({ messages, id }) { - return { message: messages[messages.length - 1], id }; - }, -}); -``` - -```tsx filename="AI SDK 5.0" -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; - -const { messages } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - // Only send the last message to the server: - prepareSendMessagesRequest({ messages, id }) { - return { body: { message: messages[messages.length - 1], id } }; - }, - }), -}); -``` - -### `@ai-sdk/vue` Changes - -The Vue.js integration has been completely restructured, replacing the `useChat` composable with a `Chat` class. - -#### useChat Replaced with Chat Class - -```typescript filename="@ai-sdk/vue v1" - -``` - -```typescript filename="@ai-sdk/vue v2" - -``` - -#### Message Structure Changes - -Messages now use a `parts` array instead of a `content` string. - -```typescript filename="@ai-sdk/vue v1" - -``` - -```typescript filename="@ai-sdk/vue v2" - -``` - -### `@ai-sdk/svelte` Changes - -The Svelte integration has also been updated with new constructor patterns and readonly properties. - -#### Constructor API Changes - -```js filename="@ai-sdk/svelte v1" -import { Chat } from '@ai-sdk/svelte'; - -const chatInstance = Chat({ - api: '/api/chat', -}); -``` - -```js filename="@ai-sdk/svelte v2" -import { Chat } from '@ai-sdk/svelte'; -import { DefaultChatTransport } from 'ai'; - -const chatInstance = Chat(() => ({ - transport: new DefaultChatTransport({ api: '/api/chat' }), -})); -``` - -##### Properties Made Readonly - -Properties are now readonly and must be updated using setter methods. - -```js filename="@ai-sdk/svelte v1" -// Direct property mutation was allowed -chatInstance.messages = [...chatInstance.messages, newMessage]; -``` - -```js filename="@ai-sdk/svelte v2" -// Must use setter methods -chatInstance.setMessages([...chatInstance.messages, newMessage]); -``` - -##### Removed Managed Input - -Like React and Vue, input management has been removed from the Svelte integration. - -```js filename="@ai-sdk/svelte v1" -// Input was managed internally -const { messages, input, handleSubmit } = chatInstance; -``` - -```js filename="@ai-sdk/svelte v2" -// Must manage input state manually -let input = ''; -const { messages, sendMessage } = chatInstance; - -const handleSubmit = () => { - sendMessage({ text: input }); - input = ''; -}; -``` - -#### `@ai-sdk/ui-utils` Package Removal - -The `@ai-sdk/ui-utils` package has been removed and its exports moved to the main `ai` package. - -```tsx filename="AI SDK 4.0" -import { getTextFromDataUrl } from '@ai-sdk/ui-utils'; -``` - -```tsx filename="AI SDK 5.0" -import { getTextFromDataUrl } from 'ai'; -``` - -**Note**: `processDataStream` was removed entirely in v5.0. Use `readUIMessageStream` instead for processing UI message streams, or use the more configurable Chat/useChat APIs for most use cases. - -### useCompletion Changes - -The `data` property has been removed from the `useCompletion` hook. - -```tsx filename="AI SDK 4.0" -const { - completion, - handleSubmit, - data, // No longer available -} = useCompletion(); -``` - -```tsx filename="AI SDK 5.0" -const { - completion, - handleSubmit, - // data property removed entirely -} = useCompletion(); -``` - -### useAssistant Removal - -The `useAssistant` hook has been removed. - -```tsx filename="AI SDK 4.0" -import { useAssistant } from '@ai-sdk/react'; -``` - -```tsx filename="AI SDK 5.0" -// useAssistant has been removed -// Use useChat with appropriate configuration instead -``` - -For an implementation of the assistant functionality with AI SDK v5, see this [example repository](https://github.com/vercel-labs/ai-sdk-openai-assistants-api). - -#### Attachments → File Parts - -The `experimental_attachments` property has been replaced with the parts array. - -```tsx filename="AI SDK 4.0" -{ - messages.map(message => ( -
- {message.content} - -
- {message.experimental_attachments?.map((attachment, index) => - attachment.contentType?.includes('image/') ? ( - {attachment.name} - ) : attachment.contentType?.includes('text/') ? ( -
- {getTextFromDataUrl(attachment.url)} -
- ) : null, - )} -
-
- )); -} -``` - -```tsx filename="AI SDK 5.0" -{ - messages.map(message => ( -
- {message.parts.map((part, index) => { - if (part.type === 'text') { - return
{part.text}
; - } - - if (part.type === 'file' && part.mediaType?.startsWith('image/')) { - return ( -
- -
- ); - } - })} -
- )); -} -``` - - - Some models do not support text files (text/plain, text/markdown, text/csv, - etc.) as file parts. For text files, you can read and send the context as a text part - instead: - -```tsx -// Instead of this: -{ type: 'file', data: buffer, mediaType: 'text/plain' } - -// Do this: -{ type: 'text', text: buffer.toString('utf-8') } -``` - - - -### Embedding Changes - -#### Provider Options for Embeddings - -Embedding model settings now use provider options instead of model parameters. - -```tsx filename="AI SDK 4.0" -const { embedding } = await embed({ - model: openai('text-embedding-3-small', { - dimensions: 10, - }), -}); -``` - -```tsx filename="AI SDK 5.0" -const { embedding } = await embed({ - model: openai('text-embedding-3-small'), - providerOptions: { - openai: { - dimensions: 10, - }, - }, -}); -``` - -#### Raw Response → Response - -The `rawResponse` property has been renamed to `response`. - -```tsx filename="AI SDK 4.0" -const { rawResponse } = await embed(/* */); -``` - -```tsx filename="AI SDK 5.0" -const { response } = await embed(/* */); -``` - -#### Parallel Requests in embedMany - -`embedMany` now makes parallel requests with a configurable `maxParallelCalls` option. - -```tsx filename="AI SDK 5.0" -const { embeddings, usage } = await embedMany({ - maxParallelCalls: 2, // Limit parallel requests - model: 'openai/text-embedding-3-small', - values: [ - 'sunny day at the beach', - 'rainy afternoon in the city', - 'snowy night in the mountains', - ], -}); -``` - -#### LangChain Adapter Moved to `@ai-sdk/langchain` - -The `LangChainAdapter` has been moved to `@ai-sdk/langchain` and the API has been updated to use UI message streams. - -```tsx filename="AI SDK 4.0" -import { LangChainAdapter } from 'ai'; - -const response = LangChainAdapter.toDataStreamResponse(stream); -``` - -```tsx filename="AI SDK 5.0" -import { toUIMessageStream } from '@ai-sdk/langchain'; -import { createUIMessageStreamResponse } from 'ai'; - -const response = createUIMessageStreamResponse({ - stream: toUIMessageStream(stream), -}); -``` - - - Don't forget to install the new package: `npm install @ai-sdk/langchain` - - -#### LlamaIndex Adapter Moved to `@ai-sdk/llamaindex` - -The `LlamaIndexAdapter` has been extracted to a separate package `@ai-sdk/llamaindex` and follows the same UI message stream pattern. - -```tsx filename="AI SDK 4.0" -import { LlamaIndexAdapter } from 'ai'; - -const response = LlamaIndexAdapter.toDataStreamResponse(stream); -``` - -```tsx filename="AI SDK 5.0" -import { toUIMessageStream } from '@ai-sdk/llamaindex'; -import { createUIMessageStreamResponse } from 'ai'; - -const response = createUIMessageStreamResponse({ - stream: toUIMessageStream(stream), -}); -``` - - - Don't forget to install the new package: `npm install @ai-sdk/llamaindex` - - -## Streaming Architecture - -The streaming architecture has been completely redesigned in v5 to support better content differentiation, concurrent streaming of multiple parts, and improved real-time UX. - -### Stream Protocol Changes - -#### Stream Protocol: Single Chunks → Start/Delta/End Pattern - -The fundamental streaming pattern has changed from single chunks to a three-phase pattern with unique IDs for each content block. - -```tsx filename="AI SDK 4.0" -for await (const chunk of result.fullStream) { - switch (chunk.type) { - case 'text-delta': { - process.stdout.write(chunk.textDelta); - break; - } - } -} -``` - -```tsx filename="AI SDK 5.0" -for await (const chunk of result.fullStream) { - switch (chunk.type) { - case 'text-start': { - // New: Initialize a text block with unique ID - console.log(`Starting text block: ${chunk.id}`); - break; - } - case 'text-delta': { - // Changed: Now includes ID and uses 'delta' property - process.stdout.write(chunk.delta); // Changed from 'textDelta' - break; - } - case 'text-end': { - // New: Finalize the text block - console.log(`Completed text block: ${chunk.id}`); - break; - } - } -} -``` - -#### Reasoning Streaming Pattern - -Reasoning content now follows the same start/delta/end pattern: - -```tsx filename="AI SDK 4.0" -for await (const chunk of result.fullStream) { - switch (chunk.type) { - case 'reasoning': { - // Single chunk with full reasoning text - console.log('Reasoning:', chunk.text); - break; - } - } -} -``` - -```tsx filename="AI SDK 5.0" -for await (const chunk of result.fullStream) { - switch (chunk.type) { - case 'reasoning-start': { - console.log(`Starting reasoning block: ${chunk.id}`); - break; - } - case 'reasoning-delta': { - process.stdout.write(chunk.delta); - break; - } - case 'reasoning-end': { - console.log(`Completed reasoning block: ${chunk.id}`); - break; - } - } -} -``` - -#### Tool Input Streaming - -Tool inputs can now be streamed as they're being generated: - -```tsx filename="AI SDK 5.0" -for await (const chunk of result.fullStream) { - switch (chunk.type) { - case 'tool-input-start': { - console.log(`Starting tool input for ${chunk.toolName}: ${chunk.id}`); - break; - } - case 'tool-input-delta': { - // Stream the JSON input as it's being generated - process.stdout.write(chunk.delta); - break; - } - case 'tool-input-end': { - console.log(`Completed tool input: ${chunk.id}`); - break; - } - case 'tool-call': { - // Final tool call with complete input - console.log('Tool call:', chunk.toolName, chunk.input); - break; - } - } -} -``` - -#### onChunk Callback Changes - -The `onChunk` callback now receives the new streaming chunk types with IDs and the start/delta/end pattern. - -```tsx filename="AI SDK 4.0" -const result = streamText({ - model: __MODEL__, - prompt: 'Write a story', - onChunk({ chunk }) { - switch (chunk.type) { - case 'text-delta': { - // Single property with text content - console.log('Text delta:', chunk.textDelta); - break; - } - } - }, -}); -``` - -```tsx filename="AI SDK 5.0" -const result = streamText({ - model: __MODEL__, - prompt: 'Write a story', - onChunk({ chunk }) { - switch (chunk.type) { - case 'text-delta': { - // Text chunks now use single 'text' type - console.log('Text chunk:', chunk.text); - break; - } - case 'reasoning': { - // Reasoning chunks use single 'reasoning' type - console.log('Reasoning chunk:', chunk.text); - break; - } - case 'source': { - console.log('Source chunk:', chunk); - break; - } - case 'tool-call': { - console.log('Tool call:', chunk.toolName, chunk.input); - break; - } - case 'tool-input-start': { - console.log( - `Tool input started for ${chunk.toolName}:`, - chunk.toolCallId, - ); - break; - } - case 'tool-input-delta': { - console.log(`Tool input delta for ${chunk.toolCallId}:`, chunk.delta); - break; - } - case 'tool-result': { - console.log('Tool result:', chunk.output); - break; - } - case 'raw': { - console.log('Raw chunk:', chunk); - break; - } - } - }, -}); -``` - -#### File Stream Parts Restructure - -File parts in streams have been flattened. - -```tsx filename="AI SDK 4.0" -for await (const chunk of result.fullStream) { - switch (chunk.type) { - case 'file': { - console.log('Media type:', chunk.file.mediaType); - console.log('File data:', chunk.file.data); - break; - } - } -} -``` - -```tsx filename="AI SDK 5.0" -for await (const chunk of result.fullStream) { - switch (chunk.type) { - case 'file': { - console.log('Media type:', chunk.mediaType); - console.log('File data:', chunk.data); - break; - } - } -} -``` - -#### Source Stream Parts Restructure - -Source stream parts have been flattened. - -```tsx filename="AI SDK 4.0" -for await (const part of result.fullStream) { - if (part.type === 'source' && part.source.sourceType === 'url') { - console.log('ID:', part.source.id); - console.log('Title:', part.source.title); - console.log('URL:', part.source.url); - } -} -``` - -```tsx filename="AI SDK 5.0" -for await (const part of result.fullStream) { - if (part.type === 'source' && part.sourceType === 'url') { - console.log('ID:', part.id); - console.log('Title:', part.title); - console.log('URL:', part.url); - } -} -``` - -#### Finish Event Changes - -Stream finish events have been renamed for consistency. - -```tsx filename="AI SDK 4.0" -for await (const part of result.fullStream) { - switch (part.type) { - case 'step-finish': { - console.log('Step finished:', part.finishReason); - break; - } - case 'finish': { - console.log('Usage:', part.usage); - break; - } - } -} -``` - -```tsx filename="AI SDK 5.0" -for await (const part of result.fullStream) { - switch (part.type) { - case 'finish-step': { - // Renamed from 'step-finish' - console.log('Step finished:', part.finishReason); - break; - } - case 'finish': { - console.log('Total Usage:', part.totalUsage); // Changed from 'usage' - break; - } - } -} -``` - -### Stream Protocol Changes - -#### Proprietary Protocol -> Server-Sent Events - -The data stream protocol has been updated to use Server-Sent Events. - -```tsx filename="AI SDK 4.0" -import { createDataStream, formatDataStreamPart } from 'ai'; - -const dataStream = createDataStream({ - execute: writer => { - writer.writeData('initialized call'); - writer.write(formatDataStreamPart('text', 'Hello')); - writer.writeSource({ - type: 'source', - sourceType: 'url', - id: 'source-1', - url: 'https://example.com', - title: 'Example Source', - }); - }, -}); -``` - -```tsx filename="AI SDK 5.0" -import { createUIMessageStream } from 'ai'; - -const stream = createUIMessageStream({ - execute: ({ writer }) => { - writer.write({ type: 'data', value: ['initialized call'] }); - writer.write({ type: 'text', value: 'Hello' }); - writer.write({ - type: 'source-url', - value: { - type: 'source', - id: 'source-1', - url: 'https://example.com', - title: 'Example Source', - }, - }); - }, -}); -``` - -#### Data Stream Response Helper Functions Renamed - -The streaming API has been completely restructured from data streams to UI message streams. - -```tsx filename="AI SDK 4.0" -// Express/Node.js servers -app.post('/stream', async (req, res) => { - const result = streamText({ - model: __MODEL__, - prompt: 'Generate content', - }); - - result.pipeDataStreamToResponse(res); -}); - -// Next.js API routes -const result = streamText({ - model: __MODEL__, - prompt: 'Generate content', -}); - -return result.toDataStreamResponse(); -``` - -```tsx filename="AI SDK 5.0" -// Express/Node.js servers -app.post('/stream', async (req, res) => { - const result = streamText({ - model: __MODEL__, - prompt: 'Generate content', - }); - - result.pipeUIMessageStreamToResponse(res); -}); - -// Next.js API routes -const result = streamText({ - model: __MODEL__, - prompt: 'Generate content', -}); - -return result.toUIMessageStreamResponse(); -``` - -#### Stream Transform Function Renaming - -Various stream-related functions have been renamed for consistency. - -```tsx filename="AI SDK 4.0" -import { DataStreamToSSETransformStream } from 'ai'; -``` - -```tsx filename="AI SDK 5.0" -import { JsonToSseTransformStream } from 'ai'; -``` - -#### Error Handling: getErrorMessage → onError - -The `getErrorMessage` option in `toDataStreamResponse` has been replaced with `onError` in `toUIMessageStreamResponse`, providing more control over error forwarding to the client. - -By default, error messages are NOT sent to the client to prevent leaking sensitive information. The `onError` callback allows you to explicitly control what error information is forwarded to the client. - -```tsx filename="AI SDK 4.0" -return result.toDataStreamResponse({ - getErrorMessage: error => { - // Return sanitized error data to send to client - // Only return what you want the client to see! - return { - errorCode: 'STREAM_ERROR', - message: 'An error occurred while processing your request', - // In production, avoid sending error.message directly to prevent information leakage - }; - }, -}); -``` - -```tsx filename="AI SDK 5.0" -return result.toUIMessageStreamResponse({ - onError: error => { - // Return sanitized error data to send to client - // Only return what you want the client to see! - return { - errorCode: 'STREAM_ERROR', - message: 'An error occurred while processing your request', - // In production, avoid sending error.message directly to prevent information leakage - }; - }, -}); -``` - -### Utility Changes - -#### ID Generation Changes - -The `createIdGenerator()` function now requires a `size` argument. - -```tsx filename="AI SDK 4.0" -const generator = createIdGenerator({ prefix: 'msg' }); -const id = generator(16); // Custom size at call time -``` - -```tsx filename="AI SDK 5.0" -const generator = createIdGenerator({ prefix: 'msg', size: 16 }); -const id = generator(); // Fixed size from creation -``` - -#### IDGenerator → IdGenerator - -The type name has been updated. - -```tsx filename="AI SDK 4.0" -import { IDGenerator } from 'ai'; -``` - -```tsx filename="AI SDK 5.0" -import { IdGenerator } from 'ai'; -``` - -### Provider Interface Changes - -#### Language Model V2 Import - -`LanguageModelV3` must now be imported from `@ai-sdk/provider`. - -```tsx filename="AI SDK 4.0" -import { LanguageModelV3 } from 'ai'; -``` - -```tsx filename="AI SDK 5.0" -import { LanguageModelV3 } from '@ai-sdk/provider'; -``` - -#### Middleware Rename - -`LanguageModelV1Middleware` has been renamed and moved. - -```tsx filename="AI SDK 4.0" -import { LanguageModelV1Middleware } from 'ai'; -``` - -```tsx filename="AI SDK 5.0" -import { LanguageModelV3Middleware } from '@ai-sdk/provider'; -``` - -#### Usage Token Properties - -Token usage properties have been renamed for consistency. - -```tsx filename="AI SDK 4.0" -// In language model implementations -{ - usage: { - promptTokens: 10, - completionTokens: 20 - } -} -``` - -```tsx filename="AI SDK 5.0" -// In language model implementations -{ - usage: { - inputTokens: 10, - outputTokens: 20, - totalTokens: 30 // Now required - } -} -``` - -#### Stream Part Type Changes - -The `LanguageModelV3StreamPart` type has been expanded to support the new streaming architecture with start/delta/end patterns and IDs. - -```tsx filename="AI SDK 4.0" -// V4: Simple stream parts -type LanguageModelV3StreamPart = - | { type: 'text-delta'; textDelta: string } - | { type: 'reasoning'; text: string } - | { type: 'tool-call'; toolCallId: string; toolName: string; input: string }; -``` - -```tsx filename="AI SDK 5.0" -// V5: Enhanced stream parts with IDs and lifecycle events -type LanguageModelV3StreamPart = - // Text blocks with start/delta/end pattern - | { - type: 'text-start'; - id: string; - providerMetadata?: SharedV2ProviderMetadata; - } - | { - type: 'text-delta'; - id: string; - delta: string; - providerMetadata?: SharedV2ProviderMetadata; - } - | { - type: 'text-end'; - id: string; - providerMetadata?: SharedV2ProviderMetadata; - } - - // Reasoning blocks with start/delta/end pattern - | { - type: 'reasoning-start'; - id: string; - providerMetadata?: SharedV2ProviderMetadata; - } - | { - type: 'reasoning-delta'; - id: string; - delta: string; - providerMetadata?: SharedV2ProviderMetadata; - } - | { - type: 'reasoning-end'; - id: string; - providerMetadata?: SharedV2ProviderMetadata; - } - - // Tool input streaming - | { - type: 'tool-input-start'; - id: string; - toolName: string; - providerMetadata?: SharedV2ProviderMetadata; - } - | { - type: 'tool-input-delta'; - id: string; - delta: string; - providerMetadata?: SharedV2ProviderMetadata; - } - | { - type: 'tool-input-end'; - id: string; - providerMetadata?: SharedV2ProviderMetadata; - } - - // Enhanced tool calls - | { - type: 'tool-call'; - toolCallId: string; - toolName: string; - input: string; - providerMetadata?: SharedV2ProviderMetadata; - } - - // Stream lifecycle events - | { type: 'stream-start'; warnings: Array } - | { - type: 'finish'; - usage: LanguageModelV3Usage; - finishReason: LanguageModelV3FinishReason; - providerMetadata?: SharedV2ProviderMetadata; - }; -``` - -#### Raw Response → Response - -Provider response objects have been updated. - -```tsx filename="AI SDK 4.0" -// In language model implementations -{ - rawResponse: { - /* ... */ - } -} -``` - -```tsx filename="AI SDK 5.0" -// In language model implementations -{ - response: { - /* ... */ - } -} -``` - -#### `wrapLanguageModel` now stable - -```tsx filename="AI SDK 4.0" -import { experimental_wrapLanguageModel } from 'ai'; -``` - -```tsx filename="AI SDK 5.0" -import { wrapLanguageModel } from 'ai'; -``` - -#### `activeTools` No Longer Experimental - -```tsx filename="AI SDK 4.0" -const result = await generateText({ - model: __MODEL__, - messages, - tools: { weatherTool, locationTool }, - experimental_activeTools: ['weatherTool'], -}); -``` - -```tsx filename="AI SDK 5.0" -const result = await generateText({ - model: __MODEL__, - messages, - tools: { weatherTool, locationTool }, - activeTools: ['weatherTool'], // No longer experimental -}); -``` - -#### `prepareStep` No Longer Experimental - -The `experimental_prepareStep` option has been promoted and no longer requires the experimental prefix. - -```tsx filename="AI SDK 4.0" -const result = await generateText({ - model: __MODEL__, - messages, - tools: { weatherTool, locationTool }, - experimental_prepareStep: ({ steps, stepNumber, model }) => { - console.log('Preparing step:', stepNumber); - return { - activeTools: ['weatherTool'], - system: 'Be helpful and concise.', - }; - }, -}); -``` - -```tsx filename="AI SDK 5.0" -const result = await generateText({ - model: __MODEL__, - messages, - tools: { weatherTool, locationTool }, - prepareStep: ({ steps, stepNumber, model }) => { - console.log('Preparing step:', stepNumber); - return { - activeTools: ['weatherTool'], - system: 'Be helpful and concise.', - // Can also configure toolChoice, model, etc. - }; - }, -}); -``` - -The `prepareStep` function receives `{ steps, stepNumber, model }` and can return: - -- `model`: Different model for this step -- `activeTools`: Which tools to make available -- `toolChoice`: Tool selection strategy -- `system`: System message for this step -- `undefined`: Use default settings - -### Temperature Default Removal - -Temperature is no longer set to `0` by default. - -```tsx filename="AI SDK 4.0" -await generateText({ - model: __MODEL__, - prompt: 'Write a creative story', - // Implicitly temperature: 0 -}); -``` - -```tsx filename="AI SDK 5.0" -await generateText({ - model: __MODEL__, - prompt: 'Write a creative story', - temperature: 0, // Must explicitly set -}); -``` - -## Message Persistence Changes - - - If you have persisted messages in a database, see the [Data Migration - Guide](/docs/migration-guides/migration-guide-5-0-data) for comprehensive - guidance on migrating your stored message data to the v5 format. - - -In v4, you would typically use helper functions like `appendResponseMessages` or `appendClientMessage` to format messages in the `onFinish` callback of `streamText`: - -```tsx filename="AI SDK 4.0" -import { - streamText, - convertToModelMessages, - appendClientMessage, - appendResponseMessages, -} from 'ai'; - -const updatedMessages = appendClientMessage({ - messages, - message: lastUserMessage, -}); - -const result = streamText({ - model: __MODEL__, - messages: updatedMessages, - experimental_generateMessageId: () => generateId(), // ID generation on streamText - onFinish: async ({ responseMessages, usage }) => { - // Use helper functions to format messages - const finalMessages = appendResponseMessages({ - messages: updatedMessages, - responseMessages, - }); - - // Save formatted messages to database - await saveMessages(finalMessages); - }, -}); -``` - -In v5, message persistence is now handled through the `toUIMessageStreamResponse` method, which automatically formats response messages in the `UIMessage` format: - -```tsx filename="AI SDK 5.0" -import { streamText, convertToModelMessages, UIMessage } from 'ai'; - -const messages: UIMessage[] = [ - // Your existing messages in UIMessage format -]; - -const result = streamText({ - model: __MODEL__, - messages: convertToModelMessages(messages), - // experimental_generateMessageId removed from here -}); - -return result.toUIMessageStreamResponse({ - originalMessages: messages, // IMPORTANT: Required to prevent duplicate messages - generateMessageId: () => generateId(), // IMPORTANT: Required for proper message ID generation - onFinish: ({ messages, responseMessage }) => { - // messages contains all messages (original + response) in UIMessage format - saveChat({ chatId, messages }); - - // responseMessage contains just the generated message in UIMessage format - saveMessage({ chatId, message: responseMessage }); - }, -}); -``` - - - **Important:** When using `toUIMessageStreamResponse`, you should always - provide both `originalMessages` and `generateMessageId` parameters. Without - these, you may experience duplicate or repeated assistant messages in your UI. - For more details, see [Troubleshooting: Repeated Assistant - Messages](/docs/troubleshooting/repeated-assistant-messages). - - -### Message ID Generation - -The `experimental_generateMessageId` option has been moved from `streamText` configuration to `toUIMessageStreamResponse`, as it's designed for use with `UIMessage`s rather than `ModelMessage`s. - -```tsx filename="AI SDK 4.0" -const result = streamText({ - model: __MODEL__, - messages, - experimental_generateMessageId: () => generateId(), -}); -``` - -```tsx filename="AI SDK 5.0" -const result = streamText({ - model: __MODEL__, - messages: convertToModelMessages(messages), -}); - -return result.toUIMessageStreamResponse({ - generateMessageId: () => generateId(), // No longer experimental - // ... -}); -``` - -For more details on message IDs and persistence, see the [Chatbot Message Persistence guide](/docs/ai-sdk-ui/chatbot-message-persistence#message-ids). - -### Using createUIMessageStream - -For more complex scenarios, especially when working with data parts, you can use `createUIMessageStream`: - -```tsx filename="AI SDK 5.0 - Advanced" -import { - createUIMessageStream, - createUIMessageStreamResponse, - streamText, - convertToModelMessages, - UIMessage, -} from 'ai'; - -const stream = createUIMessageStream({ - originalMessages: messages, - generateId: generateId, // Required for proper message ID generation - execute: ({ writer }) => { - // Write custom data parts - writer.write({ - type: 'data', - data: { status: 'processing', timestamp: Date.now() }, - }); - - // Stream the AI response - const result = streamText({ - model: __MODEL__, - messages: convertToModelMessages(messages), - }); - - writer.merge(result.toUIMessageStream()); - }, - onFinish: ({ messages }) => { - // messages contains all messages (original + response + data parts) in UIMessage format - saveChat({ chatId, messages }); - }, -}); - -return createUIMessageStreamResponse({ stream }); -``` - -## Provider & Model Changes - -### OpenAI - -#### Default Provider Instance Uses Responses API - -In AI SDK 5, the default OpenAI provider instance uses the Responses API, while AI SDK 4 used the Chat Completions API. The Chat Completions API remains fully supported and you can use it with `openai.chat(...)`. - -```tsx filename="AI SDK 4.0" -import { openai } from '@ai-sdk/openai'; - -const defaultModel = openai('gpt-4.1-mini'); // Chat Completions API -``` - -```tsx filename="AI SDK 5.0" -import { openai } from '@ai-sdk/openai'; - -const defaultModel = openai('gpt-4.1-mini'); // Responses API - -// Specify a specific API when needed: -const chatCompletionsModel = openai.chat('gpt-4.1-mini'); -const responsesModel = openai.responses('gpt-4.1-mini'); -``` - - - The Responses and Chat Completions APIs have different behavior and defaults. - If you depend on the Chat Completions API, switch your model instance to - `openai.chat(...)` and audit your configuration. - - -#### Strict Schemas (`strictSchemas`) with Responses API - -In AI SDK 4.0, you could set the `strictSchemas` option on Responses models (which defaulted to `true`). This option has been renamed to `strictJsonSchema` in AI SDK 5.0 and now defaults to `false`. - -```tsx filename="AI SDK 4.0" -import { z } from 'zod'; -import { generateObject } from 'ai'; -import { openai, type OpenAIResponsesProviderOptions } from '@ai-sdk/openai'; - -const result = await generateObject({ - model: openai.responses('gpt-4.1'), - schema: z.object({ - // ... - }), - providerOptions: { - openai: { - strictSchemas: true, // default behavior in AI SDK 4 - } satisfies OpenAIResponsesProviderOptions, - }, -}); -``` - -```tsx filename="AI SDK 5.0" -import { z } from 'zod'; -import { generateObject } from 'ai'; -import { openai, type OpenAIResponsesProviderOptions } from '@ai-sdk/openai'; - -const result = await generateObject({ - model: openai('gpt-4.1-2024'), // uses Responses API - schema: z.object({ - // ... - }), - providerOptions: { - openai: { - strictJsonSchema: true, // defaults to false, opt back in to the AI SDK 4 strict behavior - } satisfies OpenAIResponsesProviderOptions, - }, -}); -``` - -If you call `openai.chat(...)` to use the Chat Completions API directly, you can type it with `OpenAIChatLanguageModelOptions`. AI SDK 5 adds the same `strictJsonSchema` option there as well. - -#### Structured Outputs - -The `structuredOutputs` option is now configured using provider options rather than as a setting on the model instance. - -```tsx filename="AI SDK 4.0" -import { z } from 'zod'; -import { generateObject } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const result = await generateObject({ - model: openai('gpt-4.1', { structuredOutputs: true }), // use Chat Completions API - schema: z.object({ name: z.string() }), -}); -``` - -```tsx filename="AI SDK 5.0 (Chat Completions API)" -import { z } from 'zod'; -import { generateObject } from 'ai'; -import { openai, type OpenAIChatLanguageModelOptions } from '@ai-sdk/openai'; - -const result = await generateObject({ - model: openai.chat('gpt-4.1'), // use Chat Completions API - schema: z.object({ name: z.string() }), - providerOptions: { - openai: { - structuredOutputs: true, - } satisfies OpenAIChatLanguageModelOptions, - }, -}); -``` - -#### Compatibility Option Removal - -The `compatibility` option has been removed; strict compatibility mode is now the default. - -```tsx filename="AI SDK 4.0" -const openai = createOpenAI({ - compatibility: 'strict', -}); -``` - -```tsx filename="AI SDK 5.0" -const openai = createOpenAI({ - // strict compatibility is now the default -}); -``` - -#### Legacy Function Calls Removal - -The `useLegacyFunctionCalls` option has been removed. - -```tsx filename="AI SDK 4.0" -const result = streamText({ - model: openai('gpt-4.1', { useLegacyFunctionCalls: true }), -}); -``` - -```tsx filename="AI SDK 5.0" -const result = streamText({ - model: openai('gpt-4.1'), -}); -``` - -#### Simulate Streaming - -The `simulateStreaming` model option has been replaced with middleware. - -```tsx filename="AI SDK 4.0" -const result = generateText({ - model: openai('gpt-4.1', { simulateStreaming: true }), - prompt: 'Hello, world!', -}); -``` - -```tsx filename="AI SDK 5.0" -import { simulateStreamingMiddleware, wrapLanguageModel } from 'ai'; - -const model = wrapLanguageModel({ - model: openai('gpt-4.1'), - middleware: simulateStreamingMiddleware(), -}); - -const result = generateText({ - model, - prompt: 'Hello, world!', -}); -``` - -### Google - -#### Search Grounding is now a provider defined tool - -Search Grounding is now called "Google Search" and is now a provider defined tool. - -```tsx filename="AI SDK 4.0" -const { text, providerMetadata } = await generateText({ - model: google('gemini-1.5-pro', { - useSearchGrounding: true, - }), - prompt: 'List the top 5 San Francisco news from the past week.', -}); -``` - -```tsx filename="AI SDK 5.0" -import { google } from '@ai-sdk/google'; -const { text, sources, providerMetadata } = await generateText({ - model: google('gemini-1.5-pro'), - prompt: - 'List the top 5 San Francisco news from the past week.' - tools: { - google_search: google.tools.googleSearch({}), - }, -}); -``` - -### Amazon Bedrock - -#### Snake Case → Camel Case - -Provider options have been updated to use camelCase. - -```tsx filename="AI SDK 4.0" -const result = await generateText({ - model: bedrock('amazon.titan-tg1-large'), - prompt: 'Hello, world!', - providerOptions: { - bedrock: { - reasoning_config: { - /* ... */ - }, - }, - }, -}); -``` - -```tsx filename="AI SDK 5.0" -const result = await generateText({ - model: bedrock('amazon.titan-tg1-large'), - prompt: 'Hello, world!', - providerOptions: { - bedrock: { - reasoningConfig: { - /* ... */ - }, - }, - }, -}); -``` - -### Provider-Utils Changes - -Deprecated `CoreTool*` types have been removed. - -```tsx filename="AI SDK 4.0" -import { - CoreToolCall, - CoreToolResult, - CoreToolResultUnion, - CoreToolCallUnion, - CoreToolChoice, -} from '@ai-sdk/provider-utils'; -``` - -```tsx filename="AI SDK 5.0" -import { - ToolCall, - ToolResult, - TypedToolResult, - TypedToolCall, - ToolChoice, -} from '@ai-sdk/provider-utils'; -``` - -## Troubleshooting - -### TypeScript Performance Issues with Zod - -If you experience TypeScript server crashes, slow type checking, or errors like "Type instantiation is excessively deep and possibly infinite" when using Zod with AI SDK 5.0: - -1. **First, ensure you're using Zod 4.1.8 or later** - this version includes a fix for module resolution issues that cause TypeScript performance problems. - -2. If the issue persists, update your `tsconfig.json` to use `moduleResolution: "nodenext"`: - -```json -{ - "compilerOptions": { - "moduleResolution": "nodenext" - // ... other options - } -} -``` - -This resolves the TypeScript performance issues while allowing you to continue using the standard Zod import. If this doesn't resolve the issue, you can try using a version-specific import path as an alternative solution. For detailed troubleshooting steps, see [TypeScript performance issues with Zod](/docs/troubleshooting/typescript-performance-zod). - -## Codemod Table - -The following table lists available codemods for the AI SDK 5.0 upgrade -process. -For more information, see the [Codemods](#codemods) section. - -| Change | Codemod | -| ------------------------------------------------ | ----------------------------------------------------- | -| **AI SDK Core Changes** | | -| Flatten streamText file properties | `v5/flatten-streamtext-file-properties` | -| ID Generation Changes | `v5/require-createIdGenerator-size-argument` | -| IDGenerator → IdGenerator | `v5/rename-IDGenerator-to-IdGenerator` | -| Import LanguageModelV3 from provider package | `v5/import-LanguageModelV3-from-provider-package` | -| Migrate to data stream protocol v2 | `v5/migrate-to-data-stream-protocol-v2` | -| Move image model maxImagesPerCall | `v5/move-image-model-maxImagesPerCall` | -| Move LangChain adapter | `v5/move-langchain-adapter` | -| Move maxSteps to stopWhen | `v5/move-maxsteps-to-stopwhen` | -| Move provider options | `v5/move-provider-options` | -| Move React to AI SDK | `v5/move-react-to-ai-sdk` | -| Move UI utils to AI | `v5/move-ui-utils-to-ai` | -| Remove experimental wrap language model | `v5/remove-experimental-wrap-language-model` | -| Remove experimental activeTools | `v5/remove-experimental-activetools` | -| Remove experimental prepareStep | `v5/remove-experimental-preparestep` | -| Remove experimental continueSteps | `v5/remove-experimental-continuesteps` | -| Remove experimental temperature | `v5/remove-experimental-temperature` | -| Remove experimental truncate | `v5/remove-experimental-truncate` | -| Remove experimental OpenAI compatibility | `v5/remove-experimental-openai-compatibility` | -| Remove experimental OpenAI legacy function calls | `v5/remove-experimental-openai-legacy-function-calls` | -| Remove experimental OpenAI structured outputs | `v5/remove-experimental-openai-structured-outputs` | -| Remove experimental OpenAI store | `v5/remove-experimental-openai-store` | -| Remove experimental OpenAI user | `v5/remove-experimental-openai-user` | -| Remove experimental OpenAI parallel tool calls | `v5/remove-experimental-openai-parallel-tool-calls` | -| Remove experimental OpenAI response format | `v5/remove-experimental-openai-response-format` | -| Remove experimental OpenAI logit bias | `v5/remove-experimental-openai-logit-bias` | -| Remove experimental OpenAI logprobs | `v5/remove-experimental-openai-logprobs` | -| Remove experimental OpenAI seed | `v5/remove-experimental-openai-seed` | -| Remove experimental OpenAI service tier | `v5/remove-experimental-openai-service-tier` | -| Remove experimental OpenAI top logprobs | `v5/remove-experimental-openai-top-logprobs` | -| Remove experimental OpenAI transform | `v5/remove-experimental-openai-transform` | -| Remove experimental OpenAI stream options | `v5/remove-experimental-openai-stream-options` | -| Remove experimental OpenAI prediction | `v5/remove-experimental-openai-prediction` | -| Remove experimental Anthropic caching | `v5/remove-experimental-anthropic-caching` | -| Remove experimental Anthropic computer use | `v5/remove-experimental-anthropic-computer-use` | -| Remove experimental Anthropic PDF support | `v5/remove-experimental-anthropic-pdf-support` | -| Remove experimental Anthropic prompt caching | `v5/remove-experimental-anthropic-prompt-caching` | -| Remove experimental Google search grounding | `v5/remove-experimental-google-search-grounding` | -| Remove experimental Google code execution | `v5/remove-experimental-google-code-execution` | -| Remove experimental Google cached content | `v5/remove-experimental-google-cached-content` | -| Remove experimental Google custom headers | `v5/remove-experimental-google-custom-headers` | -| Rename format stream part | `v5/rename-format-stream-part` | -| Rename parse stream part | `v5/rename-parse-stream-part` | -| Replace image type with file type | `v5/replace-image-type-with-file-type` | -| Replace LlamaIndex adapter | `v5/replace-llamaindex-adapter` | -| Replace onCompletion with onFinal | `v5/replace-oncompletion-with-onfinal` | -| Replace provider metadata with provider options | `v5/replace-provider-metadata-with-provider-options` | -| Replace rawResponse with response | `v5/replace-rawresponse-with-response` | -| Replace redacted reasoning type | `v5/replace-redacted-reasoning-type` | -| Replace simulate streaming | `v5/replace-simulate-streaming` | -| Replace textDelta with text | `v5/replace-textdelta-with-text` | -| Replace usage token properties | `v5/replace-usage-token-properties` | -| Restructure file stream parts | `v5/restructure-file-stream-parts` | -| Restructure source stream parts | `v5/restructure-source-stream-parts` | -| RSC package | `v5/rsc-package` | - -## Changes Between v5 Beta Versions - -This section documents breaking changes between different beta versions of AI SDK 5.0. If you're upgrading from an earlier v5 beta version to a later one, check this section for any changes that might affect your code. - -### fullStream Type Rename: text/reasoning → text-delta/reasoning-delta - -The chunk types in `fullStream` have been renamed for consistency with UI streams and language model streams. - -```tsx filename="AI SDK 5.0 (before beta.26)" -for await (const chunk of result.fullStream) { - switch (chunk.type) { - case 'text-delta': { - process.stdout.write(chunk.text); - break; - } - case 'reasoning': { - console.log('Reasoning:', chunk.text); - break; - } - } -} -``` - -```tsx filename="AI SDK 5.0 (beta.26 and later)" -for await (const chunk of result.fullStream) { - switch (chunk.type) { - case 'text-delta': { - process.stdout.write(chunk.text); - break; - } - case 'reasoning-delta': { - console.log('Reasoning:', chunk.text); - break; - } - } -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/27-migration-guide-4-2.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/27-migration-guide-4-2.mdx deleted file mode 100644 index 39e4f3b8b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/27-migration-guide-4-2.mdx +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Migrate AI SDK 4.1 to 4.2 -description: Learn how to upgrade AI SDK 4.1 to 4.2. ---- - -# Migrate AI SDK 4.1 to 4.2 - - - Check out the [AI SDK 4.2 release blog - post](https://vercel.com/blog/ai-sdk-4-2) for more information about the - release. - - -This guide will help you upgrade to AI SDK 4.2: - -## Stable APIs - -The following APIs have been moved to stable and no longer have the `experimental_` prefix: - -- `customProvider` -- `providerOptions` (renamed from `providerMetadata` for provider-specific inputs) -- `providerMetadata` (for provider-specific outputs) -- `toolCallStreaming` option for `streamText` - -## Dependency Versions - -AI SDK requires a non-optional `zod` dependency with version `^3.23.8`. - -## UI Message Parts - -In AI SDK 4.2, we've redesigned how `useChat` handles model outputs with message parts and multiple steps. -This is a significant improvement that simplifies rendering complex, multi-modal AI responses in your UI. - -### What's Changed - -Assistant messages with tool calling now get combined into a single message with multiple parts, rather than creating separate messages for each step. -This change addresses two key developments in AI applications: - -1. **Diverse Output Types**: Models now generate more than just text; they produce reasoning steps, sources, and tool calls. -2. **Interleaved Outputs**: In multi-step agent use-cases, these different output types are frequently interleaved. - -### Benefits of the New Approach - -Previously, `useChat` stored different output types separately, which made it challenging to maintain the correct sequence in your UI when these elements were interleaved in a response, -and led to multiple consecutive assistant messages when there were tool calls. For example: - -```javascript -message.content = "Final answer: 42"; -message.reasoning = "First I'll calculate X, then Y..."; -message.toolInvocations = [{toolName: "calculator", args: {...}}]; -``` - -This structure was limiting. The new message parts approach replaces separate properties with an ordered array that preserves the exact sequence: - -```javascript -message.parts = [ - { type: "text", text: "Final answer: 42" }, - { type: "reasoning", reasoning: "First I'll calculate X, then Y..." }, - { type: "tool-invocation", toolInvocation: { toolName: "calculator", args: {...} } }, -]; -``` - -### Migration - -Existing applications using the previous message format will need to update their UI components to handle the new `parts` array. -The fields from the previous format are still available for backward compatibility, but we recommend migrating to the new format for better support of multi-modal and multi-step interactions. - -You can use the `useChat` hook with the new message parts as follows: - -```javascript -function Chat() { - const { messages } = useChat(); - return ( -
- {messages.map(message => - message.parts.map((part, i) => { - switch (part.type) { - case 'text': - return

{part.text}

; - case 'source': - return

{part.source.url}

; - case 'reasoning': - return
{part.reasoning}
; - case 'tool-invocation': - return
{part.toolInvocation.toolName}
; - case 'file': - return ( - - ); - } - }), - )} -
- ); -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/28-migration-guide-4-1.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/28-migration-guide-4-1.mdx deleted file mode 100644 index 0d5101f48..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/28-migration-guide-4-1.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Migrate AI SDK 4.0 to 4.1 -description: Learn how to upgrade AI SDK 4.0 to 4.1. ---- - -# Migrate AI SDK 4.0 to 4.1 - - - Check out the [AI SDK 4.1 release blog - post](https://vercel.com/blog/ai-sdk-4-1) for more information about the - release. - - -No breaking changes in this release. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/29-migration-guide-4-0.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/29-migration-guide-4-0.mdx deleted file mode 100644 index 5e34e9645..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/29-migration-guide-4-0.mdx +++ /dev/null @@ -1,1157 +0,0 @@ ---- -title: Migrate AI SDK 3.4 to 4.0 -description: Learn how to upgrade AI SDK 3.4 to 4.0. ---- - -# Migrate AI SDK 3.4 to 4.0 - - - Check out the [AI SDK 4.0 release blog - post](https://vercel.com/blog/ai-sdk-4-0) for more information about the - release. - - -## Recommended Migration Process - -1. Backup your project. If you use a versioning control system, make sure all previous versions are committed. -1. [Migrate to AI SDK 3.4](/docs/migration-guides/migration-guide-3-4). -1. Upgrade to AI SDK 4.0. -1. Automatically migrate your code using [codemods](#codemods). - > If you don't want to use codemods, we recommend resolving all deprecation warnings before upgrading to AI SDK 4.0. -1. Follow the breaking changes guide below. -1. Verify your project is working as expected. -1. Commit your changes. - -## AI SDK 4.0 package versions - -You need to update the following packages to the following versions in your `package.json` file(s): - -- `ai` package: `4.0.*` -- `ai-sdk@provider-utils` package: `2.0.*` -- `ai-sdk/*` packages: `1.0.*` (other `@ai-sdk` packages) - -## Codemods - -The AI SDK provides Codemod transformations to help upgrade your codebase when a -feature is deprecated, removed, or otherwise changed. - -Codemods are transformations that run on your codebase programmatically. They -allow you to easily apply many changes without having to manually go through -every file. - - - Codemods are intended as a tool to help you with the upgrade process. They may - not cover all of the changes you need to make. You may need to make additional - changes manually. - - -You can run all codemods provided as part of the 4.0 upgrade process by running -the following command from the root of your project: - -```sh -npx @ai-sdk/codemod upgrade -``` - -To run only the v4 codemods: - -```sh -npx @ai-sdk/codemod v4 -``` - -Individual codemods can be run by specifying the name of the codemod: - -```sh -npx @ai-sdk/codemod -``` - -For example, to run a specific v4 codemod: - -```sh -npx @ai-sdk/codemod v4/replace-baseurl src/ -``` - -See also the [table of codemods](#codemod-table). In addition, the latest set of -codemods can be found in the -[`@ai-sdk/codemod`](https://github.com/vercel/ai/tree/main/packages/codemod/src/codemods) -repository. - -## Provider Changes - -### Removed `baseUrl` option - -The `baseUrl` option has been removed from all providers. Please use the `baseURL` option instead. - -```ts filename="AI SDK 3.4" -const perplexity = createOpenAI({ - // ... - baseUrl: 'https://api.perplexity.ai/', -}); -``` - -```ts filename="AI SDK 4.0" -const perplexity = createOpenAI({ - // ... - baseURL: 'https://api.perplexity.ai/', -}); -``` - -### Anthropic Provider - -#### Removed `Anthropic` facade - -The `Anthropic` facade has been removed from the Anthropic provider. -Please use the `anthropic` object or the `createAnthropic` function instead. - -```ts filename="AI SDK 3.4" -const anthropic = new Anthropic({ - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const anthropic = createAnthropic({ - // ... -}); -``` - -#### Removed `topK` setting - - - There is no codemod available for this change. Please review and update your - code manually. - - -The model specific `topK` setting has been removed from the Anthropic provider. -You can use the standard `topK` setting instead. - -```ts filename="AI SDK 3.4" -const result = await generateText({ - model: anthropic('claude-3-5-sonnet-latest', { - topK: 0.5, - }), -}); -``` - -```ts filename="AI SDK 4.0" -const result = await generateText({ - model: anthropic('claude-3-5-sonnet-latest'), - topK: 0.5, -}); -``` - -### Google Generative AI Provider - -#### Removed `Google` facade - -The `Google` facade has been removed from the Google Generative AI provider. -Please use the `google` object or the `createGoogleGenerativeAI` function instead. - -```ts filename="AI SDK 3.4" -const google = new Google({ - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const google = createGoogleGenerativeAI({ - // ... -}); -``` - -#### Removed `topK` setting - - - There is no codemod available for this change. Please review and update your - code manually. - - -The model-specific `topK` setting has been removed from the Google Generative AI provider. -You can use the standard `topK` setting instead. - -```ts filename="AI SDK 3.4" -const result = await generateText({ - model: google('gemini-1.5-flash', { - topK: 0.5, - }), -}); -``` - -```ts filename="AI SDK 4.0" -const result = await generateText({ - model: google('gemini-1.5-flash'), - topK: 0.5, -}); -``` - -### Google Vertex Provider - -#### Removed `topK` setting - - - There is no codemod available for this change. Please review and update your - code manually. - - -The model-specific `topK` setting has been removed from the Google Vertex provider. -You can use the standard `topK` setting instead. - -```ts filename="AI SDK 3.4" -const result = await generateText({ - model: vertex('gemini-1.5-flash', { - topK: 0.5, - }), -}); -``` - -```ts filename="AI SDK 4.0" -const result = await generateText({ - model: vertex('gemini-1.5-flash'), - topK: 0.5, -}); -``` - -### Mistral Provider - -#### Removed `Mistral` facade - -The `Mistral` facade has been removed from the Mistral provider. -Please use the `mistral` object or the `createMistral` function instead. - -```ts filename="AI SDK 3.4" -const mistral = new Mistral({ - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const mistral = createMistral({ - // ... -}); -``` - -### OpenAI Provider - -#### Removed `OpenAI` facade - -The `OpenAI` facade has been removed from the OpenAI provider. -Please use the `openai` object or the `createOpenAI` function instead. - -```ts filename="AI SDK 3.4" -const openai = new OpenAI({ - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const openai = createOpenAI({ - // ... -}); -``` - -### LangChain Adapter - -#### Removed `toAIStream` - -The `toAIStream` function has been removed from the LangChain adapter. -Please use the `toDataStream` function instead. - -```ts filename="AI SDK 3.4" -LangChainAdapter.toAIStream(stream); -``` - -```ts filename="AI SDK 4.0" -LangChainAdapter.toDataStream(stream); -``` - -## AI SDK Core Changes - -### `streamText` returns immediately - -Instead of returning a Promise, the `streamText` function now returns immediately. -It is not necessary to await the result of `streamText`. - -```ts filename="AI SDK 3.4" -const result = await streamText({ - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const result = streamText({ - // ... -}); -``` - -### `streamObject` returns immediately - -Instead of returning a Promise, the `streamObject` function now returns immediately. -It is not necessary to await the result of `streamObject`. - -```ts filename="AI SDK 3.4" -const result = await streamObject({ - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const result = streamObject({ - // ... -}); -``` - -### Remove roundtrips - -The `maxToolRoundtrips` and `maxAutomaticRoundtrips` options have been removed from the `generateText` and `streamText` functions. -Please use the `maxSteps` option instead. - -The `roundtrips` property has been removed from the `GenerateTextResult` type. -Please use the `steps` property instead. - -```ts filename="AI SDK 3.4" -const { text, roundtrips } = await generateText({ - maxToolRoundtrips: 1, // or maxAutomaticRoundtrips - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const { text, steps } = await generateText({ - maxSteps: 2, - // ... -}); -``` - -### Removed `nanoid` export - -The `nanoid` export has been removed. Please use [`generateId`](/docs/reference/ai-sdk-core/generate-id) instead. - -```ts filename="AI SDK 3.4" -import { nanoid } from 'ai'; -``` - -```ts filename="AI SDK 4.0" -import { generateId } from 'ai'; -``` - -### Increased default size of generated IDs - - - There is no codemod available for this change. Please review and update your - code manually. - - -The [`generateId`](/docs/reference/ai-sdk-core/generate-id) function now -generates 16-character IDs. The previous default was 7 characters. - -This might e.g. require updating your database schema if you limit the length of -IDs. - -```ts filename="AI SDK 4.0" -import { generateId } from 'ai'; - -const id = generateId(); // now 16 characters -``` - -### Removed `ExperimentalMessage` types - -The following types have been removed: - -- `ExperimentalMessage` (use `ModelMessage` instead) -- `ExperimentalUserMessage` (use `CoreUserMessage` instead) -- `ExperimentalAssistantMessage` (use `CoreAssistantMessage` instead) -- `ExperimentalToolMessage` (use `CoreToolMessage` instead) - -```ts filename="AI SDK 3.4" -import { - ExperimentalMessage, - ExperimentalUserMessage, - ExperimentalAssistantMessage, - ExperimentalToolMessage, -} from 'ai'; -``` - -```ts filename="AI SDK 4.0" -import { - ModelMessage, - CoreUserMessage, - CoreAssistantMessage, - CoreToolMessage, -} from 'ai'; -``` - -### Removed `ExperimentalTool` type - -The `ExperimentalTool` type has been removed. Please use the `CoreTool` type instead. - -```ts filename="AI SDK 3.4" -import { ExperimentalTool } from 'ai'; -``` - -```ts filename="AI SDK 4.0" -import { CoreTool } from 'ai'; -``` - -### Removed experimental AI function exports - -The following exports have been removed: - -- `experimental_generateText` (use `generateText` instead) -- `experimental_streamText` (use `streamText` instead) -- `experimental_generateObject` (use `generateObject` instead) -- `experimental_streamObject` (use `streamObject` instead) - -```ts filename="AI SDK 3.4" -import { - experimental_generateText, - experimental_streamText, - experimental_generateObject, - experimental_streamObject, -} from 'ai'; -``` - -```ts filename="AI SDK 4.0" -import { generateText, streamText, generateObject, streamObject } from 'ai'; -``` - -### Removed AI-stream related methods from `streamText` - -The following methods have been removed from the `streamText` result: - -- `toAIStream` -- `pipeAIStreamToResponse` -- `toAIStreamResponse` - -Use the `toDataStream`, `pipeDataStreamToResponse`, and `toDataStreamResponse` functions instead. - -```ts filename="AI SDK 3.4" -const result = await streamText({ - // ... -}); - -result.toAIStream(); -result.pipeAIStreamToResponse(response); -result.toAIStreamResponse(); -``` - -```ts filename="AI SDK 4.0" -const result = streamText({ - // ... -}); - -result.toDataStream(); -result.pipeDataStreamToResponse(response); -result.toUIMessageStreamResponse(); -``` - -### Renamed "formatStreamPart" to "formatDataStreamPart" - -The `formatStreamPart` function has been renamed to `formatDataStreamPart`. - -```ts filename="AI SDK 3.4" -formatStreamPart('text', 'Hello, world!'); -``` - -```ts filename="AI SDK 4.0" -formatDataStreamPart('text', 'Hello, world!'); -``` - -### Renamed "parseStreamPart" to "parseDataStreamPart" - -The `parseStreamPart` function has been renamed to `parseDataStreamPart`. - -```ts filename="AI SDK 3.4" -const part = parseStreamPart(line); -``` - -```ts filename="AI SDK 4.0" -const part = parseDataStreamPart(line); -``` - -### Renamed `TokenUsage`, `CompletionTokenUsage` and `EmbeddingTokenUsage` types - -The `TokenUsage`, `CompletionTokenUsage` and `EmbeddingTokenUsage` types have -been renamed to `LanguageModelUsage` (for the first two) and -`EmbeddingModelUsage` (for the last). - -```ts filename="AI SDK 3.4" -import { TokenUsage, CompletionTokenUsage, EmbeddingTokenUsage } from 'ai'; -``` - -```ts filename="AI SDK 4.0" -import { LanguageModelUsage, EmbeddingModelUsage } from 'ai'; -``` - -### Removed deprecated telemetry data - - - There is no codemod available for this change. Please review and update your - code manually. - - -The following telemetry data values have been removed: - -- `ai.finishReason` (now in `ai.response.finishReason`) -- `ai.result.object` (now in `ai.response.object`) -- `ai.result.text` (now in `ai.response.text`) -- `ai.result.toolCalls` (now in `ai.response.toolCalls`) -- `ai.stream.msToFirstChunk` (now in `ai.response.msToFirstChunk`) - -This change will apply to observability providers and any scripts or automation that you use for processing telemetry data. - -### Provider Registry - -#### Removed experimental_Provider, experimental_ProviderRegistry, and experimental_ModelRegistry - -The `experimental_Provider` interface, `experimental_ProviderRegistry` interface, and `experimental_ModelRegistry` interface have been removed. -Please use the `Provider` interface instead. - -```ts filename="AI SDK 3.4" -import { experimental_Provider, experimental_ProviderRegistry } from 'ai'; -``` - -```ts filename="AI SDK 4.0" -import { Provider } from 'ai'; -``` - - - The model registry is not available any more. Please [register - providers](/docs/reference/ai-sdk-core/provider-registry#setup) instead. - - -#### Removed `experimental_​createModelRegistry` function - -The `experimental_createModelRegistry` function has been removed. -Please use the `experimental_createProviderRegistry` function instead. - -```ts filename="AI SDK 3.4" -import { experimental_createModelRegistry } from 'ai'; -``` - -```ts filename="AI SDK 4.0" -import { experimental_createProviderRegistry } from 'ai'; -``` - - - The model registry is not available any more. Please [register - providers](/docs/reference/ai-sdk-core/provider-registry#setup) instead. - - -### Removed `rawResponse` from results - - - There is no codemod available for this change. Please review and update your - code manually. - - -The `rawResponse` property has been removed from the `generateText`, `streamText`, `generateObject`, and `streamObject` results. -You can use the `response` property instead. - -```ts filename="AI SDK 3.4" -const { text, rawResponse } = await generateText({ - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const { text, response } = await generateText({ - // ... -}); -``` - -### Removed `init` option from `pipeDataStreamToResponse` and `toDataStreamResponse` - - - There is no codemod available for this change. Please review and update your - code manually. - - -The `init` option has been removed from the `pipeDataStreamToResponse` and `toDataStreamResponse` functions. -You can set the values from `init` directly into the `options` object. - -```ts filename="AI SDK 3.4" -const result = await streamText({ - // ... -}); - -result.toUIMessageStreamResponse(response, { - init: { - headers: { - 'X-Custom-Header': 'value', - }, - }, - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const result = streamText({ - // ... -}); - -result.toUIMessageStreamResponse(response, { - headers: { - 'X-Custom-Header': 'value', - }, - // ... -}); -``` - -### Removed `responseMessages` from `generateText` and `streamText` - - - There is no codemod available for this change. Please review and update your - code manually. - - -The `responseMessages` property has been removed from the `generateText` and `streamText` results. -This includes the `onFinish` callback. -Please use the `response.messages` property instead. - -```ts filename="AI SDK 3.4" -const { text, responseMessages } = await generateText({ - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const { text, response } = await generateText({ - // ... -}); - -const responseMessages = response.messages; -``` - -### Removed `experimental_​continuationSteps` option - -The `experimental_continuationSteps` option has been removed from the `generateText` function. -Please use the `experimental_continueSteps` option instead. - -```ts filename="AI SDK 3.4" -const result = await generateText({ - experimental_continuationSteps: true, - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const result = await generateText({ - experimental_continueSteps: true, - // ... -}); -``` - -### Removed `LanguageModelResponseMetadataWithHeaders` type - -The `LanguageModelResponseMetadataWithHeaders` type has been removed. -Please use the `LanguageModelResponseMetadata` type instead. - -```ts filename="AI SDK 3.4" -import { LanguageModelResponseMetadataWithHeaders } from 'ai'; -``` - -```ts filename="AI SDK 4.0" -import { LanguageModelResponseMetadata } from 'ai'; -``` - -#### Changed `streamText` warnings result to Promise - - - There is no codemod available for this change. Please review and update your - code manually. - - -The `warnings` property of the `StreamTextResult` type is now a Promise. - -```ts filename="AI SDK 3.4" -const result = await streamText({ - // ... -}); - -const warnings = result.warnings; -``` - -```ts filename="AI SDK 4.0" -const result = streamText({ - // ... -}); - -const warnings = await result.warnings; -``` - -#### Changed `streamObject` warnings result to Promise - - - There is no codemod available for this change. Please review and update your - code manually. - - -The `warnings` property of the `StreamObjectResult` type is now a Promise. - -```ts filename="AI SDK 3.4" -const result = await streamObject({ - // ... -}); - -const warnings = result.warnings; -``` - -```ts filename="AI SDK 4.0" -const result = streamObject({ - // ... -}); - -const warnings = await result.warnings; -``` - -#### Renamed `simulateReadableStream` `values` to `chunks` - - - There is no codemod available for this change. Please review and update your - code manually. - - -The `simulateReadableStream` function from `ai/test` has been renamed to `chunks`. - -```ts filename="AI SDK 3.4" -import { simulateReadableStream } from 'ai/test'; - -const stream = simulateReadableStream({ - values: [1, 2, 3], - chunkDelayInMs: 100, -}); -``` - -```ts filename="AI SDK 4.0" -import { simulateReadableStream } from 'ai/test'; - -const stream = simulateReadableStream({ - chunks: [1, 2, 3], - chunkDelayInMs: 100, -}); -``` - -## AI SDK RSC Changes - - - There are no codemods available for the changes in this section. Please review - and update your code manually. - - -### Removed `render` function - -The AI SDK RSC 3.0 `render` function has been removed. -Please use the `streamUI` function instead or [switch to AI SDK UI](/docs/ai-sdk-rsc/migrating-to-ui). - -```ts filename="AI SDK 3.0" -import { render } from '@ai-sdk/rsc'; -``` - -```ts filename="AI SDK 4.0" -import { streamUI } from '@ai-sdk/rsc'; -``` - -## AI SDK UI Changes - -### Removed Svelte, Vue, and SolidJS exports - - - This codemod only operates on `.ts` and `.tsx` files. If you have code in - files with other suffixes, please review and update your code manually. - - -The `ai` package no longer exports Svelte, Vue, and SolidJS UI integrations. -You need to install the `@ai-sdk/svelte`, `@ai-sdk/vue`, and `@ai-sdk/solid` packages directly. - -```ts filename="AI SDK 3.4" -import { useChat } from 'ai/svelte'; -``` - -```ts filename="AI SDK 4.0" -import { useChat } from '@ai-sdk/svelte'; -``` - -### Removed `experimental_StreamData` - -The `experimental_StreamData` export has been removed. -Please use the `StreamData` export instead. - -```ts filename="AI SDK 3.4" -import { experimental_StreamData } from 'ai'; -``` - -```ts filename="AI SDK 4.0" -import { StreamData } from 'ai'; -``` - -### `useChat` hook - - - There are no codemods available for the changes in this section. Please review - and update your code manually. - - -#### Removed `streamMode` setting - -The `streamMode` options has been removed from the `useChat` hook. -Please use the `streamProtocol` parameter instead. - -```ts filename="AI SDK 3.4" -const { messages } = useChat({ - streamMode: 'text', - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const { messages } = useChat({ - streamProtocol: 'text', - // ... -}); -``` - -#### Replaced roundtrip setting with `maxSteps` - -The following options have been removed from the `useChat` hook: - -- `experimental_maxAutomaticRoundtrips` -- `maxAutomaticRoundtrips` -- `maxToolRoundtrips` - -Please use the [`maxSteps`](/docs/ai-sdk-core/tools-and-tool-calling#multi-step-calls) option instead. -The value of `maxSteps` is equal to roundtrips + 1. - -```ts filename="AI SDK 3.4" -const { messages } = useChat({ - experimental_maxAutomaticRoundtrips: 2, - // or maxAutomaticRoundtrips - // or maxToolRoundtrips - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const { messages } = useChat({ - maxSteps: 3, // 2 roundtrips + 1 - // ... -}); -``` - -#### Removed `options` setting - -The `options` parameter in the `useChat` hook has been removed. -Please use the `headers` and `body` parameters instead. - -```ts filename="AI SDK 3.4" -const { messages } = useChat({ - options: { - headers: { - 'X-Custom-Header': 'value', - }, - }, - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const { messages } = useChat({ - headers: { - 'X-Custom-Header': 'value', - }, - // ... -}); -``` - -#### Removed `experimental_addToolResult` method - -The `experimental_addToolResult` method has been removed from the `useChat` hook. -Please use the `addToolResult` method instead. - -```ts filename="AI SDK 3.4" -const { messages, experimental_addToolResult } = useChat({ - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const { messages, addToolResult } = useChat({ - // ... -}); -``` - -#### Changed default value of `keepLastMessageOnError` to true and deprecated the option - -The `keepLastMessageOnError` option has been changed to default to `true`. -The option will be removed in the next major release. - -```ts filename="AI SDK 3.4" -const { messages } = useChat({ - keepLastMessageOnError: true, - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const { messages } = useChat({ - // ... -}); -``` - -### `useCompletion` hook - - - There are no codemods available for the changes in this section. Please review - and update your code manually. - - -#### Removed `streamMode` setting - -The `streamMode` options has been removed from the `useCompletion` hook. -Please use the `streamProtocol` parameter instead. - -```ts filename="AI SDK 3.4" -const { text } = useCompletion({ - streamMode: 'text', - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const { text } = useCompletion({ - streamProtocol: 'text', - // ... -}); -``` - -### `useAssistant` hook - -#### Removed `experimental_useAssistant` export - -The `experimental_useAssistant` export has been removed from the `useAssistant` hook. -Please use the `useAssistant` hook directly instead. - -```ts filename="AI SDK 3.4" -import { experimental_useAssistant } from '@ai-sdk/react'; -``` - -```ts filename="AI SDK 4.0" -import { useAssistant } from '@ai-sdk/react'; -``` - -#### Removed `threadId` and `messageId` from `AssistantResponse` - - - There is no codemod available for this change. Please review and update your - code manually. - - -The `threadId` and `messageId` parameters have been removed from the `AssistantResponse` function. -Please use the `threadId` and `messageId` variables from the outer scope instead. - -```ts filename="AI SDK 3.4" -return AssistantResponse( - { threadId: myThreadId, messageId: myMessageId }, - async ({ forwardStream, sendDataMessage, threadId, messageId }) => { - // use threadId and messageId here - }, -); -``` - -```ts filename="AI SDK 4.0" -return AssistantResponse( - { threadId: myThreadId, messageId: myMessageId }, - async ({ forwardStream, sendDataMessage }) => { - // use myThreadId and myMessageId here - }, -); -``` - -#### Removed `experimental_​AssistantResponse` export - - - There is no codemod available for this change. Please review and update your - code manually. - - -The `experimental_AssistantResponse` export has been removed. -Please use the `AssistantResponse` function directly instead. - -```ts filename="AI SDK 3.4" -import { experimental_AssistantResponse } from 'ai'; -``` - -```ts filename="AI SDK 4.0" -import { AssistantResponse } from 'ai'; -``` - -### `experimental_useObject` hook - - - There are no codemods available for the changes in this section. Please review - and update your code manually. - - -The `setInput` helper has been removed from the `experimental_useObject` hook. -Please use the `submit` helper instead. - -```ts filename="AI SDK 3.4" -const { object, setInput } = useObject({ - // ... -}); -``` - -```ts filename="AI SDK 4.0" -const { object, submit } = useObject({ - // ... -}); -``` - -## AI SDK Errors - -### Removed `isXXXError` static methods - -The `isXXXError` static methods have been removed from AI SDK errors. -Please use the `isInstance` method of the corresponding error class instead. - -```ts filename="AI SDK 3.4" -import { APICallError } from 'ai'; - -APICallError.isAPICallError(error); -``` - -```ts filename="AI SDK 4.0" -import { APICallError } from 'ai'; - -APICallError.isInstance(error); -``` - -### Removed `toJSON` method - - - There is no codemod available for this change. Please review and update your - code manually. - - -The `toJSON` method has been removed from AI SDK errors. - -## AI SDK 2.x Legacy Changes - - - There are no codemods available for the changes in this section. Please review - and update your code manually. - - -### Removed 2.x legacy providers - -Legacy providers from AI SDK 2.x have been removed. Please use the new [AI SDK provider architecture](/docs/foundations/providers-and-models) instead. - -#### Removed 2.x legacy function and tool calling - -The legacy `function_call` and `tools` options have been removed from `useChat` and `Message`. -The `name` property from the `Message` type has been removed. -Please use the [AI SDK Core tool calling](/docs/ai-sdk-core/tools-and-tool-calling) instead. - -### Removed 2.x prompt helpers - -Prompt helpers for constructing message prompts are no longer needed with the AI SDK provider architecture and have been removed. - -### Removed 2.x `AIStream` - -The `AIStream` function and related exports have been removed. -Please use the [`streamText`](/docs/reference/ai-sdk-core/stream-text) function and its `toDataStream()` method instead. - -### Removed 2.x `StreamingTextResponse` - -The `StreamingTextResponse` function has been removed. -Please use the [`streamText`](/docs/reference/ai-sdk-core/stream-text) function and its `toDataStreamResponse()` method instead. - -### Removed 2.x `streamToResponse` - -The `streamToResponse` function has been removed. -Please use the [`streamText`](/docs/reference/ai-sdk-core/stream-text) function and its `pipeDataStreamToResponse()` method instead. - -### Removed 2.x RSC `Tokens` streaming - -The legacy `Tokens` RSC streaming from 2.x has been removed. -`Tokens` were implemented prior to AI SDK RSC and are no longer needed. - -## Codemod Table - -The following table lists codemod availability for the AI SDK 4.0 upgrade -process. Note the codemod `upgrade` command will run all of them for you. This -list is provided to give visibility into which migrations have some automation. -It can also be helpful to find the codemod names if you'd like to run a subset -of codemods. For more, see the [Codemods](#codemods) section. - -| Change | Codemod | -| --------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | -| **Provider Changes** | | -| Removed baseUrl option | `v4/replace-baseurl` | -| **Anthropic Provider** | | -| Removed Anthropic facade | `v4/remove-anthropic-facade` | -| Removed topK setting | _N/A_ | -| **Google Generative AI Provider** | | -| Removed Google facade | `v4/remove-google-facade` | -| Removed topK setting | _N/A_ | -| **Google Vertex Provider** | | -| Removed topK setting | _N/A_ | -| **Mistral Provider** | | -| Removed Mistral facade | `v4/remove-mistral-facade` | -| **OpenAI Provider** | | -| Removed OpenAI facade | `v4/remove-openai-facade` | -| **LangChain Adapter** | | -| Removed toAIStream | `v4/replace-langchain-toaistream` | -| **AI SDK Core Changes** | | -| streamText returns immediately | `v4/remove-await-streamtext` | -| streamObject returns immediately | `v4/remove-await-streamobject` | -| Remove roundtrips | `v4/replace-roundtrips-with-maxsteps` | -| Removed nanoid export | `v4/replace-nanoid` | -| Increased default size of generated IDs | _N/A_ | -| Removed ExperimentalMessage types | `v4/remove-experimental-message-types` | -| Removed ExperimentalTool type | `v4/remove-experimental-tool` | -| Removed experimental AI function exports | `v4/remove-experimental-ai-fn-exports` | -| Removed AI-stream related methods from streamText | `v4/remove-ai-stream-methods-from-stream-text-result` | -| Renamed "formatStreamPart" to "formatDataStreamPart" | `v4/rename-format-stream-part` | -| Renamed "parseStreamPart" to "parseDataStreamPart" | `v4/rename-parse-stream-part` | -| Renamed TokenUsage, CompletionTokenUsage and EmbeddingTokenUsage types | `v4/replace-token-usage-types` | -| Removed deprecated telemetry data | _N/A_ | -| **Provider Registry** | | -| → Removed experimental_Provider, experimental_ProviderRegistry, and experimental_ModelRegistry | `v4/remove-deprecated-provider-registry-exports` | -| → Removed experimental_createModelRegistry function | _N/A_ | -| Removed rawResponse from results | _N/A_ | -| Removed init option from pipeDataStreamToResponse and toDataStreamResponse | _N/A_ | -| Removed responseMessages from generateText and streamText | _N/A_ | -| Removed experimental_continuationSteps option | `v4/replace-continuation-steps` | -| Removed LanguageModelResponseMetadataWithHeaders type | `v4/remove-metadata-with-headers` | -| Changed streamText warnings result to Promise | _N/A_ | -| Changed streamObject warnings result to Promise | _N/A_ | -| Renamed simulateReadableStream values to chunks | _N/A_ | -| **AI SDK RSC Changes** | | -| Removed render function | _N/A_ | -| **AI SDK UI Changes** | | -| Removed Svelte, Vue, and SolidJS exports | `v4/rewrite-framework-imports` | -| Removed experimental_StreamData | `v4/remove-experimental-streamdata` | -| **useChat hook** | | -| Removed streamMode setting | _N/A_ | -| Replaced roundtrip setting with maxSteps | `v4/replace-roundtrips-with-maxsteps` | -| Removed options setting | _N/A_ | -| Removed experimental_addToolResult method | _N/A_ | -| Changed default value of keepLastMessageOnError to true and deprecated the option | _N/A_ | -| **useCompletion hook** | | -| Removed streamMode setting | _N/A_ | -| **useAssistant hook** | | -| Removed experimental_useAssistant export | `v4/remove-experimental-useassistant` | -| Removed threadId and messageId from AssistantResponse | _N/A_ | -| Removed experimental_AssistantResponse export | _N/A_ | -| **experimental_useObject hook** | | -| Removed setInput helper | _N/A_ | -| **AI SDK Errors** | | -| Removed isXXXError static methods | `v4/remove-isxxxerror` | -| Removed toJSON method | _N/A_ | -| **AI SDK 2.x Legacy Changes** | | -| Removed 2.x legacy providers | _N/A_ | -| Removed 2.x legacy function and tool calling | _N/A_ | -| Removed 2.x prompt helpers | _N/A_ | -| Removed 2.x AIStream | _N/A_ | -| Removed 2.x StreamingTextResponse | _N/A_ | -| Removed 2.x streamToResponse | _N/A_ | -| Removed 2.x RSC Tokens streaming | _N/A_ | diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/36-migration-guide-3-4.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/36-migration-guide-3-4.mdx deleted file mode 100644 index b08f9d171..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/36-migration-guide-3-4.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Migrate AI SDK 3.3 to 3.4 -description: Learn how to upgrade AI SDK 3.3 to 3.4. ---- - -# Migrate AI SDK 3.3 to 3.4 - - - Check out the [AI SDK 3.4 release blog - post](https://vercel.com/blog/ai-sdk-3-4) for more information about the - release. - - -No breaking changes in this release. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/37-migration-guide-3-3.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/37-migration-guide-3-3.mdx deleted file mode 100644 index 72a22d0e6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/37-migration-guide-3-3.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Migrate AI SDK 3.2 to 3.3 -description: Learn how to upgrade AI SDK 3.2 to 3.3. ---- - -# Migrate AI SDK 3.2 to 3.3 - - - Check out the [AI SDK 3.3 release blog - post](https://vercel.com/blog/vercel-ai-sdk-3-3) for more information about - the release. - - -No breaking changes in this release. - -The following changelog encompasses all changes made in the 3.2.x series, -introducing significant improvements and new features across the AI SDK and its associated libraries: - -## New Features - -### Open Telemetry Support - -- Added experimental [OpenTelemetry support](/docs/ai-sdk-core/telemetry#telemetry) for all [AI SDK Core functions](/docs/ai-sdk-core/overview#ai-sdk-core-functions), enabling better observability and tracing capabilities. - -### AI SDK UI Improvements - -- Introduced the experimental **`useObject`** hook (for React) that can be used in conjunction with **`streamObject`** on the backend to enable seamless streaming of structured data. -- Enhanced **`useChat`** with experimental support for attachments and streaming tool calls, providing more versatile chat functionalities. -- Patched **`useChat`** to prevent empty submissions, improving the quality of user interactions by ensuring that only intended inputs are processed. -- Fix **`useChat`**'s **`reload`** function, now correctly sending data, body, and headers. -- Implemented **`setThreadId`** helper for **`useAssistant`**, simplifying thread management. -- Documented the stream data protocol for **`useChat`** and **`useCompletion`**, allowing developers to use these functions with any backend. The stream data protocol also enables the use of custom frontends with **`streamText`**. -- Added support for custom fetch functions and request body customization, offering greater control over API interactions. -- Added **`onFinish`** to **`useChat`** hook for access to token usage and finish reason. - -### Core Enhancements - -- Implemented support for sending custom request headers, enabling more tailored API requests. -- Added raw JSON schema support alongside existing Zod support, providing more options for schema and data validation. -- Introduced usage information for **`embed`** and **`embedMany`** functions, offering insights into token usage. -- Added support for additional settings including **`stopSequences`** and **`topK`**, allowing for finer control over text generation. -- Provided access to information for all steps on **`generateText`**, providing access to intermediate tool calls and results. - -### New Providers - -- [AWS Bedrock provider](/providers/ai-sdk-providers/amazon-bedrock). - -### Provider Improvements - -- Enhanced existing providers including Anthropic, Google, Azure, and OpenAI with various improvements and bug fixes. -- Upgraded the LangChain adapter with StreamEvent v2 support and introduced the **`toDataStreamResponse`** function, enabling conversion of LangChain output streams to data stream responses. -- Added legacy function calling support to the OpenAI provider. -- Updated Mistral AI provider with fixes and improvements for tool calling support. - -### UI Framework Support Expansion - -- SolidJS: Updated **`useChat`** and **`useCompletion`** to achieve feature parity with React implementations. -- Vue.js: Introduced **`useAssistant`** hook. -- Vue.js / Nuxt: [Updated examples](https://github.com/vercel/ai/tree/main/examples/nuxt-openai) to showcase latest features and best practices. -- Svelte: Added tool calling support to **`useChat`.** - -## Fixes and Improvements - -- Resolved various issues across different components of the SDK, including race conditions, error handling, and state management. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/38-migration-guide-3-2.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/38-migration-guide-3-2.mdx deleted file mode 100644 index d0c1cac44..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/38-migration-guide-3-2.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Migrate AI SDK 3.1 to 3.2 -description: Learn how to upgrade AI SDK 3.1 to 3.2. ---- - -# Migrate AI SDK 3.1 to 3.2 - - - Check out the [AI SDK 3.2 release blog - post](https://vercel.com/blog/introducing-vercel-ai-sdk-3-2) for more - information about the release. - - -This guide will help you upgrade to AI SDK 3.2: - -- Experimental `StreamingReactResponse` functionality has been removed -- Several features have been deprecated -- UI framework integrations have moved to their own Node modules - -## Upgrading - -### AI SDK - -To update to AI SDK version 3.2, run the following command using your preferred package manager: - - - -## Removed Functionality - -The experimental `StreamingReactResponse` has been removed. You can use [AI SDK RSC](/docs/ai-sdk-rsc/overview) to build streaming UIs. - -## Deprecated Functionality - -The `nanoid` export has been deprecated. Please use [`generateId`](/docs/reference/ai-sdk-core/generate-id) instead. - -## UI Package Separation - -AI SDK UI supports several frameworks: [React](https://react.dev/), [Svelte](https://svelte.dev/), [Vue.js](https://vuejs.org/), and [SolidJS](https://www.solidjs.com/). - -The integrations (other than React and RSC) have moved to separate Node modules. You need to update the import and require statements as follows: - -- Change `ai/svelte` to `@ai-sdk/svelte` -- Change `ai/vue` to `@ai-sdk/vue` -- Change `ai/solid` to `@ai-sdk/solid` - -The old exports are still available but will be removed in a future release. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/39-migration-guide-3-1.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/39-migration-guide-3-1.mdx deleted file mode 100644 index 91f5eb965..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/39-migration-guide-3-1.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- -title: Migrate AI SDK 3.0 to 3.1 -description: Learn how to upgrade AI SDK 3.0 to 3.1. ---- - -# Migrate AI SDK 3.0 to 3.1 - - - Check out the [AI SDK 3.1 release blog - post](https://vercel.com/blog/vercel-ai-sdk-3-1-modelfusion-joins-the-team) - for more information about the release. - - -This guide will help you: - -- Upgrade to AI SDK 3.1 -- Migrate from Legacy Providers to AI SDK Core -- Migrate from [`render`](/docs/reference/ai-sdk-rsc/render) to [`streamUI`](/docs/reference/ai-sdk-rsc/stream-ui) - -Upgrading to AI SDK 3.1 does not require using the newly released AI SDK Core API or [`streamUI`](/docs/reference/ai-sdk-rsc/stream-ui) function. - -## Upgrading - -### AI SDK - -To update to AI SDK version 3.1, run the following command using your preferred package manager: - - - -## Next Steps - -The release of AI SDK 3.1 introduces several new features that improve the way you build AI applications with the SDK: - -- AI SDK Core, a brand new unified API for interacting with large language models (LLMs). -- [`streamUI`](/docs/reference/ai-sdk-rsc/stream-ui), a new abstraction, built upon AI SDK Core functions that simplifies building streaming UIs. - -## Migrating from Legacy Providers to AI SDK Core - -Prior to AI SDK Core, you had to use a model provider's SDK to query their models. - -In the following Route Handler, you use the OpenAI SDK to query their model. You then pipe that response into the `OpenAIStream` function which returns a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) that you can pass to the client using a new `StreamingTextResponse`. - -```tsx -import OpenAI from 'openai'; -import { OpenAIStream, StreamingTextResponse } from 'ai'; - -const openai = new OpenAI({ - apiKey: process.env.OPENAI_API_KEY!, -}); - -export async function POST(req: Request) { - const { messages } = await req.json(); - - const response = await openai.chat.completions.create({ - model: 'gpt-4.1', - stream: true, - messages, - }); - - const stream = OpenAIStream(response); - - return new StreamingTextResponse(stream); -} -``` - -With AI SDK Core you have a unified API for any provider that implements the [AI SDK Language Model Specification](/providers/community-providers/custom-providers). - -Let’s take a look at the example above, but refactored to utilize the AI SDK Core API alongside the AI SDK OpenAI provider. In this example, you import the LLM function you want to use from the `ai` package, import the OpenAI provider from `@ai-sdk/openai`, and then you call the model and return the response using the `toDataStreamResponse()` helper function. - -```tsx -import { streamText } from 'ai'; -import { openai } from '@ai-sdk/openai'; -__PROVIDER_IMPORT__; - -export async function POST(req: Request) { - const { messages } = await req.json(); - - const result = await streamText({ - model: __MODEL__, - messages, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -## Migrating from `render` to `streamUI` - -The AI SDK RSC API was launched as part of version 3.0. This API introduced the [`render`](/docs/reference/ai-sdk-rsc/render) function, a helper function to create streamable UIs with OpenAI models. With the new AI SDK Core API, it became possible to make streamable UIs possible with any compatible provider. - -The following example Server Action uses the `render` function using the model provider directly from OpenAI. You first create an OpenAI provider instance with the OpenAI SDK. Then, you pass it to the provider key of the render function alongside a tool that returns a React Server Component, defined in the `render` key of the tool. - -```tsx -import { render } from '@ai-sdk/rsc'; -import OpenAI from 'openai'; -import { z } from 'zod'; -import { Spinner, Weather } from '@/components'; -import { getWeather } from '@/utils'; - -const openai = new OpenAI(); - -async function submitMessage(userInput = 'What is the weather in SF?') { - 'use server'; - - return render({ - provider: openai, - model: 'gpt-4.1', - messages: [ - { role: 'system', content: 'You are a helpful assistant' }, - { role: 'user', content: userInput }, - ], - text: ({ content }) =>

{content}

, - tools: { - get_city_weather: { - description: 'Get the current weather for a city', - parameters: z - .object({ - city: z.string().describe('the city'), - }) - .required(), - render: async function* ({ city }) { - yield ; - const weather = await getWeather(city); - return ; - }, - }, - }, - }); -} -``` - -With the new [`streamUI`](/docs/reference/ai-sdk-rsc/stream-ui) function, you can now use any compatible AI SDK provider. In this example, you import the AI SDK OpenAI provider. Then, you pass it to the [`model`](/docs/reference/ai-sdk-rsc/stream-ui#model) key of the new [`streamUI`](/docs/reference/ai-sdk-rsc/stream-ui) function. Finally, you declare a tool and return a React Server Component, defined in the [`generate`](/docs/reference/ai-sdk-rsc/stream-ui#tools-generate) key of the tool. - -```tsx -import { streamUI } from '@ai-sdk/rsc'; -import { openai } from '@ai-sdk/openai'; -import { z } from 'zod'; -import { Spinner, Weather } from '@/components'; -import { getWeather } from '@/utils'; - -async function submitMessage(userInput = 'What is the weather in SF?') { - 'use server'; - - const result = await streamUI({ - model: __MODEL__, - system: 'You are a helpful assistant', - messages: [{ role: 'user', content: userInput }], - text: ({ content }) =>

{content}

, - tools: { - get_city_weather: { - description: 'Get the current weather for a city', - parameters: z - .object({ - city: z.string().describe('Name of the city'), - }) - .required(), - generate: async function* ({ city }) { - yield ; - const weather = await getWeather(city); - return ; - }, - }, - }, - }); - - return result.value; -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/index.mdx deleted file mode 100644 index e076b4434..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/08-migration-guides/index.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Migration Guides -description: Learn how to upgrade between Vercel AI versions. -collapsed: true ---- - -# Migration Guides - -- [ Migrate AI SDK 5.x to 6.0 ](/docs/migration-guides/migration-guide-6-0) -- [ Migrate AI SDK 4.x to 5.0 ](/docs/migration-guides/migration-guide-5-0) -- [ Migrate your data to AI SDK 5.0 ](/docs/migration-guides/migration-guide-5-0-data) -- [ Migrate AI SDK 4.1 to 4.2 ](/docs/migration-guides/migration-guide-4-2) -- [ Migrate AI SDK 4.0 to 4.1 ](/docs/migration-guides/migration-guide-4-1) -- [ Migrate AI SDK 3.4 to 4.0 ](/docs/migration-guides/migration-guide-4-0) -- [ Migrate AI SDK 3.3 to 3.4 ](/docs/migration-guides/migration-guide-3-4) -- [ Migrate AI SDK 3.2 to 3.3 ](/docs/migration-guides/migration-guide-3-3) -- [ Migrate AI SDK 3.1 to 3.2 ](/docs/migration-guides/migration-guide-3-2) -- [ Migrate AI SDK 3.0 to 3.1 ](/docs/migration-guides/migration-guide-3-1) - -## Versioning - -- [ Versioning ](/docs/migration-guides/versioning) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/01-azure-stream-slow.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/01-azure-stream-slow.mdx deleted file mode 100644 index 09cfdee89..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/01-azure-stream-slow.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Azure OpenAI Slow to Stream -description: Learn to troubleshoot Azure OpenAI slow to stream issues. ---- - -# Azure OpenAI Slow To Stream - -## Issue - -When using OpenAI hosted on Azure, streaming is slow and in big chunks. - -## Cause - -This is a Microsoft Azure issue. Some users have reported the following solutions: - -- **Update Content Filtering Settings**: - Inside [Azure AI Studio](https://ai.azure.com/), within "Shared resources" > "Content filters", create a new - content filter and set the "Streaming mode (Preview)" under "Output filter" from "Default" - to "Asynchronous Filter". - -## Solution - -You can use the [`smoothStream` transformation](/docs/ai-sdk-core/generating-text#smoothing-streams) to stream each word individually. - -```tsx highlight="6" -import { smoothStream, streamText } from 'ai'; - -const result = streamText({ - model, - prompt, - experimental_transform: smoothStream(), -}); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/03-server-actions-in-client-components.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/03-server-actions-in-client-components.mdx deleted file mode 100644 index f2fb7b78c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/03-server-actions-in-client-components.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Server Actions in Client Components -description: Troubleshooting errors related to server actions in client components. ---- - -# Server Actions in Client Components - -You may use Server Actions in client components, but sometimes you may encounter the following issues. - -## Issue - -It is not allowed to define inline `"use server"` annotated Server Actions in Client Components. - -## Solution - -To use Server Actions in a Client Component, you can either: - -- Export them from a separate file with `"use server"` at the top. -- Pass them down through props from a Server Component. -- Implement a combination of [`createAI`](/docs/reference/ai-sdk-rsc/create-ai) and [`useActions`](/docs/reference/ai-sdk-rsc/use-actions) hooks to access them. - -Learn more about [Server Actions and Mutations](https://nextjs.org/docs/app/api-reference/functions/server-actions#with-client-components). - -```ts file='actions.ts' -'use server'; - -import { generateText } from 'ai'; -__PROVIDER_IMPORT__; - -export async function getAnswer(question: string) { - 'use server'; - - const { text } = await generateText({ - model: __MODEL__, - prompt: question, - }); - - return { answer: text }; -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/04-strange-stream-output.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/04-strange-stream-output.mdx deleted file mode 100644 index 10f39df08..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/04-strange-stream-output.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: useChat/useCompletion stream output contains 0:... instead of text -description: How to fix strange stream output in the UI ---- - -# useChat/useCompletion stream output contains 0:... instead of text - -## Issue - -I am using custom client code to process a server response that is sent using `StreamingTextResponse`. I am using version `3.0.20` or newer of the AI SDK. When I send a query, the UI streams text such as `0: "Je"`, `0: " suis"`, `0: "des"...` instead of the text that I’m looking for. - -## Background - -The AI SDK has switched to the stream data protocol in version `3.0.20`. It sends different stream parts to support data, tool calls, etc. What you see is the raw stream data protocol response. - -## Solution - -You have several options: - -1. Use the AI Core [`streamText`](/docs/reference/ai-sdk-core/stream-text) function to send a raw text stream: - - ```tsx - export async function POST(req: Request) { - const { prompt } = await req.json(); - - const result = streamText({ - model: openai.completion('gpt-3.5-turbo-instruct'), - maxOutputTokens: 2000, - prompt, - }); - - return result.toTextStreamResponse(); - } - ``` - -2. Pin the AI SDK version to `3.0.19` . This will keep the raw text stream. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/05-streamable-ui-errors.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/05-streamable-ui-errors.mdx deleted file mode 100644 index e11bc16e2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/05-streamable-ui-errors.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Streamable UI Errors -description: Troubleshooting errors related to streamable UI. ---- - -# Streamable UI Component Error - -## Issue - -- Variable Not Found -- Cannot find `div` -- `Component` refers to a value, but is being used as a type - -## Solution - -If you encounter these errors when working with streamable UIs within server actions, it is likely because the file ends in `.ts` instead of `.tsx`. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/05-tool-invocation-missing-result.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/05-tool-invocation-missing-result.mdx deleted file mode 100644 index 4ecc36ee7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/05-tool-invocation-missing-result.mdx +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Tool Invocation Missing Result Error -description: How to fix the "ToolInvocation must have a result" error when using tools without execute functions ---- - -# Tool Invocation Missing Result Error - -## Issue - -When using `generateText()` or `streamText()`, you may encounter the error "ToolInvocation must have a result" when a tool without an `execute` function is called. - -## Cause - -The error occurs when you define a tool without an `execute` function and don't provide the result through other means (like `useChat`'s `onToolCall` or `addToolOutput` functions). - -Each time a tool is invoked, the model expects to receive a result before continuing the conversation. Without a result, the model cannot determine if the tool call succeeded or failed and the conversation state becomes invalid. - -## Solution - -You have two options for handling tool results: - -1. Server-side execution using tools with an `execute` function: - -```tsx -const tools = { - weather: tool({ - description: 'Get the weather in a location', - parameters: z.object({ - location: z - .string() - .describe('The city and state, e.g. "San Francisco, CA"'), - }), - execute: async ({ location }) => { - // Fetch and return weather data - return { temperature: 72, conditions: 'sunny', location }; - }, - }), -}; -``` - -2. Client-side execution with `useChat` (omitting the `execute` function), you must provide results using `addToolOutput`: - -```tsx -import { useChat } from '@ai-sdk/react'; -import { - DefaultChatTransport, - lastAssistantMessageIsCompleteWithToolCalls, -} from 'ai'; - -const { messages, sendMessage, addToolOutput } = useChat({ - // Automatically submit when all tool results are available - sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls, - - // Handle tool calls in onToolCall - onToolCall: async ({ toolCall }) => { - if (toolCall.toolName === 'getLocation') { - try { - const result = await getLocationData(); - - // Important: Don't await inside onToolCall to avoid deadlocks - addToolOutput({ - tool: 'getLocation', - toolCallId: toolCall.toolCallId, - output: result, - }); - } catch (err) { - // Important: Don't await inside onToolCall to avoid deadlocks - addToolOutput({ - tool: 'getLocation', - toolCallId: toolCall.toolCallId, - state: 'output-error', - errorText: 'Failed to get location', - }); - } - } - }, -}); -``` - -```tsx -// For interactive UI elements: -const { messages, sendMessage, addToolOutput } = useChat({ - transport: new DefaultChatTransport({ api: '/api/chat' }), - sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls, -}); - -// Inside your JSX, when rendering tool calls: -; -``` - - - Whether handling tools on the server or client, each tool call must have a - corresponding result before the conversation can continue. - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/06-streaming-not-working-when-deployed.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/06-streaming-not-working-when-deployed.mdx deleted file mode 100644 index 6df54ee80..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/06-streaming-not-working-when-deployed.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Streaming Not Working When Deployed -description: Troubleshooting streaming issues in deployed apps. ---- - -# Streaming Not Working When Deployed - -## Issue - -Streaming with the AI SDK works in my local development environment. -However, when deploying, streaming does not work in the deployed app. -Instead of streaming, only the full response is returned after a while. - -## Cause - -The causes of this issue are varied and depend on the deployment environment. - -## Solution - -You can try the following: - -- add `'Transfer-Encoding': 'chunked'` and/or `Connection: 'keep-alive'` headers - - ```tsx - return result.toUIMessageStreamResponse({ - headers: { - 'Transfer-Encoding': 'chunked', - Connection: 'keep-alive', - }, - }); - ``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/06-streaming-not-working-when-proxied.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/06-streaming-not-working-when-proxied.mdx deleted file mode 100644 index ffab2b947..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/06-streaming-not-working-when-proxied.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Streaming Not Working When Proxied -description: Troubleshooting streaming issues in proxied apps. ---- - -# Streaming Not Working When Proxied - -## Issue - -Streaming with the AI SDK doesn't work in local development environment, or deployed in some proxy environments. -Instead of streaming, only the full response is returned after a while. - -## Cause - -The causes of this issue are caused by the proxy middleware. - -If the middleware is configured to compress the response, it will cause the streaming to fail. - -## Solution - -You can try the following, the solution only affects the streaming API: - -- add `'Content-Encoding': 'none'` headers - - ```tsx - return result.toUIMessageStreamResponse({ - headers: { - 'Content-Encoding': 'none', - }, - }); - ``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/06-timeout-on-vercel.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/06-timeout-on-vercel.mdx deleted file mode 100644 index f0abd6d89..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/06-timeout-on-vercel.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Getting Timeouts When Deploying on Vercel -description: Learn how to fix timeouts and cut off responses when deploying to Vercel. ---- - -# Getting Timeouts When Deploying on Vercel - -## Issue - -Streaming with the AI SDK works in my local development environment. -However, when I'm deploying to Vercel, longer responses get chopped off in the UI and I'm seeing timeouts in the Vercel logs or I'm seeing the error: `Uncaught (in promise) Error: Connection closed`. - -## Solution - -With Vercel's [Fluid Compute](https://vercel.com/docs/fluid-compute), the default function duration is now **5 minutes (300 seconds)** across all plans. This should be sufficient for most streaming applications. - -If you need to extend the timeout for longer-running processes, you can increase the `maxDuration` setting: - -### Next.js (App Router) - -Add the following to your route file or the page you are calling your Server Action from: - -```tsx -export const maxDuration = 600; -``` - - - Setting `maxDuration` above 300 seconds requires a Pro or Enterprise plan. - - -### Other Frameworks - -For other frameworks, you can set timeouts in your `vercel.json` file: - -```json -{ - "functions": { - "api/chat/route.ts": { - "maxDuration": 600 - } - } -} -``` - - - Setting `maxDuration` above 300 seconds requires a Pro or Enterprise plan. - - -### Maximum Duration Limits - -The maximum duration you can set depends on your Vercel plan: - -- **Hobby**: Up to 300 seconds (5 minutes) -- **Pro**: Up to 800 seconds (~13 minutes) -- **Enterprise**: Up to 800 seconds (~13 minutes) - -## Learn more - -- [Fluid Compute Default Settings](https://vercel.com/docs/fluid-compute#default-settings-by-plan) -- [Configuring Maximum Duration for Vercel Functions](https://vercel.com/docs/functions/configuring-functions/duration) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/07-unclosed-streams.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/07-unclosed-streams.mdx deleted file mode 100644 index d85635f96..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/07-unclosed-streams.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Unclosed Streams -description: Troubleshooting errors related to unclosed streams. ---- - -# Unclosed Streams - -Sometimes streams are not closed properly, which can lead to unexpected behavior. The following are some common issues that can occur when streams are not closed properly. - -## Issue - -The streamable UI has been slow to update. - -## Solution - -This happens when you create a streamable UI using [`createStreamableUI`](/docs/reference/ai-sdk-rsc/create-streamable-ui) and fail to close the stream. -In order to fix this, you must ensure you close the stream by calling the [`.done()`](/docs/reference/ai-sdk-rsc/create-streamable-ui#done) method. -This will ensure the stream is closed. - -```tsx file='app/actions.tsx' -import { createStreamableUI } from '@ai-sdk/rsc'; - -const submitMessage = async () => { - 'use server'; - - const stream = createStreamableUI('1'); - - stream.update('2'); - stream.append('3'); - stream.done('4'); // [!code ++] - - return stream.value; -}; -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/08-use-chat-failed-to-parse-stream.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/08-use-chat-failed-to-parse-stream.mdx deleted file mode 100644 index 512bd7a62..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/08-use-chat-failed-to-parse-stream.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: useChat Failed to Parse Stream -description: Troubleshooting errors related to the Use Chat Failed to Parse Stream error. ---- - -# `useChat` "Failed to Parse Stream String" Error - -## Issue - -I am using [`useChat`](/docs/reference/ai-sdk-ui/use-chat) or [`useCompletion`](/docs/reference/ai-sdk-ui/use-completion), and I am getting a `"Failed to parse stream string. Invalid code"` error. I am using version `3.0.20` or newer of the AI SDK. - -## Background - -The AI SDK has switched to the stream data protocol in version `3.0.20`. -[`useChat`](/docs/reference/ai-sdk-ui/use-chat) and [`useCompletion`](/docs/reference/ai-sdk-ui/use-completion) expect stream parts that support data, tool calls, etc. -What you see is a failure to parse the stream. -This can be caused by using an older version of the AI SDK in the backend, by providing a text stream using a custom provider, or by using a raw LangChain stream result. - -## Solution - -You can switch [`useChat`](/docs/reference/ai-sdk-ui/use-chat) and [`useCompletion`](/docs/reference/ai-sdk-ui/use-completion) to raw text stream processing with the [`streamProtocol`](/docs/reference/ai-sdk-ui/use-completion#stream-protocol) parameter. -Set it to `text` as follows: - -```tsx -const { messages, append } = useChat({ streamProtocol: 'text' }); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/09-client-stream-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/09-client-stream-error.mdx deleted file mode 100644 index 95751a6e0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/09-client-stream-error.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Server Action Plain Objects Error -description: Troubleshooting errors related to using AI SDK Core functions with Server Actions. ---- - -# "Only plain objects can be passed from client components" Server Action Error - -## Issue - -I am using [`streamText`](/docs/reference/ai-sdk-core/stream-text) with Server Actions, and I am getting a `"only plain objects and a few built ins can be passed from client components"` error. - -## Background - -This error occurs when you're trying to return a non-serializable object from a Server Action to a Client Component. The streamText function likely returns an object with methods or complex structures that can't be directly serialized and passed to the client. - -## Solution - -To fix this issue, you need to ensure that you're only returning serializable data from your Server Action. Here's how you can modify your approach: - -1. Instead of returning the entire result object from streamText, extract only the necessary serializable data. -2. Use the [`createStreamableValue`](/docs/reference/ai-sdk-rsc/create-streamable-value) function to create a streamable value that can be safely passed to the client. - -Here's an example that demonstrates how to implement this solution: [Streaming Text Generation](/examples/next-app/basics/streaming-text-generation). - -This approach ensures that only serializable data (the text) is passed to the client, avoiding the "only plain objects" error. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/10-use-chat-tools-no-response.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/10-use-chat-tools-no-response.mdx deleted file mode 100644 index 2716258ee..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/10-use-chat-tools-no-response.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: useChat No Response -description: Troubleshooting errors related to the Use Chat Failed to Parse Stream error. ---- - -# `useChat` No Response - -## Issue - -I am using [`useChat`](/docs/reference/ai-sdk-ui/use-chat). -When I log the incoming messages on the server, I can see the tool call and the tool result, but the model does not respond with anything. - -## Solution - -To resolve this issue, convert the incoming messages to the `ModelMessage` format using the [`convertToModelMessages`](/docs/reference/ai-sdk-ui/convert-to-model-messages) function. - -```tsx highlight="9" -import { openai } from '@ai-sdk/openai'; -import { convertToModelMessages, streamText } from 'ai'; -__PROVIDER_IMPORT__; - -export async function POST(req: Request) { - const { messages } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - }); - - return result.toUIMessageStreamResponse(); -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/11-use-chat-custom-request-options.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/11-use-chat-custom-request-options.mdx deleted file mode 100644 index 77be0ff93..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/11-use-chat-custom-request-options.mdx +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Custom headers, body, and credentials not working with useChat -description: Troubleshooting errors related to custom request configuration in useChat hook ---- - -# Custom headers, body, and credentials not working with useChat - -## Issue - -When using the `useChat` hook, custom request options like headers, body fields, and credentials configured directly on the hook are not being sent with the request: - -```tsx -// These options are not sent with the request -const { messages, sendMessage } = useChat({ - headers: { - Authorization: 'Bearer token123', - }, - body: { - user_id: '123', - }, - credentials: 'include', -}); -``` - -## Background - -The `useChat` hook has changed its API for configuring request options. Direct options like `headers`, `body`, and `credentials` on the hook itself are no longer supported. Instead, you need to use the `transport` configuration with `DefaultChatTransport` or pass options at the request level. - -## Solution - -There are three ways to properly configure request options with `useChat`: - -### Option 1: Request-Level Configuration (Recommended for Dynamic Values) - -For dynamic values that change over time, the recommended approach is to pass options when calling `sendMessage`: - -```tsx -const { messages, sendMessage } = useChat(); - -// Send options with each message -sendMessage( - { text: input }, - { - headers: { - Authorization: `Bearer ${getAuthToken()}`, // Dynamic auth token - 'X-Request-ID': generateRequestId(), - }, - body: { - temperature: 0.7, - max_tokens: 100, - user_id: getCurrentUserId(), // Dynamic user ID - sessionId: getCurrentSessionId(), // Dynamic session - }, - }, -); -``` - -This approach ensures that the most up-to-date values are always sent with each request. - -### Option 2: Hook-Level Configuration with Static Values - -For static values that don't change during the component lifecycle, use the `DefaultChatTransport`: - -```tsx -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; - -const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - headers: { - 'X-API-Version': 'v1', // Static API version - 'X-App-ID': 'my-app', // Static app identifier - }, - body: { - model: 'gpt-5.1', // Default model - stream: true, // Static configuration - }, - credentials: 'include', // Static credentials policy - }), -}); -``` - -### Option 3: Hook-Level Configuration with Resolvable Functions - -If you need dynamic values at the hook level, you can use functions that return configuration values. However, request-level configuration is generally preferred for better reliability: - -```tsx -import { useChat } from '@ai-sdk/react'; -import { DefaultChatTransport } from 'ai'; - -const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - headers: () => ({ - Authorization: `Bearer ${getAuthToken()}`, - 'X-User-ID': getCurrentUserId(), - }), - body: () => ({ - sessionId: getCurrentSessionId(), - preferences: getUserPreferences(), - }), - credentials: () => (isAuthenticated() ? 'include' : 'same-origin'), - }), -}); -``` - - - For component state that changes over time, request-level configuration - (Option 1) is recommended. If using hook-level functions, consider using - `useRef` to store current values and reference `ref.current` in your - configuration function. - - -### Combining Hook and Request Level Options - -Request-level options take precedence over hook-level options: - -```tsx -// Hook-level default configuration -const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - headers: { - 'X-API-Version': 'v1', - }, - body: { - model: 'gpt-5.1', - }, - }), -}); - -// Override or add options per request -sendMessage( - { text: input }, - { - headers: { - 'X-API-Version': 'v2', // This overrides the hook-level header - 'X-Request-ID': '123', // This is added - }, - body: { - model: 'gpt-5-mini', // This overrides the hook-level body field - temperature: 0.5, // This is added - }, - }, -); -``` - -For more details on request configuration, see the [Request Configuration](/docs/ai-sdk-ui/chatbot#request-configuration) documentation. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/12-typescript-performance-zod.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/12-typescript-performance-zod.mdx deleted file mode 100644 index 6cbc3fc02..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/12-typescript-performance-zod.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: TypeScript performance issues with Zod and AI SDK 5 -description: Troubleshooting TypeScript server crashes and slow performance when using Zod with AI SDK 5 ---- - -# TypeScript performance issues with Zod and AI SDK 5 - -## Issue - -When using the AI SDK 5 with Zod, you may experience: - -- TypeScript server crashes or hangs -- Extremely slow type checking in files that import AI SDK functions -- Error messages like "Type instantiation is excessively deep and possibly infinite" -- IDE becoming unresponsive when working with AI SDK code - -## Background - -The AI SDK 5 has specific compatibility requirements with Zod versions. When importing Zod using the standard import path (`import { z } from 'zod'`), TypeScript's type inference can become excessively complex, leading to performance degradation or crashes. - -## Solution - -### Upgrade Zod to 4.1.8 or Later - -The primary solution is to upgrade to Zod version 4.1.8 or later, which includes a fix for this module resolution issue: - -```bash -pnpm add zod@^4.1.8 -``` - -This version resolves the underlying problem where different module resolution settings were causing TypeScript to load the same Zod declarations twice, leading to expensive structural comparisons. - -### Alternative: Update TypeScript Configuration - -If upgrading Zod isn't possible, you can update your `tsconfig.json` to use `moduleResolution: "nodenext"`: - -```json -{ - "compilerOptions": { - "moduleResolution": "nodenext" - // ... other options - } -} -``` - -This resolves the TypeScript performance issues while allowing you to continue using the standard Zod import. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/12-use-chat-an-error-occurred.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/12-use-chat-an-error-occurred.mdx deleted file mode 100644 index d814cbf60..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/12-use-chat-an-error-occurred.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: useChat "An error occurred" -description: Troubleshooting errors related to the "An error occurred" error in useChat. ---- - -# `useChat` "An error occurred" - -## Issue - -I am using [`useChat`](/docs/reference/ai-sdk-ui/use-chat) and I get the error "An error occurred". - -## Background - -Error messages from `streamText` are masked by default when using `toDataStreamResponse` for security reasons (secure-by-default). -This prevents leaking sensitive information to the client. - -## Solution - -To forward error details to the client or to log errors, use the `getErrorMessage` function when calling `toDataStreamResponse`. - -```tsx -export function errorHandler(error: unknown) { - if (error == null) { - return 'unknown error'; - } - - if (typeof error === 'string') { - return error; - } - - if (error instanceof Error) { - return error.message; - } - - return JSON.stringify(error); -} -``` - -```tsx -const result = streamText({ - // ... -}); - -return result.toUIMessageStreamResponse({ - getErrorMessage: errorHandler, -}); -``` - -In case you are using `createDataStreamResponse`, you can use the `onError` function when calling `toDataStreamResponse`: - -```tsx -const response = createDataStreamResponse({ - // ... - async execute(dataStream) { - // ... - }, - onError: errorHandler, -}); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/13-repeated-assistant-messages.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/13-repeated-assistant-messages.mdx deleted file mode 100644 index 65263fa03..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/13-repeated-assistant-messages.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Repeated assistant messages in useChat -description: Troubleshooting duplicate assistant messages when using useChat with streamText ---- - -# Repeated assistant messages in useChat - -## Issue - -When using `useChat` with `streamText` on the server, the assistant's messages appear duplicated in the UI - showing both the previous message and the new message, or showing the same message multiple times. This can occur when using tool calls or complex message flows. - -```tsx -// Server-side code that may experience assistant message duplication on the client -export async function POST(req: Request) { - const { messages } = await req.json(); - - const result = streamText({ - model: 'openai/gpt-5-mini', - messages: await convertToModelMessages(messages), - tools: { - weather: { - description: 'Get the weather for a location', - parameters: z.object({ - location: z.string(), - }), - execute: async ({ location }) => { - return { temperature: 72, condition: 'sunny' }; - }, - }, - }, - }); - - return result.toUIMessageStreamResponse(); -} -``` - -## Background - -The duplication occurs because `toUIMessageStreamResponse` generates new message IDs for each new message. - -## Solution - -Pass the original messages array to `toUIMessageStreamResponse` using the `originalMessages` option. By passing `originalMessages`, the method can reuse existing message IDs instead of generating new ones, ensuring the client properly updates existing messages rather than creating duplicates. - -```tsx -export async function POST(req: Request) { - const { messages } = await req.json(); - - const result = streamText({ - model: 'openai/gpt-5-mini', - messages: await convertToModelMessages(messages), - tools: { - weather: { - description: 'Get the weather for a location', - parameters: z.object({ - location: z.string(), - }), - execute: async ({ location }) => { - return { temperature: 72, condition: 'sunny' }; - }, - }, - }, - }); - - return result.toUIMessageStreamResponse({ - originalMessages: messages, // Pass the original messages here - generateMessageId: generateId, - onFinish: ({ messages }) => { - saveChat({ id, messages }); - }, - }); -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/14-stream-abort-handling.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/14-stream-abort-handling.mdx deleted file mode 100644 index f0fef1bed..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/14-stream-abort-handling.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: onFinish not called when stream is aborted -description: Troubleshooting onFinish callback not executing when streams are aborted with toUIMessageStreamResponse ---- - -# onFinish not called when stream is aborted - -## Issue - -When using `toUIMessageStreamResponse` with an `onFinish` callback, the callback may not execute when the stream is aborted. This happens because the abort handler immediately terminates the response, preventing the `onFinish` callback from being triggered. - -```tsx -// Server-side code where onFinish isn't called on abort -export async function POST(req: Request) { - const { messages } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - abortSignal: req.signal, - }); - - return result.toUIMessageStreamResponse({ - onFinish: async ({ isAborted }) => { - // This isn't called when the stream is aborted! - if (isAborted) { - console.log('Stream was aborted'); - // Handle abort-specific cleanup - } else { - console.log('Stream completed normally'); - // Handle normal completion - } - }, - }); -} -``` - -## Background - -When a stream is aborted, the response is immediately terminated. Without proper handling, the `onFinish` callback has no chance to execute, preventing important cleanup operations like saving partial results or logging abort events. - -## Solution - -Add `consumeStream` to the `toUIMessageStreamResponse` configuration. This ensures that abort events are properly captured and forwarded to the `onFinish` callback, allowing it to execute even when the stream is aborted. - -```tsx -// other imports... -import { consumeStream } from 'ai'; - -export async function POST(req: Request) { - const { messages } = await req.json(); - - const result = streamText({ - model: __MODEL__, - messages: await convertToModelMessages(messages), - abortSignal: req.signal, - }); - - return result.toUIMessageStreamResponse({ - onFinish: async ({ isAborted }) => { - // Now this WILL be called even when aborted! - if (isAborted) { - console.log('Stream was aborted'); - // Handle abort-specific cleanup - } else { - console.log('Stream completed normally'); - // Handle normal completion - } - }, - consumeSseStream: consumeStream, // This enables onFinish to be called on abort - }); -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/14-tool-calling-with-structured-outputs.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/14-tool-calling-with-structured-outputs.mdx deleted file mode 100644 index cafa3b445..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/14-tool-calling-with-structured-outputs.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Tool calling with structured outputs -description: Troubleshooting tool calling when combined with structured output generation ---- - -# Tool calling with structured outputs - -## Issue - -You may want to combine tool calling with structured output generation. - -## Background - -To use tool calling with structured outputs, use `generateText` or `streamText` with the `output` option. - -**Important**: When using `output` with tool calling, the structured output generation counts as an additional step in the execution flow. - -## Solution - -When using `output` with tool calling, adjust your `stopWhen` condition to account for the additional step required for structured output generation: - -```tsx -const result = await generateText({ - model: __MODEL__, - output: Output.object({ - schema: z.object({ - summary: z.string(), - sentiment: z.enum(['positive', 'neutral', 'negative']), - }), - }), - tools: { - analyze: tool({ - description: 'Analyze data', - inputSchema: z.object({ - data: z.string(), - }), - execute: async ({ data }) => { - return { result: 'analyzed' }; - }), - }, - }, - // Add at least 1 to your intended step count to account for structured output - stopWhen: stepCountIs(3), // Now accounts for: tool call + tool result + structured output - prompt: 'Analyze the data and provide a summary', -}); -``` - -For more information about using structured outputs with `generateText` and `streamText` see [Generating Structured Data](/docs/ai-sdk-core/generating-structured-data#structured-outputs-with-generatetext-and-streamtext). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/15-abort-breaks-resumable-streams.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/15-abort-breaks-resumable-streams.mdx deleted file mode 100644 index 111574b44..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/15-abort-breaks-resumable-streams.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Abort breaks resumable streams -description: Troubleshooting stream resumption failures when using abort functionality ---- - -# Abort breaks resumable streams - -## Issue - -When using `useChat` with `resume: true` for stream resumption, the abort functionality breaks. Closing a tab, refreshing the page, or calling the `stop()` function will trigger an abort signal that interferes with the resumption mechanism, preventing streams from being properly resumed. - -```tsx -// This configuration will cause conflicts -const { messages, stop } = useChat({ - id: chatId, - resume: true, // Stream resumption enabled -}); - -// Closing the tab will trigger abort and stop resumption -``` - -## Background - -When a page is closed or refreshed, the browser automatically sends an abort signal, which breaks the resumption flow. - -## Current limitations - -We're aware of this incompatibility and are exploring solutions. **In the meantime, please choose either stream resumption or abort functionality based on your application's requirements**, but not both. - -### Option 1: Use stream resumption without abort - -If you need to support long-running generations that persist across page reloads: - -```tsx -const { messages, sendMessage } = useChat({ - id: chatId, - resume: true, -}); -``` - -### Option 2: Use abort without stream resumption - -If you need to allow users to stop streams manually: - -```tsx -const { messages, sendMessage, stop } = useChat({ - id: chatId, - resume: false, // Disable stream resumption (default behavior) -}); -``` - -## Related - -- [Chatbot Resume Streams](/docs/ai-sdk-ui/chatbot-resume-streams) -- [Stopping Streams](/docs/advanced/stopping-streams) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/15-stream-text-not-working.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/15-stream-text-not-working.mdx deleted file mode 100644 index 485b48319..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/15-stream-text-not-working.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: streamText fails silently -description: Troubleshooting errors related to the streamText function not working. ---- - -# `streamText` is not working - -## Issue - -I am using [`streamText`](/docs/reference/ai-sdk-core/stream-text) function, and it does not work. -It does not throw any errors and the stream is only containing error parts. - -## Background - -`streamText` immediately starts streaming to enable sending data without waiting for the model. -Errors become part of the stream and are not thrown to prevent e.g. servers from crashing. - -## Solution - -To log errors, you can provide an `onError` callback that is triggered when an error occurs. - -```tsx highlight="6-8" -import { streamText } from 'ai'; -__PROVIDER_IMPORT__; - -const result = streamText({ - model: __MODEL__, - prompt: 'Invent a new holiday and describe its traditions.', - onError({ error }) { - console.error(error); // your error logging logic here - }, -}); -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/16-streaming-status-delay.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/16-streaming-status-delay.mdx deleted file mode 100644 index 297285278..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/16-streaming-status-delay.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Streaming Status Shows But No Text Appears -description: Why useChat shows "streaming" status without any visible content ---- - -# Streaming Status Shows But No Text Appears - -## Issue - -When using `useChat`, the status changes to "streaming" immediately, but no text appears for several seconds. - -## Background - -The status changes to "streaming" as soon as the connection to the server is established and streaming begins - this includes metadata streaming, not just the LLM's generated tokens. - -## Solution - -Create a custom loading state that checks if the last assistant message actually contains content: - -```tsx -'use client'; - -import { useChat } from '@ai-sdk/react'; - -export default function Page() { - const { messages, status } = useChat(); - - const lastMessage = messages.at(-1); - - const showLoader = - status === 'streaming' && - lastMessage?.role === 'assistant' && - lastMessage?.parts?.length === 0; - - return ( - <> - {messages.map(message => ( -
- {message.role === 'user' ? 'User: ' : 'AI: '} - {message.parts.map((part, index) => - part.type === 'text' ? {part.text} : null, - )} -
- ))} - - {showLoader &&
Loading...
} - - ); -} -``` - -You can also check for specific part types if you're waiting for something specific: - -```tsx -const showLoader = - status === 'streaming' && - lastMessage?.role === 'assistant' && - !lastMessage?.parts?.some(part => part.type === 'text'); -``` - -## Related Issues - -- [GitHub Issue #7586](https://github.com/vercel/ai/issues/7586) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/17-use-chat-stale-body-data.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/17-use-chat-stale-body-data.mdx deleted file mode 100644 index 27648237a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/17-use-chat-stale-body-data.mdx +++ /dev/null @@ -1,141 +0,0 @@ ---- -title: Stale body values with useChat -description: Troubleshooting stale values when passing information via the body parameter of useChat ---- - -# Stale body values with useChat - -## Issue - -When using `useChat` and passing dynamic information via the `body` parameter at the hook level, the data remains stale and only reflects the value from the initial component render. This occurs because the body configuration is captured once when the hook is initialized and doesn't update with subsequent component re-renders. - -```tsx -// Problematic code - body data will be stale -export default function Chat() { - const [temperature, setTemperature] = useState(0.7); - const [userId, setUserId] = useState('user123'); - - // This body configuration is captured once and won't update - const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - body: { - temperature, // Always the initial value (0.7) - userId, // Always the initial value ('user123') - }, - }), - }); - - // Even if temperature or userId change, the body in requests will still use initial values - return ( -
- setTemperature(parseFloat(e.target.value))} - /> - {/* Chat UI */} -
- ); -} -``` - -## Background - -The hook-level body configuration is evaluated once during the initial render and doesn't re-evaluate when component state changes. - -## Solution - -Pass dynamic variables via the second argument of the `sendMessage` function instead of at the hook level. Request-level options are evaluated on each call and take precedence over hook-level options. - -```tsx -export default function Chat() { - const [temperature, setTemperature] = useState(0.7); - const [userId, setUserId] = useState('user123'); - const [input, setInput] = useState(''); - - const { messages, sendMessage } = useChat({ - // Static configuration only - transport: new DefaultChatTransport({ - api: '/api/chat', - }), - }); - - return ( -
- setTemperature(parseFloat(e.target.value))} - /> - -
{ - event.preventDefault(); - if (input.trim()) { - // Pass dynamic values as request-level options - sendMessage( - { text: input }, - { - body: { - temperature, // Current value at request time - userId, // Current value at request time - }, - }, - ); - setInput(''); - } - }} - > - setInput(e.target.value)} /> -
-
- ); -} -``` - -### Alternative: Dynamic Hook-Level Configuration - -If you need hook-level configuration that responds to changes, you can use functions that return configuration values. However, for component state, you'll need to use `useRef` to access current values: - -```tsx -export default function Chat() { - const temperatureRef = useRef(0.7); - - const { messages, sendMessage } = useChat({ - transport: new DefaultChatTransport({ - api: '/api/chat', - body: () => ({ - temperature: temperatureRef.current, // Access via ref.current - sessionId: getCurrentSessionId(), // Function calls work directly - }), - }), - }); - - // ... -} -``` - -**Recommendation:** Request-level configuration is simpler and more reliable for component state. Use it whenever you need to pass dynamic values that change during the component lifecycle. - -### Server-side handling - -On your server side, retrieve the custom fields by destructuring the request body: - -```tsx -// app/api/chat/route.ts -export async function POST(req: Request) { - const { messages, temperature, userId } = await req.json(); - - const result = streamText({ - model: 'openai/gpt-5-mini', - messages: await convertToModelMessages(messages), - temperature, // Use the dynamic temperature from the request - // ... other configuration - }); - - return result.toUIMessageStreamResponse(); -} -``` - -For more information, see [chatbot request configuration documentation](/docs/ai-sdk-ui/chatbot#request-configuration). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/18-ontoolcall-type-narrowing.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/18-ontoolcall-type-narrowing.mdx deleted file mode 100644 index 776e8669e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/18-ontoolcall-type-narrowing.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: Type Error with onToolCall -description: How to handle TypeScript type errors when using the onToolCall callback ---- - -# Type Error with onToolCall - -When using the `onToolCall` callback with TypeScript, you may encounter type errors when trying to pass tool properties directly to `addToolOutput`. - -## Problem - -TypeScript cannot automatically narrow the type of `toolCall.toolName` when you have both static and dynamic tools, leading to type errors: - -```tsx -// ❌ This causes a TypeScript error -const { messages, sendMessage, addToolOutput } = useChat({ - async onToolCall({ toolCall }) { - addToolOutput({ - tool: toolCall.toolName, // Type 'string' is not assignable to type '"yourTool" | "yourOtherTool"' - toolCallId: toolCall.toolCallId, - output: someOutput, - }); - }, -}); -``` - -The error occurs because: - -- Static tools have specific literal types for their names (e.g., `"getWeatherInformation"`) -- Dynamic tools have `toolName` as a generic `string` -- TypeScript can't guarantee that `toolCall.toolName` matches your specific tool names - -## Solution - -Check if the tool is dynamic first to enable proper type narrowing: - -```tsx -// ✅ Correct approach with type narrowing -const { messages, sendMessage, addToolOutput } = useChat({ - async onToolCall({ toolCall }) { - // Check if it's a dynamic tool first - if (toolCall.dynamic) { - return; - } - - // Now TypeScript knows this is a static tool with the correct type - addToolOutput({ - tool: toolCall.toolName, // No type error! - toolCallId: toolCall.toolCallId, - output: someOutput, - }); - }, -}); -``` - - - If you're still using the deprecated `addToolResult` method, this solution - applies the same way. Consider migrating to `addToolOutput` for consistency - with the latest API. - - -## Related - -- [Chatbot Tool Usage](/docs/ai-sdk-ui/chatbot-tool-usage) -- [Dynamic Tools](/docs/reference/ai-sdk-core/dynamic-tool) -- [useChat Reference](/docs/reference/ai-sdk-ui/use-chat) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/19-unsupported-model-version.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/19-unsupported-model-version.mdx deleted file mode 100644 index 2d59e77b9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/19-unsupported-model-version.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Unsupported model version error -description: Troubleshooting the AI_UnsupportedModelVersionError when migrating to AI SDK 5 ---- - -# Unsupported model version error - -## Issue - -When migrating to AI SDK 5, you might encounter an error stating that your model uses an unsupported version: - -``` -AI_UnsupportedModelVersionError: Unsupported model version v1 for provider "ollama.chat" and model "gamma3:4b". -AI SDK 5 only supports models that implement specification version "v2". -``` - -This error occurs because the version of the provider package you're using implements the older (v1) model specification. - -## Background - -AI SDK 5 requires all provider packages to implement specification version "v2". When you upgrade to AI SDK 5 but don't update your provider packages to compatible versions, they continue using the older "v1" specification, causing this error. - -## Solution - -### Update provider packages to AI SDK 5 compatible versions - -Update all your `@ai-sdk/*` provider packages to compatible version `2.0.0` or later. These versions implement the v2 specification required by AI SDK 5. - -```bash -pnpm install ai@latest @ai-sdk/openai@latest @ai-sdk/anthropic@latest -``` - -For AI SDK 5 compatibility, you need: - -- `ai` package: `5.0.0` or later -- `@ai-sdk/*` packages: `2.0.0` or later (for example, `@ai-sdk/openai`, `@ai-sdk/anthropic`, `@ai-sdk/google`) -- `@ai-sdk/provider` package: `2.0.0` or later -- `zod` package: `4.1.8` or later - -### Check provider compatibility - -If you're using a third-party or custom provider, verify that it has been updated to support AI SDK 5. Not all providers may have v2-compatible versions available yet. - -To check if a provider supports AI SDK 5: - -1. Check the provider's package.json for `@ai-sdk/provider` peer dependency version `2.0.0` or later -2. Review the provider's changelog or migration guide -3. Check the provider's repository for AI SDK 5 support - -For more information on migrating to AI SDK 5, see the [AI SDK 5.0 migration guide](/docs/migration-guides/migration-guide-5-0). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/20-no-object-generated-content-filter.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/20-no-object-generated-content-filter.mdx deleted file mode 100644 index 63f0c4b7b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/20-no-object-generated-content-filter.mdx +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: Object generation failed with OpenAI -description: Troubleshooting NoObjectGeneratedError with finish-reason content-filter caused by incompatible Zod schema types when using OpenAI structured outputs ---- - -# Object generation failed with OpenAI - -## Issue - -When using structured output generation with OpenAI, you may encounter a `NoObjectGeneratedError` with the finish reason `content-filter`. This error occurs when your Zod schema contains incompatible types that OpenAI's structured output feature cannot process. - -```typescript -// Problematic code - incompatible schema types -import { generateText, Output } from 'ai'; -import { openai } from '@ai-sdk/openai'; -import { z } from 'zod'; - -const result = await generateText({ - model: openai('gpt-4o-2024-08-06'), - output: Output.object({ - schema: z.object({ - name: z.string().nullish(), // ❌ .nullish() is not supported - email: z.string().optional(), // ❌ .optional() is not supported - age: z.number().nullable(), // ✅ .nullable() is supported - }), - }), - prompt: 'Generate a user profile', -}); - -// Error: NoObjectGeneratedError: No object generated. -// Finish reason: content-filter -``` - -## Background - -OpenAI's structured output generation uses JSON Schema under the hood and has specific requirements for schema compatibility. The Zod methods `.nullish()` and `.optional()` generate JSON Schema patterns that are incompatible with OpenAI's implementation, causing the model to reject the schema and return a content-filter finish reason. - -## Solution - -Replace `.nullish()` and `.optional()` with `.nullable()` in your Zod schemas when using structured output generation with OpenAI models. - -```typescript -import { generateText, Output } from 'ai'; -import { openai } from '@ai-sdk/openai'; -import { z } from 'zod'; - -// Correct approach - use .nullable() -const result = await generateText({ - model: openai('gpt-4o-2024-08-06'), - output: Output.object({ - schema: z.object({ - name: z.string().nullable(), // ✅ Use .nullable() instead of .nullish() - email: z.string().nullable(), // ✅ Use .nullable() instead of .optional() - age: z.number().nullable(), - }), - }), - prompt: 'Generate a user profile', -}); - -console.log(result.output); -// { name: "John Doe", email: "john@example.com", age: 30 } -// or { name: null, email: null, age: 25 } -``` - -### Schema Type Comparison - -| Zod Type | Compatible | JSON Schema Behavior | -| ------------- | ---------- | ------------------------------------------------------ | -| `.nullable()` | ✅ Yes | Allows `null` or the specified type | -| `.optional()` | ❌ No | Field can be omitted (not supported) | -| `.nullish()` | ❌ No | Allows `null`, `undefined`, or omitted (not supported) | - -## Related Information - -- For more details on structured output generation, see [Generating Structured Data](/docs/ai-sdk-core/generating-structured-data) -- For OpenAI-specific structured output configuration, see [OpenAI Provider - Structured Outputs](/providers/ai-sdk-providers/openai#structured-outputs) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/21-missing-tool-results-error.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/21-missing-tool-results-error.mdx deleted file mode 100644 index c40d7c15f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/21-missing-tool-results-error.mdx +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: Missing Tool Results Error -description: How to fix the "Tool results are missing for tool calls" error when using the AI SDK. ---- - -# Missing Tool Results Error - -## Issue - -You encounter the error `AI_MissingToolResultsError` with a message like: - -> Tool results are missing for tool calls: ... - -## Cause - -This error occurs when you attempt to send a new message to the Large Language Model (LLM) while there are pending tool calls from a previous turn that have not yet been resolved. - -The AI SDK core logic validates that all `tool-call` parts in the conversation history are resolved before proceeding. "Resolved" typically means: - -1. The tool has been executed and a `tool-result` has been added to the history. -2. Or, the tool call has triggered a `tool-approval-response` (if using tool approvals). - -If a tool call is found without a corresponding result or approval response, this error is thrown to prevent sending an invalid conversation history to the model. - -## Solution - -Ensure that every tool call in your conversation history is properly handled. - -### 1. Provide Tool Results - -For standard tool calls, ensure that you provide the output of the tool execution. - -```typescript -const messages = [ - { role: 'user', content: 'What is the weather in NY?' }, - { - role: 'assistant', - content: [ - { - type: 'tool-call', - toolCallId: 'call_123', - toolName: 'getWeather', - args: { location: 'New York' }, - }, - ], - }, - // You MUST include this tool message with the result: - { - role: 'tool', - content: [ - { - type: 'tool-result', - toolCallId: 'call_123', - toolName: 'getWeather', - result: 'Sunny, 25°C', - }, - ], - }, - // Now you can add a new user message - { role: 'user', content: 'And in London?' }, -]; -``` - -### 2. Handle Tool Approvals - -If you are using the tool approval workflow, ensure that you include the `tool-approval-response`. - -```typescript -const messages = [ - // ... assistant requests tool execution (needs approval) - { - role: 'tool', - content: [ - { - type: 'tool-approval-response', - approvalId: 'approval_123', - approved: true, // or false - }, - ], - }, -]; -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/30-model-is-not-assignable-to-type.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/30-model-is-not-assignable-to-type.mdx deleted file mode 100644 index bd1b40a39..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/30-model-is-not-assignable-to-type.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Model is not assignable to type "LanguageModelV1" -description: Troubleshooting errors related to incompatible models. ---- - -# Model is not assignable to type "LanguageModelV1" - -## Issue - -I have updated the AI SDK and now I get the following error: `Type 'SomeModel' is not assignable to type 'LanguageModelV1'.` - -Similar errors can occur with `EmbeddingModelV3` as well. - -## Background - -Sometimes new features are being added to the model specification. -This can cause incompatibilities with older provider versions. - -## Solution - -Update your provider packages and the AI SDK to the latest version. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/40-typescript-cannot-find-namespace-jsx.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/40-typescript-cannot-find-namespace-jsx.mdx deleted file mode 100644 index 5484ae55b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/40-typescript-cannot-find-namespace-jsx.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: TypeScript error "Cannot find namespace 'JSX'" -description: Troubleshooting errors related to TypeScript and JSX. ---- - -# TypeScript error "Cannot find namespace 'JSX'" - -## Issue - -I am using the AI SDK in a project without React, e.g. an Hono server, and I get the following error: -`error TS2503: Cannot find namespace 'JSX'.` - -## Background - -The AI SDK has a dependency on `@types/react` which defines the `JSX` namespace. -It will be removed in the next major version of the AI SDK. - -## Solution - -You can install the `@types/react` package as a dependency to fix the error. - -```bash -npm install @types/react -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/50-react-maximum-update-depth-exceeded.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/50-react-maximum-update-depth-exceeded.mdx deleted file mode 100644 index 7f86a0dc1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/50-react-maximum-update-depth-exceeded.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: React error "Maximum update depth exceeded" -description: Troubleshooting errors related to the "Maximum update depth exceeded" error. ---- - -# React error "Maximum update depth exceeded" - -## Issue - -I am using the AI SDK in a React project with the `useChat` or `useCompletion` hooks -and I get the following error when AI responses stream in: `Maximum update depth exceeded`. - -## Background - -By default, the UI is re-rendered on every chunk that arrives. -This can overload the rendering, especially on slower devices or when complex components -need updating (e.g. Markdown). Throttling can mitigate this. - -## Solution - -Use the `experimental_throttle` option to throttle the UI updates: - -### `useChat` - -```tsx filename="page.tsx" highlight="2-3" -const { messages, ... } = useChat({ - // Throttle the messages and data updates to 50ms: - experimental_throttle: 50 -}) -``` - -### `useCompletion` - -```tsx filename="page.tsx" highlight="2-3" -const { completion, ... } = useCompletion({ - // Throttle the completion and data updates to 50ms: - experimental_throttle: 50 -}) -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/60-jest-cannot-find-module-ai-rsc.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/60-jest-cannot-find-module-ai-rsc.mdx deleted file mode 100644 index b5ca97c59..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/60-jest-cannot-find-module-ai-rsc.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: "Jest: cannot find module '@ai-sdk/rsc'" -description: "Troubleshooting AI SDK errors related to the Jest: cannot find module '@ai-sdk/rsc' error" ---- - -# Jest: cannot find module '@ai-sdk/rsc' - -## Issue - -I am using AI SDK RSC and am writing tests for my RSC components with Jest. - -I am getting the following error: `Cannot find module '@ai-sdk/rsc'`. - -## Solution - -Configure the module resolution via `jest config update` in `moduleNameMapper`: - -```json filename="jest.config.js" -"moduleNameMapper": { - "^@ai-sdk/rsc$": "/node_modules/@ai-sdk/rsc/dist" -} -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/70-high-memory-usage-with-images.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/70-high-memory-usage-with-images.mdx deleted file mode 100644 index a861d92bf..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/70-high-memory-usage-with-images.mdx +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: High memory usage when processing many images -description: Troubleshooting high memory usage when using generateText or streamText with many images ---- - -# High memory usage when processing many images - -## Issue - -When using `generateText` or `streamText` with many images (e.g., in a loop or batch processing), you may notice: - -- Memory usage grows continuously and doesn't decrease -- Application eventually runs out of memory -- Memory is not reclaimed even after garbage collection - -This is especially noticeable when using `experimental_download` to process images from URLs, or when sending base64-encoded images in prompts. - -## Background - -By default, the AI SDK includes the full request and response bodies in the step results. When processing images, the request body contains the base64-encoded image data, which can be very large (a single image can be 1MB+ when base64 encoded). If you process many images and keep references to the results, this data accumulates in memory. - -For example, processing 100 images of 500KB each would include ~50MB+ of request body data in memory. - -## Solution - -Use the `experimental_include` option to disable inclusion of request and/or response bodies: - -```ts -import { generateText } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const result = await generateText({ - model: openai('gpt-4o'), - messages: [ - { - role: 'user', - content: [ - { type: 'text', text: 'Describe this image' }, - { type: 'image', image: imageUrl }, - ], - }, - ], - // Disable inclusion of request body to reduce memory usage - experimental_include: { - requestBody: false, - responseBody: false, - }, -}); -``` - -### Options - -The `experimental_include` option accepts: - -- `requestBody`: Set to `false` to exclude the request body from step results. This is where base64-encoded images are stored. Default: `true`. Available in both `generateText` and `streamText`. -- `responseBody`: Set to `false` to exclude the response body from step results. Default: `true`. Only available in `generateText`. - -### When to use - -- **Batch processing images**: When processing many images in a loop -- **Long-running agents**: When an agent may process many images over its lifetime -- **Memory-constrained environments**: When running in environments with limited memory - -### Trade-offs - -When you disable body inclusion: - -- You won't have access to `result.request.body` or `result.response.body` -- Debugging may be harder since you can't inspect the raw request/response -- If you need the bodies for logging or debugging, consider extracting the data you need before the next iteration - -## Example: Processing multiple images - -```ts -import { generateText } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const imageUrls = [ - /* array of image URLs */ -]; -const results = []; - -for (const imageUrl of imageUrls) { - const result = await generateText({ - model: openai('gpt-4o'), - messages: [ - { - role: 'user', - content: [ - { type: 'text', text: 'Describe this image' }, - { type: 'image', image: imageUrl }, - ], - }, - ], - experimental_include: { - requestBody: false, - }, - }); - - // Only store the text result, not the full result object - results.push(result.text); -} -``` - -## Learn more - -- [`generateText` API Reference](/docs/reference/ai-sdk-core/generate-text) -- [`streamText` API Reference](/docs/reference/ai-sdk-core/stream-text) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/index.mdx b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/index.mdx deleted file mode 100644 index 35a0f5783..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/docs/09-troubleshooting/index.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Troubleshooting -description: Troubleshooting information for common issues encountered with the AI SDK. -collapsed: true ---- - -# Troubleshooting - -This section is designed to help you quickly identify and resolve common issues encountered with the AI SDK, ensuring a smoother and more efficient development experience. - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/internal.d.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/internal.d.ts deleted file mode 100644 index be034cd88..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/internal.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/internal'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/package.json deleted file mode 100644 index ef2d8fcd4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/package.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "name": "ai", - "version": "6.0.138", - "description": "AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.", - "license": "Apache-2.0", - "sideEffects": false, - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", - "source": "./src/index.ts", - "files": [ - "dist/**/*", - "docs/**/*", - "src", - "!src/**/*.test.ts", - "!src/**/*.test-d.ts", - "!src/**/__snapshots__", - "CHANGELOG.md", - "internal.d.ts", - "README.md", - "test.d.ts" - ], - "directories": { - "doc": "./docs" - }, - "exports": { - "./package.json": "./package.json", - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" - }, - "./internal": { - "types": "./dist/internal/index.d.ts", - "import": "./dist/internal/index.mjs", - "module": "./dist/internal/index.mjs", - "require": "./dist/internal/index.js" - }, - "./test": { - "types": "./dist/test/index.d.ts", - "import": "./dist/test/index.mjs", - "module": "./dist/test/index.mjs", - "require": "./dist/test/index.js" - } - }, - "dependencies": { - "@opentelemetry/api": "1.9.0", - "@ai-sdk/gateway": "3.0.80", - "@ai-sdk/provider": "3.0.8", - "@ai-sdk/provider-utils": "4.0.21" - }, - "devDependencies": { - "@edge-runtime/vm": "^5.0.0", - "@types/json-schema": "7.0.15", - "@types/node": "20.17.24", - "esbuild": "^0.24.2", - "tsup": "^7.2.0", - "tsx": "^4.19.2", - "typescript": "5.8.3", - "zod": "3.25.76", - "@ai-sdk/test-server": "1.0.3", - "@vercel/ai-tsconfig": "0.0.0" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public" - }, - "homepage": "https://ai-sdk.dev/docs", - "repository": { - "type": "git", - "url": "git+https://github.com/vercel/ai.git" - }, - "bugs": { - "url": "https://github.com/vercel/ai/issues" - }, - "keywords": [ - "ai", - "vercel", - "sdk", - "llm", - "mcp", - "tool-calling", - "tools", - "structured-output", - "agent", - "agentic", - "generative", - "genai", - "chatbot", - "prompt", - "inference", - "language-model", - "streaming", - "openai", - "anthropic", - "claude", - "gemini", - "xai", - "grok" - ], - "scripts": { - "build": "pnpm clean && tsup --tsconfig tsconfig.build.json", - "build:watch": "pnpm clean && tsup --watch --tsconfig tsconfig.build.json", - "clean": "del-cli dist docs *.tsbuildinfo", - "type-check": "tsc --build", - "test": "pnpm test:node && pnpm test:edge", - "test:update": "pnpm test:node -u", - "test:watch": "vitest --config vitest.node.config.js", - "test:edge": "vitest --config vitest.edge.config.js --run", - "test:node": "vitest --config vitest.node.config.js --run", - "check-bundle-size": "tsx scripts/check-bundle-size.ts" - } -} \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/agent.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/agent.ts deleted file mode 100644 index 4ef41470e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/agent.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { ModelMessage } from '@ai-sdk/provider-utils'; -import { GenerateTextResult } from '../generate-text/generate-text-result'; -import { Output } from '../generate-text/output'; -import { StreamTextTransform } from '../generate-text/stream-text'; -import { StreamTextResult } from '../generate-text/stream-text-result'; -import { ToolSet } from '../generate-text/tool-set'; -import { TimeoutConfiguration } from '../prompt/call-settings'; -import type { ToolLoopAgentOnStepFinishCallback } from './tool-loop-agent-settings'; - -/** - * Parameters for calling an agent. - */ -export type AgentCallParameters = ([ - CALL_OPTIONS, -] extends [never] - ? { options?: never } - : { options: CALL_OPTIONS }) & - ( - | { - /** - * A prompt. It can be either a text prompt or a list of messages. - * - * You can either use `prompt` or `messages` but not both. - */ - prompt: string | Array; - - /** - * A list of messages. - * - * You can either use `prompt` or `messages` but not both. - */ - messages?: never; - } - | { - /** - * A list of messages. - * - * You can either use `prompt` or `messages` but not both. - */ - messages: Array; - - /** - * A prompt. It can be either a text prompt or a list of messages. - * - * You can either use `prompt` or `messages` but not both. - */ - prompt?: never; - } - ) & { - /** - * Abort signal. - */ - abortSignal?: AbortSignal; - - /** - * Timeout in milliseconds. Can be specified as a number or as an object with `totalMs`. - */ - timeout?: TimeoutConfiguration; - - /** - * Callback that is called when each step (LLM call) is finished, including intermediate steps. - */ - onStepFinish?: ToolLoopAgentOnStepFinishCallback; - }; - -/** - * Parameters for streaming an output from an agent. - */ -export type AgentStreamParameters< - CALL_OPTIONS, - TOOLS extends ToolSet, -> = AgentCallParameters & { - /** - * Optional stream transformations. - * They are applied in the order they are provided. - * The stream transformations must maintain the stream structure for streamText to work correctly. - */ - experimental_transform?: - | StreamTextTransform - | Array>; -}; - -/** - * An Agent receives a prompt (text or messages) and generates or streams an output - * that consists of steps, tool calls, data parts, etc. - * - * You can implement your own Agent by implementing the `Agent` interface, - * or use the `ToolLoopAgent` class. - */ -export interface Agent< - CALL_OPTIONS = never, - TOOLS extends ToolSet = {}, - OUTPUT extends Output = never, -> { - /** - * The specification version of the agent interface. This will enable - * us to evolve the agent interface and retain backwards compatibility. - */ - readonly version: 'agent-v1'; - - /** - * The id of the agent. - */ - readonly id: string | undefined; - - /** - * The tools that the agent can use. - */ - readonly tools: TOOLS; - - /** - * Generates an output from the agent (non-streaming). - */ - generate( - options: AgentCallParameters, - ): PromiseLike>; - - /** - * Streams an output from the agent (streaming). - */ - stream( - options: AgentStreamParameters, - ): PromiseLike>; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/create-agent-ui-stream-response.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/create-agent-ui-stream-response.ts deleted file mode 100644 index a8f664689..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/create-agent-ui-stream-response.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { StreamTextTransform, UIMessageStreamOptions } from '../generate-text'; -import { Output } from '../generate-text/output'; -import { ToolSet } from '../generate-text/tool-set'; -import { TimeoutConfiguration } from '../prompt/call-settings'; -import { createUIMessageStreamResponse } from '../ui-message-stream'; -import { UIMessageStreamResponseInit } from '../ui-message-stream/ui-message-stream-response-init'; -import { InferUITools, UIMessage } from '../ui/ui-messages'; -import { Agent } from './agent'; -import { createAgentUIStream } from './create-agent-ui-stream'; -import type { ToolLoopAgentOnStepFinishCallback } from './tool-loop-agent-settings'; - -/** - * Runs the agent and returns a response object with a UI message stream. - * - * @param agent - The agent to run. - * @param uiMessages - The input UI messages. - * @param abortSignal - Abort signal. Optional. - * @param timeout - Timeout in milliseconds. Optional. - * @param options - The options for the agent. Optional. - * @param experimental_transform - Stream transformations. Optional. - * @param onStepFinish - Callback that is called when each step is finished. Optional. - * @param headers - Additional headers for the response. Optional. - * @param status - The status code for the response. Optional. - * @param statusText - The status text for the response. Optional. - * @param consumeSseStream - Whether to consume the SSE stream. Optional. - * - * @returns The response object. - */ -export async function createAgentUIStreamResponse< - CALL_OPTIONS = never, - TOOLS extends ToolSet = {}, - OUTPUT extends Output = never, - MESSAGE_METADATA = unknown, ->({ - headers, - status, - statusText, - consumeSseStream, - ...options -}: { - agent: Agent; - uiMessages: unknown[]; - abortSignal?: AbortSignal; - timeout?: TimeoutConfiguration; - options?: CALL_OPTIONS; - experimental_transform?: - | StreamTextTransform - | Array>; - onStepFinish?: ToolLoopAgentOnStepFinishCallback; -} & UIMessageStreamResponseInit & - UIMessageStreamOptions< - UIMessage> - >): Promise { - return createUIMessageStreamResponse({ - headers, - status, - statusText, - consumeSseStream, - stream: await createAgentUIStream(options), - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/create-agent-ui-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/create-agent-ui-stream.ts deleted file mode 100644 index cc8da0282..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/create-agent-ui-stream.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { StreamTextTransform, UIMessageStreamOptions } from '../generate-text'; -import { Output } from '../generate-text/output'; -import { ToolSet } from '../generate-text/tool-set'; -import { TimeoutConfiguration } from '../prompt/call-settings'; -import { InferUIMessageChunk } from '../ui-message-stream'; -import { convertToModelMessages } from '../ui/convert-to-model-messages'; -import { InferUITools, UIMessage } from '../ui/ui-messages'; -import { validateUIMessages } from '../ui/validate-ui-messages'; -import { AsyncIterableStream } from '../util/async-iterable-stream'; -import { Agent } from './agent'; -import type { ToolLoopAgentOnStepFinishCallback } from './tool-loop-agent-settings'; - -/** - * Runs the agent and stream the output as a UI message stream. - * - * @param agent - The agent to run. - * @param uiMessages - The input UI messages. - * @param abortSignal - The abort signal. Optional. - * @param timeout - Timeout in milliseconds. Optional. - * @param options - The options for the agent. - * @param experimental_transform - The stream transformations. Optional. - * @param onStepFinish - Callback that is called when each step is finished. Optional. - * - * @returns The UI message stream. - */ -export async function createAgentUIStream< - CALL_OPTIONS = never, - TOOLS extends ToolSet = {}, - OUTPUT extends Output = never, - MESSAGE_METADATA = unknown, ->({ - agent, - uiMessages, - options, - abortSignal, - timeout, - experimental_transform, - onStepFinish, - ...uiMessageStreamOptions -}: { - agent: Agent; - uiMessages: unknown[]; - abortSignal?: AbortSignal; - timeout?: TimeoutConfiguration; - options?: CALL_OPTIONS; - experimental_transform?: - | StreamTextTransform - | Array>; - onStepFinish?: ToolLoopAgentOnStepFinishCallback; - // TODO `originalMessages` is part of this for bc, omit in v7 -} & UIMessageStreamOptions< - UIMessage> ->): Promise< - AsyncIterableStream< - InferUIMessageChunk>> - > -> { - const validatedMessages = await validateUIMessages< - UIMessage> - >({ - messages: uiMessages, - tools: agent.tools, - }); - - const modelMessages = await convertToModelMessages(validatedMessages, { - tools: agent.tools, - }); - - const result = await agent.stream({ - prompt: modelMessages, - options: options as CALL_OPTIONS, - abortSignal, - timeout, - experimental_transform, - onStepFinish, - }); - - return result.toUIMessageStream({ - ...uiMessageStreamOptions, - // TODO reading `originalMessages` is here for bc, always use `validatedMessages` in v7 - originalMessages: - uiMessageStreamOptions.originalMessages ?? validatedMessages, - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/index.ts deleted file mode 100644 index d2ab92830..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -export { - type Agent, - type AgentCallParameters, - type AgentStreamParameters, -} from './agent'; -export { - type ToolLoopAgentOnFinishCallback, - type ToolLoopAgentOnStepFinishCallback, - type ToolLoopAgentSettings, - - /** - * @deprecated Use `ToolLoopAgentSettings` instead. - */ - type ToolLoopAgentSettings as Experimental_AgentSettings, -} from './tool-loop-agent-settings'; -export { - ToolLoopAgent, - - /** - * @deprecated Use `ToolLoopAgent` instead. - */ - ToolLoopAgent as Experimental_Agent, -} from './tool-loop-agent'; -export { - /** - * @deprecated Use `InferAgentUIMessage` instead. - */ - type InferAgentUIMessage as Experimental_InferAgentUIMessage, - type InferAgentUIMessage, -} from './infer-agent-ui-message'; -export { createAgentUIStreamResponse } from './create-agent-ui-stream-response'; -export { createAgentUIStream } from './create-agent-ui-stream'; -export { pipeAgentUIStreamToResponse } from './pipe-agent-ui-stream-to-response'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/infer-agent-tools.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/infer-agent-tools.ts deleted file mode 100644 index f0a9d3a62..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/infer-agent-tools.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Agent } from './agent'; - -/** - * Infer the type of the tools of an agent. - */ -export type InferAgentTools = - AGENT extends Agent ? TOOLS : never; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/infer-agent-ui-message.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/infer-agent-ui-message.ts deleted file mode 100644 index f6743e0e2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/infer-agent-ui-message.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { InferUITools, UIMessage } from '../ui/ui-messages'; -import { InferAgentTools } from './infer-agent-tools'; - -/** - * Infer the UI message type of an agent. - */ -export type InferAgentUIMessage = UIMessage< - MESSAGE_METADATA, - never, - InferUITools> ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/pipe-agent-ui-stream-to-response.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/pipe-agent-ui-stream-to-response.ts deleted file mode 100644 index 048921f4b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/pipe-agent-ui-stream-to-response.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { ServerResponse } from 'node:http'; -import { StreamTextTransform, UIMessageStreamOptions } from '../generate-text'; -import { Output } from '../generate-text/output'; -import { ToolSet } from '../generate-text/tool-set'; -import { TimeoutConfiguration } from '../prompt/call-settings'; -import { pipeUIMessageStreamToResponse } from '../ui-message-stream'; -import { UIMessageStreamResponseInit } from '../ui-message-stream/ui-message-stream-response-init'; -import { InferUITools, UIMessage } from '../ui/ui-messages'; -import { Agent } from './agent'; -import { createAgentUIStream } from './create-agent-ui-stream'; -import type { ToolLoopAgentOnStepFinishCallback } from './tool-loop-agent-settings'; - -/** - * Pipes the agent UI message stream to a Node.js ServerResponse object. - * - * @param response - The Node.js ServerResponse object to pipe to. - * @param agent - The agent to run. - * @param uiMessages - The input UI messages. - * @param abortSignal - Abort signal. Optional. - * @param timeout - Timeout in milliseconds. Optional. - * @param options - The options for the agent. Optional. - * @param experimental_transform - Stream transformations. Optional. - * @param onStepFinish - Callback that is called when each step is finished. Optional. - * @param headers - Additional headers for the response. Optional. - * @param status - The status code for the response. Optional. - * @param statusText - The status text for the response. Optional. - * @param consumeSseStream - Whether to consume the SSE stream. Optional. - */ -export async function pipeAgentUIStreamToResponse< - CALL_OPTIONS = never, - TOOLS extends ToolSet = {}, - OUTPUT extends Output = never, - MESSAGE_METADATA = unknown, ->({ - response, - headers, - status, - statusText, - consumeSseStream, - ...options -}: { - response: ServerResponse; - agent: Agent; - uiMessages: unknown[]; - abortSignal?: AbortSignal; - timeout?: TimeoutConfiguration; - options?: CALL_OPTIONS; - experimental_transform?: - | StreamTextTransform - | Array>; - onStepFinish?: ToolLoopAgentOnStepFinishCallback; -} & UIMessageStreamResponseInit & - UIMessageStreamOptions< - UIMessage> - >): Promise { - pipeUIMessageStreamToResponse({ - response, - headers, - status, - statusText, - consumeSseStream, - stream: await createAgentUIStream(options), - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/tool-loop-agent-settings.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/tool-loop-agent-settings.ts deleted file mode 100644 index 18b85e404..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/tool-loop-agent-settings.ts +++ /dev/null @@ -1,195 +0,0 @@ -import { - FlexibleSchema, - MaybePromiseLike, - ProviderOptions, - SystemModelMessage, -} from '@ai-sdk/provider-utils'; -import type { - OnFinishEvent, - OnStepFinishEvent, -} from '../generate-text/callback-events'; -import { Output } from '../generate-text/output'; -import { PrepareStepFunction } from '../generate-text/prepare-step'; -import { StopCondition } from '../generate-text/stop-condition'; -import { ToolCallRepairFunction } from '../generate-text/tool-call-repair-function'; -import { ToolSet } from '../generate-text/tool-set'; -import { CallSettings } from '../prompt/call-settings'; -import { Prompt } from '../prompt/prompt'; -import { TelemetrySettings } from '../telemetry/telemetry-settings'; -import { LanguageModel, ToolChoice } from '../types/language-model'; -import { DownloadFunction } from '../util/download/download-function'; -import { AgentCallParameters } from './agent'; - -export type ToolLoopAgentOnStepFinishCallback = ( - stepResult: OnStepFinishEvent, -) => Promise | void; - -export type ToolLoopAgentOnFinishCallback = ( - event: OnFinishEvent, -) => PromiseLike | void; - -/** - * Configuration options for an agent. - */ -export type ToolLoopAgentSettings< - CALL_OPTIONS = never, - TOOLS extends ToolSet = {}, - OUTPUT extends Output = never, -> = Omit & { - /** - * The id of the agent. - */ - id?: string; - - /** - * The instructions for the agent. - * - * It can be a string, or, if you need to pass additional provider options (e.g. for caching), a `SystemModelMessage`. - */ - instructions?: string | SystemModelMessage | Array; - - /** - * The language model to use. - */ - model: LanguageModel; - - /** - * The tools that the model can call. The model needs to support calling tools. - */ - tools?: TOOLS; - - /** - * The tool choice strategy. Default: 'auto'. - */ - toolChoice?: ToolChoice>; - - /** - * Condition for stopping the generation when there are tool results in the last step. - * When the condition is an array, any of the conditions can be met to stop the generation. - * - * @default stepCountIs(20) - */ - stopWhen?: - | StopCondition> - | Array>>; - - /** - * Optional telemetry configuration (experimental). - */ - experimental_telemetry?: TelemetrySettings; - - /** - * Limits the tools that are available for the model to call without - * changing the tool call and result types in the result. - */ - activeTools?: Array>; - - /** - * Optional specification for generating structured outputs. - */ - output?: OUTPUT; - - /** - * Optional function that you can use to provide different settings for a step. - */ - prepareStep?: PrepareStepFunction>; - - /** - * A function that attempts to repair a tool call that failed to parse. - */ - experimental_repairToolCall?: ToolCallRepairFunction>; - - /** - * Callback that is called when each step (LLM call) is finished, including intermediate steps. - */ - onStepFinish?: ToolLoopAgentOnStepFinishCallback>; - - /** - * Callback that is called when all steps are finished and the response is complete. - */ - onFinish?: ToolLoopAgentOnFinishCallback>; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; - - /** - * Context that is passed into tool calls. - * - * Experimental (can break in patch releases). - * - * @default undefined - */ - experimental_context?: unknown; - - /** - * Custom download function to use for URLs. - * - * By default, files are downloaded if the model does not support the URL for the given media type. - */ - experimental_download?: DownloadFunction | undefined; - - /** - * The schema for the call options. - */ - callOptionsSchema?: FlexibleSchema; - - /** - * Prepare the parameters for the generateText or streamText call. - * - * You can use this to have templates based on call options. - */ - prepareCall?: ( - options: Omit< - AgentCallParameters>, - 'onStepFinish' - > & - Pick< - ToolLoopAgentSettings, - | 'model' - | 'tools' - | 'maxOutputTokens' - | 'temperature' - | 'topP' - | 'topK' - | 'presencePenalty' - | 'frequencyPenalty' - | 'stopSequences' - | 'seed' - | 'headers' - | 'instructions' - | 'stopWhen' - | 'experimental_telemetry' - | 'activeTools' - | 'providerOptions' - | 'experimental_context' - | 'experimental_download' - >, - ) => MaybePromiseLike< - Pick< - ToolLoopAgentSettings, - | 'model' - | 'tools' - | 'maxOutputTokens' - | 'temperature' - | 'topP' - | 'topK' - | 'presencePenalty' - | 'frequencyPenalty' - | 'stopSequences' - | 'seed' - | 'headers' - | 'instructions' - | 'stopWhen' - | 'experimental_telemetry' - | 'activeTools' - | 'providerOptions' - | 'experimental_context' - | 'experimental_download' - > & - Omit - >; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/tool-loop-agent.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/tool-loop-agent.ts deleted file mode 100644 index 6bd6436c2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/agent/tool-loop-agent.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { generateText } from '../generate-text/generate-text'; -import { GenerateTextResult } from '../generate-text/generate-text-result'; -import { Output } from '../generate-text/output'; -import { StepResult } from '../generate-text/step-result'; -import { stepCountIs } from '../generate-text/stop-condition'; -import { streamText } from '../generate-text/stream-text'; -import { StreamTextResult } from '../generate-text/stream-text-result'; -import { ToolSet } from '../generate-text/tool-set'; -import { Prompt } from '../prompt'; -import { Agent, AgentCallParameters, AgentStreamParameters } from './agent'; -import { - ToolLoopAgentOnStepFinishCallback, - ToolLoopAgentSettings, -} from './tool-loop-agent-settings'; - -/** - * A tool loop agent is an agent that runs tools in a loop. In each step, - * it calls the LLM, and if there are tool calls, it executes the tools - * and calls the LLM again in a new step with the tool results. - * - * The loop continues until: - * - A finish reasoning other than tool-calls is returned, or - * - A tool that is invoked does not have an execute function, or - * - A tool call needs approval, or - * - A stop condition is met (default stop condition is stepCountIs(20)) - */ -export class ToolLoopAgent< - CALL_OPTIONS = never, - TOOLS extends ToolSet = {}, - OUTPUT extends Output = never, -> implements Agent { - readonly version = 'agent-v1'; - - private readonly settings: ToolLoopAgentSettings; - - constructor(settings: ToolLoopAgentSettings) { - this.settings = settings; - } - - /** - * The id of the agent. - */ - get id(): string | undefined { - return this.settings.id; - } - - /** - * The tools that the agent can use. - */ - get tools(): TOOLS { - return this.settings.tools as TOOLS; - } - - private async prepareCall(options: { - prompt?: string | Array; - messages?: Array; - options?: CALL_OPTIONS; - }): Promise< - Omit< - ToolLoopAgentSettings, - 'prepareCall' | 'instructions' | 'onStepFinish' - > & - Prompt - > { - const { onStepFinish: _settingsOnStepFinish, ...settingsWithoutCallback } = - this.settings; - const baseCallArgs = { - ...settingsWithoutCallback, - stopWhen: this.settings.stopWhen ?? stepCountIs(20), - ...options, - }; - - const preparedCallArgs = - (await this.settings.prepareCall?.( - baseCallArgs as Parameters< - NonNullable< - ToolLoopAgentSettings['prepareCall'] - > - >[0], - )) ?? baseCallArgs; - - const { instructions, messages, prompt, ...callArgs } = preparedCallArgs; - - return { - ...callArgs, - - // restore prompt types - ...({ system: instructions, messages, prompt } as Prompt), - }; - } - - private mergeOnStepFinishCallbacks( - methodCallback: ToolLoopAgentOnStepFinishCallback | undefined, - ): ToolLoopAgentOnStepFinishCallback | undefined { - const constructorCallback = this.settings.onStepFinish; - - if (methodCallback && constructorCallback) { - return async (stepResult: StepResult) => { - await constructorCallback(stepResult); - await methodCallback(stepResult); - }; - } - - return methodCallback ?? constructorCallback; - } - - /** - * Generates an output from the agent (non-streaming). - */ - async generate({ - abortSignal, - timeout, - onStepFinish, - ...options - }: AgentCallParameters): Promise< - GenerateTextResult - > { - return generateText({ - ...(await this.prepareCall(options)), - abortSignal, - timeout, - onStepFinish: this.mergeOnStepFinishCallbacks(onStepFinish), - }); - } - - /** - * Streams an output from the agent (streaming). - */ - async stream({ - abortSignal, - timeout, - experimental_transform, - onStepFinish, - ...options - }: AgentStreamParameters): Promise< - StreamTextResult - > { - return streamText({ - ...(await this.prepareCall(options)), - abortSignal, - timeout, - experimental_transform, - onStepFinish: this.mergeOnStepFinishCallbacks(onStepFinish), - }); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/embed-many-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/embed-many-result.ts deleted file mode 100644 index f88a7a94c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/embed-many-result.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Embedding } from '../types'; -import { EmbeddingModelUsage } from '../types/usage'; -import { ProviderMetadata } from '../types'; -import { Warning } from '../types/warning'; - -/** - * The result of an `embedMany` call. - * It contains the embeddings, the values, and additional information. - */ -export interface EmbedManyResult { - /** - * The values that were embedded. - */ - readonly values: Array; - - /** - * The embeddings. They are in the same order as the values. - */ - readonly embeddings: Array; - - /** - * The embedding token usage. - */ - readonly usage: EmbeddingModelUsage; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - readonly warnings: Array; - - /** - * Optional provider-specific metadata. - */ - readonly providerMetadata?: ProviderMetadata; - - /** - * Optional raw response data. - */ - readonly responses?: Array< - | { - /** - * Response headers. - */ - headers?: Record; - - /** - * The response body. - */ - body?: unknown; - } - | undefined - >; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/embed-many.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/embed-many.ts deleted file mode 100644 index 70ba94862..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/embed-many.ts +++ /dev/null @@ -1,386 +0,0 @@ -import { ProviderOptions, withUserAgentSuffix } from '@ai-sdk/provider-utils'; -import { logWarnings } from '../logger/log-warnings'; -import { resolveEmbeddingModel } from '../model/resolve-model'; -import { assembleOperationName } from '../telemetry/assemble-operation-name'; -import { getBaseTelemetryAttributes } from '../telemetry/get-base-telemetry-attributes'; -import { getTracer } from '../telemetry/get-tracer'; -import { recordSpan } from '../telemetry/record-span'; -import { selectTelemetryAttributes } from '../telemetry/select-telemetry-attributes'; -import { TelemetrySettings } from '../telemetry/telemetry-settings'; -import { Embedding, EmbeddingModel, ProviderMetadata } from '../types'; -import { Warning } from '../types/warning'; -import { prepareRetries } from '../util/prepare-retries'; -import { splitArray } from '../util/split-array'; -import { EmbedManyResult } from './embed-many-result'; -import { VERSION } from '../version'; - -/** - * Embed several values using an embedding model. The type of the value is defined - * by the embedding model. - * - * `embedMany` automatically splits large requests into smaller chunks if the model - * has a limit on how many embeddings can be generated in a single call. - * - * @param model - The embedding model to use. - * @param values - The values that should be embedded. - * - * @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2. - * @param abortSignal - An optional abort signal that can be used to cancel the call. - * @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers. - * - * @param maxParallelCalls - Maximum number of concurrent requests. Default: Infinity. - * - * @param experimental_telemetry - Optional telemetry configuration (experimental). - * - * @param providerOptions - Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - * - * @returns A result object that contains the embeddings, the value, and additional information. - */ -export async function embedMany({ - model: modelArg, - values, - maxParallelCalls = Infinity, - maxRetries: maxRetriesArg, - abortSignal, - headers, - providerOptions, - experimental_telemetry: telemetry, -}: { - /** - * The embedding model to use. - */ - model: EmbeddingModel; - - /** - * The values that should be embedded. - */ - values: Array; - - /** - * Maximum number of retries per embedding model call. Set to 0 to disable retries. - * - * @default 2 - */ - maxRetries?: number; - - /** - * Abort signal. - */ - abortSignal?: AbortSignal; - - /** - * Additional headers to include in the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; - - /** - * Optional telemetry configuration (experimental). - */ - experimental_telemetry?: TelemetrySettings; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; - - /** - * Maximum number of concurrent requests. - * - * @default Infinity - */ - maxParallelCalls?: number; -}): Promise { - const model = resolveEmbeddingModel(modelArg); - - const { maxRetries, retry } = prepareRetries({ - maxRetries: maxRetriesArg, - abortSignal, - }); - - const headersWithUserAgent = withUserAgentSuffix( - headers ?? {}, - `ai/${VERSION}`, - ); - - const baseTelemetryAttributes = getBaseTelemetryAttributes({ - model, - telemetry, - headers: headersWithUserAgent, - settings: { maxRetries }, - }); - - const tracer = getTracer(telemetry); - - return recordSpan({ - name: 'ai.embedMany', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ operationId: 'ai.embedMany', telemetry }), - ...baseTelemetryAttributes, - // specific settings that only make sense on the outer level: - 'ai.values': { - input: () => values.map(value => JSON.stringify(value)), - }, - }, - }), - tracer, - fn: async span => { - const [maxEmbeddingsPerCall, supportsParallelCalls] = await Promise.all([ - model.maxEmbeddingsPerCall, - model.supportsParallelCalls, - ]); - - // the model has not specified limits on - // how many embeddings can be generated in a single call - if (maxEmbeddingsPerCall == null || maxEmbeddingsPerCall === Infinity) { - const { embeddings, usage, warnings, response, providerMetadata } = - await retry(() => { - // nested spans to align with the embedMany telemetry data: - return recordSpan({ - name: 'ai.embedMany.doEmbed', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ - operationId: 'ai.embedMany.doEmbed', - telemetry, - }), - ...baseTelemetryAttributes, - // specific settings that only make sense on the outer level: - 'ai.values': { - input: () => values.map(value => JSON.stringify(value)), - }, - }, - }), - tracer, - fn: async doEmbedSpan => { - const modelResponse = await model.doEmbed({ - values, - abortSignal, - headers: headersWithUserAgent, - providerOptions, - }); - - const embeddings = modelResponse.embeddings; - const usage = modelResponse.usage ?? { tokens: NaN }; - - doEmbedSpan.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.embeddings': { - output: () => - embeddings.map(embedding => - JSON.stringify(embedding), - ), - }, - 'ai.usage.tokens': usage.tokens, - }, - }), - ); - - return { - embeddings, - usage, - warnings: modelResponse.warnings, - providerMetadata: modelResponse.providerMetadata, - response: modelResponse.response, - }; - }, - }); - }); - - span.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.embeddings': { - output: () => - embeddings.map(embedding => JSON.stringify(embedding)), - }, - 'ai.usage.tokens': usage.tokens, - }, - }), - ); - - logWarnings({ - warnings, - provider: model.provider, - model: model.modelId, - }); - - return new DefaultEmbedManyResult({ - values, - embeddings, - usage, - warnings, - providerMetadata, - responses: [response], - }); - } - - // split the values into chunks that are small enough for the model: - const valueChunks = splitArray(values, maxEmbeddingsPerCall); - - // serially embed the chunks: - const embeddings: Array = []; - const warnings: Array = []; - const responses: Array< - | { - headers?: Record; - body?: unknown; - } - | undefined - > = []; - let tokens = 0; - let providerMetadata: ProviderMetadata | undefined; - - const parallelChunks = splitArray( - valueChunks, - supportsParallelCalls ? maxParallelCalls : 1, - ); - - for (const parallelChunk of parallelChunks) { - const results = await Promise.all( - parallelChunk.map(chunk => { - return retry(() => { - // nested spans to align with the embedMany telemetry data: - return recordSpan({ - name: 'ai.embedMany.doEmbed', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ - operationId: 'ai.embedMany.doEmbed', - telemetry, - }), - ...baseTelemetryAttributes, - // specific settings that only make sense on the outer level: - 'ai.values': { - input: () => chunk.map(value => JSON.stringify(value)), - }, - }, - }), - tracer, - fn: async doEmbedSpan => { - const modelResponse = await model.doEmbed({ - values: chunk, - abortSignal, - headers: headersWithUserAgent, - providerOptions, - }); - - const embeddings = modelResponse.embeddings; - const usage = modelResponse.usage ?? { tokens: NaN }; - - doEmbedSpan.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.embeddings': { - output: () => - embeddings.map(embedding => - JSON.stringify(embedding), - ), - }, - 'ai.usage.tokens': usage.tokens, - }, - }), - ); - - return { - embeddings, - usage, - warnings: modelResponse.warnings, - providerMetadata: modelResponse.providerMetadata, - response: modelResponse.response, - }; - }, - }); - }); - }), - ); - - for (const result of results) { - embeddings.push(...result.embeddings); - warnings.push(...result.warnings); - responses.push(result.response); - tokens += result.usage.tokens; - if (result.providerMetadata) { - if (!providerMetadata) { - providerMetadata = { ...result.providerMetadata }; - } else { - for (const [providerName, metadata] of Object.entries( - result.providerMetadata, - )) { - providerMetadata[providerName] = { - ...(providerMetadata[providerName] ?? {}), - ...metadata, - }; - } - } - } - } - } - - span.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.embeddings': { - output: () => - embeddings.map(embedding => JSON.stringify(embedding)), - }, - 'ai.usage.tokens': tokens, - }, - }), - ); - - logWarnings({ - warnings, - provider: model.provider, - model: model.modelId, - }); - - return new DefaultEmbedManyResult({ - values, - embeddings, - usage: { tokens }, - warnings, - providerMetadata: providerMetadata, - responses, - }); - }, - }); -} - -class DefaultEmbedManyResult implements EmbedManyResult { - readonly values: EmbedManyResult['values']; - readonly embeddings: EmbedManyResult['embeddings']; - readonly usage: EmbedManyResult['usage']; - readonly warnings: EmbedManyResult['warnings']; - readonly providerMetadata: EmbedManyResult['providerMetadata']; - readonly responses: EmbedManyResult['responses']; - - constructor(options: { - values: EmbedManyResult['values']; - embeddings: EmbedManyResult['embeddings']; - usage: EmbedManyResult['usage']; - warnings: EmbedManyResult['warnings']; - providerMetadata?: EmbedManyResult['providerMetadata']; - responses?: EmbedManyResult['responses']; - }) { - this.values = options.values; - this.embeddings = options.embeddings; - this.usage = options.usage; - this.warnings = options.warnings; - this.providerMetadata = options.providerMetadata; - this.responses = options.responses; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/embed-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/embed-result.ts deleted file mode 100644 index 72422103d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/embed-result.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Embedding } from '../types'; -import { EmbeddingModelUsage } from '../types/usage'; -import { ProviderMetadata } from '../types'; -import { Warning } from '../types/warning'; - -/** - * The result of an `embed` call. - * It contains the embedding, the value, and additional information. - */ -export interface EmbedResult { - /** - * The value that was embedded. - */ - readonly value: string; - - /** - * The embedding of the value. - */ - readonly embedding: Embedding; - - /** - * The embedding token usage. - */ - readonly usage: EmbeddingModelUsage; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - readonly warnings: Array; - - /** - * Optional provider-specific metadata. - */ - readonly providerMetadata?: ProviderMetadata; - - /** - * Optional response data. - */ - readonly response?: { - /** - * Response headers. - */ - headers?: Record; - - /** - * The response body. - */ - body?: unknown; - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/embed.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/embed.ts deleted file mode 100644 index b929f7290..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/embed.ts +++ /dev/null @@ -1,217 +0,0 @@ -import { ProviderOptions, withUserAgentSuffix } from '@ai-sdk/provider-utils'; -import { logWarnings } from '../logger/log-warnings'; -import { resolveEmbeddingModel } from '../model/resolve-model'; -import { assembleOperationName } from '../telemetry/assemble-operation-name'; -import { getBaseTelemetryAttributes } from '../telemetry/get-base-telemetry-attributes'; -import { getTracer } from '../telemetry/get-tracer'; -import { recordSpan } from '../telemetry/record-span'; -import { selectTelemetryAttributes } from '../telemetry/select-telemetry-attributes'; -import { TelemetrySettings } from '../telemetry/telemetry-settings'; -import { EmbeddingModel } from '../types'; -import { prepareRetries } from '../util/prepare-retries'; -import { EmbedResult } from './embed-result'; -import { VERSION } from '../version'; - -/** - * Embed a value using an embedding model. The type of the value is defined by the embedding model. - * - * @param model - The embedding model to use. - * @param value - The value that should be embedded. - * - * @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2. - * @param abortSignal - An optional abort signal that can be used to cancel the call. - * @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers. - * - * @param experimental_telemetry - Optional telemetry configuration (experimental). - * - * @param providerOptions - Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - * - * @returns A result object that contains the embedding, the value, and additional information. - */ -export async function embed({ - model: modelArg, - value, - providerOptions, - maxRetries: maxRetriesArg, - abortSignal, - headers, - experimental_telemetry: telemetry, -}: { - /** - * The embedding model to use. - */ - model: EmbeddingModel; - - /** - * The value that should be embedded. - */ - value: string; - - /** - * Maximum number of retries per embedding model call. Set to 0 to disable retries. - * - * @default 2 - */ - maxRetries?: number; - - /** - * Abort signal. - */ - abortSignal?: AbortSignal; - - /** - * Additional headers to include in the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; - - /** - * Optional telemetry configuration (experimental). - */ - experimental_telemetry?: TelemetrySettings; -}): Promise { - const model = resolveEmbeddingModel(modelArg); - - const { maxRetries, retry } = prepareRetries({ - maxRetries: maxRetriesArg, - abortSignal, - }); - - const headersWithUserAgent = withUserAgentSuffix( - headers ?? {}, - `ai/${VERSION}`, - ); - - const baseTelemetryAttributes = getBaseTelemetryAttributes({ - model: model, - telemetry, - headers: headersWithUserAgent, - settings: { maxRetries }, - }); - - const tracer = getTracer(telemetry); - - return recordSpan({ - name: 'ai.embed', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ operationId: 'ai.embed', telemetry }), - ...baseTelemetryAttributes, - 'ai.value': { input: () => JSON.stringify(value) }, - }, - }), - tracer, - fn: async span => { - const { embedding, usage, warnings, response, providerMetadata } = - await retry(() => - // nested spans to align with the embedMany telemetry data: - recordSpan({ - name: 'ai.embed.doEmbed', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ - operationId: 'ai.embed.doEmbed', - telemetry, - }), - ...baseTelemetryAttributes, - // specific settings that only make sense on the outer level: - 'ai.values': { input: () => [JSON.stringify(value)] }, - }, - }), - tracer, - fn: async doEmbedSpan => { - const modelResponse = await model.doEmbed({ - values: [value], - abortSignal, - headers: headersWithUserAgent, - providerOptions, - }); - - const embedding = modelResponse.embeddings[0]; - const usage = modelResponse.usage ?? { tokens: NaN }; - - doEmbedSpan.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.embeddings': { - output: () => - modelResponse.embeddings.map(embedding => - JSON.stringify(embedding), - ), - }, - 'ai.usage.tokens': usage.tokens, - }, - }), - ); - - return { - embedding, - usage, - warnings: modelResponse.warnings, - providerMetadata: modelResponse.providerMetadata, - response: modelResponse.response, - }; - }, - }), - ); - - span.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.embedding': { output: () => JSON.stringify(embedding) }, - 'ai.usage.tokens': usage.tokens, - }, - }), - ); - - logWarnings({ warnings, provider: model.provider, model: model.modelId }); - - return new DefaultEmbedResult({ - value, - embedding, - usage, - warnings, - providerMetadata, - response, - }); - }, - }); -} - -class DefaultEmbedResult implements EmbedResult { - readonly value: EmbedResult['value']; - readonly embedding: EmbedResult['embedding']; - readonly usage: EmbedResult['usage']; - readonly warnings: EmbedResult['warnings']; - readonly providerMetadata: EmbedResult['providerMetadata']; - readonly response: EmbedResult['response']; - - constructor(options: { - value: EmbedResult['value']; - embedding: EmbedResult['embedding']; - usage: EmbedResult['usage']; - warnings: EmbedResult['warnings']; - providerMetadata?: EmbedResult['providerMetadata']; - response?: EmbedResult['response']; - }) { - this.value = options.value; - this.embedding = options.embedding; - this.usage = options.usage; - this.warnings = options.warnings; - this.providerMetadata = options.providerMetadata; - this.response = options.response; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/index.ts deleted file mode 100644 index 4e9156124..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/embed/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './embed'; -export * from './embed-many'; -export * from './embed-many-result'; -export * from './embed-result'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/index.ts deleted file mode 100644 index 46a859dd9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -export { - AISDKError, - APICallError, - EmptyResponseBodyError, - InvalidPromptError, - InvalidResponseDataError, - JSONParseError, - LoadAPIKeyError, - LoadSettingError, - NoContentGeneratedError, - NoSuchModelError, - TooManyEmbeddingValuesForCallError, - TypeValidationError, - UnsupportedFunctionalityError, -} from '@ai-sdk/provider'; - -export { InvalidArgumentError } from './invalid-argument-error'; -export { InvalidStreamPartError } from './invalid-stream-part-error'; -export { InvalidToolApprovalError } from './invalid-tool-approval-error'; -export { InvalidToolInputError } from './invalid-tool-input-error'; -export { ToolCallNotFoundForApprovalError } from './tool-call-not-found-for-approval-error'; -export { MissingToolResultsError } from './missing-tool-result-error'; -export { NoImageGeneratedError } from './no-image-generated-error'; -export { NoObjectGeneratedError } from './no-object-generated-error'; -export { NoOutputGeneratedError } from './no-output-generated-error'; -export { NoSpeechGeneratedError } from './no-speech-generated-error'; -export { NoTranscriptGeneratedError } from './no-transcript-generated-error'; -export { NoVideoGeneratedError } from './no-video-generated-error'; -export { NoSuchToolError } from './no-such-tool-error'; -export { ToolCallRepairError } from './tool-call-repair-error'; -export { UnsupportedModelVersionError } from './unsupported-model-version-error'; -export { UIMessageStreamError } from './ui-message-stream-error'; -export { InvalidDataContentError } from '../prompt/invalid-data-content-error'; -export { InvalidMessageRoleError } from '../prompt/invalid-message-role-error'; -export { MessageConversionError } from '../prompt/message-conversion-error'; -export { DownloadError } from '@ai-sdk/provider-utils'; -export { RetryError } from '../util/retry-error'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/invalid-argument-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/invalid-argument-error.ts deleted file mode 100644 index 96f87c26e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/invalid-argument-error.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; - -const name = 'AI_InvalidArgumentError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class InvalidArgumentError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly parameter: string; - readonly value: unknown; - - constructor({ - parameter, - value, - message, - }: { - parameter: string; - value: unknown; - message: string; - }) { - super({ - name, - message: `Invalid argument for parameter ${parameter}: ${message}`, - }); - - this.parameter = parameter; - this.value = value; - } - - static isInstance(error: unknown): error is InvalidArgumentError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/invalid-stream-part-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/invalid-stream-part-error.ts deleted file mode 100644 index ca00c33ca..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/invalid-stream-part-error.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; -import { SingleRequestTextStreamPart } from '../generate-text/run-tools-transformation'; - -const name = 'AI_InvalidStreamPartError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class InvalidStreamPartError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly chunk: SingleRequestTextStreamPart; - - constructor({ - chunk, - message, - }: { - chunk: SingleRequestTextStreamPart; - message: string; - }) { - super({ name, message }); - - this.chunk = chunk; - } - - static isInstance(error: unknown): error is InvalidStreamPartError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/invalid-tool-approval-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/invalid-tool-approval-error.ts deleted file mode 100644 index 7f2510b64..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/invalid-tool-approval-error.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; - -const name = 'AI_InvalidToolApprovalError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class InvalidToolApprovalError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly approvalId: string; - - constructor({ approvalId }: { approvalId: string }) { - super({ - name, - message: - `Tool approval response references unknown approvalId: "${approvalId}". ` + - `No matching tool-approval-request found in message history.`, - }); - - this.approvalId = approvalId; - } - - static isInstance(error: unknown): error is InvalidToolApprovalError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/invalid-tool-input-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/invalid-tool-input-error.ts deleted file mode 100644 index 4568d1b9f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/invalid-tool-input-error.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { AISDKError, getErrorMessage } from '@ai-sdk/provider'; - -const name = 'AI_InvalidToolInputError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class InvalidToolInputError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly toolName: string; - readonly toolInput: string; - - constructor({ - toolInput, - toolName, - cause, - message = `Invalid input for tool ${toolName}: ${getErrorMessage(cause)}`, - }: { - message?: string; - toolInput: string; - toolName: string; - cause: unknown; - }) { - super({ name, message, cause }); - - this.toolInput = toolInput; - this.toolName = toolName; - } - - static isInstance(error: unknown): error is InvalidToolInputError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/missing-tool-result-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/missing-tool-result-error.ts deleted file mode 100644 index 0b5c6d971..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/missing-tool-result-error.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; - -const name = 'AI_MissingToolResultsError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class MissingToolResultsError extends AISDKError { - private readonly [symbol] = true; - - readonly toolCallIds: string[]; - - constructor({ toolCallIds }: { toolCallIds: string[] }) { - super({ - name, - message: `Tool result${ - toolCallIds.length > 1 ? 's are' : ' is' - } missing for tool call${toolCallIds.length > 1 ? 's' : ''} ${toolCallIds.join( - ', ', - )}.`, - }); - - this.toolCallIds = toolCallIds; - } - - static isInstance(error: unknown): error is MissingToolResultsError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-image-generated-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-image-generated-error.ts deleted file mode 100644 index 3f5b020ee..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-image-generated-error.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; -import { ImageModelResponseMetadata } from '../types/image-model-response-metadata'; - -const name = 'AI_NoImageGeneratedError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Thrown when no image could be generated. This can have multiple causes: - * - * - The model failed to generate a response. - * - The model generated a response that could not be parsed. - */ -export class NoImageGeneratedError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - /** - * The response metadata for each call. - */ - readonly responses: Array | undefined; - - constructor({ - message = 'No image generated.', - cause, - responses, - }: { - message?: string; - cause?: Error; - responses?: Array; - }) { - super({ name, message, cause }); - - this.responses = responses; - } - - static isInstance(error: unknown): error is NoImageGeneratedError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-object-generated-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-object-generated-error.ts deleted file mode 100644 index 7da222e14..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-object-generated-error.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; -import { FinishReason } from '../types/language-model'; -import { LanguageModelResponseMetadata } from '../types/language-model-response-metadata'; -import { LanguageModelUsage } from '../types/usage'; - -const name = 'AI_NoObjectGeneratedError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Thrown when no object could be generated. This can have several causes: - * - * - The model failed to generate a response. - * - The model generated a response that could not be parsed. - * - The model generated a response that could not be validated against the schema. - * - * The error contains the following properties: - * - * - `text`: The text that was generated by the model. This can be the raw text or the tool call text, depending on the model. - */ -export class NoObjectGeneratedError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - /** - * The text that was generated by the model. This can be the raw text or the tool call text, depending on the model. - */ - readonly text: string | undefined; - - /** - * The response metadata. - */ - readonly response: LanguageModelResponseMetadata | undefined; - - /** - * The usage of the model. - */ - readonly usage: LanguageModelUsage | undefined; - - /** - * Reason why the model finished generating a response. - */ - readonly finishReason: FinishReason | undefined; - - constructor({ - message = 'No object generated.', - cause, - text, - response, - usage, - finishReason, - }: { - message?: string; - cause?: Error; - text?: string; - response: LanguageModelResponseMetadata; - usage: LanguageModelUsage; - finishReason: FinishReason; - }) { - super({ name, message, cause }); - - this.text = text; - this.response = response; - this.usage = usage; - this.finishReason = finishReason; - } - - static isInstance(error: unknown): error is NoObjectGeneratedError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-output-generated-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-output-generated-error.ts deleted file mode 100644 index c2dc0e2e7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-output-generated-error.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; - -const name = 'AI_NoOutputGeneratedError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Thrown when no LLM output was generated, e.g. because of errors. - */ -export class NoOutputGeneratedError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - constructor({ - message = 'No output generated.', - cause, - }: { - message?: string; - cause?: Error; - } = {}) { - super({ name, message, cause }); - } - - static isInstance(error: unknown): error is NoOutputGeneratedError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-speech-generated-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-speech-generated-error.ts deleted file mode 100644 index 19ed2fe9c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-speech-generated-error.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; -import { SpeechModelResponseMetadata } from '../types/speech-model-response-metadata'; - -const name = 'AI_NoSpeechGeneratedError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Error that is thrown when no speech audio was generated. - */ -export class NoSpeechGeneratedError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly responses: Array; - - constructor(options: { responses: Array }) { - super({ - name, - message: 'No speech audio generated.', - }); - - this.responses = options.responses; - } - - static isInstance(error: unknown): error is NoSpeechGeneratedError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-such-tool-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-such-tool-error.ts deleted file mode 100644 index b00770d36..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-such-tool-error.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; - -const name = 'AI_NoSuchToolError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class NoSuchToolError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly toolName: string; - readonly availableTools: string[] | undefined; - - constructor({ - toolName, - availableTools = undefined, - message = `Model tried to call unavailable tool '${toolName}'. ${ - availableTools === undefined - ? 'No tools are available.' - : `Available tools: ${availableTools.join(', ')}.` - }`, - }: { - toolName: string; - availableTools?: string[] | undefined; - message?: string; - }) { - super({ name, message }); - - this.toolName = toolName; - this.availableTools = availableTools; - } - - static isInstance(error: unknown): error is NoSuchToolError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-transcript-generated-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-transcript-generated-error.ts deleted file mode 100644 index 9a69f9a65..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-transcript-generated-error.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; -import { TranscriptionModelResponseMetadata } from '../types/transcription-model-response-metadata'; - -const name = 'AI_NoTranscriptGeneratedError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Error that is thrown when no transcript was generated. - */ -export class NoTranscriptGeneratedError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly responses: Array; - - constructor(options: { - responses: Array; - }) { - super({ - name, - message: 'No transcript generated.', - }); - - this.responses = options.responses; - } - - static isInstance(error: unknown): error is NoTranscriptGeneratedError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-video-generated-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-video-generated-error.ts deleted file mode 100644 index 479d65656..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/no-video-generated-error.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; -import { VideoModelResponseMetadata } from '../types/video-model-response-metadata'; - -const name = 'AI_NoVideoGeneratedError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class NoVideoGeneratedError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly responses: Array; - - constructor({ - message = 'No video generated.', - cause, - responses, - }: { - message?: string; - cause?: unknown; - responses: Array; - }) { - super({ name, message, cause }); - - this.responses = responses; - } - - static isInstance(error: unknown): error is NoVideoGeneratedError { - return AISDKError.hasMarker(error, marker); - } - - /** - * @deprecated use `isInstance` instead - */ - static isNoVideoGeneratedError( - error: unknown, - ): error is NoVideoGeneratedError { - return error instanceof Error && - error.name === name && - typeof (error as NoVideoGeneratedError).responses !== 'undefined' - ? true - : false; - } - - /** - * @deprecated Do not use this method. It will be removed in the next major version. - */ - toJSON() { - return { - name: this.name, - message: this.message, - stack: this.stack, - - cause: this.cause, - responses: this.responses, - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/tool-call-not-found-for-approval-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/tool-call-not-found-for-approval-error.ts deleted file mode 100644 index 90bb44402..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/tool-call-not-found-for-approval-error.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; - -const name = 'AI_ToolCallNotFoundForApprovalError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class ToolCallNotFoundForApprovalError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly toolCallId: string; - readonly approvalId: string; - - constructor({ - toolCallId, - approvalId, - }: { - toolCallId: string; - approvalId: string; - }) { - super({ - name, - message: `Tool call "${toolCallId}" not found for approval request "${approvalId}".`, - }); - - this.toolCallId = toolCallId; - this.approvalId = approvalId; - } - - static isInstance(error: unknown): error is ToolCallNotFoundForApprovalError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/tool-call-repair-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/tool-call-repair-error.ts deleted file mode 100644 index cf8c8c541..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/tool-call-repair-error.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { AISDKError, getErrorMessage } from '@ai-sdk/provider'; -import { InvalidToolInputError } from './invalid-tool-input-error'; -import { NoSuchToolError } from './no-such-tool-error'; - -const name = 'AI_ToolCallRepairError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class ToolCallRepairError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly originalError: NoSuchToolError | InvalidToolInputError; - - constructor({ - cause, - originalError, - message = `Error repairing tool call: ${getErrorMessage(cause)}`, - }: { - message?: string; - cause: unknown; - originalError: NoSuchToolError | InvalidToolInputError; - }) { - super({ name, message, cause }); - this.originalError = originalError; - } - - static isInstance(error: unknown): error is ToolCallRepairError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/ui-message-stream-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/ui-message-stream-error.ts deleted file mode 100644 index 3792881e9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/ui-message-stream-error.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; - -const name = 'AI_UIMessageStreamError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -/** - * Error thrown when a UI message stream contains invalid or out-of-sequence chunks. - * - * This typically occurs when: - * - A delta chunk is received without a corresponding start chunk - * - An end chunk is received without a corresponding start chunk - * - A tool invocation is not found for the given toolCallId - * - * @see https://ai-sdk.dev/docs/reference/ai-sdk-errors/ai-ui-message-stream-error - */ -export class UIMessageStreamError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - /** - * The type of chunk that caused the error (e.g., 'text-delta', 'reasoning-end'). - */ - readonly chunkType: string; - - /** - * The ID associated with the failing chunk (part ID or toolCallId). - */ - readonly chunkId: string; - - constructor({ - chunkType, - chunkId, - message, - }: { - chunkType: string; - chunkId: string; - message: string; - }) { - super({ name, message }); - - this.chunkType = chunkType; - this.chunkId = chunkId; - } - - static isInstance(error: unknown): error is UIMessageStreamError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/unsupported-model-version-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/unsupported-model-version-error.ts deleted file mode 100644 index 822dcbcc7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/unsupported-model-version-error.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; - -/** - * Error that is thrown when a model with an unsupported version is used. - */ -export class UnsupportedModelVersionError extends AISDKError { - readonly version: string; - readonly provider: string; - readonly modelId: string; - - constructor(options: { version: string; provider: string; modelId: string }) { - super({ - name: 'AI_UnsupportedModelVersionError', - message: - `Unsupported model version ${options.version} for provider "${options.provider}" and model "${options.modelId}". ` + - `AI SDK 5 only supports models that implement specification version "v2".`, - }); - - this.version = options.version; - this.provider = options.provider; - this.modelId = options.modelId; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/verify-no-object-generated-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/verify-no-object-generated-error.ts deleted file mode 100644 index 9d092260a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/error/verify-no-object-generated-error.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { expect } from 'vitest'; - -import { - FinishReason, - LanguageModelResponseMetadata, - LanguageModelUsage, -} from '../types'; -import { NoObjectGeneratedError } from './no-object-generated-error'; - -export function verifyNoObjectGeneratedError( - error: unknown, - expected: { - message: string; - response: LanguageModelResponseMetadata & { - body?: string; - }; - usage: LanguageModelUsage; - finishReason: FinishReason; - }, -) { - expect(NoObjectGeneratedError.isInstance(error)).toBeTruthy(); - const noObjectGeneratedError = error as NoObjectGeneratedError; - expect(noObjectGeneratedError.message).toEqual(expected.message); - expect(noObjectGeneratedError.response).toEqual(expected.response); - expect(noObjectGeneratedError.usage).toEqual(expected.usage); - expect(noObjectGeneratedError.finishReason).toEqual(expected.finishReason); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-image/generate-image-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-image/generate-image-result.ts deleted file mode 100644 index 818b6511e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-image/generate-image-result.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { GeneratedFile } from '../generate-text'; -import { ImageModelProviderMetadata } from '../types/image-model'; -import { ImageModelResponseMetadata } from '../types/image-model-response-metadata'; -import { ImageModelUsage } from '../types/usage'; -import { Warning } from '../types/warning'; - -/** - * The result of a `generateImage` call. - * It contains the images and additional information. - */ -export interface GenerateImageResult { - /** - * The first image that was generated. - */ - readonly image: GeneratedFile; - - /** - * The images that were generated. - */ - readonly images: Array; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - readonly warnings: Array; - - /** - * Response metadata from the provider. There may be multiple responses if we made multiple calls to the model. - */ - readonly responses: Array; - - /** - * Provider-specific metadata. They are passed through from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - readonly providerMetadata: ImageModelProviderMetadata; - - /** - * Combined token usage across all underlying provider calls for this image generation. - */ - readonly usage: ImageModelUsage; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-image/generate-image.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-image/generate-image.ts deleted file mode 100644 index 93aa4e7d8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-image/generate-image.ts +++ /dev/null @@ -1,361 +0,0 @@ -import { - ImageModelV3, - ImageModelV3CallOptions, - ImageModelV3File, - ImageModelV3ProviderMetadata, -} from '@ai-sdk/provider'; -import { - convertBase64ToUint8Array, - DataContent, - ProviderOptions, - withUserAgentSuffix, -} from '@ai-sdk/provider-utils'; -import { NoImageGeneratedError } from '../error/no-image-generated-error'; -import { - DefaultGeneratedFile, - GeneratedFile, -} from '../generate-text/generated-file'; -import { logWarnings } from '../logger/log-warnings'; -import { resolveImageModel } from '../model/resolve-model'; -import type { ImageModel } from '../types/image-model'; -import { ImageModelResponseMetadata } from '../types/image-model-response-metadata'; -import { addImageModelUsage, ImageModelUsage } from '../types/usage'; -import { Warning } from '../types/warning'; -import { - detectMediaType, - imageMediaTypeSignatures, -} from '../util/detect-media-type'; -import { prepareRetries } from '../util/prepare-retries'; -import { VERSION } from '../version'; -import { GenerateImageResult } from './generate-image-result'; -import { convertDataContentToUint8Array } from '../prompt/data-content'; -import { splitDataUrl } from '../prompt/split-data-url'; - -export type GenerateImagePrompt = - | string - | { - images: Array; - text?: string; - mask?: DataContent; - }; - -/** - * Generates images using an image model. - * - * @param model - The image model to use. - * @param prompt - The prompt that should be used to generate the image. - * @param n - Number of images to generate. Default: 1. - * @param maxImagesPerCall - Maximum number of images to generate in a single API call. - * @param size - Size of the images to generate. Must have the format `{width}x{height}`. - * @param aspectRatio - Aspect ratio of the images to generate. Must have the format `{width}:{height}`. - * @param seed - Seed for the image generation. - * @param providerOptions - Additional provider-specific options that are passed through to the provider - * as body parameters. - * @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2. - * @param abortSignal - An optional abort signal that can be used to cancel the call. - * @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers. - * - * @returns A result object that contains the generated images. - */ -export async function generateImage({ - model: modelArg, - prompt: promptArg, - n = 1, - maxImagesPerCall, - size, - aspectRatio, - seed, - providerOptions, - maxRetries: maxRetriesArg, - abortSignal, - headers, -}: { - /** - * The image model to use. - */ - model: ImageModel; - - /** - * The prompt that should be used to generate the image. - */ - prompt: GenerateImagePrompt; - - /** - * Number of images to generate. - */ - n?: number; - - /** - * Maximum number of images to generate in a single API call. If not provided, the model's default will be used. - */ - maxImagesPerCall?: number; - - /** - * Size of the images to generate. Must have the format `{width}x{height}`. If not provided, the default size will be used. - */ - size?: `${number}x${number}`; - - /** - * Aspect ratio of the images to generate. Must have the format `{width}:{height}`. If not provided, the default aspect ratio will be used. - */ - aspectRatio?: `${number}:${number}`; - - /** - * Seed for the image generation. If not provided, the default seed will be used. - */ - seed?: number; - - /** - * Additional provider-specific options that are passed through to the provider - * as body parameters. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * ```ts - * { - * "openai": { - * "style": "vivid" - * } - * } - * ``` - */ - providerOptions?: ProviderOptions; - - /** - * Maximum number of retries per image model call. Set to 0 to disable retries. - * - * @default 2 - */ - maxRetries?: number; - - /** - * Abort signal. - */ - abortSignal?: AbortSignal; - - /** - * Additional headers to include in the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; -}): Promise { - const model = resolveImageModel(modelArg); - - const headersWithUserAgent = withUserAgentSuffix( - headers ?? {}, - `ai/${VERSION}`, - ); - - const { retry } = prepareRetries({ - maxRetries: maxRetriesArg, - abortSignal, - }); - - // default to 1 if the model has not specified limits on - // how many images can be generated in a single call - const maxImagesPerCallWithDefault = - maxImagesPerCall ?? (await invokeModelMaxImagesPerCall(model)) ?? 1; - - // parallelize calls to the model: - const callCount = Math.ceil(n / maxImagesPerCallWithDefault); - const callImageCounts = Array.from({ length: callCount }, (_, i) => { - if (i < callCount - 1) { - return maxImagesPerCallWithDefault; - } - - const remainder = n % maxImagesPerCallWithDefault; - return remainder === 0 ? maxImagesPerCallWithDefault : remainder; - }); - - const results = await Promise.all( - callImageCounts.map(async callImageCount => - retry(() => { - const { prompt, files, mask } = normalizePrompt(promptArg); - - return model.doGenerate({ - prompt, - files, - mask, - n: callImageCount, - abortSignal, - headers: headersWithUserAgent, - size, - aspectRatio, - seed, - providerOptions: providerOptions ?? {}, - }); - }), - ), - ); - - // collect result images, warnings, and response metadata - const images: Array = []; - const warnings: Array = []; - const responses: Array = []; - const providerMetadata: ImageModelV3ProviderMetadata = {}; - let totalUsage: ImageModelUsage = { - inputTokens: undefined, - outputTokens: undefined, - totalTokens: undefined, - }; - for (const result of results) { - images.push( - ...result.images.map( - image => - new DefaultGeneratedFile({ - data: image, - mediaType: - detectMediaType({ - data: image, - signatures: imageMediaTypeSignatures, - }) ?? 'image/png', - }), - ), - ); - warnings.push(...result.warnings); - - if (result.usage != null) { - totalUsage = addImageModelUsage(totalUsage, result.usage); - } - - if (result.providerMetadata) { - for (const [providerName, metadata] of Object.entries<{ - images: unknown; - }>(result.providerMetadata)) { - if (providerName === 'gateway') { - const currentEntry = providerMetadata[providerName]; - if (currentEntry != null && typeof currentEntry === 'object') { - providerMetadata[providerName] = { - ...(currentEntry as object), - ...metadata, - } as ImageModelV3ProviderMetadata[string]; - } else { - providerMetadata[providerName] = - metadata as ImageModelV3ProviderMetadata[string]; - } - const imagesValue = ( - providerMetadata[providerName] as { images?: unknown } - ).images; - if (Array.isArray(imagesValue) && imagesValue.length === 0) { - delete (providerMetadata[providerName] as { images?: unknown }) - .images; - } - } else { - providerMetadata[providerName] ??= { images: [] }; - providerMetadata[providerName].images.push( - ...result.providerMetadata[providerName].images, - ); - } - } - } - - responses.push(result.response); - } - - logWarnings({ warnings, provider: model.provider, model: model.modelId }); - - if (!images.length) { - throw new NoImageGeneratedError({ responses }); - } - - return new DefaultGenerateImageResult({ - images, - warnings, - responses, - providerMetadata, - usage: totalUsage, - }); -} - -class DefaultGenerateImageResult implements GenerateImageResult { - readonly images: Array; - readonly warnings: Array; - readonly responses: Array; - readonly providerMetadata: ImageModelV3ProviderMetadata; - readonly usage: ImageModelUsage; - - constructor(options: { - images: Array; - warnings: Array; - responses: Array; - providerMetadata: ImageModelV3ProviderMetadata; - usage: ImageModelUsage; - }) { - this.images = options.images; - this.warnings = options.warnings; - this.responses = options.responses; - this.providerMetadata = options.providerMetadata; - this.usage = options.usage; - } - - get image() { - return this.images[0]; - } -} - -async function invokeModelMaxImagesPerCall(model: ImageModelV3) { - const isFunction = model.maxImagesPerCall instanceof Function; - - if (!isFunction) { - return model.maxImagesPerCall; - } - - return model.maxImagesPerCall({ - modelId: model.modelId, - }); -} - -function normalizePrompt( - prompt: GenerateImagePrompt, -): Pick { - if (typeof prompt === 'string') { - return { prompt, files: undefined, mask: undefined }; - } - - return { - prompt: prompt.text, - files: prompt.images.map(toImageModelV3File), - mask: prompt.mask ? toImageModelV3File(prompt.mask) : undefined, - }; -} - -function toImageModelV3File(dataContent: DataContent): ImageModelV3File { - if (typeof dataContent === 'string' && dataContent.startsWith('http')) { - return { - type: 'url', - url: dataContent, - }; - } - - // Handle data URLs - if (typeof dataContent === 'string' && dataContent.startsWith('data:')) { - const { mediaType: dataUrlMediaType, base64Content } = - splitDataUrl(dataContent); - - if (base64Content != null) { - const uint8Data = convertBase64ToUint8Array(base64Content); - return { - type: 'file', - data: uint8Data, - mediaType: - dataUrlMediaType || - detectMediaType({ - data: uint8Data, - signatures: imageMediaTypeSignatures, - }) || - 'image/png', - }; - } - } - - const uint8Data = convertDataContentToUint8Array(dataContent); - return { - type: 'file', - data: uint8Data, - mediaType: - detectMediaType({ - data: uint8Data, - signatures: imageMediaTypeSignatures, - }) || 'image/png', - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-image/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-image/index.ts deleted file mode 100644 index d886b66b3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-image/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -export { generateImage } from './generate-image'; -export type { GenerateImageResult } from './generate-image-result'; - -// deprecated exports - -import { generateImage } from './generate-image'; -/** - * @deprecated Use `generateImage` instead. - */ -const experimental_generateImage = generateImage; -export { experimental_generateImage }; - -import type { GenerateImageResult } from './generate-image-result'; -/** - * @deprecated Use `GenerateImageResult` instead. - */ -type Experimental_GenerateImageResult = GenerateImageResult; -export type { Experimental_GenerateImageResult }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/generate-object-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/generate-object-result.ts deleted file mode 100644 index 7620de2f2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/generate-object-result.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { - CallWarning, - FinishReason, - LanguageModelRequestMetadata, - LanguageModelResponseMetadata, - ProviderMetadata, -} from '../types'; -import { LanguageModelUsage } from '../types/usage'; - -/** - * The result of a `generateObject` call. - */ -export interface GenerateObjectResult { - /** - * The generated object (typed according to the schema). - */ - readonly object: OBJECT; - - /** - * The reasoning that was used to generate the object. - * Concatenated from all reasoning parts. - */ - readonly reasoning: string | undefined; - - /** - * The reason why the generation finished. - */ - readonly finishReason: FinishReason; - - /** - * The token usage of the generated response. - */ - readonly usage: LanguageModelUsage; - - /** - * Warnings from the model provider (e.g. unsupported settings). - */ - readonly warnings: CallWarning[] | undefined; - - /** - * Additional request information. - */ - readonly request: LanguageModelRequestMetadata; - - /** - * Additional response information. - */ - readonly response: LanguageModelResponseMetadata & { - /** - * Response body (available only for providers that use HTTP requests). - */ - body?: unknown; - }; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - readonly providerMetadata: ProviderMetadata | undefined; - - /** - * Converts the object to a JSON response. - * The response will have a status code of 200 and a content type of `application/json; charset=utf-8`. - */ - toJsonResponse(init?: ResponseInit): Response; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/generate-object.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/generate-object.ts deleted file mode 100644 index 4f4fe846e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/generate-object.ts +++ /dev/null @@ -1,514 +0,0 @@ -import { JSONValue } from '@ai-sdk/provider'; -import { - createIdGenerator, - FlexibleSchema, - InferSchema, - ProviderOptions, - withUserAgentSuffix, -} from '@ai-sdk/provider-utils'; -import { NoObjectGeneratedError } from '../error/no-object-generated-error'; -import { extractReasoningContent } from '../generate-text/extract-reasoning-content'; -import { extractTextContent } from '../generate-text/extract-text-content'; -import { logWarnings } from '../logger/log-warnings'; -import { resolveLanguageModel } from '../model/resolve-model'; -import { CallSettings } from '../prompt/call-settings'; -import { convertToLanguageModelPrompt } from '../prompt/convert-to-language-model-prompt'; -import { prepareCallSettings } from '../prompt/prepare-call-settings'; -import { Prompt } from '../prompt/prompt'; -import { standardizePrompt } from '../prompt/standardize-prompt'; -import { wrapGatewayError } from '../prompt/wrap-gateway-error'; -import { assembleOperationName } from '../telemetry/assemble-operation-name'; -import { getBaseTelemetryAttributes } from '../telemetry/get-base-telemetry-attributes'; -import { getTracer } from '../telemetry/get-tracer'; -import { recordSpan } from '../telemetry/record-span'; -import { selectTelemetryAttributes } from '../telemetry/select-telemetry-attributes'; -import { stringifyForTelemetry } from '../telemetry/stringify-for-telemetry'; -import { TelemetrySettings } from '../telemetry/telemetry-settings'; -import { - CallWarning, - FinishReason, - LanguageModel, -} from '../types/language-model'; -import { LanguageModelRequestMetadata } from '../types/language-model-request-metadata'; -import { LanguageModelResponseMetadata } from '../types/language-model-response-metadata'; -import { ProviderMetadata } from '../types/provider-metadata'; -import { asLanguageModelUsage, LanguageModelUsage } from '../types/usage'; -import { DownloadFunction } from '../util/download/download-function'; -import { prepareHeaders } from '../util/prepare-headers'; -import { prepareRetries } from '../util/prepare-retries'; -import { VERSION } from '../version'; -import { GenerateObjectResult } from './generate-object-result'; -import { getOutputStrategy } from './output-strategy'; -import { parseAndValidateObjectResultWithRepair } from './parse-and-validate-object-result'; -import { RepairTextFunction } from './repair-text'; -import { validateObjectGenerationInput } from './validate-object-generation-input'; - -const originalGenerateId = createIdGenerator({ prefix: 'aiobj', size: 24 }); - -/** - * Generate a structured, typed object for a given prompt and schema using a language model. - * - * This function does not stream the output. If you want to stream the output, use `streamObject` instead. - * - * @param model - The language model to use. - * - * @param system - A system message that will be part of the prompt. - * @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both. - * @param messages - A list of messages. You can either use `prompt` or `messages` but not both. - * - * @param maxOutputTokens - Maximum number of tokens to generate. - * @param temperature - Temperature setting. - * The value is passed through to the provider. The range depends on the provider and model. - * It is recommended to set either `temperature` or `topP`, but not both. - * @param topP - Nucleus sampling. - * The value is passed through to the provider. The range depends on the provider and model. - * It is recommended to set either `temperature` or `topP`, but not both. - * @param topK - Only sample from the top K options for each subsequent token. - * Used to remove "long tail" low probability responses. - * Recommended for advanced use cases only. You usually only need to use temperature. - * @param presencePenalty - Presence penalty setting. - * It affects the likelihood of the model to repeat information that is already in the prompt. - * The value is passed through to the provider. The range depends on the provider and model. - * @param frequencyPenalty - Frequency penalty setting. - * It affects the likelihood of the model to repeatedly use the same words or phrases. - * The value is passed through to the provider. The range depends on the provider and model. - * @param stopSequences - Stop sequences. - * If set, the model will stop generating text when one of the stop sequences is generated. - * @param seed - The seed (integer) to use for random sampling. - * If set and supported by the model, calls will generate deterministic results. - * - * @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2. - * @param abortSignal - An optional abort signal that can be used to cancel the call. - * @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers. - * - * @param schema - The schema of the object that the model should generate. - * @param schemaName - Optional name of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. - * via tool or schema name. - * @param schemaDescription - Optional description of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. - * via tool or schema description. - * - * @param output - The type of the output. - * - * - 'object': The output is an object. - * - 'array': The output is an array. - * - 'enum': The output is an enum. - * - 'no-schema': The output is not a schema. - * - * @param experimental_repairText - A function that attempts to repair the raw output of the model - * to enable JSON parsing. - * - * @param experimental_telemetry - Optional telemetry configuration (experimental). - * - * @param providerOptions - Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - * - * @returns - * A result object that contains the generated object, the finish reason, the token usage, and additional information. - * - * @deprecated Use `generateText` with an `output` setting instead. - */ -export async function generateObject< - SCHEMA extends FlexibleSchema = FlexibleSchema, - OUTPUT extends 'object' | 'array' | 'enum' | 'no-schema' = - InferSchema extends string ? 'enum' : 'object', - RESULT = OUTPUT extends 'array' - ? Array> - : InferSchema, ->( - options: Omit & - Prompt & - (OUTPUT extends 'enum' - ? { - /** - * The enum values that the model should use. - */ - enum: Array; - output: 'enum'; - } - : OUTPUT extends 'no-schema' - ? {} - : { - /** - * The schema of the object that the model should generate. - */ - schema: SCHEMA; - - /** - * Optional name of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. - * via tool or schema name. - */ - schemaName?: string; - - /** - * Optional description of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. - * via tool or schema description. - */ - schemaDescription?: string; - }) & { - output?: OUTPUT; - - /** - * The language model to use. - */ - model: LanguageModel; - /** - * A function that attempts to repair the raw output of the model - * to enable JSON parsing. - */ - experimental_repairText?: RepairTextFunction; - - /** - * Optional telemetry configuration (experimental). - */ - - experimental_telemetry?: TelemetrySettings; - - /** - * Custom download function to use for URLs. - * - * By default, files are downloaded if the model does not support the URL for the given media type. - */ - experimental_download?: DownloadFunction | undefined; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; - - /** - * Internal. For test use only. May change without notice. - */ - _internal?: { - generateId?: () => string; - currentDate?: () => Date; - }; - }, -): Promise> { - const { - model: modelArg, - output = 'object', - system, - prompt, - messages, - maxRetries: maxRetriesArg, - abortSignal, - headers, - experimental_repairText: repairText, - experimental_telemetry: telemetry, - experimental_download: download, - providerOptions, - _internal: { - generateId = originalGenerateId, - currentDate = () => new Date(), - } = {}, - ...settings - } = options; - - const model = resolveLanguageModel(modelArg); - - const enumValues = 'enum' in options ? options.enum : undefined; - const { - schema: inputSchema, - schemaDescription, - schemaName, - } = 'schema' in options ? options : {}; - - validateObjectGenerationInput({ - output, - schema: inputSchema, - schemaName, - schemaDescription, - enumValues, - }); - - const { maxRetries, retry } = prepareRetries({ - maxRetries: maxRetriesArg, - abortSignal, - }); - - const outputStrategy = getOutputStrategy({ - output, - schema: inputSchema, - enumValues, - }); - - const callSettings = prepareCallSettings(settings); - - const headersWithUserAgent = withUserAgentSuffix( - headers ?? {}, - `ai/${VERSION}`, - ); - - const baseTelemetryAttributes = getBaseTelemetryAttributes({ - model, - telemetry, - headers: headersWithUserAgent, - settings: { ...callSettings, maxRetries }, - }); - - const tracer = getTracer(telemetry); - const jsonSchema = await outputStrategy.jsonSchema(); - - try { - return await recordSpan({ - name: 'ai.generateObject', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ - operationId: 'ai.generateObject', - telemetry, - }), - ...baseTelemetryAttributes, - // specific settings that only make sense on the outer level: - 'ai.prompt': { - input: () => JSON.stringify({ system, prompt, messages }), - }, - 'ai.schema': - jsonSchema != null - ? { input: () => JSON.stringify(jsonSchema) } - : undefined, - 'ai.schema.name': schemaName, - 'ai.schema.description': schemaDescription, - 'ai.settings.output': outputStrategy.type, - }, - }), - tracer, - fn: async span => { - let result: string; - let finishReason: FinishReason; - let usage: LanguageModelUsage; - let warnings: CallWarning[] | undefined; - let response: LanguageModelResponseMetadata; - let request: LanguageModelRequestMetadata; - let resultProviderMetadata: ProviderMetadata | undefined; - let reasoning: string | undefined; - - const standardizedPrompt = await standardizePrompt({ - system, - prompt, - messages, - } as Prompt); - - const promptMessages = await convertToLanguageModelPrompt({ - prompt: standardizedPrompt, - supportedUrls: await model.supportedUrls, - download, - }); - - const generateResult = await retry(() => - recordSpan({ - name: 'ai.generateObject.doGenerate', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ - operationId: 'ai.generateObject.doGenerate', - telemetry, - }), - ...baseTelemetryAttributes, - 'ai.prompt.messages': { - input: () => stringifyForTelemetry(promptMessages), - }, - - // standardized gen-ai llm span attributes: - 'gen_ai.system': model.provider, - 'gen_ai.request.model': model.modelId, - 'gen_ai.request.frequency_penalty': - callSettings.frequencyPenalty, - 'gen_ai.request.max_tokens': callSettings.maxOutputTokens, - 'gen_ai.request.presence_penalty': callSettings.presencePenalty, - 'gen_ai.request.temperature': callSettings.temperature, - 'gen_ai.request.top_k': callSettings.topK, - 'gen_ai.request.top_p': callSettings.topP, - }, - }), - tracer, - fn: async span => { - const result = await model.doGenerate({ - responseFormat: { - type: 'json', - schema: jsonSchema, - name: schemaName, - description: schemaDescription, - }, - ...prepareCallSettings(settings), - prompt: promptMessages, - providerOptions, - abortSignal, - headers: headersWithUserAgent, - }); - - const responseData = { - id: result.response?.id ?? generateId(), - timestamp: result.response?.timestamp ?? currentDate(), - modelId: result.response?.modelId ?? model.modelId, - headers: result.response?.headers, - body: result.response?.body, - }; - - const text = extractTextContent(result.content); - const reasoning = extractReasoningContent(result.content); - - if (text === undefined) { - throw new NoObjectGeneratedError({ - message: - 'No object generated: the model did not return a response.', - response: responseData, - usage: asLanguageModelUsage(result.usage), - finishReason: result.finishReason.unified, - }); - } - - // Add response information to the span: - span.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.response.finishReason': result.finishReason.unified, - 'ai.response.object': { output: () => text }, - 'ai.response.id': responseData.id, - 'ai.response.model': responseData.modelId, - 'ai.response.timestamp': - responseData.timestamp.toISOString(), - 'ai.response.providerMetadata': JSON.stringify( - result.providerMetadata, - ), - - // TODO rename telemetry attributes to inputTokens and outputTokens - 'ai.usage.promptTokens': result.usage.inputTokens.total, - 'ai.usage.completionTokens': - result.usage.outputTokens.total, - - // standardized gen-ai llm span attributes: - 'gen_ai.response.finish_reasons': [ - result.finishReason.unified, - ], - 'gen_ai.response.id': responseData.id, - 'gen_ai.response.model': responseData.modelId, - 'gen_ai.usage.input_tokens': result.usage.inputTokens.total, - 'gen_ai.usage.output_tokens': - result.usage.outputTokens.total, - }, - }), - ); - - return { - ...result, - objectText: text, - reasoning, - responseData, - }; - }, - }), - ); - - result = generateResult.objectText; - finishReason = generateResult.finishReason.unified; - usage = asLanguageModelUsage(generateResult.usage); - warnings = generateResult.warnings; - resultProviderMetadata = generateResult.providerMetadata; - request = generateResult.request ?? {}; - response = generateResult.responseData; - reasoning = generateResult.reasoning; - - logWarnings({ - warnings, - provider: model.provider, - model: model.modelId, - }); - - const object = await parseAndValidateObjectResultWithRepair( - result, - outputStrategy, - repairText, - { - response, - usage, - finishReason, - }, - ); - - // Add response information to the span: - span.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.response.finishReason': finishReason, - 'ai.response.object': { - output: () => JSON.stringify(object), - }, - 'ai.response.providerMetadata': JSON.stringify( - resultProviderMetadata, - ), - - // TODO rename telemetry attributes to inputTokens and outputTokens - 'ai.usage.promptTokens': usage.inputTokens, - 'ai.usage.completionTokens': usage.outputTokens, - }, - }), - ); - - return new DefaultGenerateObjectResult({ - object, - reasoning, - finishReason, - usage, - warnings, - request, - response, - providerMetadata: resultProviderMetadata, - }); - }, - }); - } catch (error) { - throw wrapGatewayError(error); - } -} - -class DefaultGenerateObjectResult implements GenerateObjectResult { - readonly object: GenerateObjectResult['object']; - readonly finishReason: GenerateObjectResult['finishReason']; - readonly usage: GenerateObjectResult['usage']; - readonly warnings: GenerateObjectResult['warnings']; - readonly providerMetadata: GenerateObjectResult['providerMetadata']; - readonly response: GenerateObjectResult['response']; - readonly request: GenerateObjectResult['request']; - readonly reasoning: GenerateObjectResult['reasoning']; - - constructor(options: { - object: GenerateObjectResult['object']; - finishReason: GenerateObjectResult['finishReason']; - usage: GenerateObjectResult['usage']; - warnings: GenerateObjectResult['warnings']; - providerMetadata: GenerateObjectResult['providerMetadata']; - response: GenerateObjectResult['response']; - request: GenerateObjectResult['request']; - reasoning: GenerateObjectResult['reasoning']; - }) { - this.object = options.object; - this.finishReason = options.finishReason; - this.usage = options.usage; - this.warnings = options.warnings; - this.providerMetadata = options.providerMetadata; - this.response = options.response; - this.request = options.request; - this.reasoning = options.reasoning; - } - - toJsonResponse(init?: ResponseInit): Response { - return new Response(JSON.stringify(this.object), { - status: init?.status ?? 200, - headers: prepareHeaders(init?.headers, { - 'content-type': 'application/json; charset=utf-8', - }), - }); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/index.ts deleted file mode 100644 index b25bd8084..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { generateObject } from './generate-object'; -export type { RepairTextFunction } from './repair-text'; -export type { GenerateObjectResult } from './generate-object-result'; -export { streamObject } from './stream-object'; -export type { StreamObjectOnFinishCallback } from './stream-object'; -export type { - ObjectStreamPart, - StreamObjectResult, -} from './stream-object-result'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/inject-json-instruction.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/inject-json-instruction.ts deleted file mode 100644 index 4ac470a03..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/inject-json-instruction.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { JSONSchema7 } from '@ai-sdk/provider'; - -const DEFAULT_SCHEMA_PREFIX = 'JSON schema:'; -const DEFAULT_SCHEMA_SUFFIX = - 'You MUST answer with a JSON object that matches the JSON schema above.'; -const DEFAULT_GENERIC_SUFFIX = 'You MUST answer with JSON.'; - -export function injectJsonInstruction({ - prompt, - schema, - schemaPrefix = schema != null ? DEFAULT_SCHEMA_PREFIX : undefined, - schemaSuffix = schema != null - ? DEFAULT_SCHEMA_SUFFIX - : DEFAULT_GENERIC_SUFFIX, -}: { - prompt?: string; - schema?: JSONSchema7; - schemaPrefix?: string; - schemaSuffix?: string; -}): string { - return [ - prompt != null && prompt.length > 0 ? prompt : undefined, - prompt != null && prompt.length > 0 ? '' : undefined, // add a newline if prompt is not null - schemaPrefix, - schema != null ? JSON.stringify(schema) : undefined, - schemaSuffix, - ] - .filter(line => line != null) - .join('\n'); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/output-strategy.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/output-strategy.ts deleted file mode 100644 index ec26a94a0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/output-strategy.ts +++ /dev/null @@ -1,415 +0,0 @@ -import { - isJSONArray, - isJSONObject, - JSONObject, - JSONSchema7, - JSONValue, - TypeValidationError, - UnsupportedFunctionalityError, -} from '@ai-sdk/provider'; -import { - asSchema, - FlexibleSchema, - safeValidateTypes, - Schema, - ValidationResult, -} from '@ai-sdk/provider-utils'; -import { NoObjectGeneratedError } from '../error/no-object-generated-error'; -import { - FinishReason, - LanguageModelResponseMetadata, - LanguageModelUsage, -} from '../types'; -import { - AsyncIterableStream, - createAsyncIterableStream, -} from '../util/async-iterable-stream'; -import { DeepPartial } from '../util/deep-partial'; -import { ObjectStreamPart } from './stream-object-result'; - -export interface OutputStrategy { - readonly type: 'object' | 'array' | 'enum' | 'no-schema'; - - jsonSchema(): Promise; - - validatePartialResult({ - value, - textDelta, - isFinalDelta, - }: { - value: JSONValue; - textDelta: string; - isFirstDelta: boolean; - isFinalDelta: boolean; - latestObject: PARTIAL | undefined; - }): Promise< - ValidationResult<{ - partial: PARTIAL; - textDelta: string; - }> - >; - validateFinalResult( - value: JSONValue | undefined, - context: { - text: string; - response: LanguageModelResponseMetadata; - usage: LanguageModelUsage; - }, - ): Promise>; - - createElementStream( - originalStream: ReadableStream>, - ): ELEMENT_STREAM; -} - -const noSchemaOutputStrategy: OutputStrategy = { - type: 'no-schema', - jsonSchema: async () => undefined, - - async validatePartialResult({ value, textDelta }) { - return { success: true, value: { partial: value, textDelta } }; - }, - - async validateFinalResult( - value: JSONValue | undefined, - context: { - text: string; - response: LanguageModelResponseMetadata; - usage: LanguageModelUsage; - finishReason: FinishReason; - }, - ): Promise> { - return value === undefined - ? { - success: false, - error: new NoObjectGeneratedError({ - message: 'No object generated: response did not match schema.', - text: context.text, - response: context.response, - usage: context.usage, - finishReason: context.finishReason, - }), - } - : { success: true, value }; - }, - - createElementStream() { - throw new UnsupportedFunctionalityError({ - functionality: 'element streams in no-schema mode', - }); - }, -}; - -const objectOutputStrategy = ( - schema: Schema, -): OutputStrategy, OBJECT, never> => ({ - type: 'object', - jsonSchema: async () => await schema.jsonSchema, - - async validatePartialResult({ value, textDelta }) { - return { - success: true, - value: { - // Note: currently no validation of partial results: - partial: value as DeepPartial, - textDelta, - }, - }; - }, - - async validateFinalResult( - value: JSONValue | undefined, - ): Promise> { - return safeValidateTypes({ value, schema }); - }, - - createElementStream() { - throw new UnsupportedFunctionalityError({ - functionality: 'element streams in object mode', - }); - }, -}); - -const arrayOutputStrategy = ( - schema: Schema, -): OutputStrategy> => { - return { - type: 'array', - - // wrap in object that contains array of elements, since most LLMs will not - // be able to generate an array directly: - // possible future optimization: use arrays directly when model supports grammar-guided generation - jsonSchema: async () => { - // remove $schema from schema.jsonSchema: - const { $schema, ...itemSchema } = await schema.jsonSchema; - - return { - $schema: 'http://json-schema.org/draft-07/schema#', - type: 'object', - properties: { - elements: { type: 'array', items: itemSchema }, - }, - required: ['elements'], - additionalProperties: false, - }; - }, - - async validatePartialResult({ - value, - latestObject, - isFirstDelta, - isFinalDelta, - }) { - // check that the value is an object that contains an array of elements: - if (!isJSONObject(value) || !isJSONArray(value.elements)) { - return { - success: false, - error: new TypeValidationError({ - value, - cause: 'value must be an object that contains an array of elements', - }), - }; - } - - const inputArray = value.elements as Array; - const resultArray: Array = []; - - for (let i = 0; i < inputArray.length; i++) { - const element = inputArray[i]; - const result = await safeValidateTypes({ value: element, schema }); - - // special treatment for last processed element: - // ignore parse or validation failures, since they indicate that the - // last element is incomplete and should not be included in the result, - // unless it is the final delta - if (i === inputArray.length - 1 && !isFinalDelta) { - continue; - } - - if (!result.success) { - return result; - } - - resultArray.push(result.value); - } - - // calculate delta: - const publishedElementCount = latestObject?.length ?? 0; - - let textDelta = ''; - - if (isFirstDelta) { - textDelta += '['; - } - - if (publishedElementCount > 0) { - textDelta += ','; - } - - textDelta += resultArray - .slice(publishedElementCount) // only new elements - .map(element => JSON.stringify(element)) - .join(','); - - if (isFinalDelta) { - textDelta += ']'; - } - - return { - success: true, - value: { - partial: resultArray, - textDelta, - }, - }; - }, - - async validateFinalResult( - value: JSONValue | undefined, - ): Promise>> { - // check that the value is an object that contains an array of elements: - if (!isJSONObject(value) || !isJSONArray(value.elements)) { - return { - success: false, - error: new TypeValidationError({ - value, - cause: 'value must be an object that contains an array of elements', - }), - }; - } - - const inputArray = value.elements as Array; - - // check that each element in the array is of the correct type: - for (const element of inputArray) { - const result = await safeValidateTypes({ value: element, schema }); - if (!result.success) { - return result; - } - } - - return { success: true, value: inputArray as Array }; - }, - - createElementStream( - originalStream: ReadableStream>, - ) { - let publishedElements = 0; - - return createAsyncIterableStream( - originalStream.pipeThrough( - new TransformStream, ELEMENT>({ - transform(chunk, controller) { - switch (chunk.type) { - case 'object': { - const array = chunk.object; - - // publish new elements one by one: - for ( - ; - publishedElements < array.length; - publishedElements++ - ) { - controller.enqueue(array[publishedElements]); - } - - break; - } - - case 'text-delta': - case 'finish': - case 'error': // suppress error (use onError instead) - break; - - default: { - const _exhaustiveCheck: never = chunk; - throw new Error( - `Unsupported chunk type: ${_exhaustiveCheck}`, - ); - } - } - }, - }), - ), - ); - }, - }; -}; - -const enumOutputStrategy = ( - enumValues: Array, -): OutputStrategy => { - return { - type: 'enum', - - // wrap in object that contains result, since most LLMs will not - // be able to generate an enum value directly: - // possible future optimization: use enums directly when model supports top-level enums - jsonSchema: async () => ({ - $schema: 'http://json-schema.org/draft-07/schema#', - type: 'object', - properties: { - result: { type: 'string', enum: enumValues }, - }, - required: ['result'], - additionalProperties: false, - }), - - async validateFinalResult( - value: JSONValue | undefined, - ): Promise> { - // check that the value is an object that contains an array of elements: - if (!isJSONObject(value) || typeof value.result !== 'string') { - return { - success: false, - error: new TypeValidationError({ - value, - cause: - 'value must be an object that contains a string in the "result" property.', - }), - }; - } - - const result = value.result as string; - - return enumValues.includes(result as ENUM) - ? { success: true, value: result as ENUM } - : { - success: false, - error: new TypeValidationError({ - value, - cause: 'value must be a string in the enum', - }), - }; - }, - - async validatePartialResult({ value, textDelta }) { - if (!isJSONObject(value) || typeof value.result !== 'string') { - return { - success: false, - error: new TypeValidationError({ - value, - cause: - 'value must be an object that contains a string in the "result" property.', - }), - }; - } - - const result = value.result as string; - const possibleEnumValues = enumValues.filter(enumValue => - enumValue.startsWith(result), - ); - - if (value.result.length === 0 || possibleEnumValues.length === 0) { - return { - success: false, - error: new TypeValidationError({ - value, - cause: 'value must be a string in the enum', - }), - }; - } - - return { - success: true, - value: { - partial: - possibleEnumValues.length > 1 ? result : possibleEnumValues[0], - textDelta, - }, - }; - }, - - createElementStream() { - // no streaming in enum mode - throw new UnsupportedFunctionalityError({ - functionality: 'element streams in enum mode', - }); - }, - }; -}; - -export function getOutputStrategy({ - output, - schema, - enumValues, -}: { - output: 'object' | 'array' | 'enum' | 'no-schema'; - schema?: FlexibleSchema; - enumValues?: Array; -}): OutputStrategy { - switch (output) { - case 'object': - return objectOutputStrategy(asSchema(schema!)); - case 'array': - return arrayOutputStrategy(asSchema(schema!)); - case 'enum': - return enumOutputStrategy(enumValues! as Array); - case 'no-schema': - return noSchemaOutputStrategy; - default: { - const _exhaustiveCheck: never = output; - throw new Error(`Unsupported output: ${_exhaustiveCheck}`); - } - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/parse-and-validate-object-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/parse-and-validate-object-result.ts deleted file mode 100644 index 436026b95..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/parse-and-validate-object-result.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { JSONParseError, TypeValidationError } from '@ai-sdk/provider'; -import { safeParseJSON } from '@ai-sdk/provider-utils'; -import { NoObjectGeneratedError } from '../error/no-object-generated-error'; -import type { - FinishReason, - LanguageModelResponseMetadata, - LanguageModelUsage, -} from '../types'; -import type { OutputStrategy } from './output-strategy'; -import { RepairTextFunction } from './repair-text'; - -/** - * Parses and validates a result string by parsing it as JSON and validating against the output strategy. - * - * @param result - The result string to parse and validate - * @param outputStrategy - The output strategy containing validation logic - * @param context - Additional context for error reporting - * @returns The validated result - * @throws NoObjectGeneratedError if parsing or validation fails - */ -async function parseAndValidateObjectResult( - result: string, - outputStrategy: OutputStrategy, - context: { - response: LanguageModelResponseMetadata; - usage: LanguageModelUsage; - finishReason: FinishReason; - }, -): Promise { - const parseResult = await safeParseJSON({ text: result }); - - if (!parseResult.success) { - throw new NoObjectGeneratedError({ - message: 'No object generated: could not parse the response.', - cause: parseResult.error, - text: result, - response: context.response, - usage: context.usage, - finishReason: context.finishReason, - }); - } - - const validationResult = await outputStrategy.validateFinalResult( - parseResult.value, - { - text: result, - response: context.response, - usage: context.usage, - }, - ); - - if (!validationResult.success) { - throw new NoObjectGeneratedError({ - message: 'No object generated: response did not match schema.', - cause: validationResult.error, - text: result, - response: context.response, - usage: context.usage, - finishReason: context.finishReason, - }); - } - - return validationResult.value; -} - -/** - * Parses and validates a result string by parsing it as JSON and validating against the output strategy. - * If the result cannot be parsed, it attempts to repair the result using the repairText function. - * - * @param result - The result string to parse and validate - * @param outputStrategy - The output strategy containing validation logic - * @param repairText - A function that attempts to repair the result string - * @param context - Additional context for error reporting - * @returns The validated result - * @throws NoObjectGeneratedError if parsing or validation fails - */ -export async function parseAndValidateObjectResultWithRepair( - result: string, - outputStrategy: OutputStrategy, - repairText: RepairTextFunction | undefined, - context: { - response: LanguageModelResponseMetadata; - usage: LanguageModelUsage; - finishReason: FinishReason; - }, -): Promise { - try { - return await parseAndValidateObjectResult(result, outputStrategy, context); - } catch (error) { - if ( - repairText != null && - NoObjectGeneratedError.isInstance(error) && - (JSONParseError.isInstance(error.cause) || - TypeValidationError.isInstance(error.cause)) - ) { - const repairedText = await repairText({ - text: result, - error: error.cause, - }); - if (repairedText === null) { - throw error; - } - return await parseAndValidateObjectResult( - repairedText, - outputStrategy, - context, - ); - } - throw error; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/repair-text.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/repair-text.ts deleted file mode 100644 index 89186fd2a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/repair-text.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { JSONParseError, TypeValidationError } from '@ai-sdk/provider'; - -/** - * A function that attempts to repair the raw output of the model - * to enable JSON parsing. - * - * Should return the repaired text or null if the text cannot be repaired. - */ -export type RepairTextFunction = (options: { - text: string; - error: JSONParseError | TypeValidationError; -}) => Promise; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/stream-object-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/stream-object-result.ts deleted file mode 100644 index cf2fd29ec..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/stream-object-result.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { ServerResponse } from 'http'; -import { AsyncIterableStream } from '../util/async-iterable-stream'; -import { - CallWarning, - FinishReason, - LanguageModelRequestMetadata, - LanguageModelResponseMetadata, - ProviderMetadata, -} from '../types'; -import { LanguageModelUsage } from '../types/usage'; - -/** - * The result of a `streamObject` call that contains the partial object stream and additional information. - */ -export interface StreamObjectResult { - /** - * Warnings from the model provider (e.g. unsupported settings) - */ - readonly warnings: Promise; - - /** - * The token usage of the generated response. Resolved when the response is finished. - */ - readonly usage: Promise; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - readonly providerMetadata: Promise; - - /** - * Additional request information from the last step. - */ - readonly request: Promise; - - /** - * Additional response information. - */ - readonly response: Promise; - - /** - * The reason why the generation finished. Taken from the last step. - * - * Resolved when the response is finished. - */ - readonly finishReason: Promise; - - /** - * The generated object (typed according to the schema). Resolved when the response is finished. - */ - readonly object: Promise; - - /** - * Stream of partial objects. It gets more complete as the stream progresses. - * - * Note that the partial object is not validated. - * If you want to be certain that the actual content matches your schema, you need to implement your own validation for partial results. - */ - readonly partialObjectStream: AsyncIterableStream; - - /** - * Stream over complete array elements. Only available if the output strategy is set to `array`. - */ - readonly elementStream: ELEMENT_STREAM; - - /** - * Text stream of the JSON representation of the generated object. It contains text chunks. - * When the stream is finished, the object is valid JSON that can be parsed. - */ - readonly textStream: AsyncIterableStream; - - /** - * Stream of different types of events, including partial objects, errors, and finish events. - * Only errors that stop the stream, such as network errors, are thrown. - */ - readonly fullStream: AsyncIterableStream>; - - /** - * Writes text delta output to a Node.js response-like object. - * It sets a `Content-Type` header to `text/plain; charset=utf-8` and - * writes each text delta as a separate chunk. - * - * @param response A Node.js response-like object (ServerResponse). - * @param init Optional headers, status code, and status text. - */ - pipeTextStreamToResponse(response: ServerResponse, init?: ResponseInit): void; - - /** - * Creates a simple text stream response. - * The response has a `Content-Type` header set to `text/plain; charset=utf-8`. - * Each text delta is encoded as UTF-8 and sent as a separate chunk. - * Non-text-delta events are ignored. - * - * @param init Optional headers, status code, and status text. - */ - toTextStreamResponse(init?: ResponseInit): Response; -} - -export type ObjectStreamPart = - | { - type: 'object'; - object: PARTIAL; - } - | { - type: 'text-delta'; - textDelta: string; - } - | { - type: 'error'; - error: unknown; - } - | { - type: 'finish'; - finishReason: FinishReason; - usage: LanguageModelUsage; - response: LanguageModelResponseMetadata; - providerMetadata?: ProviderMetadata; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/stream-object.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/stream-object.ts deleted file mode 100644 index 41410c654..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/stream-object.ts +++ /dev/null @@ -1,984 +0,0 @@ -import { - JSONValue, - LanguageModelV3FinishReason, - LanguageModelV3StreamPart, - LanguageModelV3Usage, - SharedV3ProviderMetadata, - SharedV3Warning, -} from '@ai-sdk/provider'; -import { - createIdGenerator, - DelayedPromise, - FlexibleSchema, - ProviderOptions, - type InferSchema, -} from '@ai-sdk/provider-utils'; -import { ServerResponse } from 'http'; -import { logWarnings } from '../logger/log-warnings'; -import { resolveLanguageModel } from '../model/resolve-model'; -import { CallSettings } from '../prompt/call-settings'; -import { convertToLanguageModelPrompt } from '../prompt/convert-to-language-model-prompt'; -import { prepareCallSettings } from '../prompt/prepare-call-settings'; -import { Prompt } from '../prompt/prompt'; -import { standardizePrompt } from '../prompt/standardize-prompt'; -import { wrapGatewayError } from '../prompt/wrap-gateway-error'; -import { assembleOperationName } from '../telemetry/assemble-operation-name'; -import { getBaseTelemetryAttributes } from '../telemetry/get-base-telemetry-attributes'; -import { getTracer } from '../telemetry/get-tracer'; -import { recordSpan } from '../telemetry/record-span'; -import { selectTelemetryAttributes } from '../telemetry/select-telemetry-attributes'; -import { stringifyForTelemetry } from '../telemetry/stringify-for-telemetry'; -import { TelemetrySettings } from '../telemetry/telemetry-settings'; -import { createTextStreamResponse } from '../text-stream/create-text-stream-response'; -import { pipeTextStreamToResponse } from '../text-stream/pipe-text-stream-to-response'; -import { - CallWarning, - FinishReason, - LanguageModel, -} from '../types/language-model'; -import { LanguageModelRequestMetadata } from '../types/language-model-request-metadata'; -import { LanguageModelResponseMetadata } from '../types/language-model-response-metadata'; -import { ProviderMetadata } from '../types/provider-metadata'; -import { - asLanguageModelUsage, - createNullLanguageModelUsage, - LanguageModelUsage, -} from '../types/usage'; -import { DeepPartial, isDeepEqualData, parsePartialJson } from '../util'; -import { - AsyncIterableStream, - createAsyncIterableStream, -} from '../util/async-iterable-stream'; -import { createStitchableStream } from '../util/create-stitchable-stream'; -import { DownloadFunction } from '../util/download/download-function'; -import { now as originalNow } from '../util/now'; -import { prepareRetries } from '../util/prepare-retries'; -import { getOutputStrategy, OutputStrategy } from './output-strategy'; -import { parseAndValidateObjectResultWithRepair } from './parse-and-validate-object-result'; -import { RepairTextFunction } from './repair-text'; -import { ObjectStreamPart, StreamObjectResult } from './stream-object-result'; -import { validateObjectGenerationInput } from './validate-object-generation-input'; - -const originalGenerateId = createIdGenerator({ prefix: 'aiobj', size: 24 }); - -/** - * Callback that is set using the `onError` option. - * - * @param event - The event that is passed to the callback. - */ -export type StreamObjectOnErrorCallback = (event: { - error: unknown; -}) => Promise | void; - -/** - * Callback that is set using the `onFinish` option. - * - * @param event - The event that is passed to the callback. - */ -export type StreamObjectOnFinishCallback = (event: { - /** - * The token usage of the generated response. - */ - usage: LanguageModelUsage; - - /** - * The generated object. Can be undefined if the final object does not match the schema. - */ - object: RESULT | undefined; - - /** - * Optional error object. This is e.g. a TypeValidationError when the final object does not match the schema. - */ - error: unknown | undefined; - - /** - * Response metadata. - */ - response: LanguageModelResponseMetadata; - - /** - * Warnings from the model provider (e.g. unsupported settings). - */ - warnings?: CallWarning[]; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerMetadata: ProviderMetadata | undefined; -}) => Promise | void; - -/** - * Generate a structured, typed object for a given prompt and schema using a language model. - * - * This function streams the output. If you do not want to stream the output, use `generateObject` instead. - * - * @param model - The language model to use. - * - * @param system - A system message that will be part of the prompt. - * @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both. - * @param messages - A list of messages. You can either use `prompt` or `messages` but not both. - * - * @param maxOutputTokens - Maximum number of tokens to generate. - * @param temperature - Temperature setting. - * The value is passed through to the provider. The range depends on the provider and model. - * It is recommended to set either `temperature` or `topP`, but not both. - * @param topP - Nucleus sampling. - * The value is passed through to the provider. The range depends on the provider and model. - * It is recommended to set either `temperature` or `topP`, but not both. - * @param topK - Only sample from the top K options for each subsequent token. - * Used to remove "long tail" low probability responses. - * Recommended for advanced use cases only. You usually only need to use temperature. - * @param presencePenalty - Presence penalty setting. - * It affects the likelihood of the model to repeat information that is already in the prompt. - * The value is passed through to the provider. The range depends on the provider and model. - * @param frequencyPenalty - Frequency penalty setting. - * It affects the likelihood of the model to repeatedly use the same words or phrases. - * The value is passed through to the provider. The range depends on the provider and model. - * @param stopSequences - Stop sequences. - * If set, the model will stop generating text when one of the stop sequences is generated. - * @param seed - The seed (integer) to use for random sampling. - * If set and supported by the model, calls will generate deterministic results. - * - * @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2. - * @param abortSignal - An optional abort signal that can be used to cancel the call. - * @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers. - * - * @param schema - The schema of the object that the model should generate. - * @param schemaName - Optional name of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. - * via tool or schema name. - * @param schemaDescription - Optional description of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. - * via tool or schema description. - * - * @param output - The type of the output. - * - * - 'object': The output is an object. - * - 'array': The output is an array. - * - 'enum': The output is an enum. - * - 'no-schema': The output is not a schema. - * - * @param experimental_telemetry - Optional telemetry configuration (experimental). - * - * @param providerOptions - Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - * - * @returns - * A result object for accessing the partial object stream and additional information. - * - * @deprecated Use `streamText` with an `output` setting instead. - */ -export function streamObject< - SCHEMA extends FlexibleSchema = FlexibleSchema, - OUTPUT extends 'object' | 'array' | 'enum' | 'no-schema' = - InferSchema extends string ? 'enum' : 'object', - RESULT = OUTPUT extends 'array' - ? Array> - : InferSchema, ->( - options: Omit & - Prompt & - (OUTPUT extends 'enum' - ? { - /** - * The enum values that the model should use. - */ - enum: Array; - output: 'enum'; - } - : OUTPUT extends 'no-schema' - ? {} - : { - /** - * The schema of the object that the model should generate. - */ - schema: SCHEMA; - - /** - * Optional name of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. - * via tool or schema name. - */ - schemaName?: string; - - /** - * Optional description of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. - * via tool or schema description. - */ - schemaDescription?: string; - }) & { - output?: OUTPUT; - - /** - * The language model to use. - */ - model: LanguageModel; - - /** - * A function that attempts to repair the raw output of the model - * to enable JSON parsing. - */ - experimental_repairText?: RepairTextFunction; - - /** - * Optional telemetry configuration (experimental). - */ - - experimental_telemetry?: TelemetrySettings; - - /** - * Custom download function to use for URLs. - * - * By default, files are downloaded if the model does not support the URL for the given media type. - */ - experimental_download?: DownloadFunction | undefined; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; - - /** - * Callback that is invoked when an error occurs during streaming. - * You can use it to log errors. - * The stream processing will pause until the callback promise is resolved. - */ - onError?: StreamObjectOnErrorCallback; - - /** - * Callback that is called when the LLM response and the final object validation are finished. - */ - onFinish?: StreamObjectOnFinishCallback; - - /** - * Internal. For test use only. May change without notice. - */ - _internal?: { - generateId?: () => string; - currentDate?: () => Date; - now?: () => number; - }; - }, -): StreamObjectResult< - OUTPUT extends 'enum' - ? string - : OUTPUT extends 'array' - ? RESULT - : DeepPartial, - OUTPUT extends 'array' ? RESULT : RESULT, - OUTPUT extends 'array' - ? RESULT extends Array - ? AsyncIterableStream - : never - : never -> { - const { - model, - output = 'object', - system, - prompt, - messages, - maxRetries, - abortSignal, - headers, - experimental_repairText: repairText, - experimental_telemetry: telemetry, - experimental_download: download, - providerOptions, - onError = ({ error }: { error: unknown }) => { - console.error(error); - }, - onFinish, - _internal: { - generateId = originalGenerateId, - currentDate = () => new Date(), - now = originalNow, - } = {}, - ...settings - } = options; - - const enumValues = - 'enum' in options && options.enum ? options.enum : undefined; - - const { - schema: inputSchema, - schemaDescription, - schemaName, - } = 'schema' in options ? options : {}; - - validateObjectGenerationInput({ - output, - schema: inputSchema, - schemaName, - schemaDescription, - enumValues, - }); - - const outputStrategy = getOutputStrategy({ - output, - schema: inputSchema, - enumValues, - }); - - return new DefaultStreamObjectResult({ - model, - telemetry, - headers, - settings, - maxRetries, - abortSignal, - outputStrategy, - system, - prompt, - messages, - schemaName, - schemaDescription, - providerOptions, - repairText, - onError, - onFinish, - download, - generateId, - currentDate, - now, - }); -} - -class DefaultStreamObjectResult< - PARTIAL, - RESULT, - ELEMENT_STREAM, -> implements StreamObjectResult { - private readonly _object = new DelayedPromise(); - private readonly _usage = new DelayedPromise(); - private readonly _providerMetadata = new DelayedPromise< - ProviderMetadata | undefined - >(); - private readonly _warnings = new DelayedPromise(); - private readonly _request = - new DelayedPromise(); - private readonly _response = - new DelayedPromise(); - private readonly _finishReason = new DelayedPromise(); - - private readonly baseStream: ReadableStream>; - - private readonly outputStrategy: OutputStrategy< - PARTIAL, - RESULT, - ELEMENT_STREAM - >; - - constructor({ - model: modelArg, - headers, - telemetry, - settings, - maxRetries: maxRetriesArg, - abortSignal, - outputStrategy, - system, - prompt, - messages, - schemaName, - schemaDescription, - providerOptions, - repairText, - onError, - onFinish, - download, - generateId, - currentDate, - now, - }: { - model: LanguageModel; - telemetry: TelemetrySettings | undefined; - headers: Record | undefined; - settings: Omit; - maxRetries: number | undefined; - abortSignal: AbortSignal | undefined; - outputStrategy: OutputStrategy; - system: Prompt['system']; - prompt: Prompt['prompt']; - messages: Prompt['messages']; - schemaName: string | undefined; - schemaDescription: string | undefined; - providerOptions: ProviderOptions | undefined; - repairText: RepairTextFunction | undefined; - onError: StreamObjectOnErrorCallback; - onFinish: StreamObjectOnFinishCallback | undefined; - download: DownloadFunction | undefined; - generateId: () => string; - currentDate: () => Date; - now: () => number; - }) { - const model = resolveLanguageModel(modelArg); - - const { maxRetries, retry } = prepareRetries({ - maxRetries: maxRetriesArg, - abortSignal, - }); - - const callSettings = prepareCallSettings(settings); - - const baseTelemetryAttributes = getBaseTelemetryAttributes({ - model, - telemetry, - headers, - settings: { ...callSettings, maxRetries }, - }); - - const tracer = getTracer(telemetry); - const self = this; - - const stitchableStream = - createStitchableStream>(); - - const eventProcessor = new TransformStream< - ObjectStreamPart, - ObjectStreamPart - >({ - transform(chunk, controller) { - controller.enqueue(chunk); - - if (chunk.type === 'error') { - onError({ error: wrapGatewayError(chunk.error) }); - } - }, - }); - - this.baseStream = stitchableStream.stream.pipeThrough(eventProcessor); - - recordSpan({ - name: 'ai.streamObject', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ - operationId: 'ai.streamObject', - telemetry, - }), - ...baseTelemetryAttributes, - // specific settings that only make sense on the outer level: - 'ai.prompt': { - input: () => JSON.stringify({ system, prompt, messages }), - }, - 'ai.schema': { - input: async () => - JSON.stringify(await outputStrategy.jsonSchema()), - }, - 'ai.schema.name': schemaName, - 'ai.schema.description': schemaDescription, - 'ai.settings.output': outputStrategy.type, - }, - }), - tracer, - endWhenDone: false, - fn: async rootSpan => { - const standardizedPrompt = await standardizePrompt({ - system, - prompt, - messages, - } as Prompt); - - const callOptions = { - responseFormat: { - type: 'json' as const, - schema: await outputStrategy.jsonSchema(), - name: schemaName, - description: schemaDescription, - }, - ...prepareCallSettings(settings), - prompt: await convertToLanguageModelPrompt({ - prompt: standardizedPrompt, - supportedUrls: await model.supportedUrls, - download, - }), - providerOptions, - abortSignal, - headers, - includeRawChunks: false, - }; - - const transformer: Transformer< - LanguageModelV3StreamPart, - ObjectStreamInputPart - > = { - transform: (chunk, controller) => { - switch (chunk.type) { - case 'text-delta': - controller.enqueue(chunk.delta); - break; - case 'response-metadata': - case 'finish': - case 'error': - case 'stream-start': - controller.enqueue(chunk); - break; - } - }, - }; - - const { - result: { stream, response, request }, - doStreamSpan, - startTimestampMs, - } = await retry(() => - recordSpan({ - name: 'ai.streamObject.doStream', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ - operationId: 'ai.streamObject.doStream', - telemetry, - }), - ...baseTelemetryAttributes, - 'ai.prompt.messages': { - input: () => stringifyForTelemetry(callOptions.prompt), - }, - - // standardized gen-ai llm span attributes: - 'gen_ai.system': model.provider, - 'gen_ai.request.model': model.modelId, - 'gen_ai.request.frequency_penalty': - callSettings.frequencyPenalty, - 'gen_ai.request.max_tokens': callSettings.maxOutputTokens, - 'gen_ai.request.presence_penalty': callSettings.presencePenalty, - 'gen_ai.request.temperature': callSettings.temperature, - 'gen_ai.request.top_k': callSettings.topK, - 'gen_ai.request.top_p': callSettings.topP, - }, - }), - tracer, - endWhenDone: false, - fn: async doStreamSpan => ({ - startTimestampMs: now(), - doStreamSpan, - result: await model.doStream(callOptions), - }), - }), - ); - - self._request.resolve(request ?? {}); - - // store information for onFinish callback: - let warnings: SharedV3Warning[] | undefined; - let usage: LanguageModelUsage = createNullLanguageModelUsage(); - let finishReason: FinishReason | undefined; - let providerMetadata: ProviderMetadata | undefined; - let object: RESULT | undefined; - let error: unknown | undefined; - - // pipe chunks through a transformation stream that extracts metadata: - let accumulatedText = ''; - let textDelta = ''; - let fullResponse: { - id: string; - timestamp: Date; - modelId: string; - } = { - id: generateId(), - timestamp: currentDate(), - modelId: model.modelId, - }; - - // Keep track of raw parse result before type validation, since e.g. Zod might - // change the object by mapping properties. - let latestObjectJson: JSONValue | undefined = undefined; - let latestObject: PARTIAL | undefined = undefined; - let isFirstChunk = true; - let isFirstDelta = true; - - const transformedStream = stream - .pipeThrough(new TransformStream(transformer)) - .pipeThrough( - new TransformStream< - string | ObjectStreamInputPart, - ObjectStreamPart - >({ - async transform(chunk, controller): Promise { - if ( - typeof chunk === 'object' && - chunk.type === 'stream-start' - ) { - warnings = chunk.warnings; - return; // stream start chunks are sent immediately and do not count as first chunk - } - - // Telemetry event for first chunk: - if (isFirstChunk) { - const msToFirstChunk = now() - startTimestampMs; - - isFirstChunk = false; - - doStreamSpan.addEvent('ai.stream.firstChunk', { - 'ai.stream.msToFirstChunk': msToFirstChunk, - }); - - doStreamSpan.setAttributes({ - 'ai.stream.msToFirstChunk': msToFirstChunk, - }); - } - - // process partial text chunks - if (typeof chunk === 'string') { - accumulatedText += chunk; - textDelta += chunk; - - const { value: currentObjectJson, state: parseState } = - await parsePartialJson(accumulatedText); - - if ( - currentObjectJson !== undefined && - !isDeepEqualData(latestObjectJson, currentObjectJson) - ) { - const validationResult = - await outputStrategy.validatePartialResult({ - value: currentObjectJson, - textDelta, - latestObject, - isFirstDelta, - isFinalDelta: parseState === 'successful-parse', - }); - - if ( - validationResult.success && - !isDeepEqualData( - latestObject, - validationResult.value.partial, - ) - ) { - // inside inner check to correctly parse the final element in array mode: - latestObjectJson = currentObjectJson; - latestObject = validationResult.value.partial; - - controller.enqueue({ - type: 'object', - object: latestObject, - }); - - controller.enqueue({ - type: 'text-delta', - textDelta: validationResult.value.textDelta, - }); - - textDelta = ''; - isFirstDelta = false; - } - } - - return; - } - - switch (chunk.type) { - case 'response-metadata': { - fullResponse = { - id: chunk.id ?? fullResponse.id, - timestamp: chunk.timestamp ?? fullResponse.timestamp, - modelId: chunk.modelId ?? fullResponse.modelId, - }; - break; - } - - case 'finish': { - // send final text delta: - if (textDelta !== '') { - controller.enqueue({ type: 'text-delta', textDelta }); - } - - // store finish reason for telemetry: - finishReason = chunk.finishReason.unified; - - // store usage and metadata for promises and onFinish callback: - usage = asLanguageModelUsage(chunk.usage); - providerMetadata = chunk.providerMetadata; - - controller.enqueue({ - ...chunk, - finishReason: chunk.finishReason.unified, - usage, - response: fullResponse, - }); - - // log warnings: - logWarnings({ - warnings: warnings ?? [], - provider: model.provider, - model: model.modelId, - }); - - // resolve promises that can be resolved now: - self._usage.resolve(usage); - self._providerMetadata.resolve(providerMetadata); - self._warnings.resolve(warnings); - self._response.resolve({ - ...fullResponse, - headers: response?.headers, - }); - self._finishReason.resolve(finishReason ?? 'other'); - - try { - object = await parseAndValidateObjectResultWithRepair( - accumulatedText, - outputStrategy, - repairText, - { - response: fullResponse, - usage, - finishReason, - }, - ); - self._object.resolve(object); - } catch (e) { - error = e; - self._object.reject(e); - } - break; - } - - default: { - controller.enqueue(chunk); - break; - } - } - }, - - // invoke onFinish callback and resolve toolResults promise when the stream is about to close: - async flush(controller) { - try { - const finalUsage = usage ?? { - promptTokens: NaN, - completionTokens: NaN, - totalTokens: NaN, - }; - - doStreamSpan.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.response.finishReason': finishReason, - 'ai.response.object': { - output: () => JSON.stringify(object), - }, - 'ai.response.id': fullResponse.id, - 'ai.response.model': fullResponse.modelId, - 'ai.response.timestamp': - fullResponse.timestamp.toISOString(), - 'ai.response.providerMetadata': - JSON.stringify(providerMetadata), - - 'ai.usage.inputTokens': finalUsage.inputTokens, - 'ai.usage.outputTokens': finalUsage.outputTokens, - 'ai.usage.totalTokens': finalUsage.totalTokens, - 'ai.usage.reasoningTokens': finalUsage.reasoningTokens, - 'ai.usage.cachedInputTokens': - finalUsage.cachedInputTokens, - - // standardized gen-ai llm span attributes: - 'gen_ai.response.finish_reasons': [finishReason], - 'gen_ai.response.id': fullResponse.id, - 'gen_ai.response.model': fullResponse.modelId, - 'gen_ai.usage.input_tokens': finalUsage.inputTokens, - 'gen_ai.usage.output_tokens': finalUsage.outputTokens, - }, - }), - ); - - // finish doStreamSpan before other operations for correct timing: - doStreamSpan.end(); - - // Add response information to the root span: - rootSpan.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.usage.inputTokens': finalUsage.inputTokens, - 'ai.usage.outputTokens': finalUsage.outputTokens, - 'ai.usage.totalTokens': finalUsage.totalTokens, - 'ai.usage.reasoningTokens': finalUsage.reasoningTokens, - 'ai.usage.cachedInputTokens': - finalUsage.cachedInputTokens, - 'ai.response.object': { - output: () => JSON.stringify(object), - }, - 'ai.response.providerMetadata': - JSON.stringify(providerMetadata), - }, - }), - ); - - // call onFinish callback: - await onFinish?.({ - usage: finalUsage, - object, - error, - response: { - ...fullResponse, - headers: response?.headers, - }, - warnings, - providerMetadata, - }); - } catch (error) { - controller.enqueue({ type: 'error', error }); - } finally { - rootSpan.end(); - } - }, - }), - ); - - stitchableStream.addStream(transformedStream); - }, - }) - .catch(error => { - // add an empty stream with an error to break the stream: - stitchableStream.addStream( - new ReadableStream({ - start(controller) { - controller.enqueue({ type: 'error', error }); - controller.close(); - }, - }), - ); - }) - .finally(() => { - stitchableStream.close(); - }); - - this.outputStrategy = outputStrategy; - } - - get object() { - return this._object.promise; - } - - get usage() { - return this._usage.promise; - } - - get providerMetadata() { - return this._providerMetadata.promise; - } - - get warnings() { - return this._warnings.promise; - } - - get request() { - return this._request.promise; - } - - get response() { - return this._response.promise; - } - - get finishReason() { - return this._finishReason.promise; - } - - get partialObjectStream(): AsyncIterableStream { - return createAsyncIterableStream( - this.baseStream.pipeThrough( - new TransformStream, PARTIAL>({ - transform(chunk, controller) { - switch (chunk.type) { - case 'object': - controller.enqueue(chunk.object); - break; - - case 'text-delta': - case 'finish': - case 'error': // suppress error (use onError instead) - break; - - default: { - const _exhaustiveCheck: never = chunk; - throw new Error(`Unsupported chunk type: ${_exhaustiveCheck}`); - } - } - }, - }), - ), - ); - } - - get elementStream(): ELEMENT_STREAM { - return this.outputStrategy.createElementStream(this.baseStream); - } - - get textStream(): AsyncIterableStream { - return createAsyncIterableStream( - this.baseStream.pipeThrough( - new TransformStream, string>({ - transform(chunk, controller) { - switch (chunk.type) { - case 'text-delta': - controller.enqueue(chunk.textDelta); - break; - - case 'object': - case 'finish': - case 'error': // suppress error (use onError instead) - break; - - default: { - const _exhaustiveCheck: never = chunk; - throw new Error(`Unsupported chunk type: ${_exhaustiveCheck}`); - } - } - }, - }), - ), - ); - } - - get fullStream(): AsyncIterableStream> { - return createAsyncIterableStream(this.baseStream); - } - - pipeTextStreamToResponse(response: ServerResponse, init?: ResponseInit) { - pipeTextStreamToResponse({ - response, - textStream: this.textStream, - ...init, - }); - } - - toTextStreamResponse(init?: ResponseInit): Response { - return createTextStreamResponse({ - textStream: this.textStream, - ...init, - }); - } -} - -export type ObjectStreamInputPart = - | string - | { - type: 'stream-start'; - warnings: SharedV3Warning[]; - } - | { - type: 'error'; - error: unknown; - } - | { - type: 'response-metadata'; - id?: string; - timestamp?: Date; - modelId?: string; - } - | { - type: 'finish'; - finishReason: LanguageModelV3FinishReason; - usage: LanguageModelV3Usage; - providerMetadata?: SharedV3ProviderMetadata; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/validate-object-generation-input.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/validate-object-generation-input.ts deleted file mode 100644 index ea550bfa7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-object/validate-object-generation-input.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { FlexibleSchema } from '@ai-sdk/provider-utils'; -import { InvalidArgumentError } from '../error/invalid-argument-error'; - -export function validateObjectGenerationInput({ - output, - schema, - schemaName, - schemaDescription, - enumValues, -}: { - output?: 'object' | 'array' | 'enum' | 'no-schema'; - schema?: FlexibleSchema; - schemaName?: string; - schemaDescription?: string; - enumValues?: Array; -}) { - if ( - output != null && - output !== 'object' && - output !== 'array' && - output !== 'enum' && - output !== 'no-schema' - ) { - throw new InvalidArgumentError({ - parameter: 'output', - value: output, - message: 'Invalid output type.', - }); - } - - if (output === 'no-schema') { - if (schema != null) { - throw new InvalidArgumentError({ - parameter: 'schema', - value: schema, - message: 'Schema is not supported for no-schema output.', - }); - } - - if (schemaDescription != null) { - throw new InvalidArgumentError({ - parameter: 'schemaDescription', - value: schemaDescription, - message: 'Schema description is not supported for no-schema output.', - }); - } - - if (schemaName != null) { - throw new InvalidArgumentError({ - parameter: 'schemaName', - value: schemaName, - message: 'Schema name is not supported for no-schema output.', - }); - } - - if (enumValues != null) { - throw new InvalidArgumentError({ - parameter: 'enumValues', - value: enumValues, - message: 'Enum values are not supported for no-schema output.', - }); - } - } - - if (output === 'object') { - if (schema == null) { - throw new InvalidArgumentError({ - parameter: 'schema', - value: schema, - message: 'Schema is required for object output.', - }); - } - - if (enumValues != null) { - throw new InvalidArgumentError({ - parameter: 'enumValues', - value: enumValues, - message: 'Enum values are not supported for object output.', - }); - } - } - - if (output === 'array') { - if (schema == null) { - throw new InvalidArgumentError({ - parameter: 'schema', - value: schema, - message: 'Element schema is required for array output.', - }); - } - - if (enumValues != null) { - throw new InvalidArgumentError({ - parameter: 'enumValues', - value: enumValues, - message: 'Enum values are not supported for array output.', - }); - } - } - - if (output === 'enum') { - if (schema != null) { - throw new InvalidArgumentError({ - parameter: 'schema', - value: schema, - message: 'Schema is not supported for enum output.', - }); - } - - if (schemaDescription != null) { - throw new InvalidArgumentError({ - parameter: 'schemaDescription', - value: schemaDescription, - message: 'Schema description is not supported for enum output.', - }); - } - - if (schemaName != null) { - throw new InvalidArgumentError({ - parameter: 'schemaName', - value: schemaName, - message: 'Schema name is not supported for enum output.', - }); - } - - if (enumValues == null) { - throw new InvalidArgumentError({ - parameter: 'enumValues', - value: enumValues, - message: 'Enum values are required for enum output.', - }); - } - - for (const value of enumValues) { - if (typeof value !== 'string') { - throw new InvalidArgumentError({ - parameter: 'enumValues', - value, - message: 'Enum values must be strings.', - }); - } - } - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-speech/generate-speech-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-speech/generate-speech-result.ts deleted file mode 100644 index ab855c8ba..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-speech/generate-speech-result.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { JSONObject } from '@ai-sdk/provider'; -import { SpeechModelResponseMetadata } from '../types/speech-model-response-metadata'; -import { Warning } from '../types/warning'; -import { GeneratedAudioFile } from './generated-audio-file'; - -/** - * The result of a `generateSpeech` call. - * It contains the audio data and additional information. - */ -export interface SpeechResult { - /** - * The generated audio file with the audio data. - */ - readonly audio: GeneratedAudioFile; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - readonly warnings: Array; - - /** - * Response metadata from the provider. There may be multiple responses if we made multiple calls to the model. - */ - readonly responses: Array; - - /** - * Provider metadata from the provider. - */ - readonly providerMetadata: Record; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-speech/generate-speech.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-speech/generate-speech.ts deleted file mode 100644 index e91872307..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-speech/generate-speech.ts +++ /dev/null @@ -1,191 +0,0 @@ -import { JSONObject } from '@ai-sdk/provider'; -import { ProviderOptions, withUserAgentSuffix } from '@ai-sdk/provider-utils'; -import { NoSpeechGeneratedError } from '../error/no-speech-generated-error'; -import { logWarnings } from '../logger/log-warnings'; -import { resolveSpeechModel } from '../model/resolve-model'; -import { SpeechModel } from '../types/speech-model'; -import { SpeechModelResponseMetadata } from '../types/speech-model-response-metadata'; -import { Warning } from '../types/warning'; -import { - audioMediaTypeSignatures, - detectMediaType, -} from '../util/detect-media-type'; -import { prepareRetries } from '../util/prepare-retries'; -import { VERSION } from '../version'; -import { SpeechResult } from './generate-speech-result'; -import { - DefaultGeneratedAudioFile, - GeneratedAudioFile, -} from './generated-audio-file'; - -/** - * Generates speech audio using a speech model. - * - * @param model - The speech model to use. - * @param text - The text to convert to speech. - * @param voice - The voice to use for speech generation. - * @param outputFormat - The output format to use for speech generation e.g. "mp3", "wav", etc. - * @param instructions - Instructions for the speech generation e.g. "Speak in a slow and steady tone". - * @param speed - The speed of the speech generation. - * @param language - The language for speech generation (ISO 639-1 code e.g. "en", "es", "fr") or "auto" for automatic detection. - * @param providerOptions - Additional provider-specific options that are passed through to the provider - * as body parameters. - * @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2. - * @param abortSignal - An optional abort signal that can be used to cancel the call. - * @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers. - * - * @returns A result object that contains the generated audio data. - */ -export async function generateSpeech({ - model, - text, - voice, - outputFormat, - instructions, - speed, - language, - providerOptions = {}, - maxRetries: maxRetriesArg, - abortSignal, - headers, -}: { - /** - * The speech model to use. - */ - model: SpeechModel; - - /** - * The text to convert to speech. - */ - text: string; - - /** - * The voice to use for speech generation. - */ - voice?: string; - - /** - * The desired output format for the audio e.g. "mp3", "wav", etc. - */ - outputFormat?: 'mp3' | 'wav' | (string & {}); - - /** - * Instructions for the speech generation e.g. "Speak in a slow and steady tone". - */ - instructions?: string; - - /** - * The speed of the speech generation. - */ - speed?: number; - - /** - * The language for speech generation. This should be an ISO 639-1 language code (e.g. "en", "es", "fr") - * or "auto" for automatic language detection. Provider support varies. - */ - language?: string; - - /** - * Additional provider-specific options that are passed through to the provider - * as body parameters. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * ```ts - * { - * "openai": {} - * } - * ``` - */ - providerOptions?: ProviderOptions; - - /** - * Maximum number of retries per speech model call. Set to 0 to disable retries. - * - * @default 2 - */ - maxRetries?: number; - - /** - * Abort signal. - */ - abortSignal?: AbortSignal; - - /** - * Additional headers to include in the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; -}): Promise { - const resolvedModel = resolveSpeechModel(model); - if (!resolvedModel) { - throw new Error('Model could not be resolved'); - } - - const headersWithUserAgent = withUserAgentSuffix( - headers ?? {}, - `ai/${VERSION}`, - ); - - const { retry } = prepareRetries({ - maxRetries: maxRetriesArg, - abortSignal, - }); - - const result = await retry(() => - resolvedModel.doGenerate({ - text, - voice, - outputFormat, - instructions, - speed, - language, - abortSignal, - headers: headersWithUserAgent, - providerOptions, - }), - ); - - if (!result.audio || result.audio.length === 0) { - throw new NoSpeechGeneratedError({ responses: [result.response] }); - } - - logWarnings({ - warnings: result.warnings, - provider: resolvedModel.provider, - model: resolvedModel.modelId, - }); - - return new DefaultSpeechResult({ - audio: new DefaultGeneratedAudioFile({ - data: result.audio, - mediaType: - detectMediaType({ - data: result.audio, - signatures: audioMediaTypeSignatures, - }) ?? 'audio/mp3', - }), - warnings: result.warnings, - responses: [result.response], - providerMetadata: result.providerMetadata, - }); -} - -class DefaultSpeechResult implements SpeechResult { - readonly audio: GeneratedAudioFile; - readonly warnings: Array; - readonly responses: Array; - readonly providerMetadata: Record; - - constructor(options: { - audio: GeneratedAudioFile; - warnings: Array; - responses: Array; - providerMetadata: Record | undefined; - }) { - this.audio = options.audio; - this.warnings = options.warnings; - this.responses = options.responses; - this.providerMetadata = options.providerMetadata ?? {}; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-speech/generated-audio-file.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-speech/generated-audio-file.ts deleted file mode 100644 index ce04c9bdb..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-speech/generated-audio-file.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { - GeneratedFile, - DefaultGeneratedFile, -} from '../generate-text/generated-file'; - -/** - * A generated audio file. - */ -export interface GeneratedAudioFile extends GeneratedFile { - /** - * Audio format of the file (e.g., 'mp3', 'wav', etc.) - */ - readonly format: string; -} - -export class DefaultGeneratedAudioFile - extends DefaultGeneratedFile - implements GeneratedAudioFile -{ - readonly format: string; - - constructor({ - data, - mediaType, - }: { - data: string | Uint8Array; - mediaType: string; - }) { - super({ data, mediaType }); - let format = 'mp3'; - - // If format is not provided, try to determine it from the media type - if (mediaType) { - const mediaTypeParts = mediaType.split('/'); - - if (mediaTypeParts.length === 2) { - // Handle special cases for audio formats - if (mediaType !== 'audio/mpeg') { - format = mediaTypeParts[1]; - } - } - } - - if (!format) { - // TODO this should be an AI SDK error - throw new Error( - 'Audio format must be provided or determinable from media type', - ); - } - - this.format = format; - } -} - -export class DefaultGeneratedAudioFileWithType extends DefaultGeneratedAudioFile { - readonly type = 'audio'; - - constructor(options: { - data: string | Uint8Array; - mediaType: string; - format: string; - }) { - super(options); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-speech/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-speech/index.ts deleted file mode 100644 index 21d906f91..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-speech/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { generateSpeech as experimental_generateSpeech } from './generate-speech'; -export type { SpeechResult as Experimental_SpeechResult } from './generate-speech-result'; -export type { GeneratedAudioFile } from './generated-audio-file'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/callback-events.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/callback-events.ts deleted file mode 100644 index ed55ae5dc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/callback-events.ts +++ /dev/null @@ -1,332 +0,0 @@ -import type { LanguageModelV3ToolChoice } from '@ai-sdk/provider'; -import type { - ModelMessage, - ProviderOptions, - SystemModelMessage, -} from '@ai-sdk/provider-utils'; -import type { TimeoutConfiguration } from '../prompt/call-settings'; -import type { ToolChoice } from '../types/language-model'; -import type { LanguageModelUsage } from '../types/usage'; -import type { Output } from './output'; -import type { StepResult } from './step-result'; -import type { StopCondition } from './stop-condition'; -import type { TypedToolCall } from './tool-call'; -import type { ToolSet } from './tool-set'; - -/** - * Common model information used across callback events. - */ -export interface CallbackModelInfo { - /** The provider identifier (e.g., 'openai', 'anthropic'). */ - readonly provider: string; - /** The specific model identifier (e.g., 'gpt-4o'). */ - readonly modelId: string; -} - -/** - * Event passed to the `onStart` callback. - * - * Called when the generation operation begins, before any LLM calls. - */ -export interface OnStartEvent< - TOOLS extends ToolSet = ToolSet, - OUTPUT extends Output = Output, - INCLUDE = { requestBody?: boolean; responseBody?: boolean }, -> { - /** The model being used for generation. */ - readonly model: CallbackModelInfo; - - /** The system message(s) provided to the model. */ - readonly system: - | string - | SystemModelMessage - | Array - | undefined; - - /** The prompt string or array of messages if using the prompt option. */ - readonly prompt: string | Array | undefined; - - /** The messages array if using the messages option. */ - readonly messages: Array | undefined; - - /** The tools available for this generation. */ - readonly tools: TOOLS | undefined; - - /** The tool choice strategy for this generation. */ - readonly toolChoice: ToolChoice> | undefined; - - /** Limits which tools are available for the model to call. */ - readonly activeTools: Array | undefined; - - /** Maximum number of tokens to generate. */ - readonly maxOutputTokens: number | undefined; - /** Sampling temperature for generation. */ - readonly temperature: number | undefined; - /** Top-p (nucleus) sampling parameter. */ - readonly topP: number | undefined; - /** Top-k sampling parameter. */ - readonly topK: number | undefined; - /** Presence penalty for generation. */ - readonly presencePenalty: number | undefined; - /** Frequency penalty for generation. */ - readonly frequencyPenalty: number | undefined; - /** Sequences that will stop generation. */ - readonly stopSequences: string[] | undefined; - /** Random seed for reproducible generation. */ - readonly seed: number | undefined; - /** Maximum number of retries for failed requests. */ - readonly maxRetries: number; - - /** - * Timeout configuration for the generation. - * Can be a number (milliseconds) or an object with totalMs, stepMs, chunkMs. - */ - readonly timeout: TimeoutConfiguration | undefined; - - /** Additional HTTP headers sent with the request. */ - readonly headers: Record | undefined; - - /** Additional provider-specific options. */ - readonly providerOptions: ProviderOptions | undefined; - - /** - * Condition(s) for stopping the generation. - * When the condition is an array, any of the conditions can be met to stop. - */ - readonly stopWhen: - | StopCondition - | Array> - | undefined; - - /** The output specification for structured outputs, if configured. */ - readonly output: OUTPUT | undefined; - - /** Abort signal for cancelling the operation. */ - readonly abortSignal: AbortSignal | undefined; - - /** - * Settings for controlling what data is included in step results. - */ - readonly include: INCLUDE | undefined; - - /** Identifier from telemetry settings for grouping related operations. */ - readonly functionId: string | undefined; - - /** Additional metadata passed to the generation. */ - readonly metadata: Record | undefined; - - /** - * User-defined context object that flows through the entire generation lifecycle. - * Can be accessed and modified in `prepareStep` and tool `execute` functions. - */ - readonly experimental_context: unknown; -} - -/** - * Event passed to the `onStepStart` callback. - * - * Called when a step (LLM call) begins, before the provider is called. - * Each step represents a single LLM invocation. - */ -export interface OnStepStartEvent< - TOOLS extends ToolSet = ToolSet, - OUTPUT extends Output = Output, - INCLUDE = { requestBody?: boolean; responseBody?: boolean }, -> { - /** Zero-based index of the current step. */ - readonly stepNumber: number; - - /** The model being used for this step. */ - readonly model: CallbackModelInfo; - - /** - * The system message for this step. - */ - readonly system: - | string - | SystemModelMessage - | Array - | undefined; - - /** - * The messages that will be sent to the model for this step. - * Uses the user-facing `ModelMessage` format. - * May be overridden by prepareStep. - */ - readonly messages: Array; - - /** The tools available for this generation. */ - readonly tools: TOOLS | undefined; - - /** The tool choice configuration for this step. */ - readonly toolChoice: LanguageModelV3ToolChoice | undefined; - - /** Limits which tools are available for this step. */ - readonly activeTools: Array | undefined; - - /** Array of results from previous steps (empty for first step). */ - readonly steps: ReadonlyArray>; - - /** Additional provider-specific options for this step. */ - readonly providerOptions: ProviderOptions | undefined; - - /** - * Timeout configuration for the generation. - * Can be a number (milliseconds) or an object with totalMs, stepMs, chunkMs. - */ - readonly timeout: TimeoutConfiguration | undefined; - - /** Additional HTTP headers sent with the request. */ - readonly headers: Record | undefined; - - /** - * Condition(s) for stopping the generation. - * When the condition is an array, any of the conditions can be met to stop. - */ - readonly stopWhen: - | StopCondition - | Array> - | undefined; - - /** The output specification for structured outputs, if configured. */ - readonly output: OUTPUT | undefined; - - /** Abort signal for cancelling the operation. */ - readonly abortSignal: AbortSignal | undefined; - - /** - * Settings for controlling what data is included in step results. - */ - readonly include: INCLUDE | undefined; - - /** Identifier from telemetry settings for grouping related operations. */ - readonly functionId: string | undefined; - - /** Additional metadata from telemetry settings. */ - readonly metadata: Record | undefined; - - /** - * User-defined context object. May be updated from `prepareStep` between steps. - */ - readonly experimental_context: unknown; -} - -/** - * Event passed to the `onToolCallStart` callback. - * - * Called when a tool execution begins, before the tool's `execute` function is invoked. - */ -export interface OnToolCallStartEvent { - /** Zero-based index of the current step where this tool call occurs. */ - readonly stepNumber: number | undefined; - - /** The model being used for this step. */ - readonly model: CallbackModelInfo | undefined; - - /** The full tool call object. */ - readonly toolCall: TypedToolCall; - - /** The conversation messages available at tool execution time. */ - readonly messages: Array; - - /** Signal for cancelling the operation. */ - readonly abortSignal: AbortSignal | undefined; - - /** Identifier from telemetry settings for grouping related operations. */ - readonly functionId: string | undefined; - - /** Additional metadata from telemetry settings. */ - readonly metadata: Record | undefined; - - /** User-defined context object flowing through the generation. */ - readonly experimental_context: unknown; -} - -/** - * Event passed to the `onToolCallFinish` callback. - * - * Called when a tool execution completes, either successfully or with an error. - * Uses a discriminated union on the `success` field. - */ -export type OnToolCallFinishEvent = { - /** Zero-based index of the current step where this tool call occurred. */ - readonly stepNumber: number | undefined; - - /** The model being used for this step. */ - readonly model: CallbackModelInfo | undefined; - - /** The full tool call object. */ - readonly toolCall: TypedToolCall; - - /** The conversation messages available at tool execution time. */ - readonly messages: Array; - - /** Signal for cancelling the operation. */ - readonly abortSignal: AbortSignal | undefined; - - /** Execution time of the tool call in milliseconds. */ - readonly durationMs: number; - - /** Identifier from telemetry settings for grouping related operations. */ - readonly functionId: string | undefined; - - /** Additional metadata from telemetry settings. */ - readonly metadata: Record | undefined; - - /** User-defined context object flowing through the generation. */ - readonly experimental_context: unknown; -} & ( - | { - /** Indicates the tool call succeeded. */ - readonly success: true; - /** The tool's return value. */ - readonly output: unknown; - readonly error?: never; - } - | { - /** Indicates the tool call failed. */ - readonly success: false; - readonly output?: never; - /** The error that occurred during tool execution. */ - readonly error: unknown; - } -); - -/** - * Event passed to the `onStepFinish` callback. - * - * Called when a step (LLM call) completes. - * This is simply the StepResult for that step. - */ -export type OnStepFinishEvent = - StepResult; - -/** - * Event passed to the `onFinish` callback. - * - * Called when the entire generation completes (all steps finished). - * Includes the final step's result along with aggregated data from all steps. - */ -export type OnFinishEvent = - StepResult & { - /** Array containing results from all steps in the generation. */ - readonly steps: StepResult[]; - - /** Aggregated token usage across all steps. */ - readonly totalUsage: LanguageModelUsage; - - /** - * The final state of the user-defined context object. - * - * Experimental (can break in patch releases). - * - * @default undefined - */ - experimental_context: unknown; - - /** Identifier from telemetry settings for grouping related operations. */ - readonly functionId: string | undefined; - - /** Additional metadata from telemetry settings. */ - readonly metadata: Record | undefined; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/collect-tool-approvals.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/collect-tool-approvals.ts deleted file mode 100644 index 3fbf529de..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/collect-tool-approvals.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { - ModelMessage, - ToolApprovalRequest, - ToolApprovalResponse, -} from '@ai-sdk/provider-utils'; -import { InvalidToolApprovalError } from '../error/invalid-tool-approval-error'; -import { ToolCallNotFoundForApprovalError } from '../error/tool-call-not-found-for-approval-error'; -import { TypedToolCall } from './tool-call'; -import { TypedToolResult } from './tool-result'; -import { ToolSet } from './tool-set'; - -export type CollectedToolApprovals = { - approvalRequest: ToolApprovalRequest; - approvalResponse: ToolApprovalResponse; - toolCall: TypedToolCall; -}; - -/** - * If the last message is a tool message, this function collects all tool approvals - * from that message. - */ -export function collectToolApprovals({ - messages, -}: { - messages: ModelMessage[]; -}): { - approvedToolApprovals: Array>; - deniedToolApprovals: Array>; -} { - const lastMessage = messages.at(-1); - - if (lastMessage?.role != 'tool') { - return { - approvedToolApprovals: [], - deniedToolApprovals: [], - }; - } - - // gather tool calls and prepare lookup - const toolCallsByToolCallId: Record> = {}; - for (const message of messages) { - if (message.role === 'assistant' && typeof message.content !== 'string') { - const content = message.content; - for (const part of content) { - if (part.type === 'tool-call') { - toolCallsByToolCallId[part.toolCallId] = part as TypedToolCall; - } - } - } - } - - // gather approval responses and prepare lookup - const toolApprovalRequestsByApprovalId: Record = - {}; - for (const message of messages) { - if (message.role === 'assistant' && typeof message.content !== 'string') { - const content = message.content; - for (const part of content) { - if (part.type === 'tool-approval-request') { - toolApprovalRequestsByApprovalId[part.approvalId] = part; - } - } - } - } - - // gather tool results from the last tool message - const toolResults: Record> = {}; - for (const part of lastMessage.content) { - if (part.type === 'tool-result') { - toolResults[part.toolCallId] = part as TypedToolResult; - } - } - - const approvedToolApprovals: Array> = []; - const deniedToolApprovals: Array> = []; - - const approvalResponses = lastMessage.content.filter( - part => part.type === 'tool-approval-response', - ); - for (const approvalResponse of approvalResponses) { - const approvalRequest = - toolApprovalRequestsByApprovalId[approvalResponse.approvalId]; - - if (approvalRequest == null) { - throw new InvalidToolApprovalError({ - approvalId: approvalResponse.approvalId, - }); - } - - if (toolResults[approvalRequest.toolCallId] != null) { - continue; - } - - const toolCall = toolCallsByToolCallId[approvalRequest.toolCallId]; - if (toolCall == null) { - throw new ToolCallNotFoundForApprovalError({ - toolCallId: approvalRequest.toolCallId, - approvalId: approvalRequest.approvalId, - }); - } - - const approval: CollectedToolApprovals = { - approvalRequest, - approvalResponse, - toolCall, - }; - - if (approvalResponse.approved) { - approvedToolApprovals.push(approval); - } else { - deniedToolApprovals.push(approval); - } - } - - return { approvedToolApprovals, deniedToolApprovals }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/content-part.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/content-part.ts deleted file mode 100644 index 925d1a366..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/content-part.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ProviderMetadata } from '../types'; -import { Source } from '../types/language-model'; -import { GeneratedFile } from './generated-file'; -import { ToolApprovalRequestOutput } from './tool-approval-request-output'; -import { ReasoningOutput } from './reasoning-output'; -import { TypedToolCall } from './tool-call'; -import { TypedToolError } from './tool-error'; -import { TypedToolResult } from './tool-result'; -import { ToolSet } from './tool-set'; - -export type ContentPart = - | { type: 'text'; text: string; providerMetadata?: ProviderMetadata } - | ReasoningOutput - | ({ type: 'source' } & Source) - | { type: 'file'; file: GeneratedFile; providerMetadata?: ProviderMetadata } // different because of GeneratedFile object - | ({ type: 'tool-call' } & TypedToolCall & { - providerMetadata?: ProviderMetadata; - }) - | ({ type: 'tool-result' } & TypedToolResult & { - providerMetadata?: ProviderMetadata; - }) - | ({ type: 'tool-error' } & TypedToolError & { - providerMetadata?: ProviderMetadata; - }) - | ToolApprovalRequestOutput; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/execute-tool-call.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/execute-tool-call.ts deleted file mode 100644 index 55644265c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/execute-tool-call.ts +++ /dev/null @@ -1,197 +0,0 @@ -import { executeTool, ModelMessage } from '@ai-sdk/provider-utils'; -import { Tracer } from '@opentelemetry/api'; -import { notify } from '../util/notify'; -import { assembleOperationName } from '../telemetry/assemble-operation-name'; -import { recordErrorOnSpan, recordSpan } from '../telemetry/record-span'; -import { selectTelemetryAttributes } from '../telemetry/select-telemetry-attributes'; -import { TelemetrySettings } from '../telemetry/telemetry-settings'; -import { now } from '../util/now'; -import { - GenerateTextOnToolCallFinishCallback, - GenerateTextOnToolCallStartCallback, -} from './generate-text'; -import { TypedToolCall } from './tool-call'; -import { ToolOutput } from './tool-output'; -import { ToolSet } from './tool-set'; -import { TypedToolResult } from './tool-result'; -import { TypedToolError } from './tool-error'; - -/** - * Executes a single tool call and manages its lifecycle callbacks. - * - * This function handles the complete tool execution flow: - * 1. Invokes `onToolCallStart` callback before execution - * 2. Executes the tool's `execute` function with proper context - * 3. Handles streaming outputs via `onPreliminaryToolResult` - * 4. Invokes `onToolCallFinish` callback with success or error result - * - * @returns The tool output (result or error), or undefined if the tool has no execute function. - */ -export async function executeToolCall({ - toolCall, - tools, - tracer, - telemetry, - messages, - abortSignal, - experimental_context, - stepNumber, - model, - onPreliminaryToolResult, - onToolCallStart, - onToolCallFinish, -}: { - toolCall: TypedToolCall; - tools: TOOLS | undefined; - tracer: Tracer; - telemetry: TelemetrySettings | undefined; - messages: ModelMessage[]; - abortSignal: AbortSignal | undefined; - experimental_context: unknown; - stepNumber?: number; - model?: { provider: string; modelId: string }; - onPreliminaryToolResult?: (result: TypedToolResult) => void; - onToolCallStart?: - | GenerateTextOnToolCallStartCallback - | Array | undefined | null>; - onToolCallFinish?: - | GenerateTextOnToolCallFinishCallback - | Array | undefined | null>; -}): Promise | undefined> { - const { toolName, toolCallId, input } = toolCall; - const tool = tools?.[toolName]; - - if (tool?.execute == null) { - return undefined; - } - - const baseCallbackEvent = { - stepNumber, - model, - toolCall, - messages, - abortSignal, - functionId: telemetry?.functionId, - metadata: telemetry?.metadata as Record | undefined, - experimental_context, - }; - - return recordSpan({ - name: 'ai.toolCall', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ - operationId: 'ai.toolCall', - telemetry, - }), - 'ai.toolCall.name': toolName, - 'ai.toolCall.id': toolCallId, - 'ai.toolCall.args': { - output: () => JSON.stringify(input), - }, - }, - }), - tracer, - fn: async span => { - let output: unknown; - - await notify({ event: baseCallbackEvent, callbacks: onToolCallStart }); - - const startTime = now(); - - try { - const stream = executeTool({ - execute: tool.execute!.bind(tool), - input, - options: { - toolCallId, - messages, - abortSignal, - experimental_context, - }, - }); - - for await (const part of stream) { - if (part.type === 'preliminary') { - onPreliminaryToolResult?.({ - ...toolCall, - type: 'tool-result', - output: part.output, - preliminary: true, - }); - } else { - output = part.output; - } - } - } catch (error) { - const durationMs = now() - startTime; - - await notify({ - event: { - ...baseCallbackEvent, - success: false as const, - error, - durationMs, - }, - callbacks: onToolCallFinish, - }); - - recordErrorOnSpan(span, error); - return { - type: 'tool-error', - toolCallId, - toolName, - input, - error, - dynamic: tool.type === 'dynamic', - ...(toolCall.providerMetadata != null - ? { providerMetadata: toolCall.providerMetadata } - : {}), - } as TypedToolError; - } - - const durationMs = now() - startTime; - - await notify({ - event: { - ...baseCallbackEvent, - success: true as const, - output, - durationMs, - }, - callbacks: onToolCallFinish, - }); - - try { - span.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.toolCall.result': { - output: () => JSON.stringify(output), - }, - }, - }), - ); - } catch (ignored) { - // JSON stringify might fail if the result is not serializable, - // in which case we just ignore it. In the future we might want to - // add an optional serialize method to the tool interface and warn - // if the result is not serializable. - } - - return { - type: 'tool-result', - toolCallId, - toolName, - input, - output, - dynamic: tool.type === 'dynamic', - ...(toolCall.providerMetadata != null - ? { providerMetadata: toolCall.providerMetadata } - : {}), - } as TypedToolResult; - }, - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/extract-reasoning-content.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/extract-reasoning-content.ts deleted file mode 100644 index 810b7af5c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/extract-reasoning-content.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { - LanguageModelV3Content, - LanguageModelV3Reasoning, -} from '@ai-sdk/provider'; - -export function extractReasoningContent( - content: LanguageModelV3Content[], -): string | undefined { - const parts = content.filter( - (content): content is LanguageModelV3Reasoning => - content.type === 'reasoning', - ); - - return parts.length === 0 - ? undefined - : parts.map(content => content.text).join('\n'); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/extract-text-content.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/extract-text-content.ts deleted file mode 100644 index 2efc20bba..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/extract-text-content.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { LanguageModelV3Content, LanguageModelV3Text } from '@ai-sdk/provider'; - -export function extractTextContent( - content: LanguageModelV3Content[], -): string | undefined { - const parts = content.filter( - (content): content is LanguageModelV3Text => content.type === 'text', - ); - - if (parts.length === 0) { - return undefined; - } - - return parts.map(content => content.text).join(''); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/generate-text-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/generate-text-result.ts deleted file mode 100644 index 6f37f8d69..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/generate-text-result.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { CallWarning, FinishReason, ProviderMetadata } from '../types'; -import { Source } from '../types/language-model'; -import { LanguageModelRequestMetadata } from '../types/language-model-request-metadata'; -import { LanguageModelResponseMetadata } from '../types/language-model-response-metadata'; -import { LanguageModelUsage } from '../types/usage'; -import { ContentPart } from './content-part'; -import { GeneratedFile } from './generated-file'; -import { Output } from './output'; -import { InferCompleteOutput } from './output-utils'; -import { ReasoningOutput } from './reasoning-output'; -import { ResponseMessage } from './response-message'; -import { StepResult } from './step-result'; -import { DynamicToolCall, StaticToolCall, TypedToolCall } from './tool-call'; -import { - DynamicToolResult, - StaticToolResult, - TypedToolResult, -} from './tool-result'; -import { ToolSet } from './tool-set'; - -/** - * The result of a `generateText` call. - * It contains the generated text, the tool calls that were made during the generation, and the results of the tool calls. - */ -export interface GenerateTextResult< - TOOLS extends ToolSet, - OUTPUT extends Output, -> { - /** - * The content that was generated in the last step. - */ - readonly content: Array>; - - /** - * The text that was generated in the last step. - */ - readonly text: string; - - /** - * The full reasoning that the model has generated in the last step. - */ - readonly reasoning: Array; - - /** - * The reasoning text that the model has generated in the last step. Can be undefined if the model - * has only generated text. - */ - readonly reasoningText: string | undefined; - - /** - * The files that were generated in the last step. - * Empty array if no files were generated. - */ - readonly files: Array; - - /** - * Sources that have been used as references in the last step. - */ - readonly sources: Array; - - /** - * The tool calls that were made in the last step. - */ - readonly toolCalls: Array>; - - /** - * The static tool calls that were made in the last step. - */ - readonly staticToolCalls: Array>; - - /** - * The dynamic tool calls that were made in the last step. - */ - readonly dynamicToolCalls: Array; - - /** - * The results of the tool calls from the last step. - */ - readonly toolResults: Array>; - - /** - * The static tool results that were made in the last step. - */ - readonly staticToolResults: Array>; - - /** - * The dynamic tool results that were made in the last step. - */ - readonly dynamicToolResults: Array; - - /** - * The unified reason why the generation finished. - */ - readonly finishReason: FinishReason; - - /** - * The raw reason why the generation finished (from the provider). - */ - readonly rawFinishReason: string | undefined; - - /** - * The token usage of the last step. - */ - readonly usage: LanguageModelUsage; - - /** - * The total token usage of all steps. - * When there are multiple steps, the usage is the sum of all step usages. - */ - readonly totalUsage: LanguageModelUsage; - - /** - * Warnings from the model provider (e.g. unsupported settings) - */ - readonly warnings: CallWarning[] | undefined; - - /** - * Additional request information. - */ - readonly request: LanguageModelRequestMetadata; - - /** - * Additional response information. - */ - readonly response: LanguageModelResponseMetadata & { - /** - * The response messages that were generated during the call. It consists of an assistant message, - * potentially containing tool calls. - * - * When there are tool results, there is an additional tool message with the tool results that are available. - * If there are tools that do not have execute functions, they are not included in the tool results and - * need to be added separately. - */ - messages: Array; - - /** - * Response body (available only for providers that use HTTP requests). - */ - body?: unknown; - }; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - readonly providerMetadata: ProviderMetadata | undefined; - - /** - * Details for all steps. - * You can use this to get information about intermediate steps, - * such as the tool calls or the response headers. - */ - readonly steps: Array>; - - /** - * The generated structured output. It uses the `output` specification. - * - * @deprecated Use `output` instead. - */ - readonly experimental_output: InferCompleteOutput; - - /** - * The generated structured output. It uses the `output` specification. - * - */ - readonly output: InferCompleteOutput; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/generate-text.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/generate-text.ts deleted file mode 100644 index 8383fa6ca..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/generate-text.ts +++ /dev/null @@ -1,1582 +0,0 @@ -import { - LanguageModelV3, - LanguageModelV3Content, - LanguageModelV3ToolCall, - LanguageModelV3ToolChoice, -} from '@ai-sdk/provider'; -import { - createIdGenerator, - getErrorMessage, - IdGenerator, - ProviderOptions, - SystemModelMessage, - ToolApprovalResponse, - withUserAgentSuffix, -} from '@ai-sdk/provider-utils'; -import { Tracer } from '@opentelemetry/api'; -import { NoOutputGeneratedError } from '../error'; -import { notify } from '../util/notify'; -import { logWarnings } from '../logger/log-warnings'; -import { resolveLanguageModel } from '../model/resolve-model'; -import { ModelMessage } from '../prompt'; -import { - CallSettings, - getStepTimeoutMs, - getTotalTimeoutMs, - TimeoutConfiguration, -} from '../prompt/call-settings'; -import { convertToLanguageModelPrompt } from '../prompt/convert-to-language-model-prompt'; -import { createToolModelOutput } from '../prompt/create-tool-model-output'; -import { prepareCallSettings } from '../prompt/prepare-call-settings'; -import { prepareToolsAndToolChoice } from '../prompt/prepare-tools-and-tool-choice'; -import { Prompt } from '../prompt/prompt'; -import { standardizePrompt } from '../prompt/standardize-prompt'; -import { wrapGatewayError } from '../prompt/wrap-gateway-error'; -import { ToolCallNotFoundForApprovalError } from '../error/tool-call-not-found-for-approval-error'; -import { assembleOperationName } from '../telemetry/assemble-operation-name'; -import { getBaseTelemetryAttributes } from '../telemetry/get-base-telemetry-attributes'; -import { getTracer } from '../telemetry/get-tracer'; -import { recordSpan } from '../telemetry/record-span'; -import { selectTelemetryAttributes } from '../telemetry/select-telemetry-attributes'; -import { stringifyForTelemetry } from '../telemetry/stringify-for-telemetry'; -import { getGlobalTelemetryIntegration } from '../telemetry/get-global-telemetry-integration'; -import { TelemetrySettings } from '../telemetry/telemetry-settings'; -import { - LanguageModel, - LanguageModelRequestMetadata, - ToolChoice, -} from '../types'; -import { - addLanguageModelUsage, - asLanguageModelUsage, - LanguageModelUsage, -} from '../types/usage'; -import { asArray } from '../util/as-array'; -import { DownloadFunction } from '../util/download/download-function'; -import { mergeObjects } from '../util/merge-objects'; -import { prepareRetries } from '../util/prepare-retries'; -import { VERSION } from '../version'; -import type { - OnFinishEvent, - OnStartEvent, - OnStepFinishEvent, - OnStepStartEvent, - OnToolCallFinishEvent, - OnToolCallStartEvent, -} from './callback-events'; -import { collectToolApprovals } from './collect-tool-approvals'; -import { ContentPart } from './content-part'; -import { executeToolCall } from './execute-tool-call'; -import { extractReasoningContent } from './extract-reasoning-content'; -import { extractTextContent } from './extract-text-content'; -import { GenerateTextResult } from './generate-text-result'; -import { DefaultGeneratedFile } from './generated-file'; -import { isApprovalNeeded } from './is-approval-needed'; -import { Output, text } from './output'; -import { InferCompleteOutput } from './output-utils'; -import { parseToolCall } from './parse-tool-call'; -import { PrepareStepFunction } from './prepare-step'; -import { ResponseMessage } from './response-message'; -import { DefaultStepResult, StepResult } from './step-result'; -import { - isStopConditionMet, - stepCountIs, - StopCondition, -} from './stop-condition'; -import { toResponseMessages } from './to-response-messages'; -import { ToolApprovalRequestOutput } from './tool-approval-request-output'; -import { TypedToolCall } from './tool-call'; -import { ToolCallRepairFunction } from './tool-call-repair-function'; -import { TypedToolError } from './tool-error'; -import { ToolOutput } from './tool-output'; -import { TypedToolResult } from './tool-result'; -import { ToolSet } from './tool-set'; -import { mergeAbortSignals } from '../util/merge-abort-signals'; - -const originalGenerateId = createIdGenerator({ - prefix: 'aitxt', - size: 24, -}); - -/** - * Include settings for generateText (requestBody and responseBody). - */ -type GenerateTextIncludeSettings = { - requestBody?: boolean; - responseBody?: boolean; -}; - -/** - * Callback that is set using the `experimental_onStart` option. - * - * Called when the generateText operation begins, before any LLM calls. - * Use this callback for logging, analytics, or initializing state at the - * start of a generation. - * - * @param event - The event object containing generation configuration. - */ -export type GenerateTextOnStartCallback< - TOOLS extends ToolSet = ToolSet, - OUTPUT extends Output = Output, -> = ( - event: OnStartEvent, -) => PromiseLike | void; - -/** - * Callback that is set using the `experimental_onStepStart` option. - * - * Called when a step (LLM call) begins, before the provider is called. - * Each step represents a single LLM invocation. Multiple steps occur when - * using tool calls (the model may be called multiple times in a loop). - * - * @param event - The event object containing step configuration. - */ -export type GenerateTextOnStepStartCallback< - TOOLS extends ToolSet = ToolSet, - OUTPUT extends Output = Output, -> = ( - event: OnStepStartEvent, -) => PromiseLike | void; - -/** - * Callback that is set using the `experimental_onToolCallStart` option. - * - * Called when a tool execution begins, before the tool's `execute` function is invoked. - * Use this for logging tool invocations, tracking tool usage, or pre-execution validation. - * - * @param event - The event object containing tool call information. - */ -export type GenerateTextOnToolCallStartCallback< - TOOLS extends ToolSet = ToolSet, -> = (event: OnToolCallStartEvent) => PromiseLike | void; - -/** - * Callback that is set using the `experimental_onToolCallFinish` option. - * - * Called when a tool execution completes, either successfully or with an error. - * Use this for logging tool results, tracking execution time, or error handling. - * - * The event uses a discriminated union on the `success` field: - * - When `success: true`: `output` contains the tool result, `error` is never present. - * - When `success: false`: `error` contains the error, `output` is never present. - * - * @param event - The event object containing tool call result information. - */ -export type GenerateTextOnToolCallFinishCallback< - TOOLS extends ToolSet = ToolSet, -> = (event: OnToolCallFinishEvent) => PromiseLike | void; - -/** - * Callback that is set using the `onStepFinish` option. - * - * Called when a step (LLM call) completes. The event includes all step result - * properties (text, tool calls, usage, etc.) along with additional metadata. - * - * @param stepResult - The result of the step. - */ -export type GenerateTextOnStepFinishCallback = ( - event: OnStepFinishEvent, -) => Promise | void; - -/** - * Callback that is set using the `onFinish` option. - * - * Called when the entire generation completes (all steps finished). - * The event includes the final step's result properties along with - * aggregated data from all steps. - * - * @param event - The final result along with aggregated step data. - */ -export type GenerateTextOnFinishCallback = ( - event: OnFinishEvent, -) => PromiseLike | void; - -/** - * Generate a text and call tools for a given prompt using a language model. - * - * This function does not stream the output. If you want to stream the output, use `streamText` instead. - * - * @param model - The language model to use. - * - * @param tools - Tools that are accessible to and can be called by the model. The model needs to support calling tools. - * @param toolChoice - The tool choice strategy. Default: 'auto'. - * - * @param system - A system message that will be part of the prompt. - * @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both. - * @param messages - A list of messages. You can either use `prompt` or `messages` but not both. - * - * @param maxOutputTokens - Maximum number of tokens to generate. - * @param temperature - Temperature setting. - * The value is passed through to the provider. The range depends on the provider and model. - * It is recommended to set either `temperature` or `topP`, but not both. - * @param topP - Nucleus sampling. - * The value is passed through to the provider. The range depends on the provider and model. - * It is recommended to set either `temperature` or `topP`, but not both. - * @param topK - Only sample from the top K options for each subsequent token. - * Used to remove "long tail" low probability responses. - * Recommended for advanced use cases only. You usually only need to use temperature. - * @param presencePenalty - Presence penalty setting. - * It affects the likelihood of the model to repeat information that is already in the prompt. - * The value is passed through to the provider. The range depends on the provider and model. - * @param frequencyPenalty - Frequency penalty setting. - * It affects the likelihood of the model to repeatedly use the same words or phrases. - * The value is passed through to the provider. The range depends on the provider and model. - * @param stopSequences - Stop sequences. - * If set, the model will stop generating text when one of the stop sequences is generated. - * @param seed - The seed (integer) to use for random sampling. - * If set and supported by the model, calls will generate deterministic results. - * - * @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2. - * @param abortSignal - An optional abort signal that can be used to cancel the call. - * @param timeout - An optional timeout in milliseconds. The call will be aborted if it takes longer than the specified timeout. - * @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers. - * - * @param experimental_context - User-defined context object that flows through the entire generation lifecycle. - * @param experimental_onStart - Callback invoked when generation begins, before any LLM calls. - * @param experimental_onStepStart - Callback invoked when each step begins, before the provider is called. - * Receives step number, messages (in ModelMessage format), tools, and context. - * @param experimental_onToolCallStart - Callback invoked before each tool execution begins. - * Receives tool name, call ID, input, and context. - * @param experimental_onToolCallFinish - Callback invoked after each tool execution completes. - * Uses a discriminated union: check `success` to determine if `output` or `error` is present. - * @param onStepFinish - Callback that is called when each step (LLM call) is finished, including intermediate steps. - * @param onFinish - Callback that is called when all steps are finished and the response is complete. - * - * @returns - * A result object that contains the generated text, the results of the tool calls, and additional information. - */ -export async function generateText< - TOOLS extends ToolSet, - OUTPUT extends Output = Output, ->({ - model: modelArg, - tools, - toolChoice, - system, - prompt, - messages, - maxRetries: maxRetriesArg, - abortSignal, - timeout, - headers, - stopWhen = stepCountIs(1), - experimental_output, - output = experimental_output, - experimental_telemetry: telemetry, - providerOptions, - experimental_activeTools, - activeTools = experimental_activeTools, - experimental_prepareStep, - prepareStep = experimental_prepareStep, - experimental_repairToolCall: repairToolCall, - experimental_download: download, - experimental_context, - experimental_include: include, - _internal: { generateId = originalGenerateId } = {}, - experimental_onStart: onStart, - experimental_onStepStart: onStepStart, - experimental_onToolCallStart: onToolCallStart, - experimental_onToolCallFinish: onToolCallFinish, - onStepFinish, - onFinish, - ...settings -}: CallSettings & - Prompt & { - /** - * The language model to use. - */ - model: LanguageModel; - - /** - * The tools that the model can call. The model needs to support calling tools. - */ - tools?: TOOLS; - - /** - * The tool choice strategy. Default: 'auto'. - */ - toolChoice?: ToolChoice>; - - /** - * Condition for stopping the generation when there are tool results in the last step. - * When the condition is an array, any of the conditions can be met to stop the generation. - * - * @default stepCountIs(1) - */ - stopWhen?: - | StopCondition> - | Array>>; - - /** - * Optional telemetry configuration (experimental). - */ - experimental_telemetry?: TelemetrySettings; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; - - /** - * @deprecated Use `activeTools` instead. - */ - experimental_activeTools?: Array>; - - /** - * Limits the tools that are available for the model to call without - * changing the tool call and result types in the result. - */ - activeTools?: Array>; - - /** - * Optional specification for parsing structured outputs from the LLM response. - */ - output?: OUTPUT; - - /** - * Optional specification for parsing structured outputs from the LLM response. - * - * @deprecated Use `output` instead. - */ - experimental_output?: OUTPUT; - - /** - * Custom download function to use for URLs. - * - * By default, files are downloaded if the model does not support the URL for the given media type. - */ - experimental_download?: DownloadFunction | undefined; - - /** - * @deprecated Use `prepareStep` instead. - */ - experimental_prepareStep?: PrepareStepFunction>; - - /** - * Optional function that you can use to provide different settings for a step. - */ - prepareStep?: PrepareStepFunction>; - - /** - * A function that attempts to repair a tool call that failed to parse. - */ - experimental_repairToolCall?: ToolCallRepairFunction>; - - /** - * Callback that is called when the generateText operation begins, - * before any LLM calls are made. - */ - experimental_onStart?: GenerateTextOnStartCallback, OUTPUT>; - - /** - * Callback that is called when a step (LLM call) begins, - * before the provider is called. - */ - experimental_onStepStart?: GenerateTextOnStepStartCallback< - NoInfer, - OUTPUT - >; - - /** - * Callback that is called right before a tool's execute function runs. - */ - experimental_onToolCallStart?: GenerateTextOnToolCallStartCallback< - NoInfer - >; - - /** - * Callback that is called right after a tool's execute function completes (or errors). - */ - experimental_onToolCallFinish?: GenerateTextOnToolCallFinishCallback< - NoInfer - >; - - /** - * Callback that is called when each step (LLM call) is finished, including intermediate steps. - */ - onStepFinish?: GenerateTextOnStepFinishCallback>; - - /** - * Callback that is called when all steps are finished and the response is complete. - */ - onFinish?: GenerateTextOnFinishCallback>; - - /** - * Context that is passed into tool execution. - * - * Experimental (can break in patch releases). - * - * @default undefined - */ - experimental_context?: unknown; - - /** - * Settings for controlling what data is included in step results. - * Disabling inclusion can help reduce memory usage when processing - * large payloads like images. - * - * By default, all data is included for backwards compatibility. - */ - experimental_include?: { - /** - * Whether to retain the request body in step results. - * The request body can be large when sending images or files. - * @default true - */ - requestBody?: boolean; - - /** - * Whether to retain the response body in step results. - * @default true - */ - responseBody?: boolean; - }; - - /** - * Internal. For test use only. May change without notice. - */ - _internal?: { - generateId?: IdGenerator; - }; - }): Promise> { - const model = resolveLanguageModel(modelArg); - const createGlobalTelemetry = getGlobalTelemetryIntegration(); - const stopConditions = asArray(stopWhen); - - const totalTimeoutMs = getTotalTimeoutMs(timeout); - const stepTimeoutMs = getStepTimeoutMs(timeout); - const stepAbortController = - stepTimeoutMs != null ? new AbortController() : undefined; - const mergedAbortSignal = mergeAbortSignals( - abortSignal, - totalTimeoutMs != null ? AbortSignal.timeout(totalTimeoutMs) : undefined, - stepAbortController?.signal, - ); - - const { maxRetries, retry } = prepareRetries({ - maxRetries: maxRetriesArg, - abortSignal: mergedAbortSignal, - }); - - const callSettings = prepareCallSettings(settings); - - const headersWithUserAgent = withUserAgentSuffix( - headers ?? {}, - `ai/${VERSION}`, - ); - - const baseTelemetryAttributes = getBaseTelemetryAttributes({ - model, - telemetry, - headers: headersWithUserAgent, - settings: { ...callSettings, maxRetries }, - }); - - const modelInfo = { provider: model.provider, modelId: model.modelId }; - - const initialPrompt = await standardizePrompt({ - system, - prompt, - messages, - } as Prompt); - - const globalTelemetry = createGlobalTelemetry(telemetry?.integrations); - - await notify({ - event: { - model: modelInfo, - system, - prompt, - messages, - tools, - toolChoice, - activeTools, - maxOutputTokens: callSettings.maxOutputTokens, - temperature: callSettings.temperature, - topP: callSettings.topP, - topK: callSettings.topK, - presencePenalty: callSettings.presencePenalty, - frequencyPenalty: callSettings.frequencyPenalty, - stopSequences: callSettings.stopSequences, - seed: callSettings.seed, - maxRetries, - timeout, - headers, - providerOptions, - stopWhen, - output, - abortSignal, - include, - functionId: telemetry?.functionId, - metadata: telemetry?.metadata as Record | undefined, - experimental_context, - }, - callbacks: [ - onStart, - globalTelemetry.onStart as - | undefined - | GenerateTextOnStartCallback, - ], - }); - - const tracer = getTracer(telemetry); - - try { - return await recordSpan({ - name: 'ai.generateText', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ - operationId: 'ai.generateText', - telemetry, - }), - ...baseTelemetryAttributes, - // model: - 'ai.model.provider': model.provider, - 'ai.model.id': model.modelId, - // specific settings that only make sense on the outer level: - 'ai.prompt': { - input: () => JSON.stringify({ system, prompt, messages }), - }, - }, - }), - tracer, - fn: async span => { - const initialMessages = initialPrompt.messages; - const responseMessages: Array = []; - - const { approvedToolApprovals, deniedToolApprovals } = - collectToolApprovals({ messages: initialMessages }); - - const localApprovedToolApprovals = approvedToolApprovals.filter( - toolApproval => !toolApproval.toolCall.providerExecuted, - ); - - if ( - deniedToolApprovals.length > 0 || - localApprovedToolApprovals.length > 0 - ) { - const toolOutputs = await executeTools({ - toolCalls: localApprovedToolApprovals.map( - toolApproval => toolApproval.toolCall, - ), - tools: tools as TOOLS, - tracer, - telemetry, - messages: initialMessages, - abortSignal: mergedAbortSignal, - experimental_context, - stepNumber: 0, - model: modelInfo, - onToolCallStart: [ - onToolCallStart, - globalTelemetry.onToolCallStart as - | undefined - | GenerateTextOnToolCallStartCallback, - ], - onToolCallFinish: [ - onToolCallFinish, - globalTelemetry.onToolCallFinish as - | undefined - | GenerateTextOnToolCallFinishCallback, - ], - }); - - const toolContent: Array = []; - - // add regular tool results for approved tool calls: - for (const output of toolOutputs) { - const modelOutput = await createToolModelOutput({ - toolCallId: output.toolCallId, - input: output.input, - tool: tools?.[output.toolName], - output: - output.type === 'tool-result' ? output.output : output.error, - errorMode: output.type === 'tool-error' ? 'text' : 'none', - }); - - toolContent.push({ - type: 'tool-result' as const, - toolCallId: output.toolCallId, - toolName: output.toolName, - output: modelOutput, - }); - } - - // add execution denied tool results for all denied tool approvals: - for (const toolApproval of deniedToolApprovals) { - toolContent.push({ - type: 'tool-result' as const, - toolCallId: toolApproval.toolCall.toolCallId, - toolName: toolApproval.toolCall.toolName, - output: { - type: 'execution-denied' as const, - reason: toolApproval.approvalResponse.reason, - // For provider-executed tools, include approvalId so provider can correlate - ...(toolApproval.toolCall.providerExecuted && { - providerOptions: { - openai: { - approvalId: toolApproval.approvalResponse.approvalId, - }, - }, - }), - }, - }); - } - - responseMessages.push({ - role: 'tool', - content: toolContent, - }); - } - - // Forward provider-executed approval responses to the provider - const providerExecutedToolApprovals = [ - ...approvedToolApprovals, - ...deniedToolApprovals, - ].filter(toolApproval => toolApproval.toolCall.providerExecuted); - - if (providerExecutedToolApprovals.length > 0) { - responseMessages.push({ - role: 'tool', - content: providerExecutedToolApprovals.map( - toolApproval => - ({ - type: 'tool-approval-response', - approvalId: toolApproval.approvalResponse.approvalId, - approved: toolApproval.approvalResponse.approved, - reason: toolApproval.approvalResponse.reason, - providerExecuted: true, - }) satisfies ToolApprovalResponse, - ), - }); - } - - const callSettings = prepareCallSettings(settings); - - let currentModelResponse: Awaited< - ReturnType - > & { response: { id: string; timestamp: Date; modelId: string } }; - let clientToolCalls: Array> = []; - let clientToolOutputs: Array> = []; - const steps: GenerateTextResult['steps'] = []; - - // Track provider-executed tool calls that support deferred results - // (e.g., code_execution in programmatic tool calling scenarios). - // These tools may not return their results in the same turn as their call. - const pendingDeferredToolCalls = new Map< - string, - { toolName: string } - >(); - - do { - // Set up step timeout if configured - const stepTimeoutId = - stepTimeoutMs != null - ? setTimeout(() => stepAbortController!.abort(), stepTimeoutMs) - : undefined; - - try { - const stepInputMessages = [...initialMessages, ...responseMessages]; - - const prepareStepResult = await prepareStep?.({ - model, - steps, - stepNumber: steps.length, - messages: stepInputMessages, - experimental_context, - }); - - const stepModel = resolveLanguageModel( - prepareStepResult?.model ?? model, - ); - const stepModelInfo = { - provider: stepModel.provider, - modelId: stepModel.modelId, - }; - - const promptMessages = await convertToLanguageModelPrompt({ - prompt: { - system: prepareStepResult?.system ?? initialPrompt.system, - messages: prepareStepResult?.messages ?? stepInputMessages, - }, - supportedUrls: await stepModel.supportedUrls, - download, - }); - - experimental_context = - prepareStepResult?.experimental_context ?? experimental_context; - - const stepActiveTools = - prepareStepResult?.activeTools ?? activeTools; - - const { toolChoice: stepToolChoice, tools: stepTools } = - await prepareToolsAndToolChoice({ - tools, - toolChoice: prepareStepResult?.toolChoice ?? toolChoice, - activeTools: stepActiveTools, - }); - - const stepMessages = - prepareStepResult?.messages ?? stepInputMessages; - - const stepSystem = - prepareStepResult?.system ?? initialPrompt.system; - - const stepProviderOptions = mergeObjects( - providerOptions, - prepareStepResult?.providerOptions, - ); - - await notify({ - event: { - stepNumber: steps.length, - model: stepModelInfo, - system: stepSystem, - messages: stepMessages, - tools, - toolChoice: stepToolChoice, - activeTools: stepActiveTools, - steps: [...steps], - providerOptions: stepProviderOptions, - timeout, - headers, - stopWhen, - output, - abortSignal, - include, - functionId: telemetry?.functionId, - metadata: telemetry?.metadata as - | Record - | undefined, - experimental_context, - }, - callbacks: [ - onStepStart, - globalTelemetry.onStepStart as - | undefined - | GenerateTextOnStepStartCallback, - ], - }); - - currentModelResponse = await retry(() => - recordSpan({ - name: 'ai.generateText.doGenerate', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ - operationId: 'ai.generateText.doGenerate', - telemetry, - }), - ...baseTelemetryAttributes, - // model: - 'ai.model.provider': stepModel.provider, - 'ai.model.id': stepModel.modelId, - // prompt: - 'ai.prompt.messages': { - input: () => stringifyForTelemetry(promptMessages), - }, - 'ai.prompt.tools': { - // convert the language model level tools: - input: () => stepTools?.map(tool => JSON.stringify(tool)), - }, - 'ai.prompt.toolChoice': { - input: () => - stepToolChoice != null - ? JSON.stringify(stepToolChoice) - : undefined, - }, - - // standardized gen-ai llm span attributes: - 'gen_ai.system': stepModel.provider, - 'gen_ai.request.model': stepModel.modelId, - 'gen_ai.request.frequency_penalty': - settings.frequencyPenalty, - 'gen_ai.request.max_tokens': settings.maxOutputTokens, - 'gen_ai.request.presence_penalty': settings.presencePenalty, - 'gen_ai.request.stop_sequences': settings.stopSequences, - 'gen_ai.request.temperature': - settings.temperature ?? undefined, - 'gen_ai.request.top_k': settings.topK, - 'gen_ai.request.top_p': settings.topP, - }, - }), - tracer, - fn: async span => { - const result = await stepModel.doGenerate({ - ...callSettings, - tools: stepTools, - toolChoice: stepToolChoice, - responseFormat: await output?.responseFormat, - prompt: promptMessages, - providerOptions: stepProviderOptions, - abortSignal: mergedAbortSignal, - headers: headersWithUserAgent, - }); - - // Fill in default values: - const responseData = { - id: result.response?.id ?? generateId(), - timestamp: result.response?.timestamp ?? new Date(), - modelId: result.response?.modelId ?? stepModel.modelId, - headers: result.response?.headers, - body: result.response?.body, - }; - const usage = asLanguageModelUsage(result.usage); - - // Add response information to the span: - span.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.response.finishReason': result.finishReason.unified, - 'ai.response.text': { - output: () => extractTextContent(result.content), - }, - 'ai.response.reasoning': { - output: () => extractReasoningContent(result.content), - }, - 'ai.response.toolCalls': { - output: () => { - const toolCalls = asToolCalls(result.content); - return toolCalls == null - ? undefined - : JSON.stringify(toolCalls); - }, - }, - 'ai.response.id': responseData.id, - 'ai.response.model': responseData.modelId, - 'ai.response.timestamp': - responseData.timestamp.toISOString(), - 'ai.response.providerMetadata': JSON.stringify( - result.providerMetadata, - ), - - 'ai.usage.inputTokens': result.usage.inputTokens.total, - 'ai.usage.inputTokenDetails.noCacheTokens': - result.usage.inputTokens.noCache, - 'ai.usage.inputTokenDetails.cacheReadTokens': - result.usage.inputTokens.cacheRead, - 'ai.usage.inputTokenDetails.cacheWriteTokens': - result.usage.inputTokens.cacheWrite, - 'ai.usage.outputTokens': - result.usage.outputTokens.total, - 'ai.usage.outputTokenDetails.textTokens': - result.usage.outputTokens.text, - 'ai.usage.outputTokenDetails.reasoningTokens': - result.usage.outputTokens.reasoning, - 'ai.usage.totalTokens': usage.totalTokens, - 'ai.usage.reasoningTokens': - result.usage.outputTokens.reasoning, - 'ai.usage.cachedInputTokens': - result.usage.inputTokens.cacheRead, - - // standardized gen-ai llm span attributes: - 'gen_ai.response.finish_reasons': [ - result.finishReason.unified, - ], - 'gen_ai.response.id': responseData.id, - 'gen_ai.response.model': responseData.modelId, - 'gen_ai.usage.input_tokens': - result.usage.inputTokens.total, - 'gen_ai.usage.output_tokens': - result.usage.outputTokens.total, - }, - }), - ); - - return { ...result, response: responseData }; - }, - }), - ); - - // parse tool calls: - const stepToolCalls: TypedToolCall[] = await Promise.all( - currentModelResponse.content - .filter( - (part): part is LanguageModelV3ToolCall => - part.type === 'tool-call', - ) - .map(toolCall => - parseToolCall({ - toolCall, - tools, - repairToolCall, - system, - messages: stepInputMessages, - }), - ), - ); - const toolApprovalRequests: Record< - string, - ToolApprovalRequestOutput - > = {}; - - // notify the tools that the tool calls are available: - for (const toolCall of stepToolCalls) { - if (toolCall.invalid) { - continue; // ignore invalid tool calls - } - - const tool = tools?.[toolCall.toolName]; - - if (tool == null) { - // ignore tool calls for tools that are not available, - // e.g. provider-executed dynamic tools - continue; - } - - if (tool?.onInputAvailable != null) { - await tool.onInputAvailable({ - input: toolCall.input, - toolCallId: toolCall.toolCallId, - messages: stepInputMessages, - abortSignal: mergedAbortSignal, - experimental_context, - }); - } - - if ( - await isApprovalNeeded({ - tool, - toolCall, - messages: stepInputMessages, - experimental_context, - }) - ) { - toolApprovalRequests[toolCall.toolCallId] = { - type: 'tool-approval-request', - approvalId: generateId(), - toolCall, - }; - } - } - - // insert error tool outputs for invalid tool calls: - // TODO AI SDK 6: invalid inputs should not require output parts - const invalidToolCalls = stepToolCalls.filter( - toolCall => toolCall.invalid && toolCall.dynamic, - ); - - clientToolOutputs = []; - - for (const toolCall of invalidToolCalls) { - clientToolOutputs.push({ - type: 'tool-error', - toolCallId: toolCall.toolCallId, - toolName: toolCall.toolName, - input: toolCall.input, - error: getErrorMessage(toolCall.error!), - dynamic: true, - }); - } - - // execute client tool calls: - clientToolCalls = stepToolCalls.filter( - toolCall => !toolCall.providerExecuted, - ); - - if (tools != null) { - clientToolOutputs.push( - ...(await executeTools({ - toolCalls: clientToolCalls.filter( - toolCall => - !toolCall.invalid && - toolApprovalRequests[toolCall.toolCallId] == null, - ), - tools, - tracer, - telemetry, - messages: stepInputMessages, - abortSignal: mergedAbortSignal, - experimental_context, - stepNumber: steps.length, - model: stepModelInfo, - onToolCallStart: [ - onToolCallStart, - globalTelemetry.onToolCallStart as - | undefined - | GenerateTextOnToolCallStartCallback, - ], - onToolCallFinish: [ - onToolCallFinish, - globalTelemetry.onToolCallFinish, - ], - })), - ); - } - - // Track provider-executed tool calls that support deferred results. - // In programmatic tool calling, a server tool (e.g., code_execution) may - // trigger a client tool, and the server tool's result is deferred until - // the client tool's result is sent back. - for (const toolCall of stepToolCalls) { - if (!toolCall.providerExecuted) continue; - const tool = tools?.[toolCall.toolName]; - if (tool?.type === 'provider' && tool.supportsDeferredResults) { - // Check if this tool call already has a result in the current response - const hasResultInResponse = currentModelResponse.content.some( - part => - part.type === 'tool-result' && - part.toolCallId === toolCall.toolCallId, - ); - if (!hasResultInResponse) { - pendingDeferredToolCalls.set(toolCall.toolCallId, { - toolName: toolCall.toolName, - }); - } - } - } - - // Mark deferred tool calls as resolved when we receive their results - for (const part of currentModelResponse.content) { - if (part.type === 'tool-result') { - pendingDeferredToolCalls.delete(part.toolCallId); - } - } - - // content: - const stepContent = asContent({ - content: currentModelResponse.content, - toolCalls: stepToolCalls, - toolOutputs: clientToolOutputs, - toolApprovalRequests: Object.values(toolApprovalRequests), - tools, - }); - - // append to messages for potential next step: - responseMessages.push( - ...(await toResponseMessages({ - content: stepContent, - tools, - })), - ); - - // Add step information (after response messages are updated): - // Conditionally include request.body and response.body based on include settings. - // Large payloads (e.g., base64-encoded images) can cause memory issues. - const stepRequest: LanguageModelRequestMetadata = - (include?.requestBody ?? true) - ? (currentModelResponse.request ?? {}) - : { ...currentModelResponse.request, body: undefined }; - - const stepResponse = { - ...currentModelResponse.response, - // deep clone msgs to avoid mutating past messages in multi-step: - messages: structuredClone(responseMessages), - // Conditionally include response body: - body: - (include?.responseBody ?? true) - ? currentModelResponse.response?.body - : undefined, - }; - - const stepNumber = steps.length; - - const currentStepResult: StepResult = new DefaultStepResult({ - stepNumber, - model: stepModelInfo, - functionId: telemetry?.functionId, - metadata: telemetry?.metadata as - | Record - | undefined, - experimental_context, - content: stepContent, - finishReason: currentModelResponse.finishReason.unified, - rawFinishReason: currentModelResponse.finishReason.raw, - usage: asLanguageModelUsage(currentModelResponse.usage), - warnings: currentModelResponse.warnings, - providerMetadata: currentModelResponse.providerMetadata, - request: stepRequest, - response: stepResponse, - }); - - logWarnings({ - warnings: currentModelResponse.warnings ?? [], - provider: stepModelInfo.provider, - model: stepModelInfo.modelId, - }); - - steps.push(currentStepResult); - - await notify({ - event: currentStepResult, - callbacks: [onStepFinish, globalTelemetry.onStepFinish], - }); - } finally { - if (stepTimeoutId != null) { - clearTimeout(stepTimeoutId); - } - } - } while ( - // Continue if: - // 1. There are client tool calls that have all been executed, OR - // 2. There are pending deferred results from provider-executed tools - ((clientToolCalls.length > 0 && - clientToolOutputs.length === clientToolCalls.length) || - pendingDeferredToolCalls.size > 0) && - // continue until a stop condition is met: - !(await isStopConditionMet({ stopConditions, steps })) - ); - - // Add response information to the span: - span.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.response.finishReason': - currentModelResponse.finishReason.unified, - 'ai.response.text': { - output: () => extractTextContent(currentModelResponse.content), - }, - 'ai.response.reasoning': { - output: () => - extractReasoningContent(currentModelResponse.content), - }, - 'ai.response.toolCalls': { - output: () => { - const toolCalls = asToolCalls(currentModelResponse.content); - return toolCalls == null - ? undefined - : JSON.stringify(toolCalls); - }, - }, - 'ai.response.providerMetadata': JSON.stringify( - currentModelResponse.providerMetadata, - ), - }, - }), - ); - - const lastStep = steps[steps.length - 1]; - - const totalUsage = steps.reduce( - (totalUsage, step) => { - return addLanguageModelUsage(totalUsage, step.usage); - }, - { - inputTokens: undefined, - outputTokens: undefined, - totalTokens: undefined, - reasoningTokens: undefined, - cachedInputTokens: undefined, - } as LanguageModelUsage, - ); - - span.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.usage.inputTokens': totalUsage.inputTokens, - 'ai.usage.inputTokenDetails.noCacheTokens': - totalUsage.inputTokenDetails?.noCacheTokens, - 'ai.usage.inputTokenDetails.cacheReadTokens': - totalUsage.inputTokenDetails?.cacheReadTokens, - 'ai.usage.inputTokenDetails.cacheWriteTokens': - totalUsage.inputTokenDetails?.cacheWriteTokens, - 'ai.usage.outputTokens': totalUsage.outputTokens, - 'ai.usage.outputTokenDetails.textTokens': - totalUsage.outputTokenDetails?.textTokens, - 'ai.usage.outputTokenDetails.reasoningTokens': - totalUsage.outputTokenDetails?.reasoningTokens, - 'ai.usage.totalTokens': totalUsage.totalTokens, - 'ai.usage.reasoningTokens': - totalUsage.outputTokenDetails?.reasoningTokens, - 'ai.usage.cachedInputTokens': - totalUsage.inputTokenDetails?.cacheReadTokens, - }, - }), - ); - - await notify({ - event: { - stepNumber: lastStep.stepNumber, - model: lastStep.model, - functionId: lastStep.functionId, - metadata: lastStep.metadata, - experimental_context: lastStep.experimental_context, - finishReason: lastStep.finishReason, - rawFinishReason: lastStep.rawFinishReason, - usage: lastStep.usage, - content: lastStep.content, - text: lastStep.text, - reasoningText: lastStep.reasoningText, - reasoning: lastStep.reasoning, - files: lastStep.files, - sources: lastStep.sources, - toolCalls: lastStep.toolCalls, - staticToolCalls: lastStep.staticToolCalls, - dynamicToolCalls: lastStep.dynamicToolCalls, - toolResults: lastStep.toolResults, - staticToolResults: lastStep.staticToolResults, - dynamicToolResults: lastStep.dynamicToolResults, - request: lastStep.request, - response: lastStep.response, - warnings: lastStep.warnings, - providerMetadata: lastStep.providerMetadata, - steps, - totalUsage, - }, - callbacks: [ - onFinish, - globalTelemetry.onFinish as - | undefined - | GenerateTextOnFinishCallback, - ], - }); - - // parse output only if the last step was finished with "stop": - let resolvedOutput; - if (lastStep.finishReason === 'stop') { - const outputSpecification = output ?? text(); - resolvedOutput = await outputSpecification.parseCompleteOutput( - { text: lastStep.text }, - { - response: lastStep.response, - usage: lastStep.usage, - finishReason: lastStep.finishReason, - }, - ); - } - - return new DefaultGenerateTextResult({ - steps, - totalUsage, - output: resolvedOutput, - }); - }, - }); - } catch (error) { - throw wrapGatewayError(error); - } -} - -async function executeTools({ - toolCalls, - tools, - tracer, - telemetry, - messages, - abortSignal, - experimental_context, - stepNumber, - model, - onToolCallStart, - onToolCallFinish, -}: { - toolCalls: Array>; - tools: TOOLS; - tracer: Tracer; - telemetry: TelemetrySettings | undefined; - messages: ModelMessage[]; - abortSignal: AbortSignal | undefined; - experimental_context: unknown; - stepNumber: number; - model: { provider: string; modelId: string }; - onToolCallStart: - | GenerateTextOnToolCallStartCallback - | Array | undefined | null> - | undefined; - onToolCallFinish: - | GenerateTextOnToolCallFinishCallback - | Array | undefined | null> - | undefined; -}): Promise>> { - const toolOutputs = await Promise.all( - toolCalls.map(async toolCall => - executeToolCall({ - toolCall, - tools, - tracer, - telemetry, - messages, - abortSignal, - experimental_context, - stepNumber, - model, - onToolCallStart, - onToolCallFinish, - }), - ), - ); - - return toolOutputs.filter( - (output): output is NonNullable => output != null, - ); -} - -class DefaultGenerateTextResult< - TOOLS extends ToolSet, - OUTPUT extends Output, -> implements GenerateTextResult { - readonly steps: GenerateTextResult['steps']; - readonly totalUsage: LanguageModelUsage; - private readonly _output: InferCompleteOutput | undefined; - - constructor(options: { - steps: GenerateTextResult['steps']; - output: InferCompleteOutput | undefined; - totalUsage: LanguageModelUsage; - }) { - this.steps = options.steps; - this._output = options.output; - this.totalUsage = options.totalUsage; - } - - private get finalStep() { - return this.steps[this.steps.length - 1]; - } - - get content() { - return this.finalStep.content; - } - - get text() { - return this.finalStep.text; - } - - get files() { - return this.finalStep.files; - } - - get reasoningText() { - return this.finalStep.reasoningText; - } - - get reasoning() { - return this.finalStep.reasoning; - } - - get toolCalls() { - return this.finalStep.toolCalls; - } - - get staticToolCalls() { - return this.finalStep.staticToolCalls; - } - - get dynamicToolCalls() { - return this.finalStep.dynamicToolCalls; - } - - get toolResults() { - return this.finalStep.toolResults; - } - - get staticToolResults() { - return this.finalStep.staticToolResults; - } - - get dynamicToolResults() { - return this.finalStep.dynamicToolResults; - } - - get sources() { - return this.finalStep.sources; - } - - get finishReason() { - return this.finalStep.finishReason; - } - - get rawFinishReason() { - return this.finalStep.rawFinishReason; - } - - get warnings() { - return this.finalStep.warnings; - } - - get providerMetadata() { - return this.finalStep.providerMetadata; - } - - get response() { - return this.finalStep.response; - } - - get request() { - return this.finalStep.request; - } - - get usage() { - return this.finalStep.usage; - } - - get experimental_output() { - return this.output; - } - - get output() { - if (this._output == null) { - throw new NoOutputGeneratedError(); - } - - return this._output; - } -} - -function asToolCalls(content: Array) { - const parts = content.filter( - (part): part is LanguageModelV3ToolCall => part.type === 'tool-call', - ); - - if (parts.length === 0) { - return undefined; - } - - return parts.map(toolCall => ({ - toolCallId: toolCall.toolCallId, - toolName: toolCall.toolName, - input: toolCall.input, - })); -} - -function asContent({ - content, - toolCalls, - toolOutputs, - toolApprovalRequests, - tools, -}: { - content: Array; - toolCalls: Array>; - toolOutputs: Array>; - toolApprovalRequests: Array>; - tools: TOOLS | undefined; -}): Array> { - const contentParts: Array> = []; - - for (const part of content) { - switch (part.type) { - case 'text': - case 'reasoning': - case 'source': - contentParts.push(part); - break; - - case 'file': { - contentParts.push({ - type: 'file' as const, - file: new DefaultGeneratedFile(part), - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - }); - break; - } - - case 'tool-call': { - contentParts.push( - toolCalls.find(toolCall => toolCall.toolCallId === part.toolCallId)!, - ); - break; - } - - case 'tool-result': { - const toolCall = toolCalls.find( - toolCall => toolCall.toolCallId === part.toolCallId, - ); - - // Handle deferred results for provider-executed tools (e.g., programmatic tool calling). - // When a server tool (like code_execution) triggers a client tool, the server tool's - // result may be deferred to a later turn. In this case, there's no matching tool-call - // in the current response. - if (toolCall == null) { - const tool = tools?.[part.toolName]; - const supportsDeferredResults = - tool?.type === 'provider' && tool.supportsDeferredResults; - - if (!supportsDeferredResults) { - throw new Error(`Tool call ${part.toolCallId} not found.`); - } - - // Create tool result without tool call input (deferred result) - if (part.isError) { - contentParts.push({ - type: 'tool-error' as const, - toolCallId: part.toolCallId, - toolName: part.toolName as keyof TOOLS & string, - input: undefined, - error: part.result, - providerExecuted: true, - dynamic: part.dynamic, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - } as TypedToolError); - } else { - contentParts.push({ - type: 'tool-result' as const, - toolCallId: part.toolCallId, - toolName: part.toolName as keyof TOOLS & string, - input: undefined, - output: part.result, - providerExecuted: true, - dynamic: part.dynamic, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - } as TypedToolResult); - } - break; - } - - if (part.isError) { - contentParts.push({ - type: 'tool-error' as const, - toolCallId: part.toolCallId, - toolName: part.toolName as keyof TOOLS & string, - input: toolCall.input, - error: part.result, - providerExecuted: true, - dynamic: toolCall.dynamic, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - } as TypedToolError); - } else { - contentParts.push({ - type: 'tool-result' as const, - toolCallId: part.toolCallId, - toolName: part.toolName as keyof TOOLS & string, - input: toolCall.input, - output: part.result, - providerExecuted: true, - dynamic: toolCall.dynamic, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - } as TypedToolResult); - } - break; - } - - case 'tool-approval-request': { - const toolCall = toolCalls.find( - toolCall => toolCall.toolCallId === part.toolCallId, - ); - - if (toolCall == null) { - throw new ToolCallNotFoundForApprovalError({ - toolCallId: part.toolCallId, - approvalId: part.approvalId, - }); - } - - contentParts.push({ - type: 'tool-approval-request' as const, - approvalId: part.approvalId, - toolCall, - }); - break; - } - } - } - - return [...contentParts, ...toolOutputs, ...toolApprovalRequests]; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/generated-file.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/generated-file.ts deleted file mode 100644 index 9ccd0ca80..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/generated-file.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { - convertBase64ToUint8Array, - convertUint8ArrayToBase64, -} from '@ai-sdk/provider-utils'; - -/** - * A generated file. - */ -export interface GeneratedFile { - /** - * File as a base64 encoded string. - */ - readonly base64: string; - - /** - * File as a Uint8Array. - */ - readonly uint8Array: Uint8Array; - - /** - * The IANA media type of the file. - * - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - readonly mediaType: string; -} - -export class DefaultGeneratedFile implements GeneratedFile { - private base64Data: string | undefined; - private uint8ArrayData: Uint8Array | undefined; - - readonly mediaType: string; - - constructor({ - data, - mediaType, - }: { - data: string | Uint8Array; - mediaType: string; - }) { - const isUint8Array = data instanceof Uint8Array; - this.base64Data = isUint8Array ? undefined : data; - this.uint8ArrayData = isUint8Array ? data : undefined; - this.mediaType = mediaType; - } - - // lazy conversion with caching to avoid unnecessary conversion overhead: - get base64() { - if (this.base64Data == null) { - this.base64Data = convertUint8ArrayToBase64(this.uint8ArrayData!); - } - return this.base64Data; - } - - // lazy conversion with caching to avoid unnecessary conversion overhead: - get uint8Array() { - if (this.uint8ArrayData == null) { - this.uint8ArrayData = convertBase64ToUint8Array(this.base64Data!); - } - return this.uint8ArrayData; - } -} - -export class DefaultGeneratedFileWithType extends DefaultGeneratedFile { - readonly type = 'file'; - - constructor(options: { data: string | Uint8Array; mediaType: string }) { - super(options); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/index.ts deleted file mode 100644 index b1e3e7815..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/index.ts +++ /dev/null @@ -1,74 +0,0 @@ -export { - generateText, - type GenerateTextOnFinishCallback, - type GenerateTextOnStartCallback, - type GenerateTextOnStepStartCallback, - type GenerateTextOnStepFinishCallback, - type GenerateTextOnToolCallStartCallback, - type GenerateTextOnToolCallFinishCallback, -} from './generate-text'; -export type { ContentPart } from './content-part'; -export type { GenerateTextResult } from './generate-text-result'; -export { - DefaultGeneratedFile, - type GeneratedFile as Experimental_GeneratedImage, // Image for backwards compatibility, TODO remove in v7 - type GeneratedFile, -} from './generated-file'; -export * as Output from './output'; -export type { - InferCompleteOutput as InferGenerateOutput, - InferPartialOutput as InferStreamOutput, -} from './output-utils'; -export type { PrepareStepFunction, PrepareStepResult } from './prepare-step'; -export { pruneMessages } from './prune-messages'; -export type { ReasoningOutput } from './reasoning-output'; -export { smoothStream, type ChunkDetector } from './smooth-stream'; -export type { StepResult } from './step-result'; -export { hasToolCall, stepCountIs, type StopCondition } from './stop-condition'; -export { - streamText, - type StreamTextOnChunkCallback, - type StreamTextOnErrorCallback, - type StreamTextOnFinishCallback, - type StreamTextOnStartCallback, - type StreamTextOnStepFinishCallback, - type StreamTextOnStepStartCallback, - type StreamTextOnToolCallFinishCallback, - type StreamTextOnToolCallStartCallback, - type StreamTextTransform, -} from './stream-text'; -export type { - StreamTextResult, - TextStreamPart, - UIMessageStreamOptions, -} from './stream-text-result'; -export type { ToolApprovalRequestOutput } from './tool-approval-request-output'; -export type { - DynamicToolCall, - StaticToolCall, - TypedToolCall, -} from './tool-call'; -export type { ToolCallRepairFunction } from './tool-call-repair-function'; -export type { - DynamicToolError, - StaticToolError, - TypedToolError, -} from './tool-error'; -export type { - StaticToolOutputDenied, - TypedToolOutputDenied, -} from './tool-output-denied'; -export type { - DynamicToolResult, - StaticToolResult, - TypedToolResult, -} from './tool-result'; -export type { ToolSet } from './tool-set'; -export type { - OnFinishEvent, - OnStartEvent, - OnStepFinishEvent, - OnStepStartEvent, - OnToolCallFinishEvent, - OnToolCallStartEvent, -} from './callback-events'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/is-approval-needed.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/is-approval-needed.ts deleted file mode 100644 index 834bc3b39..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/is-approval-needed.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { ModelMessage } from '@ai-sdk/provider-utils'; -import { TypedToolCall } from './tool-call'; -import { ToolSet } from './tool-set'; - -export async function isApprovalNeeded({ - tool, - toolCall, - messages, - experimental_context, -}: { - tool: TOOLS[keyof TOOLS]; - toolCall: TypedToolCall; - messages: ModelMessage[]; - experimental_context: unknown; -}) { - if (tool.needsApproval == null) { - return false; - } - - if (typeof tool.needsApproval === 'boolean') { - return tool.needsApproval; - } - - return await tool.needsApproval(toolCall.input, { - toolCallId: toolCall.toolCallId, - messages, - experimental_context, - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/output-utils.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/output-utils.ts deleted file mode 100644 index b79209719..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/output-utils.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Output } from './output'; - -/** - * Infers the complete output type from the output specification. - */ -export type InferCompleteOutput = - OUTPUT extends Output - ? COMPLETE_OUTPUT - : never; - -/** - * Infers the partial output type from the output specification. - */ -export type InferPartialOutput = - OUTPUT extends Output - ? PARTIAL_OUTPUT - : never; - -/** - * Infers the element type from an array output specification. - */ -export type InferElementOutput = - OUTPUT extends Output ? ELEMENT : never; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/output.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/output.ts deleted file mode 100644 index d1fa439ad..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/output.ts +++ /dev/null @@ -1,590 +0,0 @@ -import { - JSONValue, - LanguageModelV3CallOptions, - TypeValidationError, -} from '@ai-sdk/provider'; -import { - asSchema, - FlexibleSchema, - resolve, - safeParseJSON, - safeValidateTypes, -} from '@ai-sdk/provider-utils'; -import { NoObjectGeneratedError } from '../error/no-object-generated-error'; -import { FinishReason } from '../types/language-model'; -import { LanguageModelResponseMetadata } from '../types/language-model-response-metadata'; -import { LanguageModelUsage } from '../types/usage'; -import { DeepPartial } from '../util/deep-partial'; -import { parsePartialJson } from '../util/parse-partial-json'; -import { EnrichedStreamPart } from './stream-text'; - -export interface Output { - /** - * The name of the output mode. - */ - name: string; - - /** - * The response format to use for the model. - */ - responseFormat: PromiseLike; - - /** - * Parses the complete output of the model. - */ - parseCompleteOutput( - options: { text: string }, - context: { - response: LanguageModelResponseMetadata; - usage: LanguageModelUsage; - finishReason: FinishReason; - }, - ): Promise; - - /** - * Parses the partial output of the model. - */ - parsePartialOutput(options: { - text: string; - }): Promise<{ partial: PARTIAL } | undefined>; - - /** - * Creates a stream transform that emits individual elements as they complete. - */ - createElementStreamTransform(): - | TransformStream, ELEMENT> - | undefined; -} - -/** - * Output specification for text generation. - * This is the default output mode that generates plain text. - * - * @returns An output specification for generating text. - */ -export const text = (): Output => ({ - name: 'text', - responseFormat: Promise.resolve({ type: 'text' }), - - async parseCompleteOutput({ text }: { text: string }) { - return text; - }, - - async parsePartialOutput({ text }: { text: string }) { - return { partial: text }; - }, - - createElementStreamTransform() { - return undefined; - }, -}); - -/** - * Output specification for typed object generation using schemas. - * When the model generates a text response, it will return an object that matches the schema. - * - * @param schema - The schema of the object to generate. - * @param name - Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name. - * @param description - Optional description of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema description. - * - * @returns An output specification for generating objects with the specified schema. - */ -export const object = ({ - schema: inputSchema, - name, - description, -}: { - schema: FlexibleSchema; - /** - * Optional name of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. via tool or schema name. - */ - name?: string; - /** - * Optional description of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. via tool or schema description. - */ - description?: string; -}): Output, never> => { - const schema = asSchema(inputSchema); - - return { - name: 'object', - - responseFormat: resolve(schema.jsonSchema).then(jsonSchema => ({ - type: 'json' as const, - schema: jsonSchema, - ...(name != null && { name }), - ...(description != null && { description }), - })), - - async parseCompleteOutput( - { text }: { text: string }, - context: { - response: LanguageModelResponseMetadata; - usage: LanguageModelUsage; - finishReason: FinishReason; - }, - ) { - const parseResult = await safeParseJSON({ text }); - - if (!parseResult.success) { - throw new NoObjectGeneratedError({ - message: 'No object generated: could not parse the response.', - cause: parseResult.error, - text, - response: context.response, - usage: context.usage, - finishReason: context.finishReason, - }); - } - - const validationResult = await safeValidateTypes({ - value: parseResult.value, - schema, - }); - - if (!validationResult.success) { - throw new NoObjectGeneratedError({ - message: 'No object generated: response did not match schema.', - cause: validationResult.error, - text, - response: context.response, - usage: context.usage, - finishReason: context.finishReason, - }); - } - - return validationResult.value; - }, - - async parsePartialOutput({ text }: { text: string }) { - const result = await parsePartialJson(text); - - switch (result.state) { - case 'failed-parse': - case 'undefined-input': { - return undefined; - } - - case 'repaired-parse': - case 'successful-parse': { - return { - // Note: currently no validation of partial results: - partial: result.value as DeepPartial, - }; - } - } - }, - - createElementStreamTransform() { - return undefined; - }, - }; -}; - -/** - * Output specification for array generation. - * When the model generates a text response, it will return an array of elements. - * - * @param element - The schema of the array elements to generate. - * @param name - Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name. - * @param description - Optional description of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema description. - * - * @returns An output specification for generating an array of elements. - */ -export const array = ({ - element: inputElementSchema, - name, - description, -}: { - element: FlexibleSchema; - /** - * Optional name of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. via tool or schema name. - */ - name?: string; - /** - * Optional description of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. via tool or schema description. - */ - description?: string; -}): Output, Array, ELEMENT> => { - const elementSchema = asSchema(inputElementSchema); - - return { - name: 'array', - - // JSON schema that describes an array of elements: - responseFormat: resolve(elementSchema.jsonSchema).then(jsonSchema => { - // remove $schema from schema.jsonSchema: - const { $schema, ...itemSchema } = jsonSchema; - - return { - type: 'json' as const, - schema: { - $schema: 'http://json-schema.org/draft-07/schema#', - type: 'object', - properties: { - elements: { type: 'array', items: itemSchema }, - }, - required: ['elements'], - additionalProperties: false, - }, - ...(name != null && { name }), - ...(description != null && { description }), - }; - }), - - async parseCompleteOutput( - { text }: { text: string }, - context: { - response: LanguageModelResponseMetadata; - usage: LanguageModelUsage; - finishReason: FinishReason; - }, - ) { - const parseResult = await safeParseJSON({ text }); - - if (!parseResult.success) { - throw new NoObjectGeneratedError({ - message: 'No object generated: could not parse the response.', - cause: parseResult.error, - text, - response: context.response, - usage: context.usage, - finishReason: context.finishReason, - }); - } - - const outerValue = parseResult.value; - - if ( - outerValue == null || - typeof outerValue !== 'object' || - !('elements' in outerValue) || - !Array.isArray(outerValue.elements) - ) { - throw new NoObjectGeneratedError({ - message: 'No object generated: response did not match schema.', - cause: new TypeValidationError({ - value: outerValue, - cause: 'response must be an object with an elements array', - }), - text, - response: context.response, - usage: context.usage, - finishReason: context.finishReason, - }); - } - - for (const element of outerValue.elements) { - const validationResult = await safeValidateTypes({ - value: element, - schema: elementSchema, - }); - - if (!validationResult.success) { - throw new NoObjectGeneratedError({ - message: 'No object generated: response did not match schema.', - cause: validationResult.error, - text, - response: context.response, - usage: context.usage, - finishReason: context.finishReason, - }); - } - } - - return outerValue.elements as Array; - }, - - async parsePartialOutput({ text }: { text: string }) { - const result = await parsePartialJson(text); - - switch (result.state) { - case 'failed-parse': - case 'undefined-input': { - return undefined; - } - - case 'repaired-parse': - case 'successful-parse': { - const outerValue = result.value; - - // no parsable elements array - if ( - outerValue == null || - typeof outerValue !== 'object' || - !('elements' in outerValue) || - !Array.isArray(outerValue.elements) - ) { - return undefined; - } - - const rawElements = - result.state === 'repaired-parse' && outerValue.elements.length > 0 - ? outerValue.elements.slice(0, -1) - : outerValue.elements; - - const parsedElements: Array = []; - for (const rawElement of rawElements) { - const validationResult = await safeValidateTypes({ - value: rawElement, - schema: elementSchema, - }); - - if (validationResult.success) { - parsedElements.push(validationResult.value); - } - } - - return { partial: parsedElements }; - } - } - }, - - createElementStreamTransform() { - let publishedElements = 0; - - return new TransformStream< - EnrichedStreamPart>, - ELEMENT - >({ - transform({ partialOutput }, controller) { - if (partialOutput != null) { - // Only enqueue new elements that haven't been published yet - for ( - ; - publishedElements < partialOutput.length; - publishedElements++ - ) { - controller.enqueue(partialOutput[publishedElements]); - } - } - }, - }); - }, - }; -}; - -/** - * Output specification for choice generation. - * When the model generates a text response, it will return a one of the choice options. - * - * @param options - The available choices. - * @param name - Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name. - * @param description - Optional description of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema description. - * - * @returns An output specification for generating a choice. - */ -export const choice = ({ - options: choiceOptions, - name, - description, -}: { - options: Array; - /** - * Optional name of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. via tool or schema name. - */ - name?: string; - /** - * Optional description of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. via tool or schema description. - */ - description?: string; -}): Output => { - return { - name: 'choice', - - // JSON schema that describes an enumeration: - responseFormat: Promise.resolve({ - type: 'json', - schema: { - $schema: 'http://json-schema.org/draft-07/schema#', - type: 'object', - properties: { - result: { type: 'string', enum: choiceOptions }, - }, - required: ['result'], - additionalProperties: false, - }, - ...(name != null && { name }), - ...(description != null && { description }), - } as const), - - async parseCompleteOutput( - { text }: { text: string }, - context: { - response: LanguageModelResponseMetadata; - usage: LanguageModelUsage; - finishReason: FinishReason; - }, - ) { - const parseResult = await safeParseJSON({ text }); - - if (!parseResult.success) { - throw new NoObjectGeneratedError({ - message: 'No object generated: could not parse the response.', - cause: parseResult.error, - text, - response: context.response, - usage: context.usage, - finishReason: context.finishReason, - }); - } - - const outerValue = parseResult.value; - - if ( - outerValue == null || - typeof outerValue !== 'object' || - !('result' in outerValue) || - typeof outerValue.result !== 'string' || - !choiceOptions.includes(outerValue.result as any) - ) { - throw new NoObjectGeneratedError({ - message: 'No object generated: response did not match schema.', - cause: new TypeValidationError({ - value: outerValue, - cause: 'response must be an object that contains a choice value.', - }), - text, - response: context.response, - usage: context.usage, - finishReason: context.finishReason, - }); - } - - return outerValue.result as CHOICE; - }, - - async parsePartialOutput({ text }: { text: string }) { - const result = await parsePartialJson(text); - - switch (result.state) { - case 'failed-parse': - case 'undefined-input': { - return undefined; - } - - case 'repaired-parse': - case 'successful-parse': { - const outerValue = result.value; - - if ( - outerValue == null || - typeof outerValue !== 'object' || - !('result' in outerValue) || - typeof outerValue.result !== 'string' - ) { - return undefined; - } - - // list of potential matches. - const potentialMatches = choiceOptions.filter(choiceOption => - choiceOption.startsWith(outerValue.result as string), - ); - - if (result.state === 'successful-parse') { - // successful parse: exact choice value - return potentialMatches.includes(outerValue.result as any) - ? { partial: outerValue.result as CHOICE } - : undefined; - } else { - // repaired parse: only return if not ambiguous - return potentialMatches.length === 1 - ? { partial: potentialMatches[0] as CHOICE } - : undefined; - } - } - } - }, - - createElementStreamTransform() { - return undefined; - }, - }; -}; - -/** - * Output specification for unstructured JSON generation. - * When the model generates a text response, it will return a JSON object. - * - * @param name - Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name. - * @param description - Optional description of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema description. - * - * @returns An output specification for generating JSON. - */ -export const json = ({ - name, - description, -}: { - /** - * Optional name of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. via tool or schema name. - */ - name?: string; - /** - * Optional description of the output that should be generated. - * Used by some providers for additional LLM guidance, e.g. via tool or schema description. - */ - description?: string; -} = {}): Output => { - return { - name: 'json', - - responseFormat: Promise.resolve({ - type: 'json' as const, - ...(name != null && { name }), - ...(description != null && { description }), - }), - - async parseCompleteOutput( - { text }: { text: string }, - context: { - response: LanguageModelResponseMetadata; - usage: LanguageModelUsage; - finishReason: FinishReason; - }, - ) { - const parseResult = await safeParseJSON({ text }); - - if (!parseResult.success) { - throw new NoObjectGeneratedError({ - message: 'No object generated: could not parse the response.', - cause: parseResult.error, - text, - response: context.response, - usage: context.usage, - finishReason: context.finishReason, - }); - } - - return parseResult.value; - }, - - async parsePartialOutput({ text }: { text: string }) { - const result = await parsePartialJson(text); - - switch (result.state) { - case 'failed-parse': - case 'undefined-input': { - return undefined; - } - - case 'repaired-parse': - case 'successful-parse': { - return result.value === undefined - ? undefined - : { partial: result.value }; - } - } - }, - - createElementStreamTransform() { - return undefined; - }, - }; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/parse-tool-call.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/parse-tool-call.ts deleted file mode 100644 index 3e0b4d7f1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/parse-tool-call.ts +++ /dev/null @@ -1,188 +0,0 @@ -import { LanguageModelV3ToolCall } from '@ai-sdk/provider'; -import { - asSchema, - ModelMessage, - safeParseJSON, - safeValidateTypes, - SystemModelMessage, -} from '@ai-sdk/provider-utils'; -import { InvalidToolInputError } from '../error/invalid-tool-input-error'; -import { NoSuchToolError } from '../error/no-such-tool-error'; -import { ToolCallRepairError } from '../error/tool-call-repair-error'; -import { DynamicToolCall, TypedToolCall } from './tool-call'; -import { ToolCallRepairFunction } from './tool-call-repair-function'; -import { ToolSet } from './tool-set'; - -export async function parseToolCall({ - toolCall, - tools, - repairToolCall, - system, - messages, -}: { - toolCall: LanguageModelV3ToolCall; - tools: TOOLS | undefined; - repairToolCall: ToolCallRepairFunction | undefined; - system: string | SystemModelMessage | Array | undefined; - messages: ModelMessage[]; -}): Promise> { - try { - if (tools == null) { - // provider-executed dynamic tools are not part of our list of tools: - if (toolCall.providerExecuted && toolCall.dynamic) { - return await parseProviderExecutedDynamicToolCall(toolCall); - } - - throw new NoSuchToolError({ toolName: toolCall.toolName }); - } - - try { - return await doParseToolCall({ toolCall, tools }); - } catch (error) { - if ( - repairToolCall == null || - !( - NoSuchToolError.isInstance(error) || - InvalidToolInputError.isInstance(error) - ) - ) { - throw error; - } - - let repairedToolCall: LanguageModelV3ToolCall | null = null; - - try { - repairedToolCall = await repairToolCall({ - toolCall, - tools, - inputSchema: async ({ toolName }) => { - const { inputSchema } = tools[toolName]; - return await asSchema(inputSchema).jsonSchema; - }, - system, - messages, - error, - }); - } catch (repairError) { - throw new ToolCallRepairError({ - cause: repairError, - originalError: error, - }); - } - - // no repaired tool call returned - if (repairedToolCall == null) { - throw error; - } - - return await doParseToolCall({ toolCall: repairedToolCall, tools }); - } - } catch (error) { - // use parsed input when possible - const parsedInput = await safeParseJSON({ text: toolCall.input }); - const input = parsedInput.success ? parsedInput.value : toolCall.input; - - // TODO AI SDK 6: special invalid tool call parts - return { - type: 'tool-call', - toolCallId: toolCall.toolCallId, - toolName: toolCall.toolName, - input, - dynamic: true, - invalid: true, - error, - title: tools?.[toolCall.toolName]?.title, - providerExecuted: toolCall.providerExecuted, - providerMetadata: toolCall.providerMetadata, - }; - } -} - -async function parseProviderExecutedDynamicToolCall( - toolCall: LanguageModelV3ToolCall, -): Promise { - const parseResult = - toolCall.input.trim() === '' - ? { success: true as const, value: {} } - : await safeParseJSON({ text: toolCall.input }); - - if (parseResult.success === false) { - throw new InvalidToolInputError({ - toolName: toolCall.toolName, - toolInput: toolCall.input, - cause: parseResult.error, - }); - } - - return { - type: 'tool-call', - toolCallId: toolCall.toolCallId, - toolName: toolCall.toolName, - input: parseResult.value, - providerExecuted: true, - dynamic: true, - providerMetadata: toolCall.providerMetadata, - }; -} - -async function doParseToolCall({ - toolCall, - tools, -}: { - toolCall: LanguageModelV3ToolCall; - tools: TOOLS; -}): Promise> { - const toolName = toolCall.toolName as keyof TOOLS & string; - - const tool = tools[toolName]; - - if (tool == null) { - // provider-executed dynamic tools are not part of our list of tools: - if (toolCall.providerExecuted && toolCall.dynamic) { - return await parseProviderExecutedDynamicToolCall(toolCall); - } - - throw new NoSuchToolError({ - toolName: toolCall.toolName, - availableTools: Object.keys(tools), - }); - } - - const schema = asSchema(tool.inputSchema); - - // when the tool call has no arguments, we try passing an empty object to the schema - // (many LLMs generate empty strings for tool calls with no arguments) - const parseResult = - toolCall.input.trim() === '' - ? await safeValidateTypes({ value: {}, schema }) - : await safeParseJSON({ text: toolCall.input, schema }); - - if (parseResult.success === false) { - throw new InvalidToolInputError({ - toolName, - toolInput: toolCall.input, - cause: parseResult.error, - }); - } - - return tool.type === 'dynamic' - ? { - type: 'tool-call', - toolCallId: toolCall.toolCallId, - toolName: toolCall.toolName, - input: parseResult.value, - providerExecuted: toolCall.providerExecuted, - providerMetadata: toolCall.providerMetadata, - dynamic: true, - title: tool.title, - } - : { - type: 'tool-call', - toolCallId: toolCall.toolCallId, - toolName, - input: parseResult.value, - providerExecuted: toolCall.providerExecuted, - providerMetadata: toolCall.providerMetadata, - title: tool.title, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/prepare-step.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/prepare-step.ts deleted file mode 100644 index f3f367094..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/prepare-step.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { - ModelMessage, - ProviderOptions, - SystemModelMessage, - Tool, -} from '@ai-sdk/provider-utils'; -import { LanguageModel, ToolChoice } from '../types/language-model'; -import { StepResult } from './step-result'; - -/** - * Function that you can use to provide different settings for a step. - * - * @param options - The options for the step. - * @param options.steps - The steps that have been executed so far. - * @param options.stepNumber - The number of the step that is being executed. - * @param options.model - The model that is being used. - * @param options.messages - The messages that will be sent to the model for the current step. - * @param options.experimental_context - The context passed via the experimental_context setting (experimental). - * - * @returns An object that contains the settings for the step. - * If you return undefined (or for undefined settings), the settings from the outer level will be used. - */ -export type PrepareStepFunction< - TOOLS extends Record = Record, -> = (options: { - /** - * The steps that have been executed so far. - */ - steps: Array>>; - - /** - * The number of the step that is being executed. - */ - stepNumber: number; - - /** - * The model instance that is being used for this step. - */ - model: LanguageModel; - - /** - * The messages that will be sent to the model for the current step. - */ - messages: Array; - - /** - * The context passed via the experimental_context setting (experimental). - */ - experimental_context: unknown; -}) => PromiseLike> | PrepareStepResult; - -/** - * The result type returned by a {@link PrepareStepFunction}, - * allowing per-step overrides of model, tools, or messages. - */ -export type PrepareStepResult< - TOOLS extends Record = Record, -> = - | { - /** - * Optionally override which LanguageModel instance is used for this step. - */ - model?: LanguageModel; - - /** - * Optionally set which tool the model must call, or provide tool call configuration - * for this step. - */ - toolChoice?: ToolChoice>; - - /** - * If provided, only these tools are enabled/available for this step. - */ - activeTools?: Array>; - - /** - * Optionally override the system message(s) sent to the model for this step. - */ - system?: string | SystemModelMessage | Array; - - /** - * Optionally override the full set of messages sent to the model - * for this step. - */ - messages?: Array; - - /** - * Context that is passed into tool execution. Experimental. - * - * Changing the context will affect the context in this step - * and all subsequent steps. - */ - experimental_context?: unknown; - - /** - * Additional provider-specific options for this step. - * - * Can be used to pass provider-specific configuration such as - * container IDs for Anthropic's code execution. - */ - providerOptions?: ProviderOptions; - } - | undefined; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/prune-messages.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/prune-messages.ts deleted file mode 100644 index 953cc3ea7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/prune-messages.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { - AssistantModelMessage, - ModelMessage, - ToolModelMessage, -} from '@ai-sdk/provider-utils'; - -/** - * Prunes model messages from a list of model messages. - * - * @param messages - The list of model messages to prune. - * @param reasoning - How to remove reasoning content from assistant messages. Default is `'none'`. - * @param toolCalls - How to prune tool call/results/approval content. Default is `[]`. - * @param emptyMessages - Whether to keep or remove messages whose content is empty after pruning. Default is `'remove'`. - * - * @returns The pruned list of model messages. - */ -export function pruneMessages({ - messages, - reasoning = 'none', - toolCalls = [], - emptyMessages = 'remove', -}: { - messages: ModelMessage[]; - reasoning?: 'all' | 'before-last-message' | 'none'; - toolCalls?: - | 'all' - | 'before-last-message' - | `before-last-${number}-messages` - | 'none' - | Array<{ - type: 'all' | 'before-last-message' | `before-last-${number}-messages`; - tools?: string[]; - }>; - emptyMessages?: 'keep' | 'remove'; -}): ModelMessage[] { - // filter reasoning parts: - if (reasoning === 'all' || reasoning === 'before-last-message') { - messages = messages.map((message, messageIndex) => { - if ( - message.role !== 'assistant' || - typeof message.content === 'string' || - (reasoning === 'before-last-message' && - messageIndex === messages.length - 1) - ) { - return message; - } - - return { - ...message, - content: message.content.filter(part => part.type !== 'reasoning'), - }; - }); - } - - // filter tool calls, results, errors, and approvals: - if (toolCalls === 'none') { - toolCalls = []; - } else if (toolCalls === 'all') { - toolCalls = [{ type: 'all' }]; - } else if (toolCalls === 'before-last-message') { - toolCalls = [{ type: 'before-last-message' }]; - } else if (typeof toolCalls === 'string') { - toolCalls = [{ type: toolCalls }]; - } - - for (const toolCall of toolCalls) { - // determine how many trailing messages to keep: - const keepLastMessagesCount = - toolCall.type === 'all' - ? undefined - : toolCall.type === 'before-last-message' - ? 1 - : Number( - toolCall.type - .slice('before-last-'.length) - .slice(0, -'-messages'.length), - ); - - // scan kept messages to identify tool calls and approvals that need to be kept: - const keptToolCallIds: Set = new Set(); - const keptApprovalIds: Set = new Set(); - - if (keepLastMessagesCount != null) { - for (const message of messages.slice(-keepLastMessagesCount)) { - if ( - (message.role === 'assistant' || message.role === 'tool') && - typeof message.content !== 'string' - ) { - for (const part of message.content) { - if (part.type === 'tool-call' || part.type === 'tool-result') { - keptToolCallIds.add(part.toolCallId); - } else if ( - part.type === 'tool-approval-request' || - part.type === 'tool-approval-response' - ) { - keptApprovalIds.add(part.approvalId); - } - } - } - } - } - - messages = messages.map((message, messageIndex) => { - if ( - (message.role !== 'assistant' && message.role !== 'tool') || - typeof message.content === 'string' || - (keepLastMessagesCount && - messageIndex >= messages.length - keepLastMessagesCount) - ) { - return message; - } - - const toolCallIdToToolName: Record = {}; - const approvalIdToToolName: Record = {}; - - return { - ...message, - content: message.content.filter(part => { - // keep non-tool parts: - if ( - part.type !== 'tool-call' && - part.type !== 'tool-result' && - part.type !== 'tool-approval-request' && - part.type !== 'tool-approval-response' - ) { - return true; - } - - // track tool calls and approvals: - if (part.type === 'tool-call') { - toolCallIdToToolName[part.toolCallId] = part.toolName; - } else if (part.type === 'tool-approval-request') { - approvalIdToToolName[part.approvalId] = - toolCallIdToToolName[part.toolCallId]; - } - - // keep parts that are associated with a tool call or approval that needs to be kept: - if ( - ((part.type === 'tool-call' || part.type === 'tool-result') && - keptToolCallIds.has(part.toolCallId)) || - ((part.type === 'tool-approval-request' || - part.type === 'tool-approval-response') && - keptApprovalIds.has(part.approvalId)) - ) { - return true; - } - - // keep parts that are not associated with a tool that should be removed: - return ( - toolCall.tools != null && - !toolCall.tools.includes( - part.type === 'tool-call' || part.type === 'tool-result' - ? part.toolName - : approvalIdToToolName[part.approvalId], - ) - ); - }), - } as AssistantModelMessage | ToolModelMessage; - }); - } - - if (emptyMessages === 'remove') { - messages = messages.filter(message => message.content.length > 0); - } - - return messages; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/reasoning-output.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/reasoning-output.ts deleted file mode 100644 index 85c03103b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/reasoning-output.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ProviderMetadata } from '../types/provider-metadata'; - -/** - * Reasoning output of a text generation. It contains a reasoning. - */ -export interface ReasoningOutput { - type: 'reasoning'; - - /** - * The reasoning text. - */ - text: string; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerMetadata?: ProviderMetadata; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/reasoning.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/reasoning.ts deleted file mode 100644 index 81a5e4729..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/reasoning.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ReasoningPart } from '@ai-sdk/provider-utils'; - -export function asReasoningText( - reasoningParts: Array, -): string | undefined { - const reasoningText = reasoningParts.map(part => part.text).join(''); - return reasoningText.length > 0 ? reasoningText : undefined; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/response-message.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/response-message.ts deleted file mode 100644 index b9ed2adc2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/response-message.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { - AssistantModelMessage, - ToolModelMessage, -} from '@ai-sdk/provider-utils'; - -/** - * A message that was generated during the generation process. - * It can be either an assistant message or a tool message. - */ -export type ResponseMessage = AssistantModelMessage | ToolModelMessage; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/run-tools-transformation.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/run-tools-transformation.ts deleted file mode 100644 index 3ca22e452..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/run-tools-transformation.ts +++ /dev/null @@ -1,448 +0,0 @@ -import { LanguageModelV3StreamPart, SharedV3Warning } from '@ai-sdk/provider'; -import { - getErrorMessage, - IdGenerator, - ModelMessage, - SystemModelMessage, -} from '@ai-sdk/provider-utils'; -import { Tracer } from '@opentelemetry/api'; -import { ToolCallNotFoundForApprovalError } from '../error/tool-call-not-found-for-approval-error'; -import { TelemetrySettings } from '../telemetry/telemetry-settings'; -import { FinishReason, LanguageModelUsage, ProviderMetadata } from '../types'; -import { Source } from '../types/language-model'; -import { asLanguageModelUsage } from '../types/usage'; -import { executeToolCall } from './execute-tool-call'; -import { - StreamTextOnToolCallFinishCallback, - StreamTextOnToolCallStartCallback, -} from './stream-text'; -import { DefaultGeneratedFileWithType, GeneratedFile } from './generated-file'; -import { isApprovalNeeded } from './is-approval-needed'; -import { parseToolCall } from './parse-tool-call'; -import { ToolApprovalRequestOutput } from './tool-approval-request-output'; -import { TypedToolCall } from './tool-call'; -import { ToolCallRepairFunction } from './tool-call-repair-function'; -import { TypedToolError } from './tool-error'; -import { TypedToolResult } from './tool-result'; -import { ToolSet } from './tool-set'; - -export type SingleRequestTextStreamPart = - // Text blocks: - | { - type: 'text-start'; - providerMetadata?: ProviderMetadata; - id: string; - } - | { - type: 'text-delta'; - id: string; - providerMetadata?: ProviderMetadata; - delta: string; - } - | { - type: 'text-end'; - providerMetadata?: ProviderMetadata; - id: string; - } - - // Reasoning blocks: - | { - type: 'reasoning-start'; - providerMetadata?: ProviderMetadata; - id: string; - } - | { - type: 'reasoning-delta'; - id: string; - providerMetadata?: ProviderMetadata; - delta: string; - } - | { - type: 'reasoning-end'; - id: string; - providerMetadata?: ProviderMetadata; - } - - // Tool calls: - | { - type: 'tool-input-start'; - id: string; - toolName: string; - providerMetadata?: ProviderMetadata; - dynamic?: boolean; - title?: string; - } - | { - type: 'tool-input-delta'; - id: string; - delta: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'tool-input-end'; - id: string; - providerMetadata?: ProviderMetadata; - } - | ToolApprovalRequestOutput - - // Other types: - | ({ type: 'source' } & Source) - | { type: 'file'; file: GeneratedFile; providerMetadata?: ProviderMetadata } // different because of GeneratedFile object - | ({ type: 'tool-call' } & TypedToolCall) - | ({ type: 'tool-result' } & TypedToolResult) - | ({ type: 'tool-error' } & TypedToolError) - | { type: 'stream-start'; warnings: SharedV3Warning[] } - | { - type: 'response-metadata'; - id?: string; - timestamp?: Date; - modelId?: string; - } - | { - type: 'finish'; - finishReason: FinishReason; - rawFinishReason: string | undefined; - usage: LanguageModelUsage; - providerMetadata?: ProviderMetadata; - } - | { type: 'error'; error: unknown } - | { type: 'raw'; rawValue: unknown }; - -export function runToolsTransformation({ - tools, - generatorStream, - tracer, - telemetry, - system, - messages, - abortSignal, - repairToolCall, - experimental_context, - generateId, - stepNumber, - model, - onToolCallStart, - onToolCallFinish, -}: { - tools: TOOLS | undefined; - generatorStream: ReadableStream; - tracer: Tracer; - telemetry: TelemetrySettings | undefined; - system: string | SystemModelMessage | Array | undefined; - messages: ModelMessage[]; - abortSignal: AbortSignal | undefined; - repairToolCall: ToolCallRepairFunction | undefined; - experimental_context: unknown; - generateId: IdGenerator; - stepNumber?: number; - model?: { provider: string; modelId: string }; - onToolCallStart?: - | StreamTextOnToolCallStartCallback - | Array | undefined | null>; - onToolCallFinish?: - | StreamTextOnToolCallFinishCallback - | Array | undefined | null>; -}): ReadableStream> { - // tool results stream - let toolResultsStreamController: ReadableStreamDefaultController< - SingleRequestTextStreamPart - > | null = null; - const toolResultsStream = new ReadableStream< - SingleRequestTextStreamPart - >({ - start(controller) { - toolResultsStreamController = controller; - }, - }); - - // keep track of outstanding tool results for stream closing: - const outstandingToolResults = new Set(); - - // keep track of tool inputs for provider-side tool results - const toolInputs = new Map(); - - // keep track of parsed tool calls so provider-emitted approval requests can reference them - const toolCallsByToolCallId = new Map>(); - - let canClose = false; - let finishChunk: - | (SingleRequestTextStreamPart & { type: 'finish' }) - | undefined = undefined; - - function attemptClose() { - // close the tool results controller if no more outstanding tool calls - if (canClose && outstandingToolResults.size === 0) { - // we delay sending the finish chunk until all tool results (incl. delayed ones) - // are received to ensure that the frontend receives tool results before a message - // finish event arrives. - if (finishChunk != null) { - toolResultsStreamController!.enqueue(finishChunk); - } - - toolResultsStreamController!.close(); - } - } - - // forward stream - const forwardStream = new TransformStream< - LanguageModelV3StreamPart, - SingleRequestTextStreamPart - >({ - async transform( - chunk: LanguageModelV3StreamPart, - controller: TransformStreamDefaultController< - SingleRequestTextStreamPart - >, - ) { - const chunkType = chunk.type; - - switch (chunkType) { - // forward: - case 'stream-start': - case 'text-start': - case 'text-delta': - case 'text-end': - case 'reasoning-start': - case 'reasoning-delta': - case 'reasoning-end': - case 'tool-input-start': - case 'tool-input-delta': - case 'tool-input-end': - case 'source': - case 'response-metadata': - case 'error': - case 'raw': { - controller.enqueue(chunk); - break; - } - - case 'file': { - controller.enqueue({ - type: 'file', - file: new DefaultGeneratedFileWithType({ - data: chunk.data, - mediaType: chunk.mediaType, - }), - ...(chunk.providerMetadata != null - ? { providerMetadata: chunk.providerMetadata } - : {}), - }); - break; - } - - case 'finish': { - finishChunk = { - type: 'finish', - finishReason: chunk.finishReason.unified, - rawFinishReason: chunk.finishReason.raw, - usage: asLanguageModelUsage(chunk.usage), - providerMetadata: chunk.providerMetadata, - }; - break; - } - - case 'tool-approval-request': { - const toolCall = toolCallsByToolCallId.get(chunk.toolCallId); - if (toolCall == null) { - toolResultsStreamController!.enqueue({ - type: 'error', - error: new ToolCallNotFoundForApprovalError({ - toolCallId: chunk.toolCallId, - approvalId: chunk.approvalId, - }), - }); - break; - } - - controller.enqueue({ - type: 'tool-approval-request', - approvalId: chunk.approvalId, - toolCall, - }); - break; - } - - // process tool call: - case 'tool-call': { - try { - const toolCall = await parseToolCall({ - toolCall: chunk, - tools, - repairToolCall, - system, - messages, - }); - - toolCallsByToolCallId.set(toolCall.toolCallId, toolCall); - controller.enqueue(toolCall); - - if (toolCall.invalid) { - toolResultsStreamController!.enqueue({ - type: 'tool-error', - toolCallId: toolCall.toolCallId, - toolName: toolCall.toolName, - input: toolCall.input, - error: getErrorMessage(toolCall.error!), - dynamic: true, - title: toolCall.title, - }); - break; - } - - const tool = tools?.[toolCall.toolName]; - - if (tool == null) { - // ignore tool calls for tools that are not available, - // e.g. provider-executed dynamic tools - break; - } - - if (tool.onInputAvailable != null) { - await tool.onInputAvailable({ - input: toolCall.input, - toolCallId: toolCall.toolCallId, - messages, - abortSignal, - experimental_context, - }); - } - - if ( - await isApprovalNeeded({ - tool, - toolCall, - messages, - experimental_context, - }) - ) { - toolResultsStreamController!.enqueue({ - type: 'tool-approval-request', - approvalId: generateId(), - toolCall, - }); - break; - } - - toolInputs.set(toolCall.toolCallId, toolCall.input); - - // Only execute tools that are not provider-executed: - if (tool.execute != null && toolCall.providerExecuted !== true) { - const toolExecutionId = generateId(); // use our own id to guarantee uniqueness - outstandingToolResults.add(toolExecutionId); - - // Note: we don't await the tool execution here (by leaving out 'await' on recordSpan), - // because we want to process the next chunk as soon as possible. - // This is important for the case where the tool execution takes a long time. - executeToolCall({ - toolCall, - tools, - tracer, - telemetry, - messages, - abortSignal, - experimental_context, - stepNumber, - model, - onToolCallStart, - onToolCallFinish, - onPreliminaryToolResult: result => { - toolResultsStreamController!.enqueue(result); - }, - }) - .then(result => { - toolResultsStreamController!.enqueue(result); - }) - .catch(error => { - toolResultsStreamController!.enqueue({ - type: 'error', - error, - }); - }) - .finally(() => { - outstandingToolResults.delete(toolExecutionId); - attemptClose(); - }); - } - } catch (error) { - toolResultsStreamController!.enqueue({ type: 'error', error }); - } - - break; - } - - case 'tool-result': { - const toolName = chunk.toolName as keyof TOOLS & string; - - if (chunk.isError) { - toolResultsStreamController!.enqueue({ - type: 'tool-error', - toolCallId: chunk.toolCallId, - toolName, - input: toolInputs.get(chunk.toolCallId), - providerExecuted: true, - error: chunk.result, - dynamic: chunk.dynamic, - ...(chunk.providerMetadata != null - ? { providerMetadata: chunk.providerMetadata } - : {}), - } as TypedToolError); - } else { - controller.enqueue({ - type: 'tool-result', - toolCallId: chunk.toolCallId, - toolName, - input: toolInputs.get(chunk.toolCallId), - output: chunk.result, - providerExecuted: true, - dynamic: chunk.dynamic, - ...(chunk.providerMetadata != null - ? { providerMetadata: chunk.providerMetadata } - : {}), - } as TypedToolResult); - } - break; - } - - default: { - const _exhaustiveCheck: never = chunkType; - throw new Error(`Unhandled chunk type: ${_exhaustiveCheck}`); - } - } - }, - - flush() { - canClose = true; - attemptClose(); - }, - }); - - // combine the generator stream and the tool results stream - return new ReadableStream>({ - async start(controller) { - // need to wait for both pipes so there are no dangling promises that - // can cause uncaught promise rejections when the stream is aborted - return Promise.all([ - generatorStream.pipeThrough(forwardStream).pipeTo( - new WritableStream({ - write(chunk) { - controller.enqueue(chunk); - }, - close() { - // the generator stream controller is automatically closed when it's consumed - }, - }), - ), - toolResultsStream.pipeTo( - new WritableStream({ - write(chunk) { - controller.enqueue(chunk); - }, - close() { - controller.close(); - }, - }), - ), - ]); - }, - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/smooth-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/smooth-stream.ts deleted file mode 100644 index 64e50677b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/smooth-stream.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { delay as originalDelay } from '@ai-sdk/provider-utils'; -import { SharedV3ProviderMetadata } from '@ai-sdk/provider'; -import { TextStreamPart } from './stream-text-result'; -import { ToolSet } from './tool-set'; -import { InvalidArgumentError } from '@ai-sdk/provider'; - -const CHUNKING_REGEXPS = { - word: /\S+\s+/m, - line: /\n+/m, -}; - -/** - * Detects the first chunk in a buffer. - * - * @param buffer - The buffer to detect the first chunk in. - * - * @returns The first detected chunk, or `undefined` if no chunk was detected. - */ -export type ChunkDetector = (buffer: string) => string | undefined | null; - -/** - * Smooths text and reasoning streaming output. - * - * @param delayInMs - The delay in milliseconds between each chunk. Defaults to 10ms. Can be set to `null` to skip the delay. - * @param chunking - Controls how the text is chunked for streaming. Use "word" to stream word by word (default), "line" to stream line by line, provide a custom RegExp pattern for custom chunking, provide an Intl.Segmenter for locale-aware word segmentation (recommended for CJK languages), or provide a custom ChunkDetector function. - * - * @returns A transform stream that smooths text streaming output. - */ -export function smoothStream({ - delayInMs = 10, - chunking = 'word', - _internal: { delay = originalDelay } = {}, -}: { - delayInMs?: number | null; - chunking?: 'word' | 'line' | RegExp | ChunkDetector | Intl.Segmenter; - /** - * Internal. For test use only. May change without notice. - */ - _internal?: { - delay?: (delayInMs: number | null) => Promise; - }; -} = {}): (options: { - tools: TOOLS; -}) => TransformStream, TextStreamPart> { - let detectChunk: ChunkDetector; - - // Check if chunking is an Intl.Segmenter (duck-typing for segment method) - if ( - chunking != null && - typeof chunking === 'object' && - 'segment' in chunking && - typeof chunking.segment === 'function' - ) { - const segmenter = chunking as Intl.Segmenter; - detectChunk = (buffer: string) => { - if (buffer.length === 0) return null; - const iterator = segmenter.segment(buffer)[Symbol.iterator](); - const first = iterator.next().value; - return first?.segment || null; - }; - } else if (typeof chunking === 'function') { - detectChunk = buffer => { - const match = chunking(buffer); - - if (match == null) { - return null; - } - - if (!match.length) { - throw new Error(`Chunking function must return a non-empty string.`); - } - - if (!buffer.startsWith(match)) { - throw new Error( - `Chunking function must return a match that is a prefix of the buffer. Received: "${match}" expected to start with "${buffer}"`, - ); - } - - return match; - }; - } else { - const chunkingRegex = - typeof chunking === 'string' - ? CHUNKING_REGEXPS[chunking] - : chunking instanceof RegExp - ? chunking - : undefined; - - if (chunkingRegex == null) { - throw new InvalidArgumentError({ - argument: 'chunking', - message: `Chunking must be "word", "line", a RegExp, an Intl.Segmenter, or a ChunkDetector function. Received: ${chunking}`, - }); - } - - detectChunk = buffer => { - const match = chunkingRegex.exec(buffer); - - if (!match) { - return null; - } - - return buffer.slice(0, match.index) + match?.[0]; - }; - } - - return () => { - let buffer = ''; - let id = ''; - let type: 'text-delta' | 'reasoning-delta' | undefined = undefined; - let providerMetadata: SharedV3ProviderMetadata | undefined = undefined; - - function flushBuffer( - controller: TransformStreamDefaultController>, - ) { - if (buffer.length > 0 && type !== undefined) { - controller.enqueue({ - type, - text: buffer, - id, - ...(providerMetadata != null ? { providerMetadata } : {}), - }); - buffer = ''; - providerMetadata = undefined; - } - } - - return new TransformStream, TextStreamPart>({ - async transform(chunk, controller) { - // Handle non-smoothable chunks: flush buffer and pass through - if (chunk.type !== 'text-delta' && chunk.type !== 'reasoning-delta') { - flushBuffer(controller); - controller.enqueue(chunk); - return; - } - - // Flush buffer when type or id changes - if ((chunk.type !== type || chunk.id !== id) && buffer.length > 0) { - flushBuffer(controller); - } - - buffer += chunk.text; - id = chunk.id; - type = chunk.type; - - // Preserve providerMetadata (e.g., Anthropic thinking signatures) - if (chunk.providerMetadata != null) { - providerMetadata = chunk.providerMetadata; - } - - let match; - - while ((match = detectChunk(buffer)) != null) { - controller.enqueue({ type, text: match, id }); - buffer = buffer.slice(match.length); - - await delay(delayInMs); - } - }, - }); - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/step-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/step-result.ts deleted file mode 100644 index f1f8a3a41..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/step-result.ts +++ /dev/null @@ -1,290 +0,0 @@ -import { ReasoningPart } from '@ai-sdk/provider-utils'; -import { - CallWarning, - FinishReason, - LanguageModelRequestMetadata, - LanguageModelResponseMetadata, - ProviderMetadata, -} from '../types'; -import { Source } from '../types/language-model'; -import { LanguageModelUsage } from '../types/usage'; -import { ContentPart } from './content-part'; -import { GeneratedFile } from './generated-file'; -import { ResponseMessage } from './response-message'; -import { DynamicToolCall, StaticToolCall, TypedToolCall } from './tool-call'; -import { - DynamicToolResult, - StaticToolResult, - TypedToolResult, -} from './tool-result'; -import { ToolSet } from './tool-set'; - -/** - * The result of a single step in the generation process. - */ -export type StepResult = { - /** - * Zero-based index of this step. - */ - readonly stepNumber: number; - - /** - * Information about the model that produced this step. - */ - readonly model: { - /** The provider of the model. */ - readonly provider: string; - /** The ID of the model. */ - readonly modelId: string; - }; - - /** - * Identifier from telemetry settings for grouping related operations. - */ - readonly functionId: string | undefined; - - /** - * Additional metadata from telemetry settings. - */ - readonly metadata: Record | undefined; - - /** - * User-defined context object flowing through the generation. - * - * Experimental (can break in patch releases). - */ - readonly experimental_context: unknown; - - /** - * The content that was generated in the last step. - */ - readonly content: Array>; - - /** - * The generated text. - */ - readonly text: string; - - /** - * The reasoning that was generated during the generation. - */ - readonly reasoning: Array; - - /** - * The reasoning text that was generated during the generation. - */ - readonly reasoningText: string | undefined; - - /** - * The files that were generated during the generation. - */ - readonly files: Array; - - /** - * The sources that were used to generate the text. - */ - readonly sources: Array; - - /** - * The tool calls that were made during the generation. - */ - readonly toolCalls: Array>; - - /** - * The static tool calls that were made in the last step. - */ - readonly staticToolCalls: Array>; - - /** - * The dynamic tool calls that were made in the last step. - */ - readonly dynamicToolCalls: Array; - - /** - * The results of the tool calls. - */ - readonly toolResults: Array>; - - /** - * The static tool results that were made in the last step. - */ - readonly staticToolResults: Array>; - - /** - * The dynamic tool results that were made in the last step. - */ - readonly dynamicToolResults: Array; - - /** - * The unified reason why the generation finished. - */ - readonly finishReason: FinishReason; - - /** - * The raw reason why the generation finished (from the provider). - */ - readonly rawFinishReason: string | undefined; - - /** - * The token usage of the generated text. - */ - readonly usage: LanguageModelUsage; - - /** - * Warnings from the model provider (e.g. unsupported settings). - */ - readonly warnings: CallWarning[] | undefined; - - /** - * Additional request information. - */ - readonly request: LanguageModelRequestMetadata; - - /** - * Additional response information. - */ - readonly response: LanguageModelResponseMetadata & { - /** - * The response messages that were generated during the call. - * Response messages can be either assistant messages or tool messages. - * They contain a generated id. - */ - readonly messages: Array; - - /** - * Response body (available only for providers that use HTTP requests). - */ - body?: unknown; - }; - - /** - * Additional provider-specific metadata. They are passed through - * from the provider to the AI SDK and enable provider-specific - * results that can be fully encapsulated in the provider. - */ - readonly providerMetadata: ProviderMetadata | undefined; -}; - -export class DefaultStepResult< - TOOLS extends ToolSet, -> implements StepResult { - readonly stepNumber: StepResult['stepNumber']; - readonly model: StepResult['model']; - readonly functionId: StepResult['functionId']; - readonly metadata: StepResult['metadata']; - readonly experimental_context: StepResult['experimental_context']; - readonly content: StepResult['content']; - readonly finishReason: StepResult['finishReason']; - readonly rawFinishReason: StepResult['rawFinishReason']; - readonly usage: StepResult['usage']; - readonly warnings: StepResult['warnings']; - readonly request: StepResult['request']; - readonly response: StepResult['response']; - readonly providerMetadata: StepResult['providerMetadata']; - - constructor({ - stepNumber, - model, - functionId, - metadata, - experimental_context, - content, - finishReason, - rawFinishReason, - usage, - warnings, - request, - response, - providerMetadata, - }: { - stepNumber: StepResult['stepNumber']; - model: StepResult['model']; - functionId: StepResult['functionId']; - metadata: StepResult['metadata']; - experimental_context: StepResult['experimental_context']; - content: StepResult['content']; - finishReason: StepResult['finishReason']; - rawFinishReason: StepResult['rawFinishReason']; - usage: StepResult['usage']; - warnings: StepResult['warnings']; - request: StepResult['request']; - response: StepResult['response']; - providerMetadata: StepResult['providerMetadata']; - }) { - this.stepNumber = stepNumber; - this.model = model; - this.functionId = functionId; - this.metadata = metadata; - this.experimental_context = experimental_context; - this.content = content; - this.finishReason = finishReason; - this.rawFinishReason = rawFinishReason; - this.usage = usage; - this.warnings = warnings; - this.request = request; - this.response = response; - this.providerMetadata = providerMetadata; - } - - get text() { - return this.content - .filter(part => part.type === 'text') - .map(part => part.text) - .join(''); - } - - get reasoning() { - return this.content.filter(part => part.type === 'reasoning'); - } - - get reasoningText() { - return this.reasoning.length === 0 - ? undefined - : this.reasoning.map(part => part.text).join(''); - } - - get files() { - return this.content - .filter(part => part.type === 'file') - .map(part => part.file); - } - - get sources() { - return this.content.filter(part => part.type === 'source'); - } - - get toolCalls() { - return this.content.filter(part => part.type === 'tool-call'); - } - - get staticToolCalls() { - return this.toolCalls.filter( - (toolCall): toolCall is StaticToolCall => - toolCall.dynamic !== true, - ); - } - - get dynamicToolCalls() { - return this.toolCalls.filter( - (toolCall): toolCall is DynamicToolCall => toolCall.dynamic === true, - ); - } - - get toolResults() { - return this.content.filter(part => part.type === 'tool-result'); - } - - get staticToolResults() { - return this.toolResults.filter( - (toolResult): toolResult is StaticToolResult => - toolResult.dynamic !== true, - ); - } - - get dynamicToolResults() { - return this.toolResults.filter( - (toolResult): toolResult is DynamicToolResult => - toolResult.dynamic === true, - ); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/stop-condition.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/stop-condition.ts deleted file mode 100644 index 4a2bd316e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/stop-condition.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { StepResult } from './step-result'; -import { ToolSet } from './tool-set'; - -export type StopCondition = (options: { - steps: Array>; -}) => PromiseLike | boolean; - -export function stepCountIs(stepCount: number): StopCondition { - return ({ steps }) => steps.length === stepCount; -} - -export function hasToolCall(toolName: string): StopCondition { - return ({ steps }) => - steps[steps.length - 1]?.toolCalls?.some( - toolCall => toolCall.toolName === toolName, - ) ?? false; -} - -export async function isStopConditionMet({ - stopConditions, - steps, -}: { - stopConditions: Array>; - steps: Array>; -}): Promise { - return ( - await Promise.all(stopConditions.map(condition => condition({ steps }))) - ).some(result => result); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/stream-text-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/stream-text-result.ts deleted file mode 100644 index bc2840be9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/stream-text-result.ts +++ /dev/null @@ -1,463 +0,0 @@ -import { IdGenerator } from '@ai-sdk/provider-utils'; -import { ServerResponse } from 'node:http'; -import { - CallWarning, - FinishReason, - LanguageModelRequestMetadata, - ProviderMetadata, -} from '../types'; -import { Source } from '../types/language-model'; -import { LanguageModelResponseMetadata } from '../types/language-model-response-metadata'; -import { LanguageModelUsage } from '../types/usage'; -import { InferUIMessageChunk } from '../ui-message-stream/ui-message-chunks'; -import { UIMessageStreamOnFinishCallback } from '../ui-message-stream/ui-message-stream-on-finish-callback'; -import { UIMessageStreamResponseInit } from '../ui-message-stream/ui-message-stream-response-init'; -import { InferUIMessageMetadata, UIMessage } from '../ui/ui-messages'; -import { AsyncIterableStream } from '../util/async-iterable-stream'; -import { ErrorHandler } from '../util/error-handler'; -import { ContentPart } from './content-part'; -import { GeneratedFile } from './generated-file'; -import { Output } from './output'; -import { - InferCompleteOutput, - InferElementOutput, - InferPartialOutput, -} from './output-utils'; -import { ReasoningOutput } from './reasoning-output'; -import { ResponseMessage } from './response-message'; -import { StepResult } from './step-result'; -import { ToolApprovalRequestOutput } from './tool-approval-request-output'; -import { DynamicToolCall, StaticToolCall, TypedToolCall } from './tool-call'; -import { TypedToolError } from './tool-error'; -import { StaticToolOutputDenied } from './tool-output-denied'; -import { - DynamicToolResult, - StaticToolResult, - TypedToolResult, -} from './tool-result'; -import { ToolSet } from './tool-set'; - -export type UIMessageStreamOptions = { - /** - * The original messages. If they are provided, persistence mode is assumed, - * and a message ID is provided for the response message. - */ - originalMessages?: UI_MESSAGE[]; - - /** - * Generate a message ID for the response message. - * - * If not provided, no message ID will be set for the response message (unless - * the original messages are provided and the last message is an assistant message). - */ - generateMessageId?: IdGenerator; - - onFinish?: UIMessageStreamOnFinishCallback; - - /** - * Extracts message metadata that will be send to the client. - * - * Called on `start` and `finish` events. - */ - messageMetadata?: (options: { - part: TextStreamPart; - }) => InferUIMessageMetadata | undefined; - - /** - * Send reasoning parts to the client. - * Default to true. - */ - sendReasoning?: boolean; - - /** - * Send source parts to the client. - * Default to false. - */ - sendSources?: boolean; - - /** - * Send the finish event to the client. - * Set to false if you are using additional streamText calls - * that send additional data. - * Default to true. - */ - sendFinish?: boolean; - - /** - * Send the message start event to the client. - * Set to false if you are using additional streamText calls - * and the message start event has already been sent. - * Default to true. - */ - sendStart?: boolean; - - /** - * Process an error, e.g. to log it. Default to `() => 'An error occurred.'`. - * - * @returns error message to include in the data stream. - */ - onError?: (error: unknown) => string; -}; - -export type ConsumeStreamOptions = { - onError?: ErrorHandler; -}; - -/** - * A result object for accessing different stream types and additional information. - */ -export interface StreamTextResult< - TOOLS extends ToolSet, - OUTPUT extends Output, -> { - /** - * The content that was generated in the last step. - * - * Automatically consumes the stream. - */ - readonly content: PromiseLike>>; - - /** - * The full text that has been generated by the last step. - * - * Automatically consumes the stream. - */ - readonly text: PromiseLike; - - /** - * The full reasoning that the model has generated. - * - * Automatically consumes the stream. - */ - readonly reasoning: PromiseLike>; - - /** - * The reasoning that has been generated by the last step. - * - * Automatically consumes the stream. - */ - readonly reasoningText: PromiseLike; - - /** - * Files that have been generated by the model in the last step. - * - * Automatically consumes the stream. - */ - readonly files: PromiseLike; - - /** - * Sources that have been used as references in the last step. - * - * Automatically consumes the stream. - */ - readonly sources: PromiseLike; - - /** - * The tool calls that have been executed in the last step. - * - * Automatically consumes the stream. - */ - readonly toolCalls: PromiseLike[]>; - - /** - * The static tool calls that have been executed in the last step. - * - * Automatically consumes the stream. - */ - readonly staticToolCalls: PromiseLike[]>; - - /** - * The dynamic tool calls that have been executed in the last step. - * - * Automatically consumes the stream. - */ - readonly dynamicToolCalls: PromiseLike; - - /** - * The static tool results that have been generated in the last step. - * - * Automatically consumes the stream. - */ - readonly staticToolResults: PromiseLike[]>; - - /** - * The dynamic tool results that have been generated in the last step. - * - * Automatically consumes the stream. - */ - readonly dynamicToolResults: PromiseLike; - - /** - * The tool results that have been generated in the last step. - * - * Automatically consumes the stream. - */ - readonly toolResults: PromiseLike[]>; - - /** - * The unified finish reason why the generation finished. Taken from the last step. - * - * Automatically consumes the stream. - */ - readonly finishReason: PromiseLike; - - /** - * The raw reason why the generation finished (from the provider). Taken from the last step. - * - * Automatically consumes the stream. - */ - readonly rawFinishReason: PromiseLike; - - /** - * The token usage of the last step. - * - * Automatically consumes the stream. - */ - readonly usage: PromiseLike; - - /** - * The total token usage of the generated response. - * When there are multiple steps, the usage is the sum of all step usages. - * - * Automatically consumes the stream. - */ - readonly totalUsage: PromiseLike; - - /** - * Warnings from the model provider (e.g. unsupported settings) for the first step. - * - * Automatically consumes the stream. - */ - readonly warnings: PromiseLike; - - /** - * Details for all steps. - * You can use this to get information about intermediate steps, - * such as the tool calls or the response headers. - * - * Automatically consumes the stream. - */ - readonly steps: PromiseLike>>; - - /** - * Additional request information from the last step. - * - * Automatically consumes the stream. - */ - readonly request: PromiseLike; - - /** - * Additional response information from the last step. - * - * Automatically consumes the stream. - */ - readonly response: PromiseLike< - LanguageModelResponseMetadata & { - /** - * The response messages that were generated during the call. It consists of an assistant message, - * potentially containing tool calls. - * - * When there are tool results, there is an additional tool message with the tool results that are available. - * If there are tools that do not have execute functions, they are not included in the tool results and - * need to be added separately. - */ - messages: Array; - } - >; - - /** - * Additional provider-specific metadata from the last step. - * Metadata is passed through from the provider to the AI SDK and - * enables provider-specific results that can be fully encapsulated in the provider. - */ - readonly providerMetadata: PromiseLike; - - /** - * A text stream that returns only the generated text deltas. You can use it - * as either an AsyncIterable or a ReadableStream. When an error occurs, the - * stream will throw the error. - */ - readonly textStream: AsyncIterableStream; - - /** - * A stream with all events, including text deltas, tool calls, tool results, and - * errors. - * You can use it as either an AsyncIterable or a ReadableStream. - * Only errors that stop the stream, such as network errors, are thrown. - */ - readonly fullStream: AsyncIterableStream>; - - /** - * A stream of partial outputs. It uses the `output` specification. - * - * @deprecated Use `partialOutputStream` instead. - */ - readonly experimental_partialOutputStream: AsyncIterableStream< - InferPartialOutput - >; - - /** - * A stream of partial parsed outputs. It uses the `output` specification. - */ - readonly partialOutputStream: AsyncIterableStream>; - - /** - * A stream of individual array elements as they complete. - * Only available when using `output: Output.array()`. - */ - readonly elementStream: AsyncIterableStream>; - - /** - * The complete parsed output. It uses the `output` specification. - */ - readonly output: PromiseLike>; - - /** - * Consumes the stream without processing the parts. - * This is useful to force the stream to finish. - * It effectively removes the backpressure and allows the stream to finish, - * triggering the `onFinish` callback and the promise resolution. - * - * If an error occurs, it is passed to the optional `onError` callback. - */ - consumeStream(options?: ConsumeStreamOptions): PromiseLike; - - /** - * Converts the result to a UI message stream. - * - * @returns A UI message stream. - */ - toUIMessageStream( - options?: UIMessageStreamOptions, - ): AsyncIterableStream>; - - /** - * Writes UI message stream output to a Node.js response-like object. - */ - pipeUIMessageStreamToResponse( - response: ServerResponse, - options?: UIMessageStreamResponseInit & UIMessageStreamOptions, - ): void; - - /** - * Writes text delta output to a Node.js response-like object. - * It sets a `Content-Type` header to `text/plain; charset=utf-8` and - * writes each text delta as a separate chunk. - * - * @param response A Node.js response-like object (ServerResponse). - * @param init Optional headers, status code, and status text. - */ - pipeTextStreamToResponse(response: ServerResponse, init?: ResponseInit): void; - - /** - * Converts the result to a streamed response object with a stream data part stream. - * - * @returns A response object. - */ - toUIMessageStreamResponse( - options?: UIMessageStreamResponseInit & UIMessageStreamOptions, - ): Response; - - /** - * Creates a simple text stream response. - * Each text delta is encoded as UTF-8 and sent as a separate chunk. - * Non-text-delta events are ignored. - * @param init Optional headers, status code, and status text. - */ - toTextStreamResponse(init?: ResponseInit): Response; -} - -export type TextStreamPart = - | { - type: 'text-start'; - id: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'text-end'; - id: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'text-delta'; - id: string; - providerMetadata?: ProviderMetadata; - text: string; - } - | { - type: 'reasoning-start'; - id: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'reasoning-end'; - id: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'reasoning-delta'; - providerMetadata?: ProviderMetadata; - id: string; - text: string; - } - | { - type: 'tool-input-start'; - id: string; - toolName: string; - providerMetadata?: ProviderMetadata; - providerExecuted?: boolean; - dynamic?: boolean; - title?: string; - } - | { - type: 'tool-input-end'; - id: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'tool-input-delta'; - id: string; - delta: string; - providerMetadata?: ProviderMetadata; - } - | ({ type: 'source' } & Source) - | { type: 'file'; file: GeneratedFile; providerMetadata?: ProviderMetadata } // different because of GeneratedFile object - | ({ type: 'tool-call' } & TypedToolCall) - | ({ type: 'tool-result' } & TypedToolResult) - | ({ type: 'tool-error' } & TypedToolError) - | ({ type: 'tool-output-denied' } & StaticToolOutputDenied) - | ToolApprovalRequestOutput - | { - type: 'start-step'; - request: LanguageModelRequestMetadata; - warnings: CallWarning[]; - } - | { - type: 'finish-step'; - response: LanguageModelResponseMetadata; - usage: LanguageModelUsage; - finishReason: FinishReason; - rawFinishReason: string | undefined; - providerMetadata: ProviderMetadata | undefined; - } - | { - type: 'start'; - } - | { - type: 'finish'; - finishReason: FinishReason; - rawFinishReason: string | undefined; - totalUsage: LanguageModelUsage; - } - | { - type: 'abort'; - reason?: string; - } - | { - type: 'error'; - error: unknown; - } - | { - type: 'raw'; - rawValue: unknown; - }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/stream-text.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/stream-text.ts deleted file mode 100644 index d5f0cbd44..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/stream-text.ts +++ /dev/null @@ -1,2844 +0,0 @@ -import { - getErrorMessage, - LanguageModelV3, - LanguageModelV3ToolChoice, - SharedV3Warning, - UnsupportedFunctionalityError, -} from '@ai-sdk/provider'; -import { - createIdGenerator, - DelayedPromise, - IdGenerator, - isAbortError, - ModelMessage, - ProviderOptions, - SystemModelMessage, - ToolApprovalResponse, - ToolContent, -} from '@ai-sdk/provider-utils'; -import { Span } from '@opentelemetry/api'; -import { ServerResponse } from 'node:http'; -import { NoOutputGeneratedError } from '../error'; -import { Listener, notify } from '../util/notify'; -import { logWarnings } from '../logger/log-warnings'; -import { resolveLanguageModel } from '../model/resolve-model'; -import { - CallSettings, - getChunkTimeoutMs, - getStepTimeoutMs, - getTotalTimeoutMs, - TimeoutConfiguration, -} from '../prompt/call-settings'; -import { convertToLanguageModelPrompt } from '../prompt/convert-to-language-model-prompt'; -import { createToolModelOutput } from '../prompt/create-tool-model-output'; -import { prepareCallSettings } from '../prompt/prepare-call-settings'; -import { prepareToolsAndToolChoice } from '../prompt/prepare-tools-and-tool-choice'; -import { Prompt } from '../prompt/prompt'; -import { standardizePrompt } from '../prompt/standardize-prompt'; -import { wrapGatewayError } from '../prompt/wrap-gateway-error'; -import { assembleOperationName } from '../telemetry/assemble-operation-name'; -import { getBaseTelemetryAttributes } from '../telemetry/get-base-telemetry-attributes'; -import { getTracer } from '../telemetry/get-tracer'; -import { recordSpan } from '../telemetry/record-span'; -import { selectTelemetryAttributes } from '../telemetry/select-telemetry-attributes'; -import { stringifyForTelemetry } from '../telemetry/stringify-for-telemetry'; -import { getGlobalTelemetryIntegration } from '../telemetry/get-global-telemetry-integration'; -import { TelemetrySettings } from '../telemetry/telemetry-settings'; -import { createTextStreamResponse } from '../text-stream/create-text-stream-response'; -import { pipeTextStreamToResponse } from '../text-stream/pipe-text-stream-to-response'; -import { LanguageModelRequestMetadata } from '../types'; -import { - CallWarning, - FinishReason, - LanguageModel, - ToolChoice, -} from '../types/language-model'; -import { ProviderMetadata } from '../types/provider-metadata'; -import { - addLanguageModelUsage, - createNullLanguageModelUsage, - LanguageModelUsage, -} from '../types/usage'; -import { UIMessage } from '../ui'; -import { createUIMessageStreamResponse } from '../ui-message-stream/create-ui-message-stream-response'; -import { getResponseUIMessageId } from '../ui-message-stream/get-response-ui-message-id'; -import { handleUIMessageStreamFinish } from '../ui-message-stream/handle-ui-message-stream-finish'; -import { pipeUIMessageStreamToResponse } from '../ui-message-stream/pipe-ui-message-stream-to-response'; -import { - InferUIMessageChunk, - UIMessageChunk, -} from '../ui-message-stream/ui-message-chunks'; -import { UIMessageStreamResponseInit } from '../ui-message-stream/ui-message-stream-response-init'; -import { InferUIMessageData, InferUIMessageMetadata } from '../ui/ui-messages'; -import { asArray } from '../util/as-array'; -import { - AsyncIterableStream, - createAsyncIterableStream, -} from '../util/async-iterable-stream'; -import { consumeStream } from '../util/consume-stream'; -import { createStitchableStream } from '../util/create-stitchable-stream'; -import { DownloadFunction } from '../util/download/download-function'; -import { mergeAbortSignals } from '../util/merge-abort-signals'; -import { mergeObjects } from '../util/merge-objects'; -import { now as originalNow } from '../util/now'; -import { prepareRetries } from '../util/prepare-retries'; -import { collectToolApprovals } from './collect-tool-approvals'; -import type { - OnFinishEvent, - OnStartEvent, - OnStepFinishEvent, - OnStepStartEvent, - OnToolCallFinishEvent, - OnToolCallStartEvent, -} from './callback-events'; -import { ContentPart } from './content-part'; -import { executeToolCall } from './execute-tool-call'; -import { Output, text } from './output'; -import { - InferCompleteOutput, - InferElementOutput, - InferPartialOutput, -} from './output-utils'; -import { PrepareStepFunction } from './prepare-step'; -import { ResponseMessage } from './response-message'; -import { - runToolsTransformation, - SingleRequestTextStreamPart, -} from './run-tools-transformation'; -import { DefaultStepResult, StepResult } from './step-result'; -import { - isStopConditionMet, - stepCountIs, - StopCondition, -} from './stop-condition'; -import { - ConsumeStreamOptions, - StreamTextResult, - TextStreamPart, - UIMessageStreamOptions, -} from './stream-text-result'; -import { toResponseMessages } from './to-response-messages'; -import { TypedToolCall } from './tool-call'; -import { ToolCallRepairFunction } from './tool-call-repair-function'; -import { ToolOutput } from './tool-output'; -import { StaticToolOutputDenied } from './tool-output-denied'; -import { ToolSet } from './tool-set'; - -const originalGenerateId = createIdGenerator({ - prefix: 'aitxt', - size: 24, -}); - -/** - * A transformation that is applied to the stream. - * - * @param stopStream - A function that stops the source stream. - * @param tools - The tools that are accessible to and can be called by the model. The model needs to support calling tools. - */ -export type StreamTextTransform = (options: { - tools: TOOLS; // for type inference - stopStream: () => void; -}) => TransformStream, TextStreamPart>; - -/** - * Callback that is set using the `onError` option. - * - * @param event - The event that is passed to the callback. - */ -export type StreamTextOnErrorCallback = (event: { - error: unknown; -}) => PromiseLike | void; - -/** - * Callback that is set using the `onStepFinish` option. - * - * @param stepResult - The result of the step. - */ -export type StreamTextOnStepFinishCallback = ( - event: OnStepFinishEvent, -) => PromiseLike | void; - -/** - * Callback that is set using the `onChunk` option. - * - * @param event - The event that is passed to the callback. - */ -export type StreamTextOnChunkCallback = (event: { - chunk: Extract< - TextStreamPart, - { - type: - | 'text-delta' - | 'reasoning-delta' - | 'source' - | 'tool-call' - | 'tool-input-start' - | 'tool-input-delta' - | 'tool-result' - | 'raw'; - } - >; -}) => PromiseLike | void; - -/** - * Callback that is set using the `onFinish` option. - * - * @param event - The event that is passed to the callback. - */ -export type StreamTextOnFinishCallback = ( - event: OnFinishEvent, -) => PromiseLike | void; - -/** - * Callback that is set using the `onAbort` option. - * - * @param event - The event that is passed to the callback. - */ -export type StreamTextOnAbortCallback = (event: { - /** - * Details for all previously finished steps. - */ - readonly steps: StepResult[]; -}) => PromiseLike | void; - -/** - * Include settings for streamText (requestBody only). - */ -type StreamTextIncludeSettings = { requestBody?: boolean }; - -/** - * Callback that is set using the `experimental_onStart` option. - * - * Called when the streamText operation begins, before any LLM calls. - * Use this callback for logging, analytics, or initializing state at the - * start of a generation. - * - * @param event - The event object containing generation configuration. - */ -export type StreamTextOnStartCallback< - TOOLS extends ToolSet = ToolSet, - OUTPUT extends Output = Output, -> = ( - event: OnStartEvent, -) => PromiseLike | void; - -/** - * Callback that is set using the `experimental_onStepStart` option. - * - * Called when a step (LLM call) begins, before the provider is called. - * Each step represents a single LLM invocation. Multiple steps occur when - * using tool calls (the model may be called multiple times in a loop). - * - * @param event - The event object containing step configuration. - */ -export type StreamTextOnStepStartCallback< - TOOLS extends ToolSet = ToolSet, - OUTPUT extends Output = Output, -> = ( - event: OnStepStartEvent, -) => PromiseLike | void; - -export type StreamTextOnToolCallStartCallback = - (event: OnToolCallStartEvent) => PromiseLike | void; - -export type StreamTextOnToolCallFinishCallback< - TOOLS extends ToolSet = ToolSet, -> = (event: OnToolCallFinishEvent) => PromiseLike | void; - -/** - * Generate a text and call tools for a given prompt using a language model. - * - * This function streams the output. If you do not want to stream the output, use `generateText` instead. - * - * @param model - The language model to use. - * @param tools - Tools that are accessible to and can be called by the model. The model needs to support calling tools. - * - * @param system - A system message that will be part of the prompt. - * @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both. - * @param messages - A list of messages. You can either use `prompt` or `messages` but not both. - * - * @param maxOutputTokens - Maximum number of tokens to generate. - * @param temperature - Temperature setting. - * The value is passed through to the provider. The range depends on the provider and model. - * It is recommended to set either `temperature` or `topP`, but not both. - * @param topP - Nucleus sampling. - * The value is passed through to the provider. The range depends on the provider and model. - * It is recommended to set either `temperature` or `topP`, but not both. - * @param topK - Only sample from the top K options for each subsequent token. - * Used to remove "long tail" low probability responses. - * Recommended for advanced use cases only. You usually only need to use temperature. - * @param presencePenalty - Presence penalty setting. - * It affects the likelihood of the model to repeat information that is already in the prompt. - * The value is passed through to the provider. The range depends on the provider and model. - * @param frequencyPenalty - Frequency penalty setting. - * It affects the likelihood of the model to repeatedly use the same words or phrases. - * The value is passed through to the provider. The range depends on the provider and model. - * @param stopSequences - Stop sequences. - * If set, the model will stop generating text when one of the stop sequences is generated. - * @param seed - The seed (integer) to use for random sampling. - * If set and supported by the model, calls will generate deterministic results. - * - * @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2. - * @param abortSignal - An optional abort signal that can be used to cancel the call. - * @param timeout - An optional timeout in milliseconds. The call will be aborted if it takes longer than the specified timeout. - * @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers. - * - * @param onChunk - Callback that is called for each chunk of the stream. The stream processing will pause until the callback promise is resolved. - * @param onError - Callback that is called when an error occurs during streaming. You can use it to log errors. - * @param onStepFinish - Callback that is called when each step (LLM call) is finished, including intermediate steps. - * @param onFinish - Callback that is called when all steps are finished and the response is complete. - * - * @returns - * A result object for accessing different stream types and additional information. - */ -export function streamText< - TOOLS extends ToolSet, - OUTPUT extends Output = Output, ->({ - model, - tools, - toolChoice, - system, - prompt, - messages, - maxRetries, - abortSignal, - timeout, - headers, - stopWhen = stepCountIs(1), - experimental_output, - output = experimental_output, - experimental_telemetry: telemetry, - prepareStep, - providerOptions, - experimental_activeTools, - activeTools = experimental_activeTools, - experimental_repairToolCall: repairToolCall, - experimental_transform: transform, - experimental_download: download, - includeRawChunks = false, - onChunk, - onError = ({ error }) => { - console.error(error); - }, - onFinish, - onAbort, - onStepFinish, - experimental_onStart: onStart, - experimental_onStepStart: onStepStart, - experimental_onToolCallStart: onToolCallStart, - experimental_onToolCallFinish: onToolCallFinish, - experimental_context, - experimental_include: include, - _internal: { now = originalNow, generateId = originalGenerateId } = {}, - ...settings -}: CallSettings & - Prompt & { - /** - * The language model to use. - */ - model: LanguageModel; - - /** - * The tools that the model can call. The model needs to support calling tools. - */ - tools?: TOOLS; - - /** - * The tool choice strategy. Default: 'auto'. - */ - toolChoice?: ToolChoice; - - /** - * Condition for stopping the generation when there are tool results in the last step. - * When the condition is an array, any of the conditions can be met to stop the generation. - * - * @default stepCountIs(1) - */ - stopWhen?: - | StopCondition> - | Array>>; - - /** - * Optional telemetry configuration (experimental). - */ - experimental_telemetry?: TelemetrySettings; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; - - /** - * @deprecated Use `activeTools` instead. - */ - experimental_activeTools?: Array>; - - /** - * Limits the tools that are available for the model to call without - * changing the tool call and result types in the result. - */ - activeTools?: Array>; - - /** - * Optional specification for parsing structured outputs from the LLM response. - */ - output?: OUTPUT; - - /** - * Optional specification for parsing structured outputs from the LLM response. - * - * @deprecated Use `output` instead. - */ - experimental_output?: OUTPUT; - - /** - * Optional function that you can use to provide different settings for a step. - * - * @param options - The options for the step. - * @param options.steps - The steps that have been executed so far. - * @param options.stepNumber - The number of the step that is being executed. - * @param options.model - The model that is being used. - * - * @returns An object that contains the settings for the step. - * If you return undefined (or for undefined settings), the settings from the outer level will be used. - */ - prepareStep?: PrepareStepFunction>; - - /** - * A function that attempts to repair a tool call that failed to parse. - */ - experimental_repairToolCall?: ToolCallRepairFunction; - - /** - * Optional stream transformations. - * They are applied in the order they are provided. - * The stream transformations must maintain the stream structure for streamText to work correctly. - */ - experimental_transform?: - | StreamTextTransform - | Array>; - - /** - * Custom download function to use for URLs. - * - * By default, files are downloaded if the model does not support the URL for the given media type. - */ - experimental_download?: DownloadFunction | undefined; - - /** - * Whether to include raw chunks from the provider in the stream. - * When enabled, you will receive raw chunks with type 'raw' that contain the unprocessed data from the provider. - * This allows access to cutting-edge provider features not yet wrapped by the AI SDK. - * Defaults to false. - */ - includeRawChunks?: boolean; - - /** - * Callback that is called for each chunk of the stream. - * The stream processing will pause until the callback promise is resolved. - */ - onChunk?: StreamTextOnChunkCallback; - - /** - * Callback that is invoked when an error occurs during streaming. - * You can use it to log errors. - * The stream processing will pause until the callback promise is resolved. - */ - onError?: StreamTextOnErrorCallback; - - /** - * Callback that is called when the LLM response and all request tool executions - * (for tools that have an `execute` function) are finished. - * - * The usage is the combined usage of all steps. - */ - onFinish?: StreamTextOnFinishCallback; - - onAbort?: StreamTextOnAbortCallback; - - /** - * Callback that is called when each step (LLM call) is finished, including intermediate steps. - */ - onStepFinish?: StreamTextOnStepFinishCallback; - - /** - * Callback that is called when the streamText operation begins, - * before any LLM calls are made. - */ - experimental_onStart?: StreamTextOnStartCallback, OUTPUT>; - - /** - * Callback that is called when a step (LLM call) begins, - * before the provider is called. - */ - experimental_onStepStart?: StreamTextOnStepStartCallback< - NoInfer, - OUTPUT - >; - - /** - * Callback that is called right before a tool's execute function runs. - */ - experimental_onToolCallStart?: StreamTextOnToolCallStartCallback< - NoInfer - >; - - /** - * Callback that is called right after a tool's execute function completes (or errors). - */ - experimental_onToolCallFinish?: StreamTextOnToolCallFinishCallback< - NoInfer - >; - - /** - * Context that is passed into tool execution. - * - * Experimental (can break in patch releases). - * - * @default undefined - */ - experimental_context?: unknown; - - /** - * Settings for controlling what data is included in step results. - * Disabling inclusion can help reduce memory usage when processing - * large payloads like images. - * - * By default, all data is included for backwards compatibility. - */ - experimental_include?: { - /** - * Whether to retain the request body in step results. - * The request body can be large when sending images or files. - * @default true - */ - requestBody?: boolean; - }; - - /** - * Internal. For test use only. May change without notice. - */ - _internal?: { - now?: () => number; - generateId?: IdGenerator; - }; - }): StreamTextResult { - const totalTimeoutMs = getTotalTimeoutMs(timeout); - const stepTimeoutMs = getStepTimeoutMs(timeout); - const chunkTimeoutMs = getChunkTimeoutMs(timeout); - const stepAbortController = - stepTimeoutMs != null ? new AbortController() : undefined; - const chunkAbortController = - chunkTimeoutMs != null ? new AbortController() : undefined; - return new DefaultStreamTextResult({ - model: resolveLanguageModel(model), - telemetry, - headers, - settings, - maxRetries, - abortSignal: mergeAbortSignals( - abortSignal, - totalTimeoutMs != null ? AbortSignal.timeout(totalTimeoutMs) : undefined, - stepAbortController?.signal, - chunkAbortController?.signal, - ), - stepTimeoutMs, - stepAbortController, - chunkTimeoutMs, - chunkAbortController, - system, - prompt, - messages, - tools, - toolChoice, - transforms: asArray(transform), - activeTools, - repairToolCall, - stopConditions: asArray(stopWhen), - output, - providerOptions, - prepareStep, - includeRawChunks, - timeout, - stopWhen, - originalAbortSignal: abortSignal, - onChunk, - onError, - onFinish, - onAbort, - onStepFinish, - onStart, - onStepStart, - onToolCallStart, - onToolCallFinish, - now, - generateId, - experimental_context, - download, - include, - }); -} - -export type EnrichedStreamPart = { - part: TextStreamPart; - partialOutput: PARTIAL_OUTPUT | undefined; -}; - -function createOutputTransformStream< - TOOLS extends ToolSet, - OUTPUT extends Output, ->( - output: OUTPUT, -): TransformStream< - TextStreamPart, - EnrichedStreamPart> -> { - let firstTextChunkId: string | undefined = undefined; - let text = ''; - let textChunk = ''; - let textProviderMetadata: ProviderMetadata | undefined = undefined; - let lastPublishedJson = ''; - - function publishTextChunk({ - controller, - partialOutput = undefined, - }: { - controller: TransformStreamDefaultController< - EnrichedStreamPart> - >; - partialOutput?: InferPartialOutput; - }) { - controller.enqueue({ - part: { - type: 'text-delta', - id: firstTextChunkId!, - text: textChunk, - providerMetadata: textProviderMetadata, - }, - partialOutput, - }); - textChunk = ''; - } - - return new TransformStream< - TextStreamPart, - EnrichedStreamPart> - >({ - async transform(chunk, controller) { - // ensure that we publish the last text chunk before the step finish: - if (chunk.type === 'finish-step' && textChunk.length > 0) { - publishTextChunk({ controller }); - } - - if ( - chunk.type !== 'text-delta' && - chunk.type !== 'text-start' && - chunk.type !== 'text-end' - ) { - controller.enqueue({ part: chunk, partialOutput: undefined }); - return; - } - - // we have to pick a text chunk which contains the json text - // since we are streaming, we have to pick the first text chunk - if (firstTextChunkId == null) { - firstTextChunkId = chunk.id; - } else if (chunk.id !== firstTextChunkId) { - controller.enqueue({ part: chunk, partialOutput: undefined }); - return; - } - - if (chunk.type === 'text-start') { - controller.enqueue({ part: chunk, partialOutput: undefined }); - return; - } - - if (chunk.type === 'text-end') { - if (textChunk.length > 0) { - publishTextChunk({ controller }); - } - controller.enqueue({ part: chunk, partialOutput: undefined }); - return; - } - - text += chunk.text; - textChunk += chunk.text; - textProviderMetadata = chunk.providerMetadata ?? textProviderMetadata; - - // only publish if partial json can be parsed: - const result = await output.parsePartialOutput({ text }); - - // null should be allowed (valid JSON value) but undefined should not: - if (result !== undefined) { - // only send new json if it has changed: - const currentJson = JSON.stringify(result.partial); - if (currentJson !== lastPublishedJson) { - publishTextChunk({ controller, partialOutput: result.partial }); - lastPublishedJson = currentJson; - } - } - }, - }); -} - -class DefaultStreamTextResult< - TOOLS extends ToolSet, - OUTPUT extends Output, -> implements StreamTextResult { - private readonly _totalUsage = new DelayedPromise< - Awaited['usage']> - >(); - private readonly _finishReason = new DelayedPromise< - Awaited['finishReason']> - >(); - private readonly _rawFinishReason = new DelayedPromise< - Awaited['rawFinishReason']> - >(); - private readonly _steps = new DelayedPromise< - Awaited['steps']> - >(); - - private readonly addStream: ( - stream: ReadableStream>, - ) => void; - - private readonly closeStream: () => void; - - private baseStream: ReadableStream< - EnrichedStreamPart> - >; - - private outputSpecification: OUTPUT | undefined; - - private includeRawChunks: boolean; - - private tools: TOOLS | undefined; - - constructor({ - model, - telemetry, - headers, - settings, - maxRetries: maxRetriesArg, - abortSignal, - stepTimeoutMs, - stepAbortController, - chunkTimeoutMs, - chunkAbortController, - system, - prompt, - messages, - tools, - toolChoice, - transforms, - activeTools, - repairToolCall, - stopConditions, - output, - providerOptions, - prepareStep, - includeRawChunks, - now, - generateId, - timeout, - stopWhen, - originalAbortSignal, - onChunk, - onError, - onFinish, - onAbort, - onStepFinish, - onStart, - onStepStart, - onToolCallStart, - onToolCallFinish, - experimental_context, - download, - include, - }: { - model: LanguageModelV3; - telemetry: TelemetrySettings | undefined; - headers: Record | undefined; - settings: Omit; - maxRetries: number | undefined; - abortSignal: AbortSignal | undefined; - stepTimeoutMs: number | undefined; - stepAbortController: AbortController | undefined; - chunkTimeoutMs: number | undefined; - chunkAbortController: AbortController | undefined; - system: Prompt['system']; - prompt: Prompt['prompt']; - messages: Prompt['messages']; - tools: TOOLS | undefined; - toolChoice: ToolChoice | undefined; - transforms: Array>; - activeTools: Array | undefined; - repairToolCall: ToolCallRepairFunction | undefined; - stopConditions: Array>>; - output: OUTPUT | undefined; - providerOptions: ProviderOptions | undefined; - prepareStep: PrepareStepFunction> | undefined; - includeRawChunks: boolean; - now: () => number; - generateId: () => string; - timeout: TimeoutConfiguration | undefined; - stopWhen: - | StopCondition> - | Array>> - | undefined; - originalAbortSignal: AbortSignal | undefined; - experimental_context: unknown; - download: DownloadFunction | undefined; - include: { requestBody?: boolean } | undefined; - - // callbacks: - onChunk: undefined | StreamTextOnChunkCallback; - onError: StreamTextOnErrorCallback; - onFinish: undefined | StreamTextOnFinishCallback; - onAbort: undefined | StreamTextOnAbortCallback; - onStepFinish: undefined | StreamTextOnStepFinishCallback; - onStart: undefined | StreamTextOnStartCallback; - onStepStart: undefined | StreamTextOnStepStartCallback; - onToolCallStart: undefined | StreamTextOnToolCallStartCallback; - onToolCallFinish: undefined | StreamTextOnToolCallFinishCallback; - }) { - this.outputSpecification = output; - this.includeRawChunks = includeRawChunks; - this.tools = tools; - - const createGlobalTelemetry = getGlobalTelemetryIntegration< - TOOLS, - OUTPUT - >(); - const globalTelemetry = createGlobalTelemetry(telemetry?.integrations); - - // promise to ensure that the step has been fully processed by the event processor - // before a new step is started. This is required because the continuation condition - // needs the updated steps to determine if another step is needed. - let stepFinish!: DelayedPromise; - - let recordedContent: Array> = []; - const recordedResponseMessages: Array = []; - let recordedFinishReason: FinishReason | undefined = undefined; - let recordedRawFinishReason: string | undefined = undefined; - let recordedTotalUsage: LanguageModelUsage | undefined = undefined; - let recordedRequest: LanguageModelRequestMetadata = {}; - let recordedWarnings: Array = []; - const recordedSteps: StepResult[] = []; - - // Track provider-executed tool calls that support deferred results - // (e.g., code_execution in programmatic tool calling scenarios). - // These tools may not return their results in the same turn as their call. - const pendingDeferredToolCalls = new Map(); - - let rootSpan!: Span; - - let activeTextContent: Record< - string, - { - type: 'text'; - text: string; - providerMetadata: ProviderMetadata | undefined; - } - > = {}; - - let activeReasoningContent: Record< - string, - { - type: 'reasoning'; - text: string; - providerMetadata: ProviderMetadata | undefined; - } - > = {}; - - const eventProcessor = new TransformStream< - EnrichedStreamPart>, - EnrichedStreamPart> - >({ - async transform(chunk, controller) { - controller.enqueue(chunk); // forward the chunk to the next stream - - const { part } = chunk; - - if ( - part.type === 'text-delta' || - part.type === 'reasoning-delta' || - part.type === 'source' || - part.type === 'tool-call' || - part.type === 'tool-result' || - part.type === 'tool-input-start' || - part.type === 'tool-input-delta' || - part.type === 'raw' - ) { - await onChunk?.({ chunk: part }); - } - - if (part.type === 'error') { - await onError({ error: wrapGatewayError(part.error) }); - } - - if (part.type === 'text-start') { - activeTextContent[part.id] = { - type: 'text', - text: '', - providerMetadata: part.providerMetadata, - }; - - recordedContent.push(activeTextContent[part.id]); - } - - if (part.type === 'text-delta') { - const activeText = activeTextContent[part.id]; - - if (activeText == null) { - controller.enqueue({ - part: { - type: 'error', - error: `text part ${part.id} not found`, - }, - partialOutput: undefined, - }); - return; - } - - activeText.text += part.text; - activeText.providerMetadata = - part.providerMetadata ?? activeText.providerMetadata; - } - - if (part.type === 'text-end') { - const activeText = activeTextContent[part.id]; - - if (activeText == null) { - controller.enqueue({ - part: { - type: 'error', - error: `text part ${part.id} not found`, - }, - partialOutput: undefined, - }); - return; - } - - activeText.providerMetadata = - part.providerMetadata ?? activeText.providerMetadata; - - delete activeTextContent[part.id]; - } - - if (part.type === 'reasoning-start') { - activeReasoningContent[part.id] = { - type: 'reasoning', - text: '', - providerMetadata: part.providerMetadata, - }; - - recordedContent.push(activeReasoningContent[part.id]); - } - - if (part.type === 'reasoning-delta') { - const activeReasoning = activeReasoningContent[part.id]; - - if (activeReasoning == null) { - controller.enqueue({ - part: { - type: 'error', - error: `reasoning part ${part.id} not found`, - }, - partialOutput: undefined, - }); - return; - } - - activeReasoning.text += part.text; - activeReasoning.providerMetadata = - part.providerMetadata ?? activeReasoning.providerMetadata; - } - - if (part.type === 'reasoning-end') { - const activeReasoning = activeReasoningContent[part.id]; - - if (activeReasoning == null) { - controller.enqueue({ - part: { - type: 'error', - error: `reasoning part ${part.id} not found`, - }, - partialOutput: undefined, - }); - return; - } - - activeReasoning.providerMetadata = - part.providerMetadata ?? activeReasoning.providerMetadata; - - delete activeReasoningContent[part.id]; - } - - if (part.type === 'file') { - recordedContent.push({ - type: 'file', - file: part.file, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - }); - } - - if (part.type === 'source') { - recordedContent.push(part); - } - - if (part.type === 'tool-call') { - recordedContent.push(part); - } - - if (part.type === 'tool-result' && !part.preliminary) { - recordedContent.push(part); - } - - if (part.type === 'tool-approval-request') { - recordedContent.push(part); - } - - if (part.type === 'tool-error') { - recordedContent.push(part); - } - - if (part.type === 'start-step') { - // reset the recorded data when a new step starts: - recordedContent = []; - activeReasoningContent = {}; - activeTextContent = {}; - - recordedRequest = part.request; - recordedWarnings = part.warnings; - } - - if (part.type === 'finish-step') { - const stepMessages = await toResponseMessages({ - content: recordedContent, - tools, - }); - - // Add step information (after response messages are updated): - const currentStepResult: StepResult = new DefaultStepResult({ - stepNumber: recordedSteps.length, - model: modelInfo, - ...callbackTelemetryProps, - experimental_context, - content: recordedContent, - finishReason: part.finishReason, - rawFinishReason: part.rawFinishReason, - usage: part.usage, - warnings: recordedWarnings, - request: recordedRequest, - response: { - ...part.response, - messages: [...recordedResponseMessages, ...stepMessages], - }, - providerMetadata: part.providerMetadata, - }); - - await notify({ - event: currentStepResult, - callbacks: [onStepFinish, globalTelemetry.onStepFinish], - }); - - logWarnings({ - warnings: recordedWarnings, - provider: modelInfo.provider, - model: modelInfo.modelId, - }); - - recordedSteps.push(currentStepResult); - - recordedResponseMessages.push(...stepMessages); - - // resolve the promise to signal that the step has been fully processed - // by the event processor: - stepFinish.resolve(); - } - - if (part.type === 'finish') { - recordedTotalUsage = part.totalUsage; - recordedFinishReason = part.finishReason; - recordedRawFinishReason = part.rawFinishReason; - } - }, - - async flush(controller) { - try { - if (recordedSteps.length === 0) { - const error = abortSignal?.aborted - ? abortSignal.reason - : new NoOutputGeneratedError({ - message: 'No output generated. Check the stream for errors.', - }); - - self._finishReason.reject(error); - self._rawFinishReason.reject(error); - self._totalUsage.reject(error); - self._steps.reject(error); - - return; // no steps recorded (e.g. in error scenario) - } - - // derived: - const finishReason = recordedFinishReason ?? 'other'; - const totalUsage = - recordedTotalUsage ?? createNullLanguageModelUsage(); - - // from finish: - self._finishReason.resolve(finishReason); - self._rawFinishReason.resolve(recordedRawFinishReason); - self._totalUsage.resolve(totalUsage); - - // aggregate results: - self._steps.resolve(recordedSteps); - - // call onFinish callback: - const finalStep = recordedSteps[recordedSteps.length - 1]; - - await notify({ - event: { - stepNumber: finalStep.stepNumber, - model: finalStep.model, - functionId: finalStep.functionId, - metadata: finalStep.metadata, - experimental_context: finalStep.experimental_context, - finishReason: finalStep.finishReason, - rawFinishReason: finalStep.rawFinishReason, - totalUsage, - usage: finalStep.usage, - content: finalStep.content, - text: finalStep.text, - reasoningText: finalStep.reasoningText, - reasoning: finalStep.reasoning, - files: finalStep.files, - sources: finalStep.sources, - toolCalls: finalStep.toolCalls, - staticToolCalls: finalStep.staticToolCalls, - dynamicToolCalls: finalStep.dynamicToolCalls, - toolResults: finalStep.toolResults, - staticToolResults: finalStep.staticToolResults, - dynamicToolResults: finalStep.dynamicToolResults, - request: finalStep.request, - response: finalStep.response, - warnings: finalStep.warnings, - providerMetadata: finalStep.providerMetadata, - steps: recordedSteps, - }, - callbacks: [ - onFinish, - globalTelemetry.onFinish as - | undefined - | StreamTextOnFinishCallback, - ], - }); - - // Add response information to the root span: - rootSpan.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.response.finishReason': finishReason, - 'ai.response.text': { output: () => finalStep.text }, - 'ai.response.reasoning': { - output: () => finalStep.reasoningText, - }, - 'ai.response.toolCalls': { - output: () => - finalStep.toolCalls?.length - ? JSON.stringify(finalStep.toolCalls) - : undefined, - }, - 'ai.response.providerMetadata': JSON.stringify( - finalStep.providerMetadata, - ), - 'ai.usage.inputTokens': totalUsage.inputTokens, - 'ai.usage.inputTokenDetails.noCacheTokens': - totalUsage.inputTokenDetails?.noCacheTokens, - 'ai.usage.inputTokenDetails.cacheReadTokens': - totalUsage.inputTokenDetails?.cacheReadTokens, - 'ai.usage.inputTokenDetails.cacheWriteTokens': - totalUsage.inputTokenDetails?.cacheWriteTokens, - 'ai.usage.outputTokens': totalUsage.outputTokens, - 'ai.usage.outputTokenDetails.textTokens': - totalUsage.outputTokenDetails?.textTokens, - 'ai.usage.outputTokenDetails.reasoningTokens': - totalUsage.outputTokenDetails?.reasoningTokens, - 'ai.usage.totalTokens': totalUsage.totalTokens, - 'ai.usage.reasoningTokens': - totalUsage.outputTokenDetails?.reasoningTokens, - 'ai.usage.cachedInputTokens': - totalUsage.inputTokenDetails?.cacheReadTokens, - }, - }), - ); - } catch (error) { - controller.error(error); - } finally { - rootSpan.end(); - } - }, - }); - - // initialize the stitchable stream and the transformed stream: - const stitchableStream = createStitchableStream>(); - this.addStream = stitchableStream.addStream; - this.closeStream = stitchableStream.close; - - // resilient stream that handles abort signals and errors: - const reader = stitchableStream.stream.getReader(); - let stream = new ReadableStream>({ - async start(controller) { - // send start event: - controller.enqueue({ type: 'start' }); - }, - - async pull(controller) { - // abort handling: - function abort() { - onAbort?.({ steps: recordedSteps }); - controller.enqueue({ - type: 'abort', - // The `reason` is usually of type DOMException, but it can also be of any type, - // so we use getErrorMessage for serialization because it is already designed to accept values of the unknown type. - // See: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/reason - ...(abortSignal?.reason !== undefined - ? { reason: getErrorMessage(abortSignal.reason) } - : {}), - }); - controller.close(); - } - - try { - const { done, value } = await reader.read(); - - if (done) { - controller.close(); - return; - } - - if (abortSignal?.aborted) { - abort(); - return; - } - - controller.enqueue(value); - } catch (error) { - if (isAbortError(error) && abortSignal?.aborted) { - abort(); - } else { - controller.error(error); - } - } - }, - - cancel(reason) { - return stitchableStream.stream.cancel(reason); - }, - }); - - // transform the stream before output parsing - // to enable replacement of stream segments: - for (const transform of transforms) { - stream = stream.pipeThrough( - transform({ - tools: tools as TOOLS, - stopStream() { - stitchableStream.terminate(); - }, - }), - ); - } - - this.baseStream = stream - .pipeThrough(createOutputTransformStream(output ?? text())) - .pipeThrough(eventProcessor); - - const { maxRetries, retry } = prepareRetries({ - maxRetries: maxRetriesArg, - abortSignal, - }); - - const tracer = getTracer(telemetry); - - const callSettings = prepareCallSettings(settings); - - const baseTelemetryAttributes = getBaseTelemetryAttributes({ - model, - telemetry, - headers, - settings: { ...callSettings, maxRetries }, - }); - - const self = this; - - const modelInfo = { provider: model.provider, modelId: model.modelId }; - const callbackTelemetryProps = { - functionId: telemetry?.functionId, - metadata: telemetry?.metadata as Record | undefined, - }; - - recordSpan({ - name: 'ai.streamText', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ operationId: 'ai.streamText', telemetry }), - ...baseTelemetryAttributes, - // specific settings that only make sense on the outer level: - 'ai.prompt': { - input: () => JSON.stringify({ system, prompt, messages }), - }, - }, - }), - tracer, - endWhenDone: false, - fn: async rootSpanArg => { - rootSpan = rootSpanArg; - - const initialPrompt = await standardizePrompt({ - system, - prompt, - messages, - } as Prompt); - - await notify({ - event: { - model: modelInfo, - system, - prompt, - messages, - tools, - toolChoice, - activeTools, - maxOutputTokens: callSettings.maxOutputTokens, - temperature: callSettings.temperature, - topP: callSettings.topP, - topK: callSettings.topK, - presencePenalty: callSettings.presencePenalty, - frequencyPenalty: callSettings.frequencyPenalty, - stopSequences: callSettings.stopSequences, - seed: callSettings.seed, - maxRetries, - timeout, - headers, - providerOptions, - stopWhen, - output, - abortSignal: originalAbortSignal, - include, - ...callbackTelemetryProps, - experimental_context, - }, - callbacks: [ - onStart, - globalTelemetry.onStart as - | undefined - | StreamTextOnStartCallback, - ], - }); - - const initialMessages = initialPrompt.messages; - const initialResponseMessages: Array = []; - - const { approvedToolApprovals, deniedToolApprovals } = - collectToolApprovals({ messages: initialMessages }); - - // initial tool execution step stream - if ( - deniedToolApprovals.length > 0 || - approvedToolApprovals.length > 0 - ) { - const providerExecutedToolApprovals = [ - ...approvedToolApprovals, - ...deniedToolApprovals, - ].filter(toolApproval => toolApproval.toolCall.providerExecuted); - - const localApprovedToolApprovals = approvedToolApprovals.filter( - toolApproval => !toolApproval.toolCall.providerExecuted, - ); - const localDeniedToolApprovals = deniedToolApprovals.filter( - toolApproval => !toolApproval.toolCall.providerExecuted, - ); - - const deniedProviderExecutedToolApprovals = - deniedToolApprovals.filter( - toolApproval => toolApproval.toolCall.providerExecuted, - ); - - let toolExecutionStepStreamController: - | ReadableStreamDefaultController> - | undefined; - const toolExecutionStepStream = new ReadableStream< - TextStreamPart - >({ - start(controller) { - toolExecutionStepStreamController = controller; - }, - }); - - self.addStream(toolExecutionStepStream); - - try { - for (const toolApproval of [ - ...localDeniedToolApprovals, - ...deniedProviderExecutedToolApprovals, - ]) { - toolExecutionStepStreamController?.enqueue({ - type: 'tool-output-denied', - toolCallId: toolApproval.toolCall.toolCallId, - toolName: toolApproval.toolCall.toolName, - } as StaticToolOutputDenied); - } - - const toolOutputs: Array> = []; - - await Promise.all( - localApprovedToolApprovals.map(async toolApproval => { - const result = await executeToolCall({ - toolCall: toolApproval.toolCall, - tools, - tracer, - telemetry, - messages: initialMessages, - abortSignal, - experimental_context, - stepNumber: recordedSteps.length, - model: modelInfo, - onToolCallStart: [ - onToolCallStart, - globalTelemetry.onToolCallStart as - | undefined - | StreamTextOnToolCallStartCallback, - ], - onToolCallFinish: [ - onToolCallFinish, - globalTelemetry.onToolCallFinish, - ], - onPreliminaryToolResult: result => { - toolExecutionStepStreamController?.enqueue(result); - }, - }); - - if (result != null) { - toolExecutionStepStreamController?.enqueue(result); - toolOutputs.push(result); - } - }), - ); - - // forward provider-executed approval responses to the provider (do not execute locally): - if (providerExecutedToolApprovals.length > 0) { - initialResponseMessages.push({ - role: 'tool', - content: providerExecutedToolApprovals.map( - toolApproval => - ({ - type: 'tool-approval-response', - approvalId: toolApproval.approvalResponse.approvalId, - approved: toolApproval.approvalResponse.approved, - reason: toolApproval.approvalResponse.reason, - providerExecuted: true, - }) satisfies ToolApprovalResponse, - ), - }); - } - - // Local tool results (approved + denied) are sent as tool results: - if (toolOutputs.length > 0 || localDeniedToolApprovals.length > 0) { - const localToolContent: ToolContent = []; - - // add regular tool results for approved tool calls: - for (const output of toolOutputs) { - localToolContent.push({ - type: 'tool-result' as const, - toolCallId: output.toolCallId, - toolName: output.toolName, - output: await createToolModelOutput({ - toolCallId: output.toolCallId, - input: output.input, - tool: tools?.[output.toolName], - output: - output.type === 'tool-result' - ? output.output - : output.error, - errorMode: output.type === 'tool-error' ? 'text' : 'none', - }), - }); - } - - // add execution denied tool results for denied local tool approvals: - for (const toolApproval of localDeniedToolApprovals) { - localToolContent.push({ - type: 'tool-result' as const, - toolCallId: toolApproval.toolCall.toolCallId, - toolName: toolApproval.toolCall.toolName, - output: { - type: 'execution-denied' as const, - reason: toolApproval.approvalResponse.reason, - }, - }); - } - - initialResponseMessages.push({ - role: 'tool', - content: localToolContent, - }); - } - } finally { - toolExecutionStepStreamController?.close(); - } - } - - recordedResponseMessages.push(...initialResponseMessages); - - async function streamStep({ - currentStep, - responseMessages, - usage, - }: { - currentStep: number; - responseMessages: Array; - usage: LanguageModelUsage; - }) { - const includeRawChunks = self.includeRawChunks; - - // Set up step timeout if configured - const stepTimeoutId = - stepTimeoutMs != null - ? setTimeout(() => stepAbortController!.abort(), stepTimeoutMs) - : undefined; - - // Set up chunk timeout tracking (will be reset on each chunk) - let chunkTimeoutId: ReturnType | undefined = - undefined; - - function resetChunkTimeout() { - if (chunkTimeoutMs != null) { - if (chunkTimeoutId != null) { - clearTimeout(chunkTimeoutId); - } - chunkTimeoutId = setTimeout( - () => chunkAbortController!.abort(), - chunkTimeoutMs, - ); - } - } - - function clearChunkTimeout() { - if (chunkTimeoutId != null) { - clearTimeout(chunkTimeoutId); - chunkTimeoutId = undefined; - } - } - - function clearStepTimeout() { - if (stepTimeoutId != null) { - clearTimeout(stepTimeoutId); - } - } - - try { - stepFinish = new DelayedPromise(); - - const stepInputMessages = [...initialMessages, ...responseMessages]; - - const prepareStepResult = await prepareStep?.({ - model, - steps: recordedSteps, - stepNumber: recordedSteps.length, - messages: stepInputMessages, - experimental_context, - }); - - const stepModel = resolveLanguageModel( - prepareStepResult?.model ?? model, - ); - const stepModelInfo = { - provider: stepModel.provider, - modelId: stepModel.modelId, - }; - - const promptMessages = await convertToLanguageModelPrompt({ - prompt: { - system: prepareStepResult?.system ?? initialPrompt.system, - messages: prepareStepResult?.messages ?? stepInputMessages, - }, - supportedUrls: await stepModel.supportedUrls, - download, - }); - - const stepActiveTools = - prepareStepResult?.activeTools ?? activeTools; - - const { toolChoice: stepToolChoice, tools: stepTools } = - await prepareToolsAndToolChoice({ - tools, - toolChoice: prepareStepResult?.toolChoice ?? toolChoice, - activeTools: stepActiveTools, - }); - - experimental_context = - prepareStepResult?.experimental_context ?? experimental_context; - - const stepMessages = - prepareStepResult?.messages ?? stepInputMessages; - - const stepSystem = - prepareStepResult?.system ?? initialPrompt.system; - - const stepProviderOptions = mergeObjects( - providerOptions, - prepareStepResult?.providerOptions, - ); - - await notify({ - event: { - stepNumber: recordedSteps.length, - model: stepModelInfo, - system: stepSystem, - messages: stepMessages, - tools, - toolChoice: stepToolChoice, - activeTools: stepActiveTools, - steps: [...recordedSteps], - providerOptions: stepProviderOptions, - timeout, - headers, - stopWhen, - output, - abortSignal: originalAbortSignal, - include, - ...callbackTelemetryProps, - experimental_context, - }, - callbacks: [ - onStepStart, - globalTelemetry.onStepStart as - | undefined - | StreamTextOnStepStartCallback, - ], - }); - - const { - result: { stream, response, request }, - doStreamSpan, - startTimestampMs, - } = await retry(() => - recordSpan({ - name: 'ai.streamText.doStream', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ - operationId: 'ai.streamText.doStream', - telemetry, - }), - ...baseTelemetryAttributes, - // model: - 'ai.model.provider': stepModel.provider, - 'ai.model.id': stepModel.modelId, - // prompt: - 'ai.prompt.messages': { - input: () => stringifyForTelemetry(promptMessages), - }, - 'ai.prompt.tools': { - // convert the language model level tools: - input: () => stepTools?.map(tool => JSON.stringify(tool)), - }, - 'ai.prompt.toolChoice': { - input: () => - stepToolChoice != null - ? JSON.stringify(stepToolChoice) - : undefined, - }, - - // standardized gen-ai llm span attributes: - 'gen_ai.system': stepModel.provider, - 'gen_ai.request.model': stepModel.modelId, - 'gen_ai.request.frequency_penalty': - callSettings.frequencyPenalty, - 'gen_ai.request.max_tokens': callSettings.maxOutputTokens, - 'gen_ai.request.presence_penalty': - callSettings.presencePenalty, - 'gen_ai.request.stop_sequences': callSettings.stopSequences, - 'gen_ai.request.temperature': callSettings.temperature, - 'gen_ai.request.top_k': callSettings.topK, - 'gen_ai.request.top_p': callSettings.topP, - }, - }), - tracer, - endWhenDone: false, - fn: async doStreamSpan => ({ - startTimestampMs: now(), // get before the call - doStreamSpan, - result: await stepModel.doStream({ - ...callSettings, - tools: stepTools, - toolChoice: stepToolChoice, - responseFormat: await output?.responseFormat, - prompt: promptMessages, - providerOptions: stepProviderOptions, - abortSignal, - headers, - includeRawChunks, - }), - }), - }), - ); - - const streamWithToolResults = runToolsTransformation({ - tools, - generatorStream: stream, - tracer, - telemetry, - system, - messages: stepInputMessages, - repairToolCall, - abortSignal, - experimental_context, - generateId, - stepNumber: recordedSteps.length, - model: stepModelInfo, - onToolCallStart: [ - onToolCallStart, - globalTelemetry.onToolCallStart as - | undefined - | StreamTextOnToolCallStartCallback, - ], - onToolCallFinish: [ - onToolCallFinish, - globalTelemetry.onToolCallFinish, - ], - }); - - // Conditionally include request.body based on include settings. - // Large payloads (e.g., base64-encoded images) can cause memory issues. - const stepRequest: LanguageModelRequestMetadata = - (include?.requestBody ?? true) - ? (request ?? {}) - : { ...request, body: undefined }; - const stepToolCalls: TypedToolCall[] = []; - const stepToolOutputs: ToolOutput[] = []; - let warnings: SharedV3Warning[] | undefined; - - const activeToolCallToolNames: Record = {}; - - let stepFinishReason: FinishReason = 'other'; - let stepRawFinishReason: string | undefined = undefined; - - let stepUsage: LanguageModelUsage = createNullLanguageModelUsage(); - let stepProviderMetadata: ProviderMetadata | undefined; - let stepFirstChunk = true; - let stepResponse: { id: string; timestamp: Date; modelId: string } = - { - id: generateId(), - timestamp: new Date(), - modelId: modelInfo.modelId, - }; - - // raw text as it comes from the provider. recorded for telemetry. - let activeText = ''; - - self.addStream( - streamWithToolResults.pipeThrough( - new TransformStream< - SingleRequestTextStreamPart, - TextStreamPart - >({ - async transform(chunk, controller): Promise { - resetChunkTimeout(); - - if (chunk.type === 'stream-start') { - warnings = chunk.warnings; - return; // stream start chunks are sent immediately and do not count as first chunk - } - - if (stepFirstChunk) { - // Telemetry for first chunk: - const msToFirstChunk = now() - startTimestampMs; - - stepFirstChunk = false; - - doStreamSpan.addEvent('ai.stream.firstChunk', { - 'ai.response.msToFirstChunk': msToFirstChunk, - }); - - doStreamSpan.setAttributes({ - 'ai.response.msToFirstChunk': msToFirstChunk, - }); - - // Step start: - controller.enqueue({ - type: 'start-step', - request: stepRequest, - warnings: warnings ?? [], - }); - } - - const chunkType = chunk.type; - switch (chunkType) { - case 'tool-approval-request': - case 'text-start': - case 'text-end': { - controller.enqueue(chunk); - break; - } - - case 'text-delta': { - if (chunk.delta.length > 0) { - controller.enqueue({ - type: 'text-delta', - id: chunk.id, - text: chunk.delta, - providerMetadata: chunk.providerMetadata, - }); - activeText += chunk.delta; - } - break; - } - - case 'reasoning-start': - case 'reasoning-end': { - controller.enqueue(chunk); - break; - } - - case 'reasoning-delta': { - controller.enqueue({ - type: 'reasoning-delta', - id: chunk.id, - text: chunk.delta, - providerMetadata: chunk.providerMetadata, - }); - break; - } - - case 'tool-call': { - controller.enqueue(chunk); - // store tool calls for onFinish callback and toolCalls promise: - stepToolCalls.push(chunk); - break; - } - - case 'tool-result': { - controller.enqueue(chunk); - - if (!chunk.preliminary) { - stepToolOutputs.push(chunk); - } - - break; - } - - case 'tool-error': { - controller.enqueue(chunk); - stepToolOutputs.push(chunk); - break; - } - - case 'response-metadata': { - stepResponse = { - id: chunk.id ?? stepResponse.id, - timestamp: chunk.timestamp ?? stepResponse.timestamp, - modelId: chunk.modelId ?? stepResponse.modelId, - }; - break; - } - - case 'finish': { - // Note: tool executions might not be finished yet when the finish event is emitted. - // store usage and finish reason for promises and onFinish callback: - stepUsage = chunk.usage; - stepFinishReason = chunk.finishReason; - stepRawFinishReason = chunk.rawFinishReason; - stepProviderMetadata = chunk.providerMetadata; - - // Telemetry for finish event timing - // (since tool executions can take longer and distort calculations) - const msToFinish = now() - startTimestampMs; - doStreamSpan.addEvent('ai.stream.finish'); - doStreamSpan.setAttributes({ - 'ai.response.msToFinish': msToFinish, - 'ai.response.avgOutputTokensPerSecond': - (1000 * (stepUsage.outputTokens ?? 0)) / msToFinish, - }); - - break; - } - - case 'file': { - controller.enqueue(chunk); - break; - } - - case 'source': { - controller.enqueue(chunk); - break; - } - - case 'tool-input-start': { - activeToolCallToolNames[chunk.id] = chunk.toolName; - - const tool = tools?.[chunk.toolName]; - if (tool?.onInputStart != null) { - await tool.onInputStart({ - toolCallId: chunk.id, - messages: stepInputMessages, - abortSignal, - experimental_context, - }); - } - - controller.enqueue({ - ...chunk, - dynamic: chunk.dynamic ?? tool?.type === 'dynamic', - title: tool?.title, - }); - break; - } - - case 'tool-input-end': { - delete activeToolCallToolNames[chunk.id]; - controller.enqueue(chunk); - break; - } - - case 'tool-input-delta': { - const toolName = activeToolCallToolNames[chunk.id]; - const tool = tools?.[toolName]; - - if (tool?.onInputDelta != null) { - await tool.onInputDelta({ - inputTextDelta: chunk.delta, - toolCallId: chunk.id, - messages: stepInputMessages, - abortSignal, - experimental_context, - }); - } - - controller.enqueue(chunk); - break; - } - - case 'error': { - controller.enqueue(chunk); - stepFinishReason = 'error'; - break; - } - - case 'raw': { - if (includeRawChunks) { - controller.enqueue(chunk); - } - break; - } - - default: { - const exhaustiveCheck: never = chunkType; - throw new Error( - `Unknown chunk type: ${exhaustiveCheck}`, - ); - } - } - }, - - // invoke onFinish callback and resolve toolResults promise when the stream is about to close: - async flush(controller) { - const stepToolCallsJson = - stepToolCalls.length > 0 - ? JSON.stringify(stepToolCalls) - : undefined; - - // record telemetry attributes that don't depend on transforms: - try { - doStreamSpan.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.response.finishReason': stepFinishReason, - 'ai.response.toolCalls': { - output: () => stepToolCallsJson, - }, - 'ai.response.id': stepResponse.id, - 'ai.response.model': stepResponse.modelId, - 'ai.response.timestamp': - stepResponse.timestamp.toISOString(), - 'ai.usage.inputTokens': stepUsage.inputTokens, - 'ai.usage.inputTokenDetails.noCacheTokens': - stepUsage.inputTokenDetails?.noCacheTokens, - 'ai.usage.inputTokenDetails.cacheReadTokens': - stepUsage.inputTokenDetails?.cacheReadTokens, - 'ai.usage.inputTokenDetails.cacheWriteTokens': - stepUsage.inputTokenDetails?.cacheWriteTokens, - 'ai.usage.outputTokens': stepUsage.outputTokens, - 'ai.usage.outputTokenDetails.textTokens': - stepUsage.outputTokenDetails?.textTokens, - 'ai.usage.outputTokenDetails.reasoningTokens': - stepUsage.outputTokenDetails?.reasoningTokens, - 'ai.usage.totalTokens': stepUsage.totalTokens, - 'ai.usage.reasoningTokens': - stepUsage.outputTokenDetails?.reasoningTokens, - 'ai.usage.cachedInputTokens': - stepUsage.inputTokenDetails?.cacheReadTokens, - - // standardized gen-ai llm span attributes: - 'gen_ai.response.finish_reasons': [ - stepFinishReason, - ], - 'gen_ai.response.id': stepResponse.id, - 'gen_ai.response.model': stepResponse.modelId, - 'gen_ai.usage.input_tokens': stepUsage.inputTokens, - 'gen_ai.usage.output_tokens': - stepUsage.outputTokens, - }, - }), - ); - } catch (error) { - // ignore error setting telemetry attributes - } - - controller.enqueue({ - type: 'finish-step', - finishReason: stepFinishReason, - rawFinishReason: stepRawFinishReason, - usage: stepUsage, - providerMetadata: stepProviderMetadata, - response: { - ...stepResponse, - headers: response?.headers, - }, - }); - - const combinedUsage = addLanguageModelUsage( - usage, - stepUsage, - ); - - // wait for the step to be fully processed by the event processor - // to ensure that the recorded steps are complete: - await stepFinish.promise; - - // set transform-dependent attributes after the step has been - // fully processed (post-transform) by the event processor: - const processedStep = - recordedSteps[recordedSteps.length - 1]; - try { - doStreamSpan.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.response.text': { - output: () => processedStep.text, - }, - 'ai.response.reasoning': { - output: () => processedStep.reasoningText, - }, - 'ai.response.providerMetadata': JSON.stringify( - processedStep.providerMetadata, - ), - }, - }), - ); - } catch (error) { - // ignore error setting telemetry attributes - } finally { - doStreamSpan.end(); - } - - const clientToolCalls = stepToolCalls.filter( - toolCall => toolCall.providerExecuted !== true, - ); - const clientToolOutputs = stepToolOutputs.filter( - toolOutput => toolOutput.providerExecuted !== true, - ); - - // Track provider-executed tool calls that support deferred results. - // In programmatic tool calling, a server tool (e.g., code_execution) may - // trigger a client tool, and the server tool's result is deferred until - // the client tool's result is sent back. - for (const toolCall of stepToolCalls) { - if (toolCall.providerExecuted !== true) continue; - const tool = tools?.[toolCall.toolName]; - if ( - tool?.type === 'provider' && - tool.supportsDeferredResults - ) { - // Check if this tool call already has a result in the current step - const hasResultInStep = stepToolOutputs.some( - output => - (output.type === 'tool-result' || - output.type === 'tool-error') && - output.toolCallId === toolCall.toolCallId, - ); - if (!hasResultInStep) { - pendingDeferredToolCalls.set(toolCall.toolCallId, { - toolName: toolCall.toolName, - }); - } - } - } - - // Mark deferred tool calls as resolved when we receive their results - for (const output of stepToolOutputs) { - if ( - output.type === 'tool-result' || - output.type === 'tool-error' - ) { - pendingDeferredToolCalls.delete(output.toolCallId); - } - } - - // Clear the step and chunk timeouts before the next step is started - clearStepTimeout(); - clearChunkTimeout(); - - if ( - // Continue if: - // 1. There are client tool calls that have all been executed, OR - // 2. There are pending deferred results from provider-executed tools - ((clientToolCalls.length > 0 && - clientToolOutputs.length === clientToolCalls.length) || - pendingDeferredToolCalls.size > 0) && - // continue until a stop condition is met: - !(await isStopConditionMet({ - stopConditions, - steps: recordedSteps, - })) - ) { - // append to messages for the next step: - responseMessages.push( - ...(await toResponseMessages({ - content: - // use transformed content to create the messages for the next step: - recordedSteps[recordedSteps.length - 1].content, - tools, - })), - ); - - try { - await streamStep({ - currentStep: currentStep + 1, - responseMessages, - usage: combinedUsage, - }); - } catch (error) { - controller.enqueue({ - type: 'error', - error, - }); - - self.closeStream(); - } - } else { - controller.enqueue({ - type: 'finish', - finishReason: stepFinishReason, - rawFinishReason: stepRawFinishReason, - totalUsage: combinedUsage, - }); - - self.closeStream(); // close the stitchable stream - } - }, - }), - ), - ); - } finally { - clearStepTimeout(); - clearChunkTimeout(); - } - } - - // add the initial stream to the stitchable stream - await streamStep({ - currentStep: 0, - responseMessages: initialResponseMessages, - usage: createNullLanguageModelUsage(), - }); - }, - }).catch(error => { - // add an error stream part and close the streams: - self.addStream( - new ReadableStream({ - start(controller) { - controller.enqueue({ type: 'error', error }); - controller.close(); - }, - }), - ); - self.closeStream(); - }); - } - - get steps() { - // when any of the promises are accessed, the stream is consumed - // so it resolves without needing to consume the stream separately - this.consumeStream(); - - return this._steps.promise; - } - - private get finalStep() { - return this.steps.then(steps => steps[steps.length - 1]); - } - - get content() { - return this.finalStep.then(step => step.content); - } - - get warnings() { - return this.finalStep.then(step => step.warnings); - } - - get providerMetadata() { - return this.finalStep.then(step => step.providerMetadata); - } - - get text() { - return this.finalStep.then(step => step.text); - } - - get reasoningText() { - return this.finalStep.then(step => step.reasoningText); - } - - get reasoning() { - return this.finalStep.then(step => step.reasoning); - } - - get sources() { - return this.finalStep.then(step => step.sources); - } - - get files() { - return this.finalStep.then(step => step.files); - } - - get toolCalls() { - return this.finalStep.then(step => step.toolCalls); - } - - get staticToolCalls() { - return this.finalStep.then(step => step.staticToolCalls); - } - - get dynamicToolCalls() { - return this.finalStep.then(step => step.dynamicToolCalls); - } - - get toolResults() { - return this.finalStep.then(step => step.toolResults); - } - - get staticToolResults() { - return this.finalStep.then(step => step.staticToolResults); - } - - get dynamicToolResults() { - return this.finalStep.then(step => step.dynamicToolResults); - } - - get usage() { - return this.finalStep.then(step => step.usage); - } - - get request() { - return this.finalStep.then(step => step.request); - } - - get response() { - return this.finalStep.then(step => step.response); - } - - get totalUsage() { - // when any of the promises are accessed, the stream is consumed - // so it resolves without needing to consume the stream separately - this.consumeStream(); - - return this._totalUsage.promise; - } - - get finishReason() { - // when any of the promises are accessed, the stream is consumed - // so it resolves without needing to consume the stream separately - this.consumeStream(); - - return this._finishReason.promise; - } - - get rawFinishReason() { - // when any of the promises are accessed, the stream is consumed - // so it resolves without needing to consume the stream separately - this.consumeStream(); - - return this._rawFinishReason.promise; - } - - /** - * Split out a new stream from the original stream. - * The original stream is replaced to allow for further splitting, - * since we do not know how many times the stream will be split. - * - * Note: this leads to buffering the stream content on the server. - * However, the LLM results are expected to be small enough to not cause issues. - */ - private teeStream() { - const [stream1, stream2] = this.baseStream.tee(); - this.baseStream = stream2; - return stream1; - } - - get textStream(): AsyncIterableStream { - return createAsyncIterableStream( - this.teeStream().pipeThrough( - new TransformStream< - EnrichedStreamPart>, - string - >({ - transform({ part }, controller) { - if (part.type === 'text-delta') { - controller.enqueue(part.text); - } - }, - }), - ), - ); - } - - get fullStream(): AsyncIterableStream> { - return createAsyncIterableStream( - this.teeStream().pipeThrough( - new TransformStream< - EnrichedStreamPart>, - TextStreamPart - >({ - transform({ part }, controller) { - controller.enqueue(part); - }, - }), - ), - ); - } - - async consumeStream(options?: ConsumeStreamOptions): Promise { - try { - await consumeStream({ - stream: this.fullStream, - onError: options?.onError, - }); - } catch (error) { - options?.onError?.(error); - } - } - - get experimental_partialOutputStream(): AsyncIterableStream< - InferPartialOutput - > { - return this.partialOutputStream; - } - - get partialOutputStream(): AsyncIterableStream> { - return createAsyncIterableStream( - this.teeStream().pipeThrough( - new TransformStream< - EnrichedStreamPart>, - InferPartialOutput - >({ - transform({ partialOutput }, controller) { - if (partialOutput != null) { - controller.enqueue(partialOutput); - } - }, - }), - ), - ); - } - - get elementStream(): AsyncIterableStream> { - const transform = this.outputSpecification?.createElementStreamTransform(); - - if (transform == null) { - throw new UnsupportedFunctionalityError({ - functionality: `element streams in ${this.outputSpecification?.name ?? 'text'} mode`, - }); - } - - return createAsyncIterableStream(this.teeStream().pipeThrough(transform)); - } - - get output(): Promise> { - return this.finalStep.then(step => { - const output = this.outputSpecification ?? text(); - return output.parseCompleteOutput( - { text: step.text }, - { - response: step.response, - usage: step.usage, - finishReason: step.finishReason, - }, - ); - }); - } - - toUIMessageStream({ - originalMessages, - generateMessageId, - onFinish, - messageMetadata, - sendReasoning = true, - sendSources = false, - sendStart = true, - sendFinish = true, - onError = getErrorMessage, - }: UIMessageStreamOptions = {}): AsyncIterableStream< - InferUIMessageChunk - > { - const responseMessageId = - generateMessageId != null - ? getResponseUIMessageId({ - originalMessages, - responseMessageId: generateMessageId, - }) - : undefined; - - // TODO simplify once dynamic is no longer needed for invalid tool inputs - const isDynamic = (part: { toolName: string; dynamic?: boolean }) => { - const tool = this.tools?.[part.toolName]; - - // provider-executed, dynamic tools are not listed in the tools object - if (tool == null) { - return part.dynamic; - } - - return tool?.type === 'dynamic' ? true : undefined; - }; - - const baseStream = this.fullStream.pipeThrough( - new TransformStream< - TextStreamPart, - UIMessageChunk< - InferUIMessageMetadata, - InferUIMessageData - > - >({ - transform: async (part, controller) => { - const messageMetadataValue = messageMetadata?.({ part }); - - const partType = part.type; - switch (partType) { - case 'text-start': { - controller.enqueue({ - type: 'text-start', - id: part.id, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - }); - break; - } - - case 'text-delta': { - controller.enqueue({ - type: 'text-delta', - id: part.id, - delta: part.text, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - }); - break; - } - - case 'text-end': { - controller.enqueue({ - type: 'text-end', - id: part.id, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - }); - break; - } - - case 'reasoning-start': { - controller.enqueue({ - type: 'reasoning-start', - id: part.id, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - }); - break; - } - - case 'reasoning-delta': { - if (sendReasoning) { - controller.enqueue({ - type: 'reasoning-delta', - id: part.id, - delta: part.text, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - }); - } - break; - } - - case 'reasoning-end': { - controller.enqueue({ - type: 'reasoning-end', - id: part.id, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - }); - break; - } - - case 'file': { - controller.enqueue({ - type: 'file', - mediaType: part.file.mediaType, - url: `data:${part.file.mediaType};base64,${part.file.base64}`, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - }); - break; - } - - case 'source': { - if (sendSources && part.sourceType === 'url') { - controller.enqueue({ - type: 'source-url', - sourceId: part.id, - url: part.url, - title: part.title, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - }); - } - - if (sendSources && part.sourceType === 'document') { - controller.enqueue({ - type: 'source-document', - sourceId: part.id, - mediaType: part.mediaType, - title: part.title, - filename: part.filename, - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - }); - } - break; - } - - case 'tool-input-start': { - const dynamic = isDynamic(part); - - controller.enqueue({ - type: 'tool-input-start', - toolCallId: part.id, - toolName: part.toolName, - ...(part.providerExecuted != null - ? { providerExecuted: part.providerExecuted } - : {}), - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - ...(dynamic != null ? { dynamic } : {}), - ...(part.title != null ? { title: part.title } : {}), - }); - break; - } - - case 'tool-input-delta': { - controller.enqueue({ - type: 'tool-input-delta', - toolCallId: part.id, - inputTextDelta: part.delta, - }); - break; - } - - case 'tool-call': { - const dynamic = isDynamic(part); - - if (part.invalid) { - controller.enqueue({ - type: 'tool-input-error', - toolCallId: part.toolCallId, - toolName: part.toolName, - input: part.input, - ...(part.providerExecuted != null - ? { providerExecuted: part.providerExecuted } - : {}), - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - ...(dynamic != null ? { dynamic } : {}), - errorText: onError(part.error), - ...(part.title != null ? { title: part.title } : {}), - }); - } else { - controller.enqueue({ - type: 'tool-input-available', - toolCallId: part.toolCallId, - toolName: part.toolName, - input: part.input, - ...(part.providerExecuted != null - ? { providerExecuted: part.providerExecuted } - : {}), - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - ...(dynamic != null ? { dynamic } : {}), - ...(part.title != null ? { title: part.title } : {}), - }); - } - - break; - } - - case 'tool-approval-request': { - controller.enqueue({ - type: 'tool-approval-request', - approvalId: part.approvalId, - toolCallId: part.toolCall.toolCallId, - }); - break; - } - - case 'tool-result': { - const dynamic = isDynamic(part); - - controller.enqueue({ - type: 'tool-output-available', - toolCallId: part.toolCallId, - output: part.output, - ...(part.providerExecuted != null - ? { providerExecuted: part.providerExecuted } - : {}), - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - ...(part.preliminary != null - ? { preliminary: part.preliminary } - : {}), - ...(dynamic != null ? { dynamic } : {}), - }); - break; - } - - case 'tool-error': { - const dynamic = isDynamic(part); - - controller.enqueue({ - type: 'tool-output-error', - toolCallId: part.toolCallId, - errorText: part.providerExecuted - ? typeof part.error === 'string' - ? part.error - : JSON.stringify(part.error) - : onError(part.error), - ...(part.providerExecuted != null - ? { providerExecuted: part.providerExecuted } - : {}), - ...(part.providerMetadata != null - ? { providerMetadata: part.providerMetadata } - : {}), - ...(dynamic != null ? { dynamic } : {}), - }); - break; - } - - case 'tool-output-denied': { - controller.enqueue({ - type: 'tool-output-denied', - toolCallId: part.toolCallId, - }); - break; - } - - case 'error': { - controller.enqueue({ - type: 'error', - errorText: onError(part.error), - }); - break; - } - - case 'start-step': { - controller.enqueue({ type: 'start-step' }); - break; - } - - case 'finish-step': { - controller.enqueue({ type: 'finish-step' }); - break; - } - - case 'start': { - if (sendStart) { - controller.enqueue({ - type: 'start', - ...(messageMetadataValue != null - ? { messageMetadata: messageMetadataValue } - : {}), - ...(responseMessageId != null - ? { messageId: responseMessageId } - : {}), - }); - } - break; - } - - case 'finish': { - if (sendFinish) { - controller.enqueue({ - type: 'finish', - finishReason: part.finishReason, - ...(messageMetadataValue != null - ? { messageMetadata: messageMetadataValue } - : {}), - }); - } - break; - } - - case 'abort': { - controller.enqueue(part); - break; - } - - case 'tool-input-end': { - break; - } - - case 'raw': { - // Raw chunks are not included in UI message streams - // as they contain provider-specific data for developer use - break; - } - - default: { - const exhaustiveCheck: never = partType; - throw new Error(`Unknown chunk type: ${exhaustiveCheck}`); - } - } - - // start and finish events already have metadata - // so we only need to send metadata for other parts - if ( - messageMetadataValue != null && - partType !== 'start' && - partType !== 'finish' - ) { - controller.enqueue({ - type: 'message-metadata', - messageMetadata: messageMetadataValue, - }); - } - }, - }), - ); - - return createAsyncIterableStream( - handleUIMessageStreamFinish({ - stream: baseStream, - messageId: responseMessageId ?? generateMessageId?.(), - originalMessages, - onFinish, - onError, - }), - ); - } - - pipeUIMessageStreamToResponse( - response: ServerResponse, - { - originalMessages, - generateMessageId, - onFinish, - messageMetadata, - sendReasoning, - sendSources, - sendFinish, - sendStart, - onError, - ...init - }: UIMessageStreamResponseInit & UIMessageStreamOptions = {}, - ) { - pipeUIMessageStreamToResponse({ - response, - stream: this.toUIMessageStream({ - originalMessages, - generateMessageId, - onFinish, - messageMetadata, - sendReasoning, - sendSources, - sendFinish, - sendStart, - onError, - }), - ...init, - }); - } - - pipeTextStreamToResponse(response: ServerResponse, init?: ResponseInit) { - pipeTextStreamToResponse({ - response, - textStream: this.textStream, - ...init, - }); - } - - toUIMessageStreamResponse({ - originalMessages, - generateMessageId, - onFinish, - messageMetadata, - sendReasoning, - sendSources, - sendFinish, - sendStart, - onError, - ...init - }: UIMessageStreamResponseInit & - UIMessageStreamOptions = {}): Response { - return createUIMessageStreamResponse({ - stream: this.toUIMessageStream({ - originalMessages, - generateMessageId, - onFinish, - messageMetadata, - sendReasoning, - sendSources, - sendFinish, - sendStart, - onError, - }), - ...init, - }); - } - - toTextStreamResponse(init?: ResponseInit): Response { - return createTextStreamResponse({ - textStream: this.textStream, - ...init, - }); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/to-response-messages.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/to-response-messages.ts deleted file mode 100644 index b2fb6e8b7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/to-response-messages.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { - AssistantContent, - AssistantModelMessage, - ToolContent, - ToolModelMessage, -} from '../prompt'; -import { createToolModelOutput } from '../prompt/create-tool-model-output'; -import { ContentPart } from './content-part'; -import { ToolSet } from './tool-set'; - -/** - * Converts the result of a `generateText` or `streamText` call to a list of response messages. - */ -export async function toResponseMessages({ - content: inputContent, - tools, -}: { - content: Array>; - tools: TOOLS | undefined; -}): Promise> { - const responseMessages: Array = []; - - const content: AssistantContent = []; - for (const part of inputContent) { - // Skip sources - they are response-only content that no provider expects back - if (part.type === 'source') { - continue; - } - - // Skip non-provider-executed tool results/errors (they go in the tool message) - if ( - (part.type === 'tool-result' || part.type === 'tool-error') && - !part.providerExecuted - ) { - continue; - } - - // Skip empty text - if (part.type === 'text' && part.text.length === 0) { - continue; - } - - switch (part.type) { - case 'text': - content.push({ - type: 'text', - text: part.text, - providerOptions: part.providerMetadata, - }); - break; - case 'reasoning': - content.push({ - type: 'reasoning', - text: part.text, - providerOptions: part.providerMetadata, - }); - break; - case 'file': - content.push({ - type: 'file', - data: part.file.base64, - mediaType: part.file.mediaType, - providerOptions: part.providerMetadata, - }); - break; - case 'tool-call': - content.push({ - type: 'tool-call', - toolCallId: part.toolCallId, - toolName: part.toolName, - input: part.input, - providerExecuted: part.providerExecuted, - providerOptions: part.providerMetadata, - }); - break; - case 'tool-result': { - const output = await createToolModelOutput({ - toolCallId: part.toolCallId, - input: part.input, - tool: tools?.[part.toolName], - output: part.output, - errorMode: 'none', - }); - content.push({ - type: 'tool-result', - toolCallId: part.toolCallId, - toolName: part.toolName, - output, - providerOptions: part.providerMetadata, - }); - break; - } - case 'tool-error': { - const output = await createToolModelOutput({ - toolCallId: part.toolCallId, - input: part.input, - tool: tools?.[part.toolName], - output: part.error, - errorMode: 'json', - }); - content.push({ - type: 'tool-result', - toolCallId: part.toolCallId, - toolName: part.toolName, - output, - providerOptions: part.providerMetadata, - }); - break; - } - case 'tool-approval-request': - content.push({ - type: 'tool-approval-request', - approvalId: part.approvalId, - toolCallId: part.toolCall.toolCallId, - }); - break; - } - } - - if (content.length > 0) { - responseMessages.push({ - role: 'assistant', - content, - }); - } - - const toolResultContent: ToolContent = []; - for (const part of inputContent) { - if ( - !(part.type === 'tool-result' || part.type === 'tool-error') || - part.providerExecuted - ) { - continue; - } - - const output = await createToolModelOutput({ - toolCallId: part.toolCallId, - input: part.input, - tool: tools?.[part.toolName], - output: part.type === 'tool-result' ? part.output : part.error, - errorMode: part.type === 'tool-error' ? 'text' : 'none', - }); - - toolResultContent.push({ - type: 'tool-result', - toolCallId: part.toolCallId, - toolName: part.toolName, - output, - ...(part.providerMetadata != null - ? { providerOptions: part.providerMetadata } - : {}), - }); - } - - if (toolResultContent.length > 0) { - responseMessages.push({ - role: 'tool', - content: toolResultContent, - }); - } - - return responseMessages; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-approval-request-output.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-approval-request-output.ts deleted file mode 100644 index 2880b67e0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-approval-request-output.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { TypedToolCall } from './tool-call'; -import { ToolSet } from './tool-set'; - -/** - * Output part that indicates that a tool approval request has been made. - * - * The tool approval request can be approved or denied in the next tool message. - */ -export type ToolApprovalRequestOutput = { - type: 'tool-approval-request'; - - /** - * ID of the tool approval request. - */ - approvalId: string; - - /** - * Tool call that the approval request is for. - */ - toolCall: TypedToolCall; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-call-repair-function.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-call-repair-function.ts deleted file mode 100644 index ff63129aa..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-call-repair-function.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { JSONSchema7, LanguageModelV3ToolCall } from '@ai-sdk/provider'; -import { InvalidToolInputError } from '../error/invalid-tool-input-error'; -import { NoSuchToolError } from '../error/no-such-tool-error'; -import { ModelMessage, SystemModelMessage } from '../prompt'; -import { ToolSet } from './tool-set'; - -/** - * A function that attempts to repair a tool call that failed to parse. - * - * It receives the error and the context as arguments and returns the repair - * tool call JSON as text. - * - * @param options.system - The system prompt. - * @param options.messages - The messages in the current generation step. - * @param options.toolCall - The tool call that failed to parse. - * @param options.tools - The tools that are available. - * @param options.inputSchema - A function that returns the JSON Schema for a tool. - * @param options.error - The error that occurred while parsing the tool call. - */ -export type ToolCallRepairFunction = (options: { - system: string | SystemModelMessage | Array | undefined; - messages: ModelMessage[]; - toolCall: LanguageModelV3ToolCall; - tools: TOOLS; - inputSchema: (options: { toolName: string }) => PromiseLike; - error: NoSuchToolError | InvalidToolInputError; -}) => Promise; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-call.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-call.ts deleted file mode 100644 index b6f087a67..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-call.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Tool } from '@ai-sdk/provider-utils'; -import { ProviderMetadata } from '../types'; -import { ValueOf } from '../util/value-of'; -import { ToolSet } from './tool-set'; - -type BaseToolCall = { - type: 'tool-call'; - toolCallId: string; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; -}; - -export type StaticToolCall = ValueOf<{ - [NAME in keyof TOOLS]: BaseToolCall & { - toolName: NAME & string; - input: TOOLS[NAME] extends Tool ? PARAMETERS : never; - dynamic?: false | undefined; - invalid?: false | undefined; - error?: never; - title?: string; - }; -}>; - -export type DynamicToolCall = BaseToolCall & { - toolName: string; - input: unknown; - dynamic: true; - title?: string; - - /** - * True if this is caused by an unparsable tool call or - * a tool that does not exist. - */ - // Added into DynamicToolCall to avoid breaking changes. - // TODO AI SDK 6: separate into a new InvalidToolCall type - invalid?: boolean; - - /** - * The error that caused the tool call to be invalid. - */ - // TODO AI SDK 6: separate into a new InvalidToolCall type - error?: unknown; -}; - -export type TypedToolCall = - | StaticToolCall - | DynamicToolCall; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-error.ts deleted file mode 100644 index 12d0540ef..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-error.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { InferToolInput } from '@ai-sdk/provider-utils'; -import { ProviderMetadata } from '../types'; -import { ValueOf } from '../util/value-of'; -import { ToolSet } from './tool-set'; - -export type StaticToolError = ValueOf<{ - [NAME in keyof TOOLS]: { - type: 'tool-error'; - toolCallId: string; - toolName: NAME & string; - input: InferToolInput; - error: unknown; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; - dynamic?: false | undefined; - title?: string; - }; -}>; - -export type DynamicToolError = { - type: 'tool-error'; - toolCallId: string; - toolName: string; - input: unknown; - error: unknown; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; - dynamic: true; - title?: string; -}; - -export type TypedToolError = - | StaticToolError - | DynamicToolError; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-output-denied.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-output-denied.ts deleted file mode 100644 index dc3cf700e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-output-denied.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ValueOf } from '../util/value-of'; -import { ToolSet } from './tool-set'; - -/** - * Tool output when the tool execution has been denied (for static tools). - */ -export type StaticToolOutputDenied = ValueOf<{ - [NAME in keyof TOOLS]: { - type: 'tool-output-denied'; - toolCallId: string; - toolName: NAME & string; - providerExecuted?: boolean; - dynamic?: false | undefined; - }; -}>; - -/** - * Tool output when the tool execution has been denied. - */ -export type TypedToolOutputDenied = - StaticToolOutputDenied; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-output.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-output.ts deleted file mode 100644 index 0c79c1426..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-output.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { TypedToolError } from './tool-error'; -import { TypedToolResult } from './tool-result'; -import { ToolSet } from './tool-set'; - -export type ToolOutput = - | TypedToolResult - | TypedToolError; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-result.ts deleted file mode 100644 index 406deef02..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-result.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { InferToolInput, InferToolOutput } from '@ai-sdk/provider-utils'; -import { ProviderMetadata } from '../types'; -import { ValueOf } from '../../src/util/value-of'; -import { ToolSet } from './tool-set'; - -export type StaticToolResult = ValueOf<{ - [NAME in keyof TOOLS]: { - type: 'tool-result'; - toolCallId: string; - toolName: NAME & string; - input: InferToolInput; - output: InferToolOutput; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; - dynamic?: false | undefined; - preliminary?: boolean; - title?: string; - }; -}>; - -export type DynamicToolResult = { - type: 'tool-result'; - toolCallId: string; - toolName: string; - input: unknown; - output: unknown; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; - dynamic: true; - preliminary?: boolean; - title?: string; -}; - -export type TypedToolResult = - | StaticToolResult - | DynamicToolResult; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-set.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-set.ts deleted file mode 100644 index 09e64774d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-text/tool-set.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Tool } from '@ai-sdk/provider-utils'; - -export type ToolSet = Record< - string, - (Tool | Tool | Tool | Tool) & - Pick< - Tool, - | 'execute' - | 'onInputAvailable' - | 'onInputStart' - | 'onInputDelta' - | 'needsApproval' - > ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-video/generate-video-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-video/generate-video-result.ts deleted file mode 100644 index 10a45156b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-video/generate-video-result.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { GeneratedFile } from '../generate-text'; -import { VideoModelProviderMetadata } from '../types/video-model'; -import { VideoModelResponseMetadata } from '../types/video-model-response-metadata'; -import { Warning } from '../types/warning'; - -/** - * The result of an `experimental_generateVideo` call. - * Contains the generated video and additional information. - */ -export interface GenerateVideoResult { - /** - * The first video that was generated. - */ - readonly video: GeneratedFile; - - /** - * All videos that were generated. - */ - readonly videos: Array; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - readonly warnings: Array; - - /** - * Response metadata from the provider. - * May contain multiple responses if multiple calls were made. - */ - readonly responses: Array; - - /** - * Provider-specific metadata passed through from the provider. - */ - readonly providerMetadata: VideoModelProviderMetadata; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-video/generate-video.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-video/generate-video.ts deleted file mode 100644 index 9846838df..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-video/generate-video.ts +++ /dev/null @@ -1,402 +0,0 @@ -import type { - Experimental_VideoModelV3, - Experimental_VideoModelV3CallOptions, - Experimental_VideoModelV3File, - SharedV3ProviderMetadata, -} from '@ai-sdk/provider'; -import { - convertBase64ToUint8Array, - type DataContent, - type ProviderOptions, - withUserAgentSuffix, -} from '@ai-sdk/provider-utils'; -import { NoVideoGeneratedError } from '../error/no-video-generated-error'; -import { - DefaultGeneratedFile, - type GeneratedFile, -} from '../generate-text/generated-file'; -import { logWarnings } from '../logger/log-warnings'; -import { resolveVideoModel } from '../model/resolve-model'; -import type { VideoModel } from '../types/video-model'; -import type { VideoModelResponseMetadata } from '../types/video-model-response-metadata'; -import type { Warning } from '../types/warning'; -import { - detectMediaType, - imageMediaTypeSignatures, - videoMediaTypeSignatures, -} from '../util/detect-media-type'; -import { createDownload } from '../util/download/create-download'; -import { prepareRetries } from '../util/prepare-retries'; -import { VERSION } from '../version'; -import type { GenerateVideoResult } from './generate-video-result'; -import { splitDataUrl } from '../prompt/split-data-url'; - -export type GenerateVideoPrompt = - | string - | { - image: DataContent; - text?: string; - }; - -/** - * Generates videos using a video model. - * - * @param model - The video model to use. - * @param prompt - The prompt that should be used to generate the video. - * @param n - Number of videos to generate. Default: 1. - * @param aspectRatio - Aspect ratio of the videos to generate. Must have the format `{width}:{height}`. - * @param resolution - Resolution of the videos to generate. Must have the format `{width}x{height}`. - * @param duration - Duration of the video in seconds. - * @param fps - Frames per second for the video. - * @param seed - Seed for the video generation. - * @param providerOptions - Additional provider-specific options that are passed through to the provider - * as body parameters. - * @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2. - * @param abortSignal - An optional abort signal that can be used to cancel the call. - * @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers. - * - * @returns A result object that contains the generated videos. - */ -const defaultDownload = createDownload(); - -export async function experimental_generateVideo({ - model: modelArg, - prompt: promptArg, - n = 1, - maxVideosPerCall, - aspectRatio, - resolution, - duration, - fps, - seed, - providerOptions, - maxRetries: maxRetriesArg, - abortSignal, - headers, - download: downloadFn = defaultDownload, -}: { - /** - * The video model to use. - */ - model: VideoModel; - - /** - * The prompt that should be used to generate the video. - */ - prompt: GenerateVideoPrompt; - - /** - * Number of videos to generate. - */ - n?: number; - - /** - * Maximum number of videos per API call. If not provided, the model's default will be used. - */ - maxVideosPerCall?: number; - - /** - * Aspect ratio of the videos to generate. Must have the format `{width}:{height}`. - */ - aspectRatio?: `${number}:${number}`; - - /** - * Resolution of the videos to generate. Must have the format `{width}x{height}`. - */ - resolution?: `${number}x${number}`; - - /** - * Duration of the video in seconds. - */ - duration?: number; - - /** - * Frames per second for the video. - */ - fps?: number; - - /** - * Seed for the video generation. - */ - seed?: number; - - /** - * Additional provider-specific options that are passed through to the provider - * as body parameters. - */ - providerOptions?: ProviderOptions; - - /** - * Maximum number of retries per video model call. Set to 0 to disable retries. - * - * @default 2 - */ - maxRetries?: number; - - /** - * Abort signal. - */ - abortSignal?: AbortSignal; - - /** - * Additional headers to include in the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; - - /** - * Custom download function for fetching videos from URLs. - * Use `createDownload()` from `ai` to create a download function with custom size limits. - * - * @default createDownload() (2 GiB limit) - */ - download?: (options: { - url: URL; - abortSignal?: AbortSignal; - }) => Promise<{ data: Uint8Array; mediaType: string | undefined }>; -}): Promise { - const model = resolveVideoModel(modelArg); - - const headersWithUserAgent = withUserAgentSuffix( - headers ?? {}, - `ai/${VERSION}`, - ); - - const { retry } = prepareRetries({ - maxRetries: maxRetriesArg, - abortSignal, - }); - - const { prompt, image } = normalizePrompt(promptArg); - - const maxVideosPerCallWithDefault = - maxVideosPerCall ?? (await invokeModelMaxVideosPerCall(model)) ?? 1; - - // parallelize calls to the model: - const callCount = Math.ceil(n / maxVideosPerCallWithDefault); - const callVideoCounts = Array.from({ length: callCount }, (_, index) => { - const remaining = n - index * maxVideosPerCallWithDefault; - return Math.min(remaining, maxVideosPerCallWithDefault); - }); - - const results = await Promise.all( - callVideoCounts.map(async callVideoCount => - retry(() => - model.doGenerate({ - prompt, - n: callVideoCount, - aspectRatio, - resolution, - duration, - fps, - seed, - image, - providerOptions: providerOptions ?? {}, - headers: headersWithUserAgent, - abortSignal, - } satisfies Experimental_VideoModelV3CallOptions), - ), - ), - ); - - // collect result videos, warnings, and response metadata - const videos: Array = []; - const warnings: Array = []; - const responses: Array = []; - const providerMetadata: SharedV3ProviderMetadata = {}; - - for (const result of results) { - for (const videoData of result.videos) { - switch (videoData.type) { - case 'url': { - const { data, mediaType: downloadedMediaType } = await downloadFn({ - url: new URL(videoData.url), - abortSignal, - }); - - // Filter out generic/unknown media types that should fall through to detection - const isUsableMediaType = (type: string | undefined): boolean => - !!type && type !== 'application/octet-stream'; - - const mediaType = - (isUsableMediaType(videoData.mediaType) && videoData.mediaType) || - (isUsableMediaType(downloadedMediaType) && downloadedMediaType) || - detectMediaType({ - data, - signatures: videoMediaTypeSignatures, - }) || - 'video/mp4'; - - videos.push( - new DefaultGeneratedFile({ - data, - mediaType, - }), - ); - break; - } - - case 'base64': { - videos.push( - new DefaultGeneratedFile({ - data: videoData.data, - mediaType: videoData.mediaType || 'video/mp4', - }), - ); - break; - } - - case 'binary': { - const mediaType = - videoData.mediaType || - detectMediaType({ - data: videoData.data, - signatures: videoMediaTypeSignatures, - }) || - 'video/mp4'; - - videos.push( - new DefaultGeneratedFile({ - data: videoData.data, - mediaType, - }), - ); - break; - } - } - } - - warnings.push(...result.warnings); - - responses.push({ - timestamp: result.response.timestamp, - modelId: result.response.modelId, - headers: result.response.headers, - providerMetadata: result.providerMetadata, - }); - - if (result.providerMetadata != null) { - for (const [providerName, metadata] of Object.entries( - result.providerMetadata, - )) { - const existingMetadata = providerMetadata[providerName]; - if (existingMetadata != null && typeof existingMetadata === 'object') { - providerMetadata[providerName] = { - ...existingMetadata, - ...metadata, - }; - - // Merge videos arrays if both exist - if ( - 'videos' in existingMetadata && - Array.isArray(existingMetadata.videos) && - 'videos' in metadata && - Array.isArray(metadata.videos) - ) { - (providerMetadata[providerName] as { videos: unknown[] }).videos = [ - ...existingMetadata.videos, - ...metadata.videos, - ]; - } - } else { - providerMetadata[providerName] = metadata; - } - } - } - } - - if (videos.length === 0) { - throw new NoVideoGeneratedError({ responses }); - } - - if (warnings.length > 0) { - logWarnings({ - warnings, - provider: model.provider, - model: model.modelId, - }); - } - - return { - video: videos[0], - videos, - warnings, - responses, - providerMetadata, - }; -} - -function normalizePrompt(promptArg: GenerateVideoPrompt): { - prompt: string | undefined; - image: Experimental_VideoModelV3File | undefined; -} { - if (typeof promptArg === 'string') { - return { - prompt: promptArg, - image: undefined, - }; - } - - let image: Experimental_VideoModelV3File | undefined; - - if (promptArg.image != null) { - const dataContent = promptArg.image; - - if (typeof dataContent === 'string') { - if ( - dataContent.startsWith('http://') || - dataContent.startsWith('https://') - ) { - image = { - type: 'url', - url: dataContent, - }; - } else if (dataContent.startsWith('data:')) { - const { mediaType, base64Content } = splitDataUrl(dataContent); - image = { - type: 'file', - mediaType: mediaType ?? 'image/png', - data: convertBase64ToUint8Array(base64Content ?? ''), - }; - } else { - const bytes = convertBase64ToUint8Array(dataContent); - const mediaType = - detectMediaType({ - data: bytes, - signatures: imageMediaTypeSignatures, - }) ?? 'image/png'; - - image = { - type: 'file', - mediaType, - data: bytes, - }; - } - } else if (dataContent instanceof Uint8Array) { - const mediaType = - detectMediaType({ - data: dataContent, - signatures: imageMediaTypeSignatures, - }) ?? 'image/png'; - - image = { - type: 'file', - mediaType, - data: dataContent, - }; - } - } - - return { - prompt: promptArg.text, - image, - }; -} - -async function invokeModelMaxVideosPerCall(model: Experimental_VideoModelV3) { - if (typeof model.maxVideosPerCall === 'function') { - return await model.maxVideosPerCall({ modelId: model.modelId }); - } - - return model.maxVideosPerCall; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-video/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-video/index.ts deleted file mode 100644 index cce8a7a1d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/generate-video/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type { GenerateVideoPrompt } from './generate-video'; -export { experimental_generateVideo } from './generate-video'; -export type { GenerateVideoResult } from './generate-video-result'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/global.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/global.ts deleted file mode 100644 index c641650d4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/global.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { ProviderV3 } from '@ai-sdk/provider'; -import { LogWarningsFunction } from './logger/log-warnings'; -import type { TelemetryIntegration } from './telemetry/telemetry-integration'; - -// add AI SDK default provider to the globalThis object -declare global { - /** - * The default provider to use for the AI SDK. - * String model ids are resolved to the default provider and model id. - * - * If not set, the default provider is the Vercel AI gateway provider. - * - * @see https://ai-sdk.dev/docs/ai-sdk-core/provider-management#global-provider-configuration - */ - var AI_SDK_DEFAULT_PROVIDER: ProviderV3 | undefined; - - /** - * The warning logger to use for the AI SDK. - * - * If not set, the default logger is the console.warn function. - * - * If set to false, no warnings are logged. - */ - var AI_SDK_LOG_WARNINGS: LogWarningsFunction | undefined | false; - - /** - * Globally registered telemetry integrations for the AI SDK. - * - * Integrations registered here receive lifecycle events (onStart, onStepStart, - * etc.) from every `generateText`, `streamText`, and similar call. - * - * Prefer using `registerTelemetryIntegration()` from `'ai'` instead of - * assigning this directly. - */ - var AI_SDK_TELEMETRY_INTEGRATIONS: TelemetryIntegration[] | undefined; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/index.ts deleted file mode 100644 index 20e194148..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -// re-exports: -export { createGateway, gateway, type GatewayModelId } from '@ai-sdk/gateway'; -export { - asSchema, - createIdGenerator, - dynamicTool, - generateId, - jsonSchema, - parseJsonEventStream, - tool, - zodSchema, - type FlexibleSchema, - type IdGenerator, - type InferSchema, - type InferToolInput, - type InferToolOutput, - type Schema, - type Tool, - type ToolApprovalRequest, - type ToolApprovalResponse, - type ToolCallOptions, - type ToolExecutionOptions, - type ToolExecuteFunction, -} from '@ai-sdk/provider-utils'; - -// directory exports -export * from './agent'; -export * from './embed'; -export * from './error'; -export * from './generate-image'; -export * from './generate-object'; -export * from './generate-speech'; -export * from './generate-text'; -export * from './generate-video'; -export * from './logger'; -export * from './middleware'; -export * from './prompt'; -export * from './registry'; -export * from './rerank'; -export * from './text-stream'; -export * from './transcribe'; -export * from './types'; -export * from './ui'; -export * from './ui-message-stream'; -export * from './util'; -export * from './telemetry'; - -// import globals -import './global'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/logger/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/logger/index.ts deleted file mode 100644 index 89d17951c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/logger/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @deprecated Use `LogWarningsFunction` instead. - */ -export type { LogWarningsFunction as Experimental_LogWarningsFunction } from './log-warnings'; - -export { type LogWarningsFunction } from './log-warnings'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/logger/log-warnings.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/logger/log-warnings.ts deleted file mode 100644 index 4b0d33adf..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/logger/log-warnings.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { Warning } from '../types'; - -/** - * A function for logging warnings. - * - * You can assign it to the `AI_SDK_LOG_WARNINGS` global variable to use it as the default warning logger. - * - * @example - * ```ts - * globalThis.AI_SDK_LOG_WARNINGS = (options) => { - * console.log('WARNINGS:', options.warnings, options.provider, options.model); - * }; - * ``` - */ -export type LogWarningsFunction = (options: { - /** - * The warnings returned by the model provider. - */ - warnings: Warning[]; - - /** - * The provider id used for the call. - */ - provider: string; - - /** - * The model id used for the call. - */ - model: string; -}) => void; - -/** - * Formats a warning object into a human-readable string with clear AI SDK branding. - * - * @param options - The options for formatting the warning. - * @param options.warning - The warning to format. - * @param options.provider - The provider id used for the call. - * @param options.model - The model id used for the call. - * @returns A formatted warning message string. - */ -function formatWarning({ - warning, - provider, - model, -}: { - warning: Warning; - provider: string; - model: string; -}): string { - const prefix = `AI SDK Warning (${provider} / ${model}):`; - - switch (warning.type) { - case 'unsupported': { - let message = `${prefix} The feature "${warning.feature}" is not supported.`; - if (warning.details) { - message += ` ${warning.details}`; - } - return message; - } - - case 'compatibility': { - let message = `${prefix} The feature "${warning.feature}" is used in a compatibility mode.`; - if (warning.details) { - message += ` ${warning.details}`; - } - return message; - } - - case 'other': { - return `${prefix} ${warning.message}`; - } - - default: { - // Fallback for any unknown warning types - return `${prefix} ${JSON.stringify(warning, null, 2)}`; - } - } -} - -export const FIRST_WARNING_INFO_MESSAGE = - 'AI SDK Warning System: To turn off warning logging, set the AI_SDK_LOG_WARNINGS global to false.'; - -let hasLoggedBefore = false; - -/** - * Logs warnings to the console or uses a custom logger if configured. - * - * The behavior can be customized via the `AI_SDK_LOG_WARNINGS` global variable: - * - If set to `false`, warnings are suppressed. - * - If set to a function, that function is called with the warnings. - * - Otherwise, warnings are logged to the console using `console.warn`. - * - * @param options - The options containing warnings and context. - * @param options.warnings - The warnings to log. - * @param options.provider - The provider id used for the call. - * @param options.model - The model id used for the call. - */ -export const logWarnings: LogWarningsFunction = options => { - // if the warnings array is empty, do nothing - if (options.warnings.length === 0) { - return; - } - - const logger = globalThis.AI_SDK_LOG_WARNINGS; - - // if the logger is set to false, do nothing - if (logger === false) { - return; - } - - // use the provided logger if it is a function - if (typeof logger === 'function') { - logger(options); - return; - } - - // display information note on first call - if (!hasLoggedBefore) { - hasLoggedBefore = true; - console.info(FIRST_WARNING_INFO_MESSAGE); - } - - // default behavior: log warnings to the console - for (const warning of options.warnings) { - console.warn( - formatWarning({ - warning, - provider: options.provider, - model: options.model, - }), - ); - } -}; - -/** - * Resets the internal logging state. Used for testing purposes. - */ -export const resetLogWarningsState = () => { - hasLoggedBefore = false; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/add-tool-input-examples-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/add-tool-input-examples-middleware.ts deleted file mode 100644 index 62cfdfdc9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/add-tool-input-examples-middleware.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { JSONObject, LanguageModelV3FunctionTool } from '@ai-sdk/provider'; -import { LanguageModelMiddleware } from '../types'; - -function defaultFormatExample(example: { input: JSONObject }): string { - return JSON.stringify(example.input); -} - -/** - * Middleware that appends input examples to tool descriptions. - * - * This is useful for providers that don't natively support the `inputExamples` - * property. The middleware serializes examples into the tool's description text. - * - * @param options - Configuration options for the middleware. - * @param options.prefix - A prefix to prepend before the examples. Default: 'Input Examples:' - * @param options.format - Optional custom formatter for each example. - * Receives the example object and its index. Default: JSON.stringify(example.input) - * @param options.remove - Whether to remove the inputExamples property - * after adding them to the description. Default: true - * - * @example - * ```ts - * import { wrapLanguageModel, addToolInputExamplesMiddleware } from 'ai'; - * - * const model = wrapLanguageModel({ - * model: yourModel, - * middleware: addToolInputExamplesMiddleware(), - * }); - * ``` - */ -export function addToolInputExamplesMiddleware({ - prefix = 'Input Examples:', - format = defaultFormatExample, - remove = true, -}: { - /** - * A prefix to prepend before the examples. - */ - prefix?: string; - - /** - * Optional custom formatter for each example. - * Receives the example object and its index. - * Default: JSON.stringify(example.input) - */ - format?: (example: { input: JSONObject }, index: number) => string; - - /** - * Whether to remove the inputExamples property after adding them to the description. - * Default: true - */ - remove?: boolean; -} = {}): LanguageModelMiddleware { - return { - specificationVersion: 'v3', - transformParams: async ({ params }) => { - if (!params.tools?.length) { - return params; - } - - const transformedTools = params.tools.map(tool => { - // Only transform function tools that have inputExamples - if (tool.type !== 'function' || !tool.inputExamples?.length) { - return tool; - } - - const formattedExamples = tool.inputExamples - .map((example, index) => format(example, index)) - .join('\n'); - - const examplesSection = `${prefix}\n${formattedExamples}`; - - const toolDescription = tool.description - ? `${tool.description}\n\n${examplesSection}` - : examplesSection; - - return { - ...tool, - description: toolDescription, - inputExamples: remove ? undefined : tool.inputExamples, - } satisfies LanguageModelV3FunctionTool; - }); - - return { - ...params, - tools: transformedTools, - }; - }, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/default-embedding-settings-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/default-embedding-settings-middleware.ts deleted file mode 100644 index 8dff8c7f1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/default-embedding-settings-middleware.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { EmbeddingModelV3CallOptions } from '@ai-sdk/provider'; -import { EmbeddingModelMiddleware } from '../types'; -import { mergeObjects } from '../util/merge-objects'; - -/** - * Applies default settings for an embedding model. - */ -export function defaultEmbeddingSettingsMiddleware({ - settings, -}: { - settings: Partial<{ - headers?: EmbeddingModelV3CallOptions['headers']; - providerOptions?: EmbeddingModelV3CallOptions['providerOptions']; - }>; -}): EmbeddingModelMiddleware { - return { - specificationVersion: 'v3', - transformParams: async ({ params }) => { - return mergeObjects(settings, params) as EmbeddingModelV3CallOptions; - }, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/default-settings-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/default-settings-middleware.ts deleted file mode 100644 index 980816dcf..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/default-settings-middleware.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { LanguageModelV3CallOptions } from '@ai-sdk/provider'; -import { LanguageModelMiddleware } from '../types'; -import { mergeObjects } from '../util/merge-objects'; - -/** - * Applies default settings for a language model. - */ -export function defaultSettingsMiddleware({ - settings, -}: { - settings: Partial<{ - maxOutputTokens?: LanguageModelV3CallOptions['maxOutputTokens']; - temperature?: LanguageModelV3CallOptions['temperature']; - stopSequences?: LanguageModelV3CallOptions['stopSequences']; - topP?: LanguageModelV3CallOptions['topP']; - topK?: LanguageModelV3CallOptions['topK']; - presencePenalty?: LanguageModelV3CallOptions['presencePenalty']; - frequencyPenalty?: LanguageModelV3CallOptions['frequencyPenalty']; - responseFormat?: LanguageModelV3CallOptions['responseFormat']; - seed?: LanguageModelV3CallOptions['seed']; - tools?: LanguageModelV3CallOptions['tools']; - toolChoice?: LanguageModelV3CallOptions['toolChoice']; - headers?: LanguageModelV3CallOptions['headers']; - providerOptions?: LanguageModelV3CallOptions['providerOptions']; - }>; -}): LanguageModelMiddleware { - return { - specificationVersion: 'v3', - transformParams: async ({ params }) => { - return mergeObjects(settings, params) as LanguageModelV3CallOptions; - }, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/extract-json-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/extract-json-middleware.ts deleted file mode 100644 index 75174a4d9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/extract-json-middleware.ts +++ /dev/null @@ -1,197 +0,0 @@ -import type { - LanguageModelV3Content, - LanguageModelV3StreamPart, -} from '@ai-sdk/provider'; -import { LanguageModelMiddleware } from '../types/language-model-middleware'; - -/** - * Default transform function that strips markdown code fences from text. - */ -function defaultTransform(text: string): string { - return text - .replace(/^```(?:json)?\s*\n?/, '') - .replace(/\n?```\s*$/, '') - .trim(); -} - -/** - * Middleware that extracts JSON from text content by stripping - * markdown code fences and other formatting. - * - * This is useful when using Output.object() with models that wrap - * JSON responses in markdown code blocks. - * - * @param options - Configuration options for the middleware. - * @param options.transform - Custom transform function. If provided, this will be - * used instead of the default markdown fence stripping. - */ -export function extractJsonMiddleware(options?: { - /** - * Custom transform function to apply to text content. - * Receives the raw text and should return the transformed text. - * If not provided, the default transform strips markdown code fences. - */ - transform?: (text: string) => string; -}): LanguageModelMiddleware { - const transform = options?.transform ?? defaultTransform; - const hasCustomTransform = options?.transform !== undefined; - - return { - specificationVersion: 'v3', - - wrapGenerate: async ({ doGenerate }) => { - const { content, ...rest } = await doGenerate(); - - const transformedContent: LanguageModelV3Content[] = []; - for (const part of content) { - if (part.type !== 'text') { - transformedContent.push(part); - continue; - } - - transformedContent.push({ - ...part, - text: transform(part.text), - }); - } - - return { content: transformedContent, ...rest }; - }, - wrapStream: async ({ doStream }) => { - const { stream, ...rest } = await doStream(); - - const textBlocks: Record< - string, - { - startEvent: LanguageModelV3StreamPart; - phase: 'prefix' | 'streaming' | 'buffering'; - buffer: string; - prefixStripped: boolean; - } - > = {}; - - const SUFFIX_BUFFER_SIZE = 12; - - return { - stream: stream.pipeThrough( - new TransformStream< - LanguageModelV3StreamPart, - LanguageModelV3StreamPart - >({ - transform: (chunk, controller) => { - if (chunk.type === 'text-start') { - textBlocks[chunk.id] = { - startEvent: chunk, - // Custom transforms need to buffer all content - phase: hasCustomTransform ? 'buffering' : 'prefix', - buffer: '', - prefixStripped: false, - }; - return; - } - - if (chunk.type === 'text-delta') { - const block = textBlocks[chunk.id]; - if (!block) { - controller.enqueue(chunk); - return; - } - - block.buffer += chunk.delta; - - // Custom transform: buffer everything, transform at end - if (block.phase === 'buffering') { - return; - } - - if (block.phase === 'prefix') { - // Check if we can determine prefix status - if ( - block.buffer.length > 0 && - !block.buffer.startsWith('`') - ) { - block.phase = 'streaming'; - controller.enqueue(block.startEvent); - } else if (block.buffer.startsWith('```')) { - // Only strip prefix when we have a newline (fence is complete) - if (block.buffer.includes('\n')) { - const prefixMatch = - block.buffer.match(/^```(?:json)?\s*\n/); - if (prefixMatch) { - block.buffer = block.buffer.slice( - prefixMatch[0].length, - ); - block.prefixStripped = true; - block.phase = 'streaming'; - controller.enqueue(block.startEvent); - } else { - // Has newline but doesn't match fence pattern - block.phase = 'streaming'; - controller.enqueue(block.startEvent); - } - } - // else keep buffering until we see a newline - } else if ( - block.buffer.length >= 3 && - !block.buffer.startsWith('```') - ) { - block.phase = 'streaming'; - controller.enqueue(block.startEvent); - } - } - - // Stream content - if ( - block.phase === 'streaming' && - block.buffer.length > SUFFIX_BUFFER_SIZE - ) { - const toStream = block.buffer.slice(0, -SUFFIX_BUFFER_SIZE); - block.buffer = block.buffer.slice(-SUFFIX_BUFFER_SIZE); - controller.enqueue({ - type: 'text-delta', - id: chunk.id, - delta: toStream, - }); - } - return; - } - - if (chunk.type === 'text-end') { - const block = textBlocks[chunk.id]; - if (block) { - if (block.phase === 'prefix' || block.phase === 'buffering') { - controller.enqueue(block.startEvent); - } - - let remaining = block.buffer; - if (block.phase === 'buffering') { - remaining = transform(remaining); - } else if (block.prefixStripped) { - // strip suffix since prefix already handled - remaining = remaining.replace(/\n?```\s*$/, '').trimEnd(); - } else { - // Apply full transform (handles both prefix and suffix) - remaining = transform(remaining); - } - - if (remaining.length > 0) { - controller.enqueue({ - type: 'text-delta', - id: chunk.id, - delta: remaining, - }); - } - controller.enqueue(chunk); - delete textBlocks[chunk.id]; - return; - } - } - controller.enqueue(chunk); - }, - }), - ), - ...rest, - }; - }, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/extract-reasoning-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/extract-reasoning-middleware.ts deleted file mode 100644 index ac7f918e8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/extract-reasoning-middleware.ts +++ /dev/null @@ -1,249 +0,0 @@ -import type { - LanguageModelV3Content, - LanguageModelV3StreamPart, -} from '@ai-sdk/provider'; -import { LanguageModelMiddleware } from '../types/language-model-middleware'; -import { getPotentialStartIndex } from '../util/get-potential-start-index'; - -/** - * Extracts an XML-tagged reasoning section from the generated text and exposes it - * as a `reasoning` property on the result. - * - * @param tagName - The name of the XML tag to extract reasoning from. - * @param separator - The separator to use between reasoning and text sections. - * @param startWithReasoning - Whether to start with reasoning tokens. - */ -export function extractReasoningMiddleware({ - tagName, - separator = '\n', - startWithReasoning = false, -}: { - tagName: string; - separator?: string; - startWithReasoning?: boolean; -}): LanguageModelMiddleware { - const openingTag = `<${tagName}>`; - const closingTag = `<\/${tagName}>`; - - return { - specificationVersion: 'v3', - wrapGenerate: async ({ doGenerate }) => { - const { content, ...rest } = await doGenerate(); - - const transformedContent: LanguageModelV3Content[] = []; - for (const part of content) { - if (part.type !== 'text') { - transformedContent.push(part); - continue; - } - - const text = startWithReasoning ? openingTag + part.text : part.text; - - const regexp = new RegExp(`${openingTag}(.*?)${closingTag}`, 'gs'); - const matches = Array.from(text.matchAll(regexp)); - - if (!matches.length) { - transformedContent.push(part); - continue; - } - - const reasoningText = matches.map(match => match[1]).join(separator); - - let textWithoutReasoning = text; - for (let i = matches.length - 1; i >= 0; i--) { - const match = matches[i]; - - const beforeMatch = textWithoutReasoning.slice(0, match.index); - const afterMatch = textWithoutReasoning.slice( - match.index! + match[0].length, - ); - - textWithoutReasoning = - beforeMatch + - (beforeMatch.length > 0 && afterMatch.length > 0 ? separator : '') + - afterMatch; - } - - transformedContent.push({ - type: 'reasoning', - text: reasoningText, - }); - - transformedContent.push({ - type: 'text', - text: textWithoutReasoning, - }); - } - - return { content: transformedContent, ...rest }; - }, - - wrapStream: async ({ doStream }) => { - const { stream, ...rest } = await doStream(); - - const reasoningExtractions: Record< - string, - { - isFirstReasoning: boolean; - isFirstText: boolean; - afterSwitch: boolean; - isReasoning: boolean; - buffer: string; - idCounter: number; - textId: string; - } - > = {}; - - let delayedTextStart: LanguageModelV3StreamPart | undefined; - - return { - stream: stream.pipeThrough( - new TransformStream< - LanguageModelV3StreamPart, - LanguageModelV3StreamPart - >({ - transform: (chunk, controller) => { - // do not send `text-start` before `reasoning-start` - // https://github.com/vercel/ai/issues/7774 - if (chunk.type === 'text-start') { - delayedTextStart = chunk; - return; - } - - if (chunk.type === 'text-end' && delayedTextStart) { - controller.enqueue(delayedTextStart); - delayedTextStart = undefined; - } - - if (chunk.type !== 'text-delta') { - controller.enqueue(chunk); - return; - } - - if (reasoningExtractions[chunk.id] == null) { - reasoningExtractions[chunk.id] = { - isFirstReasoning: true, - isFirstText: true, - afterSwitch: false, - isReasoning: startWithReasoning, - buffer: '', - idCounter: 0, - textId: chunk.id, - }; - } - - const activeExtraction = reasoningExtractions[chunk.id]; - - activeExtraction.buffer += chunk.delta; - - function publish(text: string) { - if (text.length > 0) { - const prefix = - activeExtraction.afterSwitch && - (activeExtraction.isReasoning - ? !activeExtraction.isFirstReasoning - : !activeExtraction.isFirstText) - ? separator - : ''; - - if ( - activeExtraction.isReasoning && - (activeExtraction.afterSwitch || - activeExtraction.isFirstReasoning) - ) { - controller.enqueue({ - type: 'reasoning-start', - id: `reasoning-${activeExtraction.idCounter}`, - }); - } - - if (activeExtraction.isReasoning) { - controller.enqueue({ - type: 'reasoning-delta', - delta: prefix + text, - id: `reasoning-${activeExtraction.idCounter}`, - }); - } else { - if (delayedTextStart) { - controller.enqueue(delayedTextStart); - delayedTextStart = undefined; - } - controller.enqueue({ - type: 'text-delta', - delta: prefix + text, - id: activeExtraction.textId, - }); - } - activeExtraction.afterSwitch = false; - - if (activeExtraction.isReasoning) { - activeExtraction.isFirstReasoning = false; - } else { - activeExtraction.isFirstText = false; - } - } - } - - do { - const nextTag = activeExtraction.isReasoning - ? closingTag - : openingTag; - - const startIndex = getPotentialStartIndex( - activeExtraction.buffer, - nextTag, - ); - - // no opening or closing tag found, publish the buffer - if (startIndex == null) { - publish(activeExtraction.buffer); - activeExtraction.buffer = ''; - break; - } - - // publish text before the tag - publish(activeExtraction.buffer.slice(0, startIndex)); - - const foundFullMatch = - startIndex + nextTag.length <= activeExtraction.buffer.length; - - if (foundFullMatch) { - activeExtraction.buffer = activeExtraction.buffer.slice( - startIndex + nextTag.length, - ); - - if (activeExtraction.isReasoning) { - // Emit reasoning-start for empty reasoning blocks (no delta was published). - // This handles both cases: - // - startWithReasoning=false: (afterSwitch=true) - // - startWithReasoning=true: immediate (afterSwitch=false) - if (activeExtraction.isFirstReasoning) { - controller.enqueue({ - type: 'reasoning-start', - id: `reasoning-${activeExtraction.idCounter}`, - }); - } - - // reasoning part finished: - controller.enqueue({ - type: 'reasoning-end', - id: `reasoning-${activeExtraction.idCounter++}`, - }); - } - - activeExtraction.isReasoning = !activeExtraction.isReasoning; - activeExtraction.afterSwitch = true; - } else { - activeExtraction.buffer = - activeExtraction.buffer.slice(startIndex); - break; - } - } while (true); - }, - }), - ), - ...rest, - }; - }, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/index.ts deleted file mode 100644 index 4d349a8b4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -export { defaultEmbeddingSettingsMiddleware } from './default-embedding-settings-middleware'; -export { defaultSettingsMiddleware } from './default-settings-middleware'; -export { extractJsonMiddleware } from './extract-json-middleware'; -export { extractReasoningMiddleware } from './extract-reasoning-middleware'; -export { simulateStreamingMiddleware } from './simulate-streaming-middleware'; -export { addToolInputExamplesMiddleware } from './add-tool-input-examples-middleware'; -export { wrapLanguageModel } from './wrap-language-model'; -export { wrapEmbeddingModel } from './wrap-embedding-model'; -export { wrapImageModel } from './wrap-image-model'; -export { wrapProvider } from './wrap-provider'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/simulate-streaming-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/simulate-streaming-middleware.ts deleted file mode 100644 index d06cdadbe..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/simulate-streaming-middleware.ts +++ /dev/null @@ -1,79 +0,0 @@ -import type { LanguageModelV3StreamPart } from '@ai-sdk/provider'; -import { LanguageModelMiddleware } from '../types'; - -/** - * Simulates streaming chunks with the response from a generate call. - */ -export function simulateStreamingMiddleware(): LanguageModelMiddleware { - return { - specificationVersion: 'v3', - wrapStream: async ({ doGenerate }) => { - const result = await doGenerate(); - - let id = 0; - - const simulatedStream = new ReadableStream({ - start(controller) { - controller.enqueue({ - type: 'stream-start', - warnings: result.warnings, - }); - - controller.enqueue({ type: 'response-metadata', ...result.response }); - - for (const part of result.content) { - switch (part.type) { - case 'text': { - if (part.text.length > 0) { - controller.enqueue({ type: 'text-start', id: String(id) }); - controller.enqueue({ - type: 'text-delta', - id: String(id), - delta: part.text, - }); - controller.enqueue({ type: 'text-end', id: String(id) }); - id++; - } - break; - } - case 'reasoning': { - controller.enqueue({ - type: 'reasoning-start', - id: String(id), - providerMetadata: part.providerMetadata, - }); - controller.enqueue({ - type: 'reasoning-delta', - id: String(id), - delta: part.text, - }); - controller.enqueue({ type: 'reasoning-end', id: String(id) }); - id++; - break; - } - default: { - controller.enqueue(part); - break; - } - } - } - - controller.enqueue({ - type: 'finish', - finishReason: result.finishReason, - usage: result.usage, - providerMetadata: result.providerMetadata, - }); - - controller.close(); - }, - }); - - return { - stream: simulatedStream, - request: result.request, - response: result.response, - }; - }, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/wrap-embedding-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/wrap-embedding-model.ts deleted file mode 100644 index c241a58b0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/wrap-embedding-model.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { - EmbeddingModelV3, - EmbeddingModelV3CallOptions, -} from '@ai-sdk/provider'; -import { EmbeddingModelMiddleware } from '../types'; -import { asArray } from '../util/as-array'; - -/** - * Wraps an EmbeddingModelV3 instance with middleware functionality. - * This function allows you to apply middleware to transform parameters, - * wrap embed operations of an embedding model. - * - * @param options - Configuration options for wrapping the embedding model. - * @param options.model - The original EmbeddingModelV3 instance to be wrapped. - * @param options.middleware - The middleware to be applied to the embedding model. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model. - * @param options.modelId - Optional custom model ID to override the original model's ID. - * @param options.providerId - Optional custom provider ID to override the original model's provider ID. - * @returns A new EmbeddingModelV3 instance with middleware applied. - */ -export const wrapEmbeddingModel = ({ - model, - middleware: middlewareArg, - modelId, - providerId, -}: { - model: EmbeddingModelV3; - middleware: EmbeddingModelMiddleware | EmbeddingModelMiddleware[]; - modelId?: string; - providerId?: string; -}): EmbeddingModelV3 => { - return [...asArray(middlewareArg)] - .reverse() - .reduce((wrappedModel, middleware) => { - return doWrap({ model: wrappedModel, middleware, modelId, providerId }); - }, model); -}; - -const doWrap = ({ - model, - middleware: { - transformParams, - wrapEmbed, - overrideProvider, - overrideModelId, - overrideMaxEmbeddingsPerCall, - overrideSupportsParallelCalls, - }, - modelId, - providerId, -}: { - model: EmbeddingModelV3; - middleware: EmbeddingModelMiddleware; - modelId?: string; - providerId?: string; -}): EmbeddingModelV3 => { - async function doTransform({ - params, - }: { - params: EmbeddingModelV3CallOptions; - }) { - return transformParams ? await transformParams({ params, model }) : params; - } - - return { - specificationVersion: 'v3', - provider: providerId ?? overrideProvider?.({ model }) ?? model.provider, - modelId: modelId ?? overrideModelId?.({ model }) ?? model.modelId, - maxEmbeddingsPerCall: - overrideMaxEmbeddingsPerCall?.({ model }) ?? model.maxEmbeddingsPerCall, - supportsParallelCalls: - overrideSupportsParallelCalls?.({ model }) ?? model.supportsParallelCalls, - async doEmbed( - params: EmbeddingModelV3CallOptions, - ): Promise>> { - const transformedParams = await doTransform({ params }); - const doEmbed = async () => model.doEmbed(transformedParams); - return wrapEmbed - ? wrapEmbed({ - doEmbed, - params: transformedParams, - model, - }) - : doEmbed(); - }, - }; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/wrap-image-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/wrap-image-model.ts deleted file mode 100644 index 8877372b6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/wrap-image-model.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { ImageModelV3, ImageModelV3CallOptions } from '@ai-sdk/provider'; -import { ImageModelMiddleware } from '../types'; -import { asArray } from '../util/as-array'; - -/** - * Wraps an ImageModelV3 instance with middleware functionality. - * This function allows you to apply middleware to transform parameters - * and wrap generate operations of an image model. - * - * @param options - Configuration options for wrapping the image model. - * @param options.model - The original ImageModelV3 instance to be wrapped. - * @param options.middleware - The middleware to be applied to the image model. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model. - * @param options.modelId - Optional custom model ID to override the original model's ID. - * @param options.providerId - Optional custom provider ID to override the original model's provider ID. - * @returns A new ImageModelV3 instance with middleware applied. - */ -export const wrapImageModel = ({ - model, - middleware: middlewareArg, - modelId, - providerId, -}: { - model: ImageModelV3; - middleware: ImageModelMiddleware | ImageModelMiddleware[]; - modelId?: string; - providerId?: string; -}): ImageModelV3 => { - return [...asArray(middlewareArg)] - .reverse() - .reduce((wrappedModel, middleware) => { - return doWrap({ model: wrappedModel, middleware, modelId, providerId }); - }, model); -}; - -const doWrap = ({ - model, - middleware: { - transformParams, - wrapGenerate, - overrideProvider, - overrideModelId, - overrideMaxImagesPerCall, - }, - modelId, - providerId, -}: { - model: ImageModelV3; - middleware: ImageModelMiddleware; - modelId?: string; - providerId?: string; -}): ImageModelV3 => { - async function doTransform({ params }: { params: ImageModelV3CallOptions }) { - return transformParams ? await transformParams({ params, model }) : params; - } - - const maxImagesPerCallRaw = - overrideMaxImagesPerCall?.({ model }) ?? model.maxImagesPerCall; - - // Ensure provider implementations that rely on `this` inside `maxImagesPerCall` - // keep working after the value is copied onto the wrapper object. - const maxImagesPerCall = - maxImagesPerCallRaw instanceof Function - ? maxImagesPerCallRaw.bind(model) - : maxImagesPerCallRaw; - - return { - specificationVersion: 'v3', - provider: providerId ?? overrideProvider?.({ model }) ?? model.provider, - modelId: modelId ?? overrideModelId?.({ model }) ?? model.modelId, - maxImagesPerCall, - async doGenerate( - params: ImageModelV3CallOptions, - ): Promise>> { - const transformedParams = await doTransform({ params }); - const doGenerate = async () => model.doGenerate(transformedParams); - return wrapGenerate - ? wrapGenerate({ - doGenerate, - params: transformedParams, - model, - }) - : doGenerate(); - }, - }; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/wrap-language-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/wrap-language-model.ts deleted file mode 100644 index ea6f88819..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/wrap-language-model.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { - LanguageModelV3, - LanguageModelV3CallOptions, - LanguageModelV3GenerateResult, - LanguageModelV3StreamResult, -} from '@ai-sdk/provider'; -import { LanguageModelMiddleware } from '../types'; -import { asArray } from '../util/as-array'; - -/** - * Wraps a LanguageModelV3 instance with middleware functionality. - * This function allows you to apply middleware to transform parameters, - * wrap generate operations, and wrap stream operations of a language model. - * - * @param options - Configuration options for wrapping the language model. - * @param options.model - The original LanguageModelV3 instance to be wrapped. - * @param options.middleware - The middleware to be applied to the language model. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model. - * @param options.modelId - Optional custom model ID to override the original model's ID. - * @param options.providerId - Optional custom provider ID to override the original model's provider ID. - * @returns A new LanguageModelV3 instance with middleware applied. - */ -export const wrapLanguageModel = ({ - model, - middleware: middlewareArg, - modelId, - providerId, -}: { - model: LanguageModelV3; - middleware: LanguageModelMiddleware | LanguageModelMiddleware[]; - modelId?: string; - providerId?: string; -}): LanguageModelV3 => { - return [...asArray(middlewareArg)] - .reverse() - .reduce((wrappedModel, middleware) => { - return doWrap({ model: wrappedModel, middleware, modelId, providerId }); - }, model); -}; - -const doWrap = ({ - model, - middleware: { - transformParams, - wrapGenerate, - wrapStream, - overrideProvider, - overrideModelId, - overrideSupportedUrls, - }, - modelId, - providerId, -}: { - model: LanguageModelV3; - middleware: LanguageModelMiddleware; - modelId?: string; - providerId?: string; -}): LanguageModelV3 => { - async function doTransform({ - params, - type, - }: { - params: LanguageModelV3CallOptions; - type: 'generate' | 'stream'; - }) { - return transformParams - ? await transformParams({ params, type, model }) - : params; - } - - return { - specificationVersion: 'v3', - - provider: providerId ?? overrideProvider?.({ model }) ?? model.provider, - modelId: modelId ?? overrideModelId?.({ model }) ?? model.modelId, - supportedUrls: overrideSupportedUrls?.({ model }) ?? model.supportedUrls, - - async doGenerate( - params: LanguageModelV3CallOptions, - ): Promise { - const transformedParams = await doTransform({ params, type: 'generate' }); - const doGenerate = async () => model.doGenerate(transformedParams); - const doStream = async () => model.doStream(transformedParams); - return wrapGenerate - ? wrapGenerate({ - doGenerate, - doStream, - params: transformedParams, - model, - }) - : doGenerate(); - }, - - async doStream( - params: LanguageModelV3CallOptions, - ): Promise { - const transformedParams = await doTransform({ params, type: 'stream' }); - const doGenerate = async () => model.doGenerate(transformedParams); - const doStream = async () => model.doStream(transformedParams); - return wrapStream - ? wrapStream({ doGenerate, doStream, params: transformedParams, model }) - : doStream(); - }, - }; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/wrap-provider.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/wrap-provider.ts deleted file mode 100644 index ff59f933a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/middleware/wrap-provider.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { ProviderV2, ProviderV3 } from '@ai-sdk/provider'; -import { ImageModelMiddleware } from '../types/image-model-middleware'; -import { LanguageModelMiddleware } from '../types/language-model-middleware'; -import { wrapImageModel } from './wrap-image-model'; -import { wrapLanguageModel } from './wrap-language-model'; -import { asProviderV3 } from '../model/as-provider-v3'; - -/** - * Wraps a ProviderV3 instance with middleware functionality. - * This function allows you to apply middleware to all language models - * from the provider, enabling you to transform parameters, wrap generate - * operations, and wrap stream operations for every language model. - * - * @param options - Configuration options for wrapping the provider. - * @param options.provider - The original ProviderV3 instance to be wrapped. - * @param options.languageModelMiddleware - The middleware to be applied to all language models from the provider. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model. - * @param options.imageModelMiddleware - Optional middleware to be applied to all image models from the provider. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model. - * @returns A new ProviderV3 instance with middleware applied to all language models. - */ -export function wrapProvider({ - provider, - languageModelMiddleware, - imageModelMiddleware, -}: { - provider: ProviderV3 | ProviderV2; - languageModelMiddleware: LanguageModelMiddleware | LanguageModelMiddleware[]; - imageModelMiddleware?: ImageModelMiddleware | ImageModelMiddleware[]; -}): ProviderV3 { - const providerV3 = asProviderV3(provider); - return { - specificationVersion: 'v3', - languageModel: (modelId: string) => - wrapLanguageModel({ - model: providerV3.languageModel(modelId), - middleware: languageModelMiddleware, - }), - embeddingModel: providerV3.embeddingModel, - imageModel: (modelId: string) => { - let model = providerV3.imageModel(modelId); - - if (imageModelMiddleware != null) { - model = wrapImageModel({ model, middleware: imageModelMiddleware }); - } - - return model; - }, - transcriptionModel: providerV3.transcriptionModel, - speechModel: providerV3.speechModel, - rerankingModel: providerV3.rerankingModel, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-embedding-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-embedding-model-v3.ts deleted file mode 100644 index 890779aaa..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-embedding-model-v3.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { EmbeddingModelV2, EmbeddingModelV3 } from '@ai-sdk/provider'; -import { logV2CompatibilityWarning } from '../util/log-v2-compatibility-warning'; - -export function asEmbeddingModelV3( - model: EmbeddingModelV2 | EmbeddingModelV3, -): EmbeddingModelV3 { - if (model.specificationVersion === 'v3') { - return model; - } - - logV2CompatibilityWarning({ - provider: model.provider, - modelId: model.modelId, - }); - - // TODO this could break, we need to properly map v2 to v3 - // and support all relevant v3 properties: - return new Proxy(model, { - get(target, prop: keyof EmbeddingModelV2) { - if (prop === 'specificationVersion') return 'v3'; - return target[prop]; - }, - }) as unknown as EmbeddingModelV3; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-image-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-image-model-v3.ts deleted file mode 100644 index a39d75f6e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-image-model-v3.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ImageModelV2, ImageModelV3 } from '@ai-sdk/provider'; -import { logV2CompatibilityWarning } from '../util/log-v2-compatibility-warning'; - -export function asImageModelV3( - model: ImageModelV2 | ImageModelV3, -): ImageModelV3 { - if (model.specificationVersion === 'v3') { - return model; - } - - logV2CompatibilityWarning({ - provider: model.provider, - modelId: model.modelId, - }); - - // TODO this could break, we need to properly map v2 to v3 - // and support all relevant v3 properties: - return new Proxy(model, { - get(target, prop: keyof ImageModelV2) { - if (prop === 'specificationVersion') return 'v3'; - return target[prop]; - }, - }) as unknown as ImageModelV3; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-language-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-language-model-v3.ts deleted file mode 100644 index 017c4ce22..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-language-model-v3.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { - LanguageModelV2, - LanguageModelV2FinishReason, - LanguageModelV2StreamPart, - LanguageModelV2Usage, - LanguageModelV3, - LanguageModelV3FinishReason, - LanguageModelV3StreamPart, - LanguageModelV3Usage, -} from '@ai-sdk/provider'; -import { logV2CompatibilityWarning } from '../util/log-v2-compatibility-warning'; - -export function asLanguageModelV3( - model: LanguageModelV2 | LanguageModelV3, -): LanguageModelV3 { - if (model.specificationVersion === 'v3') { - return model; - } - - logV2CompatibilityWarning({ - provider: model.provider, - modelId: model.modelId, - }); - - // TODO this could break, we need to properly map v2 to v3 - // and support all relevant v3 properties: - return new Proxy(model, { - get(target, prop: keyof LanguageModelV2) { - switch (prop) { - case 'specificationVersion': - return 'v3'; - case 'doGenerate': - return async (...args: Parameters) => { - const result = await target.doGenerate(...args); - return { - ...result, - finishReason: convertV2FinishReasonToV3(result.finishReason), - usage: convertV2UsageToV3(result.usage), - }; - }; - case 'doStream': - return async (...args: Parameters) => { - const result = await target.doStream(...args); - return { - ...result, - stream: convertV2StreamToV3(result.stream), - }; - }; - default: - return target[prop]; - } - }, - }) as unknown as LanguageModelV3; -} - -function convertV2StreamToV3( - stream: ReadableStream, -): ReadableStream { - return stream.pipeThrough( - new TransformStream({ - transform(chunk, controller) { - switch (chunk.type) { - case 'finish': - controller.enqueue({ - ...chunk, - finishReason: convertV2FinishReasonToV3(chunk.finishReason), - usage: convertV2UsageToV3(chunk.usage), - }); - break; - default: - // TODO: AI SDK 6 - no casting (stream parts need to be mapped) - controller.enqueue(chunk as LanguageModelV3StreamPart); - break; - } - }, - }), - ); -} - -function convertV2FinishReasonToV3( - finishReason: LanguageModelV2FinishReason, -): LanguageModelV3FinishReason { - return { - unified: finishReason === 'unknown' ? 'other' : finishReason, - raw: undefined, - }; -} - -function convertV2UsageToV3(usage: LanguageModelV2Usage): LanguageModelV3Usage { - return { - inputTokens: { - total: usage.inputTokens, - noCache: undefined, - cacheRead: usage.cachedInputTokens, - cacheWrite: undefined, - }, - outputTokens: { - total: usage.outputTokens, - text: undefined, - reasoning: usage.reasoningTokens, - }, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-provider-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-provider-v3.ts deleted file mode 100644 index a09402b68..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-provider-v3.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { ProviderV2, ProviderV3 } from '@ai-sdk/provider'; -import { asEmbeddingModelV3 } from './as-embedding-model-v3'; -import { asImageModelV3 } from './as-image-model-v3'; -import { asLanguageModelV3 } from './as-language-model-v3'; -import { asTranscriptionModelV3 } from './as-transcription-model-v3'; -import { asSpeechModelV3 } from './as-speech-model-v3'; - -export function asProviderV3(provider: ProviderV2 | ProviderV3): ProviderV3 { - if ( - 'specificationVersion' in provider && - provider.specificationVersion === 'v3' - ) { - return provider; - } - - // v3 providers have already been returned - const v2Provider: ProviderV2 = provider as ProviderV2; - - return { - specificationVersion: 'v3', - languageModel: (modelId: string) => - asLanguageModelV3(v2Provider.languageModel(modelId)), - embeddingModel: (modelId: string) => - asEmbeddingModelV3(v2Provider.textEmbeddingModel(modelId)), - imageModel: (modelId: string) => - asImageModelV3(v2Provider.imageModel(modelId)), - transcriptionModel: v2Provider.transcriptionModel - ? (modelId: string) => - asTranscriptionModelV3(v2Provider.transcriptionModel!(modelId)) - : undefined, - speechModel: v2Provider.speechModel - ? (modelId: string) => asSpeechModelV3(v2Provider.speechModel!(modelId)) - : undefined, - rerankingModel: undefined, // v2 providers don't have reranking models - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-speech-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-speech-model-v3.ts deleted file mode 100644 index 1ab4e0d00..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-speech-model-v3.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { SpeechModelV2, SpeechModelV3 } from '@ai-sdk/provider'; -import { logV2CompatibilityWarning } from '../util/log-v2-compatibility-warning'; - -export function asSpeechModelV3( - model: SpeechModelV3 | SpeechModelV2, -): SpeechModelV3 { - if (model.specificationVersion === 'v3') { - return model; - } - - logV2CompatibilityWarning({ - provider: model.provider, - modelId: model.modelId, - }); - - // TODO this could break, we need to properly map v2 to v3 - // and support all relevant v3 properties: - return new Proxy(model, { - get(target, prop: keyof SpeechModelV2) { - if (prop === 'specificationVersion') return 'v3'; - return target[prop]; - }, - }) as unknown as SpeechModelV3; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-transcription-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-transcription-model-v3.ts deleted file mode 100644 index d96ab0e37..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/as-transcription-model-v3.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TranscriptionModelV2, TranscriptionModelV3 } from '@ai-sdk/provider'; -import { logV2CompatibilityWarning } from '../util/log-v2-compatibility-warning'; - -export function asTranscriptionModelV3( - model: TranscriptionModelV3 | TranscriptionModelV2, -): TranscriptionModelV3 { - if (model.specificationVersion === 'v3') { - return model; - } - - logV2CompatibilityWarning({ - provider: model.provider, - modelId: model.modelId, - }); - - // TODO this could break, we need to properly map v2 to v3 - // and support all relevant v3 properties: - return new Proxy(model, { - get(target, prop: keyof TranscriptionModelV2) { - if (prop === 'specificationVersion') return 'v3'; - return target[prop]; - }, - }) as unknown as TranscriptionModelV3; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/resolve-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/resolve-model.ts deleted file mode 100644 index 0514b7d8a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/model/resolve-model.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { gateway } from '@ai-sdk/gateway'; -import { - EmbeddingModelV3, - Experimental_VideoModelV3, - ImageModelV3, - LanguageModelV3, - ProviderV3, - SpeechModelV3, - TranscriptionModelV3, -} from '@ai-sdk/provider'; -import { UnsupportedModelVersionError } from '../error'; -import { EmbeddingModel } from '../types/embedding-model'; -import { LanguageModel } from '../types/language-model'; -import { SpeechModel } from '../types/speech-model'; -import { TranscriptionModel } from '../types/transcription-model'; -import { asEmbeddingModelV3 } from './as-embedding-model-v3'; -import { asImageModelV3 } from './as-image-model-v3'; -import { asLanguageModelV3 } from './as-language-model-v3'; -import { asSpeechModelV3 } from './as-speech-model-v3'; -import { asTranscriptionModelV3 } from './as-transcription-model-v3'; -import { ImageModel } from '../types/image-model'; -import { VideoModel } from '../types/video-model'; - -export function resolveLanguageModel(model: LanguageModel): LanguageModelV3 { - if (typeof model !== 'string') { - if ( - model.specificationVersion !== 'v3' && - model.specificationVersion !== 'v2' - ) { - const unsupportedModel: any = model; - throw new UnsupportedModelVersionError({ - version: unsupportedModel.specificationVersion, - provider: unsupportedModel.provider, - modelId: unsupportedModel.modelId, - }); - } - - return asLanguageModelV3(model); - } - - return getGlobalProvider().languageModel(model); -} - -export function resolveEmbeddingModel(model: EmbeddingModel): EmbeddingModelV3 { - if (typeof model !== 'string') { - if ( - model.specificationVersion !== 'v3' && - model.specificationVersion !== 'v2' - ) { - const unsupportedModel: any = model; - throw new UnsupportedModelVersionError({ - version: unsupportedModel.specificationVersion, - provider: unsupportedModel.provider, - modelId: unsupportedModel.modelId, - }); - } - - return asEmbeddingModelV3(model); - } - - return getGlobalProvider().embeddingModel(model); -} - -export function resolveTranscriptionModel( - model: TranscriptionModel, -): TranscriptionModelV3 | undefined { - if (typeof model !== 'string') { - if ( - model.specificationVersion !== 'v3' && - model.specificationVersion !== 'v2' - ) { - const unsupportedModel: any = model; - throw new UnsupportedModelVersionError({ - version: unsupportedModel.specificationVersion, - provider: unsupportedModel.provider, - modelId: unsupportedModel.modelId, - }); - } - return asTranscriptionModelV3(model); - } - - return getGlobalProvider().transcriptionModel?.(model); -} - -export function resolveSpeechModel( - model: SpeechModel, -): SpeechModelV3 | undefined { - if (typeof model !== 'string') { - if ( - model.specificationVersion !== 'v3' && - model.specificationVersion !== 'v2' - ) { - const unsupportedModel: any = model; - throw new UnsupportedModelVersionError({ - version: unsupportedModel.specificationVersion, - provider: unsupportedModel.provider, - modelId: unsupportedModel.modelId, - }); - } - return asSpeechModelV3(model); - } - - return getGlobalProvider().speechModel?.(model); -} - -export function resolveImageModel(model: ImageModel): ImageModelV3 { - if (typeof model !== 'string') { - if ( - model.specificationVersion !== 'v3' && - model.specificationVersion !== 'v2' - ) { - const unsupportedModel: any = model; - throw new UnsupportedModelVersionError({ - version: unsupportedModel.specificationVersion, - provider: unsupportedModel.provider, - modelId: unsupportedModel.modelId, - }); - } - - return asImageModelV3(model); - } - - return getGlobalProvider().imageModel(model); -} - -export function resolveVideoModel( - model: VideoModel, -): Experimental_VideoModelV3 { - if (typeof model === 'string') { - const provider = getGlobalProvider(); - // TODO AI SDK v7 - // @ts-expect-error - videoModel support is experimental - const videoModel = provider.videoModel; - - if (!videoModel) { - throw new Error( - 'The default provider does not support video models. ' + - 'Please use a Experimental_VideoModelV3 object from a provider (e.g., vertex.video("model-id")).', - ); - } - - return videoModel(model); - } - - if (model.specificationVersion !== 'v3') { - const unsupportedModel: any = model; - throw new UnsupportedModelVersionError({ - version: unsupportedModel.specificationVersion, - provider: unsupportedModel.provider, - modelId: unsupportedModel.modelId, - }); - } - - return model; -} - -function getGlobalProvider(): ProviderV3 { - return globalThis.AI_SDK_DEFAULT_PROVIDER ?? gateway; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/call-settings.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/call-settings.ts deleted file mode 100644 index fe9b29c60..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/call-settings.ts +++ /dev/null @@ -1,148 +0,0 @@ -/** - * Timeout configuration for API calls. Can be specified as: - * - A number representing milliseconds - * - An object with `totalMs` property for the total timeout in milliseconds - * - An object with `stepMs` property for the timeout of each step in milliseconds - * - An object with `chunkMs` property for the timeout between stream chunks (streaming only) - */ -export type TimeoutConfiguration = - | number - | { totalMs?: number; stepMs?: number; chunkMs?: number }; - -/** - * Extracts the total timeout value in milliseconds from a TimeoutConfiguration. - * - * @param timeout - The timeout configuration. - * @returns The total timeout in milliseconds, or undefined if no timeout is configured. - */ -export function getTotalTimeoutMs( - timeout: TimeoutConfiguration | undefined, -): number | undefined { - if (timeout == null) { - return undefined; - } - if (typeof timeout === 'number') { - return timeout; - } - return timeout.totalMs; -} - -/** - * Extracts the step timeout value in milliseconds from a TimeoutConfiguration. - * - * @param timeout - The timeout configuration. - * @returns The step timeout in milliseconds, or undefined if no step timeout is configured. - */ -export function getStepTimeoutMs( - timeout: TimeoutConfiguration | undefined, -): number | undefined { - if (timeout == null || typeof timeout === 'number') { - return undefined; - } - return timeout.stepMs; -} - -/** - * Extracts the chunk timeout value in milliseconds from a TimeoutConfiguration. - * This timeout is for streaming only - it aborts if no new chunk is received within the specified duration. - * - * @param timeout - The timeout configuration. - * @returns The chunk timeout in milliseconds, or undefined if no chunk timeout is configured. - */ -export function getChunkTimeoutMs( - timeout: TimeoutConfiguration | undefined, -): number | undefined { - if (timeout == null || typeof timeout === 'number') { - return undefined; - } - return timeout.chunkMs; -} - -export type CallSettings = { - /** - * Maximum number of tokens to generate. - */ - maxOutputTokens?: number; - - /** - * Temperature setting. The range depends on the provider and model. - * - * It is recommended to set either `temperature` or `topP`, but not both. - */ - temperature?: number; - - /** - * Nucleus sampling. This is a number between 0 and 1. - * - * E.g. 0.1 would mean that only tokens with the top 10% probability mass - * are considered. - * - * It is recommended to set either `temperature` or `topP`, but not both. - */ - topP?: number; - - /** - * Only sample from the top K options for each subsequent token. - * - * Used to remove "long tail" low probability responses. - * Recommended for advanced use cases only. You usually only need to use temperature. - */ - topK?: number; - - /** - * Presence penalty setting. It affects the likelihood of the model to - * repeat information that is already in the prompt. - * - * The presence penalty is a number between -1 (increase repetition) - * and 1 (maximum penalty, decrease repetition). 0 means no penalty. - */ - presencePenalty?: number; - - /** - * Frequency penalty setting. It affects the likelihood of the model - * to repeatedly use the same words or phrases. - * - * The frequency penalty is a number between -1 (increase repetition) - * and 1 (maximum penalty, decrease repetition). 0 means no penalty. - */ - frequencyPenalty?: number; - - /** - * Stop sequences. - * If set, the model will stop generating text when one of the stop sequences is generated. - * Providers may have limits on the number of stop sequences. - */ - stopSequences?: string[]; - - /** - * The seed (integer) to use for random sampling. If set and supported - * by the model, calls will generate deterministic results. - */ - seed?: number; - - /** - * Maximum number of retries. Set to 0 to disable retries. - * - * @default 2 - */ - maxRetries?: number; - - /** - * Abort signal. - */ - abortSignal?: AbortSignal; - - /** - * Timeout in milliseconds. The call will be aborted if it takes longer - * than the specified timeout. Can be used alongside abortSignal. - * - * Can be specified as a number (milliseconds) or as an object with `totalMs`. - */ - timeout?: TimeoutConfiguration; - - /** - * Additional HTTP headers to be sent with the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/content-part.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/content-part.ts deleted file mode 100644 index 6b7464bdd..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/content-part.ts +++ /dev/null @@ -1,215 +0,0 @@ -import { - FilePart, - ImagePart, - ProviderOptions, - ReasoningPart, - TextPart, - ToolApprovalRequest, - ToolApprovalResponse, - ToolResultOutput, - ToolResultPart, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import { jsonValueSchema } from '../types/json-value'; -import { providerMetadataSchema } from '../types/provider-metadata'; -import { dataContentSchema } from './data-content'; - -/** - * @internal - */ -export const textPartSchema: z.ZodType = z.object({ - type: z.literal('text'), - text: z.string(), - providerOptions: providerMetadataSchema.optional(), -}); - -/** - * @internal - */ -export const imagePartSchema: z.ZodType = z.object({ - type: z.literal('image'), - image: z.union([dataContentSchema, z.instanceof(URL)]), - mediaType: z.string().optional(), - providerOptions: providerMetadataSchema.optional(), -}); - -/** - * @internal - */ -export const filePartSchema: z.ZodType = z.object({ - type: z.literal('file'), - data: z.union([dataContentSchema, z.instanceof(URL)]), - filename: z.string().optional(), - mediaType: z.string(), - providerOptions: providerMetadataSchema.optional(), -}); - -/** - * @internal - */ -export const reasoningPartSchema: z.ZodType = z.object({ - type: z.literal('reasoning'), - text: z.string(), - providerOptions: providerMetadataSchema.optional(), -}); - -/** - * Tool call content part of a prompt. It contains a tool call (usually generated by the AI model). - */ -export interface ToolCallPart { - type: 'tool-call'; - - /** - * ID of the tool call. This ID is used to match the tool call with the tool result. - */ - toolCallId: string; - - /** - * Name of the tool that is being called. - */ - toolName: string; - - /** - * Arguments of the tool call. This is a JSON-serializable object that matches the tool's input schema. - */ - input: unknown; - - /** - * Additional provider-specific metadata. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; -} - -/** - * @internal - */ -export const toolCallPartSchema: z.ZodType = z.object({ - type: z.literal('tool-call'), - toolCallId: z.string(), - toolName: z.string(), - input: z.unknown(), - providerOptions: providerMetadataSchema.optional(), - providerExecuted: z.boolean().optional(), -}) as z.ZodType; // necessary bc input is optional on Zod type - -/** - * @internal - */ -export const outputSchema: z.ZodType = z.discriminatedUnion( - 'type', - [ - z.object({ - type: z.literal('text'), - value: z.string(), - providerOptions: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('json'), - value: jsonValueSchema, - providerOptions: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('execution-denied'), - reason: z.string().optional(), - providerOptions: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('error-text'), - value: z.string(), - providerOptions: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('error-json'), - value: jsonValueSchema, - providerOptions: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('content'), - value: z.array( - z.union([ - z.object({ - type: z.literal('text'), - text: z.string(), - providerOptions: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('media'), - data: z.string(), - mediaType: z.string(), - }), - z.object({ - type: z.literal('file-data'), - data: z.string(), - mediaType: z.string(), - filename: z.string().optional(), - providerOptions: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('file-url'), - url: z.string(), - providerOptions: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('file-id'), - fileId: z.union([z.string(), z.record(z.string(), z.string())]), - providerOptions: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('image-data'), - data: z.string(), - mediaType: z.string(), - providerOptions: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('image-url'), - url: z.string(), - providerOptions: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('image-file-id'), - fileId: z.union([z.string(), z.record(z.string(), z.string())]), - providerOptions: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('custom'), - providerOptions: providerMetadataSchema.optional(), - }), - ]), - ), - }), - ], -); - -/** - * @internal - */ -export const toolResultPartSchema: z.ZodType = z.object({ - type: z.literal('tool-result'), - toolCallId: z.string(), - toolName: z.string(), - output: outputSchema, - providerOptions: providerMetadataSchema.optional(), -}) as z.ZodType; // necessary bc result is optional on Zod type - -/** - * @internal - */ -export const toolApprovalRequestSchema: z.ZodType = - z.object({ - type: z.literal('tool-approval-request'), - approvalId: z.string(), - toolCallId: z.string(), - }); - -/** - * @internal - */ -export const toolApprovalResponseSchema: z.ZodType = - z.object({ - type: z.literal('tool-approval-response'), - approvalId: z.string(), - approved: z.boolean(), - reason: z.string().optional(), - }); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/convert-to-language-model-prompt.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/convert-to-language-model-prompt.ts deleted file mode 100644 index 4fedd90b1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/convert-to-language-model-prompt.ts +++ /dev/null @@ -1,526 +0,0 @@ -import { - LanguageModelV3FilePart, - LanguageModelV3Message, - LanguageModelV3Prompt, - LanguageModelV3TextPart, - LanguageModelV3ToolResultOutput, -} from '@ai-sdk/provider'; -import { - DataContent, - FilePart, - ImagePart, - isUrlSupported, - ModelMessage, - ReasoningPart, - TextPart, - ToolCallPart, - ToolResultOutput, - ToolResultPart, -} from '@ai-sdk/provider-utils'; -import { - detectMediaType, - imageMediaTypeSignatures, -} from '../util/detect-media-type'; -import { - createDefaultDownloadFunction, - DownloadFunction, -} from '../util/download/download-function'; -import { convertToLanguageModelV3DataContent } from './data-content'; -import { InvalidMessageRoleError } from './invalid-message-role-error'; -import { StandardizedPrompt } from './standardize-prompt'; -import { asArray } from '../util/as-array'; -import { MissingToolResultsError } from '../error/missing-tool-result-error'; - -export async function convertToLanguageModelPrompt({ - prompt, - supportedUrls, - download = createDefaultDownloadFunction(), -}: { - prompt: StandardizedPrompt; - supportedUrls: Record; - download: DownloadFunction | undefined; -}): Promise { - const downloadedAssets = await downloadAssets( - prompt.messages, - download, - supportedUrls, - ); - - const approvalIdToToolCallId = new Map(); - for (const message of prompt.messages) { - if (message.role === 'assistant' && Array.isArray(message.content)) { - for (const part of message.content) { - if ( - part.type === 'tool-approval-request' && - 'approvalId' in part && - 'toolCallId' in part - ) { - approvalIdToToolCallId.set( - part.approvalId as string, - part.toolCallId as string, - ); - } - } - } - } - - const approvedToolCallIds = new Set(); - for (const message of prompt.messages) { - if (message.role === 'tool') { - for (const part of message.content) { - if (part.type === 'tool-approval-response') { - const toolCallId = approvalIdToToolCallId.get(part.approvalId); - if (toolCallId) { - approvedToolCallIds.add(toolCallId); - } - } - } - } - } - - const messages = [ - ...(prompt.system != null - ? typeof prompt.system === 'string' - ? [{ role: 'system' as const, content: prompt.system }] - : asArray(prompt.system).map(message => ({ - role: 'system' as const, - content: message.content, - providerOptions: message.providerOptions, - })) - : []), - ...prompt.messages.map(message => - convertToLanguageModelMessage({ message, downloadedAssets }), - ), - ]; - - // combine consecutive tool messages into a single tool message - const combinedMessages = []; - for (const message of messages) { - if (message.role !== 'tool') { - combinedMessages.push(message); - continue; - } - - const lastCombinedMessage = combinedMessages.at(-1); - if (lastCombinedMessage?.role === 'tool') { - lastCombinedMessage.content.push(...message.content); - } else { - combinedMessages.push(message); - } - } - - const toolCallIds = new Set(); - - for (const message of combinedMessages) { - switch (message.role) { - case 'assistant': { - for (const content of message.content) { - if (content.type === 'tool-call' && !content.providerExecuted) { - toolCallIds.add(content.toolCallId); - } - } - break; - } - case 'tool': { - for (const content of message.content) { - if (content.type === 'tool-result') { - toolCallIds.delete(content.toolCallId); - } - } - break; - } - case 'user': - case 'system': - // remove approved tool calls from the set before checking: - for (const id of approvedToolCallIds) { - toolCallIds.delete(id); - } - - if (toolCallIds.size > 0) { - throw new MissingToolResultsError({ - toolCallIds: Array.from(toolCallIds), - }); - } - break; - } - } - - // remove approved tool calls from the set before checking: - for (const id of approvedToolCallIds) { - toolCallIds.delete(id); - } - - if (toolCallIds.size > 0) { - throw new MissingToolResultsError({ toolCallIds: Array.from(toolCallIds) }); - } - - return combinedMessages.filter( - // Filter out empty tool messages (e.g. if they only contained - // tool-approval-response parts that were removed). - // This prevents sending invalid empty messages to the provider. - // Note: provider-executed tool-approval-response parts are preserved. - message => message.role !== 'tool' || message.content.length > 0, - ); -} - -/** - * Convert a ModelMessage to a LanguageModelV3Message. - * - * @param message - The ModelMessage to convert. - * @param downloadedAssets - A map of URLs to their downloaded data. Only - * available if the model does not support URLs, null otherwise. - */ -export function convertToLanguageModelMessage({ - message, - downloadedAssets, -}: { - message: ModelMessage; - downloadedAssets: Record< - string, - { mediaType: string | undefined; data: Uint8Array } - >; -}): LanguageModelV3Message { - const role = message.role; - switch (role) { - case 'system': { - return { - role: 'system', - content: message.content, - providerOptions: message.providerOptions, - }; - } - - case 'user': { - if (typeof message.content === 'string') { - return { - role: 'user', - content: [{ type: 'text', text: message.content }], - providerOptions: message.providerOptions, - }; - } - - return { - role: 'user', - content: message.content - .map(part => convertPartToLanguageModelPart(part, downloadedAssets)) - // remove empty text parts: - .filter(part => part.type !== 'text' || part.text !== ''), - providerOptions: message.providerOptions, - }; - } - - case 'assistant': { - if (typeof message.content === 'string') { - return { - role: 'assistant', - content: [{ type: 'text', text: message.content }], - providerOptions: message.providerOptions, - }; - } - - return { - role: 'assistant', - content: message.content - .filter( - // remove empty text parts (no text, and no provider options): - part => - part.type !== 'text' || - part.text !== '' || - part.providerOptions != null, - ) - .filter( - ( - part, - ): part is - | TextPart - | FilePart - | ReasoningPart - | ToolCallPart - | ToolResultPart => part.type !== 'tool-approval-request', - ) - .map(part => { - const providerOptions = part.providerOptions; - - switch (part.type) { - case 'file': { - const { data, mediaType } = convertToLanguageModelV3DataContent( - part.data, - ); - return { - type: 'file', - data, - filename: part.filename, - mediaType: mediaType ?? part.mediaType, - providerOptions, - }; - } - case 'reasoning': { - return { - type: 'reasoning', - text: part.text, - providerOptions, - }; - } - case 'text': { - return { - type: 'text' as const, - text: part.text, - providerOptions, - }; - } - case 'tool-call': { - return { - type: 'tool-call' as const, - toolCallId: part.toolCallId, - toolName: part.toolName, - input: part.input, - providerExecuted: part.providerExecuted, - providerOptions, - }; - } - case 'tool-result': { - return { - type: 'tool-result' as const, - toolCallId: part.toolCallId, - toolName: part.toolName, - output: mapToolResultOutput(part.output), - providerOptions, - }; - } - } - }), - providerOptions: message.providerOptions, - }; - } - - case 'tool': { - return { - role: 'tool', - content: message.content - .filter( - // Only include tool-approval-response for provider-executed tools - part => - part.type !== 'tool-approval-response' || part.providerExecuted, - ) - .map(part => { - switch (part.type) { - case 'tool-result': { - return { - type: 'tool-result' as const, - toolCallId: part.toolCallId, - toolName: part.toolName, - output: mapToolResultOutput(part.output), - providerOptions: part.providerOptions, - }; - } - case 'tool-approval-response': { - return { - type: 'tool-approval-response' as const, - approvalId: part.approvalId, - approved: part.approved, - reason: part.reason, - }; - } - } - }), - providerOptions: message.providerOptions, - }; - } - - default: { - const _exhaustiveCheck: never = role; - throw new InvalidMessageRoleError({ role: _exhaustiveCheck }); - } - } -} - -/** - * Downloads images and files from URLs in the messages. - */ -async function downloadAssets( - messages: ModelMessage[], - download: DownloadFunction, - supportedUrls: Record, -): Promise< - Record -> { - const plannedDownloads = messages - .filter(message => message.role === 'user') - .map(message => message.content) - .filter((content): content is Array => - Array.isArray(content), - ) - .flat() - .filter( - (part): part is ImagePart | FilePart => - part.type === 'image' || part.type === 'file', - ) - .map(part => { - const mediaType = - part.mediaType ?? (part.type === 'image' ? 'image/*' : undefined); - - let data = part.type === 'image' ? part.image : part.data; - if (typeof data === 'string') { - try { - data = new URL(data); - } catch (ignored) {} - } - - return { mediaType, data }; - }) - - .filter( - (part): part is { mediaType: string | undefined; data: URL } => - part.data instanceof URL, - ) - .map(part => ({ - url: part.data, - isUrlSupportedByModel: - part.mediaType != null && - isUrlSupported({ - url: part.data.toString(), - mediaType: part.mediaType, - supportedUrls, - }), - })); - - // download in parallel: - const downloadedFiles = await download(plannedDownloads); - - return Object.fromEntries( - downloadedFiles - .map((file, index) => - file == null - ? null - : [ - plannedDownloads[index].url.toString(), - { data: file.data, mediaType: file.mediaType }, - ], - ) - .filter(file => file != null), - ); -} - -/** - * Convert part of a message to a LanguageModelV3Part. - * - * @param part - The part to convert. - * @param downloadedAssets - A map of URLs to their downloaded data. Only - * available if the model does not support URLs, null otherwise. - * @returns The converted part. - */ -function convertPartToLanguageModelPart( - part: TextPart | ImagePart | FilePart, - downloadedAssets: Record< - string, - { mediaType: string | undefined; data: Uint8Array } - >, -): LanguageModelV3TextPart | LanguageModelV3FilePart { - if (part.type === 'text') { - return { - type: 'text', - text: part.text, - providerOptions: part.providerOptions, - }; - } - - let originalData: DataContent | URL; - const type = part.type; - switch (type) { - case 'image': - originalData = part.image; - break; - case 'file': - originalData = part.data; - - break; - default: - throw new Error(`Unsupported part type: ${type}`); - } - - const { data: convertedData, mediaType: convertedMediaType } = - convertToLanguageModelV3DataContent(originalData); - - let mediaType: string | undefined = convertedMediaType ?? part.mediaType; - let data: Uint8Array | string | URL = convertedData; // binary | base64 | url - - // If the content is a URL, we check if it was downloaded: - if (data instanceof URL) { - const downloadedFile = downloadedAssets[data.toString()]; - if (downloadedFile) { - data = downloadedFile.data; - mediaType ??= downloadedFile.mediaType; - } - } - - // Now that we have the normalized data either as a URL or a Uint8Array, - // we can create the LanguageModelV3Part. - switch (type) { - case 'image': { - // When possible, try to detect the media type automatically - // to deal with incorrect media type inputs. - // When detection fails, use provided media type. - if (data instanceof Uint8Array || typeof data === 'string') { - mediaType = - detectMediaType({ data, signatures: imageMediaTypeSignatures }) ?? - mediaType; - } - - return { - type: 'file', - mediaType: mediaType ?? 'image/*', // any image - filename: undefined, - data, - providerOptions: part.providerOptions, - }; - } - - case 'file': { - // We must have a mediaType for files, if not, throw an error. - if (mediaType == null) { - throw new Error(`Media type is missing for file part`); - } - - return { - type: 'file', - mediaType, - filename: part.filename, - data, - providerOptions: part.providerOptions, - }; - } - } -} - -function mapToolResultOutput( - output: ToolResultOutput, -): LanguageModelV3ToolResultOutput { - if (output.type !== 'content') { - return output; - } - - return { - type: 'content', - value: output.value.map(item => { - if (item.type !== 'media') { - return item; - } - - // AI SDK 5 tool backwards compatibility: - // map media type to image-data or file-data - if (item.mediaType.startsWith('image/')) { - return { - type: 'image-data' as const, - data: item.data, - mediaType: item.mediaType, - }; - } - - return { - type: 'file-data' as const, - data: item.data, - mediaType: item.mediaType, - }; - }), - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/create-tool-model-output.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/create-tool-model-output.ts deleted file mode 100644 index 142699efe..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/create-tool-model-output.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { getErrorMessage, JSONValue } from '@ai-sdk/provider'; -import { Tool, ToolResultOutput } from '@ai-sdk/provider-utils'; - -export async function createToolModelOutput({ - toolCallId, - input, - output, - tool, - errorMode, -}: { - toolCallId: string; - input: unknown; - output: unknown; - tool: Tool | undefined; - errorMode: 'none' | 'text' | 'json'; -}): Promise { - if (errorMode === 'text') { - return { type: 'error-text', value: getErrorMessage(output) }; - } else if (errorMode === 'json') { - return { type: 'error-json', value: toJSONValue(output) }; - } - - if (tool?.toModelOutput) { - return await tool.toModelOutput({ toolCallId, input, output }); - } - - return typeof output === 'string' - ? { type: 'text', value: output } - : { type: 'json', value: toJSONValue(output) }; -} - -function toJSONValue(value: unknown): JSONValue { - return value === undefined ? null : (value as JSONValue); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/data-content.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/data-content.ts deleted file mode 100644 index 49f73e014..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/data-content.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { AISDKError, LanguageModelV3DataContent } from '@ai-sdk/provider'; -import { - convertBase64ToUint8Array, - convertUint8ArrayToBase64, - DataContent, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import { InvalidDataContentError } from './invalid-data-content-error'; -import { splitDataUrl } from './split-data-url'; - -/** - * @internal - */ -export const dataContentSchema: z.ZodType = z.union([ - z.string(), - z.instanceof(Uint8Array), - z.instanceof(ArrayBuffer), - z.custom( - // Buffer might not be available in some environments such as CloudFlare: - (value: unknown): value is Buffer => - globalThis.Buffer?.isBuffer(value) ?? false, - { message: 'Must be a Buffer' }, - ), -]); - -export function convertToLanguageModelV3DataContent( - content: DataContent | URL, -): { - data: LanguageModelV3DataContent; - mediaType: string | undefined; -} { - // Buffer & Uint8Array: - if (content instanceof Uint8Array) { - return { data: content, mediaType: undefined }; - } - - // ArrayBuffer needs conversion to Uint8Array (lightweight): - if (content instanceof ArrayBuffer) { - return { data: new Uint8Array(content), mediaType: undefined }; - } - - // Attempt to create a URL from the data. If it fails, we can assume the data - // is not a URL and likely some other sort of data. - if (typeof content === 'string') { - try { - content = new URL(content); - } catch (error) { - // ignored - } - } - - // Extract data from data URL: - if (content instanceof URL && content.protocol === 'data:') { - const { mediaType: dataUrlMediaType, base64Content } = splitDataUrl( - content.toString(), - ); - - if (dataUrlMediaType == null || base64Content == null) { - throw new AISDKError({ - name: 'InvalidDataContentError', - message: `Invalid data URL format in content ${content.toString()}`, - }); - } - - return { data: base64Content, mediaType: dataUrlMediaType }; - } - - return { data: content, mediaType: undefined }; -} - -/** - * Converts data content to a base64-encoded string. - * - * @param content - Data content to convert. - * @returns Base64-encoded string. - */ -export function convertDataContentToBase64String(content: DataContent): string { - if (typeof content === 'string') { - return content; - } - - if (content instanceof ArrayBuffer) { - return convertUint8ArrayToBase64(new Uint8Array(content)); - } - - return convertUint8ArrayToBase64(content); -} - -/** - * Converts data content to a Uint8Array. - * - * @param content - Data content to convert. - * @returns Uint8Array. - */ -export function convertDataContentToUint8Array( - content: DataContent, -): Uint8Array { - if (content instanceof Uint8Array) { - return content; - } - - if (typeof content === 'string') { - try { - return convertBase64ToUint8Array(content); - } catch (error) { - throw new InvalidDataContentError({ - message: - 'Invalid data content. Content string is not a base64-encoded media.', - content, - cause: error, - }); - } - } - - if (content instanceof ArrayBuffer) { - return new Uint8Array(content); - } - - throw new InvalidDataContentError({ content }); -} - -/** - * Converts a Uint8Array to a string of text. - * - * @param uint8Array - The Uint8Array to convert. - * @returns The converted string. - */ -export function convertUint8ArrayToText(uint8Array: Uint8Array): string { - try { - return new TextDecoder().decode(uint8Array); - } catch (error) { - throw new Error('Error decoding Uint8Array to text'); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/index.ts deleted file mode 100644 index e763f3fb7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -export type { CallSettings, TimeoutConfiguration } from './call-settings'; -export { - assistantModelMessageSchema, - modelMessageSchema, - systemModelMessageSchema, - toolModelMessageSchema, - userModelMessageSchema, -} from './message'; -export type { Prompt } from './prompt'; - -// re-export types from provider-utils -export type { - AssistantContent, - AssistantModelMessage, - DataContent, - FilePart, - ImagePart, - ModelMessage, - SystemModelMessage, - TextPart, - ToolCallPart, - ToolContent, - ToolModelMessage, - ToolResultPart, - UserContent, - UserModelMessage, -} from '@ai-sdk/provider-utils'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/invalid-data-content-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/invalid-data-content-error.ts deleted file mode 100644 index 8c9523b7f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/invalid-data-content-error.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; - -const name = 'AI_InvalidDataContentError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class InvalidDataContentError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly content: unknown; - - constructor({ - content, - cause, - message = `Invalid data content. Expected a base64 string, Uint8Array, ArrayBuffer, or Buffer, but got ${typeof content}.`, - }: { - content: unknown; - cause?: unknown; - message?: string; - }) { - super({ name, message, cause }); - - this.content = content; - } - - static isInstance(error: unknown): error is InvalidDataContentError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/invalid-message-role-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/invalid-message-role-error.ts deleted file mode 100644 index 42d12417d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/invalid-message-role-error.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; - -const name = 'AI_InvalidMessageRoleError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class InvalidMessageRoleError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly role: string; - - constructor({ - role, - message = `Invalid message role: '${role}'. Must be one of: "system", "user", "assistant", "tool".`, - }: { - role: string; - message?: string; - }) { - super({ name, message }); - - this.role = role; - } - - static isInstance(error: unknown): error is InvalidMessageRoleError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/message-conversion-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/message-conversion-error.ts deleted file mode 100644 index 1a45f30b6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/message-conversion-error.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; -import { UIMessage } from '../ui/ui-messages'; - -const name = 'AI_MessageConversionError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class MessageConversionError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - readonly originalMessage: Omit; - - constructor({ - originalMessage, - message, - }: { - originalMessage: Omit; - message: string; - }) { - super({ name, message }); - - this.originalMessage = originalMessage; - } - - static isInstance(error: unknown): error is MessageConversionError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/message.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/message.ts deleted file mode 100644 index 298653ff5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/message.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { - AssistantModelMessage, - ModelMessage, - SystemModelMessage, - ToolModelMessage, - UserModelMessage, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import { providerMetadataSchema } from '../types/provider-metadata'; -import { - filePartSchema, - imagePartSchema, - reasoningPartSchema, - textPartSchema, - toolApprovalRequestSchema, - toolCallPartSchema, - toolApprovalResponseSchema, - toolResultPartSchema, -} from './content-part'; - -export const systemModelMessageSchema: z.ZodType = z.object( - { - role: z.literal('system'), - content: z.string(), - providerOptions: providerMetadataSchema.optional(), - }, -); - -export const userModelMessageSchema: z.ZodType = z.object({ - role: z.literal('user'), - content: z.union([ - z.string(), - z.array(z.union([textPartSchema, imagePartSchema, filePartSchema])), - ]), - providerOptions: providerMetadataSchema.optional(), -}); - -export const assistantModelMessageSchema: z.ZodType = - z.object({ - role: z.literal('assistant'), - content: z.union([ - z.string(), - z.array( - z.union([ - textPartSchema, - filePartSchema, - reasoningPartSchema, - toolCallPartSchema, - toolResultPartSchema, - toolApprovalRequestSchema, - ]), - ), - ]), - providerOptions: providerMetadataSchema.optional(), - }); - -export const toolModelMessageSchema: z.ZodType = z.object({ - role: z.literal('tool'), - content: z.array(z.union([toolResultPartSchema, toolApprovalResponseSchema])), - providerOptions: providerMetadataSchema.optional(), -}); - -export const modelMessageSchema: z.ZodType = z.union([ - systemModelMessageSchema, - userModelMessageSchema, - assistantModelMessageSchema, - toolModelMessageSchema, -]); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/prepare-call-settings.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/prepare-call-settings.ts deleted file mode 100644 index 499930175..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/prepare-call-settings.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { InvalidArgumentError } from '../error/invalid-argument-error'; -import { CallSettings } from './call-settings'; - -/** - * Validates call settings and returns a new object with limited values. - */ -export function prepareCallSettings({ - maxOutputTokens, - temperature, - topP, - topK, - presencePenalty, - frequencyPenalty, - seed, - stopSequences, -}: Omit): Omit< - CallSettings, - 'abortSignal' | 'headers' | 'maxRetries' -> { - if (maxOutputTokens != null) { - if (!Number.isInteger(maxOutputTokens)) { - throw new InvalidArgumentError({ - parameter: 'maxOutputTokens', - value: maxOutputTokens, - message: 'maxOutputTokens must be an integer', - }); - } - - if (maxOutputTokens < 1) { - throw new InvalidArgumentError({ - parameter: 'maxOutputTokens', - value: maxOutputTokens, - message: 'maxOutputTokens must be >= 1', - }); - } - } - - if (temperature != null) { - if (typeof temperature !== 'number') { - throw new InvalidArgumentError({ - parameter: 'temperature', - value: temperature, - message: 'temperature must be a number', - }); - } - } - - if (topP != null) { - if (typeof topP !== 'number') { - throw new InvalidArgumentError({ - parameter: 'topP', - value: topP, - message: 'topP must be a number', - }); - } - } - - if (topK != null) { - if (typeof topK !== 'number') { - throw new InvalidArgumentError({ - parameter: 'topK', - value: topK, - message: 'topK must be a number', - }); - } - } - - if (presencePenalty != null) { - if (typeof presencePenalty !== 'number') { - throw new InvalidArgumentError({ - parameter: 'presencePenalty', - value: presencePenalty, - message: 'presencePenalty must be a number', - }); - } - } - - if (frequencyPenalty != null) { - if (typeof frequencyPenalty !== 'number') { - throw new InvalidArgumentError({ - parameter: 'frequencyPenalty', - value: frequencyPenalty, - message: 'frequencyPenalty must be a number', - }); - } - } - - if (seed != null) { - if (!Number.isInteger(seed)) { - throw new InvalidArgumentError({ - parameter: 'seed', - value: seed, - message: 'seed must be an integer', - }); - } - } - - return { - maxOutputTokens, - temperature, - topP, - topK, - presencePenalty, - frequencyPenalty, - stopSequences, - seed, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/prepare-tools-and-tool-choice.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/prepare-tools-and-tool-choice.ts deleted file mode 100644 index 01bc568a3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/prepare-tools-and-tool-choice.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { - LanguageModelV3FunctionTool, - LanguageModelV3ProviderTool, - LanguageModelV3ToolChoice, -} from '@ai-sdk/provider'; -import { asSchema } from '@ai-sdk/provider-utils'; -import { isNonEmptyObject } from '../util/is-non-empty-object'; -import { ToolSet } from '../generate-text'; -import { ToolChoice } from '../types/language-model'; - -export async function prepareToolsAndToolChoice({ - tools, - toolChoice, - activeTools, -}: { - tools: TOOLS | undefined; - toolChoice: ToolChoice | undefined; - activeTools: Array | undefined; -}): Promise<{ - tools: - | Array - | undefined; - toolChoice: LanguageModelV3ToolChoice | undefined; -}> { - if (!isNonEmptyObject(tools)) { - return { - tools: undefined, - toolChoice: undefined, - }; - } - - // when activeTools is provided, we only include the tools that are in the list: - const filteredTools = - activeTools != null - ? Object.entries(tools).filter(([name]) => - activeTools.includes(name as keyof TOOLS), - ) - : Object.entries(tools); - - const languageModelTools: Array< - LanguageModelV3FunctionTool | LanguageModelV3ProviderTool - > = []; - for (const [name, tool] of filteredTools) { - const toolType = tool.type; - - switch (toolType) { - case undefined: - case 'dynamic': - case 'function': - languageModelTools.push({ - type: 'function' as const, - name, - description: tool.description, - inputSchema: await asSchema(tool.inputSchema).jsonSchema, - ...(tool.inputExamples != null - ? { inputExamples: tool.inputExamples } - : {}), - providerOptions: tool.providerOptions, - ...(tool.strict != null ? { strict: tool.strict } : {}), - }); - break; - case 'provider': - languageModelTools.push({ - type: 'provider' as const, - name, - id: tool.id, - args: tool.args, - }); - break; - default: { - const exhaustiveCheck: never = toolType as never; - throw new Error(`Unsupported tool type: ${exhaustiveCheck}`); - } - } - } - - return { - tools: languageModelTools, - toolChoice: - toolChoice == null - ? { type: 'auto' } - : typeof toolChoice === 'string' - ? { type: toolChoice } - : { type: 'tool' as const, toolName: toolChoice.toolName as string }, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/prompt.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/prompt.ts deleted file mode 100644 index de21de540..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/prompt.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { ModelMessage, SystemModelMessage } from '@ai-sdk/provider-utils'; - -/** - * Prompt part of the AI function options. - * It contains a system message, a simple text prompt, or a list of messages. - */ -export type Prompt = { - /** - * System message to include in the prompt. Can be used with `prompt` or `messages`. - */ - system?: string | SystemModelMessage | Array; -} & ( - | { - /** - * A prompt. It can be either a text prompt or a list of messages. - * - * You can either use `prompt` or `messages` but not both. - */ - prompt: string | Array; - - /** - * A list of messages. - * - * You can either use `prompt` or `messages` but not both. - */ - messages?: never; - } - | { - /** - * A list of messages. - * - * You can either use `prompt` or `messages` but not both. - */ - messages: Array; - - /** - * A prompt. It can be either a text prompt or a list of messages. - * - * You can either use `prompt` or `messages` but not both. - */ - prompt?: never; - } -); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/split-data-url.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/split-data-url.ts deleted file mode 100644 index ced71e78c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/split-data-url.ts +++ /dev/null @@ -1,17 +0,0 @@ -export function splitDataUrl(dataUrl: string): { - mediaType: string | undefined; - base64Content: string | undefined; -} { - try { - const [header, base64Content] = dataUrl.split(','); - return { - mediaType: header.split(';')[0].split(':')[1], - base64Content, - }; - } catch (error) { - return { - mediaType: undefined, - base64Content: undefined, - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/standardize-prompt.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/standardize-prompt.ts deleted file mode 100644 index aa1920a0b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/standardize-prompt.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { InvalidPromptError } from '@ai-sdk/provider'; -import { - ModelMessage, - safeValidateTypes, - SystemModelMessage, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import { modelMessageSchema } from './message'; -import { Prompt } from './prompt'; -import { asArray } from '../util/as-array'; - -export type StandardizedPrompt = { - /** - * System message. - */ - system?: string | SystemModelMessage | Array; - - /** - * Messages. - */ - messages: ModelMessage[]; -}; - -export async function standardizePrompt( - prompt: Prompt, -): Promise { - if (prompt.prompt == null && prompt.messages == null) { - throw new InvalidPromptError({ - prompt, - message: 'prompt or messages must be defined', - }); - } - - if (prompt.prompt != null && prompt.messages != null) { - throw new InvalidPromptError({ - prompt, - message: 'prompt and messages cannot be defined at the same time', - }); - } - - // validate that system is a string or a SystemModelMessage - if ( - prompt.system != null && - typeof prompt.system !== 'string' && - !asArray(prompt.system).every( - message => - typeof message === 'object' && - message !== null && - 'role' in message && - message.role === 'system', - ) - ) { - throw new InvalidPromptError({ - prompt, - message: - 'system must be a string, SystemModelMessage, or array of SystemModelMessage', - }); - } - - let messages: ModelMessage[]; - - if (prompt.prompt != null && typeof prompt.prompt === 'string') { - messages = [{ role: 'user', content: prompt.prompt }]; - } else if (prompt.prompt != null && Array.isArray(prompt.prompt)) { - messages = prompt.prompt; - } else if (prompt.messages != null) { - messages = prompt.messages; - } else { - throw new InvalidPromptError({ - prompt, - message: 'prompt or messages must be defined', - }); - } - - if (messages.length === 0) { - throw new InvalidPromptError({ - prompt, - message: 'messages must not be empty', - }); - } - - const validationResult = await safeValidateTypes({ - value: messages, - schema: z.array(modelMessageSchema), - }); - - if (!validationResult.success) { - throw new InvalidPromptError({ - prompt, - message: 'The messages do not match the ModelMessage[] schema.', - cause: validationResult.error, - }); - } - - return { - messages, - system: prompt.system, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/wrap-gateway-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/wrap-gateway-error.ts deleted file mode 100644 index 19fa3caf8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/prompt/wrap-gateway-error.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { GatewayAuthenticationError } from '@ai-sdk/gateway'; -import { AISDKError } from '@ai-sdk/provider'; - -export function wrapGatewayError(error: unknown): unknown { - if (!GatewayAuthenticationError.isInstance(error)) return error; - - const isProductionEnv = process?.env.NODE_ENV === 'production'; - const moreInfoURL = 'https://ai-sdk.dev/unauthenticated-ai-gateway'; - - if (isProductionEnv) { - return new AISDKError({ - name: 'GatewayError', - message: `Unauthenticated. Configure AI_GATEWAY_API_KEY or use a provider module. Learn more: ${moreInfoURL}`, - }); - } - - return Object.assign( - new Error(`\u001b[1m\u001b[31mUnauthenticated request to AI Gateway.\u001b[0m - -To authenticate, set the \u001b[33mAI_GATEWAY_API_KEY\u001b[0m environment variable with your API key. - -Alternatively, you can use a provider module instead of the AI Gateway. - -Learn more: \u001b[34m${moreInfoURL}\u001b[0m - -`), - { name: 'GatewayAuthenticationError' }, - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/registry/custom-provider.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/registry/custom-provider.ts deleted file mode 100644 index 915d01609..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/registry/custom-provider.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { - EmbeddingModelV3, - Experimental_VideoModelV3, - ImageModelV3, - LanguageModelV3, - NoSuchModelError, - ProviderV2, - ProviderV3, - RerankingModelV3, - SpeechModelV3, - TranscriptionModelV3, -} from '@ai-sdk/provider'; -import { asProviderV3 } from '../model/as-provider-v3'; - -/** - * Creates a custom provider with specified language models, text embedding models, image models, transcription models, speech models, and an optional fallback provider. - * - * @param {Object} options - The options for creating the custom provider. - * @param {Record} [options.languageModels] - A record of language models, where keys are model IDs and values are LanguageModelV3 instances. - * @param {Record} [options.embeddingModels] - A record of text embedding models, where keys are model IDs and values are EmbeddingModelV3 instances. - * @param {Record} [options.imageModels] - A record of image models, where keys are model IDs and values are ImageModelV3 instances. - * @param {Record} [options.transcriptionModels] - A record of transcription models, where keys are model IDs and values are TranscriptionModelV3 instances. - * @param {Record} [options.speechModels] - A record of speech models, where keys are model IDs and values are SpeechModelV3 instances. - * @param {Record} [options.rerankingModels] - A record of reranking models, where keys are model IDs and values are RerankingModelV3 instances. - * @param {ProviderV3} [options.fallbackProvider] - An optional fallback provider to use when a requested model is not found in the custom provider. - * @returns {ProviderV3} A ProviderV3 object with languageModel, embeddingModel, imageModel, transcriptionModel, and speechModel methods. - * - * @throws {NoSuchModelError} Throws when a requested model is not found and no fallback provider is available. - */ -export function customProvider< - LANGUAGE_MODELS extends Record, - EMBEDDING_MODELS extends Record, - IMAGE_MODELS extends Record, - TRANSCRIPTION_MODELS extends Record, - SPEECH_MODELS extends Record, - RERANKING_MODELS extends Record, - VIDEO_MODELS extends Record, ->({ - languageModels, - embeddingModels, - imageModels, - transcriptionModels, - speechModels, - rerankingModels, - videoModels, - fallbackProvider: fallbackProviderArg, -}: { - languageModels?: LANGUAGE_MODELS; - embeddingModels?: EMBEDDING_MODELS; - imageModels?: IMAGE_MODELS; - transcriptionModels?: TRANSCRIPTION_MODELS; - speechModels?: SPEECH_MODELS; - rerankingModels?: RERANKING_MODELS; - videoModels?: VIDEO_MODELS; - fallbackProvider?: ProviderV3 | ProviderV2; -}): ProviderV3 & { - languageModel(modelId: ExtractModelId): LanguageModelV3; - embeddingModel(modelId: ExtractModelId): EmbeddingModelV3; - imageModel(modelId: ExtractModelId): ImageModelV3; - transcriptionModel( - modelId: ExtractModelId, - ): TranscriptionModelV3; - rerankingModel(modelId: ExtractModelId): RerankingModelV3; - speechModel(modelId: ExtractModelId): SpeechModelV3; - videoModel(modelId: ExtractModelId): Experimental_VideoModelV3; -} { - const fallbackProvider = fallbackProviderArg - ? asProviderV3(fallbackProviderArg) - : undefined; - - return { - specificationVersion: 'v3', - languageModel(modelId: ExtractModelId): LanguageModelV3 { - if (languageModels != null && modelId in languageModels) { - return languageModels[modelId]; - } - - if (fallbackProvider) { - return (fallbackProvider as ProviderV3).languageModel(modelId); - } - - throw new NoSuchModelError({ modelId, modelType: 'languageModel' }); - }, - - embeddingModel( - modelId: ExtractModelId, - ): EmbeddingModelV3 { - if (embeddingModels != null && modelId in embeddingModels) { - return embeddingModels[modelId]; - } - - if (fallbackProvider) { - return (fallbackProvider as ProviderV3).embeddingModel(modelId); - } - - throw new NoSuchModelError({ modelId, modelType: 'embeddingModel' }); - }, - - imageModel(modelId: ExtractModelId): ImageModelV3 { - if (imageModels != null && modelId in imageModels) { - return imageModels[modelId]; - } - - if (fallbackProvider?.imageModel) { - return (fallbackProvider as ProviderV3).imageModel(modelId); - } - - throw new NoSuchModelError({ modelId, modelType: 'imageModel' }); - }, - - transcriptionModel( - modelId: ExtractModelId, - ): TranscriptionModelV3 { - if (transcriptionModels != null && modelId in transcriptionModels) { - return transcriptionModels[modelId]; - } - - if (fallbackProvider?.transcriptionModel) { - return (fallbackProvider as ProviderV3).transcriptionModel!(modelId); - } - - throw new NoSuchModelError({ modelId, modelType: 'transcriptionModel' }); - }, - - speechModel(modelId: ExtractModelId): SpeechModelV3 { - if (speechModels != null && modelId in speechModels) { - return speechModels[modelId]; - } - - if (fallbackProvider?.speechModel) { - return (fallbackProvider as ProviderV3).speechModel!(modelId); - } - - throw new NoSuchModelError({ modelId, modelType: 'speechModel' }); - }, - rerankingModel( - modelId: ExtractModelId, - ): RerankingModelV3 { - if (rerankingModels != null && modelId in rerankingModels) { - return rerankingModels[modelId]; - } - - if (fallbackProvider?.rerankingModel) { - return fallbackProvider.rerankingModel(modelId); - } - - throw new NoSuchModelError({ modelId, modelType: 'rerankingModel' }); - }, - videoModel( - modelId: ExtractModelId, - ): Experimental_VideoModelV3 { - if (videoModels != null && modelId in videoModels) { - return videoModels[modelId]; - } - - // TODO AI SDK v7 - // @ts-expect-error - videoModel support is experimental - const videoModel = fallbackProvider?.videoModel; - if (videoModel) { - return videoModel(modelId); - } - - throw new NoSuchModelError({ modelId, modelType: 'videoModel' }); - }, - }; -} - -/** - * @deprecated Use `customProvider` instead. - */ -export const experimental_customProvider = customProvider; - -type ExtractModelId> = Extract< - keyof MODELS, - string ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/registry/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/registry/index.ts deleted file mode 100644 index 065e79f34..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/registry/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { customProvider, experimental_customProvider } from './custom-provider'; -export { NoSuchProviderError } from './no-such-provider-error'; -export { - createProviderRegistry, - experimental_createProviderRegistry, -} from './provider-registry'; -export type { ProviderRegistryProvider } from './provider-registry'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/registry/no-such-provider-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/registry/no-such-provider-error.ts deleted file mode 100644 index eec8e7704..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/registry/no-such-provider-error.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { AISDKError, NoSuchModelError } from '@ai-sdk/provider'; - -const name = 'AI_NoSuchProviderError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export class NoSuchProviderError extends NoSuchModelError { - private readonly [symbol] = true; // used in isInstance - - readonly providerId: string; - readonly availableProviders: string[]; - - constructor({ - modelId, - modelType, - providerId, - availableProviders, - message = `No such provider: ${providerId} (available providers: ${availableProviders.join()})`, - }: { - modelId: string; - modelType: - | 'languageModel' - | 'embeddingModel' - | 'imageModel' - | 'transcriptionModel' - | 'speechModel' - | 'rerankingModel'; - providerId: string; - availableProviders: string[]; - message?: string; - }) { - super({ errorName: name, modelId, modelType, message }); - - this.providerId = providerId; - this.availableProviders = availableProviders; - } - - static isInstance(error: unknown): error is NoSuchProviderError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/registry/provider-registry.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/registry/provider-registry.ts deleted file mode 100644 index 4d0ca66d9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/registry/provider-registry.ts +++ /dev/null @@ -1,327 +0,0 @@ -import { - EmbeddingModelV3, - ImageModelV3, - LanguageModelV3, - NoSuchModelError, - ProviderV3, - RerankingModelV3, - SpeechModelV3, - TranscriptionModelV3, -} from '@ai-sdk/provider'; -import { wrapImageModel } from '../middleware/wrap-image-model'; -import { wrapLanguageModel } from '../middleware/wrap-language-model'; -import { ImageModelMiddleware, LanguageModelMiddleware } from '../types'; -import { NoSuchProviderError } from './no-such-provider-error'; - -type ExtractLiteralUnion = T extends string - ? string extends T - ? never - : T - : never; - -export interface ProviderRegistryProvider< - PROVIDERS extends Record = Record, - SEPARATOR extends string = ':', -> { - languageModel( - id: KEY extends string - ? `${KEY & string}${SEPARATOR}${ExtractLiteralUnion>[0]>}` - : never, - ): LanguageModelV3; - languageModel( - id: KEY extends string ? `${KEY & string}${SEPARATOR}${string}` : never, - ): LanguageModelV3; - - embeddingModel( - id: KEY extends string - ? `${KEY & string}${SEPARATOR}${ExtractLiteralUnion>[0]>}` - : never, - ): EmbeddingModelV3; - embeddingModel( - id: KEY extends string ? `${KEY & string}${SEPARATOR}${string}` : never, - ): EmbeddingModelV3; - - imageModel( - id: KEY extends string - ? `${KEY & string}${SEPARATOR}${ExtractLiteralUnion>[0]>}` - : never, - ): ImageModelV3; - imageModel( - id: KEY extends string ? `${KEY & string}${SEPARATOR}${string}` : never, - ): ImageModelV3; - - transcriptionModel( - id: KEY extends string - ? `${KEY & string}${SEPARATOR}${ExtractLiteralUnion>[0]>}` - : never, - ): TranscriptionModelV3; - transcriptionModel( - id: KEY extends string ? `${KEY & string}${SEPARATOR}${string}` : never, - ): TranscriptionModelV3; - - speechModel( - id: KEY extends string - ? `${KEY & string}${SEPARATOR}${ExtractLiteralUnion>[0]>}` - : never, - ): SpeechModelV3; - speechModel( - id: KEY extends string ? `${KEY & string}${SEPARATOR}${string}` : never, - ): SpeechModelV3; - - rerankingModel( - id: KEY extends string - ? `${KEY & string}${SEPARATOR}${ExtractLiteralUnion>[0]>}` - : never, - ): RerankingModelV3; - rerankingModel( - id: KEY extends string ? `${KEY & string}${SEPARATOR}${string}` : never, - ): RerankingModelV3; -} - -/** - * Creates a registry for the given providers with optional middleware functionality. - * This function allows you to register multiple providers and optionally apply middleware - * to all language models from the registry, enabling you to transform parameters, wrap generate - * operations, and wrap stream operations for every language model accessed through the registry. - * - * @param providers - A record of provider instances to be registered in the registry. - * @param options - Configuration options for the provider registry. - * @param options.separator - The separator used between provider ID and model ID in the combined identifier. Defaults to ':'. - * @param options.languageModelMiddleware - Optional middleware to be applied to all language models from the registry. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model. - * @param options.imageModelMiddleware - Optional middleware to be applied to all image models from the registry. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model. - * @returns A new ProviderRegistryProvider instance that provides access to all registered providers with optional middleware applied to language and image models. - */ -export function createProviderRegistry< - PROVIDERS extends Record, - SEPARATOR extends string = ':', ->( - providers: PROVIDERS, - { - separator = ':' as SEPARATOR, - languageModelMiddleware, - imageModelMiddleware, - }: { - separator?: SEPARATOR; - languageModelMiddleware?: - | LanguageModelMiddleware - | LanguageModelMiddleware[]; - imageModelMiddleware?: ImageModelMiddleware | ImageModelMiddleware[]; - } = {}, -): ProviderRegistryProvider { - const registry = new DefaultProviderRegistry({ - separator, - languageModelMiddleware, - imageModelMiddleware, - }); - - for (const [id, provider] of Object.entries(providers)) { - registry.registerProvider({ id, provider } as { - id: keyof PROVIDERS; - provider: PROVIDERS[keyof PROVIDERS]; - }); - } - - return registry; -} - -/** - * @deprecated Use `createProviderRegistry` instead. - */ -export const experimental_createProviderRegistry = createProviderRegistry; - -class DefaultProviderRegistry< - PROVIDERS extends Record, - SEPARATOR extends string, -> implements ProviderRegistryProvider { - private providers: PROVIDERS = {} as PROVIDERS; - private separator: SEPARATOR; - private languageModelMiddleware?: - | LanguageModelMiddleware - | LanguageModelMiddleware[]; - private imageModelMiddleware?: ImageModelMiddleware | ImageModelMiddleware[]; - - constructor({ - separator, - languageModelMiddleware, - imageModelMiddleware, - }: { - separator: SEPARATOR; - languageModelMiddleware?: - | LanguageModelMiddleware - | LanguageModelMiddleware[]; - imageModelMiddleware?: ImageModelMiddleware | ImageModelMiddleware[]; - }) { - this.separator = separator; - this.languageModelMiddleware = languageModelMiddleware; - this.imageModelMiddleware = imageModelMiddleware; - } - - registerProvider({ - id, - provider, - }: { - id: K; - provider: PROVIDERS[K]; - }): void { - this.providers[id] = provider; - } - - private getProvider( - id: string, - modelType: - | 'languageModel' - | 'embeddingModel' - | 'imageModel' - | 'transcriptionModel' - | 'speechModel' - | 'rerankingModel', - ): ProviderV3 { - const provider = this.providers[id as keyof PROVIDERS]; - - if (provider == null) { - throw new NoSuchProviderError({ - modelId: id, - modelType, - providerId: id, - availableProviders: Object.keys(this.providers), - }); - } - - return provider; - } - - private splitId( - id: string, - modelType: - | 'languageModel' - | 'embeddingModel' - | 'imageModel' - | 'transcriptionModel' - | 'speechModel' - | 'rerankingModel', - ): [string, string] { - const index = id.indexOf(this.separator); - - if (index === -1) { - throw new NoSuchModelError({ - modelId: id, - modelType, - message: - `Invalid ${modelType} id for registry: ${id} ` + - `(must be in the format "providerId${this.separator}modelId")`, - }); - } - - return [id.slice(0, index), id.slice(index + this.separator.length)]; - } - - languageModel( - id: `${KEY & string}${SEPARATOR}${string}`, - ): LanguageModelV3 { - const [providerId, modelId] = this.splitId(id, 'languageModel'); - let model = this.getProvider(providerId, 'languageModel').languageModel?.( - modelId, - ); - - if (model == null) { - throw new NoSuchModelError({ modelId: id, modelType: 'languageModel' }); - } - - if (this.languageModelMiddleware != null) { - model = wrapLanguageModel({ - model, - middleware: this.languageModelMiddleware, - }); - } - - return model; - } - - embeddingModel( - id: `${KEY & string}${SEPARATOR}${string}`, - ): EmbeddingModelV3 { - const [providerId, modelId] = this.splitId(id, 'embeddingModel'); - const provider = this.getProvider(providerId, 'embeddingModel'); - - const model = provider.embeddingModel?.(modelId); - - if (model == null) { - throw new NoSuchModelError({ - modelId: id, - modelType: 'embeddingModel', - }); - } - - return model; - } - - imageModel( - id: `${KEY & string}${SEPARATOR}${string}`, - ): ImageModelV3 { - const [providerId, modelId] = this.splitId(id, 'imageModel'); - const provider = this.getProvider(providerId, 'imageModel'); - - let model = provider.imageModel?.(modelId); - - if (model == null) { - throw new NoSuchModelError({ modelId: id, modelType: 'imageModel' }); - } - - if (this.imageModelMiddleware != null) { - model = wrapImageModel({ - model, - middleware: this.imageModelMiddleware, - }); - } - - return model; - } - - transcriptionModel( - id: `${KEY & string}${SEPARATOR}${string}`, - ): TranscriptionModelV3 { - const [providerId, modelId] = this.splitId(id, 'transcriptionModel'); - const provider = this.getProvider(providerId, 'transcriptionModel'); - - const model = provider.transcriptionModel?.(modelId); - - if (model == null) { - throw new NoSuchModelError({ - modelId: id, - modelType: 'transcriptionModel', - }); - } - - return model; - } - - speechModel( - id: `${KEY & string}${SEPARATOR}${string}`, - ): SpeechModelV3 { - const [providerId, modelId] = this.splitId(id, 'speechModel'); - const provider = this.getProvider(providerId, 'speechModel'); - - const model = provider.speechModel?.(modelId); - - if (model == null) { - throw new NoSuchModelError({ modelId: id, modelType: 'speechModel' }); - } - - return model; - } - - rerankingModel( - id: `${KEY & string}${SEPARATOR}${string}`, - ): RerankingModelV3 { - const [providerId, modelId] = this.splitId(id, 'rerankingModel'); - const provider = this.getProvider(providerId, 'rerankingModel'); - - const model = provider.rerankingModel?.(modelId); - - if (model == null) { - throw new NoSuchModelError({ modelId: id, modelType: 'rerankingModel' }); - } - - return model; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/rerank/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/rerank/index.ts deleted file mode 100644 index 1864179fa..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/rerank/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { rerank } from './rerank'; -export type { RerankResult } from './rerank-result'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/rerank/rerank-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/rerank/rerank-result.ts deleted file mode 100644 index 3483d7fb0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/rerank/rerank-result.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { ProviderMetadata } from '../types/provider-metadata'; - -/** - * The result of a `rerank` call. - * It contains the original documents, the reranked documents, and additional information. - */ -export interface RerankResult { - /** - * The original documents that were reranked. - */ - readonly originalDocuments: Array; - - /** - * Reranked documents. - * - * Sorted by relevance score in descending order. - * - * Can be less than the original documents if there was a topN limit. - */ - readonly rerankedDocuments: Array; - - /** - * The ranking is a list of objects with the original index, - * relevance score, and the reranked document. - * - * Sorted by relevance score in descending order. - * - * Can be less than the original documents if there was a topN limit. - */ - readonly ranking: Array<{ - originalIndex: number; - score: number; - document: VALUE; - }>; - - /** - * Optional provider-specific metadata. - */ - readonly providerMetadata?: ProviderMetadata; - - /** - * Optional raw response data. - */ - readonly response: { - /** - * ID for the generated response if the provider sends one. - */ - id?: string; - - /** - * Timestamp of the generated response. - */ - timestamp: Date; - - /** - * The ID of the model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers. - */ - headers?: Record; - - /** - * The response body. - */ - body?: unknown; - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/rerank/rerank.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/rerank/rerank.ts deleted file mode 100644 index ae16110a5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/rerank/rerank.ts +++ /dev/null @@ -1,239 +0,0 @@ -import { JSONObject, RerankingModelV3CallOptions } from '@ai-sdk/provider'; -import { ProviderOptions } from '@ai-sdk/provider-utils'; -import { prepareRetries } from '../../src/util/prepare-retries'; -import { assembleOperationName } from '../telemetry/assemble-operation-name'; -import { getBaseTelemetryAttributes } from '../telemetry/get-base-telemetry-attributes'; -import { getTracer } from '../telemetry/get-tracer'; -import { recordSpan } from '../telemetry/record-span'; -import { selectTelemetryAttributes } from '../telemetry/select-telemetry-attributes'; -import { TelemetrySettings } from '../telemetry/telemetry-settings'; -import { RerankingModel } from '../types'; -import { RerankResult } from './rerank-result'; -import { logWarnings } from '../logger/log-warnings'; - -/** - * Rerank documents using a reranking model. The type of the value is defined by the reranking model. - * - * @param model - The reranking model to use. - * @param documents - The documents that should be reranked. - * @param query - The query to rerank the documents against. - * @param topN - Number of top documents to return. - * - * @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2. - * @param abortSignal - An optional abort signal that can be used to cancel the call. - * @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers. - * @param providerOptions - Additional provider-specific options. - * @param experimental_telemetry - Optional telemetry configuration (experimental). - * - * @returns A result object that contains the reranked documents, the reranked indices, and additional information. - */ -export async function rerank({ - model, - documents, - query, - topN, - maxRetries: maxRetriesArg, - abortSignal, - headers, - providerOptions, - experimental_telemetry: telemetry, -}: { - /** - * The reranking model to use. - */ - model: RerankingModel; - - /** - * The documents that should be reranked. - */ - documents: Array; - - /** - * The query to rerank the documents against. - */ - query: string; - - /** - * Number of top documents to return. - */ - topN?: number; - - /** - * Maximum number of retries per reranking model call. Set to 0 to disable retries. - * - * @default 2 - */ - maxRetries?: number; - - /** - * Abort signal. - */ - abortSignal?: AbortSignal; - - /** - * Additional headers to include in the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; - - /** - * Optional telemetry configuration (experimental). - */ - experimental_telemetry?: TelemetrySettings; - - /** - * Additional provider-specific options. They are passed through - * to the provider from the AI SDK and enable provider-specific - * functionality that can be fully encapsulated in the provider. - */ - providerOptions?: ProviderOptions; -}): Promise> { - if (documents.length === 0) { - return new DefaultRerankResult({ - originalDocuments: [], - ranking: [], - providerMetadata: undefined, - response: { - timestamp: new Date(), - modelId: model.modelId, - }, - }); - } - - const { maxRetries, retry } = prepareRetries({ - maxRetries: maxRetriesArg, - abortSignal, - }); - - // detect the type of the documents: - const documentsToSend: RerankingModelV3CallOptions['documents'] = - typeof documents[0] === 'string' - ? { type: 'text', values: documents as string[] } - : { type: 'object', values: documents as JSONObject[] }; - - const baseTelemetryAttributes = getBaseTelemetryAttributes({ - model, - telemetry, - headers, - settings: { maxRetries }, - }); - - const tracer = getTracer(telemetry); - - return recordSpan({ - name: 'ai.rerank', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ operationId: 'ai.rerank', telemetry }), - ...baseTelemetryAttributes, - 'ai.documents': { - input: () => documents.map(document => JSON.stringify(document)), - }, - }, - }), - tracer, - fn: async () => { - const { ranking, response, providerMetadata, warnings } = await retry( - () => - recordSpan({ - name: 'ai.rerank.doRerank', - attributes: selectTelemetryAttributes({ - telemetry, - attributes: { - ...assembleOperationName({ - operationId: 'ai.rerank.doRerank', - telemetry, - }), - ...baseTelemetryAttributes, - // specific settings that only make sense on the outer level: - 'ai.documents': { - input: () => - documents.map(document => JSON.stringify(document)), - }, - }, - }), - tracer, - fn: async doRerankSpan => { - const modelResponse = await model.doRerank({ - documents: documentsToSend, - query, - topN, - providerOptions, - abortSignal, - headers, - }); - - const ranking = modelResponse.ranking; - - doRerankSpan.setAttributes( - await selectTelemetryAttributes({ - telemetry, - attributes: { - 'ai.ranking.type': documentsToSend.type, - 'ai.ranking': { - output: () => - ranking.map(ranking => JSON.stringify(ranking)), - }, - }, - }), - ); - - return { - ranking, - providerMetadata: modelResponse.providerMetadata, - response: modelResponse.response, - warnings: modelResponse.warnings, - }; - }, - }), - ); - - logWarnings({ - warnings: warnings ?? [], - provider: model.provider, - model: model.modelId, - }); - - return new DefaultRerankResult({ - originalDocuments: documents, - ranking: ranking.map(ranking => ({ - originalIndex: ranking.index, - score: ranking.relevanceScore, - document: documents[ranking.index], - })), - providerMetadata, - response: { - id: response?.id, - timestamp: response?.timestamp ?? new Date(), - modelId: response?.modelId ?? model.modelId, - headers: response?.headers, - body: response?.body, - }, - }); - }, - }); -} - -class DefaultRerankResult implements RerankResult { - readonly originalDocuments: RerankResult['originalDocuments']; - readonly ranking: RerankResult['ranking']; - readonly response: RerankResult['response']; - readonly providerMetadata: RerankResult['providerMetadata']; - - constructor(options: { - originalDocuments: RerankResult['originalDocuments']; - ranking: RerankResult['ranking']; - providerMetadata?: RerankResult['providerMetadata']; - response: RerankResult['response']; - }) { - this.originalDocuments = options.originalDocuments; - this.ranking = options.ranking; - this.response = options.response; - this.providerMetadata = options.providerMetadata; - } - - get rerankedDocuments(): RerankResult['rerankedDocuments'] { - return this.ranking.map(ranking => ranking.document); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/assemble-operation-name.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/assemble-operation-name.ts deleted file mode 100644 index b19eed600..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/assemble-operation-name.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { TelemetrySettings } from './telemetry-settings'; - -export function assembleOperationName({ - operationId, - telemetry, -}: { - operationId: string; - telemetry?: TelemetrySettings; -}) { - return { - // standardized operation and resource name: - 'operation.name': `${operationId}${ - telemetry?.functionId != null ? ` ${telemetry.functionId}` : '' - }`, - 'resource.name': telemetry?.functionId, - - // detailed, AI SDK specific data: - 'ai.operationId': operationId, - 'ai.telemetry.functionId': telemetry?.functionId, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/get-base-telemetry-attributes.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/get-base-telemetry-attributes.ts deleted file mode 100644 index c45928e91..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/get-base-telemetry-attributes.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Attributes, AttributeValue } from '@opentelemetry/api'; -import { CallSettings, getTotalTimeoutMs } from '../prompt/call-settings'; -import { TelemetrySettings } from './telemetry-settings'; - -export function getBaseTelemetryAttributes({ - model, - settings, - telemetry, - headers, -}: { - model: { modelId: string; provider: string }; - settings: Omit; - telemetry: TelemetrySettings | undefined; - headers: Record | undefined; -}): Attributes { - return { - 'ai.model.provider': model.provider, - 'ai.model.id': model.modelId, - - // settings: - ...Object.entries(settings).reduce((attributes, [key, value]) => { - // Handle timeout specially since it can be a number or object - if (key === 'timeout') { - const totalTimeoutMs = getTotalTimeoutMs( - value as Parameters[0], - ); - if (totalTimeoutMs != null) { - attributes[`ai.settings.${key}`] = totalTimeoutMs; - } - } else { - attributes[`ai.settings.${key}`] = value as AttributeValue; - } - return attributes; - }, {} as Attributes), - - // add metadata as attributes: - ...Object.entries(telemetry?.metadata ?? {}).reduce( - (attributes, [key, value]) => { - attributes[`ai.telemetry.metadata.${key}`] = value; - return attributes; - }, - {} as Attributes, - ), - - // request headers - ...Object.entries(headers ?? {}).reduce((attributes, [key, value]) => { - if (value !== undefined) { - attributes[`ai.request.headers.${key}`] = value; - } - return attributes; - }, {} as Attributes), - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/get-global-telemetry-integration.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/get-global-telemetry-integration.ts deleted file mode 100644 index a5b610b6d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/get-global-telemetry-integration.ts +++ /dev/null @@ -1,85 +0,0 @@ -import type { Output } from '../generate-text/output'; -import type { ToolSet } from '../generate-text/tool-set'; -import { asArray } from '../util/as-array'; -import type { TelemetryIntegration } from './telemetry-integration'; -import { getGlobalTelemetryIntegrations } from './telemetry-integration-registry'; - -/** - * Wraps a telemetry integration with bound methods. - * Use this when creating class-based integrations to ensure methods - * work correctly when passed as callbacks. - */ -export function bindTelemetryIntegration( - integration: TelemetryIntegration, -): TelemetryIntegration { - return { - onStart: integration.onStart?.bind(integration), - onStepStart: integration.onStepStart?.bind(integration), - onToolCallStart: integration.onToolCallStart?.bind(integration), - onToolCallFinish: integration.onToolCallFinish?.bind(integration), - onStepFinish: integration.onStepFinish?.bind(integration), - onFinish: integration.onFinish?.bind(integration), - }; -} - -/** - * Creates a factory that merges globally registered integrations - * (via `registerTelemetryIntegration`) with per-call integrations - * into a single composite integration. - * - * Returns a factory function that accepts local integrations and - * returns the merged TelemetryIntegration. - */ -export function getGlobalTelemetryIntegration< - TOOLS extends ToolSet = ToolSet, - OUTPUT extends Output = Output, ->(): ( - integrations: TelemetryIntegration | Array | undefined, -) => TelemetryIntegration { - const globalIntegrations = getGlobalTelemetryIntegrations(); - - return ( - integrations: - | TelemetryIntegration - | Array - | undefined, - ): TelemetryIntegration => { - const localIntegrations = asArray(integrations); - const allIntegrations = [...globalIntegrations, ...localIntegrations]; - - function createTelemetryComposite( - getListenerFromIntegration: ( - integration: TelemetryIntegration, - ) => ((event: EVENT) => PromiseLike | void) | undefined, - ): ((event: EVENT) => Promise) | undefined { - const listeners = allIntegrations - .map(getListenerFromIntegration) - .filter(Boolean) as Array<(event: EVENT) => PromiseLike | void>; - - return async (event: EVENT) => { - for (const listener of listeners) { - try { - await listener(event); - } catch (_ignored) {} - } - }; - } - - return { - onStart: createTelemetryComposite(integration => integration.onStart), - onStepStart: createTelemetryComposite( - integration => integration.onStepStart, - ), - onToolCallStart: createTelemetryComposite( - integration => integration.onToolCallStart, - ), - onToolCallFinish: createTelemetryComposite( - integration => integration.onToolCallFinish, - ), - onStepFinish: createTelemetryComposite( - integration => integration.onStepFinish, - ), - onFinish: createTelemetryComposite(integration => integration.onFinish), - }; - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/get-tracer.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/get-tracer.ts deleted file mode 100644 index 7ed63286a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/get-tracer.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Tracer, trace } from '@opentelemetry/api'; -import { noopTracer } from './noop-tracer'; - -export function getTracer({ - isEnabled = false, - tracer, -}: { - isEnabled?: boolean; - tracer?: Tracer; -} = {}): Tracer { - if (!isEnabled) { - return noopTracer; - } - - if (tracer) { - return tracer; - } - - return trace.getTracer('ai'); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/index.ts deleted file mode 100644 index 71d82c274..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type { TelemetrySettings } from './telemetry-settings'; -export type { TelemetryIntegration } from './telemetry-integration'; -export { bindTelemetryIntegration } from './get-global-telemetry-integration'; -export { registerTelemetryIntegration } from './telemetry-integration-registry'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/noop-tracer.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/noop-tracer.ts deleted file mode 100644 index 2ddaa643b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/noop-tracer.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Span, SpanContext, Tracer } from '@opentelemetry/api'; - -/** - * Tracer implementation that does nothing (null object). - */ -export const noopTracer: Tracer = { - startSpan(): Span { - return noopSpan; - }, - - startActiveSpan unknown>( - name: unknown, - arg1: unknown, - arg2?: unknown, - arg3?: F, - ): ReturnType { - if (typeof arg1 === 'function') { - return arg1(noopSpan); - } - if (typeof arg2 === 'function') { - return arg2(noopSpan); - } - if (typeof arg3 === 'function') { - return arg3(noopSpan); - } - }, -}; - -const noopSpan: Span = { - spanContext() { - return noopSpanContext; - }, - setAttribute() { - return this; - }, - setAttributes() { - return this; - }, - addEvent() { - return this; - }, - addLink() { - return this; - }, - addLinks() { - return this; - }, - setStatus() { - return this; - }, - updateName() { - return this; - }, - end() { - return this; - }, - isRecording() { - return false; - }, - recordException() { - return this; - }, -}; - -const noopSpanContext: SpanContext = { - traceId: '', - spanId: '', - traceFlags: 0, -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/record-span.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/record-span.ts deleted file mode 100644 index d43bc3b57..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/record-span.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { - Attributes, - Span, - Tracer, - SpanStatusCode, - context, -} from '@opentelemetry/api'; - -export async function recordSpan({ - name, - tracer, - attributes, - fn, - endWhenDone = true, -}: { - name: string; - tracer: Tracer; - attributes: Attributes | PromiseLike; - fn: (span: Span) => Promise; - endWhenDone?: boolean; -}) { - return tracer.startActiveSpan( - name, - { attributes: await attributes }, - async span => { - // Capture the current context to maintain it across async generator yields - const ctx = context.active(); - - try { - // Execute within the captured context to ensure async generators - // don't lose the active span when they yield - const result = await context.with(ctx, () => fn(span)); - - if (endWhenDone) { - span.end(); - } - - return result; - } catch (error) { - try { - recordErrorOnSpan(span, error); - } finally { - // always stop the span when there is an error: - span.end(); - } - - throw error; - } - }, - ); -} - -/** - * Record an error on a span. Sets the span status to error. If the error is - * an instance of Error, an exception event with name, message, and stack - * will also be recorded. - * - * @param span - The span to record the error on. - * @param error - The error to record on the span. - */ -export function recordErrorOnSpan(span: Span, error: unknown) { - if (error instanceof Error) { - span.recordException({ - name: error.name, - message: error.message, - stack: error.stack, - }); - span.setStatus({ - code: SpanStatusCode.ERROR, - message: error.message, - }); - } else { - span.setStatus({ code: SpanStatusCode.ERROR }); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/select-telemetry-attributes.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/select-telemetry-attributes.ts deleted file mode 100644 index 091b4e43e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/select-telemetry-attributes.ts +++ /dev/null @@ -1,78 +0,0 @@ -import type { Attributes, AttributeValue } from '@opentelemetry/api'; -import type { TelemetrySettings } from './telemetry-settings'; - -type ResolvableAttributeValue = () => - | AttributeValue - | PromiseLike - | undefined; - -export async function selectTelemetryAttributes({ - telemetry, - attributes, -}: { - telemetry?: TelemetrySettings; - attributes: { - [attributeKey: string]: - | AttributeValue - | { input: ResolvableAttributeValue } - | { output: ResolvableAttributeValue } - | undefined; - }; -}): Promise { - // when telemetry is disabled, return an empty object to avoid serialization overhead: - if (telemetry?.isEnabled !== true) { - return {}; - } - - const resultAttributes: Attributes = {}; - - for (const [key, value] of Object.entries(attributes)) { - if (value == null) { - continue; - } - - // input value, check if it should be recorded: - if ( - typeof value === 'object' && - 'input' in value && - typeof value.input === 'function' - ) { - // default to true: - if (telemetry?.recordInputs === false) { - continue; - } - - const result = await value.input(); - - if (result != null) { - resultAttributes[key] = result; - } - - continue; - } - - // output value, check if it should be recorded: - if ( - typeof value === 'object' && - 'output' in value && - typeof value.output === 'function' - ) { - // default to true: - if (telemetry?.recordOutputs === false) { - continue; - } - - const result = await value.output(); - - if (result != null) { - resultAttributes[key] = result; - } - continue; - } - - // value is an attribute value already: - resultAttributes[key] = value as AttributeValue; - } - - return resultAttributes; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/stringify-for-telemetry.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/stringify-for-telemetry.ts deleted file mode 100644 index 6c6fe8e1b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/stringify-for-telemetry.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { - LanguageModelV3Message, - LanguageModelV3Prompt, -} from '@ai-sdk/provider'; -import { convertDataContentToBase64String } from '../prompt/data-content'; - -/** - * Helper utility to serialize prompt content for OpenTelemetry tracing. - * It is initially created because normalized LanguageModelV3Prompt carries - * images as Uint8Arrays, on which JSON.stringify acts weirdly, converting - * them to objects with stringified indices as keys, e.g. {"0": 42, "1": 69 }. - */ -export function stringifyForTelemetry(prompt: LanguageModelV3Prompt): string { - return JSON.stringify( - prompt.map((message: LanguageModelV3Message) => ({ - ...message, - content: - typeof message.content === 'string' - ? message.content - : message.content.map(part => - part.type === 'file' - ? { - ...part, - data: - part.data instanceof Uint8Array - ? convertDataContentToBase64String(part.data) - : part.data, - } - : part, - ), - })), - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/telemetry-integration-registry.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/telemetry-integration-registry.ts deleted file mode 100644 index 8b0266162..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/telemetry-integration-registry.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { TelemetryIntegration } from './telemetry-integration'; - -/** - * Registers a telemetry integration globally. - */ -export function registerTelemetryIntegration( - integration: TelemetryIntegration, -): void { - if (!globalThis.AI_SDK_TELEMETRY_INTEGRATIONS) { - globalThis.AI_SDK_TELEMETRY_INTEGRATIONS = []; - } - globalThis.AI_SDK_TELEMETRY_INTEGRATIONS.push(integration); -} - -export function getGlobalTelemetryIntegrations(): TelemetryIntegration[] { - return globalThis.AI_SDK_TELEMETRY_INTEGRATIONS ?? []; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/telemetry-integration.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/telemetry-integration.ts deleted file mode 100644 index 11d4eff80..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/telemetry-integration.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { - OnFinishEvent, - OnStartEvent, - OnStepFinishEvent, - OnStepStartEvent, - OnToolCallFinishEvent, - OnToolCallStartEvent, -} from '../generate-text/callback-events'; -import type { Output } from '../generate-text/output'; -import type { ToolSet } from '../generate-text/tool-set'; -import { Listener } from '../util/notify'; - -/** - * Implement this interface to create custom telemetry integrations. - * Methods can be sync or return a PromiseLike. - */ -export interface TelemetryIntegration { - onStart?: Listener>; - onStepStart?: Listener>; - onToolCallStart?: Listener>; - onToolCallFinish?: Listener>; - onStepFinish?: Listener>; - onFinish?: Listener>; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/telemetry-settings.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/telemetry-settings.ts deleted file mode 100644 index 66f0ce87c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/telemetry/telemetry-settings.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { AttributeValue, Tracer } from '@opentelemetry/api'; -import type { TelemetryIntegration } from './telemetry-integration'; - -/** - * Telemetry configuration. - */ -// This is meant to be both flexible for custom app requirements (metadata) -// and extensible for standardization (example: functionId, more to come). -export type TelemetrySettings = { - /** - * Enable or disable telemetry. Disabled by default while experimental. - */ - isEnabled?: boolean; - - /** - * Enable or disable input recording. Enabled by default. - * - * You might want to disable input recording to avoid recording sensitive - * information, to reduce data transfers, or to increase performance. - */ - recordInputs?: boolean; - - /** - * Enable or disable output recording. Enabled by default. - * - * You might want to disable output recording to avoid recording sensitive - * information, to reduce data transfers, or to increase performance. - */ - recordOutputs?: boolean; - - /** - * Identifier for this function. Used to group telemetry data by function. - */ - functionId?: string; - - /** - * Additional information to include in the telemetry data. - */ - metadata?: Record; - - /** - * A custom tracer to use for the telemetry data. - */ - tracer?: Tracer; - - /** - * Per-call telemetry integrations that receive lifecycle events during generation. - * - * These integrations run after any globally registered integrations - * (see `registerTelemetryIntegration`). - */ - integrations?: TelemetryIntegration | TelemetryIntegration[]; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-embedding-model-v2.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-embedding-model-v2.ts deleted file mode 100644 index 0dccd1734..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-embedding-model-v2.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { EmbeddingModelV2 } from '@ai-sdk/provider'; -import { notImplemented } from './not-implemented'; - -export class MockEmbeddingModelV2 implements EmbeddingModelV2 { - readonly specificationVersion = 'v2'; - - readonly provider: EmbeddingModelV2['provider']; - readonly modelId: EmbeddingModelV2['modelId']; - readonly maxEmbeddingsPerCall: EmbeddingModelV2['maxEmbeddingsPerCall']; - readonly supportsParallelCalls: EmbeddingModelV2['supportsParallelCalls']; - - doEmbed: EmbeddingModelV2['doEmbed']; - - constructor({ - provider = 'mock-provider', - modelId = 'mock-model-id', - maxEmbeddingsPerCall = 1, - supportsParallelCalls = false, - doEmbed = notImplemented, - }: { - provider?: EmbeddingModelV2['provider']; - modelId?: EmbeddingModelV2['modelId']; - maxEmbeddingsPerCall?: - | EmbeddingModelV2['maxEmbeddingsPerCall'] - | null; - supportsParallelCalls?: EmbeddingModelV2['supportsParallelCalls']; - doEmbed?: EmbeddingModelV2['doEmbed']; - } = {}) { - this.provider = provider; - this.modelId = modelId; - this.maxEmbeddingsPerCall = maxEmbeddingsPerCall ?? undefined; - this.supportsParallelCalls = supportsParallelCalls; - this.doEmbed = doEmbed; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-embedding-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-embedding-model-v3.ts deleted file mode 100644 index 14f54e087..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-embedding-model-v3.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { EmbeddingModelV3 } from '@ai-sdk/provider'; -import { notImplemented } from './not-implemented'; - -export class MockEmbeddingModelV3 implements EmbeddingModelV3 { - readonly specificationVersion = 'v3'; - - readonly provider: EmbeddingModelV3['provider']; - readonly modelId: EmbeddingModelV3['modelId']; - readonly maxEmbeddingsPerCall: EmbeddingModelV3['maxEmbeddingsPerCall']; - readonly supportsParallelCalls: EmbeddingModelV3['supportsParallelCalls']; - - doEmbed: EmbeddingModelV3['doEmbed']; - - doEmbedCalls: Parameters[0][] = []; - - constructor({ - provider = 'mock-provider', - modelId = 'mock-model-id', - maxEmbeddingsPerCall = 1, - supportsParallelCalls = false, - doEmbed = notImplemented, - }: { - provider?: EmbeddingModelV3['provider']; - modelId?: EmbeddingModelV3['modelId']; - maxEmbeddingsPerCall?: EmbeddingModelV3['maxEmbeddingsPerCall'] | null; - supportsParallelCalls?: EmbeddingModelV3['supportsParallelCalls']; - doEmbed?: - | EmbeddingModelV3['doEmbed'] - | Awaited> - | Awaited>[]; - } = {}) { - this.provider = provider; - this.modelId = modelId; - this.maxEmbeddingsPerCall = maxEmbeddingsPerCall ?? undefined; - this.supportsParallelCalls = supportsParallelCalls; - this.doEmbed = async options => { - this.doEmbedCalls.push(options); - - if (typeof doEmbed === 'function') { - return doEmbed(options); - } else if (Array.isArray(doEmbed)) { - return doEmbed[this.doEmbedCalls.length]; - } else { - return doEmbed; - } - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-image-model-v2.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-image-model-v2.ts deleted file mode 100644 index 73876b4c4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-image-model-v2.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ImageModelV2 } from '@ai-sdk/provider'; -import { notImplemented } from './not-implemented'; - -export class MockImageModelV2 implements ImageModelV2 { - readonly specificationVersion = 'v2'; - readonly provider: ImageModelV2['provider']; - readonly modelId: ImageModelV2['modelId']; - readonly maxImagesPerCall: ImageModelV2['maxImagesPerCall']; - - doGenerate: ImageModelV2['doGenerate']; - - constructor({ - provider = 'mock-provider', - modelId = 'mock-model-id', - maxImagesPerCall = 1, - doGenerate = notImplemented, - }: { - provider?: ImageModelV2['provider']; - modelId?: ImageModelV2['modelId']; - maxImagesPerCall?: ImageModelV2['maxImagesPerCall']; - doGenerate?: ImageModelV2['doGenerate']; - } = {}) { - this.provider = provider; - this.modelId = modelId; - this.maxImagesPerCall = maxImagesPerCall; - this.doGenerate = doGenerate; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-image-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-image-model-v3.ts deleted file mode 100644 index 96d599abd..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-image-model-v3.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ImageModelV3 } from '@ai-sdk/provider'; -import { notImplemented } from './not-implemented'; - -export class MockImageModelV3 implements ImageModelV3 { - readonly specificationVersion = 'v3'; - readonly provider: ImageModelV3['provider']; - readonly modelId: ImageModelV3['modelId']; - readonly maxImagesPerCall: ImageModelV3['maxImagesPerCall']; - - doGenerate: ImageModelV3['doGenerate']; - - constructor({ - provider = 'mock-provider', - modelId = 'mock-model-id', - maxImagesPerCall = 1, - doGenerate = notImplemented, - }: { - provider?: ImageModelV3['provider']; - modelId?: ImageModelV3['modelId']; - maxImagesPerCall?: ImageModelV3['maxImagesPerCall']; - doGenerate?: ImageModelV3['doGenerate']; - } = {}) { - this.provider = provider; - this.modelId = modelId; - this.maxImagesPerCall = maxImagesPerCall; - this.doGenerate = doGenerate; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-language-model-v2.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-language-model-v2.ts deleted file mode 100644 index 3bfc3bc63..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-language-model-v2.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { LanguageModelV2 } from '@ai-sdk/provider'; -import { notImplemented } from './not-implemented'; - -export class MockLanguageModelV2 implements LanguageModelV2 { - readonly specificationVersion = 'v2'; - - private _supportedUrls: () => LanguageModelV2['supportedUrls']; - - readonly provider: LanguageModelV2['provider']; - readonly modelId: LanguageModelV2['modelId']; - - doGenerate: LanguageModelV2['doGenerate']; - doStream: LanguageModelV2['doStream']; - - doGenerateCalls: Parameters[0][] = []; - doStreamCalls: Parameters[0][] = []; - - constructor({ - provider = 'mock-provider', - modelId = 'mock-model-id', - supportedUrls = {}, - doGenerate = notImplemented, - doStream = notImplemented, - }: { - provider?: LanguageModelV2['provider']; - modelId?: LanguageModelV2['modelId']; - supportedUrls?: - | LanguageModelV2['supportedUrls'] - | (() => LanguageModelV2['supportedUrls']); - doGenerate?: - | LanguageModelV2['doGenerate'] - | Awaited> - | Awaited>[]; - doStream?: - | LanguageModelV2['doStream'] - | Awaited> - | Awaited>[]; - } = {}) { - this.provider = provider; - this.modelId = modelId; - this.doGenerate = async options => { - this.doGenerateCalls.push(options); - - if (typeof doGenerate === 'function') { - return doGenerate(options); - } else if (Array.isArray(doGenerate)) { - return doGenerate[this.doGenerateCalls.length]; - } else { - return doGenerate; - } - }; - this.doStream = async options => { - this.doStreamCalls.push(options); - - if (typeof doStream === 'function') { - return doStream(options); - } else if (Array.isArray(doStream)) { - return doStream[this.doStreamCalls.length]; - } else { - return doStream; - } - }; - this._supportedUrls = - typeof supportedUrls === 'function' - ? supportedUrls - : async () => supportedUrls; - } - - get supportedUrls() { - return this._supportedUrls(); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-language-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-language-model-v3.ts deleted file mode 100644 index 4c78ab279..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-language-model-v3.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { - LanguageModelV3, - LanguageModelV3CallOptions, - LanguageModelV3GenerateResult, - LanguageModelV3StreamResult, -} from '@ai-sdk/provider'; -import { notImplemented } from './not-implemented'; - -export class MockLanguageModelV3 implements LanguageModelV3 { - readonly specificationVersion = 'v3'; - - private _supportedUrls: () => LanguageModelV3['supportedUrls']; - - readonly provider: LanguageModelV3['provider']; - readonly modelId: LanguageModelV3['modelId']; - - doGenerate: LanguageModelV3['doGenerate']; - doStream: LanguageModelV3['doStream']; - - doGenerateCalls: LanguageModelV3CallOptions[] = []; - doStreamCalls: LanguageModelV3CallOptions[] = []; - - constructor({ - provider = 'mock-provider', - modelId = 'mock-model-id', - supportedUrls = {}, - doGenerate = notImplemented, - doStream = notImplemented, - }: { - provider?: LanguageModelV3['provider']; - modelId?: LanguageModelV3['modelId']; - supportedUrls?: - | LanguageModelV3['supportedUrls'] - | (() => LanguageModelV3['supportedUrls']); - doGenerate?: - | LanguageModelV3['doGenerate'] - | LanguageModelV3GenerateResult - | LanguageModelV3GenerateResult[]; - doStream?: - | LanguageModelV3['doStream'] - | LanguageModelV3StreamResult - | LanguageModelV3StreamResult[]; - } = {}) { - this.provider = provider; - this.modelId = modelId; - this.doGenerate = async options => { - this.doGenerateCalls.push(options); - - if (typeof doGenerate === 'function') { - return doGenerate(options); - } else if (Array.isArray(doGenerate)) { - return doGenerate[this.doGenerateCalls.length]; - } else { - return doGenerate; - } - }; - this.doStream = async options => { - this.doStreamCalls.push(options); - - if (typeof doStream === 'function') { - return doStream(options); - } else if (Array.isArray(doStream)) { - return doStream[this.doStreamCalls.length]; - } else { - return doStream; - } - }; - this._supportedUrls = - typeof supportedUrls === 'function' - ? supportedUrls - : async () => supportedUrls; - } - - get supportedUrls() { - return this._supportedUrls(); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-provider-v2.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-provider-v2.ts deleted file mode 100644 index fc238dce7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-provider-v2.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { - EmbeddingModelV2, - ImageModelV2, - LanguageModelV2, - NoSuchModelError, - ProviderV2, - SpeechModelV2, - TranscriptionModelV2, -} from '@ai-sdk/provider'; - -export class MockProviderV2 implements ProviderV2 { - languageModel: ProviderV2['languageModel']; - textEmbeddingModel: ProviderV2['textEmbeddingModel']; - imageModel: ProviderV2['imageModel']; - transcriptionModel: ProviderV2['transcriptionModel']; - speechModel: ProviderV2['speechModel']; - - constructor({ - languageModels, - embeddingModels, - imageModels, - transcriptionModels, - speechModels, - }: { - languageModels?: Record; - embeddingModels?: Record>; - imageModels?: Record; - transcriptionModels?: Record; - speechModels?: Record; - } = {}) { - this.languageModel = (modelId: string) => { - if (!languageModels?.[modelId]) { - throw new NoSuchModelError({ modelId, modelType: 'languageModel' }); - } - return languageModels[modelId]; - }; - this.textEmbeddingModel = (modelId: string) => { - if (!embeddingModels?.[modelId]) { - throw new NoSuchModelError({ - modelId, - modelType: 'textEmbeddingModel' as any, // backwards compatibility - }); - } - return embeddingModels[modelId]; - }; - this.imageModel = (modelId: string) => { - if (!imageModels?.[modelId]) { - throw new NoSuchModelError({ modelId, modelType: 'imageModel' }); - } - return imageModels[modelId]; - }; - this.transcriptionModel = (modelId: string) => { - if (!transcriptionModels?.[modelId]) { - throw new NoSuchModelError({ - modelId, - modelType: 'transcriptionModel', - }); - } - return transcriptionModels[modelId]; - }; - this.speechModel = (modelId: string) => { - if (!speechModels?.[modelId]) { - throw new NoSuchModelError({ modelId, modelType: 'speechModel' }); - } - return speechModels[modelId]; - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-provider-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-provider-v3.ts deleted file mode 100644 index 79175eca8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-provider-v3.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { - EmbeddingModelV3, - ImageModelV3, - LanguageModelV3, - NoSuchModelError, - ProviderV3, - SpeechModelV3, - TranscriptionModelV3, - RerankingModelV3, -} from '@ai-sdk/provider'; - -export class MockProviderV3 implements ProviderV3 { - readonly specificationVersion = 'v3' as const; - - languageModel: ProviderV3['languageModel']; - embeddingModel: ProviderV3['embeddingModel']; - imageModel: ProviderV3['imageModel']; - transcriptionModel: ProviderV3['transcriptionModel']; - speechModel: ProviderV3['speechModel']; - rerankingModel: ProviderV3['rerankingModel']; - - constructor({ - languageModels, - embeddingModels, - imageModels, - transcriptionModels, - speechModels, - rerankingModels, - }: { - languageModels?: Record; - embeddingModels?: Record; - imageModels?: Record; - transcriptionModels?: Record; - speechModels?: Record; - rerankingModels?: Record; - } = {}) { - this.languageModel = (modelId: string) => { - if (!languageModels?.[modelId]) { - throw new NoSuchModelError({ modelId, modelType: 'languageModel' }); - } - return languageModels[modelId]; - }; - this.embeddingModel = (modelId: string) => { - if (!embeddingModels?.[modelId]) { - throw new NoSuchModelError({ - modelId, - modelType: 'embeddingModel', - }); - } - return embeddingModels[modelId]; - }; - this.imageModel = (modelId: string) => { - if (!imageModels?.[modelId]) { - throw new NoSuchModelError({ modelId, modelType: 'imageModel' }); - } - return imageModels[modelId]; - }; - this.transcriptionModel = (modelId: string) => { - if (!transcriptionModels?.[modelId]) { - throw new NoSuchModelError({ - modelId, - modelType: 'transcriptionModel', - }); - } - return transcriptionModels[modelId]; - }; - this.speechModel = (modelId: string): SpeechModelV3 => { - if (!speechModels?.[modelId]) { - throw new NoSuchModelError({ modelId, modelType: 'speechModel' }); - } - return speechModels[modelId]; - }; - this.rerankingModel = (modelId: string) => { - if (!rerankingModels?.[modelId]) { - throw new NoSuchModelError({ modelId, modelType: 'rerankingModel' }); - } - return rerankingModels[modelId]; - }; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-reranking-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-reranking-model-v3.ts deleted file mode 100644 index 4523ae8b2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-reranking-model-v3.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { RerankingModelV3 } from '@ai-sdk/provider'; -import { notImplemented } from './not-implemented'; - -export class MockRerankingModelV3 implements RerankingModelV3 { - readonly specificationVersion = 'v3'; - - readonly provider: RerankingModelV3['provider']; - readonly modelId: RerankingModelV3['modelId']; - - doRerank: RerankingModelV3['doRerank']; - - constructor({ - provider = 'mock-provider', - modelId = 'mock-model-id', - doRerank = notImplemented, - }: { - provider?: RerankingModelV3['provider']; - modelId?: RerankingModelV3['modelId']; - doRerank?: RerankingModelV3['doRerank']; - } = {}) { - this.provider = provider; - this.modelId = modelId; - this.doRerank = doRerank; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-server-response.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-server-response.ts deleted file mode 100644 index d4cf05123..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-server-response.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { EventEmitter } from 'node:events'; -import { ServerResponse } from 'node:http'; - -class MockServerResponse extends EventEmitter { - writtenChunks: any[] = []; - headers: Record = {}; - statusCode = 0; - statusMessage = ''; - ended = false; - - write(chunk: any): boolean { - this.writtenChunks.push(chunk); - return true; - } - - end(): void { - this.ended = true; - } - - writeHead( - statusCode: number, - arg2: string | Record, - arg3?: Record, - ): void { - this.statusCode = statusCode; - - if (typeof arg2 === 'string') { - this.statusMessage = arg2; - this.headers = arg3 ?? {}; - } else { - this.statusMessage = ''; - this.headers = arg2; - } - } - - get body() { - // Combine all written chunks into a single string - return this.writtenChunks.join(''); - } - - /** - * Get the decoded chunks as strings. - */ - getDecodedChunks() { - const decoder = new TextDecoder(); - return this.writtenChunks.map(chunk => decoder.decode(chunk)); - } - - /** - * Wait for the stream to finish writing to the mock response. - */ - async waitForEnd() { - await new Promise(resolve => { - const checkIfEnded = () => { - if (this.ended) { - resolve(undefined); - } else { - setImmediate(checkIfEnded); - } - }; - checkIfEnded(); - }); - } -} - -export function createMockServerResponse(): ServerResponse & - MockServerResponse { - return new MockServerResponse() as ServerResponse & MockServerResponse; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-speech-model-v2.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-speech-model-v2.ts deleted file mode 100644 index 61794b1b2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-speech-model-v2.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { SpeechModelV2 } from '@ai-sdk/provider'; -import { notImplemented } from './not-implemented'; - -export class MockSpeechModelV2 implements SpeechModelV2 { - readonly specificationVersion = 'v2'; - readonly provider: SpeechModelV2['provider']; - readonly modelId: SpeechModelV2['modelId']; - - doGenerate: SpeechModelV2['doGenerate']; - - constructor({ - provider = 'mock-provider', - modelId = 'mock-model-id', - doGenerate = notImplemented, - }: { - provider?: SpeechModelV2['provider']; - modelId?: SpeechModelV2['modelId']; - doGenerate?: SpeechModelV2['doGenerate']; - } = {}) { - this.provider = provider; - this.modelId = modelId; - this.doGenerate = doGenerate; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-speech-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-speech-model-v3.ts deleted file mode 100644 index 3152728ac..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-speech-model-v3.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { SpeechModelV3 } from '@ai-sdk/provider'; -import { notImplemented } from './not-implemented'; - -export class MockSpeechModelV3 implements SpeechModelV3 { - readonly specificationVersion = 'v3'; - readonly provider: SpeechModelV3['provider']; - readonly modelId: SpeechModelV3['modelId']; - - doGenerate: SpeechModelV3['doGenerate']; - - constructor({ - provider = 'mock-provider', - modelId = 'mock-model-id', - doGenerate = notImplemented, - }: { - provider?: SpeechModelV3['provider']; - modelId?: SpeechModelV3['modelId']; - doGenerate?: SpeechModelV3['doGenerate']; - } = {}) { - this.provider = provider; - this.modelId = modelId; - this.doGenerate = doGenerate; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-tracer.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-tracer.ts deleted file mode 100644 index 931dcb39b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-tracer.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { - AttributeValue, - Attributes, - Context, - Exception, - Span, - SpanContext, - SpanOptions, - SpanStatus, - TimeInput, - Tracer, -} from '@opentelemetry/api'; - -export class MockTracer implements Tracer { - spans: MockSpan[] = []; - - get jsonSpans() { - return this.spans.map(span => ({ - name: span.name, - attributes: span.attributes, - events: span.events, - ...(span.status && { status: span.status }), - })); - } - - startSpan(name: string, options?: SpanOptions, context?: Context): Span { - const span = new MockSpan({ - name, - options, - context, - }); - this.spans.push(span); - return span; - } - - startActiveSpan unknown>( - name: string, - arg1: unknown, - arg2?: unknown, - arg3?: F, - ): ReturnType { - if (typeof arg1 === 'function') { - const span = new MockSpan({ - name, - }); - this.spans.push(span); - return arg1(span); - } - if (typeof arg2 === 'function') { - const span = new MockSpan({ - name, - options: arg1 as SpanOptions, - }); - this.spans.push(span); - return arg2(span); - } - if (typeof arg3 === 'function') { - const span = new MockSpan({ - name, - options: arg1 as SpanOptions, - context: arg2 as Context, - }); - this.spans.push(span); - return arg3(span); - } - } -} - -class MockSpan implements Span { - name: string; - context?: Context; - options?: SpanOptions; - attributes: Attributes; - events: Array<{ - name: string; - attributes: Attributes | undefined; - time?: [number, number]; - }> = []; - status?: SpanStatus; - - readonly _spanContext: SpanContext = new MockSpanContext(); - - constructor({ - name, - options, - context, - }: { - name: string; - options?: SpanOptions; - context?: Context; - }) { - this.name = name; - this.context = context; - this.options = options; - this.attributes = options?.attributes ?? {}; - } - - spanContext(): SpanContext { - return this._spanContext; - } - - setAttribute(key: string, value: AttributeValue): this { - this.attributes = { ...this.attributes, [key]: value }; - return this; - } - - setAttributes(attributes: Attributes): this { - this.attributes = { ...this.attributes, ...attributes }; - return this; - } - - addEvent(name: string, attributes?: Attributes): this { - this.events.push({ name, attributes }); - return this; - } - - addLink() { - return this; - } - addLinks() { - return this; - } - setStatus(status: SpanStatus) { - this.status = status; - return this; - } - updateName() { - return this; - } - end() { - return this; - } - isRecording() { - return false; - } - recordException(exception: Exception, time?: TimeInput) { - const error = - typeof exception === 'string' ? new Error(exception) : exception; - this.events.push({ - name: 'exception', - attributes: { - 'exception.type': error.constructor?.name || 'Error', - 'exception.name': error.name || 'Error', - 'exception.message': error.message || '', - 'exception.stack': error.stack || '', - }, - time: Array.isArray(time) ? time : [0, 0], - }); - } -} - -class MockSpanContext implements SpanContext { - traceId = 'test-trace-id'; - spanId = 'test-span-id'; - traceFlags = 0; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-transcription-model-v2.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-transcription-model-v2.ts deleted file mode 100644 index 087bca51d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-transcription-model-v2.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TranscriptionModelV2 } from '@ai-sdk/provider'; -import { notImplemented } from './not-implemented'; - -export class MockTranscriptionModelV2 implements TranscriptionModelV2 { - readonly specificationVersion = 'v2'; - readonly provider: TranscriptionModelV2['provider']; - readonly modelId: TranscriptionModelV2['modelId']; - - doGenerate: TranscriptionModelV2['doGenerate']; - - constructor({ - provider = 'mock-provider', - modelId = 'mock-model-id', - doGenerate = notImplemented, - }: { - provider?: TranscriptionModelV2['provider']; - modelId?: TranscriptionModelV2['modelId']; - doGenerate?: TranscriptionModelV2['doGenerate']; - } = {}) { - this.provider = provider; - this.modelId = modelId; - this.doGenerate = doGenerate; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-transcription-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-transcription-model-v3.ts deleted file mode 100644 index 434274e75..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-transcription-model-v3.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TranscriptionModelV3 } from '@ai-sdk/provider'; -import { notImplemented } from './not-implemented'; - -export class MockTranscriptionModelV3 implements TranscriptionModelV3 { - readonly specificationVersion = 'v3'; - readonly provider: TranscriptionModelV3['provider']; - readonly modelId: TranscriptionModelV3['modelId']; - - doGenerate: TranscriptionModelV3['doGenerate']; - - constructor({ - provider = 'mock-provider', - modelId = 'mock-model-id', - doGenerate = notImplemented, - }: { - provider?: TranscriptionModelV3['provider']; - modelId?: TranscriptionModelV3['modelId']; - doGenerate?: TranscriptionModelV3['doGenerate']; - } = {}) { - this.provider = provider; - this.modelId = modelId; - this.doGenerate = doGenerate; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-values.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-values.ts deleted file mode 100644 index bcf5f14da..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-values.ts +++ /dev/null @@ -1,4 +0,0 @@ -export function mockValues(...values: T[]): () => T { - let counter = 0; - return () => values[counter++] ?? values[values.length - 1]; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-video-model-v3.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-video-model-v3.ts deleted file mode 100644 index 514b8e279..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/mock-video-model-v3.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Experimental_VideoModelV3 } from '@ai-sdk/provider'; -import { notImplemented } from './not-implemented'; - -export class MockVideoModelV3 implements Experimental_VideoModelV3 { - readonly specificationVersion = 'v3'; - readonly provider: Experimental_VideoModelV3['provider']; - readonly modelId: Experimental_VideoModelV3['modelId']; - readonly maxVideosPerCall: Experimental_VideoModelV3['maxVideosPerCall']; - - doGenerate: Experimental_VideoModelV3['doGenerate']; - - constructor({ - provider = 'mock-provider', - modelId = 'mock-model-id', - maxVideosPerCall = 1, - doGenerate = notImplemented, - }: { - provider?: Experimental_VideoModelV3['provider']; - modelId?: Experimental_VideoModelV3['modelId']; - maxVideosPerCall?: Experimental_VideoModelV3['maxVideosPerCall']; - doGenerate?: Experimental_VideoModelV3['doGenerate']; - } = {}) { - this.provider = provider; - this.modelId = modelId; - this.maxVideosPerCall = maxVideosPerCall; - this.doGenerate = doGenerate; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/not-implemented.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/not-implemented.ts deleted file mode 100644 index cc9d2bb0d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/test/not-implemented.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function notImplemented(): never { - throw new Error('Not implemented'); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/text-stream/create-text-stream-response.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/text-stream/create-text-stream-response.ts deleted file mode 100644 index c900dbe3f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/text-stream/create-text-stream-response.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { prepareHeaders } from '../util/prepare-headers'; - -/** - * Creates a Response object from a text stream. - * Each text chunk is encoded as UTF-8 and sent as a separate chunk. - * Sets a `Content-Type` header to `text/plain; charset=utf-8`. - * - * @param options - The options for creating the response. - * @param options.status - Optional HTTP status code (default: 200). - * @param options.statusText - Optional HTTP status text. - * @param options.headers - Optional response headers. - * @param options.textStream - The text stream to send. - * @returns A Response object with the text stream body. - */ -export function createTextStreamResponse({ - status, - statusText, - headers, - textStream, -}: ResponseInit & { - textStream: ReadableStream; -}): Response { - return new Response(textStream.pipeThrough(new TextEncoderStream()), { - status: status ?? 200, - statusText, - headers: prepareHeaders(headers, { - 'content-type': 'text/plain; charset=utf-8', - }), - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/text-stream/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/text-stream/index.ts deleted file mode 100644 index cad64485a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/text-stream/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { createTextStreamResponse } from './create-text-stream-response'; -export { pipeTextStreamToResponse } from './pipe-text-stream-to-response'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/text-stream/pipe-text-stream-to-response.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/text-stream/pipe-text-stream-to-response.ts deleted file mode 100644 index 9f5e7ae70..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/text-stream/pipe-text-stream-to-response.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { ServerResponse } from 'node:http'; -import { prepareHeaders } from '../util/prepare-headers'; -import { writeToServerResponse } from '../util/write-to-server-response'; - -/** - * Writes a text stream to a Node.js ServerResponse object. - * Each text chunk is encoded as UTF-8 and written as a separate chunk. - * Sets a `Content-Type` header to `text/plain; charset=utf-8`. - * - * @param options - The options for piping the stream. - * @param options.response - The Node.js ServerResponse to write to. - * @param options.status - Optional HTTP status code. - * @param options.statusText - Optional HTTP status text. - * @param options.headers - Optional response headers. - * @param options.textStream - The text stream to pipe. - */ -export function pipeTextStreamToResponse({ - response, - status, - statusText, - headers, - textStream, -}: { - response: ServerResponse; - textStream: ReadableStream; -} & ResponseInit): void { - writeToServerResponse({ - response, - status, - statusText, - headers: Object.fromEntries( - prepareHeaders(headers, { - 'content-type': 'text/plain; charset=utf-8', - }).entries(), - ), - stream: textStream.pipeThrough(new TextEncoderStream()), - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/transcribe/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/transcribe/index.ts deleted file mode 100644 index 596a3d8b7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/transcribe/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { transcribe as experimental_transcribe } from './transcribe'; -export type { TranscriptionResult as Experimental_TranscriptionResult } from './transcribe-result'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/transcribe/transcribe-result.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/transcribe/transcribe-result.ts deleted file mode 100644 index bc4981655..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/transcribe/transcribe-result.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { JSONObject } from '@ai-sdk/provider'; -import { TranscriptionModelResponseMetadata } from '../types/transcription-model-response-metadata'; -import { Warning } from '../types/warning'; - -/** - * The result of a `transcribe` call. - * It contains the transcript and additional information. - */ -export interface TranscriptionResult { - /** - * The complete transcribed text from the audio. - */ - readonly text: string; - - /** - * Array of transcript segments with timing information. - * Each segment represents a portion of the transcribed text with start and end times. - */ - readonly segments: Array<{ - /** - * The text content of this segment. - */ - readonly text: string; - /** - * The start time of this segment in seconds. - */ - readonly startSecond: number; - /** - * The end time of this segment in seconds. - */ - readonly endSecond: number; - }>; - - /** - * The detected language of the audio content, as an ISO-639-1 code (e.g., 'en' for English). - * May be undefined if the language couldn't be detected. - */ - readonly language: string | undefined; - - /** - * The total duration of the audio file in seconds. - * May be undefined if the duration couldn't be determined. - */ - readonly durationInSeconds: number | undefined; - - /** - * Warnings for the call, e.g. unsupported settings. - */ - readonly warnings: Array; - - /** - * Response metadata from the provider. There may be multiple responses if we made multiple calls to the model. - */ - readonly responses: Array; - - /** - * Provider metadata from the provider. - */ - readonly providerMetadata: Record; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/transcribe/transcribe.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/transcribe/transcribe.ts deleted file mode 100644 index c142597b2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/transcribe/transcribe.ts +++ /dev/null @@ -1,187 +0,0 @@ -import { JSONObject } from '@ai-sdk/provider'; -import { ProviderOptions, withUserAgentSuffix } from '@ai-sdk/provider-utils'; -import { NoTranscriptGeneratedError } from '../error/no-transcript-generated-error'; -import { logWarnings } from '../logger/log-warnings'; -import { DataContent } from '../prompt'; -import { convertDataContentToUint8Array } from '../prompt/data-content'; -import { TranscriptionModel } from '../types/transcription-model'; -import { TranscriptionModelResponseMetadata } from '../types/transcription-model-response-metadata'; -import { - audioMediaTypeSignatures, - detectMediaType, -} from '../util/detect-media-type'; -import { createDownload } from '../util/download/create-download'; -import { prepareRetries } from '../util/prepare-retries'; -import { TranscriptionResult } from './transcribe-result'; -import { VERSION } from '../version'; -import { resolveTranscriptionModel } from '../model/resolve-model'; -import { Warning } from '../types'; -/** - * Generates transcripts using a transcription model. - * - * @param model - The transcription model to use. - * @param audio - The audio data to transcribe as DataContent (string | Uint8Array | ArrayBuffer | Buffer) or a URL. - * @param providerOptions - Additional provider-specific options that are passed through to the provider - * as body parameters. - * @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2. - * @param abortSignal - An optional abort signal that can be used to cancel the call. - * @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers. - * - * @returns A result object that contains the generated transcript. - */ -const defaultDownload = createDownload(); - -export async function transcribe({ - model, - audio, - providerOptions = {}, - maxRetries: maxRetriesArg, - abortSignal, - headers, - download: downloadFn = defaultDownload, -}: { - /** - * The transcription model to use. - */ - model: TranscriptionModel; - - /** - * The audio data to transcribe. - */ - audio: DataContent | URL; - - /** - * Additional provider-specific options that are passed through to the provider - * as body parameters. - * - * The outer record is keyed by the provider name, and the inner - * record is keyed by the provider-specific metadata key. - * ```ts - * { - * "openai": { - * "temperature": 0 - * } - * } - * ``` - */ - providerOptions?: ProviderOptions; - - /** - * Maximum number of retries per transcript model call. Set to 0 to disable retries. - * - * @default 2 - */ - maxRetries?: number; - - /** - * Abort signal. - */ - abortSignal?: AbortSignal; - - /** - * Additional headers to include in the request. - * Only applicable for HTTP-based providers. - */ - headers?: Record; - - /** - * Custom download function for fetching audio from URLs. - * Use `createDownload()` from `ai` to create a download function with custom size limits. - * - * @default createDownload() (2 GiB limit) - */ - download?: (options: { - url: URL; - abortSignal?: AbortSignal; - }) => Promise<{ data: Uint8Array; mediaType: string | undefined }>; -}): Promise { - const resolvedModel = resolveTranscriptionModel(model); - if (!resolvedModel) { - throw new Error('Model could not be resolved'); - } - - const { retry } = prepareRetries({ - maxRetries: maxRetriesArg, - abortSignal, - }); - - const headersWithUserAgent = withUserAgentSuffix( - headers ?? {}, - `ai/${VERSION}`, - ); - - const audioData = - audio instanceof URL - ? (await downloadFn({ url: audio, abortSignal })).data - : convertDataContentToUint8Array(audio); - - const result = await retry(() => - resolvedModel.doGenerate({ - audio: audioData, - abortSignal, - headers: headersWithUserAgent, - providerOptions, - mediaType: - detectMediaType({ - data: audioData, - signatures: audioMediaTypeSignatures, - }) ?? 'audio/wav', - }), - ); - - logWarnings({ - warnings: result.warnings, - provider: resolvedModel.provider, - model: resolvedModel.modelId, - }); - - if (!result.text) { - throw new NoTranscriptGeneratedError({ responses: [result.response] }); - } - - return new DefaultTranscriptionResult({ - text: result.text, - segments: result.segments, - language: result.language, - durationInSeconds: result.durationInSeconds, - warnings: result.warnings, - responses: [result.response], - providerMetadata: result.providerMetadata, - }); -} - -class DefaultTranscriptionResult implements TranscriptionResult { - readonly text: string; - readonly segments: Array<{ - text: string; - startSecond: number; - endSecond: number; - }>; - readonly language: string | undefined; - readonly durationInSeconds: number | undefined; - readonly warnings: Array; - readonly responses: Array; - readonly providerMetadata: Record; - - constructor(options: { - text: string; - segments: Array<{ - text: string; - startSecond: number; - endSecond: number; - }>; - language: string | undefined; - durationInSeconds: number | undefined; - warnings: Array; - responses: Array; - providerMetadata: Record | undefined; - }) { - this.text = options.text; - this.segments = options.segments; - this.language = options.language; - this.durationInSeconds = options.durationInSeconds; - this.warnings = options.warnings; - this.responses = options.responses; - this.providerMetadata = options.providerMetadata ?? {}; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/embedding-model-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/embedding-model-middleware.ts deleted file mode 100644 index 1023fbfc1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/embedding-model-middleware.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { EmbeddingModelV3Middleware } from '@ai-sdk/provider'; - -export type EmbeddingModelMiddleware = EmbeddingModelV3Middleware; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/embedding-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/embedding-model.ts deleted file mode 100644 index 91a63bb7a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/embedding-model.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { - EmbeddingModelV2, - EmbeddingModelV3, - EmbeddingModelV3Embedding, -} from '@ai-sdk/provider'; - -/** - * Embedding model that is used by the AI SDK. - */ -export type EmbeddingModel = - | string - | EmbeddingModelV3 - | EmbeddingModelV2; - -/** - * Embedding. - */ -export type Embedding = EmbeddingModelV3Embedding; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/image-model-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/image-model-middleware.ts deleted file mode 100644 index 701449385..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/image-model-middleware.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { ImageModelV3Middleware } from '@ai-sdk/provider'; - -export type ImageModelMiddleware = ImageModelV3Middleware; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/image-model-response-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/image-model-response-metadata.ts deleted file mode 100644 index 518cdcfe7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/image-model-response-metadata.ts +++ /dev/null @@ -1,16 +0,0 @@ -export type ImageModelResponseMetadata = { - /** - * Timestamp for the start of the generated response. - */ - timestamp: Date; - - /** - * The ID of the response model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers. - */ - headers?: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/image-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/image-model.ts deleted file mode 100644 index 83fd71465..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/image-model.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { - ImageModelV2, - ImageModelV3, - ImageModelV3ProviderMetadata, - ImageModelV2ProviderMetadata, -} from '@ai-sdk/provider'; - -/** - * Image model that is used by the AI SDK. - */ -export type ImageModel = string | ImageModelV3 | ImageModelV2; - -/** - * Metadata from the model provider for this call. - */ -// TODO should this be v3 only? -export type ImageModelProviderMetadata = - | ImageModelV3ProviderMetadata - | ImageModelV2ProviderMetadata; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/index.ts deleted file mode 100644 index d276556cb..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -export type { JSONSchema7 } from '@ai-sdk/provider'; -export type { Embedding, EmbeddingModel } from './embedding-model'; -export type { EmbeddingModelMiddleware } from './embedding-model-middleware'; -export type { ImageModel, ImageModelProviderMetadata } from './image-model'; -export type { ImageModelMiddleware } from './image-model-middleware'; -export type { ImageModelResponseMetadata } from './image-model-response-metadata'; -export type { JSONValue } from './json-value'; -export type { - CallWarning, - FinishReason, - LanguageModel, - ToolChoice, -} from './language-model'; -export type { LanguageModelMiddleware } from './language-model-middleware'; -export type { LanguageModelRequestMetadata } from './language-model-request-metadata'; -export type { LanguageModelResponseMetadata } from './language-model-response-metadata'; -export type { Provider } from './provider'; -export type { ProviderMetadata } from './provider-metadata'; -export type { RerankingModel } from './reranking-model'; -export type { SpeechModel } from './speech-model'; -export type { SpeechModelResponseMetadata } from './speech-model-response-metadata'; -export type { TranscriptionModel } from './transcription-model'; -export type { TranscriptionModelResponseMetadata } from './transcription-model-response-metadata'; -export type { - EmbeddingModelUsage, - ImageModelUsage, - LanguageModelUsage, -} from './usage'; -export type { Warning } from './warning'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/json-value.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/json-value.ts deleted file mode 100644 index 05994543a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/json-value.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { JSONValue as OriginalJSONValue } from '@ai-sdk/provider'; -import { z } from 'zod/v4'; - -export const jsonValueSchema: z.ZodType = z.lazy(() => - z.union([ - z.null(), - z.string(), - z.number(), - z.boolean(), - z.record(z.string(), jsonValueSchema.optional()), - z.array(jsonValueSchema), - ]), -); - -export type JSONValue = OriginalJSONValue; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/language-model-middleware.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/language-model-middleware.ts deleted file mode 100644 index 2b96d0f29..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/language-model-middleware.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { LanguageModelV3Middleware } from '@ai-sdk/provider'; - -export type LanguageModelMiddleware = LanguageModelV3Middleware; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/language-model-request-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/language-model-request-metadata.ts deleted file mode 100644 index 84a09a9c1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/language-model-request-metadata.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type LanguageModelRequestMetadata = { - /** - * Request HTTP body that was sent to the provider API. - */ - body?: unknown; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/language-model-response-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/language-model-response-metadata.ts deleted file mode 100644 index c8bcc9138..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/language-model-response-metadata.ts +++ /dev/null @@ -1,21 +0,0 @@ -export type LanguageModelResponseMetadata = { - /** - * ID for the generated response. - */ - id: string; - - /** - * Timestamp for the start of the generated response. - */ - timestamp: Date; - - /** - * The ID of the response model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers (available only for providers that use HTTP requests). - */ - headers?: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/language-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/language-model.ts deleted file mode 100644 index e12fd988b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/language-model.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { GatewayModelId } from '@ai-sdk/gateway'; -import { - LanguageModelV2, - LanguageModelV3, - SharedV3Warning, - LanguageModelV3Source, -} from '@ai-sdk/provider'; - -declare global { - /** - * Global interface that can be augmented by third-party packages to register custom model IDs. - * - * You can register model IDs in two ways: - * - * 1. Register based on Model IDs from a provider package: - * @example - * ```typescript - * import { openai } from '@ai-sdk/openai'; - * type OpenAIResponsesModelId = Parameters[0]; - * - * declare global { - * interface RegisteredProviderModels { - * openai: OpenAIResponsesModelId; - * } - * } - * ``` - * - * 2. Register individual model IDs directly as keys: - * @example - * ```typescript - * declare global { - * interface RegisteredProviderModels { - * 'my-provider:my-model': any; - * 'my-provider:another-model': any; - * } - * } - * ``` - */ - interface RegisteredProviderModels {} -} - -/** - * Global provider model ID type that defaults to GatewayModelId but can be augmented - * by third-party packages via declaration merging. - */ -export type GlobalProviderModelId = [keyof RegisteredProviderModels] extends [ - never, -] - ? GatewayModelId - : - | keyof RegisteredProviderModels - | RegisteredProviderModels[keyof RegisteredProviderModels]; - -/** - * Language model that is used by the AI SDK. - */ -export type LanguageModel = - | GlobalProviderModelId - | LanguageModelV3 - | LanguageModelV2; - -/** - * Reason why a language model finished generating a response. - * - * Can be one of the following: - * - `stop`: model generated stop sequence - * - `length`: model generated maximum number of tokens - * - `content-filter`: content filter violation stopped the model - * - `tool-calls`: model triggered tool calls - * - `error`: model stopped because of an error - * - `other`: model stopped for other reasons - */ -export type FinishReason = - | 'stop' - | 'length' - | 'content-filter' - | 'tool-calls' - | 'error' - | 'other'; - -/** - * Warning from the model provider for this call. The call will proceed, but e.g. - * some settings might not be supported, which can lead to suboptimal results. - */ -export type CallWarning = SharedV3Warning; - -/** - * A source that has been used as input to generate the response. - */ -export type Source = LanguageModelV3Source; - -/** - * Tool choice for the generation. It supports the following settings: - * - * - `auto` (default): the model can choose whether and which tools to call. - * - `required`: the model must call a tool. It can choose which tool to call. - * - `none`: the model must not call tools - * - `{ type: 'tool', toolName: string (typed) }`: the model must call the specified tool - */ -export type ToolChoice> = - | 'auto' - | 'none' - | 'required' - | { type: 'tool'; toolName: Extract }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/provider-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/provider-metadata.ts deleted file mode 100644 index f9039a051..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/provider-metadata.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { SharedV3ProviderMetadata } from '@ai-sdk/provider'; -import { z } from 'zod/v4'; -import { jsonValueSchema } from './json-value'; - -/** - * Additional provider-specific metadata that is returned from the provider. - * - * This is needed to enable provider-specific functionality that can be - * fully encapsulated in the provider. - */ -export type ProviderMetadata = SharedV3ProviderMetadata; - -export const providerMetadataSchema: z.ZodType = z.record( - z.string(), - z.record(z.string(), jsonValueSchema.optional()), -); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/provider.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/provider.ts deleted file mode 100644 index 1f0dd4c1d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/provider.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { EmbeddingModel } from './embedding-model'; -import { LanguageModel } from './language-model'; -import { ImageModel } from './image-model'; -import { RerankingModel } from './reranking-model'; - -/** - * Provider for language, text embedding, and image models. - */ -export type Provider = { - /** - * Returns the language model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {LanguageModel} The language model associated with the id - * - * @throws {NoSuchModelError} If no such model exists. - */ - languageModel(modelId: string): LanguageModel; - - /** - * Returns the text embedding model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {EmbeddingModel} The embedding model associated with the id - * - * @throws {NoSuchModelError} If no such model exists. - */ - embeddingModel(modelId: string): EmbeddingModel; - - /** - * Returns the image model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {ImageModel} The image model associated with the id - */ - imageModel(modelId: string): ImageModel; - - /** - * Returns the reranking model with the given id. - * The model id is then passed to the provider function to get the model. - * - * @param {string} modelId - The id of the model to return. - * - * @returns {RerankingModel} The reranking model associated with the id - * - * @throws {NoSuchModelError} If no such model exists. - */ - rerankingModel(modelId: string): RerankingModel; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/reranking-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/reranking-model.ts deleted file mode 100644 index 77304b596..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/reranking-model.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { RerankingModelV3 } from '@ai-sdk/provider'; - -/** - * Reranking model that is used by the AI SDK. - */ -export type RerankingModel = RerankingModelV3; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/speech-model-response-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/speech-model-response-metadata.ts deleted file mode 100644 index 6f3bb099b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/speech-model-response-metadata.ts +++ /dev/null @@ -1,21 +0,0 @@ -export type SpeechModelResponseMetadata = { - /** - * Timestamp for the start of the generated response. - */ - timestamp: Date; - - /** - * The ID of the response model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers. - */ - headers?: Record; - - /** - * Response body. - */ - body?: unknown; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/speech-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/speech-model.ts deleted file mode 100644 index 6674636f2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/speech-model.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { SpeechModelV2, SpeechModelV3 } from '@ai-sdk/provider'; - -/** - * Speech model that is used by the AI SDK. - */ -export type SpeechModel = string | SpeechModelV3 | SpeechModelV2; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/transcription-model-response-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/transcription-model-response-metadata.ts deleted file mode 100644 index 8259665af..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/transcription-model-response-metadata.ts +++ /dev/null @@ -1,16 +0,0 @@ -export type TranscriptionModelResponseMetadata = { - /** - * Timestamp for the start of the generated response. - */ - timestamp: Date; - - /** - * The ID of the response model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers. - */ - headers?: Record; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/transcription-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/transcription-model.ts deleted file mode 100644 index c7151d49c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/transcription-model.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { TranscriptionModelV2, TranscriptionModelV3 } from '@ai-sdk/provider'; - -/** - * Transcription model that is used by the AI SDK. - */ -export type TranscriptionModel = - | string - | TranscriptionModelV3 - | TranscriptionModelV2; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/usage.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/usage.ts deleted file mode 100644 index 986ab013c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/usage.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { - ImageModelV3Usage, - JSONObject, - LanguageModelV3Usage, -} from '@ai-sdk/provider'; - -/** - * Represents the number of tokens used in a prompt and completion. - */ -export type LanguageModelUsage = { - /** - * The total number of input (prompt) tokens used. - */ - inputTokens: number | undefined; - - /** - * Detailed information about the input tokens. - */ - inputTokenDetails: { - /** - * The number of non-cached input (prompt) tokens used. - */ - noCacheTokens: number | undefined; - - /** - * The number of cached input (prompt) tokens read. - */ - cacheReadTokens: number | undefined; - - /** - * The number of cached input (prompt) tokens written. - */ - cacheWriteTokens: number | undefined; - }; - - /** - * The number of total output (completion) tokens used. - */ - outputTokens: number | undefined; - - /** - * Detailed information about the output tokens. - */ - outputTokenDetails: { - /** - * The number of text tokens used. - */ - textTokens: number | undefined; - - /** - * The number of reasoning tokens used. - */ - reasoningTokens: number | undefined; - }; - - /** - * The total number of tokens used. - */ - totalTokens: number | undefined; - - /** - * @deprecated Use outputTokenDetails.reasoningTokens instead. - */ - reasoningTokens?: number | undefined; - - /** - * @deprecated Use inputTokenDetails.cacheReadTokens instead. - */ - cachedInputTokens?: number | undefined; - - /** - * Raw usage information from the provider. - * - * This is the usage information in the shape that the provider returns. - * It can include additional information that is not part of the standard usage information. - */ - raw?: JSONObject; -}; - -/** - * Represents the number of tokens used in an embedding. - */ -// TODO replace with EmbeddingModelV3Usage -export type EmbeddingModelUsage = { - /** - * The number of tokens used in the embedding. - */ - tokens: number; -}; - -export function asLanguageModelUsage( - usage: LanguageModelV3Usage, -): LanguageModelUsage { - return { - inputTokens: usage.inputTokens.total, - inputTokenDetails: { - noCacheTokens: usage.inputTokens.noCache, - cacheReadTokens: usage.inputTokens.cacheRead, - cacheWriteTokens: usage.inputTokens.cacheWrite, - }, - outputTokens: usage.outputTokens.total, - outputTokenDetails: { - textTokens: usage.outputTokens.text, - reasoningTokens: usage.outputTokens.reasoning, - }, - totalTokens: addTokenCounts( - usage.inputTokens.total, - usage.outputTokens.total, - ), - raw: usage.raw, - reasoningTokens: usage.outputTokens.reasoning, - cachedInputTokens: usage.inputTokens.cacheRead, - }; -} - -export function createNullLanguageModelUsage(): LanguageModelUsage { - return { - inputTokens: undefined, - inputTokenDetails: { - noCacheTokens: undefined, - cacheReadTokens: undefined, - cacheWriteTokens: undefined, - }, - outputTokens: undefined, - outputTokenDetails: { - textTokens: undefined, - reasoningTokens: undefined, - }, - totalTokens: undefined, - raw: undefined, - }; -} - -export function addLanguageModelUsage( - usage1: LanguageModelUsage, - usage2: LanguageModelUsage, -): LanguageModelUsage { - return { - inputTokens: addTokenCounts(usage1.inputTokens, usage2.inputTokens), - inputTokenDetails: { - noCacheTokens: addTokenCounts( - usage1.inputTokenDetails?.noCacheTokens, - usage2.inputTokenDetails?.noCacheTokens, - ), - cacheReadTokens: addTokenCounts( - usage1.inputTokenDetails?.cacheReadTokens, - usage2.inputTokenDetails?.cacheReadTokens, - ), - cacheWriteTokens: addTokenCounts( - usage1.inputTokenDetails?.cacheWriteTokens, - usage2.inputTokenDetails?.cacheWriteTokens, - ), - }, - outputTokens: addTokenCounts(usage1.outputTokens, usage2.outputTokens), - outputTokenDetails: { - textTokens: addTokenCounts( - usage1.outputTokenDetails?.textTokens, - usage2.outputTokenDetails?.textTokens, - ), - reasoningTokens: addTokenCounts( - usage1.outputTokenDetails?.reasoningTokens, - usage2.outputTokenDetails?.reasoningTokens, - ), - }, - totalTokens: addTokenCounts(usage1.totalTokens, usage2.totalTokens), - reasoningTokens: addTokenCounts( - usage1.reasoningTokens, - usage2.reasoningTokens, - ), - cachedInputTokens: addTokenCounts( - usage1.cachedInputTokens, - usage2.cachedInputTokens, - ), - }; -} - -function addTokenCounts( - tokenCount1: number | undefined, - tokenCount2: number | undefined, -): number | undefined { - return tokenCount1 == null && tokenCount2 == null - ? undefined - : (tokenCount1 ?? 0) + (tokenCount2 ?? 0); -} - -/** - * Usage information for an image model call. - */ -export type ImageModelUsage = ImageModelV3Usage; - -export function addImageModelUsage( - usage1: ImageModelUsage, - usage2: ImageModelUsage, -): ImageModelUsage { - return { - inputTokens: addTokenCounts(usage1.inputTokens, usage2.inputTokens), - outputTokens: addTokenCounts(usage1.outputTokens, usage2.outputTokens), - totalTokens: addTokenCounts(usage1.totalTokens, usage2.totalTokens), - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/video-model-response-metadata.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/video-model-response-metadata.ts deleted file mode 100644 index ac8da49d4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/video-model-response-metadata.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { SharedV3ProviderMetadata } from '@ai-sdk/provider'; - -/** - * Response metadata for a video model call. - */ -export type VideoModelResponseMetadata = { - /** - * Timestamp for the start of the generated response. - */ - timestamp: Date; - - /** - * The ID of the response model that was used to generate the response. - */ - modelId: string; - - /** - * Response headers. - */ - headers?: Record; - - /** - * Provider-specific metadata for this call. - * When multiple calls are made (n > maxVideosPerCall), each response - * contains its own providerMetadata, allowing lossless per-call access. - */ - providerMetadata?: SharedV3ProviderMetadata; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/video-model.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/video-model.ts deleted file mode 100644 index 0362ef21f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/video-model.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { - Experimental_VideoModelV3, - SharedV3ProviderMetadata, -} from '@ai-sdk/provider'; - -/** - * A video model can be a string (model ID) or a Experimental_VideoModelV3 object. - */ -export type VideoModel = string | Experimental_VideoModelV3; - -export type VideoModelProviderMetadata = SharedV3ProviderMetadata; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/warning.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/warning.ts deleted file mode 100644 index f18691732..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/types/warning.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { SharedV3Warning } from '@ai-sdk/provider'; - -/** - * Warning from the model provider for this call. The call will proceed, but e.g. - * some settings might not be supported, which can lead to suboptimal results. - */ -export type Warning = SharedV3Warning; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/create-ui-message-stream-response.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/create-ui-message-stream-response.ts deleted file mode 100644 index 05f24c4cb..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/create-ui-message-stream-response.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { prepareHeaders } from '../util/prepare-headers'; -import { JsonToSseTransformStream } from './json-to-sse-transform-stream'; -import { UI_MESSAGE_STREAM_HEADERS } from './ui-message-stream-headers'; -import { UIMessageChunk } from './ui-message-chunks'; -import { UIMessageStreamResponseInit } from './ui-message-stream-response-init'; - -/** - * Creates a Response object from a UI message stream. - * The stream is transformed to Server-Sent Events (SSE) format. - * - * @param options.status - The HTTP status code for the response. - * @param options.statusText - The HTTP status text for the response. - * @param options.headers - Additional HTTP headers to include in the response. - * @param options.stream - The UI message chunk stream to send. - * @param options.consumeSseStream - Optional callback to consume a copy of the SSE stream independently. - * - * @returns A `Response` object with the UI message stream as the body. - */ -export function createUIMessageStreamResponse({ - status, - statusText, - headers, - stream, - consumeSseStream, -}: UIMessageStreamResponseInit & { - stream: ReadableStream; -}): Response { - let sseStream = stream.pipeThrough(new JsonToSseTransformStream()); - - // when the consumeSseStream is provided, we need to tee the stream - // and send the second part to the consumeSseStream function - // so that it can be consumed by the client independently - if (consumeSseStream) { - const [stream1, stream2] = sseStream.tee(); - sseStream = stream1; - consumeSseStream({ stream: stream2 }); // no await (do not block the response) - } - - return new Response(sseStream.pipeThrough(new TextEncoderStream()), { - status, - statusText, - headers: prepareHeaders(headers, UI_MESSAGE_STREAM_HEADERS), - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/create-ui-message-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/create-ui-message-stream.ts deleted file mode 100644 index c49797da2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/create-ui-message-stream.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { - generateId as generateIdFunc, - getErrorMessage, - IdGenerator, -} from '@ai-sdk/provider-utils'; -import { UIMessage } from '../ui/ui-messages'; -import { handleUIMessageStreamFinish } from './handle-ui-message-stream-finish'; -import { InferUIMessageChunk } from './ui-message-chunks'; -import { UIMessageStreamOnFinishCallback } from './ui-message-stream-on-finish-callback'; -import { UIMessageStreamOnStepFinishCallback } from './ui-message-stream-on-step-finish-callback'; -import { UIMessageStreamWriter } from './ui-message-stream-writer'; - -/** - * Creates a UI message stream that can be used to send messages to the client. - * - * @param options.execute - A function that is called with a writer to write UI message chunks to the stream. - * @param options.onError - A function that extracts an error message from an error. Defaults to `getErrorMessage`. - * @param options.originalMessages - The original messages. If provided, persistence mode is assumed - * and a message ID is provided for the response message. - * @param options.onStepFinish - A callback that is called when each step finishes. Useful for persisting intermediate messages. - * @param options.onFinish - A callback that is called when the stream finishes. - * @param options.generateId - A function that generates a unique ID. Defaults to the built-in ID generator. - * - * @returns A `ReadableStream` of UI message chunks. - */ -export function createUIMessageStream({ - execute, - onError = getErrorMessage, - originalMessages, - onStepFinish, - onFinish, - generateId = generateIdFunc, -}: { - execute: (options: { - writer: UIMessageStreamWriter; - }) => Promise | void; - onError?: (error: unknown) => string; - - /** - * The original messages. If they are provided, persistence mode is assumed, - * and a message ID is provided for the response message. - */ - originalMessages?: UI_MESSAGE[]; - - /** - * Callback that is called when each step finishes during multi-step agent runs. - */ - onStepFinish?: UIMessageStreamOnStepFinishCallback; - - onFinish?: UIMessageStreamOnFinishCallback; - - generateId?: IdGenerator; -}): ReadableStream> { - let controller!: ReadableStreamDefaultController< - InferUIMessageChunk - >; - - const ongoingStreamPromises: Promise[] = []; - - const stream = new ReadableStream({ - start(controllerArg) { - controller = controllerArg; - }, - }); - - function safeEnqueue(data: InferUIMessageChunk) { - try { - controller.enqueue(data); - } catch (error) { - // suppress errors when the stream has been closed - } - } - - try { - const result = execute({ - writer: { - write(part: InferUIMessageChunk) { - safeEnqueue(part); - }, - merge(streamArg) { - ongoingStreamPromises.push( - (async () => { - const reader = streamArg.getReader(); - while (true) { - const { done, value } = await reader.read(); - if (done) break; - safeEnqueue(value); - } - })().catch(error => { - safeEnqueue({ - type: 'error', - errorText: onError(error), - } as InferUIMessageChunk); - }), - ); - }, - onError, - }, - }); - - if (result) { - ongoingStreamPromises.push( - result.catch(error => { - safeEnqueue({ - type: 'error', - errorText: onError(error), - } as InferUIMessageChunk); - }), - ); - } - } catch (error) { - safeEnqueue({ - type: 'error', - errorText: onError(error), - } as InferUIMessageChunk); - } - - // Wait until all ongoing streams are done. This approach enables merging - // streams even after execute has returned, as long as there is still an - // open merged stream. This is important to e.g. forward new streams and - // from callbacks. - const waitForStreams: Promise = new Promise(async resolve => { - while (ongoingStreamPromises.length > 0) { - await ongoingStreamPromises.shift(); - } - resolve(); - }); - - waitForStreams.finally(() => { - try { - controller.close(); - } catch (error) { - // suppress errors when the stream has been closed - } - }); - - return handleUIMessageStreamFinish({ - stream, - messageId: generateId(), - originalMessages, - onStepFinish, - onFinish, - onError, - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/get-response-ui-message-id.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/get-response-ui-message-id.ts deleted file mode 100644 index a9bc71ac2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/get-response-ui-message-id.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { IdGenerator } from '@ai-sdk/provider-utils'; -import { UIMessage } from '../ui/ui-messages'; - -/** - * Determines the message ID to use for a response message. - * If the last message is an assistant message, its ID is reused (continuation). - * Otherwise, a new ID is generated or the provided ID is used. - * - * @param options.originalMessages - The original messages. If not provided, returns `undefined` - * since client-side ID generation is used in non-persistence mode. - * @param options.responseMessageId - The response message ID or an ID generator function. - * - * @returns The message ID to use, or `undefined` if no persistence mode. - */ -export function getResponseUIMessageId({ - originalMessages, - responseMessageId, -}: { - originalMessages: UIMessage[] | undefined; - responseMessageId: string | IdGenerator; -}) { - // when there are no original messages (i.e. no persistence), - // the assistant message id generation is handled on the client side. - if (originalMessages == null) { - return undefined; - } - - const lastMessage = originalMessages[originalMessages.length - 1]; - - return lastMessage?.role === 'assistant' - ? lastMessage.id - : typeof responseMessageId === 'function' - ? responseMessageId() - : responseMessageId; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/handle-ui-message-stream-finish.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/handle-ui-message-stream-finish.ts deleted file mode 100644 index d37f639f9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/handle-ui-message-stream-finish.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { - createStreamingUIMessageState, - processUIMessageStream, - StreamingUIMessageState, -} from '../ui/process-ui-message-stream'; -import { UIMessage } from '../ui/ui-messages'; -import { ErrorHandler } from '../util/error-handler'; -import { InferUIMessageChunk, UIMessageChunk } from './ui-message-chunks'; -import { UIMessageStreamOnFinishCallback } from './ui-message-stream-on-finish-callback'; -import { UIMessageStreamOnStepFinishCallback } from './ui-message-stream-on-step-finish-callback'; - -export function handleUIMessageStreamFinish({ - messageId, - originalMessages = [], - onStepFinish, - onFinish, - onError, - stream, -}: { - stream: ReadableStream>; - - /** - * The message ID to use for the response message. - * If not provided, no id will be set for the response message. - */ - messageId?: string; - - /** - * The original messages. - */ - originalMessages?: UI_MESSAGE[]; - - onError: ErrorHandler; - - /** - * Callback that is called when each step finishes during multi-step agent runs. - */ - onStepFinish?: UIMessageStreamOnStepFinishCallback; - - onFinish?: UIMessageStreamOnFinishCallback; -}): ReadableStream> { - // last message is only relevant for assistant messages - let lastMessage: UI_MESSAGE | undefined = - originalMessages?.[originalMessages.length - 1]; - if (lastMessage?.role !== 'assistant') { - lastMessage = undefined; - } else { - // appending to the last message, so we need to use the same id - messageId = lastMessage.id; - } - - let isAborted = false; - - const idInjectedStream = stream.pipeThrough( - new TransformStream< - InferUIMessageChunk, - InferUIMessageChunk - >({ - transform(chunk, controller) { - // when there is no messageId in the start chunk, - // but the user checked for persistence, - // inject the messageId into the chunk - if (chunk.type === 'start') { - const startChunk = chunk as UIMessageChunk & { type: 'start' }; - if (startChunk.messageId == null && messageId != null) { - startChunk.messageId = messageId; - } - } - - if (chunk.type === 'abort') { - isAborted = true; - } - - controller.enqueue(chunk); - }, - }), - ); - - // Only process the stream if we need to track state for callbacks - if (onFinish == null && onStepFinish == null) { - return idInjectedStream; - } - - const state = createStreamingUIMessageState({ - lastMessage: lastMessage - ? (structuredClone(lastMessage) as UI_MESSAGE) - : undefined, - messageId: messageId ?? '', // will be overridden by the stream - }); - - const runUpdateMessageJob = async ( - job: (options: { - state: StreamingUIMessageState; - write: () => void; - }) => Promise, - ) => { - await job({ state, write: () => {} }); - }; - - let finishCalled = false; - - const callOnFinish = async () => { - if (finishCalled || !onFinish) { - return; - } - finishCalled = true; - - const isContinuation = state.message.id === lastMessage?.id; - await onFinish({ - isAborted, - isContinuation, - responseMessage: state.message as UI_MESSAGE, - messages: [ - ...(isContinuation ? originalMessages.slice(0, -1) : originalMessages), - state.message, - ] as UI_MESSAGE[], - finishReason: state.finishReason, - }); - }; - - const callOnStepFinish = async () => { - if (!onStepFinish) { - return; - } - - const isContinuation = state.message.id === lastMessage?.id; - - try { - await onStepFinish({ - isContinuation, - responseMessage: structuredClone(state.message) as UI_MESSAGE, - messages: [ - ...(isContinuation - ? originalMessages.slice(0, -1) - : originalMessages), - structuredClone(state.message), - ] as UI_MESSAGE[], - }); - } catch (error) { - onError(error); - } - }; - - return processUIMessageStream({ - stream: idInjectedStream, - runUpdateMessageJob, - onError, - }).pipeThrough( - new TransformStream< - InferUIMessageChunk, - InferUIMessageChunk - >({ - async transform(chunk, controller) { - if (chunk.type === 'finish-step') { - await callOnStepFinish(); - } - - controller.enqueue(chunk); - }, - // @ts-expect-error cancel is still new and missing from types https://developer.mozilla.org/en-US/docs/Web/API/TransformStream#browser_compatibility - async cancel() { - await callOnFinish(); - }, - - async flush() { - await callOnFinish(); - }, - }), - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/index.ts deleted file mode 100644 index 48dd9208f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -export { createUIMessageStream } from './create-ui-message-stream'; -export { createUIMessageStreamResponse } from './create-ui-message-stream-response'; -export { JsonToSseTransformStream } from './json-to-sse-transform-stream'; -export { pipeUIMessageStreamToResponse } from './pipe-ui-message-stream-to-response'; -export { readUIMessageStream } from './read-ui-message-stream'; -export { - uiMessageChunkSchema, - type InferUIMessageChunk, - type UIMessageChunk, -} from './ui-message-chunks'; -export { UI_MESSAGE_STREAM_HEADERS } from './ui-message-stream-headers'; -export type { UIMessageStreamOnFinishCallback } from './ui-message-stream-on-finish-callback'; -export type { UIMessageStreamOnStepFinishCallback } from './ui-message-stream-on-step-finish-callback'; -export type { UIMessageStreamWriter } from './ui-message-stream-writer'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/json-to-sse-transform-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/json-to-sse-transform-stream.ts deleted file mode 100644 index e554e101f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/json-to-sse-transform-stream.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * A TransformStream that converts JSON objects to Server-Sent Events (SSE) format. - * Each object is serialized to JSON and wrapped in `data: ...\n\n` format. - * When the stream ends, a `data: [DONE]\n\n` message is sent. - */ -export class JsonToSseTransformStream extends TransformStream { - constructor() { - super({ - transform(part, controller) { - controller.enqueue(`data: ${JSON.stringify(part)}\n\n`); - }, - flush(controller) { - controller.enqueue('data: [DONE]\n\n'); - }, - }); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/pipe-ui-message-stream-to-response.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/pipe-ui-message-stream-to-response.ts deleted file mode 100644 index 99abe8def..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/pipe-ui-message-stream-to-response.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { ServerResponse } from 'node:http'; -import { prepareHeaders } from '../util/prepare-headers'; -import { writeToServerResponse } from '../util/write-to-server-response'; -import { JsonToSseTransformStream } from './json-to-sse-transform-stream'; -import { UI_MESSAGE_STREAM_HEADERS } from './ui-message-stream-headers'; -import { UIMessageChunk } from './ui-message-chunks'; -import { UIMessageStreamResponseInit } from './ui-message-stream-response-init'; - -/** - * Pipes a UI message stream to a Node.js ServerResponse object. - * The stream is transformed to Server-Sent Events (SSE) format. - * - * @param options.response - The Node.js ServerResponse object to write to. - * @param options.status - The HTTP status code for the response. - * @param options.statusText - The HTTP status text for the response. - * @param options.headers - Additional HTTP headers to include in the response. - * @param options.stream - The UI message chunk stream to send. - * @param options.consumeSseStream - Optional callback to consume a copy of the SSE stream independently. - */ -export function pipeUIMessageStreamToResponse({ - response, - status, - statusText, - headers, - stream, - consumeSseStream, -}: { - response: ServerResponse; - stream: ReadableStream; -} & UIMessageStreamResponseInit): void { - let sseStream = stream.pipeThrough(new JsonToSseTransformStream()); - - // when the consumeSseStream is provided, we need to tee the stream - // and send the second part to the consumeSseStream function - // so that it can be consumed by the client independently - if (consumeSseStream) { - const [stream1, stream2] = sseStream.tee(); - sseStream = stream1; - consumeSseStream({ stream: stream2 }); // no await (do not block the response) - } - - writeToServerResponse({ - response, - status, - statusText, - headers: Object.fromEntries( - prepareHeaders(headers, UI_MESSAGE_STREAM_HEADERS).entries(), - ), - stream: sseStream.pipeThrough(new TextEncoderStream()), - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/read-ui-message-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/read-ui-message-stream.ts deleted file mode 100644 index 0288bb41c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/read-ui-message-stream.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { UIMessage } from '../ui/ui-messages'; -import { UIMessageChunk } from './ui-message-chunks'; -import { - createStreamingUIMessageState, - processUIMessageStream, - StreamingUIMessageState, -} from '../ui/process-ui-message-stream'; -import { - AsyncIterableStream, - createAsyncIterableStream, -} from '../util/async-iterable-stream'; -import { consumeStream } from '../util/consume-stream'; - -/** - * Transforms a stream of `UIMessageChunk`s into an `AsyncIterableStream` of `UIMessage`s. - * - * @param options.message - The last assistant message to use as a starting point when the conversation is resumed. Otherwise undefined. - * @param options.stream - The stream of `UIMessageChunk`s to read. - * @param options.terminateOnError - Whether to terminate the stream if an error occurs. - * @param options.onError - A function that is called when an error occurs. - * - * @returns An `AsyncIterableStream` of `UIMessage`s. Each stream part is a different state of the same message - * as it is being completed. - */ -export function readUIMessageStream({ - message, - stream, - onError, - terminateOnError = false, -}: { - message?: UI_MESSAGE; - stream: ReadableStream; - onError?: (error: unknown) => void; - terminateOnError?: boolean; -}): AsyncIterableStream { - let controller: ReadableStreamDefaultController | undefined; - let hasErrored = false; - - const outputStream = new ReadableStream({ - start(controllerParam) { - controller = controllerParam; - }, - }); - - const state = createStreamingUIMessageState({ - messageId: message?.id ?? '', - lastMessage: message, - }); - - const handleError = (error: unknown) => { - onError?.(error); - - if (!hasErrored && terminateOnError) { - hasErrored = true; - controller?.error(error); - } - }; - - consumeStream({ - stream: processUIMessageStream({ - stream, - runUpdateMessageJob( - job: (options: { - state: StreamingUIMessageState; - write: () => void; - }) => Promise, - ) { - return job({ - state, - write: () => { - controller?.enqueue(structuredClone(state.message)); - }, - }); - }, - onError: handleError, - }), - onError: handleError, - }).finally(() => { - // Only close if no error occurred. Calling close() on an errored controller - // throws "Invalid state: Controller is already closed" TypeError. - if (!hasErrored) { - controller?.close(); - } - }); - - return createAsyncIterableStream(outputStream); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-chunks.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-chunks.ts deleted file mode 100644 index 726ecdf47..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-chunks.ts +++ /dev/null @@ -1,350 +0,0 @@ -import { z } from 'zod/v4'; -import { - ProviderMetadata, - providerMetadataSchema, -} from '../types/provider-metadata'; -import { FinishReason } from '../types/language-model'; -import { - InferUIMessageData, - InferUIMessageMetadata, - UIDataTypes, - UIMessage, -} from '../ui/ui-messages'; -import { ValueOf } from '../util/value-of'; -import { lazySchema, zodSchema } from '@ai-sdk/provider-utils'; - -export const uiMessageChunkSchema = lazySchema(() => - zodSchema( - z.union([ - z.strictObject({ - type: z.literal('text-start'), - id: z.string(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.strictObject({ - type: z.literal('text-delta'), - id: z.string(), - delta: z.string(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.strictObject({ - type: z.literal('text-end'), - id: z.string(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.strictObject({ - type: z.literal('error'), - errorText: z.string(), - }), - z.strictObject({ - type: z.literal('tool-input-start'), - toolCallId: z.string(), - toolName: z.string(), - providerExecuted: z.boolean().optional(), - providerMetadata: providerMetadataSchema.optional(), - dynamic: z.boolean().optional(), - title: z.string().optional(), - }), - z.strictObject({ - type: z.literal('tool-input-delta'), - toolCallId: z.string(), - inputTextDelta: z.string(), - }), - z.strictObject({ - type: z.literal('tool-input-available'), - toolCallId: z.string(), - toolName: z.string(), - input: z.unknown(), - providerExecuted: z.boolean().optional(), - providerMetadata: providerMetadataSchema.optional(), - dynamic: z.boolean().optional(), - title: z.string().optional(), - }), - z.strictObject({ - type: z.literal('tool-input-error'), - toolCallId: z.string(), - toolName: z.string(), - input: z.unknown(), - providerExecuted: z.boolean().optional(), - providerMetadata: providerMetadataSchema.optional(), - dynamic: z.boolean().optional(), - errorText: z.string(), - title: z.string().optional(), - }), - z.strictObject({ - type: z.literal('tool-approval-request'), - approvalId: z.string(), - toolCallId: z.string(), - }), - z.strictObject({ - type: z.literal('tool-output-available'), - toolCallId: z.string(), - output: z.unknown(), - providerExecuted: z.boolean().optional(), - providerMetadata: providerMetadataSchema.optional(), - dynamic: z.boolean().optional(), - preliminary: z.boolean().optional(), - }), - z.strictObject({ - type: z.literal('tool-output-error'), - toolCallId: z.string(), - errorText: z.string(), - providerExecuted: z.boolean().optional(), - providerMetadata: providerMetadataSchema.optional(), - dynamic: z.boolean().optional(), - }), - z.strictObject({ - type: z.literal('tool-output-denied'), - toolCallId: z.string(), - }), - z.strictObject({ - type: z.literal('reasoning-start'), - id: z.string(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.strictObject({ - type: z.literal('reasoning-delta'), - id: z.string(), - delta: z.string(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.strictObject({ - type: z.literal('reasoning-end'), - id: z.string(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.strictObject({ - type: z.literal('source-url'), - sourceId: z.string(), - url: z.string(), - title: z.string().optional(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.strictObject({ - type: z.literal('source-document'), - sourceId: z.string(), - mediaType: z.string(), - title: z.string(), - filename: z.string().optional(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.strictObject({ - type: z.literal('file'), - url: z.string(), - mediaType: z.string(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.strictObject({ - type: z.custom<`data-${string}`>( - (value): value is `data-${string}` => - typeof value === 'string' && value.startsWith('data-'), - { message: 'Type must start with "data-"' }, - ), - id: z.string().optional(), - data: z.unknown(), - transient: z.boolean().optional(), - }), - z.strictObject({ - type: z.literal('start-step'), - }), - z.strictObject({ - type: z.literal('finish-step'), - }), - z.strictObject({ - type: z.literal('start'), - messageId: z.string().optional(), - messageMetadata: z.unknown().optional(), - }), - z.strictObject({ - type: z.literal('finish'), - finishReason: z - .enum([ - 'stop', - 'length', - 'content-filter', - 'tool-calls', - 'error', - 'other', - ] as const satisfies readonly FinishReason[]) - .optional(), - messageMetadata: z.unknown().optional(), - }), - z.strictObject({ - type: z.literal('abort'), - reason: z.string().optional(), - }), - z.strictObject({ - type: z.literal('message-metadata'), - messageMetadata: z.unknown(), - }), - ]), - ), -); - -export type DataUIMessageChunk = ValueOf<{ - [NAME in keyof DATA_TYPES & string]: { - type: `data-${NAME}`; - id?: string; - data: DATA_TYPES[NAME]; - transient?: boolean; - }; -}>; - -export type UIMessageChunk< - METADATA = unknown, - DATA_TYPES extends UIDataTypes = UIDataTypes, -> = - | { - type: 'text-start'; - id: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'text-delta'; - delta: string; - id: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'text-end'; - id: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'reasoning-start'; - id: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'reasoning-delta'; - id: string; - delta: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'reasoning-end'; - id: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'error'; - errorText: string; - } - | { - type: 'tool-input-available'; - toolCallId: string; - toolName: string; - input: unknown; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; - dynamic?: boolean; - title?: string; - } - | { - type: 'tool-input-error'; - toolCallId: string; - toolName: string; - input: unknown; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; - dynamic?: boolean; - errorText: string; - title?: string; - } - | { - type: 'tool-approval-request'; - approvalId: string; - toolCallId: string; - } - | { - type: 'tool-output-available'; - toolCallId: string; - output: unknown; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; - dynamic?: boolean; - preliminary?: boolean; - } - | { - type: 'tool-output-error'; - toolCallId: string; - errorText: string; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; - dynamic?: boolean; - } - | { - type: 'tool-output-denied'; - toolCallId: string; - } - | { - type: 'tool-input-start'; - toolCallId: string; - toolName: string; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; - dynamic?: boolean; - title?: string; - } - | { - type: 'tool-input-delta'; - toolCallId: string; - inputTextDelta: string; - } - | { - type: 'source-url'; - sourceId: string; - url: string; - title?: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'source-document'; - sourceId: string; - mediaType: string; - title: string; - filename?: string; - providerMetadata?: ProviderMetadata; - } - | { - type: 'file'; - url: string; - mediaType: string; - providerMetadata?: ProviderMetadata; - } - | DataUIMessageChunk - | { - type: 'start-step'; - } - | { - type: 'finish-step'; - } - | { - type: 'start'; - messageId?: string; - messageMetadata?: METADATA; - } - | { - type: 'finish'; - finishReason?: FinishReason; - messageMetadata?: METADATA; - } - | { - type: 'abort'; - reason?: string; - } - | { - type: 'message-metadata'; - messageMetadata: METADATA; - }; - -export function isDataUIMessageChunk( - chunk: UIMessageChunk, -): chunk is DataUIMessageChunk { - return chunk.type.startsWith('data-'); -} - -export type InferUIMessageChunk = UIMessageChunk< - InferUIMessageMetadata, - InferUIMessageData ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-headers.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-headers.ts deleted file mode 100644 index ff0149f9a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-headers.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const UI_MESSAGE_STREAM_HEADERS = { - 'content-type': 'text/event-stream', - 'cache-control': 'no-cache', - connection: 'keep-alive', - 'x-vercel-ai-ui-message-stream': 'v1', - 'x-accel-buffering': 'no', // disable nginx buffering -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-on-finish-callback.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-on-finish-callback.ts deleted file mode 100644 index c65f95b34..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-on-finish-callback.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { FinishReason } from '../types/language-model'; -import { UIMessage } from '../ui/ui-messages'; - -export type UIMessageStreamOnFinishCallback = - (event: { - /** - * The updated list of UI messages. - */ - messages: UI_MESSAGE[]; - - /** - * Indicates whether the response message is a continuation of the last original message, - * or if a new message was created. - */ - isContinuation: boolean; - - /** - * Indicates whether the stream was aborted. - */ - isAborted: boolean; - - /** - * The message that was sent to the client as a response - * (including the original message if it was extended). - */ - responseMessage: UI_MESSAGE; - - /** - * The reason why the generation finished. - */ - finishReason?: FinishReason; - }) => PromiseLike | void; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-on-step-finish-callback.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-on-step-finish-callback.ts deleted file mode 100644 index 90dcc8e0e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-on-step-finish-callback.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { UIMessage } from '../ui/ui-messages'; - -/** - * Callback that is called when a step finishes during streaming. - * This is useful for persisting intermediate UI messages during multi-step agent runs. - */ -export type UIMessageStreamOnStepFinishCallback = - (event: { - /** - * The updated list of UI messages at the end of this step. - */ - messages: UI_MESSAGE[]; - - /** - * Indicates whether the response message is a continuation of the last original message, - * or if a new message was created. - */ - isContinuation: boolean; - - /** - * The message that was sent to the client as a response - * (including the original message if it was extended). - */ - responseMessage: UI_MESSAGE; - }) => PromiseLike | void; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-response-init.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-response-init.ts deleted file mode 100644 index 8bbba8c93..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-response-init.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Options for creating a UI message stream response. - * Extends the standard `ResponseInit` with additional streaming options. - */ -export type UIMessageStreamResponseInit = ResponseInit & { - /** - * Optional callback to consume a copy of the SSE stream independently. - * This is useful for logging, debugging, or processing the stream in parallel. - * The callback receives a tee'd copy of the stream and does not block the response. - */ - consumeSseStream?: (options: { - stream: ReadableStream; - }) => PromiseLike | void; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-writer.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-writer.ts deleted file mode 100644 index f079e1c62..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui-message-stream/ui-message-stream-writer.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { UIMessage } from '../ui'; -import { ErrorHandler } from '../util/error-handler'; -import { InferUIMessageChunk } from './ui-message-chunks'; - -export interface UIMessageStreamWriter< - UI_MESSAGE extends UIMessage = UIMessage, -> { - /** - * Appends a data stream part to the stream. - */ - write(part: InferUIMessageChunk): void; - - /** - * Merges the contents of another stream to this stream. - */ - merge(stream: ReadableStream>): void; - - /** - * Error handler that is used by the data stream writer. - * This is intended for forwarding when merging streams - * to prevent duplicated error masking. - */ - onError: ErrorHandler | undefined; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/call-completion-api.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/call-completion-api.ts deleted file mode 100644 index 8174dac67..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/call-completion-api.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { - parseJsonEventStream, - ParseResult, - withUserAgentSuffix, - getRuntimeEnvironmentUserAgent, -} from '@ai-sdk/provider-utils'; -import { - UIMessageChunk, - uiMessageChunkSchema, -} from '../ui-message-stream/ui-message-chunks'; -import { consumeStream } from '../util/consume-stream'; -import { processTextStream } from './process-text-stream'; -import { VERSION } from '../version'; - -// use function to allow for mocking in tests: -const getOriginalFetch = () => fetch; - -export async function callCompletionApi({ - api, - prompt, - credentials, - headers, - body, - streamProtocol = 'data', - setCompletion, - setLoading, - setError, - setAbortController, - onFinish, - onError, - fetch = getOriginalFetch(), -}: { - api: string; - prompt: string; - credentials: RequestCredentials | undefined; - headers: HeadersInit | undefined; - body: Record; - streamProtocol: 'data' | 'text' | undefined; - setCompletion: (completion: string) => void; - setLoading: (loading: boolean) => void; - setError: (error: Error | undefined) => void; - setAbortController: (abortController: AbortController | null) => void; - onFinish: ((prompt: string, completion: string) => void) | undefined; - onError: ((error: Error) => void) | undefined; - fetch: ReturnType | undefined; -}) { - try { - setLoading(true); - setError(undefined); - - const abortController = new AbortController(); - setAbortController(abortController); - - // Empty the completion immediately. - setCompletion(''); - - const response = await fetch(api, { - method: 'POST', - body: JSON.stringify({ - prompt, - ...body, - }), - credentials, - headers: withUserAgentSuffix( - { - 'Content-Type': 'application/json', - ...headers, - }, - `ai-sdk/${VERSION}`, - getRuntimeEnvironmentUserAgent(), - ), - signal: abortController.signal, - }).catch(err => { - throw err; - }); - - if (!response.ok) { - throw new Error( - (await response.text()) ?? 'Failed to fetch the chat response.', - ); - } - - if (!response.body) { - throw new Error('The response body is empty.'); - } - - let result = ''; - - switch (streamProtocol) { - case 'text': { - await processTextStream({ - stream: response.body, - onTextPart: chunk => { - result += chunk; - setCompletion(result); - }, - }); - break; - } - case 'data': { - await consumeStream({ - stream: parseJsonEventStream({ - stream: response.body, - schema: uiMessageChunkSchema, - }).pipeThrough( - new TransformStream, UIMessageChunk>({ - async transform(part) { - if (!part.success) { - throw part.error; - } - - const streamPart = part.value; - if (streamPart.type === 'text-delta') { - result += streamPart.delta; - setCompletion(result); - } else if (streamPart.type === 'error') { - throw new Error(streamPart.errorText); - } - }, - }), - ), - onError: error => { - throw error; - }, - }); - break; - } - default: { - const exhaustiveCheck: never = streamProtocol; - throw new Error(`Unknown stream protocol: ${exhaustiveCheck}`); - } - } - - if (onFinish) { - onFinish(prompt, result); - } - - setAbortController(null); - return result; - } catch (err) { - // Ignore abort errors as they are expected. - if ((err as any).name === 'AbortError') { - setAbortController(null); - return null; - } - - if (err instanceof Error) { - if (onError) { - onError(err); - } - } - - setError(err as Error); - } finally { - setLoading(false); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/chat-transport.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/chat-transport.ts deleted file mode 100644 index 22fc8c5f3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/chat-transport.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { UIMessageChunk } from '../ui-message-stream'; -import { ChatRequestOptions } from './chat'; -import { UIMessage } from './ui-messages'; - -/** - * Transport interface for handling chat message communication and streaming. - * - * The `ChatTransport` interface provides fine-grained control over how messages - * are sent to API endpoints and how responses are processed. This enables - * alternative communication protocols like WebSockets, custom authentication - * patterns, or specialized backend integrations. - * - * @template UI_MESSAGE - The UI message type extending UIMessage - */ -export interface ChatTransport { - /** - * Sends messages to the chat API endpoint and returns a streaming response. - * - * This method handles both new message submission and message regeneration. - * It supports real-time streaming of responses through UIMessageChunk events. - * - * @param options - Configuration object containing: - * @param options.trigger - The type of message submission: - * - `'submit-message'`: Submitting a new user message - * - `'regenerate-message'`: Regenerating an assistant response - * @param options.chatId - Unique identifier for the chat session - * @param options.messageId - ID of the message to regenerate (for regenerate-message trigger) or undefined for new messages - * @param options.messages - Array of UI messages representing the conversation history - * @param options.abortSignal - Signal to abort the request if needed - * @param options.headers - Additional HTTP headers to include in the request - * @param options.body - Additional JSON properties to include in the request body - * @param options.metadata - Custom metadata to attach to the request - * - * @returns Promise resolving to a ReadableStream of UIMessageChunk objects. - * The stream emits various chunk types like: - * - `text-start`, `text-delta`, `text-end`: For streaming text content - * - `tool-input-start`, `tool-input-delta`, `tool-input-available`: For tool calls - * - `data-part-start`, `data-part-delta`, `data-part-available`: For data parts - * - `error`: For error handling - * - * @throws Error when the API request fails or response is invalid - */ - sendMessages: ( - options: { - /** The type of message submission - either new message or regeneration */ - trigger: 'submit-message' | 'regenerate-message'; - /** Unique identifier for the chat session */ - chatId: string; - /** ID of the message to regenerate, or undefined for new messages */ - messageId: string | undefined; - /** Array of UI messages representing the conversation history */ - messages: UI_MESSAGE[]; - /** Signal to abort the request if needed */ - abortSignal: AbortSignal | undefined; - } & ChatRequestOptions, - ) => Promise>; - - /** - * Reconnects to an existing streaming response for the specified chat session. - * - * This method is used to resume streaming when a connection is interrupted - * or when resuming a chat session. It's particularly useful for maintaining - * continuity in long-running conversations or recovering from network issues. - * - * @param options - Configuration object containing: - * @param options.chatId - Unique identifier for the chat session to reconnect to - * @param options.headers - Additional HTTP headers to include in the reconnection request - * @param options.body - Additional JSON properties to include in the request body - * @param options.metadata - Custom metadata to attach to the request - * - * @returns Promise resolving to: - * - `ReadableStream`: If an active stream is found and can be resumed - * - `null`: If no active stream exists for the specified chat session (e.g., response already completed) - * - * @throws Error when the reconnection request fails or response is invalid - */ - reconnectToStream: ( - options: { - /** Unique identifier for the chat session to reconnect to */ - chatId: string; - } & ChatRequestOptions, - ) => Promise | null>; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/chat.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/chat.ts deleted file mode 100644 index 6dbd3c661..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/chat.ts +++ /dev/null @@ -1,786 +0,0 @@ -import { - FlexibleSchema, - generateId as generateIdFunc, - IdGenerator, - InferSchema, -} from '@ai-sdk/provider-utils'; -import { FinishReason } from '../types/language-model'; -import { UIMessageChunk } from '../ui-message-stream/ui-message-chunks'; -import { consumeStream } from '../util/consume-stream'; -import { SerialJobExecutor } from '../util/serial-job-executor'; -import { ChatTransport } from './chat-transport'; -import { convertFileListToFileUIParts } from './convert-file-list-to-file-ui-parts'; -import { DefaultChatTransport } from './default-chat-transport'; -import { - createStreamingUIMessageState, - processUIMessageStream, - StreamingUIMessageState, -} from './process-ui-message-stream'; -import { - InferUIMessageToolCall, - isToolUIPart, - UIMessagePart, - UITools, - type DataUIPart, - type FileUIPart, - type InferUIMessageData, - type InferUIMessageMetadata, - type InferUIMessageTools, - type UIDataTypes, - type UIMessage, -} from './ui-messages'; - -export type CreateUIMessage = Omit< - UI_MESSAGE, - 'id' | 'role' -> & { - id?: UI_MESSAGE['id']; - role?: UI_MESSAGE['role']; -}; - -export type UIDataPartSchemas = Record; - -export type UIDataTypesToSchemas = { - [K in keyof T]: FlexibleSchema; -}; - -export type InferUIDataParts = { - [K in keyof T]: InferSchema; -}; - -export type ChatRequestOptions = { - /** - * Additional headers that should be to be passed to the API endpoint. - */ - headers?: Record | Headers; - - /** - * Additional body JSON properties that should be sent to the API endpoint. - */ - body?: object; // TODO JSONStringifyable - - metadata?: unknown; -}; - -/** - * Function that can be called to add a tool approval response to the chat. - */ -export type ChatAddToolApproveResponseFunction = ({ - id, - approved, - reason, - options, -}: { - id: string; - - /** - * Flag indicating whether the approval was granted or denied. - */ - approved: boolean; - - /** - * Optional reason for the approval or denial. - */ - reason?: string; - - /** - * Optional request options to be used if `sendAutomaticallyWhen` callback returns true. - */ - options?: ChatRequestOptions; -}) => void | PromiseLike; - -/** - * Function that can be called to add a tool output to the chat. - */ -export type ChatAddToolOutputFunction = < - TOOL extends keyof InferUIMessageTools, ->({ - state, - tool, - toolCallId, - output, - errorText, - options, -}: { - /** - * Name of the tool that was called. - */ - tool: TOOL; - - /** - * Identifier of the tool call to add output for. - */ - toolCallId: string; - - /** - * Optional request options to be used if `sendAutomaticallyWhen` callback returns true. - */ - options?: ChatRequestOptions; -} & ( - | { - state?: 'output-available'; - output: InferUIMessageTools[TOOL]['output']; - errorText?: never; - } - | { - state: 'output-error'; - output?: never; - errorText: string; - } -)) => void | PromiseLike; - -export type ChatStatus = 'submitted' | 'streaming' | 'ready' | 'error'; - -type ActiveResponse = { - state: StreamingUIMessageState; - abortController: AbortController; -}; - -export interface ChatState { - status: ChatStatus; - - error: Error | undefined; - - messages: UI_MESSAGE[]; - pushMessage: (message: UI_MESSAGE) => void; - popMessage: () => void; - replaceMessage: (index: number, message: UI_MESSAGE) => void; - - snapshot: (thing: T) => T; -} - -export type ChatOnErrorCallback = (error: Error) => void; - -export type ChatOnToolCallCallback = - (options: { - toolCall: InferUIMessageToolCall; - }) => void | PromiseLike; - -export type ChatOnDataCallback = ( - dataPart: DataUIPart>, -) => void; - -/** - * Function that is called when the assistant response has finished streaming. - * - * @param message The assistant message that was streamed. - * @param messages The full chat history, including the assistant message. - * - * @param isAbort Indicates whether the request has been aborted. - * @param isDisconnect Indicates whether the request has been ended by a network error. - * @param isError Indicates whether the request has been ended by an error. - * @param finishReason The reason why the generation finished. - */ -export type ChatOnFinishCallback = (options: { - message: UI_MESSAGE; - messages: UI_MESSAGE[]; - isAbort: boolean; - isDisconnect: boolean; - isError: boolean; - finishReason?: FinishReason; -}) => void; - -export interface ChatInit { - /** - * A unique identifier for the chat. If not provided, a random one will be - * generated. - */ - id?: string; - - messageMetadataSchema?: FlexibleSchema>; - dataPartSchemas?: UIDataTypesToSchemas>; - - messages?: UI_MESSAGE[]; - - /** - * A way to provide a function that is going to be used for ids for messages and the chat. - * If not provided the default AI SDK `generateId` is used. - */ - generateId?: IdGenerator; - - transport?: ChatTransport; - - /** - * Callback function to be called when an error is encountered. - */ - onError?: ChatOnErrorCallback; - - /** - * Optional callback function that is invoked when a tool call is received. - * Intended for automatic client-side tool execution. - * - * You can optionally return a result for the tool call, - * either synchronously or asynchronously. - */ - onToolCall?: ChatOnToolCallCallback; - - /** - * Function that is called when the assistant response has finished streaming. - */ - onFinish?: ChatOnFinishCallback; - - /** - * Optional callback function that is called when a data part is received. - * - * @param data The data part that was received. - */ - onData?: ChatOnDataCallback; - - /** - * When provided, this function will be called when the stream is finished or a tool call is added - * to determine if the current messages should be resubmitted. - */ - sendAutomaticallyWhen?: (options: { - messages: UI_MESSAGE[]; - }) => boolean | PromiseLike; -} - -export abstract class AbstractChat { - readonly id: string; - readonly generateId: IdGenerator; - - protected state: ChatState; - - private messageMetadataSchema: - | FlexibleSchema> - | undefined; - private dataPartSchemas: - | UIDataTypesToSchemas> - | undefined; - private readonly transport: ChatTransport; - private onError?: ChatInit['onError']; - private onToolCall?: ChatInit['onToolCall']; - private onFinish?: ChatInit['onFinish']; - private onData?: ChatInit['onData']; - private sendAutomaticallyWhen?: ChatInit['sendAutomaticallyWhen']; - - private activeResponse: ActiveResponse | undefined = undefined; - private jobExecutor = new SerialJobExecutor(); - - constructor({ - generateId = generateIdFunc, - id = generateId(), - transport = new DefaultChatTransport(), - messageMetadataSchema, - dataPartSchemas, - state, - onError, - onToolCall, - onFinish, - onData, - sendAutomaticallyWhen, - }: Omit, 'messages'> & { - state: ChatState; - }) { - this.id = id; - this.transport = transport; - this.generateId = generateId; - this.messageMetadataSchema = messageMetadataSchema; - this.dataPartSchemas = dataPartSchemas; - this.state = state; - this.onError = onError; - this.onToolCall = onToolCall; - this.onFinish = onFinish; - this.onData = onData; - this.sendAutomaticallyWhen = sendAutomaticallyWhen; - } - - /** - * Hook status: - * - * - `submitted`: The message has been sent to the API and we're awaiting the start of the response stream. - * - `streaming`: The response is actively streaming in from the API, receiving chunks of data. - * - `ready`: The full response has been received and processed; a new user message can be submitted. - * - `error`: An error occurred during the API request, preventing successful completion. - */ - get status(): ChatStatus { - return this.state.status; - } - - protected setStatus({ - status, - error, - }: { - status: ChatStatus; - error?: Error; - }) { - if (this.status === status) return; - - this.state.status = status; - this.state.error = error; - } - - get error() { - return this.state.error; - } - - get messages(): UI_MESSAGE[] { - return this.state.messages; - } - - get lastMessage(): UI_MESSAGE | undefined { - return this.state.messages[this.state.messages.length - 1]; - } - - set messages(messages: UI_MESSAGE[]) { - this.state.messages = messages; - } - - /** - * Appends or replaces a user message to the chat list. This triggers the API call to fetch - * the assistant's response. - * - * If a messageId is provided, the message will be replaced. - */ - sendMessage = async ( - message?: - | (CreateUIMessage & { - text?: never; - files?: never; - messageId?: string; - }) - | { - text: string; - files?: FileList | FileUIPart[]; - metadata?: InferUIMessageMetadata; - parts?: never; - messageId?: string; - } - | { - files: FileList | FileUIPart[]; - metadata?: InferUIMessageMetadata; - parts?: never; - messageId?: string; - }, - options?: ChatRequestOptions, - ): Promise => { - if (message == null) { - await this.makeRequest({ - trigger: 'submit-message', - messageId: this.lastMessage?.id, - ...options, - }); - return; - } - - let uiMessage: CreateUIMessage; - - if ('text' in message || 'files' in message) { - const fileParts = Array.isArray(message.files) - ? message.files - : await convertFileListToFileUIParts(message.files); - - uiMessage = { - parts: [ - ...fileParts, - ...('text' in message && message.text != null - ? [{ type: 'text' as const, text: message.text }] - : []), - ], - } as UI_MESSAGE; - } else { - uiMessage = message; - } - - if (message.messageId != null) { - const messageIndex = this.state.messages.findIndex( - m => m.id === message.messageId, - ); - - if (messageIndex === -1) { - throw new Error(`message with id ${message.messageId} not found`); - } - - if (this.state.messages[messageIndex].role !== 'user') { - throw new Error( - `message with id ${message.messageId} is not a user message`, - ); - } - - // remove all messages after the message with the given id - this.state.messages = this.state.messages.slice(0, messageIndex + 1); - - // update the message with the new content - this.state.replaceMessage(messageIndex, { - ...uiMessage, - id: message.messageId, - role: uiMessage.role ?? 'user', - metadata: message.metadata, - } as UI_MESSAGE); - } else { - this.state.pushMessage({ - ...uiMessage, - id: uiMessage.id ?? this.generateId(), - role: uiMessage.role ?? 'user', - metadata: message.metadata, - } as UI_MESSAGE); - } - - await this.makeRequest({ - trigger: 'submit-message', - messageId: message.messageId, - ...options, - }); - }; - - /** - * Regenerate the assistant message with the provided message id. - * If no message id is provided, the last assistant message will be regenerated. - */ - regenerate = async ({ - messageId, - ...options - }: { - messageId?: string; - } & ChatRequestOptions = {}): Promise => { - const messageIndex = - messageId == null - ? this.state.messages.length - 1 - : this.state.messages.findIndex(message => message.id === messageId); - - if (messageIndex === -1) { - throw new Error(`message ${messageId} not found`); - } - - // set the messages to the message before the assistant message - this.state.messages = this.state.messages.slice( - 0, - // if the message is a user message, we need to include it in the request: - this.messages[messageIndex].role === 'assistant' - ? messageIndex - : messageIndex + 1, - ); - - await this.makeRequest({ - trigger: 'regenerate-message', - messageId, - ...options, - }); - }; - - /** - * Attempt to resume an ongoing streaming response. - */ - resumeStream = async (options: ChatRequestOptions = {}): Promise => { - await this.makeRequest({ trigger: 'resume-stream', ...options }); - }; - - /** - * Clear the error state and set the status to ready if the chat is in an error state. - */ - clearError = () => { - if (this.status === 'error') { - this.state.error = undefined; - this.setStatus({ status: 'ready' }); - } - }; - - addToolApprovalResponse: ChatAddToolApproveResponseFunction = async ({ - id, - approved, - reason, - options, - }) => - this.jobExecutor.run(async () => { - const messages = this.state.messages; - const lastMessage = messages[messages.length - 1]; - - const updatePart = ( - part: UIMessagePart, - ): UIMessagePart => - isToolUIPart(part) && - part.state === 'approval-requested' && - part.approval.id === id - ? { - ...part, - state: 'approval-responded', - approval: { id, approved, reason }, - } - : part; - - // update the message to trigger an immediate UI update - this.state.replaceMessage(messages.length - 1, { - ...lastMessage, - parts: lastMessage.parts.map(updatePart), - }); - - // update the active response if it exists - if (this.activeResponse) { - this.activeResponse.state.message.parts = - this.activeResponse.state.message.parts.map(updatePart); - } - - // automatically send the message if the sendAutomaticallyWhen function returns true - if ( - this.status !== 'streaming' && - this.status !== 'submitted' && - this.sendAutomaticallyWhen - ) { - this.shouldSendAutomatically().then(shouldSend => { - if (shouldSend) { - // no await to avoid deadlocking - this.makeRequest({ - trigger: 'submit-message', - messageId: this.lastMessage?.id, - ...options, - }); - } - }); - } - }); - - addToolOutput: ChatAddToolOutputFunction = async ({ - state = 'output-available', - toolCallId, - output, - errorText, - options, - }) => - this.jobExecutor.run(async () => { - const messages = this.state.messages; - const lastMessage = messages[messages.length - 1]; - - const updatePart = ( - part: UIMessagePart, - ): UIMessagePart => - isToolUIPart(part) && part.toolCallId === toolCallId - ? ({ ...part, state, output, errorText } as typeof part) - : part; - - // update the message to trigger an immediate UI update - this.state.replaceMessage(messages.length - 1, { - ...lastMessage, - parts: lastMessage.parts.map(updatePart), - }); - - // update the active response if it exists - if (this.activeResponse) { - this.activeResponse.state.message.parts = - this.activeResponse.state.message.parts.map(updatePart); - } - - // automatically send the message if the sendAutomaticallyWhen function returns true - if ( - this.status !== 'streaming' && - this.status !== 'submitted' && - this.sendAutomaticallyWhen - ) { - this.shouldSendAutomatically().then(shouldSend => { - if (shouldSend) { - // no await to avoid deadlocking - this.makeRequest({ - trigger: 'submit-message', - messageId: this.lastMessage?.id, - ...options, - }); - } - }); - } - }); - - /** @deprecated Use addToolOutput */ - addToolResult = this.addToolOutput; - - /** - * Abort the current request immediately, keep the generated tokens if any. - */ - stop = async () => { - if (this.status !== 'streaming' && this.status !== 'submitted') return; - - if (this.activeResponse?.abortController) { - this.activeResponse.abortController.abort(); - } - }; - - private async shouldSendAutomatically(): Promise { - if (!this.sendAutomaticallyWhen) return false; - - const result = this.sendAutomaticallyWhen({ - messages: this.state.messages, - }); - - // Check if result is a promise - if (result && typeof result === 'object' && 'then' in result) { - return await result; - } - - return result as boolean; - } - - private async makeRequest({ - trigger, - metadata, - headers, - body, - messageId, - }: { - trigger: 'submit-message' | 'resume-stream' | 'regenerate-message'; - messageId?: string; - } & ChatRequestOptions) { - // For resume-stream, check if there's an active stream before - // changing status. This avoids a brief flash of 'submitted' status - // when there is no stream to resume (e.g. on page load). - let resumeStream: ReadableStream | undefined; - if (trigger === 'resume-stream') { - try { - const reconnect = await this.transport.reconnectToStream({ - chatId: this.id, - metadata, - headers, - body, - }); - - if (reconnect == null) { - return; // no active stream found, so we do not resume - } - - resumeStream = reconnect; - } catch (err) { - if (this.onError && err instanceof Error) { - this.onError(err); - } - this.setStatus({ status: 'error', error: err as Error }); - return; - } - } - - this.setStatus({ status: 'submitted', error: undefined }); - - const lastMessage = this.lastMessage; - - let isAbort = false; - let isDisconnect = false; - let isError = false; - - try { - const activeResponse = { - state: createStreamingUIMessageState({ - lastMessage: this.state.snapshot(lastMessage), - messageId: this.generateId(), - }), - abortController: new AbortController(), - } as ActiveResponse; - - activeResponse.abortController.signal.addEventListener('abort', () => { - isAbort = true; - }); - - this.activeResponse = activeResponse; - - let stream: ReadableStream; - - if (trigger === 'resume-stream') { - stream = resumeStream!; - } else { - stream = await this.transport.sendMessages({ - chatId: this.id, - messages: this.state.messages, - abortSignal: activeResponse.abortController.signal, - metadata, - headers, - body, - trigger, - messageId, - }); - } - - const runUpdateMessageJob = ( - job: (options: { - state: StreamingUIMessageState; - write: () => void; - }) => Promise, - ) => - // serialize the job execution to avoid race conditions: - this.jobExecutor.run(() => - job({ - state: activeResponse.state, - write: () => { - // streaming is set on first write (before it should be "submitted") - this.setStatus({ status: 'streaming' }); - - const replaceLastMessage = - activeResponse.state.message.id === this.lastMessage?.id; - - if (replaceLastMessage) { - this.state.replaceMessage( - this.state.messages.length - 1, - activeResponse.state.message, - ); - } else { - this.state.pushMessage(activeResponse.state.message); - } - }, - }), - ); - - await consumeStream({ - stream: processUIMessageStream({ - stream, - onToolCall: this.onToolCall, - onData: this.onData, - messageMetadataSchema: this.messageMetadataSchema, - dataPartSchemas: this.dataPartSchemas, - runUpdateMessageJob, - onError: error => { - throw error; - }, - }), - onError: error => { - throw error; - }, - }); - - this.setStatus({ status: 'ready' }); - } catch (err) { - // Ignore abort errors as they are expected. - if (isAbort || (err as any).name === 'AbortError') { - isAbort = true; - this.setStatus({ status: 'ready' }); - return null; - } - - isError = true; - - // Network errors such as disconnected, timeout, etc. - if ( - err instanceof TypeError && - (err.message.toLowerCase().includes('fetch') || - err.message.toLowerCase().includes('network')) - ) { - isDisconnect = true; - } - - if (this.onError && err instanceof Error) { - this.onError(err); - } - - this.setStatus({ status: 'error', error: err as Error }); - } finally { - try { - this.onFinish?.({ - message: this.activeResponse!.state.message, - messages: this.state.messages, - isAbort, - isDisconnect, - isError, - finishReason: this.activeResponse?.state.finishReason, - }); - } catch (err) { - console.error(err); - } - - this.activeResponse = undefined; - } - - // automatically send the message if the sendAutomaticallyWhen function returns true - if (!isError && (await this.shouldSendAutomatically())) { - await this.makeRequest({ - trigger: 'submit-message', - messageId: this.lastMessage?.id, - metadata, - headers, - body, - }); - } - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/convert-file-list-to-file-ui-parts.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/convert-file-list-to-file-ui-parts.ts deleted file mode 100644 index 19cd243b7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/convert-file-list-to-file-ui-parts.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { FileUIPart } from './ui-messages'; - -export async function convertFileListToFileUIParts( - files: FileList | undefined, -): Promise> { - if (files == null) { - return []; - } - - // React-native doesn't have a FileList global: - if (!globalThis.FileList || !(files instanceof globalThis.FileList)) { - throw new Error('FileList is not supported in the current environment'); - } - - return Promise.all( - Array.from(files).map(async file => { - const { name, type } = file; - - const dataUrl = await new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onload = readerEvent => { - resolve(readerEvent.target?.result as string); - }; - reader.onerror = error => reject(error); - reader.readAsDataURL(file); - }); - - return { - type: 'file', - mediaType: type, - filename: name, - url: dataUrl, - }; - }), - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/convert-to-model-messages.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/convert-to-model-messages.ts deleted file mode 100644 index d01737f8b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/convert-to-model-messages.ts +++ /dev/null @@ -1,379 +0,0 @@ -import { - AssistantContent, - FilePart, - isNonNullable, - ModelMessage, - TextPart, - ToolApprovalResponse, - ToolResultPart, -} from '@ai-sdk/provider-utils'; -import { ToolSet } from '../generate-text/tool-set'; -import { createToolModelOutput } from '../prompt/create-tool-model-output'; -import { MessageConversionError } from '../prompt/message-conversion-error'; -import { - DataUIPart, - DynamicToolUIPart, - FileUIPart, - getToolName, - InferUIMessageData, - InferUIMessageTools, - isDataUIPart, - isFileUIPart, - isReasoningUIPart, - isTextUIPart, - isToolUIPart, - ReasoningUIPart, - TextUIPart, - ToolUIPart, - UIMessage, -} from './ui-messages'; - -/** - * Converts an array of UI messages from useChat into an array of ModelMessages that can be used - * with the AI functions (e.g. `streamText`, `generateText`). - * - * @param messages - The UI messages to convert. - * @param options.tools - The tools to use. - * @param options.ignoreIncompleteToolCalls - Whether to ignore incomplete tool calls. Default is `false`. - * @param options.convertDataPart - Optional function to convert data parts to text or file model message parts. Returns `undefined` if the part should be ignored. - * - * @returns An array of ModelMessages. - */ -export async function convertToModelMessages( - messages: Array>, - options?: { - tools?: ToolSet; - ignoreIncompleteToolCalls?: boolean; - convertDataPart?: ( - part: DataUIPart>, - ) => TextPart | FilePart | undefined; - }, -): Promise { - const modelMessages: ModelMessage[] = []; - - if (options?.ignoreIncompleteToolCalls) { - messages = messages.map(message => ({ - ...message, - parts: message.parts.filter( - part => - !isToolUIPart(part) || - (part.state !== 'input-streaming' && - part.state !== 'input-available'), - ), - })); - } - - for (const message of messages) { - switch (message.role) { - case 'system': { - const textParts = message.parts.filter( - (part): part is TextUIPart => part.type === 'text', - ); - - const providerMetadata = textParts.reduce((acc, part) => { - if (part.providerMetadata != null) { - return { ...acc, ...part.providerMetadata }; - } - return acc; - }, {}); - - modelMessages.push({ - role: 'system', - content: textParts.map(part => part.text).join(''), - ...(Object.keys(providerMetadata).length > 0 - ? { providerOptions: providerMetadata } - : {}), - }); - break; - } - - case 'user': { - modelMessages.push({ - role: 'user', - content: message.parts - .map((part): TextPart | FilePart | undefined => { - // Process text parts - if (isTextUIPart(part)) { - return { - type: 'text' as const, - text: part.text, - ...(part.providerMetadata != null - ? { providerOptions: part.providerMetadata } - : {}), - }; - } - - // Process file parts - if (isFileUIPart(part)) { - return { - type: 'file' as const, - mediaType: part.mediaType, - filename: part.filename, - data: part.url, - ...(part.providerMetadata != null - ? { providerOptions: part.providerMetadata } - : {}), - }; - } - - // Process data parts with converter if provided - if (isDataUIPart(part)) { - return options?.convertDataPart?.( - part as DataUIPart>, - ); - } - }) - .filter(isNonNullable), - }); - - break; - } - - case 'assistant': { - if (message.parts != null) { - let block: Array< - | TextUIPart - | ToolUIPart> - | ReasoningUIPart - | FileUIPart - | DynamicToolUIPart - | DataUIPart> - > = []; - - async function processBlock() { - if (block.length === 0) { - return; - } - - const content: AssistantContent = []; - - for (const part of block) { - if (isTextUIPart(part)) { - content.push({ - type: 'text' as const, - text: part.text, - ...(part.providerMetadata != null - ? { providerOptions: part.providerMetadata } - : {}), - }); - } else if (isFileUIPart(part)) { - content.push({ - type: 'file' as const, - mediaType: part.mediaType, - filename: part.filename, - data: part.url, - ...(part.providerMetadata != null - ? { providerOptions: part.providerMetadata } - : {}), - }); - } else if (isReasoningUIPart(part)) { - content.push({ - type: 'reasoning' as const, - text: part.text, - providerOptions: part.providerMetadata, - }); - } else if (isToolUIPart(part)) { - const toolName = getToolName(part); - - if (part.state !== 'input-streaming') { - content.push({ - type: 'tool-call' as const, - toolCallId: part.toolCallId, - toolName, - input: - part.state === 'output-error' - ? (part.input ?? - ('rawInput' in part ? part.rawInput : undefined)) - : part.input, - providerExecuted: part.providerExecuted, - ...(part.callProviderMetadata != null - ? { providerOptions: part.callProviderMetadata } - : {}), - }); - - if (part.approval != null) { - content.push({ - type: 'tool-approval-request' as const, - approvalId: part.approval.id, - toolCallId: part.toolCallId, - }); - } - - if ( - part.providerExecuted === true && - part.state !== 'approval-responded' && - (part.state === 'output-available' || - part.state === 'output-error') - ) { - const resultProviderMetadata = - part.resultProviderMetadata ?? part.callProviderMetadata; - - content.push({ - type: 'tool-result', - toolCallId: part.toolCallId, - toolName, - output: await createToolModelOutput({ - toolCallId: part.toolCallId, - input: part.input, - output: - part.state === 'output-error' - ? part.errorText - : part.output, - tool: options?.tools?.[toolName], - errorMode: - part.state === 'output-error' ? 'json' : 'none', - }), - ...(resultProviderMetadata != null - ? { providerOptions: resultProviderMetadata } - : {}), - }); - } - } - } else if (isDataUIPart(part)) { - const dataPart = options?.convertDataPart?.( - part as DataUIPart>, - ); - - if (dataPart != null) { - content.push(dataPart); - } - } else { - const _exhaustiveCheck: never = part; - throw new Error(`Unsupported part: ${_exhaustiveCheck}`); - } - } - - modelMessages.push({ - role: 'assistant', - content, - }); - - // check if there are tool invocations with results in the block - // Include non-provider-executed tools, OR provider-executed tools with approval responses - const toolParts = block.filter( - part => - isToolUIPart(part) && - (part.providerExecuted !== true || - part.approval?.approved != null), - ) as ( - | ToolUIPart> - | DynamicToolUIPart - )[]; - - // tool message with tool results - if (toolParts.length > 0) { - { - const content: Array = - []; - for (const toolPart of toolParts) { - // add approval response for approved tool calls: - if (toolPart.approval?.approved != null) { - content.push({ - type: 'tool-approval-response' as const, - approvalId: toolPart.approval.id, - approved: toolPart.approval.approved, - reason: toolPart.approval.reason, - providerExecuted: toolPart.providerExecuted, - }); - } - - // For provider-executed tools, the tool result is already in the - // assistant content. Skip adding to tool message to avoid duplicates - // (which would create orphaned function_call_output entries). - if (toolPart.providerExecuted === true) { - continue; - } - - switch (toolPart.state) { - case 'output-denied': { - content.push({ - type: 'tool-result', - toolCallId: toolPart.toolCallId, - toolName: getToolName(toolPart), - output: { - type: 'error-text' as const, - value: - toolPart.approval.reason ?? - 'Tool execution denied.', - }, - ...(toolPart.callProviderMetadata != null - ? { providerOptions: toolPart.callProviderMetadata } - : {}), - }); - break; - } - - case 'output-error': - case 'output-available': { - const toolName = getToolName(toolPart); - content.push({ - type: 'tool-result', - toolCallId: toolPart.toolCallId, - toolName, - output: await createToolModelOutput({ - toolCallId: toolPart.toolCallId, - input: toolPart.input, - output: - toolPart.state === 'output-error' - ? toolPart.errorText - : toolPart.output, - tool: options?.tools?.[toolName], - errorMode: - toolPart.state === 'output-error' ? 'text' : 'none', - }), - ...(toolPart.callProviderMetadata != null - ? { providerOptions: toolPart.callProviderMetadata } - : {}), - }); - break; - } - } - } - - if (content.length > 0) { - modelMessages.push({ - role: 'tool', - content, - }); - } - } - } - - // updates for next block - block = []; - } - - for (const part of message.parts) { - if ( - isTextUIPart(part) || - isReasoningUIPart(part) || - isFileUIPart(part) || - isToolUIPart(part) || - isDataUIPart(part) - ) { - block.push(part as (typeof block)[number]); - } else if (part.type === 'step-start') { - await processBlock(); - } - } - - await processBlock(); - - break; - } - - break; - } - - default: { - const _exhaustiveCheck: never = message.role; - throw new MessageConversionError({ - originalMessage: message, - message: `Unsupported role: ${_exhaustiveCheck}`, - }); - } - } - } - - return modelMessages; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/default-chat-transport.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/default-chat-transport.ts deleted file mode 100644 index c9d1b43a0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/default-chat-transport.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { parseJsonEventStream, ParseResult } from '@ai-sdk/provider-utils'; -import { - UIMessageChunk, - uiMessageChunkSchema, -} from '../ui-message-stream/ui-message-chunks'; -import { - HttpChatTransport, - HttpChatTransportInitOptions, -} from './http-chat-transport'; -import { UIMessage } from './ui-messages'; - -export class DefaultChatTransport< - UI_MESSAGE extends UIMessage, -> extends HttpChatTransport { - constructor(options: HttpChatTransportInitOptions = {}) { - super(options); - } - - protected processResponseStream( - stream: ReadableStream>, - ): ReadableStream { - return parseJsonEventStream({ - stream, - schema: uiMessageChunkSchema, - }).pipeThrough( - new TransformStream, UIMessageChunk>({ - async transform(chunk, controller) { - if (!chunk.success) { - throw chunk.error; - } - controller.enqueue(chunk.value); - }, - }), - ); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/direct-chat-transport.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/direct-chat-transport.ts deleted file mode 100644 index a795eadbd..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/direct-chat-transport.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { Output } from '../generate-text/output'; -import { UIMessageStreamOptions } from '../generate-text/stream-text-result'; -import { ToolSet } from '../generate-text/tool-set'; -import { UIMessageChunk } from '../ui-message-stream/ui-message-chunks'; -import { Agent } from '../agent/agent'; -import { ChatTransport } from './chat-transport'; -import { convertToModelMessages } from './convert-to-model-messages'; -import { InferUITools, UIMessage } from './ui-messages'; -import { validateUIMessages } from './validate-ui-messages'; - -/** - * Options for the `DirectChatTransport` class. - */ -export type DirectChatTransportOptions< - CALL_OPTIONS, - TOOLS extends ToolSet, - OUTPUT extends Output, - UI_MESSAGE extends UIMessage>, -> = { - /** - * The agent to use for generating responses. - */ - agent: Agent; - - /** - * Options to pass to the agent when calling it. - */ - options?: CALL_OPTIONS; -} & Omit, 'onFinish'>; - -/** - * A transport that directly communicates with an Agent in-process, - * without going through HTTP. This is useful for: - * - Server-side rendering scenarios - * - Testing without network - * - Single-process applications - * - * @example - * ```tsx - * import { useChat } from '@ai-sdk/react'; - * import { DirectChatTransport } from 'ai'; - * import { myAgent } from './my-agent'; - * - * const { messages, sendMessage } = useChat({ - * transport: new DirectChatTransport({ agent: myAgent }), - * }); - * ``` - */ -export class DirectChatTransport< - CALL_OPTIONS = never, - TOOLS extends ToolSet = {}, - OUTPUT extends Output = never, - UI_MESSAGE extends UIMessage> = UIMessage< - unknown, - never, - InferUITools - >, -> implements ChatTransport { - private readonly agent: Agent; - private readonly agentOptions: CALL_OPTIONS | undefined; - private readonly uiMessageStreamOptions: Omit< - UIMessageStreamOptions, - 'onFinish' - >; - - constructor({ - agent, - options, - ...uiMessageStreamOptions - }: DirectChatTransportOptions) { - this.agent = agent; - this.agentOptions = options; - this.uiMessageStreamOptions = uiMessageStreamOptions; - } - - async sendMessages({ - messages, - abortSignal, - }: Parameters['sendMessages']>[0]): Promise< - ReadableStream - > { - // Validate the incoming UI messages - const validatedMessages = await validateUIMessages({ - messages, - tools: this.agent.tools, - }); - - // Convert UI messages to model messages - const modelMessages = await convertToModelMessages(validatedMessages, { - tools: this.agent.tools, - }); - - // Stream from the agent - const result = await this.agent.stream({ - prompt: modelMessages, - abortSignal, - ...(this.agentOptions !== undefined - ? { options: this.agentOptions } - : {}), - } as Parameters['stream']>[0]); - - // Return the UI message stream - return result.toUIMessageStream(this.uiMessageStreamOptions); - } - - /** - * Direct transport does not support reconnection since there is no - * persistent server-side stream to reconnect to. - * - * @returns Always returns `null` - */ - async reconnectToStream( - _options: Parameters['reconnectToStream']>[0], - ): Promise | null> { - return null; - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/http-chat-transport.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/http-chat-transport.ts deleted file mode 100644 index 57aa3dbb8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/http-chat-transport.ts +++ /dev/null @@ -1,273 +0,0 @@ -import { - FetchFunction, - Resolvable, - normalizeHeaders, - resolve, -} from '@ai-sdk/provider-utils'; -import { UIMessageChunk } from '../ui-message-stream/ui-message-chunks'; -import { ChatTransport } from './chat-transport'; -import { UIMessage } from './ui-messages'; - -export type PrepareSendMessagesRequest = ( - options: { - id: string; - messages: UI_MESSAGE[]; - requestMetadata: unknown; - body: Record | undefined; - credentials: RequestCredentials | undefined; - headers: HeadersInit | undefined; - api: string; - } & { - trigger: 'submit-message' | 'regenerate-message'; - messageId: string | undefined; - }, -) => - | { - body: object; - headers?: HeadersInit; - credentials?: RequestCredentials; - api?: string; - } - | PromiseLike<{ - body: object; - headers?: HeadersInit; - credentials?: RequestCredentials; - api?: string; - }>; - -export type PrepareReconnectToStreamRequest = (options: { - id: string; - requestMetadata: unknown; - body: Record | undefined; - credentials: RequestCredentials | undefined; - headers: HeadersInit | undefined; - api: string; -}) => - | { - headers?: HeadersInit; - credentials?: RequestCredentials; - api?: string; - } - | PromiseLike<{ - headers?: HeadersInit; - credentials?: RequestCredentials; - api?: string; - }>; - -/** - * Options for the `HttpChatTransport` class. - * - * @param UI_MESSAGE - The type of message to be used in the chat. - */ -export type HttpChatTransportInitOptions = { - /** - * The API URL to be used for the chat transport. - * Defaults to '/api/chat'. - */ - api?: string; - - /** - * The credentials mode to be used for the fetch request. - * Possible values are: 'omit', 'same-origin', 'include'. - * Defaults to 'same-origin'. - */ - credentials?: Resolvable; - - /** - * HTTP headers to be sent with the API request. - */ - headers?: Resolvable | Headers>; - - /** - * Extra body object to be sent with the API request. - * @example - * Send a `sessionId` to the API along with the messages. - * ```js - * useChat({ - * body: { - * sessionId: '123', - * } - * }) - * ``` - */ - body?: Resolvable; - - /** - * Custom fetch implementation. You can use it as a middleware to intercept requests, - * or to provide a custom fetch implementation for e.g. testing. - */ - fetch?: FetchFunction; - - /** - * When a function is provided, it will be used - * to prepare the request body for the chat API. This can be useful for - * customizing the request body based on the messages and data in the chat. - */ - prepareSendMessagesRequest?: PrepareSendMessagesRequest; - - /** - * When a function is provided, it will be used - * to prepare the reconnect request for the chat API. This can be useful for - * customizing the request based on the chat session. - */ - prepareReconnectToStreamRequest?: PrepareReconnectToStreamRequest; -}; - -export abstract class HttpChatTransport< - UI_MESSAGE extends UIMessage, -> implements ChatTransport { - protected api: string; - protected credentials: HttpChatTransportInitOptions['credentials']; - protected headers: HttpChatTransportInitOptions['headers']; - protected body: HttpChatTransportInitOptions['body']; - protected fetch?: FetchFunction; - protected prepareSendMessagesRequest?: PrepareSendMessagesRequest; - protected prepareReconnectToStreamRequest?: PrepareReconnectToStreamRequest; - - constructor({ - api = '/api/chat', - credentials, - headers, - body, - fetch, - prepareSendMessagesRequest, - prepareReconnectToStreamRequest, - }: HttpChatTransportInitOptions) { - this.api = api; - this.credentials = credentials; - this.headers = headers; - this.body = body; - this.fetch = fetch; - this.prepareSendMessagesRequest = prepareSendMessagesRequest; - this.prepareReconnectToStreamRequest = prepareReconnectToStreamRequest; - } - - async sendMessages({ - abortSignal, - ...options - }: Parameters['sendMessages']>[0]) { - const resolvedBody = await resolve(this.body); - const resolvedHeaders = await resolve(this.headers); - const resolvedCredentials = await resolve(this.credentials); - - const baseHeaders = { - ...normalizeHeaders(resolvedHeaders), - ...normalizeHeaders(options.headers), - }; - - const preparedRequest = await this.prepareSendMessagesRequest?.({ - api: this.api, - id: options.chatId, - messages: options.messages, - body: { ...resolvedBody, ...options.body }, - headers: baseHeaders, - credentials: resolvedCredentials, - requestMetadata: options.metadata, - trigger: options.trigger, - messageId: options.messageId, - }); - - const api = preparedRequest?.api ?? this.api; - const headers = - preparedRequest?.headers !== undefined - ? normalizeHeaders(preparedRequest.headers) - : baseHeaders; - const body = - preparedRequest?.body !== undefined - ? preparedRequest.body - : { - ...resolvedBody, - ...options.body, - id: options.chatId, - messages: options.messages, - trigger: options.trigger, - messageId: options.messageId, - }; - const credentials = preparedRequest?.credentials ?? resolvedCredentials; - - // avoid caching globalThis.fetch in case it is patched by other libraries - const fetch = this.fetch ?? globalThis.fetch; - - const response = await fetch(api, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...headers, - }, - body: JSON.stringify(body), - credentials, - signal: abortSignal, - }); - - if (!response.ok) { - throw new Error( - (await response.text()) ?? 'Failed to fetch the chat response.', - ); - } - - if (!response.body) { - throw new Error('The response body is empty.'); - } - - return this.processResponseStream(response.body); - } - - async reconnectToStream( - options: Parameters['reconnectToStream']>[0], - ): Promise | null> { - const resolvedBody = await resolve(this.body); - const resolvedHeaders = await resolve(this.headers); - const resolvedCredentials = await resolve(this.credentials); - - const baseHeaders = { - ...normalizeHeaders(resolvedHeaders), - ...normalizeHeaders(options.headers), - }; - - const preparedRequest = await this.prepareReconnectToStreamRequest?.({ - api: this.api, - id: options.chatId, - body: { ...resolvedBody, ...options.body }, - headers: baseHeaders, - credentials: resolvedCredentials, - requestMetadata: options.metadata, - }); - - const api = preparedRequest?.api ?? `${this.api}/${options.chatId}/stream`; - const headers = - preparedRequest?.headers !== undefined - ? normalizeHeaders(preparedRequest.headers) - : baseHeaders; - const credentials = preparedRequest?.credentials ?? resolvedCredentials; - - // avoid caching globalThis.fetch in case it is patched by other libraries - const fetch = this.fetch ?? globalThis.fetch; - - const response = await fetch(api, { - method: 'GET', - headers, - credentials, - }); - - // no active stream found, so we do not resume - if (response.status === 204) { - return null; - } - - if (!response.ok) { - throw new Error( - (await response.text()) ?? 'Failed to fetch the chat response.', - ); - } - - if (!response.body) { - throw new Error('The response body is empty.'); - } - - return this.processResponseStream(response.body); - } - - protected abstract processResponseStream( - stream: ReadableStream>, - ): ReadableStream; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/index.ts deleted file mode 100644 index d8109eaf7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/index.ts +++ /dev/null @@ -1,72 +0,0 @@ -export { callCompletionApi } from './call-completion-api'; -export { - AbstractChat, - type ChatAddToolApproveResponseFunction, - type ChatAddToolOutputFunction, - type ChatInit, - type ChatOnDataCallback, - type ChatOnErrorCallback, - type ChatOnFinishCallback, - type ChatOnToolCallCallback, - type ChatRequestOptions, - type ChatState, - type ChatStatus, - type CreateUIMessage, - type InferUIDataParts, - type UIDataPartSchemas, -} from './chat'; -export { type ChatTransport } from './chat-transport'; -export { convertFileListToFileUIParts } from './convert-file-list-to-file-ui-parts'; -export { convertToModelMessages } from './convert-to-model-messages'; -export { DefaultChatTransport } from './default-chat-transport'; -export { - DirectChatTransport, - type DirectChatTransportOptions, -} from './direct-chat-transport'; -export { - HttpChatTransport, - type HttpChatTransportInitOptions, - type PrepareReconnectToStreamRequest, - type PrepareSendMessagesRequest, -} from './http-chat-transport'; -export { lastAssistantMessageIsCompleteWithApprovalResponses } from './last-assistant-message-is-complete-with-approval-responses'; -export { lastAssistantMessageIsCompleteWithToolCalls } from './last-assistant-message-is-complete-with-tool-calls'; -export { TextStreamChatTransport } from './text-stream-chat-transport'; -export { - getStaticToolName, - getToolName, - getToolOrDynamicToolName, - isDataUIPart, - isFileUIPart, - isReasoningUIPart, - isStaticToolUIPart, - isTextUIPart, - isToolOrDynamicToolUIPart, - isToolUIPart, - type DataUIPart, - type DynamicToolUIPart, - type FileUIPart, - type InferUITool, - type InferUITools, - type ReasoningUIPart, - type SourceDocumentUIPart, - type SourceUrlUIPart, - type StepStartUIPart, - type TextUIPart, - type ToolUIPart, - type UIDataTypes, - type UIMessage, - type UIMessagePart, - type UITool, - type UIToolInvocation, - type UITools, -} from './ui-messages'; -export { - type CompletionRequestOptions, - type UseCompletionOptions, -} from './use-completion'; -export { - safeValidateUIMessages, - validateUIMessages, - type SafeValidateUIMessagesResult, -} from './validate-ui-messages'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/last-assistant-message-is-complete-with-approval-responses.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/last-assistant-message-is-complete-with-approval-responses.ts deleted file mode 100644 index 55247e725..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/last-assistant-message-is-complete-with-approval-responses.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { isToolUIPart, type UIMessage } from './ui-messages'; - -/** - * Check if the last message is an assistant message with completed tool call approvals. - * The last step of the message must have at least one tool approval response and - * all tool approvals must have a response. - */ -export function lastAssistantMessageIsCompleteWithApprovalResponses({ - messages, -}: { - messages: UIMessage[]; -}): boolean { - const message = messages[messages.length - 1]; - - if (!message) { - return false; - } - - if (message.role !== 'assistant') { - return false; - } - - const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => { - return part.type === 'step-start' ? index : lastIndex; - }, -1); - - const lastStepToolInvocations = message.parts - .slice(lastStepStartIndex + 1) - .filter(isToolUIPart) - .filter(part => !part.providerExecuted); - - return ( - // has at least one tool approval response - lastStepToolInvocations.filter(part => part.state === 'approval-responded') - .length > 0 && - // all tool approvals must have a response - lastStepToolInvocations.every( - part => - part.state === 'output-available' || - part.state === 'output-error' || - part.state === 'approval-responded', - ) - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/last-assistant-message-is-complete-with-tool-calls.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/last-assistant-message-is-complete-with-tool-calls.ts deleted file mode 100644 index 29469bca8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/last-assistant-message-is-complete-with-tool-calls.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { isToolUIPart, type UIMessage } from './ui-messages'; - -/** - * Check if the last message is an assistant message with completed tool calls. - * The last step of the message must have at least one tool invocation and - * all tool invocations must have a result. - */ -export function lastAssistantMessageIsCompleteWithToolCalls({ - messages, -}: { - messages: UIMessage[]; -}): boolean { - const message = messages[messages.length - 1]; - - if (!message) { - return false; - } - - if (message.role !== 'assistant') { - return false; - } - - const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => { - return part.type === 'step-start' ? index : lastIndex; - }, -1); - - const lastStepToolInvocations = message.parts - .slice(lastStepStartIndex + 1) - .filter(isToolUIPart) - .filter(part => !part.providerExecuted); - - return ( - lastStepToolInvocations.length > 0 && - lastStepToolInvocations.every( - part => - part.state === 'output-available' || part.state === 'output-error', - ) - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/process-text-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/process-text-stream.ts deleted file mode 100644 index dc30eea74..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/process-text-stream.ts +++ /dev/null @@ -1,16 +0,0 @@ -export async function processTextStream({ - stream, - onTextPart, -}: { - stream: ReadableStream; - onTextPart: (chunk: string) => Promise | void; -}): Promise { - const reader = stream.pipeThrough(new TextDecoderStream()).getReader(); - while (true) { - const { done, value } = await reader.read(); - if (done) { - break; - } - await onTextPart(value); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/process-ui-message-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/process-ui-message-stream.ts deleted file mode 100644 index edc5b567c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/process-ui-message-stream.ts +++ /dev/null @@ -1,845 +0,0 @@ -import { TypeValidationContext } from '@ai-sdk/provider'; -import { FlexibleSchema, validateTypes } from '@ai-sdk/provider-utils'; -import { UIMessageStreamError } from '../error/ui-message-stream-error'; -import { ProviderMetadata } from '../types'; -import { FinishReason } from '../types/language-model'; -import { - DataUIMessageChunk, - InferUIMessageChunk, - isDataUIMessageChunk, - UIMessageChunk, -} from '../ui-message-stream/ui-message-chunks'; -import { ErrorHandler } from '../util/error-handler'; -import { mergeObjects } from '../util/merge-objects'; -import { parsePartialJson } from '../util/parse-partial-json'; -import { UIDataTypesToSchemas } from './chat'; -import { - DataUIPart, - DynamicToolUIPart, - getStaticToolName, - InferUIMessageData, - InferUIMessageMetadata, - InferUIMessageToolCall, - InferUIMessageTools, - isStaticToolUIPart, - isToolUIPart, - ReasoningUIPart, - TextUIPart, - ToolUIPart, - UIMessage, - UIMessagePart, -} from './ui-messages'; - -export type StreamingUIMessageState = { - message: UI_MESSAGE; - activeTextParts: Record; - activeReasoningParts: Record; - partialToolCalls: Record< - string, - { - text: string; - index: number; - toolName: string; - dynamic?: boolean; - title?: string; - } - >; - finishReason?: FinishReason; -}; - -export function createStreamingUIMessageState({ - lastMessage, - messageId, -}: { - lastMessage: UI_MESSAGE | undefined; - messageId: string; -}): StreamingUIMessageState { - return { - message: - lastMessage?.role === 'assistant' - ? lastMessage - : ({ - id: messageId, - metadata: undefined, - role: 'assistant', - parts: [] as UIMessagePart< - InferUIMessageData, - InferUIMessageTools - >[], - } as UI_MESSAGE), - activeTextParts: {}, - activeReasoningParts: {}, - partialToolCalls: {}, - }; -} - -export function processUIMessageStream({ - stream, - messageMetadataSchema, - dataPartSchemas, - runUpdateMessageJob, - onError, - onToolCall, - onData, -}: { - // input stream is not fully typed yet: - stream: ReadableStream; - messageMetadataSchema?: FlexibleSchema>; - dataPartSchemas?: UIDataTypesToSchemas>; - onToolCall?: (options: { - toolCall: InferUIMessageToolCall; - }) => void | PromiseLike; - onData?: (dataPart: DataUIPart>) => void; - runUpdateMessageJob: ( - job: (options: { - state: StreamingUIMessageState; - write: () => void; - }) => Promise, - ) => Promise; - onError: ErrorHandler; -}): ReadableStream> { - return stream.pipeThrough( - new TransformStream>({ - async transform(chunk, controller) { - await runUpdateMessageJob(async ({ state, write }) => { - function getToolInvocation(toolCallId: string) { - const toolInvocations = state.message.parts.filter(isToolUIPart); - - const toolInvocation = toolInvocations.find( - invocation => invocation.toolCallId === toolCallId, - ); - - if (toolInvocation == null) { - throw new UIMessageStreamError({ - chunkType: 'tool-invocation', - chunkId: toolCallId, - message: `No tool invocation found for tool call ID "${toolCallId}".`, - }); - } - - return toolInvocation; - } - - function updateToolPart( - options: { - toolName: keyof InferUIMessageTools & string; - toolCallId: string; - providerExecuted?: boolean; - title?: string; - } & ( - | { - state: 'input-streaming'; - input: unknown; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; - } - | { - state: 'input-available'; - input: unknown; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; - } - | { - state: 'output-available'; - input: unknown; - output: unknown; - providerExecuted?: boolean; - preliminary?: boolean; - providerMetadata?: ProviderMetadata; - } - | { - state: 'output-error'; - input: unknown; - rawInput?: unknown; - errorText: string; - providerExecuted?: boolean; - providerMetadata?: ProviderMetadata; - } - ), - ) { - const part = state.message.parts.find( - part => - isStaticToolUIPart(part) && - part.toolCallId === options.toolCallId, - ) as ToolUIPart> | undefined; - - const anyOptions = options as any; - const anyPart = part as any; - - if (part != null) { - part.state = options.state; - anyPart.input = anyOptions.input; - anyPart.output = anyOptions.output; - anyPart.errorText = anyOptions.errorText; - anyPart.rawInput = anyOptions.rawInput; - anyPart.preliminary = anyOptions.preliminary; - if (options.title !== undefined) { - anyPart.title = options.title; - } - // once providerExecuted is set, it stays for streaming - anyPart.providerExecuted = - anyOptions.providerExecuted ?? part.providerExecuted; - - const providerMetadata = anyOptions.providerMetadata; - - if (providerMetadata != null) { - if ( - options.state === 'output-available' || - options.state === 'output-error' - ) { - const resultPart = part as Extract< - ToolUIPart>, - { state: 'output-available' | 'output-error' } - >; - - resultPart.resultProviderMetadata = providerMetadata; - } else { - part.callProviderMetadata = providerMetadata; - } - } - } else { - state.message.parts.push({ - type: `tool-${options.toolName}`, - toolCallId: options.toolCallId, - state: options.state, - title: options.title, - input: anyOptions.input, - output: anyOptions.output, - rawInput: anyOptions.rawInput, - errorText: anyOptions.errorText, - providerExecuted: anyOptions.providerExecuted, - preliminary: anyOptions.preliminary, - ...(anyOptions.providerMetadata != null && - (options.state === 'output-available' || - options.state === 'output-error') - ? { resultProviderMetadata: anyOptions.providerMetadata } - : {}), - ...(anyOptions.providerMetadata != null && - !( - options.state === 'output-available' || - options.state === 'output-error' - ) - ? { callProviderMetadata: anyOptions.providerMetadata } - : {}), - } as ToolUIPart>); - } - } - - function updateDynamicToolPart( - options: { - toolName: keyof InferUIMessageTools & string; - toolCallId: string; - providerExecuted?: boolean; - title?: string; - } & ( - | { - state: 'input-streaming'; - input: unknown; - providerMetadata?: ProviderMetadata; - } - | { - state: 'input-available'; - input: unknown; - providerMetadata?: ProviderMetadata; - } - | { - state: 'output-available'; - input: unknown; - output: unknown; - preliminary: boolean | undefined; - providerMetadata?: ProviderMetadata; - } - | { - state: 'output-error'; - input: unknown; - errorText: string; - providerMetadata?: ProviderMetadata; - } - ), - ) { - const part = state.message.parts.find( - part => - part.type === 'dynamic-tool' && - part.toolCallId === options.toolCallId, - ) as DynamicToolUIPart | undefined; - - const anyOptions = options as any; - const anyPart = part as any; - - if (part != null) { - part.state = options.state; - anyPart.toolName = options.toolName; - anyPart.input = anyOptions.input; - anyPart.output = anyOptions.output; - anyPart.errorText = anyOptions.errorText; - anyPart.rawInput = anyOptions.rawInput ?? anyPart.rawInput; - anyPart.preliminary = anyOptions.preliminary; - if (options.title !== undefined) { - anyPart.title = options.title; - } - // once providerExecuted is set, it stays for streaming - anyPart.providerExecuted = - anyOptions.providerExecuted ?? part.providerExecuted; - - const providerMetadata = anyOptions.providerMetadata; - - if (providerMetadata != null) { - if ( - options.state === 'output-available' || - options.state === 'output-error' - ) { - const resultPart = part as Extract< - DynamicToolUIPart, - { state: 'output-available' | 'output-error' } - >; - - resultPart.resultProviderMetadata = providerMetadata; - } else { - part.callProviderMetadata = providerMetadata; - } - } - } else { - state.message.parts.push({ - type: 'dynamic-tool', - toolName: options.toolName, - toolCallId: options.toolCallId, - state: options.state, - input: anyOptions.input, - output: anyOptions.output, - errorText: anyOptions.errorText, - preliminary: anyOptions.preliminary, - providerExecuted: anyOptions.providerExecuted, - title: options.title, - ...(anyOptions.providerMetadata != null && - (options.state === 'output-available' || - options.state === 'output-error') - ? { resultProviderMetadata: anyOptions.providerMetadata } - : {}), - ...(anyOptions.providerMetadata != null && - !( - options.state === 'output-available' || - options.state === 'output-error' - ) - ? { callProviderMetadata: anyOptions.providerMetadata } - : {}), - } as DynamicToolUIPart); - } - } - - async function updateMessageMetadata(metadata: unknown) { - if (metadata != null) { - const mergedMetadata = - state.message.metadata != null - ? mergeObjects(state.message.metadata, metadata) - : metadata; - - if (messageMetadataSchema != null) { - await validateTypes({ - value: mergedMetadata, - schema: messageMetadataSchema, - context: { - field: 'message.metadata', - entityId: state.message.id, - }, - }); - } - - state.message.metadata = - mergedMetadata as InferUIMessageMetadata; - } - } - - switch (chunk.type) { - case 'text-start': { - const textPart: TextUIPart = { - type: 'text', - text: '', - providerMetadata: chunk.providerMetadata, - state: 'streaming', - }; - state.activeTextParts[chunk.id] = textPart; - state.message.parts.push(textPart); - write(); - break; - } - - case 'text-delta': { - const textPart = state.activeTextParts[chunk.id]; - if (textPart == null) { - throw new UIMessageStreamError({ - chunkType: 'text-delta', - chunkId: chunk.id, - message: - `Received text-delta for missing text part with ID "${chunk.id}". ` + - `Ensure a "text-start" chunk is sent before any "text-delta" chunks.`, - }); - } - textPart.text += chunk.delta; - textPart.providerMetadata = - chunk.providerMetadata ?? textPart.providerMetadata; - write(); - break; - } - - case 'text-end': { - const textPart = state.activeTextParts[chunk.id]; - if (textPart == null) { - throw new UIMessageStreamError({ - chunkType: 'text-end', - chunkId: chunk.id, - message: - `Received text-end for missing text part with ID "${chunk.id}". ` + - `Ensure a "text-start" chunk is sent before any "text-end" chunks.`, - }); - } - textPart.state = 'done'; - textPart.providerMetadata = - chunk.providerMetadata ?? textPart.providerMetadata; - delete state.activeTextParts[chunk.id]; - write(); - break; - } - - case 'reasoning-start': { - const reasoningPart: ReasoningUIPart = { - type: 'reasoning', - text: '', - providerMetadata: chunk.providerMetadata, - state: 'streaming', - }; - state.activeReasoningParts[chunk.id] = reasoningPart; - state.message.parts.push(reasoningPart); - write(); - break; - } - - case 'reasoning-delta': { - const reasoningPart = state.activeReasoningParts[chunk.id]; - if (reasoningPart == null) { - throw new UIMessageStreamError({ - chunkType: 'reasoning-delta', - chunkId: chunk.id, - message: - `Received reasoning-delta for missing reasoning part with ID "${chunk.id}". ` + - `Ensure a "reasoning-start" chunk is sent before any "reasoning-delta" chunks.`, - }); - } - reasoningPart.text += chunk.delta; - reasoningPart.providerMetadata = - chunk.providerMetadata ?? reasoningPart.providerMetadata; - write(); - break; - } - - case 'reasoning-end': { - const reasoningPart = state.activeReasoningParts[chunk.id]; - if (reasoningPart == null) { - throw new UIMessageStreamError({ - chunkType: 'reasoning-end', - chunkId: chunk.id, - message: - `Received reasoning-end for missing reasoning part with ID "${chunk.id}". ` + - `Ensure a "reasoning-start" chunk is sent before any "reasoning-end" chunks.`, - }); - } - reasoningPart.providerMetadata = - chunk.providerMetadata ?? reasoningPart.providerMetadata; - reasoningPart.state = 'done'; - delete state.activeReasoningParts[chunk.id]; - - write(); - break; - } - - case 'file': { - state.message.parts.push({ - type: 'file', - mediaType: chunk.mediaType, - url: chunk.url, - ...(chunk.providerMetadata != null - ? { providerMetadata: chunk.providerMetadata } - : {}), - }); - - write(); - break; - } - - case 'source-url': { - state.message.parts.push({ - type: 'source-url', - sourceId: chunk.sourceId, - url: chunk.url, - title: chunk.title, - providerMetadata: chunk.providerMetadata, - }); - - write(); - break; - } - - case 'source-document': { - state.message.parts.push({ - type: 'source-document', - sourceId: chunk.sourceId, - mediaType: chunk.mediaType, - title: chunk.title, - filename: chunk.filename, - providerMetadata: chunk.providerMetadata, - }); - - write(); - break; - } - - case 'tool-input-start': { - const toolInvocations = - state.message.parts.filter(isStaticToolUIPart); - - // add the partial tool call to the map - state.partialToolCalls[chunk.toolCallId] = { - text: '', - toolName: chunk.toolName, - index: toolInvocations.length, - dynamic: chunk.dynamic, - title: chunk.title, - }; - - if (chunk.dynamic) { - updateDynamicToolPart({ - toolCallId: chunk.toolCallId, - toolName: chunk.toolName, - state: 'input-streaming', - input: undefined, - providerExecuted: chunk.providerExecuted, - title: chunk.title, - providerMetadata: chunk.providerMetadata, - }); - } else { - updateToolPart({ - toolCallId: chunk.toolCallId, - toolName: chunk.toolName, - state: 'input-streaming', - input: undefined, - providerExecuted: chunk.providerExecuted, - title: chunk.title, - providerMetadata: chunk.providerMetadata, - }); - } - - write(); - break; - } - - case 'tool-input-delta': { - const partialToolCall = state.partialToolCalls[chunk.toolCallId]; - if (partialToolCall == null) { - throw new UIMessageStreamError({ - chunkType: 'tool-input-delta', - chunkId: chunk.toolCallId, - message: - `Received tool-input-delta for missing tool call with ID "${chunk.toolCallId}". ` + - `Ensure a "tool-input-start" chunk is sent before any "tool-input-delta" chunks.`, - }); - } - - partialToolCall.text += chunk.inputTextDelta; - - const { value: partialArgs } = await parsePartialJson( - partialToolCall.text, - ); - - if (partialToolCall.dynamic) { - updateDynamicToolPart({ - toolCallId: chunk.toolCallId, - toolName: partialToolCall.toolName, - state: 'input-streaming', - input: partialArgs, - title: partialToolCall.title, - }); - } else { - updateToolPart({ - toolCallId: chunk.toolCallId, - toolName: partialToolCall.toolName, - state: 'input-streaming', - input: partialArgs, - title: partialToolCall.title, - }); - } - - write(); - break; - } - - case 'tool-input-available': { - if (chunk.dynamic) { - updateDynamicToolPart({ - toolCallId: chunk.toolCallId, - toolName: chunk.toolName, - state: 'input-available', - input: chunk.input, - providerExecuted: chunk.providerExecuted, - providerMetadata: chunk.providerMetadata, - title: chunk.title, - }); - } else { - updateToolPart({ - toolCallId: chunk.toolCallId, - toolName: chunk.toolName, - state: 'input-available', - input: chunk.input, - providerExecuted: chunk.providerExecuted, - providerMetadata: chunk.providerMetadata, - title: chunk.title, - }); - } - - write(); - - // invoke the onToolCall callback if it exists. This is blocking. - // In the future we should make this non-blocking, which - // requires additional state management for error handling etc. - // Skip calling onToolCall for provider-executed tools since they are already executed - if (onToolCall && !chunk.providerExecuted) { - await onToolCall({ - toolCall: chunk as InferUIMessageToolCall, - }); - } - break; - } - - case 'tool-input-error': { - // When a part already exists for this toolCallId (e.g. from - // tool-input-start), honour its type so we update in place - // instead of creating a duplicate with a mismatched type. - const existingPart = state.message.parts - .filter(isToolUIPart) - .find(p => p.toolCallId === chunk.toolCallId); - const isDynamic = - existingPart != null - ? existingPart.type === 'dynamic-tool' - : !!chunk.dynamic; - - if (isDynamic) { - updateDynamicToolPart({ - toolCallId: chunk.toolCallId, - toolName: chunk.toolName, - state: 'output-error', - input: chunk.input, - errorText: chunk.errorText, - providerExecuted: chunk.providerExecuted, - providerMetadata: chunk.providerMetadata, - }); - } else { - updateToolPart({ - toolCallId: chunk.toolCallId, - toolName: chunk.toolName, - state: 'output-error', - input: undefined, - rawInput: chunk.input, - errorText: chunk.errorText, - providerExecuted: chunk.providerExecuted, - providerMetadata: chunk.providerMetadata, - }); - } - - write(); - break; - } - - case 'tool-approval-request': { - const toolInvocation = getToolInvocation(chunk.toolCallId); - toolInvocation.state = 'approval-requested'; - toolInvocation.approval = { id: chunk.approvalId }; - write(); - break; - } - - case 'tool-output-denied': { - const toolInvocation = getToolInvocation(chunk.toolCallId); - toolInvocation.state = 'output-denied'; - write(); - break; - } - - case 'tool-output-available': { - const toolInvocation = getToolInvocation(chunk.toolCallId); - - if (toolInvocation.type === 'dynamic-tool') { - updateDynamicToolPart({ - toolCallId: chunk.toolCallId, - toolName: toolInvocation.toolName, - state: 'output-available', - input: (toolInvocation as any).input, - output: chunk.output, - preliminary: chunk.preliminary, - providerExecuted: chunk.providerExecuted, - providerMetadata: chunk.providerMetadata, - title: toolInvocation.title, - }); - } else { - updateToolPart({ - toolCallId: chunk.toolCallId, - toolName: getStaticToolName(toolInvocation), - state: 'output-available', - input: (toolInvocation as any).input, - output: chunk.output, - providerExecuted: chunk.providerExecuted, - preliminary: chunk.preliminary, - providerMetadata: chunk.providerMetadata, - title: toolInvocation.title, - }); - } - - write(); - break; - } - - case 'tool-output-error': { - const toolInvocation = getToolInvocation(chunk.toolCallId); - - if (toolInvocation.type === 'dynamic-tool') { - updateDynamicToolPart({ - toolCallId: chunk.toolCallId, - toolName: toolInvocation.toolName, - state: 'output-error', - input: (toolInvocation as any).input, - errorText: chunk.errorText, - providerExecuted: chunk.providerExecuted, - providerMetadata: chunk.providerMetadata, - title: toolInvocation.title, - }); - } else { - updateToolPart({ - toolCallId: chunk.toolCallId, - toolName: getStaticToolName(toolInvocation), - state: 'output-error', - input: (toolInvocation as any).input, - rawInput: (toolInvocation as any).rawInput, - errorText: chunk.errorText, - providerExecuted: chunk.providerExecuted, - providerMetadata: chunk.providerMetadata, - title: toolInvocation.title, - }); - } - - write(); - break; - } - - case 'start-step': { - // add a step boundary part to the message - state.message.parts.push({ type: 'step-start' }); - break; - } - - case 'finish-step': { - // reset the current text and reasoning parts - state.activeTextParts = {}; - state.activeReasoningParts = {}; - break; - } - - case 'start': { - if (chunk.messageId != null) { - state.message.id = chunk.messageId; - } - - await updateMessageMetadata(chunk.messageMetadata); - - if (chunk.messageId != null || chunk.messageMetadata != null) { - write(); - } - break; - } - - case 'finish': { - if (chunk.finishReason != null) { - state.finishReason = chunk.finishReason; - } - await updateMessageMetadata(chunk.messageMetadata); - if (chunk.messageMetadata != null) { - write(); - } - break; - } - - case 'message-metadata': { - await updateMessageMetadata(chunk.messageMetadata); - if (chunk.messageMetadata != null) { - write(); - } - break; - } - - case 'error': { - onError?.(new Error(chunk.errorText)); - break; - } - - default: { - if (isDataUIMessageChunk(chunk)) { - // validate data chunk if dataPartSchemas is provided - if (dataPartSchemas?.[chunk.type] != null) { - const partIdx = state.message.parts.findIndex( - p => - 'id' in p && - 'data' in p && - p.id === chunk.id && - p.type === chunk.type, - ); - const actualPartIdx = - partIdx >= 0 ? partIdx : state.message.parts.length; - - await validateTypes({ - value: chunk.data, - schema: dataPartSchemas[chunk.type], - context: { - field: `message.parts[${actualPartIdx}].data`, - entityName: chunk.type, - entityId: chunk.id, - }, - }); - } - - // cast, validation is done above - const dataChunk = chunk as DataUIMessageChunk< - InferUIMessageData - >; - - // transient parts are not added to the message state - if (dataChunk.transient) { - onData?.(dataChunk); - break; - } - - const existingUIPart = - dataChunk.id != null - ? (state.message.parts.find( - chunkArg => - dataChunk.type === chunkArg.type && - dataChunk.id === chunkArg.id, - ) as - | DataUIPart> - | undefined) - : undefined; - - if (existingUIPart != null) { - existingUIPart.data = dataChunk.data; - } else { - state.message.parts.push(dataChunk); - } - - onData?.(dataChunk); - - write(); - } - } - } - - controller.enqueue(chunk as InferUIMessageChunk); - }); - }, - }), - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/text-stream-chat-transport.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/text-stream-chat-transport.ts deleted file mode 100644 index c140aca64..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/text-stream-chat-transport.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { UIMessageChunk } from '../ui-message-stream/ui-message-chunks'; -import { - HttpChatTransport, - HttpChatTransportInitOptions, -} from './http-chat-transport'; -import { transformTextToUiMessageStream } from './transform-text-to-ui-message-stream'; -import { UIMessage } from './ui-messages'; - -export class TextStreamChatTransport< - UI_MESSAGE extends UIMessage, -> extends HttpChatTransport { - constructor(options: HttpChatTransportInitOptions = {}) { - super(options); - } - - protected processResponseStream( - stream: ReadableStream>, - ): ReadableStream { - return transformTextToUiMessageStream({ - stream: stream.pipeThrough(new TextDecoderStream()), - }); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/transform-text-to-ui-message-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/transform-text-to-ui-message-stream.ts deleted file mode 100644 index 58749762f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/transform-text-to-ui-message-stream.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { UIMessageChunk } from '../ui-message-stream/ui-message-chunks'; - -export function transformTextToUiMessageStream({ - stream, -}: { - stream: ReadableStream; -}) { - return stream.pipeThrough( - new TransformStream({ - start(controller) { - controller.enqueue({ type: 'start' }); - controller.enqueue({ type: 'start-step' }); - controller.enqueue({ type: 'text-start', id: 'text-1' }); - }, - - async transform(part, controller) { - controller.enqueue({ type: 'text-delta', id: 'text-1', delta: part }); - }, - - async flush(controller) { - controller.enqueue({ type: 'text-end', id: 'text-1' }); - controller.enqueue({ type: 'finish-step' }); - controller.enqueue({ type: 'finish' }); - }, - }), - ); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/ui-messages.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/ui-messages.ts deleted file mode 100644 index ad22cc89a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/ui-messages.ts +++ /dev/null @@ -1,540 +0,0 @@ -import { - InferToolInput, - InferToolOutput, - Tool, - ToolCall, -} from '@ai-sdk/provider-utils'; -import { ToolSet } from '../generate-text'; -import { ProviderMetadata } from '../types/provider-metadata'; -import { DeepPartial } from '../util/deep-partial'; -import { ValueOf } from '../util/value-of'; - -/** - * The data types that can be used in the UI message for the UI message data parts. - */ -export type UIDataTypes = Record; - -export type UITool = { - input: unknown; - output: unknown | undefined; -}; - -/** - * Infer the input and output types of a tool so it can be used as a UI tool. - */ -export type InferUITool = { - input: InferToolInput; - output: InferToolOutput; -}; - -/** - * Infer the input and output types of a tool set so it can be used as a UI tool set. - */ -export type InferUITools = { - [NAME in keyof TOOLS & string]: InferUITool; -}; - -export type UITools = Record; - -/** - * AI SDK UI Messages. They are used in the client and to communicate between the frontend and the API routes. - */ -export interface UIMessage< - METADATA = unknown, - DATA_PARTS extends UIDataTypes = UIDataTypes, - TOOLS extends UITools = UITools, -> { - /** - * A unique identifier for the message. - */ - id: string; - - /** - * The role of the message. - */ - role: 'system' | 'user' | 'assistant'; - - /** - * The metadata of the message. - */ - metadata?: METADATA; - - /** - * The parts of the message. Use this for rendering the message in the UI. - * - * System messages should be avoided (set the system prompt on the server instead). - * They can have text parts. - * - * User messages can have text parts and file parts. - * - * Assistant messages can have text, reasoning, tool invocation, and file parts. - */ - parts: Array>; -} - -export type UIMessagePart< - DATA_TYPES extends UIDataTypes, - TOOLS extends UITools, -> = - | TextUIPart - | ReasoningUIPart - | ToolUIPart - | DynamicToolUIPart - | SourceUrlUIPart - | SourceDocumentUIPart - | FileUIPart - | DataUIPart - | StepStartUIPart; - -/** - * A text part of a message. - */ -export type TextUIPart = { - type: 'text'; - - /** - * The text content. - */ - text: string; - - /** - * The state of the text part. - */ - state?: 'streaming' | 'done'; - - /** - * The provider metadata. - */ - providerMetadata?: ProviderMetadata; -}; - -/** - * A reasoning part of a message. - */ -export type ReasoningUIPart = { - type: 'reasoning'; - - /** - * The reasoning text. - */ - text: string; - - /** - * The state of the reasoning part. - */ - state?: 'streaming' | 'done'; - - /** - * The provider metadata. - */ - providerMetadata?: ProviderMetadata; -}; - -/** - * A source part of a message. - */ -export type SourceUrlUIPart = { - type: 'source-url'; - sourceId: string; - url: string; - title?: string; - providerMetadata?: ProviderMetadata; -}; - -/** - * A document source part of a message. - */ -export type SourceDocumentUIPart = { - type: 'source-document'; - sourceId: string; - mediaType: string; - title: string; - filename?: string; - providerMetadata?: ProviderMetadata; -}; - -/** - * A file part of a message. - */ -export type FileUIPart = { - type: 'file'; - - /** - * IANA media type of the file. - * - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - mediaType: string; - - /** - * Optional filename of the file. - */ - filename?: string; - - /** - * The URL of the file. - * It can either be a URL to a hosted file or a [Data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs). - */ - url: string; - - /** - * The provider metadata. - */ - providerMetadata?: ProviderMetadata; -}; - -/** - * A step boundary part of a message. - */ -export type StepStartUIPart = { - type: 'step-start'; -}; - -export type DataUIPart = ValueOf<{ - [NAME in keyof DATA_TYPES & string]: { - type: `data-${NAME}`; - id?: string; - data: DATA_TYPES[NAME]; - }; -}>; - -type asUITool = TOOL extends Tool - ? InferUITool - : TOOL; - -/** - * Check if a message part is a data part. - */ -export function isDataUIPart( - part: UIMessagePart, -): part is DataUIPart { - return part.type.startsWith('data-'); -} - -/** - * A UI tool invocation contains all the information needed to render a tool invocation in the UI. - * It can be derived from a tool without knowing the tool name, and can be used to define - * UI components for the tool. - */ -export type UIToolInvocation = { - /** - * ID of the tool call. - */ - toolCallId: string; - title?: string; - - /** - * Whether the tool call was executed by the provider. - */ - providerExecuted?: boolean; -} & ( - | { - state: 'input-streaming'; - input: DeepPartial['input']> | undefined; - output?: never; - errorText?: never; - callProviderMetadata?: ProviderMetadata; - approval?: never; - } - | { - state: 'input-available'; - input: asUITool['input']; - output?: never; - errorText?: never; - callProviderMetadata?: ProviderMetadata; - approval?: never; - } - | { - state: 'approval-requested'; - input: asUITool['input']; - output?: never; - errorText?: never; - callProviderMetadata?: ProviderMetadata; - approval: { - id: string; - approved?: never; - reason?: never; - }; - } - | { - state: 'approval-responded'; - input: asUITool['input']; - output?: never; - errorText?: never; - callProviderMetadata?: ProviderMetadata; - approval: { - id: string; - approved: boolean; - reason?: string; - }; - } - | { - state: 'output-available'; - input: asUITool['input']; - output: asUITool['output']; - errorText?: never; - callProviderMetadata?: ProviderMetadata; - resultProviderMetadata?: ProviderMetadata; - preliminary?: boolean; - approval?: { - id: string; - approved: true; - reason?: string; - }; - } - | { - state: 'output-error'; // TODO AI SDK 6: change to 'error' state - input: asUITool['input'] | undefined; - rawInput?: unknown; // TODO AI SDK 6: remove this field, input should be unknown - output?: never; - errorText: string; - callProviderMetadata?: ProviderMetadata; - resultProviderMetadata?: ProviderMetadata; - approval?: { - id: string; - approved: true; - reason?: string; - }; - } - | { - state: 'output-denied'; - input: asUITool['input']; - output?: never; - errorText?: never; - callProviderMetadata?: ProviderMetadata; - approval: { - id: string; - approved: false; - reason?: string; - }; - } -); - -export type ToolUIPart = ValueOf<{ - [NAME in keyof TOOLS & string]: { - type: `tool-${NAME}`; - } & UIToolInvocation; -}>; - -export type DynamicToolUIPart = { - type: 'dynamic-tool'; - - /** - * Name of the tool that is being called. - */ - toolName: string; - - /** - * ID of the tool call. - */ - toolCallId: string; - title?: string; - - /** - * Whether the tool call was executed by the provider. - */ - providerExecuted?: boolean; -} & ( - | { - state: 'input-streaming'; - input: unknown | undefined; - output?: never; - errorText?: never; - callProviderMetadata?: ProviderMetadata; - approval?: never; - } - | { - state: 'input-available'; - input: unknown; - output?: never; - errorText?: never; - callProviderMetadata?: ProviderMetadata; - approval?: never; - } - | { - state: 'approval-requested'; - input: unknown; - output?: never; - errorText?: never; - callProviderMetadata?: ProviderMetadata; - approval: { - id: string; - approved?: never; - reason?: never; - }; - } - | { - state: 'approval-responded'; - input: unknown; - output?: never; - errorText?: never; - callProviderMetadata?: ProviderMetadata; - approval: { - id: string; - approved: boolean; - reason?: string; - }; - } - | { - state: 'output-available'; - input: unknown; - output: unknown; - errorText?: never; - callProviderMetadata?: ProviderMetadata; - resultProviderMetadata?: ProviderMetadata; - preliminary?: boolean; - approval?: { - id: string; - approved: true; - reason?: string; - }; - } - | { - state: 'output-error'; // TODO AI SDK 6: change to 'error' state - input: unknown; - output?: never; - errorText: string; - callProviderMetadata?: ProviderMetadata; - resultProviderMetadata?: ProviderMetadata; - approval?: { - id: string; - approved: true; - reason?: string; - }; - } - | { - state: 'output-denied'; - input: unknown; - output?: never; - errorText?: never; - callProviderMetadata?: ProviderMetadata; - approval: { - id: string; - approved: false; - reason?: string; - }; - } -); - -/** - * Type guard to check if a message part is a text part. - */ -export function isTextUIPart( - part: UIMessagePart, -): part is TextUIPart { - return part.type === 'text'; -} - -/** - * Type guard to check if a message part is a file part. - */ -export function isFileUIPart( - part: UIMessagePart, -): part is FileUIPart { - return part.type === 'file'; -} - -/** - * Type guard to check if a message part is a reasoning part. - */ -export function isReasoningUIPart( - part: UIMessagePart, -): part is ReasoningUIPart { - return part.type === 'reasoning'; -} - -/** - * Check if a message part is a static tool part. - * - * Static tools are tools for which the types are known at development time. - */ -export function isStaticToolUIPart( - part: UIMessagePart, -): part is ToolUIPart { - return part.type.startsWith('tool-'); -} - -/** - * Check if a message part is a dynamic tool part. - * - * Dynamic tools are tools for which the input and output types are unknown. - */ -export function isDynamicToolUIPart( - part: UIMessagePart, -): part is DynamicToolUIPart { - return part.type === 'dynamic-tool'; -} - -/** - * Check if a message part is a tool part. - * - * Tool parts are either static or dynamic tools. - * - * Use `isStaticToolUIPart` or `isDynamicToolUIPart` to check the type of the tool. - */ -export function isToolUIPart( - part: UIMessagePart, -): part is ToolUIPart | DynamicToolUIPart { - return isStaticToolUIPart(part) || isDynamicToolUIPart(part); -} - -/** - * @deprecated Use isToolUIPart instead. - */ -export const isToolOrDynamicToolUIPart = isToolUIPart; - -/** - * Returns the name of the static tool. - * - * The possible values are the keys of the tool set. - */ -export function getStaticToolName( - part: ToolUIPart, -): keyof TOOLS { - return part.type.split('-').slice(1).join('-') as keyof TOOLS; -} - -/** - * Returns the name of the tool (static or dynamic). - * - * This function will not restrict the name to the keys of the tool set. - * If you need to restrict the name to the keys of the tool set, use `getStaticToolName` instead. - */ -export function getToolName( - part: ToolUIPart | DynamicToolUIPart, -): string { - return isDynamicToolUIPart(part) ? part.toolName : getStaticToolName(part); -} - -/** - * @deprecated Use getToolName instead. - */ -export const getToolOrDynamicToolName = getToolName; - -export type InferUIMessageMetadata = - T extends UIMessage ? METADATA : unknown; - -export type InferUIMessageData = - T extends UIMessage ? DATA_TYPES : UIDataTypes; - -export type InferUIMessageTools = - T extends UIMessage ? TOOLS : UITools; - -export type InferUIMessageToolOutputs = - InferUIMessageTools[keyof InferUIMessageTools]['output']; - -export type InferUIMessageToolCall = - | ValueOf<{ - [NAME in keyof InferUIMessageTools]: ToolCall< - NAME & string, - InferUIMessageTools[NAME] extends { input: infer INPUT } - ? INPUT - : never - > & { dynamic?: false }; - }> - | (ToolCall & { dynamic: true }); - -export type InferUIMessagePart = UIMessagePart< - InferUIMessageData, - InferUIMessageTools ->; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/use-completion.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/use-completion.ts deleted file mode 100644 index 0b03d91a9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/use-completion.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { FetchFunction } from '@ai-sdk/provider-utils'; - -export type CompletionRequestOptions = { - /** - * An optional object of headers to be passed to the API endpoint. - */ - headers?: Record | Headers; - - /** - * An optional object to be passed to the API endpoint. - */ - body?: object; -}; - -export type UseCompletionOptions = { - /** - * The API endpoint that accepts a `{ prompt: string }` object and returns - * a stream of tokens of the AI completion response. Defaults to `/api/completion`. - */ - api?: string; - /** - * A unique identifier for the completion. If not provided, a random one will be - * generated. When provided, the `useCompletion` hook with the same `id` will - * have shared states across components. - */ - id?: string; - - /** - * Initial prompt input of the completion. - */ - initialInput?: string; - - /** - * Initial completion result. Useful to load an existing history. - */ - initialCompletion?: string; - - /** - * Callback function to be called when the completion is finished streaming. - */ - onFinish?: (prompt: string, completion: string) => void; - - /** - * Callback function to be called when an error is encountered. - */ - onError?: (error: Error) => void; - - /** - * The credentials mode to be used for the fetch request. - * Possible values are: 'omit', 'same-origin', 'include'. - * Defaults to 'same-origin'. - */ - credentials?: RequestCredentials; - - /** - * HTTP headers to be sent with the API request. - */ - headers?: Record | Headers; - - /** - * Extra body object to be sent with the API request. - * @example - * Send a `sessionId` to the API along with the prompt. - * ```js - * useCompletion({ - * body: { - * sessionId: '123', - * } - * }) - * ``` - */ - body?: object; - - /** - * Streaming protocol that is used. Defaults to `data`. - */ - streamProtocol?: 'data' | 'text'; - - /** - * Custom fetch implementation. You can use it as a middleware to intercept requests, - * or to provide a custom fetch implementation for e.g. testing. - */ - fetch?: FetchFunction; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/validate-ui-messages.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/validate-ui-messages.ts deleted file mode 100644 index 1aa1b1891..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/ui/validate-ui-messages.ts +++ /dev/null @@ -1,510 +0,0 @@ -import { TypeValidationContext, TypeValidationError } from '@ai-sdk/provider'; -import { - FlexibleSchema, - lazySchema, - StandardSchemaV1, - Tool, - validateTypes, - zodSchema, -} from '@ai-sdk/provider-utils'; -import { z } from 'zod/v4'; -import { InvalidArgumentError } from '../error'; -import { providerMetadataSchema } from '../types/provider-metadata'; -import { - DataUIPart, - InferUIMessageData, - InferUIMessageTools, - ToolUIPart, - UIMessage, -} from './ui-messages'; - -const uiMessagesSchema = lazySchema(() => - zodSchema( - z - .array( - z.object({ - id: z.string(), - role: z.enum(['system', 'user', 'assistant']), - metadata: z.unknown().optional(), - parts: z - .array( - z.union([ - z.object({ - type: z.literal('text'), - text: z.string(), - state: z.enum(['streaming', 'done']).optional(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('reasoning'), - text: z.string(), - state: z.enum(['streaming', 'done']).optional(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('source-url'), - sourceId: z.string(), - url: z.string(), - title: z.string().optional(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('source-document'), - sourceId: z.string(), - mediaType: z.string(), - title: z.string(), - filename: z.string().optional(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('file'), - mediaType: z.string(), - filename: z.string().optional(), - url: z.string(), - providerMetadata: providerMetadataSchema.optional(), - }), - z.object({ - type: z.literal('step-start'), - }), - z.object({ - type: z.string().startsWith('data-'), - id: z.string().optional(), - data: z.unknown(), - }), - z.object({ - type: z.literal('dynamic-tool'), - toolName: z.string(), - toolCallId: z.string(), - state: z.literal('input-streaming'), - input: z.unknown().optional(), - providerExecuted: z.boolean().optional(), - callProviderMetadata: providerMetadataSchema.optional(), - output: z.never().optional(), - errorText: z.never().optional(), - approval: z.never().optional(), - }), - z.object({ - type: z.literal('dynamic-tool'), - toolName: z.string(), - toolCallId: z.string(), - state: z.literal('input-available'), - input: z.unknown(), - providerExecuted: z.boolean().optional(), - output: z.never().optional(), - errorText: z.never().optional(), - callProviderMetadata: providerMetadataSchema.optional(), - approval: z.never().optional(), - }), - z.object({ - type: z.literal('dynamic-tool'), - toolName: z.string(), - toolCallId: z.string(), - state: z.literal('approval-requested'), - input: z.unknown(), - providerExecuted: z.boolean().optional(), - output: z.never().optional(), - errorText: z.never().optional(), - callProviderMetadata: providerMetadataSchema.optional(), - approval: z.object({ - id: z.string(), - approved: z.never().optional(), - reason: z.never().optional(), - }), - }), - z.object({ - type: z.literal('dynamic-tool'), - toolName: z.string(), - toolCallId: z.string(), - state: z.literal('approval-responded'), - input: z.unknown(), - providerExecuted: z.boolean().optional(), - output: z.never().optional(), - errorText: z.never().optional(), - callProviderMetadata: providerMetadataSchema.optional(), - approval: z.object({ - id: z.string(), - approved: z.boolean(), - reason: z.string().optional(), - }), - }), - z.object({ - type: z.literal('dynamic-tool'), - toolName: z.string(), - toolCallId: z.string(), - state: z.literal('output-available'), - input: z.unknown(), - providerExecuted: z.boolean().optional(), - output: z.unknown(), - errorText: z.never().optional(), - callProviderMetadata: providerMetadataSchema.optional(), - resultProviderMetadata: providerMetadataSchema.optional(), - preliminary: z.boolean().optional(), - approval: z - .object({ - id: z.string(), - approved: z.literal(true), - reason: z.string().optional(), - }) - .optional(), - }), - z.object({ - type: z.literal('dynamic-tool'), - toolName: z.string(), - toolCallId: z.string(), - state: z.literal('output-error'), - input: z.unknown(), - rawInput: z.unknown().optional(), - providerExecuted: z.boolean().optional(), - output: z.never().optional(), - errorText: z.string(), - callProviderMetadata: providerMetadataSchema.optional(), - resultProviderMetadata: providerMetadataSchema.optional(), - approval: z - .object({ - id: z.string(), - approved: z.literal(true), - reason: z.string().optional(), - }) - .optional(), - }), - z.object({ - type: z.literal('dynamic-tool'), - toolName: z.string(), - toolCallId: z.string(), - state: z.literal('output-denied'), - input: z.unknown(), - providerExecuted: z.boolean().optional(), - output: z.never().optional(), - errorText: z.never().optional(), - callProviderMetadata: providerMetadataSchema.optional(), - approval: z.object({ - id: z.string(), - approved: z.literal(false), - reason: z.string().optional(), - }), - }), - z.object({ - type: z.string().startsWith('tool-'), - toolCallId: z.string(), - state: z.literal('input-streaming'), - providerExecuted: z.boolean().optional(), - callProviderMetadata: providerMetadataSchema.optional(), - input: z.unknown().optional(), - output: z.never().optional(), - errorText: z.never().optional(), - approval: z.never().optional(), - }), - z.object({ - type: z.string().startsWith('tool-'), - toolCallId: z.string(), - state: z.literal('input-available'), - providerExecuted: z.boolean().optional(), - input: z.unknown(), - output: z.never().optional(), - errorText: z.never().optional(), - callProviderMetadata: providerMetadataSchema.optional(), - approval: z.never().optional(), - }), - z.object({ - type: z.string().startsWith('tool-'), - toolCallId: z.string(), - state: z.literal('approval-requested'), - input: z.unknown(), - providerExecuted: z.boolean().optional(), - output: z.never().optional(), - errorText: z.never().optional(), - callProviderMetadata: providerMetadataSchema.optional(), - approval: z.object({ - id: z.string(), - approved: z.never().optional(), - reason: z.never().optional(), - }), - }), - z.object({ - type: z.string().startsWith('tool-'), - toolCallId: z.string(), - state: z.literal('approval-responded'), - input: z.unknown(), - providerExecuted: z.boolean().optional(), - output: z.never().optional(), - errorText: z.never().optional(), - callProviderMetadata: providerMetadataSchema.optional(), - approval: z.object({ - id: z.string(), - approved: z.boolean(), - reason: z.string().optional(), - }), - }), - z.object({ - type: z.string().startsWith('tool-'), - toolCallId: z.string(), - state: z.literal('output-available'), - providerExecuted: z.boolean().optional(), - input: z.unknown(), - output: z.unknown(), - errorText: z.never().optional(), - callProviderMetadata: providerMetadataSchema.optional(), - resultProviderMetadata: providerMetadataSchema.optional(), - preliminary: z.boolean().optional(), - approval: z - .object({ - id: z.string(), - approved: z.literal(true), - reason: z.string().optional(), - }) - .optional(), - }), - z.object({ - type: z.string().startsWith('tool-'), - toolCallId: z.string(), - state: z.literal('output-error'), - providerExecuted: z.boolean().optional(), - input: z.unknown(), - rawInput: z.unknown().optional(), - output: z.never().optional(), - errorText: z.string(), - callProviderMetadata: providerMetadataSchema.optional(), - resultProviderMetadata: providerMetadataSchema.optional(), - approval: z - .object({ - id: z.string(), - approved: z.literal(true), - reason: z.string().optional(), - }) - .optional(), - }), - z.object({ - type: z.string().startsWith('tool-'), - toolCallId: z.string(), - state: z.literal('output-denied'), - providerExecuted: z.boolean().optional(), - input: z.unknown(), - output: z.never().optional(), - errorText: z.never().optional(), - callProviderMetadata: providerMetadataSchema.optional(), - approval: z.object({ - id: z.string(), - approved: z.literal(false), - reason: z.string().optional(), - }), - }), - ]), - ) - .nonempty('Message must contain at least one part'), - }), - ) - .nonempty('Messages array must not be empty'), - ), -); - -export type SafeValidateUIMessagesResult = - | { - success: true; - data: Array; - } - | { - success: false; - error: Error; - }; - -/** - * Validates a list of UI messages like `validateUIMessages`, - * but instead of throwing it returns `{ success: true, data }` - * or `{ success: false, error }`. - */ -export async function safeValidateUIMessages({ - messages, - metadataSchema, - dataSchemas, - tools, -}: { - messages: unknown; - metadataSchema?: FlexibleSchema; - dataSchemas?: { - [NAME in keyof InferUIMessageData & string]?: FlexibleSchema< - InferUIMessageData[NAME] - >; - }; - tools?: { - [NAME in keyof InferUIMessageTools & string]?: Tool< - InferUIMessageTools[NAME]['input'], - InferUIMessageTools[NAME]['output'] - >; - }; -}): Promise> { - try { - if (messages == null) { - return { - success: false, - error: new InvalidArgumentError({ - parameter: 'messages', - value: messages, - message: 'messages parameter must be provided', - }), - }; - } - - const validatedMessages = await validateTypes({ - value: messages, - schema: uiMessagesSchema, - }); - - if (metadataSchema) { - for (const [msgIdx, message] of validatedMessages.entries()) { - await validateTypes({ - value: message.metadata, - schema: metadataSchema, - context: { - field: `messages[${msgIdx}].metadata`, - entityId: message.id, - }, - }); - } - } - - if (dataSchemas || tools) { - for (const [msgIdx, message] of validatedMessages.entries()) { - for (const [partIdx, part] of message.parts.entries()) { - // Data part validation - if (dataSchemas && part.type.startsWith('data-')) { - const dataPart = part as DataUIPart>; - const dataName = dataPart.type.slice(5); - const dataSchema = dataSchemas[dataName]; - - if (!dataSchema) { - return { - success: false, - error: new TypeValidationError({ - value: dataPart.data, - cause: `No data schema found for data part ${dataName}`, - context: { - field: `messages[${msgIdx}].parts[${partIdx}].data`, - entityName: dataName, - entityId: dataPart.id, - }, - }), - }; - } - - await validateTypes({ - value: dataPart.data, - schema: dataSchema, - context: { - field: `messages[${msgIdx}].parts[${partIdx}].data`, - entityName: dataName, - entityId: dataPart.id, - }, - }); - } - - // Tool part validation - if (tools && part.type.startsWith('tool-')) { - const toolPart = part as ToolUIPart< - InferUIMessageTools - >; - const toolName = toolPart.type.slice(5); - const tool = tools[toolName]; - - // TODO support dynamic tools - if (!tool) { - return { - success: false, - error: new TypeValidationError({ - value: toolPart.input, - cause: `No tool schema found for tool part ${toolName}`, - context: { - field: `messages[${msgIdx}].parts[${partIdx}].input`, - entityName: toolName, - entityId: toolPart.toolCallId, - }, - }), - }; - } - - // Tool input validation - if ( - toolPart.state === 'input-available' || - toolPart.state === 'output-available' || - (toolPart.state === 'output-error' && - toolPart.input !== undefined) - ) { - await validateTypes({ - value: toolPart.input, - schema: tool.inputSchema, - context: { - field: `messages[${msgIdx}].parts[${partIdx}].input`, - entityName: toolName, - entityId: toolPart.toolCallId, - }, - }); - } - - // Tool output validation - if (toolPart.state === 'output-available' && tool.outputSchema) { - await validateTypes({ - value: toolPart.output, - schema: tool.outputSchema, - context: { - field: `messages[${msgIdx}].parts[${partIdx}].output`, - entityName: toolName, - entityId: toolPart.toolCallId, - }, - }); - } - } - } - } - } - - return { - success: true, - data: validatedMessages as Array, - }; - } catch (error) { - const err = error as Error; - - return { - success: false, - error: err, - }; - } -} - -/** - * Validates a list of UI messages. - * - * Metadata, data parts, and generic tool call structures are only validated if - * the corresponding schemas are provided. Otherwise, they are assumed to be - * valid. - */ -export async function validateUIMessages({ - messages, - metadataSchema, - dataSchemas, - tools, -}: { - messages: unknown; - metadataSchema?: FlexibleSchema; - dataSchemas?: { - [NAME in keyof InferUIMessageData & string]?: FlexibleSchema< - InferUIMessageData[NAME] - >; - }; - tools?: { - [NAME in keyof InferUIMessageTools & string]?: Tool< - InferUIMessageTools[NAME]['input'], - InferUIMessageTools[NAME]['output'] - >; - }; -}): Promise> { - const response = await safeValidateUIMessages({ - messages, - metadataSchema, - dataSchemas, - tools, - }); - - if (!response.success) throw response.error; - - return response.data; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/as-array.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/as-array.ts deleted file mode 100644 index 3a9a1a9ab..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/as-array.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function asArray(value: T | T[] | undefined): T[] { - return value === undefined ? [] : Array.isArray(value) ? value : [value]; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/async-iterable-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/async-iterable-stream.ts deleted file mode 100644 index b92d403bb..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/async-iterable-stream.ts +++ /dev/null @@ -1,94 +0,0 @@ -/** - * A type that combines AsyncIterable and ReadableStream. - * This allows a ReadableStream to be consumed using for-await-of syntax. - */ -export type AsyncIterableStream = AsyncIterable & ReadableStream; - -/** - * Wraps a ReadableStream and returns an object that is both a ReadableStream and an AsyncIterable. - * This enables consumption of the stream using for-await-of, with proper resource cleanup on early exit or error. - * - * @template T The type of the stream's chunks. - * @param source The source ReadableStream to wrap. - * @returns An AsyncIterableStream that can be used as both a ReadableStream and an AsyncIterable. - */ -export function createAsyncIterableStream( - source: ReadableStream, -): AsyncIterableStream { - // Pipe through a TransformStream to ensure a fresh, unlocked stream. - const stream = source.pipeThrough(new TransformStream()); - - /** - * Implements the async iterator protocol for the stream. - * Ensures proper cleanup (cancelling and releasing the reader) on completion, early exit, or error. - */ - (stream as AsyncIterableStream)[Symbol.asyncIterator] = function ( - this: ReadableStream, - ): AsyncIterator { - const reader = this.getReader(); - - let finished = false; - - /** - * Cleans up the reader by cancelling and releasing the lock. - */ - async function cleanup(cancelStream: boolean) { - if (finished) return; - - finished = true; - try { - if (cancelStream) { - await reader.cancel?.(); - } - } finally { - try { - reader.releaseLock(); - } catch {} - } - } - - return { - /** - * Reads the next chunk from the stream. - * @returns A promise resolving to the next IteratorResult. - */ - async next(): Promise> { - if (finished) { - return { done: true, value: undefined }; - } - - const { done, value } = await reader.read(); - - if (done) { - await cleanup(true); - return { done: true, value: undefined }; - } - - return { done: false, value }; - }, - - /** - * May be called on early exit (e.g., break from for-await) or after completion. - * Ensures the stream is cancelled and resources are released. - * @returns A promise resolving to a completed IteratorResult. - */ - async return(): Promise> { - await cleanup(true); - return { done: true, value: undefined }; - }, - - /** - * Called on early exit with error. - * Ensures the stream is cancelled and resources are released, then rethrows the error. - * @param err The error to throw. - * @returns A promise that rejects with the provided error. - */ - async throw(err: unknown): Promise> { - await cleanup(true); - throw err; - }, - }; - }; - - return stream as AsyncIterableStream; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/consume-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/consume-stream.ts deleted file mode 100644 index c5a6e2039..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/consume-stream.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Consumes a ReadableStream until it's fully read. - * - * This function reads the stream chunk by chunk until the stream is exhausted. - * It doesn't process or return the data from the stream; it simply ensures - * that the entire stream is read. - * - * @param options - The options for consuming the stream. - * @param options.stream - The ReadableStream to be consumed. - * @param options.onError - Optional callback to handle errors that occur during consumption. - * @returns A promise that resolves when the stream is fully consumed. - */ -export async function consumeStream({ - stream, - onError, -}: { - stream: ReadableStream; - onError?: (error: unknown) => void; -}): Promise { - const reader = stream.getReader(); - try { - while (true) { - const { done } = await reader.read(); - if (done) break; - } - } catch (error) { - onError?.(error); - } finally { - reader.releaseLock(); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/cosine-similarity.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/cosine-similarity.ts deleted file mode 100644 index a01b200a9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/cosine-similarity.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { InvalidArgumentError } from '../error/invalid-argument-error'; - -/** - * Calculates the cosine similarity between two vectors. This is a useful metric for - * comparing the similarity of two vectors such as embeddings. - * - * @param vector1 - The first vector. - * @param vector2 - The second vector. - * - * @returns The cosine similarity between vector1 and vector2, or 0 if either vector is the zero vector. - * - * @throws {InvalidArgumentError} If the vectors do not have the same length. - */ -export function cosineSimilarity(vector1: number[], vector2: number[]): number { - if (vector1.length !== vector2.length) { - throw new InvalidArgumentError({ - parameter: 'vector1,vector2', - value: { vector1Length: vector1.length, vector2Length: vector2.length }, - message: `Vectors must have the same length`, - }); - } - - const n = vector1.length; - - if (n === 0) { - return 0; // Return 0 for empty vectors if no error is thrown - } - - let magnitudeSquared1 = 0; - let magnitudeSquared2 = 0; - let dotProduct = 0; - - for (let i = 0; i < n; i++) { - const value1 = vector1[i]; - const value2 = vector2[i]; - - magnitudeSquared1 += value1 * value1; - magnitudeSquared2 += value2 * value2; - dotProduct += value1 * value2; - } - - return magnitudeSquared1 === 0 || magnitudeSquared2 === 0 - ? 0 - : dotProduct / - (Math.sqrt(magnitudeSquared1) * Math.sqrt(magnitudeSquared2)); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/create-resolvable-promise.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/create-resolvable-promise.ts deleted file mode 100644 index 76271088d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/create-resolvable-promise.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { ErrorHandler } from './error-handler'; - -/** - * Creates a Promise with externally accessible resolve and reject functions. - * - * @template T - The type of the value that the Promise will resolve to. - * @returns An object containing: - * - promise: A Promise that can be resolved or rejected externally. - * - resolve: A function to resolve the Promise with a value of type T. - * - reject: A function to reject the Promise with an error. - */ -export function createResolvablePromise(): { - promise: Promise; - resolve: (value: T) => void; - reject: ErrorHandler; -} { - let resolve: (value: T) => void; - let reject: ErrorHandler; - - const promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - - return { - promise, - resolve: resolve!, - reject: reject!, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/create-stitchable-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/create-stitchable-stream.ts deleted file mode 100644 index afcc75827..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/create-stitchable-stream.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { createResolvablePromise } from './create-resolvable-promise'; - -/** - * Creates a stitchable stream that can pipe one stream at a time. - * - * @template T - The type of values emitted by the streams. - * @returns {Object} An object containing the stitchable stream and control methods. - */ -export function createStitchableStream(): { - stream: ReadableStream; - addStream: (innerStream: ReadableStream) => void; - close: () => void; - terminate: () => void; -} { - let innerStreamReaders: ReadableStreamDefaultReader[] = []; - let controller: ReadableStreamDefaultController | null = null; - let isClosed = false; - let waitForNewStream = createResolvablePromise(); - - const terminate = () => { - isClosed = true; - waitForNewStream.resolve(); - - innerStreamReaders.forEach(reader => reader.cancel()); - innerStreamReaders = []; - controller?.close(); - }; - - const processPull = async () => { - // Case 1: Outer stream is closed and no more inner streams - if (isClosed && innerStreamReaders.length === 0) { - controller?.close(); - return; - } - - // Case 2: No inner streams available, but outer stream is open - // wait for a new inner stream to be added or the outer stream to close - if (innerStreamReaders.length === 0) { - waitForNewStream = createResolvablePromise(); - await waitForNewStream.promise; - return processPull(); - } - - try { - const { value, done } = await innerStreamReaders[0].read(); - - if (done) { - // Case 3: Current inner stream is done - innerStreamReaders.shift(); // Remove the finished stream - - if (innerStreamReaders.length === 0 && isClosed) { - // when closed and no more inner streams, stop pulling - controller?.close(); - } else { - // continue pulling from the next stream - await processPull(); - } - } else { - // Case 4: Current inner stream returns an item - controller?.enqueue(value); - } - } catch (error) { - // Case 5: Current inner stream throws an error - controller?.error(error); - innerStreamReaders.shift(); // Remove the errored stream - terminate(); // we have errored, terminate all streams - } - }; - - return { - stream: new ReadableStream({ - start(controllerParam) { - controller = controllerParam; - }, - pull: processPull, - async cancel() { - for (const reader of innerStreamReaders) { - await reader.cancel(); - } - innerStreamReaders = []; - isClosed = true; - }, - }), - addStream: (innerStream: ReadableStream) => { - if (isClosed) { - throw new Error('Cannot add inner stream: outer stream is closed'); - } - - innerStreamReaders.push(innerStream.getReader()); - waitForNewStream.resolve(); - }, - - /** - * Gracefully close the outer stream. This will let the inner streams - * finish processing and then close the outer stream. - */ - close: () => { - isClosed = true; - waitForNewStream.resolve(); - - if (innerStreamReaders.length === 0) { - controller?.close(); - } - }, - - /** - * Immediately close the outer stream. This will cancel all inner streams - * and close the outer stream. - */ - terminate, - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/data-url.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/data-url.ts deleted file mode 100644 index 101349627..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/data-url.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Converts a data URL of type text/* to a text string. - */ -export function getTextFromDataUrl(dataUrl: string): string { - const [header, base64Content] = dataUrl.split(','); - const mediaType = header.split(';')[0].split(':')[1]; - - if (mediaType == null || base64Content == null) { - throw new Error('Invalid data URL format'); - } - - try { - return window.atob(base64Content); - } catch (error) { - throw new Error(`Error decoding data URL`); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/deep-partial.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/deep-partial.ts deleted file mode 100644 index 08bdb4d0d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/deep-partial.ts +++ /dev/null @@ -1,84 +0,0 @@ -// License for this File only: -// -// MIT License -// -// Copyright (c) Sindre Sorhus (https://sindresorhus.com) -// Copyright (c) Vercel, Inc. (https://vercel.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and -// to permit persons to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or substantial portions -// of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -import { FlexibleSchema, InferSchema } from '@ai-sdk/provider-utils'; - -/** - * Create a type from an object with all keys and nested keys set to optional. - * The helper supports normal objects and schemas (which are resolved automatically). - * It always recurses into arrays. - * - * Adopted from [type-fest](https://github.com/sindresorhus/type-fest/tree/main) PartialDeep. - */ - -export type DeepPartial = T extends FlexibleSchema - ? DeepPartialInternal> // resolve schemas first to prevent infinite recursion - : DeepPartialInternal; - -type DeepPartialInternal = T extends - | null - | undefined - | string - | number - | boolean - | symbol - | bigint - | void - | Date - | RegExp - | ((...arguments_: any[]) => unknown) - | (new (...arguments_: any[]) => unknown) - ? T - : T extends Map - ? PartialMap - : T extends Set - ? PartialSet - : T extends ReadonlyMap - ? PartialReadonlyMap - : T extends ReadonlySet - ? PartialReadonlySet - : T extends object - ? T extends ReadonlyArray // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156 - ? ItemType[] extends T // Test for arrays (non-tuples) specifically - ? readonly ItemType[] extends T // Differentiate readonly and mutable arrays - ? ReadonlyArray> - : Array> - : PartialObject // Tuples behave properly - : PartialObject - : unknown; - -type PartialMap = {} & Map< - DeepPartialInternal, - DeepPartialInternal ->; - -type PartialSet = {} & Set>; - -type PartialReadonlyMap = {} & ReadonlyMap< - DeepPartialInternal, - DeepPartialInternal ->; - -type PartialReadonlySet = {} & ReadonlySet>; - -type PartialObject = { - [KeyType in keyof ObjectType]?: DeepPartialInternal; -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/detect-media-type.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/detect-media-type.ts deleted file mode 100644 index 66d05014b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/detect-media-type.ts +++ /dev/null @@ -1,226 +0,0 @@ -import { convertBase64ToUint8Array } from '@ai-sdk/provider-utils'; - -export const imageMediaTypeSignatures = [ - { - mediaType: 'image/gif' as const, - bytesPrefix: [0x47, 0x49, 0x46], // GIF - }, - { - mediaType: 'image/png' as const, - bytesPrefix: [0x89, 0x50, 0x4e, 0x47], // PNG - }, - { - mediaType: 'image/jpeg' as const, - bytesPrefix: [0xff, 0xd8], // JPEG - }, - { - mediaType: 'image/webp' as const, - bytesPrefix: [ - 0x52, - 0x49, - 0x46, - 0x46, // "RIFF" - null, - null, - null, - null, // file size (variable) - 0x57, - 0x45, - 0x42, - 0x50, // "WEBP" - ], - }, - { - mediaType: 'image/bmp' as const, - bytesPrefix: [0x42, 0x4d], - }, - { - mediaType: 'image/tiff' as const, - bytesPrefix: [0x49, 0x49, 0x2a, 0x00], - }, - { - mediaType: 'image/tiff' as const, - bytesPrefix: [0x4d, 0x4d, 0x00, 0x2a], - }, - { - mediaType: 'image/avif' as const, - bytesPrefix: [ - 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x61, 0x76, 0x69, 0x66, - ], - }, - { - mediaType: 'image/heic' as const, - bytesPrefix: [ - 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x68, 0x65, 0x69, 0x63, - ], - }, -] as const; - -export const audioMediaTypeSignatures = [ - { - mediaType: 'audio/mpeg' as const, - bytesPrefix: [0xff, 0xfb], - }, - { - mediaType: 'audio/mpeg' as const, - bytesPrefix: [0xff, 0xfa], - }, - { - mediaType: 'audio/mpeg' as const, - bytesPrefix: [0xff, 0xf3], - }, - { - mediaType: 'audio/mpeg' as const, - bytesPrefix: [0xff, 0xf2], - }, - { - mediaType: 'audio/mpeg' as const, - bytesPrefix: [0xff, 0xe3], - }, - { - mediaType: 'audio/mpeg' as const, - bytesPrefix: [0xff, 0xe2], - }, - { - mediaType: 'audio/wav' as const, - bytesPrefix: [ - 0x52, // R - 0x49, // I - 0x46, // F - 0x46, // F - null, - null, - null, - null, - 0x57, // W - 0x41, // A - 0x56, // V - 0x45, // E - ], - }, - { - mediaType: 'audio/ogg' as const, - bytesPrefix: [0x4f, 0x67, 0x67, 0x53], - }, - { - mediaType: 'audio/flac' as const, - bytesPrefix: [0x66, 0x4c, 0x61, 0x43], - }, - { - mediaType: 'audio/aac' as const, - bytesPrefix: [0x40, 0x15, 0x00, 0x00], - }, - { - mediaType: 'audio/mp4' as const, - bytesPrefix: [0x66, 0x74, 0x79, 0x70], - }, - { - mediaType: 'audio/webm', - bytesPrefix: [0x1a, 0x45, 0xdf, 0xa3], - }, -] as const; - -export const videoMediaTypeSignatures = [ - { - mediaType: 'video/mp4' as const, - bytesPrefix: [ - 0x00, - 0x00, - 0x00, - null, - 0x66, - 0x74, - 0x79, - 0x70, // ftyp - ], - }, - { - mediaType: 'video/webm' as const, - bytesPrefix: [0x1a, 0x45, 0xdf, 0xa3], // EBML - }, - { - mediaType: 'video/quicktime' as const, - bytesPrefix: [ - 0x00, - 0x00, - 0x00, - 0x14, - 0x66, - 0x74, - 0x79, - 0x70, - 0x71, - 0x74, // ftypqt - ], - }, - { - mediaType: 'video/x-msvideo' as const, - bytesPrefix: [0x52, 0x49, 0x46, 0x46], // RIFF (AVI) - }, -] as const; - -const stripID3 = (data: Uint8Array | string) => { - const bytes = - typeof data === 'string' ? convertBase64ToUint8Array(data) : data; - const id3Size = - ((bytes[6] & 0x7f) << 21) | - ((bytes[7] & 0x7f) << 14) | - ((bytes[8] & 0x7f) << 7) | - (bytes[9] & 0x7f); - - // The raw MP3 starts here - return bytes.slice(id3Size + 10); -}; - -function stripID3TagsIfPresent(data: Uint8Array | string): Uint8Array | string { - const hasId3 = - (typeof data === 'string' && data.startsWith('SUQz')) || - (typeof data !== 'string' && - data.length > 10 && - data[0] === 0x49 && // 'I' - data[1] === 0x44 && // 'D' - data[2] === 0x33); // '3' - - return hasId3 ? stripID3(data) : data; -} - -/** - * Detect the media IANA media type of a file using a list of signatures. - * - * @param data - The file data. - * @param signatures - The signatures to use for detection. - * @returns The media type of the file. - */ -export function detectMediaType({ - data, - signatures, -}: { - data: Uint8Array | string; - signatures: - | typeof audioMediaTypeSignatures - | typeof imageMediaTypeSignatures - | typeof videoMediaTypeSignatures; -}): (typeof signatures)[number]['mediaType'] | undefined { - const processedData = stripID3TagsIfPresent(data); - - // Convert the first ~18 bytes (24 base64 chars) for consistent detection logic: - const bytes = - typeof processedData === 'string' - ? convertBase64ToUint8Array( - processedData.substring(0, Math.min(processedData.length, 24)), - ) - : processedData; - - for (const signature of signatures) { - if ( - bytes.length >= signature.bytesPrefix.length && - signature.bytesPrefix.every( - (byte, index) => byte === null || bytes[index] === byte, - ) - ) { - return signature.mediaType; - } - } - - return undefined; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/download/create-download.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/download/create-download.ts deleted file mode 100644 index 9ca7b051f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/download/create-download.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { download as internalDownload } from './download'; - -/** - * Creates a download function with configurable options. - * - * @param options - Configuration options for the download function. - * @param options.maxBytes - Maximum allowed download size in bytes. Default: 2 GiB. - * @returns A download function that can be passed to `transcribe()` or `experimental_generateVideo()`. - */ -export function createDownload(options?: { maxBytes?: number }) { - return ({ url, abortSignal }: { url: URL; abortSignal?: AbortSignal }) => - internalDownload({ url, maxBytes: options?.maxBytes, abortSignal }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/download/download-function.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/download/download-function.ts deleted file mode 100644 index 92320aca1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/download/download-function.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { download as originalDownload } from './download'; - -/** - * Experimental. Can change in patch versions without warning. - * - * Download function. Called with the array of URLs and a boolean indicating - * whether the URL is supported by the model. - * - * The download function can decide for each URL: - * - to return null (which means that the URL should be passed to the model) - * - to download the asset and return the data (incl. retries, authentication, etc.) - * - * Should throw DownloadError if the download fails. - * - * Should return an array of objects sorted by the order of the requested downloads. - * For each object, the data should be a Uint8Array if the URL was downloaded. - * For each object, the mediaType should be the media type of the downloaded asset. - * For each object, the data should be null if the URL should be passed through as is. - */ -export type DownloadFunction = ( - options: Array<{ - url: URL; - isUrlSupportedByModel: boolean; - }>, -) => PromiseLike< - Array<{ - data: Uint8Array; - mediaType: string | undefined; - } | null> ->; - -/** - * Default download function. - * Downloads the file if it is not supported by the model. - */ -export const createDefaultDownloadFunction = - (download: typeof originalDownload = originalDownload): DownloadFunction => - requestedDownloads => - Promise.all( - requestedDownloads.map(async requestedDownload => - requestedDownload.isUrlSupportedByModel - ? null - : download(requestedDownload), - ), - ); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/download/download.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/download/download.ts deleted file mode 100644 index 2cbb37570..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/download/download.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { - DownloadError, - readResponseWithSizeLimit, - DEFAULT_MAX_DOWNLOAD_SIZE, - validateDownloadUrl, -} from '@ai-sdk/provider-utils'; -import { - withUserAgentSuffix, - getRuntimeEnvironmentUserAgent, -} from '@ai-sdk/provider-utils'; -import { VERSION } from '../../version'; - -/** - * Download a file from a URL. - * - * @param url - The URL to download from. - * @param maxBytes - Maximum allowed download size in bytes. Defaults to 100 MiB. - * @param abortSignal - An optional abort signal to cancel the download. - * @returns The downloaded data and media type. - * - * @throws DownloadError if the download fails or exceeds maxBytes. - */ -export const download = async ({ - url, - maxBytes, - abortSignal, -}: { - url: URL; - maxBytes?: number; - abortSignal?: AbortSignal; -}) => { - const urlText = url.toString(); - validateDownloadUrl(urlText); - try { - const response = await fetch(urlText, { - headers: withUserAgentSuffix( - {}, - `ai-sdk/${VERSION}`, - getRuntimeEnvironmentUserAgent(), - ), - signal: abortSignal, - }); - - // Validate final URL after redirects to prevent SSRF via open redirect - if (response.redirected) { - validateDownloadUrl(response.url); - } - - if (!response.ok) { - throw new DownloadError({ - url: urlText, - statusCode: response.status, - statusText: response.statusText, - }); - } - - const data = await readResponseWithSizeLimit({ - response, - url: urlText, - maxBytes: maxBytes ?? DEFAULT_MAX_DOWNLOAD_SIZE, - }); - - return { - data, - mediaType: response.headers.get('content-type') ?? undefined, - }; - } catch (error) { - if (DownloadError.isInstance(error)) { - throw error; - } - - throw new DownloadError({ url: urlText, cause: error }); - } -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/error-handler.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/error-handler.ts deleted file mode 100644 index 96b3d8db4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/error-handler.ts +++ /dev/null @@ -1 +0,0 @@ -export type ErrorHandler = (error: unknown) => void; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/fix-json.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/fix-json.ts deleted file mode 100644 index 09a728077..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/fix-json.ts +++ /dev/null @@ -1,401 +0,0 @@ -type State = - | 'ROOT' - | 'FINISH' - | 'INSIDE_STRING' - | 'INSIDE_STRING_ESCAPE' - | 'INSIDE_LITERAL' - | 'INSIDE_NUMBER' - | 'INSIDE_OBJECT_START' - | 'INSIDE_OBJECT_KEY' - | 'INSIDE_OBJECT_AFTER_KEY' - | 'INSIDE_OBJECT_BEFORE_VALUE' - | 'INSIDE_OBJECT_AFTER_VALUE' - | 'INSIDE_OBJECT_AFTER_COMMA' - | 'INSIDE_ARRAY_START' - | 'INSIDE_ARRAY_AFTER_VALUE' - | 'INSIDE_ARRAY_AFTER_COMMA'; - -// Implemented as a scanner with additional fixing -// that performs a single linear time scan pass over the partial JSON. -// -// The states should ideally match relevant states from the JSON spec: -// https://www.json.org/json-en.html -// -// Please note that invalid JSON is not considered/covered, because it -// is assumed that the resulting JSON will be processed by a standard -// JSON parser that will detect any invalid JSON. -export function fixJson(input: string): string { - const stack: State[] = ['ROOT']; - let lastValidIndex = -1; - let literalStart: number | null = null; - - function processValueStart(char: string, i: number, swapState: State) { - { - switch (char) { - case '"': { - lastValidIndex = i; - stack.pop(); - stack.push(swapState); - stack.push('INSIDE_STRING'); - break; - } - - case 'f': - case 't': - case 'n': { - lastValidIndex = i; - literalStart = i; - stack.pop(); - stack.push(swapState); - stack.push('INSIDE_LITERAL'); - break; - } - - case '-': { - stack.pop(); - stack.push(swapState); - stack.push('INSIDE_NUMBER'); - break; - } - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - lastValidIndex = i; - stack.pop(); - stack.push(swapState); - stack.push('INSIDE_NUMBER'); - break; - } - - case '{': { - lastValidIndex = i; - stack.pop(); - stack.push(swapState); - stack.push('INSIDE_OBJECT_START'); - break; - } - - case '[': { - lastValidIndex = i; - stack.pop(); - stack.push(swapState); - stack.push('INSIDE_ARRAY_START'); - break; - } - } - } - } - - function processAfterObjectValue(char: string, i: number) { - switch (char) { - case ',': { - stack.pop(); - stack.push('INSIDE_OBJECT_AFTER_COMMA'); - break; - } - case '}': { - lastValidIndex = i; - stack.pop(); - break; - } - } - } - - function processAfterArrayValue(char: string, i: number) { - switch (char) { - case ',': { - stack.pop(); - stack.push('INSIDE_ARRAY_AFTER_COMMA'); - break; - } - case ']': { - lastValidIndex = i; - stack.pop(); - break; - } - } - } - - for (let i = 0; i < input.length; i++) { - const char = input[i]; - const currentState = stack[stack.length - 1]; - - switch (currentState) { - case 'ROOT': - processValueStart(char, i, 'FINISH'); - break; - - case 'INSIDE_OBJECT_START': { - switch (char) { - case '"': { - stack.pop(); - stack.push('INSIDE_OBJECT_KEY'); - break; - } - case '}': { - lastValidIndex = i; - stack.pop(); - break; - } - } - break; - } - - case 'INSIDE_OBJECT_AFTER_COMMA': { - switch (char) { - case '"': { - stack.pop(); - stack.push('INSIDE_OBJECT_KEY'); - break; - } - } - break; - } - - case 'INSIDE_OBJECT_KEY': { - switch (char) { - case '"': { - stack.pop(); - stack.push('INSIDE_OBJECT_AFTER_KEY'); - break; - } - } - break; - } - - case 'INSIDE_OBJECT_AFTER_KEY': { - switch (char) { - case ':': { - stack.pop(); - stack.push('INSIDE_OBJECT_BEFORE_VALUE'); - - break; - } - } - break; - } - - case 'INSIDE_OBJECT_BEFORE_VALUE': { - processValueStart(char, i, 'INSIDE_OBJECT_AFTER_VALUE'); - break; - } - - case 'INSIDE_OBJECT_AFTER_VALUE': { - processAfterObjectValue(char, i); - break; - } - - case 'INSIDE_STRING': { - switch (char) { - case '"': { - stack.pop(); - lastValidIndex = i; - break; - } - - case '\\': { - stack.push('INSIDE_STRING_ESCAPE'); - break; - } - - default: { - lastValidIndex = i; - } - } - - break; - } - - case 'INSIDE_ARRAY_START': { - switch (char) { - case ']': { - lastValidIndex = i; - stack.pop(); - break; - } - - default: { - lastValidIndex = i; - processValueStart(char, i, 'INSIDE_ARRAY_AFTER_VALUE'); - break; - } - } - break; - } - - case 'INSIDE_ARRAY_AFTER_VALUE': { - switch (char) { - case ',': { - stack.pop(); - stack.push('INSIDE_ARRAY_AFTER_COMMA'); - break; - } - - case ']': { - lastValidIndex = i; - stack.pop(); - break; - } - - default: { - lastValidIndex = i; - break; - } - } - - break; - } - - case 'INSIDE_ARRAY_AFTER_COMMA': { - processValueStart(char, i, 'INSIDE_ARRAY_AFTER_VALUE'); - break; - } - - case 'INSIDE_STRING_ESCAPE': { - stack.pop(); - lastValidIndex = i; - - break; - } - - case 'INSIDE_NUMBER': { - switch (char) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - lastValidIndex = i; - break; - } - - case 'e': - case 'E': - case '-': - case '.': { - break; - } - - case ',': { - stack.pop(); - - if (stack[stack.length - 1] === 'INSIDE_ARRAY_AFTER_VALUE') { - processAfterArrayValue(char, i); - } - - if (stack[stack.length - 1] === 'INSIDE_OBJECT_AFTER_VALUE') { - processAfterObjectValue(char, i); - } - - break; - } - - case '}': { - stack.pop(); - - if (stack[stack.length - 1] === 'INSIDE_OBJECT_AFTER_VALUE') { - processAfterObjectValue(char, i); - } - - break; - } - - case ']': { - stack.pop(); - - if (stack[stack.length - 1] === 'INSIDE_ARRAY_AFTER_VALUE') { - processAfterArrayValue(char, i); - } - - break; - } - - default: { - stack.pop(); - break; - } - } - - break; - } - - case 'INSIDE_LITERAL': { - const partialLiteral = input.substring(literalStart!, i + 1); - - if ( - !'false'.startsWith(partialLiteral) && - !'true'.startsWith(partialLiteral) && - !'null'.startsWith(partialLiteral) - ) { - stack.pop(); - - if (stack[stack.length - 1] === 'INSIDE_OBJECT_AFTER_VALUE') { - processAfterObjectValue(char, i); - } else if (stack[stack.length - 1] === 'INSIDE_ARRAY_AFTER_VALUE') { - processAfterArrayValue(char, i); - } - } else { - lastValidIndex = i; - } - - break; - } - } - } - - let result = input.slice(0, lastValidIndex + 1); - - for (let i = stack.length - 1; i >= 0; i--) { - const state = stack[i]; - - switch (state) { - case 'INSIDE_STRING': { - result += '"'; - break; - } - - case 'INSIDE_OBJECT_KEY': - case 'INSIDE_OBJECT_AFTER_KEY': - case 'INSIDE_OBJECT_AFTER_COMMA': - case 'INSIDE_OBJECT_START': - case 'INSIDE_OBJECT_BEFORE_VALUE': - case 'INSIDE_OBJECT_AFTER_VALUE': { - result += '}'; - break; - } - - case 'INSIDE_ARRAY_START': - case 'INSIDE_ARRAY_AFTER_COMMA': - case 'INSIDE_ARRAY_AFTER_VALUE': { - result += ']'; - break; - } - - case 'INSIDE_LITERAL': { - const partialLiteral = input.substring(literalStart!, input.length); - - if ('true'.startsWith(partialLiteral)) { - result += 'true'.slice(partialLiteral.length); - } else if ('false'.startsWith(partialLiteral)) { - result += 'false'.slice(partialLiteral.length); - } else if ('null'.startsWith(partialLiteral)) { - result += 'null'.slice(partialLiteral.length); - } - } - } - } - - return result; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/get-potential-start-index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/get-potential-start-index.ts deleted file mode 100644 index 06ba2189e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/get-potential-start-index.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Finds the potential starting index where searchedText could begin in text. - * - * This function checks for both complete and partial matches: - * - If searchedText is found as a complete substring, returns the index of the first occurrence. - * - If the end of text matches the beginning of searchedText (partial match), - * returns the index where that partial match starts. - * - * @param text - The text to search within. - * @param searchedText - The text to search for. - * @returns The starting index of the match (complete or partial), or null if - * searchedText is empty or no match is found. - */ -export function getPotentialStartIndex( - text: string, - searchedText: string, -): number | null { - // Return null immediately if searchedText is empty. - if (searchedText.length === 0) { - return null; - } - - // Check if the searchedText exists as a direct substring of text. - const directIndex = text.indexOf(searchedText); - if (directIndex !== -1) { - return directIndex; - } - - // Otherwise, look for the largest suffix of "text" that matches - // a prefix of "searchedText". We go from the end of text inward. - for (let i = text.length - 1; i >= 0; i--) { - const suffix = text.substring(i); - if (searchedText.startsWith(suffix)) { - return i; - } - } - - return null; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/index.ts deleted file mode 100644 index df377f20b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export type { AsyncIterableStream } from './async-iterable-stream'; -export { consumeStream } from './consume-stream'; -export { cosineSimilarity } from './cosine-similarity'; -export { createDownload } from './download/create-download'; -export { getTextFromDataUrl } from './data-url'; -export type { DeepPartial } from './deep-partial'; -export type { DownloadFunction as Experimental_DownloadFunction } from './download/download-function'; -export { type ErrorHandler } from './error-handler'; -export { isDeepEqualData } from './is-deep-equal-data'; -export { parsePartialJson } from './parse-partial-json'; -export { SerialJobExecutor } from './serial-job-executor'; -export { simulateReadableStream } from './simulate-readable-stream'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/is-deep-equal-data.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/is-deep-equal-data.ts deleted file mode 100644 index 5dac5e3f3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/is-deep-equal-data.ts +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Performs a deep-equal comparison of two parsed JSON objects. - * - * @param {any} obj1 - The first object to compare. - * @param {any} obj2 - The second object to compare. - * @returns {boolean} - Returns true if the two objects are deeply equal, false otherwise. - */ -export function isDeepEqualData(obj1: any, obj2: any): boolean { - // Check for strict equality first - if (obj1 === obj2) return true; - - // Check if either is null or undefined - if (obj1 == null || obj2 == null) return false; - - // Check if both are objects - if (typeof obj1 !== 'object' && typeof obj2 !== 'object') - return obj1 === obj2; - - // If they are not strictly equal, they both need to be Objects - if (obj1.constructor !== obj2.constructor) return false; - - // Special handling for Date objects - if (obj1 instanceof Date && obj2 instanceof Date) { - return obj1.getTime() === obj2.getTime(); - } - - // Handle arrays: compare length and then perform a recursive deep comparison on each item - if (Array.isArray(obj1)) { - if (obj1.length !== obj2.length) return false; - for (let i = 0; i < obj1.length; i++) { - if (!isDeepEqualData(obj1[i], obj2[i])) return false; - } - return true; // All array elements matched - } - - // Compare the set of keys in each object - const keys1 = Object.keys(obj1); - const keys2 = Object.keys(obj2); - if (keys1.length !== keys2.length) return false; - - // Check each key-value pair recursively - for (const key of keys1) { - if (!keys2.includes(key)) return false; - if (!isDeepEqualData(obj1[key], obj2[key])) return false; - } - - return true; // All keys and values matched -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/is-non-empty-object.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/is-non-empty-object.ts deleted file mode 100644 index bf6d297dc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/is-non-empty-object.ts +++ /dev/null @@ -1,5 +0,0 @@ -export function isNonEmptyObject( - object: Record | undefined | null, -): object is Record { - return object != null && Object.keys(object).length > 0; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/job.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/job.ts deleted file mode 100644 index 61d0624cb..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/job.ts +++ /dev/null @@ -1 +0,0 @@ -export type Job = () => Promise; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/log-v2-compatibility-warning.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/log-v2-compatibility-warning.ts deleted file mode 100644 index 6c7353263..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/log-v2-compatibility-warning.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { logWarnings } from '../logger/log-warnings'; - -export function logV2CompatibilityWarning({ - provider, - modelId, -}: { - provider: string; - modelId: string; -}): void { - logWarnings({ - warnings: [ - { - type: 'compatibility', - feature: 'specificationVersion', - details: `Using v2 specification compatibility mode. Some features may not be available.`, - }, - ], - provider, - model: modelId, - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/merge-abort-signals.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/merge-abort-signals.ts deleted file mode 100644 index d4ebf2390..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/merge-abort-signals.ts +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Merges multiple AbortSignals into a single AbortSignal. - * The returned signal will abort when any of the input signals abort, - * with the same reason as the first signal to abort. - * - * @param signals - The AbortSignals to merge. Null and undefined values are filtered out. - * @returns An AbortSignal that aborts when any of the input signals abort, - * or undefined if no valid signals are provided. - */ -export function mergeAbortSignals( - ...signals: (AbortSignal | null | undefined)[] -): AbortSignal | undefined { - const validSignals = signals.filter( - (signal): signal is AbortSignal => signal != null, - ); - - if (validSignals.length === 0) { - return undefined; - } - - if (validSignals.length === 1) { - return validSignals[0]; - } - - const controller = new AbortController(); - - for (const signal of validSignals) { - if (signal.aborted) { - controller.abort(signal.reason); - return controller.signal; - } - - signal.addEventListener( - 'abort', - () => { - controller.abort(signal.reason); - }, - { once: true }, - ); - } - - return controller.signal; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/merge-objects.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/merge-objects.ts deleted file mode 100644 index 3e367835b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/merge-objects.ts +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Deeply merges two objects together. - * - Properties from the `overrides` object override those in the `base` object with the same key. - * - For nested objects, the merge is performed recursively (deep merge). - * - Arrays are replaced, not merged. - * - Primitive values are replaced. - * - If both `base` and `overrides` are undefined, returns undefined. - * - If one of `base` or `overrides` is undefined, returns the other. - * - * @param base The target object to merge into - * @param overrides The source object to merge from - * @returns A new object with the merged properties, or undefined if both inputs are undefined - */ -export function mergeObjects( - base: T | undefined, - overrides: U | undefined, -): (T & U) | T | U | undefined { - // If both inputs are undefined, return undefined - if (base === undefined && overrides === undefined) { - return undefined; - } - - // If target is undefined, return source - if (base === undefined) { - return overrides; - } - - // If source is undefined, return target - if (overrides === undefined) { - return base; - } - - // Create a new object to avoid mutating the inputs - const result = { ...base } as T & U; - - // Iterate through all keys in the source object - for (const key in overrides) { - if (Object.prototype.hasOwnProperty.call(overrides, key)) { - const overridesValue = overrides[key]; - - // Skip if the overrides value is undefined - if (overridesValue === undefined) continue; - - // Get the base value if it exists - const baseValue = - key in base ? base[key as unknown as keyof T] : undefined; - - // Check if both values are objects that can be deeply merged - const isSourceObject = - overridesValue !== null && - typeof overridesValue === 'object' && - !Array.isArray(overridesValue) && - !(overridesValue instanceof Date) && - !(overridesValue instanceof RegExp); - - const isTargetObject = - baseValue !== null && - baseValue !== undefined && - typeof baseValue === 'object' && - !Array.isArray(baseValue) && - !(baseValue instanceof Date) && - !(baseValue instanceof RegExp); - - // If both values are mergeable objects, merge them recursively - if (isSourceObject && isTargetObject) { - result[key as keyof (T & U)] = mergeObjects( - baseValue as object, - overridesValue as object, - ) as any; - } else { - // For primitives, arrays, or when one value is not a mergeable object, - // simply override with the source value - result[key as keyof (T & U)] = overridesValue as any; - } - } - } - - return result; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/notify.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/notify.ts deleted file mode 100644 index 57fe9b676..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/notify.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { asArray } from './as-array'; - -/** - * A callback function that can be used to notify listeners. - */ -export type Listener = (event: EVENT) => PromiseLike | void; - -/** - * Notifies all provided callbacks with the given event. - * Errors in callbacks do not break the generation flow. - */ -export async function notify(options: { - event: EVENT; - callbacks?: Listener | Array | undefined | null>; -}): Promise { - for (const callback of asArray(options.callbacks)) { - if (callback == null) continue; - try { - await callback(options.event); - } catch (_ignored) {} - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/now.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/now.ts deleted file mode 100644 index f5f894ae8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/now.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Shim for performance.now() to support environments that don't have it: -export function now(): number { - return globalThis?.performance?.now() ?? Date.now(); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/parse-partial-json.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/parse-partial-json.ts deleted file mode 100644 index 107133f63..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/parse-partial-json.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { JSONValue } from '@ai-sdk/provider'; -import { safeParseJSON } from '@ai-sdk/provider-utils'; -import { fixJson } from './fix-json'; - -export async function parsePartialJson(jsonText: string | undefined): Promise<{ - value: JSONValue | undefined; - state: - | 'undefined-input' - | 'successful-parse' - | 'repaired-parse' - | 'failed-parse'; -}> { - if (jsonText === undefined) { - return { value: undefined, state: 'undefined-input' }; - } - - let result = await safeParseJSON({ text: jsonText }); - - if (result.success) { - return { value: result.value, state: 'successful-parse' }; - } - - result = await safeParseJSON({ text: fixJson(jsonText) }); - - if (result.success) { - return { value: result.value, state: 'repaired-parse' }; - } - - return { value: undefined, state: 'failed-parse' }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/prepare-headers.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/prepare-headers.ts deleted file mode 100644 index 9fa02f110..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/prepare-headers.ts +++ /dev/null @@ -1,14 +0,0 @@ -export function prepareHeaders( - headers: HeadersInit | undefined, - defaultHeaders: Record, -): Headers { - const responseHeaders = new Headers(headers ?? {}); - - for (const [key, value] of Object.entries(defaultHeaders)) { - if (!responseHeaders.has(key)) { - responseHeaders.set(key, value); - } - } - - return responseHeaders; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/prepare-retries.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/prepare-retries.ts deleted file mode 100644 index 00b7f4839..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/prepare-retries.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { InvalidArgumentError } from '../error/invalid-argument-error'; -import { - RetryFunction, - retryWithExponentialBackoffRespectingRetryHeaders, -} from '../util/retry-with-exponential-backoff'; - -/** - * Validate and prepare retries. - */ -export function prepareRetries({ - maxRetries, - abortSignal, -}: { - maxRetries: number | undefined; - abortSignal: AbortSignal | undefined; -}): { - maxRetries: number; - retry: RetryFunction; -} { - if (maxRetries != null) { - if (!Number.isInteger(maxRetries)) { - throw new InvalidArgumentError({ - parameter: 'maxRetries', - value: maxRetries, - message: 'maxRetries must be an integer', - }); - } - - if (maxRetries < 0) { - throw new InvalidArgumentError({ - parameter: 'maxRetries', - value: maxRetries, - message: 'maxRetries must be >= 0', - }); - } - } - - const maxRetriesResult = maxRetries ?? 2; - - return { - maxRetries: maxRetriesResult, - retry: retryWithExponentialBackoffRespectingRetryHeaders({ - maxRetries: maxRetriesResult, - abortSignal, - }), - }; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/retry-error.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/retry-error.ts deleted file mode 100644 index 5ba20e422..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/retry-error.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { AISDKError } from '@ai-sdk/provider'; - -const name = 'AI_RetryError'; -const marker = `vercel.ai.error.${name}`; -const symbol = Symbol.for(marker); - -export type RetryErrorReason = - | 'maxRetriesExceeded' - | 'errorNotRetryable' - | 'abort'; - -export class RetryError extends AISDKError { - private readonly [symbol] = true; // used in isInstance - - // note: property order determines debugging output - readonly reason: RetryErrorReason; - readonly lastError: unknown; - readonly errors: Array; - - constructor({ - message, - reason, - errors, - }: { - message: string; - reason: RetryErrorReason; - errors: Array; - }) { - super({ name, message }); - - this.reason = reason; - this.errors = errors; - - // separate our last error to make debugging via log easier: - this.lastError = errors[errors.length - 1]; - } - - static isInstance(error: unknown): error is RetryError { - return AISDKError.hasMarker(error, marker); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/retry-with-exponential-backoff.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/retry-with-exponential-backoff.ts deleted file mode 100644 index 9ec528b0a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/retry-with-exponential-backoff.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { APICallError } from '@ai-sdk/provider'; -import { delay, getErrorMessage, isAbortError } from '@ai-sdk/provider-utils'; -import { RetryError } from './retry-error'; - -export type RetryFunction = ( - fn: () => PromiseLike, -) => PromiseLike; - -function getRetryDelayInMs({ - error, - exponentialBackoffDelay, -}: { - error: APICallError; - exponentialBackoffDelay: number; -}): number { - const headers = error.responseHeaders; - - if (!headers) return exponentialBackoffDelay; - - let ms: number | undefined; - - // retry-ms is more precise than retry-after and used by e.g. OpenAI - const retryAfterMs = headers['retry-after-ms']; - if (retryAfterMs) { - const timeoutMs = parseFloat(retryAfterMs); - if (!Number.isNaN(timeoutMs)) { - ms = timeoutMs; - } - } - - // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After - const retryAfter = headers['retry-after']; - if (retryAfter && ms === undefined) { - const timeoutSeconds = parseFloat(retryAfter); - if (!Number.isNaN(timeoutSeconds)) { - ms = timeoutSeconds * 1000; - } else { - ms = Date.parse(retryAfter) - Date.now(); - } - } - - // check that the delay is reasonable: - if ( - ms != null && - !Number.isNaN(ms) && - 0 <= ms && - (ms < 60 * 1000 || ms < exponentialBackoffDelay) - ) { - return ms; - } - - return exponentialBackoffDelay; -} - -/** - * The `retryWithExponentialBackoffRespectingRetryHeaders` strategy retries a failed API call with an exponential backoff, - * while respecting rate limit headers (retry-after-ms and retry-after) if they are provided and reasonable (0-60 seconds). - * You can configure the maximum number of retries, the initial delay, and the backoff factor. - */ -export const retryWithExponentialBackoffRespectingRetryHeaders = - ({ - maxRetries = 2, - initialDelayInMs = 2000, - backoffFactor = 2, - abortSignal, - }: { - maxRetries?: number; - initialDelayInMs?: number; - backoffFactor?: number; - abortSignal?: AbortSignal; - } = {}): RetryFunction => - async (f: () => PromiseLike) => - _retryWithExponentialBackoff(f, { - maxRetries, - delayInMs: initialDelayInMs, - backoffFactor, - abortSignal, - }); - -async function _retryWithExponentialBackoff( - f: () => PromiseLike, - { - maxRetries, - delayInMs, - backoffFactor, - abortSignal, - }: { - maxRetries: number; - delayInMs: number; - backoffFactor: number; - abortSignal: AbortSignal | undefined; - }, - errors: unknown[] = [], -): Promise { - try { - return await f(); - } catch (error) { - if (isAbortError(error)) { - throw error; // don't retry when the request was aborted - } - - if (maxRetries === 0) { - throw error; // don't wrap the error when retries are disabled - } - - const errorMessage = getErrorMessage(error); - const newErrors = [...errors, error]; - const tryNumber = newErrors.length; - - if (tryNumber > maxRetries) { - throw new RetryError({ - message: `Failed after ${tryNumber} attempts. Last error: ${errorMessage}`, - reason: 'maxRetriesExceeded', - errors: newErrors, - }); - } - - if ( - error instanceof Error && - APICallError.isInstance(error) && - error.isRetryable === true && - tryNumber <= maxRetries - ) { - await delay( - getRetryDelayInMs({ - error, - exponentialBackoffDelay: delayInMs, - }), - { abortSignal }, - ); - - return _retryWithExponentialBackoff( - f, - { - maxRetries, - delayInMs: backoffFactor * delayInMs, - backoffFactor, - abortSignal, - }, - newErrors, - ); - } - - if (tryNumber === 1) { - throw error; // don't wrap the error when a non-retryable error occurs on the first try - } - - throw new RetryError({ - message: `Failed after ${tryNumber} attempts with non-retryable error: '${errorMessage}'`, - reason: 'errorNotRetryable', - errors: newErrors, - }); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/serial-job-executor.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/serial-job-executor.ts deleted file mode 100644 index 4a037b0ca..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/serial-job-executor.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Job } from './job'; - -export class SerialJobExecutor { - private queue: Array = []; - private isProcessing = false; - - private async processQueue() { - if (this.isProcessing) { - return; - } - - this.isProcessing = true; - - while (this.queue.length > 0) { - await this.queue[0](); - this.queue.shift(); - } - - this.isProcessing = false; - } - - async run(job: Job): Promise { - return new Promise((resolve, reject) => { - this.queue.push(async () => { - try { - await job(); - resolve(); - } catch (error) { - reject(error); - } - }); - - void this.processQueue(); - }); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/simulate-readable-stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/simulate-readable-stream.ts deleted file mode 100644 index 8ceb4a638..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/simulate-readable-stream.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { delay as delayFunction } from '@ai-sdk/provider-utils'; - -/** - * Creates a ReadableStream that emits the provided values with an optional delay between each value. - * - * @param options - The configuration options - * @param options.chunks - Array of values to be emitted by the stream - * @param options.initialDelayInMs - Optional initial delay in milliseconds before emitting the first value (default: 0). Can be set to `null` to skip the initial delay. The difference between `initialDelayInMs: null` and `initialDelayInMs: 0` is that `initialDelayInMs: null` will emit the values without any delay, while `initialDelayInMs: 0` will emit the values with a delay of 0 milliseconds. - * @param options.chunkDelayInMs - Optional delay in milliseconds between emitting each value (default: 0). Can be set to `null` to skip the delay. The difference between `chunkDelayInMs: null` and `chunkDelayInMs: 0` is that `chunkDelayInMs: null` will emit the values without any delay, while `chunkDelayInMs: 0` will emit the values with a delay of 0 milliseconds. - * @returns A ReadableStream that emits the provided values - */ -export function simulateReadableStream({ - chunks, - initialDelayInMs = 0, - chunkDelayInMs = 0, - _internal, -}: { - chunks: T[]; - initialDelayInMs?: number | null; - chunkDelayInMs?: number | null; - _internal?: { - delay?: (ms: number | null) => Promise; - }; -}): ReadableStream { - const delay = _internal?.delay ?? delayFunction; - - let index = 0; - - return new ReadableStream({ - async pull(controller) { - if (index < chunks.length) { - await delay(index === 0 ? initialDelayInMs : chunkDelayInMs); - controller.enqueue(chunks[index++]); - } else { - controller.close(); - } - }, - }); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/split-array.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/split-array.ts deleted file mode 100644 index 8d8906759..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/split-array.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Splits an array into chunks of a specified size. - * - * @template T - The type of elements in the array. - * @param {T[]} array - The array to split. - * @param {number} chunkSize - The size of each chunk. - * @returns {T[][]} - A new array containing the chunks. - */ -export function splitArray(array: T[], chunkSize: number): T[][] { - if (chunkSize <= 0) { - throw new Error('chunkSize must be greater than 0'); - } - - const result = []; - for (let i = 0; i < array.length; i += chunkSize) { - result.push(array.slice(i, i + chunkSize)); - } - - return result; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/value-of.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/value-of.ts deleted file mode 100644 index 3419620a5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/value-of.ts +++ /dev/null @@ -1,65 +0,0 @@ -// License for this File only: -// -// MIT License -// -// Copyright (c) Sindre Sorhus (https://sindresorhus.com) -// Copyright (c) Vercel, Inc. (https://vercel.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and -// to permit persons to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or substantial portions -// of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -/** - * Create a union of the given object's values, and optionally specify which keys to get the values from. - * - * Please upvote [this issue](https://github.com/microsoft/TypeScript/issues/31438) if you want to have this type as a built-in in TypeScript. - * - * @example - * ``` - * // data.json - * { - * 'foo': 1, - * 'bar': 2, - * 'biz': 3 - * } - * - * // main.ts - * import type {ValueOf} from 'type-fest'; - * import data = require('./data.json'); - * - * export function getData(name: string): ValueOf { - * return data[name]; - * } - * - * export function onlyBar(name: string): ValueOf { - * return data[name]; - * } - * - * // file.ts - * import {getData, onlyBar} from './main'; - * - * getData('foo'); - * //=> 1 - * - * onlyBar('foo'); - * //=> TypeError ... - * - * onlyBar('bar'); - * //=> 2 - * ``` - * @see https://github.com/sindresorhus/type-fest/blob/main/source/value-of.d.ts - */ -export type ValueOf< - ObjectType, - ValueType extends keyof ObjectType = keyof ObjectType, -> = ObjectType[ValueType]; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/write-to-server-response.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/write-to-server-response.ts deleted file mode 100644 index 1e9ead8b1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/util/write-to-server-response.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { ServerResponse } from 'node:http'; - -/** - * Writes the content of a stream to a server response. - */ -export function writeToServerResponse({ - response, - status, - statusText, - headers, - stream, -}: { - response: ServerResponse; - status?: number; - statusText?: string; - headers?: Record; - stream: ReadableStream; -}): void { - const statusCode = status ?? 200; - if (statusText !== undefined) { - response.writeHead(statusCode, statusText, headers); - } else { - response.writeHead(statusCode, headers); - } - - const reader = stream.getReader(); - const read = async () => { - try { - while (true) { - const { done, value } = await reader.read(); - if (done) break; - - // Respect backpressure: if write() returns false, wait for 'drain' event - const canContinue = response.write(value); - if (!canContinue) { - await new Promise(resolve => { - response.once('drain', resolve); - }); - } - } - } catch (error) { - throw error; - } finally { - response.end(); - } - }; - - read(); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/version.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/version.ts deleted file mode 100644 index 8fda877d6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/src/version.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare const __PACKAGE_VERSION__: string | undefined; -export const VERSION: string = - typeof __PACKAGE_VERSION__ !== 'undefined' - ? __PACKAGE_VERSION__ - : '0.0.0-test'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/test.d.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/test.d.ts deleted file mode 100644 index 990366a86..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/ai/test.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/test'; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/CHANGELOG.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/CHANGELOG.md deleted file mode 100644 index c3d6a9c80..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/CHANGELOG.md +++ /dev/null @@ -1,621 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. - -## [Unreleased](https://github.com/motdotla/dotenv/compare/v17.3.1...master) - -## [17.3.1](https://github.com/motdotla/dotenv/compare/v17.3.0...v17.3.1) (2026-02-12) - -### Changed - -* Fix as2 example command in README and update spanish README - -## [17.3.0](https://github.com/motdotla/dotenv/compare/v17.2.4...v17.3.0) (2026-02-12) - -### Added - -* Add a new README section on dotenv’s approach to the agentic future. - -### Changed - -* Rewrite README to get humans started more quickly with less noise while simultaneously making more accessible for llms and agents to go deeper into details. - -## [17.2.4](https://github.com/motdotla/dotenv/compare/v17.2.3...v17.2.4) (2026-02-05) - -### Changed - -* Make `DotenvPopulateInput` accept `NodeJS.ProcessEnv` type ([#915](https://github.com/motdotla/dotenv/pull/915)) -- Give back to dotenv by checking out my newest project [vestauth](https://github.com/vestauth/vestauth). It is auth for agents. Thank you for using my software. - -## [17.2.3](https://github.com/motdotla/dotenv/compare/v17.2.2...v17.2.3) (2025-09-29) - -### Changed - -* Fixed typescript error definition ([#912](https://github.com/motdotla/dotenv/pull/912)) - -## [17.2.2](https://github.com/motdotla/dotenv/compare/v17.2.1...v17.2.2) (2025-09-02) - -### Added - -- 🙏 A big thank you to new sponsor [Tuple.app](https://tuple.app/dotenv) - *the premier screen sharing app for developers on macOS and Windows.* Go check them out. It's wonderful and generous of them to give back to open source by sponsoring dotenv. Give them some love back. - -## [17.2.1](https://github.com/motdotla/dotenv/compare/v17.2.0...v17.2.1) (2025-07-24) - -### Changed - -* Fix clickable tip links by removing parentheses ([#897](https://github.com/motdotla/dotenv/pull/897)) - -## [17.2.0](https://github.com/motdotla/dotenv/compare/v17.1.0...v17.2.0) (2025-07-09) - -### Added - -* Optionally specify `DOTENV_CONFIG_QUIET=true` in your environment or `.env` file to quiet the runtime log ([#889](https://github.com/motdotla/dotenv/pull/889)) -* Just like dotenv any `DOTENV_CONFIG_` environment variables take precedence over any code set options like `({quiet: false})` - -```ini -# .env -DOTENV_CONFIG_QUIET=true -HELLO="World" -``` -```js -// index.js -require('dotenv').config() -console.log(`Hello ${process.env.HELLO}`) -``` -```sh -$ node index.js -Hello World - -or - -$ DOTENV_CONFIG_QUIET=true node index.js -``` - -## [17.1.0](https://github.com/motdotla/dotenv/compare/v17.0.1...v17.1.0) (2025-07-07) - -### Added - -* Add additional security and configuration tips to the runtime log ([#884](https://github.com/motdotla/dotenv/pull/884)) -* Dim the tips text from the main injection information text - -```js -const TIPS = [ - '🔐 encrypt with dotenvx: https://dotenvx.com', - '🔐 prevent committing .env to code: https://dotenvx.com/precommit', - '🔐 prevent building .env in docker: https://dotenvx.com/prebuild', - '🛠️ run anywhere with `dotenvx run -- yourcommand`', - '⚙️ specify custom .env file path with { path: \'/custom/path/.env\' }', - '⚙️ enable debug logging with { debug: true }', - '⚙️ override existing env vars with { override: true }', - '⚙️ suppress all logs with { quiet: true }', - '⚙️ write to custom object with { processEnv: myObject }', - '⚙️ load multiple .env files with { path: [\'.env.local\', \'.env\'] }' -] -``` - -## [17.0.1](https://github.com/motdotla/dotenv/compare/v17.0.0...v17.0.1) (2025-07-01) - -### Changed - -* Patched injected log to count only populated/set keys to process.env ([#879](https://github.com/motdotla/dotenv/pull/879)) - -## [17.0.0](https://github.com/motdotla/dotenv/compare/v16.6.1...v17.0.0) (2025-06-27) - -### Changed - -- Default `quiet` to false - informational (file and keys count) runtime log message shows by default ([#875](https://github.com/motdotla/dotenv/pull/875)) - -## [16.6.1](https://github.com/motdotla/dotenv/compare/v16.6.0...v16.6.1) (2025-06-27) - -### Changed - -- Default `quiet` to true – hiding the runtime log message ([#874](https://github.com/motdotla/dotenv/pull/874)) -- NOTICE: 17.0.0 will be released with quiet defaulting to false. Use `config({ quiet: true })` to suppress. -- And check out the new [dotenvx](https://github.com/dotenvx/dotenvx). As coding workflows evolve and agents increasingly handle secrets, encrypted .env files offer a much safer way to deploy both agents and code together with secure secrets. Simply switch `require('dotenv').config()` for `require('@dotenvx/dotenvx').config()`. - -## [16.6.0](https://github.com/motdotla/dotenv/compare/v16.5.0...v16.6.0) (2025-06-26) - -### Added - -- Default log helpful message `[dotenv@16.6.0] injecting env (1) from .env` ([#870](https://github.com/motdotla/dotenv/pull/870)) -- Use `{ quiet: true }` to suppress -- Aligns dotenv more closely with [dotenvx](https://github.com/dotenvx/dotenvx). - -## [16.5.0](https://github.com/motdotla/dotenv/compare/v16.4.7...v16.5.0) (2025-04-07) - -### Added - -- 🎉 Added new sponsor [Graphite](https://graphite.dev/?utm_source=github&utm_medium=repo&utm_campaign=dotenv) - *the AI developer productivity platform helping teams on GitHub ship higher quality software, faster*. - -> [!TIP] -> **[Become a sponsor](https://github.com/sponsors/motdotla)** -> -> The dotenvx README is viewed thousands of times DAILY on GitHub and NPM. -> Sponsoring dotenv is a great way to get in front of developers and give back to the developer community at the same time. - -### Changed - -- Remove `_log` method. Use `_debug` [#862](https://github.com/motdotla/dotenv/pull/862) - -## [16.4.7](https://github.com/motdotla/dotenv/compare/v16.4.6...v16.4.7) (2024-12-03) - -### Changed - -- Ignore `.tap` folder when publishing. (oops, sorry about that everyone. - @motdotla) [#848](https://github.com/motdotla/dotenv/pull/848) - -## [16.4.6](https://github.com/motdotla/dotenv/compare/v16.4.5...v16.4.6) (2024-12-02) - -### Changed - -- Clean up stale dev dependencies [#847](https://github.com/motdotla/dotenv/pull/847) -- Various README updates clarifying usage and alternative solutions using [dotenvx](https://github.com/dotenvx/dotenvx) - -## [16.4.5](https://github.com/motdotla/dotenv/compare/v16.4.4...v16.4.5) (2024-02-19) - -### Changed - -- 🐞 Fix recent regression when using `path` option. return to historical behavior: do not attempt to auto find `.env` if `path` set. (regression was introduced in `16.4.3`) [#814](https://github.com/motdotla/dotenv/pull/814) - -## [16.4.4](https://github.com/motdotla/dotenv/compare/v16.4.3...v16.4.4) (2024-02-13) - -### Changed - -- 🐞 Replaced chaining operator `?.` with old school `&&` (fixing node 12 failures) [#812](https://github.com/motdotla/dotenv/pull/812) - -## [16.4.3](https://github.com/motdotla/dotenv/compare/v16.4.2...v16.4.3) (2024-02-12) - -### Changed - -- Fixed processing of multiple files in `options.path` [#805](https://github.com/motdotla/dotenv/pull/805) - -## [16.4.2](https://github.com/motdotla/dotenv/compare/v16.4.1...v16.4.2) (2024-02-10) - -### Changed - -- Changed funding link in package.json to [`dotenvx.com`](https://dotenvx.com) - -## [16.4.1](https://github.com/motdotla/dotenv/compare/v16.4.0...v16.4.1) (2024-01-24) - -- Patch support for array as `path` option [#797](https://github.com/motdotla/dotenv/pull/797) - -## [16.4.0](https://github.com/motdotla/dotenv/compare/v16.3.2...v16.4.0) (2024-01-23) - -- Add `error.code` to error messages around `.env.vault` decryption handling [#795](https://github.com/motdotla/dotenv/pull/795) -- Add ability to find `.env.vault` file when filename(s) passed as an array [#784](https://github.com/motdotla/dotenv/pull/784) - -## [16.3.2](https://github.com/motdotla/dotenv/compare/v16.3.1...v16.3.2) (2024-01-18) - -### Added - -- Add debug message when no encoding set [#735](https://github.com/motdotla/dotenv/pull/735) - -### Changed - -- Fix output typing for `populate` [#792](https://github.com/motdotla/dotenv/pull/792) -- Use subarray instead of slice [#793](https://github.com/motdotla/dotenv/pull/793) - -## [16.3.1](https://github.com/motdotla/dotenv/compare/v16.3.0...v16.3.1) (2023-06-17) - -### Added - -- Add missing type definitions for `processEnv` and `DOTENV_KEY` options. [#756](https://github.com/motdotla/dotenv/pull/756) - -## [16.3.0](https://github.com/motdotla/dotenv/compare/v16.2.0...v16.3.0) (2023-06-16) - -### Added - -- Optionally pass `DOTENV_KEY` to options rather than relying on `process.env.DOTENV_KEY`. Defaults to `process.env.DOTENV_KEY` [#754](https://github.com/motdotla/dotenv/pull/754) - -## [16.2.0](https://github.com/motdotla/dotenv/compare/v16.1.4...v16.2.0) (2023-06-15) - -### Added - -- Optionally write to your own target object rather than `process.env`. Defaults to `process.env`. [#753](https://github.com/motdotla/dotenv/pull/753) -- Add import type URL to types file [#751](https://github.com/motdotla/dotenv/pull/751) - -## [16.1.4](https://github.com/motdotla/dotenv/compare/v16.1.3...v16.1.4) (2023-06-04) - -### Added - -- Added `.github/` to `.npmignore` [#747](https://github.com/motdotla/dotenv/pull/747) - -## [16.1.3](https://github.com/motdotla/dotenv/compare/v16.1.2...v16.1.3) (2023-05-31) - -### Removed - -- Removed `browser` keys for `path`, `os`, and `crypto` in package.json. These were set to false incorrectly as of 16.1. Instead, if using dotenv on the front-end make sure to include polyfills for `path`, `os`, and `crypto`. [node-polyfill-webpack-plugin](https://github.com/Richienb/node-polyfill-webpack-plugin) provides these. - -## [16.1.2](https://github.com/motdotla/dotenv/compare/v16.1.1...v16.1.2) (2023-05-31) - -### Changed - -- Exposed private function `_configDotenv` as `configDotenv`. [#744](https://github.com/motdotla/dotenv/pull/744) - -## [16.1.1](https://github.com/motdotla/dotenv/compare/v16.1.0...v16.1.1) (2023-05-30) - -### Added - -- Added type definition for `decrypt` function - -### Changed - -- Fixed `{crypto: false}` in `packageJson.browser` - -## [16.1.0](https://github.com/motdotla/dotenv/compare/v16.0.3...v16.1.0) (2023-05-30) - -### Added - -- Add `populate` convenience method [#733](https://github.com/motdotla/dotenv/pull/733) -- Accept URL as path option [#720](https://github.com/motdotla/dotenv/pull/720) -- Add dotenv to `npm fund` command -- Spanish language README [#698](https://github.com/motdotla/dotenv/pull/698) -- Add `.env.vault` support. 🎉 ([#730](https://github.com/motdotla/dotenv/pull/730)) - -ℹ️ `.env.vault` extends the `.env` file format standard with a localized encrypted vault file. Package it securely with your production code deploys. It's cloud agnostic so that you can deploy your secrets anywhere – without [risky third-party integrations](https://techcrunch.com/2023/01/05/circleci-breach/). [read more](https://github.com/motdotla/dotenv#-deploying) - -### Changed - -- Fixed "cannot resolve 'fs'" error on tools like Replit [#693](https://github.com/motdotla/dotenv/pull/693) - -## [16.0.3](https://github.com/motdotla/dotenv/compare/v16.0.2...v16.0.3) (2022-09-29) - -### Changed - -- Added library version to debug logs ([#682](https://github.com/motdotla/dotenv/pull/682)) - -## [16.0.2](https://github.com/motdotla/dotenv/compare/v16.0.1...v16.0.2) (2022-08-30) - -### Added - -- Export `env-options.js` and `cli-options.js` in package.json for use with downstream [dotenv-expand](https://github.com/motdotla/dotenv-expand) module - -## [16.0.1](https://github.com/motdotla/dotenv/compare/v16.0.0...v16.0.1) (2022-05-10) - -### Changed - -- Minor README clarifications -- Development ONLY: updated devDependencies as recommended for development only security risks ([#658](https://github.com/motdotla/dotenv/pull/658)) - -## [16.0.0](https://github.com/motdotla/dotenv/compare/v15.0.1...v16.0.0) (2022-02-02) - -### Added - -- _Breaking:_ Backtick support 🎉 ([#615](https://github.com/motdotla/dotenv/pull/615)) - -If you had values containing the backtick character, please quote those values with either single or double quotes. - -## [15.0.1](https://github.com/motdotla/dotenv/compare/v15.0.0...v15.0.1) (2022-02-02) - -### Changed - -- Properly parse empty single or double quoted values 🐞 ([#614](https://github.com/motdotla/dotenv/pull/614)) - -## [15.0.0](https://github.com/motdotla/dotenv/compare/v14.3.2...v15.0.0) (2022-01-31) - -`v15.0.0` is a major new release with some important breaking changes. - -### Added - -- _Breaking:_ Multiline parsing support (just works. no need for the flag.) - -### Changed - -- _Breaking:_ `#` marks the beginning of a comment (UNLESS the value is wrapped in quotes. Please update your `.env` files to wrap in quotes any values containing `#`. For example: `SECRET_HASH="something-with-a-#-hash"`). - -..Understandably, (as some teams have noted) this is tedious to do across the entire team. To make it less tedious, we recommend using [dotenv cli](https://github.com/dotenv-org/cli) going forward. It's an optional plugin that will keep your `.env` files in sync between machines, environments, or team members. - -### Removed - -- _Breaking:_ Remove multiline option (just works out of the box now. no need for the flag.) - -## [14.3.2](https://github.com/motdotla/dotenv/compare/v14.3.1...v14.3.2) (2022-01-25) - -### Changed - -- Preserve backwards compatibility on values containing `#` 🐞 ([#603](https://github.com/motdotla/dotenv/pull/603)) - -## [14.3.1](https://github.com/motdotla/dotenv/compare/v14.3.0...v14.3.1) (2022-01-25) - -### Changed - -- Preserve backwards compatibility on exports by re-introducing the prior in-place exports 🐞 ([#606](https://github.com/motdotla/dotenv/pull/606)) - -## [14.3.0](https://github.com/motdotla/dotenv/compare/v14.2.0...v14.3.0) (2022-01-24) - -### Added - -- Add `multiline` option 🎉 ([#486](https://github.com/motdotla/dotenv/pull/486)) - -## [14.2.0](https://github.com/motdotla/dotenv/compare/v14.1.1...v14.2.0) (2022-01-17) - -### Added - -- Add `dotenv_config_override` cli option -- Add `DOTENV_CONFIG_OVERRIDE` command line env option - -## [14.1.1](https://github.com/motdotla/dotenv/compare/v14.1.0...v14.1.1) (2022-01-17) - -### Added - -- Add React gotcha to FAQ on README - -## [14.1.0](https://github.com/motdotla/dotenv/compare/v14.0.1...v14.1.0) (2022-01-17) - -### Added - -- Add `override` option 🎉 ([#595](https://github.com/motdotla/dotenv/pull/595)) - -## [14.0.1](https://github.com/motdotla/dotenv/compare/v14.0.0...v14.0.1) (2022-01-16) - -### Added - -- Log error on failure to load `.env` file ([#594](https://github.com/motdotla/dotenv/pull/594)) - -## [14.0.0](https://github.com/motdotla/dotenv/compare/v13.0.1...v14.0.0) (2022-01-16) - -### Added - -- _Breaking:_ Support inline comments for the parser 🎉 ([#568](https://github.com/motdotla/dotenv/pull/568)) - -## [13.0.1](https://github.com/motdotla/dotenv/compare/v13.0.0...v13.0.1) (2022-01-16) - -### Changed - -* Hide comments and newlines from debug output ([#404](https://github.com/motdotla/dotenv/pull/404)) - -## [13.0.0](https://github.com/motdotla/dotenv/compare/v12.0.4...v13.0.0) (2022-01-16) - -### Added - -* _Breaking:_ Add type file for `config.js` ([#539](https://github.com/motdotla/dotenv/pull/539)) - -## [12.0.4](https://github.com/motdotla/dotenv/compare/v12.0.3...v12.0.4) (2022-01-16) - -### Changed - -* README updates -* Minor order adjustment to package json format - -## [12.0.3](https://github.com/motdotla/dotenv/compare/v12.0.2...v12.0.3) (2022-01-15) - -### Changed - -* Simplified jsdoc for consistency across editors - -## [12.0.2](https://github.com/motdotla/dotenv/compare/v12.0.1...v12.0.2) (2022-01-15) - -### Changed - -* Improve embedded jsdoc type documentation - -## [12.0.1](https://github.com/motdotla/dotenv/compare/v12.0.0...v12.0.1) (2022-01-15) - -### Changed - -* README updates and clarifications - -## [12.0.0](https://github.com/motdotla/dotenv/compare/v11.0.0...v12.0.0) (2022-01-15) - -### Removed - -- _Breaking:_ drop support for Flow static type checker ([#584](https://github.com/motdotla/dotenv/pull/584)) - -### Changed - -- Move types/index.d.ts to lib/main.d.ts ([#585](https://github.com/motdotla/dotenv/pull/585)) -- Typescript cleanup ([#587](https://github.com/motdotla/dotenv/pull/587)) -- Explicit typescript inclusion in package.json ([#566](https://github.com/motdotla/dotenv/pull/566)) - -## [11.0.0](https://github.com/motdotla/dotenv/compare/v10.0.0...v11.0.0) (2022-01-11) - -### Changed - -- _Breaking:_ drop support for Node v10 ([#558](https://github.com/motdotla/dotenv/pull/558)) -- Patch debug option ([#550](https://github.com/motdotla/dotenv/pull/550)) - -## [10.0.0](https://github.com/motdotla/dotenv/compare/v9.0.2...v10.0.0) (2021-05-20) - -### Added - -- Add generic support to parse function -- Allow for import "dotenv/config.js" -- Add support to resolve home directory in path via ~ - -## [9.0.2](https://github.com/motdotla/dotenv/compare/v9.0.1...v9.0.2) (2021-05-10) - -### Changed - -- Support windows newlines with debug mode - -## [9.0.1](https://github.com/motdotla/dotenv/compare/v9.0.0...v9.0.1) (2021-05-08) - -### Changed - -- Updates to README - -## [9.0.0](https://github.com/motdotla/dotenv/compare/v8.6.0...v9.0.0) (2021-05-05) - -### Changed - -- _Breaking:_ drop support for Node v8 - -## [8.6.0](https://github.com/motdotla/dotenv/compare/v8.5.1...v8.6.0) (2021-05-05) - -### Added - -- define package.json in exports - -## [8.5.1](https://github.com/motdotla/dotenv/compare/v8.5.0...v8.5.1) (2021-05-05) - -### Changed - -- updated dev dependencies via npm audit - -## [8.5.0](https://github.com/motdotla/dotenv/compare/v8.4.0...v8.5.0) (2021-05-05) - -### Added - -- allow for `import "dotenv/config"` - -## [8.4.0](https://github.com/motdotla/dotenv/compare/v8.3.0...v8.4.0) (2021-05-05) - -### Changed - -- point to exact types file to work with VS Code - -## [8.3.0](https://github.com/motdotla/dotenv/compare/v8.2.0...v8.3.0) (2021-05-05) - -### Changed - -- _Breaking:_ drop support for Node v8 (mistake to be released as minor bump. later bumped to 9.0.0. see above.) - -## [8.2.0](https://github.com/motdotla/dotenv/compare/v8.1.0...v8.2.0) (2019-10-16) - -### Added - -- TypeScript types - -## [8.1.0](https://github.com/motdotla/dotenv/compare/v8.0.0...v8.1.0) (2019-08-18) - -### Changed - -- _Breaking:_ drop support for Node v6 ([#392](https://github.com/motdotla/dotenv/issues/392)) - -# [8.0.0](https://github.com/motdotla/dotenv/compare/v7.0.0...v8.0.0) (2019-05-02) - -### Changed - -- _Breaking:_ drop support for Node v6 ([#302](https://github.com/motdotla/dotenv/issues/392)) - -## [7.0.0] - 2019-03-12 - -### Fixed - -- Fix removing unbalanced quotes ([#376](https://github.com/motdotla/dotenv/pull/376)) - -### Removed - -- Removed `load` alias for `config` for consistency throughout code and documentation. - -## [6.2.0] - 2018-12-03 - -### Added - -- Support preload configuration via environment variables ([#351](https://github.com/motdotla/dotenv/issues/351)) - -## [6.1.0] - 2018-10-08 - -### Added - -- `debug` option for `config` and `parse` methods will turn on logging - -## [6.0.0] - 2018-06-02 - -### Changed - -- _Breaking:_ drop support for Node v4 ([#304](https://github.com/motdotla/dotenv/pull/304)) - -## [5.0.0] - 2018-01-29 - -### Added - -- Testing against Node v8 and v9 -- Documentation on trim behavior of values -- Documentation on how to use with `import` - -### Changed - -- _Breaking_: default `path` is now `path.resolve(process.cwd(), '.env')` -- _Breaking_: does not write over keys already in `process.env` if the key has a falsy value -- using `const` and `let` instead of `var` - -### Removed - -- Testing against Node v7 - -## [4.0.0] - 2016-12-23 - -### Changed - -- Return Object with parsed content or error instead of false ([#165](https://github.com/motdotla/dotenv/pull/165)). - -### Removed - -- `verbose` option removed in favor of returning result. - -## [3.0.0] - 2016-12-20 - -### Added - -- `verbose` option will log any error messages. Off by default. -- parses email addresses correctly -- allow importing config method directly in ES6 - -### Changed - -- Suppress error messages by default ([#154](https://github.com/motdotla/dotenv/pull/154)) -- Ignoring more files for NPM to make package download smaller - -### Fixed - -- False positive test due to case-sensitive variable ([#124](https://github.com/motdotla/dotenv/pull/124)) - -### Removed - -- `silent` option removed in favor of `verbose` - -## [2.0.0] - 2016-01-20 - -### Added - -- CHANGELOG to ["make it easier for users and contributors to see precisely what notable changes have been made between each release"](http://keepachangelog.com/). Linked to from README -- LICENSE to be more explicit about what was defined in `package.json`. Linked to from README -- Testing nodejs v4 on travis-ci -- added examples of how to use dotenv in different ways -- return parsed object on success rather than boolean true - -### Changed - -- README has shorter description not referencing ruby gem since we don't have or want feature parity - -### Removed - -- Variable expansion and escaping so environment variables are encouraged to be fully orthogonal - -## [1.2.0] - 2015-06-20 - -### Added - -- Preload hook to require dotenv without including it in your code - -### Changed - -- clarified license to be "BSD-2-Clause" in `package.json` - -### Fixed - -- retain spaces in string vars - -## [1.1.0] - 2015-03-31 - -### Added - -- Silent option to silence `console.log` when `.env` missing - -## [1.0.0] - 2015-03-13 - -### Removed - -- support for multiple `.env` files. should always use one `.env` file for the current environment - -[7.0.0]: https://github.com/motdotla/dotenv/compare/v6.2.0...v7.0.0 -[6.2.0]: https://github.com/motdotla/dotenv/compare/v6.1.0...v6.2.0 -[6.1.0]: https://github.com/motdotla/dotenv/compare/v6.0.0...v6.1.0 -[6.0.0]: https://github.com/motdotla/dotenv/compare/v5.0.0...v6.0.0 -[5.0.0]: https://github.com/motdotla/dotenv/compare/v4.0.0...v5.0.0 -[4.0.0]: https://github.com/motdotla/dotenv/compare/v3.0.0...v4.0.0 -[3.0.0]: https://github.com/motdotla/dotenv/compare/v2.0.0...v3.0.0 -[2.0.0]: https://github.com/motdotla/dotenv/compare/v1.2.0...v2.0.0 -[1.2.0]: https://github.com/motdotla/dotenv/compare/v1.1.0...v1.2.0 -[1.1.0]: https://github.com/motdotla/dotenv/compare/v1.0.0...v1.1.0 -[1.0.0]: https://github.com/motdotla/dotenv/compare/v0.4.0...v1.0.0 diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/LICENSE deleted file mode 100644 index c430ad8bd..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2015, Scott Motte -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/README-es.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/README-es.md deleted file mode 100644 index 441160c37..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/README-es.md +++ /dev/null @@ -1,774 +0,0 @@ -# dotenv [![NPM version](https://img.shields.io/npm/v/dotenv.svg?style=flat-square)](https://www.npmjs.com/package/dotenv) [![downloads](https://img.shields.io/npm/dw/dotenv)](https://www.npmjs.com/package/dotenv) - -dotenv - -Dotenv is a zero-dependency module that loads environment variables from a `.env` file into [`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env). Storing configuration in the environment separate from code is based on [The Twelve-Factor App](https://12factor.net/config) methodology. - -[Watch the tutorial](https://www.youtube.com/watch?v=YtkZR0NFd1g) - -  - -## Usage - -Install it. - -```sh -npm install dotenv --save -``` - -Create a `.env` file in the root of your project: - -```ini -# .env -S3_BUCKET="YOURS3BUCKET" -SECRET_KEY="YOURSECRETKEYGOESHERE" -``` - -And as early as possible in your application, import and configure dotenv: - -```javascript -require('dotenv').config() // or import 'dotenv/config' if you're using ES6 -... -console.log(process.env) // remove this after you've confirmed it is working -``` - -That's it. `process.env` now has the keys and values you defined in your `.env` file: - -  - -## Advanced - -
ES6
- -Import with [ES6](#how-do-i-use-dotenv-with-import): - -```javascript -import 'dotenv/config' -``` - -ES6 import if you need to set config options: - -```javascript -import dotenv from 'dotenv' -dotenv.config({ path: '/custom/path/to/.env' }) -``` - -
-
bun
- -```sh -bun add dotenv -``` - -
-
yarn
- -```sh -yarn add dotenv -``` - -
-
pnpm
- -```sh -pnpm add dotenv -``` - -
-
Monorepos
- -For monorepos with a structure like `apps/backend/app.js`, put it the `.env` file in the root of the folder where your `app.js` process runs. - -```ini -# app/backend/.env -S3_BUCKET="YOURS3BUCKET" -SECRET_KEY="YOURSECRETKEYGOESHERE" -``` - -
-
Multiline Values
- -If you need multiline variables, for example private keys, those are now supported (`>= v15.0.0`) with line breaks: - -```ini -PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY----- -... -Kh9NV... -... ------END RSA PRIVATE KEY-----" -``` - -Alternatively, you can double quote strings and use the `\n` character: - -```ini -PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END RSA PRIVATE KEY-----\n" -``` - -
-
Comments
- -Comments may be added to your file on their own line or inline: - -```ini -# This is a comment -SECRET_KEY=YOURSECRETKEYGOESHERE # comment -SECRET_HASH="something-with-a-#-hash" -``` - -Comments begin where a `#` exists, so if your value contains a `#` please wrap it in quotes. This is a breaking change from `>= v15.0.0` and on. - -
-
Parsing
- -The engine which parses the contents of your file containing environment variables is available to use. It accepts a String or Buffer and will return an Object with the parsed keys and values. - -```javascript -const dotenv = require('dotenv') -const buf = Buffer.from('BASIC=basic') -const config = dotenv.parse(buf) // will return an object -console.log(typeof config, config) // object { BASIC : 'basic' } -``` - -
-
Preload
- -> Note: Consider using [`dotenvx`](https://github.com/dotenvx/dotenvx) instead of preloading. I am now doing (and recommending) so. -> -> It serves the same purpose (you do not need to require and load dotenv), adds better debugging, and works with ANY language, framework, or platform. – [motdotla](https://mot.la) - -You can use the `--require` (`-r`) [command line option](https://nodejs.org/api/cli.html#-r---require-module) to preload dotenv. By doing this, you do not need to require and load dotenv in your application code. - -```bash -$ node -r dotenv/config your_script.js -``` - -The configuration options below are supported as command line arguments in the format `dotenv_config_
-
Variable Expansion
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) for variable expansion. - -Reference and expand variables already on your machine for use in your .env file. - -```ini -# .env -USERNAME="username" -DATABASE_URL="postgres://${USERNAME}@localhost/my_database" -``` -```js -// index.js -console.log('DATABASE_URL', process.env.DATABASE_URL) -``` -```sh -$ dotenvx run --debug -- node index.js -[dotenvx@0.14.1] injecting env (2) from .env -DATABASE_URL postgres://username@localhost/my_database -``` - -
-
Command Substitution
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) for command substitution. - -Add the output of a command to one of your variables in your .env file. - -```ini -# .env -DATABASE_URL="postgres://$(whoami)@localhost/my_database" -``` -```js -// index.js -console.log('DATABASE_URL', process.env.DATABASE_URL) -``` -```sh -$ dotenvx run --debug -- node index.js -[dotenvx@0.14.1] injecting env (1) from .env -DATABASE_URL postgres://yourusername@localhost/my_database -``` - -
-
Encryption
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) for encryption. - -Add encryption to your `.env` files with a single command. - -``` -$ dotenvx set HELLO Production -f .env.production -$ echo "console.log('Hello ' + process.env.HELLO)" > index.js - -$ DOTENV_PRIVATE_KEY_PRODUCTION="<.env.production private key>" dotenvx run -- node index.js -[dotenvx] injecting env (2) from .env.production -Hello Production -``` - -[learn more](https://github.com/dotenvx/dotenvx?tab=readme-ov-file#encryption) - -
-
Multiple Environments
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) to manage multiple environments. - -Run any environment locally. Create a `.env.ENVIRONMENT` file and use `-f` to load it. It's straightforward, yet flexible. - -```bash -$ echo "HELLO=production" > .env.production -$ echo "console.log('Hello ' + process.env.HELLO)" > index.js - -$ dotenvx run -f=.env.production -- node index.js -Hello production -> ^^ -``` - -or with multiple .env files - -```bash -$ echo "HELLO=local" > .env.local -$ echo "HELLO=World" > .env -$ echo "console.log('Hello ' + process.env.HELLO)" > index.js - -$ dotenvx run -f=.env.local -f=.env -- node index.js -Hello local -``` - -[more environment examples](https://dotenvx.com/docs/quickstart/environments) - -
-
Production
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) for production deploys. - -Create a `.env.production` file. - -```sh -$ echo "HELLO=production" > .env.production -``` - -Encrypt it. - -```sh -$ dotenvx encrypt -f .env.production -``` - -Set `DOTENV_PRIVATE_KEY_PRODUCTION` (found in `.env.keys`) on your server. - -``` -$ heroku config:set DOTENV_PRIVATE_KEY_PRODUCTION=value -``` - -Commit your `.env.production` file to code and deploy. - -``` -$ git add .env.production -$ git commit -m "encrypted .env.production" -$ git push heroku main -``` - -Dotenvx will decrypt and inject the secrets at runtime using `dotenvx run -- node index.js`. - -
-
Syncing
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) to sync your .env files. - -Encrypt them with `dotenvx encrypt -f .env` and safely include them in source control. Your secrets are securely synced with your git. - -This still subscribes to the twelve-factor app rules by generating a decryption key separate from code. - -
-
More Examples
- -See [examples](https://github.com/dotenv-org/examples) of using dotenv with various frameworks, languages, and configurations. - -* [nodejs](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-nodejs) -* [nodejs (debug on)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-nodejs-debug) -* [nodejs (override on)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-nodejs-override) -* [nodejs (processEnv override)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-custom-target) -* [esm](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-esm) -* [esm (preload)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-esm-preload) -* [typescript](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-typescript) -* [typescript parse](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-typescript-parse) -* [typescript config](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-typescript-config) -* [webpack](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-webpack) -* [webpack (plugin)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-webpack2) -* [react](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-react) -* [react (typescript)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-react-typescript) -* [express](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-express) -* [nestjs](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-nestjs) -* [fastify](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-fastify) - -
- -  - -## Agentes - -dotenvx-as2 - -> El software está cambiando, y dotenv debe cambiar con él—por eso construí [agentic secret storage (AS2)](https://dotenvx.com/as2). Los agentes ejecutan código sin humanos en la terminal, por lo que los archivos `.env` en texto plano son el primitivo equivocado. -> -> AS2 está diseñado para software autónomo: cifrado por defecto, cero acceso a consola y entrega priorizando la criptografía que mantiene a los operadores fuera del circuito. -> -> Está respaldado por [Vestauth](https://github.com/vestauth/vestauth), la capa de autenticación pionera y de confianza para agentes—que otorga a cada agente una identidad criptográfica para firmar solicitudes con claves privadas y verificarlas con claves públicas. Sin secretos compartidos que se filtren. -> -> Es lo que uso ahora. - [motdotla](https://mot.la) - -### Inicio rápido - -Instala vestauth e inicializa tu agente. - -```bash -npm i -g vestauth - -vestauth agent init -``` - -Tu agente puede `set` secretos con un endpoint `curl` simple: - -```bash -vestauth agent curl -X POST https://as2.dotenvx.com/set -d '{"KEY":"value"}' -``` - -Y tu agente puede `get` secretos con un endpoint `curl` simple: - -```bash -vestauth agent curl https://as2.dotenvx.com/get?key=KEY -``` - -¡Eso es todo! Este nuevo primitivo habilita el acceso a secretos para agentes sin intervención humana, flujos de OAuth ni claves API. Es el futuro para los agentes. - -  - -## FAQ - -
Should I commit my `.env` file?
- -No. - -Unless you encrypt it with [dotenvx](https://github.com/dotenvx/dotenvx). Then we recommend you do. - -
-
What about variable expansion?
- -Use [dotenvx](https://github.com/dotenvx/dotenvx). - -
-
Should I have multiple `.env` files?
- -We recommend creating one `.env` file per environment. Use `.env` for local/development, `.env.production` for production and so on. This still follows the twelve factor principles as each is attributed individually to its own environment. Avoid custom set ups that work in inheritance somehow (`.env.production` inherits values form `.env` for example). It is better to duplicate values if necessary across each `.env.environment` file. - -> In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as “environments”, but instead are independently managed for each deploy. This is a model that scales up smoothly as the app naturally expands into more deploys over its lifetime. -> -> – [The Twelve-Factor App](http://12factor.net/config) - -Additionally, we recommend using [dotenvx](https://github.com/dotenvx/dotenvx) to encrypt and manage these. - -
- -
How do I use dotenv with `import`?
- -Simply.. - -```javascript -// index.mjs (ESM) -import 'dotenv/config' // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import -import express from 'express' -``` - -A little background.. - -> When you run a module containing an `import` declaration, the modules it imports are loaded first, then each module body is executed in a depth-first traversal of the dependency graph, avoiding cycles by skipping anything already executed. -> -> – [ES6 In Depth: Modules](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/) - -What does this mean in plain language? It means you would think the following would work but it won't. - -`errorReporter.mjs`: -```js -class Client { - constructor (apiKey) { - console.log('apiKey', apiKey) - - this.apiKey = apiKey - } -} - -export default new Client(process.env.API_KEY) -``` -`index.mjs`: -```js -// Note: this is INCORRECT and will not work -import * as dotenv from 'dotenv' -dotenv.config() - -import errorReporter from './errorReporter.mjs' // process.env.API_KEY will be blank! -``` - -`process.env.API_KEY` will be blank. - -Instead, `index.mjs` should be written as.. - -```js -import 'dotenv/config' - -import errorReporter from './errorReporter.mjs' -``` - -Does that make sense? It's a bit unintuitive, but it is how importing of ES6 modules work. Here is a [working example of this pitfall](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-es6-import-pitfall). - -There are two alternatives to this approach: - -1. Preload with dotenvx: `dotenvx run -- node index.js` (_Note: you do not need to `import` dotenv with this approach_) -2. Create a separate file that will execute `config` first as outlined in [this comment on #133](https://github.com/motdotla/dotenv/issues/133#issuecomment-255298822) -
- -
Can I customize/write plugins for dotenv?
- -Yes! `dotenv.config()` returns an object representing the parsed `.env` file. This gives you everything you need to continue setting values on `process.env`. For example: - -```js -const dotenv = require('dotenv') -const variableExpansion = require('dotenv-expand') -const myEnv = dotenv.config() -variableExpansion(myEnv) -``` - -
-
What rules does the parsing engine follow?
- -The parsing engine currently supports the following rules: - -- `BASIC=basic` becomes `{BASIC: 'basic'}` -- empty lines are skipped -- lines beginning with `#` are treated as comments -- `#` marks the beginning of a comment (unless when the value is wrapped in quotes) -- empty values become empty strings (`EMPTY=` becomes `{EMPTY: ''}`) -- inner quotes are maintained (think JSON) (`JSON={"foo": "bar"}` becomes `{JSON:"{\"foo\": \"bar\"}"`) -- whitespace is removed from both ends of unquoted values (see more on [`trim`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)) (`FOO= some value ` becomes `{FOO: 'some value'}`) -- single and double quoted values are escaped (`SINGLE_QUOTE='quoted'` becomes `{SINGLE_QUOTE: "quoted"}`) -- single and double quoted values maintain whitespace from both ends (`FOO=" some value "` becomes `{FOO: ' some value '}`) -- double quoted values expand new lines (`MULTILINE="new\nline"` becomes - -``` -{MULTILINE: 'new -line'} -``` - -- backticks are supported (`` BACKTICK_KEY=`This has 'single' and "double" quotes inside of it.` ``) - -
-
What about syncing and securing .env files?
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) to unlock syncing encrypted .env files over git. - -
-
What if I accidentally commit my `.env` file to code?
- -Remove it, [remove git history](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository) and then install the [git pre-commit hook](https://github.com/dotenvx/dotenvx#pre-commit) to prevent this from ever happening again. - -``` -npm i -g @dotenvx/dotenvx -dotenvx precommit --install -``` - -
-
What happens to environment variables that were already set?
- -By default, we will never modify any environment variables that have already been set. In particular, if there is a variable in your `.env` file which collides with one that already exists in your environment, then that variable will be skipped. - -If instead, you want to override `process.env` use the `override` option. - -```javascript -require('dotenv').config({ override: true }) -``` - -
-
How can I prevent committing my `.env` file to a Docker build?
- -Use the [docker prebuild hook](https://dotenvx.com/docs/features/prebuild). - -```bash -# Dockerfile -... -RUN curl -fsS https://dotenvx.sh/ | sh -... -RUN dotenvx prebuild -CMD ["dotenvx", "run", "--", "node", "index.js"] -``` - -
-
How come my environment variables are not showing up for React?
- -Your React code is run in Webpack, where the `fs` module or even the `process` global itself are not accessible out-of-the-box. `process.env` can only be injected through Webpack configuration. - -If you are using [`react-scripts`](https://www.npmjs.com/package/react-scripts), which is distributed through [`create-react-app`](https://create-react-app.dev/), it has dotenv built in but with a quirk. Preface your environment variables with `REACT_APP_`. See [this stack overflow](https://stackoverflow.com/questions/42182577/is-it-possible-to-use-dotenv-in-a-react-project) for more details. - -If you are using other frameworks (e.g. Next.js, Gatsby...), you need to consult their documentation for how to inject environment variables into the client. - -
-
Why is the `.env` file not loading my environment variables successfully?
- -Most likely your `.env` file is not in the correct place. [See this stack overflow](https://stackoverflow.com/questions/42335016/dotenv-file-is-not-loading-environment-variables). - -Turn on debug mode and try again.. - -```js -require('dotenv').config({ debug: true }) -``` - -You will receive a helpful error outputted to your console. - -
-
Why am I getting the error `Module not found: Error: Can't resolve 'crypto|os|path'`?
- -You are using dotenv on the front-end and have not included a polyfill. Webpack < 5 used to include these for you. Do the following: - -```bash -npm install node-polyfill-webpack-plugin -``` - -Configure your `webpack.config.js` to something like the following. - -```js -require('dotenv').config() - -const path = require('path'); -const webpack = require('webpack') - -const NodePolyfillPlugin = require('node-polyfill-webpack-plugin') - -module.exports = { - mode: 'development', - entry: './src/index.ts', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist'), - }, - plugins: [ - new NodePolyfillPlugin(), - new webpack.DefinePlugin({ - 'process.env': { - HELLO: JSON.stringify(process.env.HELLO) - } - }), - ] -}; -``` - -Alternatively, just use [dotenv-webpack](https://github.com/mrsteele/dotenv-webpack) which does this and more behind the scenes for you. - -
- -  - -## Docs - -Dotenv exposes four functions: - -* `config` -* `parse` -* `populate` - -### Config - -`config` will read your `.env` file, parse the contents, assign it to -[`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env), -and return an Object with a `parsed` key containing the loaded content or an `error` key if it failed. - -```js -const result = dotenv.config() - -if (result.error) { - throw result.error -} - -console.log(result.parsed) -``` - -You can additionally, pass options to `config`. - -#### Options - -##### path - -Default: `path.resolve(process.cwd(), '.env')` - -Specify a custom path if your file containing environment variables is located elsewhere. - -```js -require('dotenv').config({ path: '/custom/path/to/.env' }) -``` - -By default, `config` will look for a file called .env in the current working directory. - -Pass in multiple files as an array, and they will be parsed in order and combined with `process.env` (or `option.processEnv`, if set). The first value set for a variable will win, unless the `options.override` flag is set, in which case the last value set will win. If a value already exists in `process.env` and the `options.override` flag is NOT set, no changes will be made to that value. - -```js -require('dotenv').config({ path: ['.env.local', '.env'] }) -``` - -##### quiet - -Default: `false` - -Suppress runtime logging message. - -```js -// index.js -require('dotenv').config({ quiet: false }) // change to true to suppress -console.log(`Hello ${process.env.HELLO}`) -``` - -```ini -# .env -HELLO=World -``` - -```sh -$ node index.js -[dotenv@17.0.0] injecting env (1) from .env -Hello World -``` - -##### encoding - -Default: `utf8` - -Specify the encoding of your file containing environment variables. - -```js -require('dotenv').config({ encoding: 'latin1' }) -``` - -##### debug - -Default: `false` - -Turn on logging to help debug why certain keys or values are not being set as you expect. - -```js -require('dotenv').config({ debug: process.env.DEBUG }) -``` - -##### override - -Default: `false` - -Override any environment variables that have already been set on your machine with values from your .env file(s). If multiple files have been provided in `option.path` the override will also be used as each file is combined with the next. Without `override` being set, the first value wins. With `override` set the last value wins. - -```js -require('dotenv').config({ override: true }) -``` - -##### processEnv - -Default: `process.env` - -Specify an object to write your environment variables to. Defaults to `process.env` environment variables. - -```js -const myObject = {} -require('dotenv').config({ processEnv: myObject }) - -console.log(myObject) // values from .env -console.log(process.env) // this was not changed or written to -``` - -### Parse - -The engine which parses the contents of your file containing environment -variables is available to use. It accepts a String or Buffer and will return -an Object with the parsed keys and values. - -```js -const dotenv = require('dotenv') -const buf = Buffer.from('BASIC=basic') -const config = dotenv.parse(buf) // will return an object -console.log(typeof config, config) // object { BASIC : 'basic' } -``` - -#### Options - -##### debug - -Default: `false` - -Turn on logging to help debug why certain keys or values are not being set as you expect. - -```js -const dotenv = require('dotenv') -const buf = Buffer.from('hello world') -const opt = { debug: true } -const config = dotenv.parse(buf, opt) -// expect a debug message because the buffer is not in KEY=VAL form -``` - -### Populate - -The engine which populates the contents of your .env file to `process.env` is available for use. It accepts a target, a source, and options. This is useful for power users who want to supply their own objects. - -For example, customizing the source: - -```js -const dotenv = require('dotenv') -const parsed = { HELLO: 'world' } - -dotenv.populate(process.env, parsed) - -console.log(process.env.HELLO) // world -``` - -For example, customizing the source AND target: - -```js -const dotenv = require('dotenv') -const parsed = { HELLO: 'universe' } -const target = { HELLO: 'world' } // empty object - -dotenv.populate(target, parsed, { override: true, debug: true }) - -console.log(target) // { HELLO: 'universe' } -``` - -#### options - -##### Debug - -Default: `false` - -Turn on logging to help debug why certain keys or values are not being populated as you expect. - -##### override - -Default: `false` - -Override any environment variables that have already been set. - -  - -## CHANGELOG - -See [CHANGELOG.md](CHANGELOG.md) - -  - -## Who's using dotenv? - -[These npm modules depend on it.](https://www.npmjs.com/browse/depended/dotenv) - -Projects that expand it often use the [keyword "dotenv" on npm](https://www.npmjs.com/search?q=keywords:dotenv). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/README.md deleted file mode 100644 index b82a43814..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/README.md +++ /dev/null @@ -1,774 +0,0 @@ -# dotenv [![NPM version](https://img.shields.io/npm/v/dotenv.svg?style=flat-square)](https://www.npmjs.com/package/dotenv) [![downloads](https://img.shields.io/npm/dw/dotenv)](https://www.npmjs.com/package/dotenv) - -dotenv - -Dotenv is a zero-dependency module that loads environment variables from a `.env` file into [`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env). Storing configuration in the environment separate from code is based on [The Twelve-Factor App](https://12factor.net/config) methodology. - -[Watch the tutorial](https://www.youtube.com/watch?v=YtkZR0NFd1g) - -  - -## Usage - -Install it. - -```sh -npm install dotenv --save -``` - -Create a `.env` file in the root of your project: - -```ini -# .env -S3_BUCKET="YOURS3BUCKET" -SECRET_KEY="YOURSECRETKEYGOESHERE" -``` - -And as early as possible in your application, import and configure dotenv: - -```javascript -require('dotenv').config() // or import 'dotenv/config' if you're using ES6 -... -console.log(process.env) // remove this after you've confirmed it is working -``` - -That's it. `process.env` now has the keys and values you defined in your `.env` file: - -  - -## Advanced - -
ES6
- -Import with [ES6](#how-do-i-use-dotenv-with-import): - -```javascript -import 'dotenv/config' -``` - -ES6 import if you need to set config options: - -```javascript -import dotenv from 'dotenv' -dotenv.config({ path: '/custom/path/to/.env' }) -``` - -
-
bun
- -```sh -bun add dotenv -``` - -
-
yarn
- -```sh -yarn add dotenv -``` - -
-
pnpm
- -```sh -pnpm add dotenv -``` - -
-
Monorepos
- -For monorepos with a structure like `apps/backend/app.js`, put it the `.env` file in the root of the folder where your `app.js` process runs. - -```ini -# app/backend/.env -S3_BUCKET="YOURS3BUCKET" -SECRET_KEY="YOURSECRETKEYGOESHERE" -``` - -
-
Multiline Values
- -If you need multiline variables, for example private keys, those are now supported (`>= v15.0.0`) with line breaks: - -```ini -PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY----- -... -Kh9NV... -... ------END RSA PRIVATE KEY-----" -``` - -Alternatively, you can double quote strings and use the `\n` character: - -```ini -PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END RSA PRIVATE KEY-----\n" -``` - -
-
Comments
- -Comments may be added to your file on their own line or inline: - -```ini -# This is a comment -SECRET_KEY=YOURSECRETKEYGOESHERE # comment -SECRET_HASH="something-with-a-#-hash" -``` - -Comments begin where a `#` exists, so if your value contains a `#` please wrap it in quotes. This is a breaking change from `>= v15.0.0` and on. - -
-
Parsing
- -The engine which parses the contents of your file containing environment variables is available to use. It accepts a String or Buffer and will return an Object with the parsed keys and values. - -```javascript -const dotenv = require('dotenv') -const buf = Buffer.from('BASIC=basic') -const config = dotenv.parse(buf) // will return an object -console.log(typeof config, config) // object { BASIC : 'basic' } -``` - -
-
Preload
- -> Note: Consider using [`dotenvx`](https://github.com/dotenvx/dotenvx) instead of preloading. I am now doing (and recommending) so. -> -> It serves the same purpose (you do not need to require and load dotenv), adds better debugging, and works with ANY language, framework, or platform. – [motdotla](https://mot.la) - -You can use the `--require` (`-r`) [command line option](https://nodejs.org/api/cli.html#-r---require-module) to preload dotenv. By doing this, you do not need to require and load dotenv in your application code. - -```bash -$ node -r dotenv/config your_script.js -``` - -The configuration options below are supported as command line arguments in the format `dotenv_config_
-
Variable Expansion
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) for variable expansion. - -Reference and expand variables already on your machine for use in your .env file. - -```ini -# .env -USERNAME="username" -DATABASE_URL="postgres://${USERNAME}@localhost/my_database" -``` -```js -// index.js -console.log('DATABASE_URL', process.env.DATABASE_URL) -``` -```sh -$ dotenvx run --debug -- node index.js -[dotenvx@0.14.1] injecting env (2) from .env -DATABASE_URL postgres://username@localhost/my_database -``` - -
-
Command Substitution
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) for command substitution. - -Add the output of a command to one of your variables in your .env file. - -```ini -# .env -DATABASE_URL="postgres://$(whoami)@localhost/my_database" -``` -```js -// index.js -console.log('DATABASE_URL', process.env.DATABASE_URL) -``` -```sh -$ dotenvx run --debug -- node index.js -[dotenvx@0.14.1] injecting env (1) from .env -DATABASE_URL postgres://yourusername@localhost/my_database -``` - -
-
Encryption
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) for encryption. - -Add encryption to your `.env` files with a single command. - -``` -$ dotenvx set HELLO Production -f .env.production -$ echo "console.log('Hello ' + process.env.HELLO)" > index.js - -$ DOTENV_PRIVATE_KEY_PRODUCTION="<.env.production private key>" dotenvx run -- node index.js -[dotenvx] injecting env (2) from .env.production -Hello Production -``` - -[learn more](https://github.com/dotenvx/dotenvx?tab=readme-ov-file#encryption) - -
-
Multiple Environments
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) to manage multiple environments. - -Run any environment locally. Create a `.env.ENVIRONMENT` file and use `-f` to load it. It's straightforward, yet flexible. - -```bash -$ echo "HELLO=production" > .env.production -$ echo "console.log('Hello ' + process.env.HELLO)" > index.js - -$ dotenvx run -f=.env.production -- node index.js -Hello production -> ^^ -``` - -or with multiple .env files - -```bash -$ echo "HELLO=local" > .env.local -$ echo "HELLO=World" > .env -$ echo "console.log('Hello ' + process.env.HELLO)" > index.js - -$ dotenvx run -f=.env.local -f=.env -- node index.js -Hello local -``` - -[more environment examples](https://dotenvx.com/docs/quickstart/environments) - -
-
Production
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) for production deploys. - -Create a `.env.production` file. - -```sh -$ echo "HELLO=production" > .env.production -``` - -Encrypt it. - -```sh -$ dotenvx encrypt -f .env.production -``` - -Set `DOTENV_PRIVATE_KEY_PRODUCTION` (found in `.env.keys`) on your server. - -``` -$ heroku config:set DOTENV_PRIVATE_KEY_PRODUCTION=value -``` - -Commit your `.env.production` file to code and deploy. - -``` -$ git add .env.production -$ git commit -m "encrypted .env.production" -$ git push heroku main -``` - -Dotenvx will decrypt and inject the secrets at runtime using `dotenvx run -- node index.js`. - -
-
Syncing
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) to sync your .env files. - -Encrypt them with `dotenvx encrypt -f .env` and safely include them in source control. Your secrets are securely synced with your git. - -This still subscribes to the twelve-factor app rules by generating a decryption key separate from code. - -
-
More Examples
- -See [examples](https://github.com/dotenv-org/examples) of using dotenv with various frameworks, languages, and configurations. - -* [nodejs](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-nodejs) -* [nodejs (debug on)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-nodejs-debug) -* [nodejs (override on)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-nodejs-override) -* [nodejs (processEnv override)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-custom-target) -* [esm](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-esm) -* [esm (preload)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-esm-preload) -* [typescript](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-typescript) -* [typescript parse](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-typescript-parse) -* [typescript config](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-typescript-config) -* [webpack](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-webpack) -* [webpack (plugin)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-webpack2) -* [react](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-react) -* [react (typescript)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-react-typescript) -* [express](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-express) -* [nestjs](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-nestjs) -* [fastify](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-fastify) - -
- -  - -## Agents - -dotenvx-as2 - -> Software is changing, and dotenv must change with it—that is why I built [agentic secret storage (AS2)](https://dotenvx.com/as2). Agents run code without humans at terminals, so plaintext `.env` files are the wrong primitive. -> -> AS2 is built for autonomous software: encrypted by default, zero console access, and cryptography‑first delivery that keeps operators out of the loop. -> -> It is backed by [Vestauth](https://github.com/vestauth/vestauth), the trusted, pioneering auth layer for agents—giving each agent a cryptographic identity so requests are signed with private keys and verified with public keys. No shared secrets to leak. -> -> It's what I'm using now. - [motdotla](https://mot.la) - -### Quickstart - -Install vestauth and initialize your agent. - -```bash -npm i -g vestauth - -vestauth agent init -``` - -Your agent `set`s secrets with a simple `curl` endpoint: - -```bash -vestauth agent curl -X POST https://as2.dotenvx.com/set -d '{"KEY":"value"}' -``` - -And your agent `get`s secrets with a simple `curl` endpoint: - -```bash -vestauth agent curl https://as2.dotenvx.com/get?key=KEY -``` - -That's it! This new primitive unlocks secrets access for agents without human-in-the-loop, oauth flows, or API keys. It's the future for agents. - -  - -## FAQ - -
Should I commit my `.env` file?
- -No. - -Unless you encrypt it with [dotenvx](https://github.com/dotenvx/dotenvx). Then we recommend you do. - -
-
What about variable expansion?
- -Use [dotenvx](https://github.com/dotenvx/dotenvx). - -
-
Should I have multiple `.env` files?
- -We recommend creating one `.env` file per environment. Use `.env` for local/development, `.env.production` for production and so on. This still follows the twelve factor principles as each is attributed individually to its own environment. Avoid custom set ups that work in inheritance somehow (`.env.production` inherits values form `.env` for example). It is better to duplicate values if necessary across each `.env.environment` file. - -> In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as “environments”, but instead are independently managed for each deploy. This is a model that scales up smoothly as the app naturally expands into more deploys over its lifetime. -> -> – [The Twelve-Factor App](http://12factor.net/config) - -Additionally, we recommend using [dotenvx](https://github.com/dotenvx/dotenvx) to encrypt and manage these. - -
- -
How do I use dotenv with `import`?
- -Simply.. - -```javascript -// index.mjs (ESM) -import 'dotenv/config' // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import -import express from 'express' -``` - -A little background.. - -> When you run a module containing an `import` declaration, the modules it imports are loaded first, then each module body is executed in a depth-first traversal of the dependency graph, avoiding cycles by skipping anything already executed. -> -> – [ES6 In Depth: Modules](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/) - -What does this mean in plain language? It means you would think the following would work but it won't. - -`errorReporter.mjs`: -```js -class Client { - constructor (apiKey) { - console.log('apiKey', apiKey) - - this.apiKey = apiKey - } -} - -export default new Client(process.env.API_KEY) -``` -`index.mjs`: -```js -// Note: this is INCORRECT and will not work -import * as dotenv from 'dotenv' -dotenv.config() - -import errorReporter from './errorReporter.mjs' // process.env.API_KEY will be blank! -``` - -`process.env.API_KEY` will be blank. - -Instead, `index.mjs` should be written as.. - -```js -import 'dotenv/config' - -import errorReporter from './errorReporter.mjs' -``` - -Does that make sense? It's a bit unintuitive, but it is how importing of ES6 modules work. Here is a [working example of this pitfall](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-es6-import-pitfall). - -There are two alternatives to this approach: - -1. Preload with dotenvx: `dotenvx run -- node index.js` (_Note: you do not need to `import` dotenv with this approach_) -2. Create a separate file that will execute `config` first as outlined in [this comment on #133](https://github.com/motdotla/dotenv/issues/133#issuecomment-255298822) -
- -
Can I customize/write plugins for dotenv?
- -Yes! `dotenv.config()` returns an object representing the parsed `.env` file. This gives you everything you need to continue setting values on `process.env`. For example: - -```js -const dotenv = require('dotenv') -const variableExpansion = require('dotenv-expand') -const myEnv = dotenv.config() -variableExpansion(myEnv) -``` - -
-
What rules does the parsing engine follow?
- -The parsing engine currently supports the following rules: - -- `BASIC=basic` becomes `{BASIC: 'basic'}` -- empty lines are skipped -- lines beginning with `#` are treated as comments -- `#` marks the beginning of a comment (unless when the value is wrapped in quotes) -- empty values become empty strings (`EMPTY=` becomes `{EMPTY: ''}`) -- inner quotes are maintained (think JSON) (`JSON={"foo": "bar"}` becomes `{JSON:"{\"foo\": \"bar\"}"`) -- whitespace is removed from both ends of unquoted values (see more on [`trim`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)) (`FOO= some value ` becomes `{FOO: 'some value'}`) -- single and double quoted values are escaped (`SINGLE_QUOTE='quoted'` becomes `{SINGLE_QUOTE: "quoted"}`) -- single and double quoted values maintain whitespace from both ends (`FOO=" some value "` becomes `{FOO: ' some value '}`) -- double quoted values expand new lines (`MULTILINE="new\nline"` becomes - -``` -{MULTILINE: 'new -line'} -``` - -- backticks are supported (`` BACKTICK_KEY=`This has 'single' and "double" quotes inside of it.` ``) - -
-
What about syncing and securing .env files?
- -Use [dotenvx](https://github.com/dotenvx/dotenvx) to unlock syncing encrypted .env files over git. - -
-
What if I accidentally commit my `.env` file to code?
- -Remove it, [remove git history](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository) and then install the [git pre-commit hook](https://github.com/dotenvx/dotenvx#pre-commit) to prevent this from ever happening again. - -``` -npm i -g @dotenvx/dotenvx -dotenvx precommit --install -``` - -
-
What happens to environment variables that were already set?
- -By default, we will never modify any environment variables that have already been set. In particular, if there is a variable in your `.env` file which collides with one that already exists in your environment, then that variable will be skipped. - -If instead, you want to override `process.env` use the `override` option. - -```javascript -require('dotenv').config({ override: true }) -``` - -
-
How can I prevent committing my `.env` file to a Docker build?
- -Use the [docker prebuild hook](https://dotenvx.com/docs/features/prebuild). - -```bash -# Dockerfile -... -RUN curl -fsS https://dotenvx.sh/ | sh -... -RUN dotenvx prebuild -CMD ["dotenvx", "run", "--", "node", "index.js"] -``` - -
-
How come my environment variables are not showing up for React?
- -Your React code is run in Webpack, where the `fs` module or even the `process` global itself are not accessible out-of-the-box. `process.env` can only be injected through Webpack configuration. - -If you are using [`react-scripts`](https://www.npmjs.com/package/react-scripts), which is distributed through [`create-react-app`](https://create-react-app.dev/), it has dotenv built in but with a quirk. Preface your environment variables with `REACT_APP_`. See [this stack overflow](https://stackoverflow.com/questions/42182577/is-it-possible-to-use-dotenv-in-a-react-project) for more details. - -If you are using other frameworks (e.g. Next.js, Gatsby...), you need to consult their documentation for how to inject environment variables into the client. - -
-
Why is the `.env` file not loading my environment variables successfully?
- -Most likely your `.env` file is not in the correct place. [See this stack overflow](https://stackoverflow.com/questions/42335016/dotenv-file-is-not-loading-environment-variables). - -Turn on debug mode and try again.. - -```js -require('dotenv').config({ debug: true }) -``` - -You will receive a helpful error outputted to your console. - -
-
Why am I getting the error `Module not found: Error: Can't resolve 'crypto|os|path'`?
- -You are using dotenv on the front-end and have not included a polyfill. Webpack < 5 used to include these for you. Do the following: - -```bash -npm install node-polyfill-webpack-plugin -``` - -Configure your `webpack.config.js` to something like the following. - -```js -require('dotenv').config() - -const path = require('path'); -const webpack = require('webpack') - -const NodePolyfillPlugin = require('node-polyfill-webpack-plugin') - -module.exports = { - mode: 'development', - entry: './src/index.ts', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist'), - }, - plugins: [ - new NodePolyfillPlugin(), - new webpack.DefinePlugin({ - 'process.env': { - HELLO: JSON.stringify(process.env.HELLO) - } - }), - ] -}; -``` - -Alternatively, just use [dotenv-webpack](https://github.com/mrsteele/dotenv-webpack) which does this and more behind the scenes for you. - -
- -  - -## Docs - -Dotenv exposes four functions: - -* `config` -* `parse` -* `populate` - -### Config - -`config` will read your `.env` file, parse the contents, assign it to -[`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env), -and return an Object with a `parsed` key containing the loaded content or an `error` key if it failed. - -```js -const result = dotenv.config() - -if (result.error) { - throw result.error -} - -console.log(result.parsed) -``` - -You can additionally, pass options to `config`. - -#### Options - -##### path - -Default: `path.resolve(process.cwd(), '.env')` - -Specify a custom path if your file containing environment variables is located elsewhere. - -```js -require('dotenv').config({ path: '/custom/path/to/.env' }) -``` - -By default, `config` will look for a file called .env in the current working directory. - -Pass in multiple files as an array, and they will be parsed in order and combined with `process.env` (or `option.processEnv`, if set). The first value set for a variable will win, unless the `options.override` flag is set, in which case the last value set will win. If a value already exists in `process.env` and the `options.override` flag is NOT set, no changes will be made to that value. - -```js -require('dotenv').config({ path: ['.env.local', '.env'] }) -``` - -##### quiet - -Default: `false` - -Suppress runtime logging message. - -```js -// index.js -require('dotenv').config({ quiet: false }) // change to true to suppress -console.log(`Hello ${process.env.HELLO}`) -``` - -```ini -# .env -HELLO=World -``` - -```sh -$ node index.js -[dotenv@17.0.0] injecting env (1) from .env -Hello World -``` - -##### encoding - -Default: `utf8` - -Specify the encoding of your file containing environment variables. - -```js -require('dotenv').config({ encoding: 'latin1' }) -``` - -##### debug - -Default: `false` - -Turn on logging to help debug why certain keys or values are not being set as you expect. - -```js -require('dotenv').config({ debug: process.env.DEBUG }) -``` - -##### override - -Default: `false` - -Override any environment variables that have already been set on your machine with values from your .env file(s). If multiple files have been provided in `option.path` the override will also be used as each file is combined with the next. Without `override` being set, the first value wins. With `override` set the last value wins. - -```js -require('dotenv').config({ override: true }) -``` - -##### processEnv - -Default: `process.env` - -Specify an object to write your environment variables to. Defaults to `process.env` environment variables. - -```js -const myObject = {} -require('dotenv').config({ processEnv: myObject }) - -console.log(myObject) // values from .env -console.log(process.env) // this was not changed or written to -``` - -### Parse - -The engine which parses the contents of your file containing environment -variables is available to use. It accepts a String or Buffer and will return -an Object with the parsed keys and values. - -```js -const dotenv = require('dotenv') -const buf = Buffer.from('BASIC=basic') -const config = dotenv.parse(buf) // will return an object -console.log(typeof config, config) // object { BASIC : 'basic' } -``` - -#### Options - -##### debug - -Default: `false` - -Turn on logging to help debug why certain keys or values are not being set as you expect. - -```js -const dotenv = require('dotenv') -const buf = Buffer.from('hello world') -const opt = { debug: true } -const config = dotenv.parse(buf, opt) -// expect a debug message because the buffer is not in KEY=VAL form -``` - -### Populate - -The engine which populates the contents of your .env file to `process.env` is available for use. It accepts a target, a source, and options. This is useful for power users who want to supply their own objects. - -For example, customizing the source: - -```js -const dotenv = require('dotenv') -const parsed = { HELLO: 'world' } - -dotenv.populate(process.env, parsed) - -console.log(process.env.HELLO) // world -``` - -For example, customizing the source AND target: - -```js -const dotenv = require('dotenv') -const parsed = { HELLO: 'universe' } -const target = { HELLO: 'world' } // empty object - -dotenv.populate(target, parsed, { override: true, debug: true }) - -console.log(target) // { HELLO: 'universe' } -``` - -#### options - -##### Debug - -Default: `false` - -Turn on logging to help debug why certain keys or values are not being populated as you expect. - -##### override - -Default: `false` - -Override any environment variables that have already been set. - -  - -## CHANGELOG - -See [CHANGELOG.md](CHANGELOG.md) - -  - -## Who's using dotenv? - -[These npm modules depend on it.](https://www.npmjs.com/browse/depended/dotenv) - -Projects that expand it often use the [keyword "dotenv" on npm](https://www.npmjs.com/search?q=keywords:dotenv). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/SECURITY.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/SECURITY.md deleted file mode 100644 index 237a8ce74..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/SECURITY.md +++ /dev/null @@ -1 +0,0 @@ -Please report any security vulnerabilities to security@dotenvx.com. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/config.d.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/config.d.ts deleted file mode 100644 index cb0ff5c3b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/config.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/config.js b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/config.js deleted file mode 100644 index b0b5576be..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/config.js +++ /dev/null @@ -1,9 +0,0 @@ -(function () { - require('./lib/main').config( - Object.assign( - {}, - require('./lib/env-options'), - require('./lib/cli-options')(process.argv) - ) - ) -})() diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/package.json deleted file mode 100644 index 209912e80..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/dotenv/package.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "dotenv", - "version": "17.3.1", - "description": "Loads environment variables from .env file", - "main": "lib/main.js", - "types": "lib/main.d.ts", - "exports": { - ".": { - "types": "./lib/main.d.ts", - "require": "./lib/main.js", - "default": "./lib/main.js" - }, - "./config": "./config.js", - "./config.js": "./config.js", - "./lib/env-options": "./lib/env-options.js", - "./lib/env-options.js": "./lib/env-options.js", - "./lib/cli-options": "./lib/cli-options.js", - "./lib/cli-options.js": "./lib/cli-options.js", - "./package.json": "./package.json" - }, - "scripts": { - "dts-check": "tsc --project tests/types/tsconfig.json", - "lint": "standard", - "pretest": "npm run lint && npm run dts-check", - "test": "tap run tests/**/*.js --allow-empty-coverage --disable-coverage --timeout=60000", - "test:coverage": "tap run tests/**/*.js --show-full-coverage --timeout=60000 --coverage-report=text --coverage-report=lcov", - "prerelease": "npm test", - "release": "standard-version" - }, - "repository": { - "type": "git", - "url": "git://github.com/motdotla/dotenv.git" - }, - "homepage": "https://github.com/motdotla/dotenv#readme", - "funding": "https://dotenvx.com", - "keywords": [ - "dotenv", - "env", - ".env", - "environment", - "variables", - "config", - "settings" - ], - "readmeFilename": "README.md", - "license": "BSD-2-Clause", - "devDependencies": { - "@types/node": "^18.11.3", - "decache": "^4.6.2", - "sinon": "^14.0.1", - "standard": "^17.0.0", - "standard-version": "^9.5.0", - "tap": "^19.2.0", - "typescript": "^4.8.4" - }, - "engines": { - "node": ">=12" - }, - "browser": { - "fs": false - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/LICENSE.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/LICENSE.md deleted file mode 100644 index 2027e8dcf..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 Evan Wallace - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/README.md deleted file mode 100644 index 93863d198..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# esbuild - -This is a JavaScript bundler and minifier. See https://github.com/evanw/esbuild and the [JavaScript API documentation](https://esbuild.github.io/api/) for details. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/bin/esbuild b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/bin/esbuild deleted file mode 100755 index 073f4e8e8..000000000 Binary files a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/bin/esbuild and /dev/null differ diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/install.js b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/install.js deleted file mode 100644 index 1019e6243..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/install.js +++ /dev/null @@ -1,289 +0,0 @@ -"use strict"; -var __create = Object.create; -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __getProtoOf = Object.getPrototypeOf; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; -}; -var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( - // If the importer is in node compatibility mode or this is not an ESM - // file that has been converted to a CommonJS file using a Babel- - // compatible transform (i.e. "__esModule" has not been set), then set - // "default" to the CommonJS "module.exports" for node compatibility. - isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, - mod -)); - -// lib/npm/node-platform.ts -var fs = require("fs"); -var os = require("os"); -var path = require("path"); -var ESBUILD_BINARY_PATH = process.env.ESBUILD_BINARY_PATH || ESBUILD_BINARY_PATH; -var isValidBinaryPath = (x) => !!x && x !== "/usr/bin/esbuild"; -var knownWindowsPackages = { - "win32 arm64 LE": "@esbuild/win32-arm64", - "win32 ia32 LE": "@esbuild/win32-ia32", - "win32 x64 LE": "@esbuild/win32-x64" -}; -var knownUnixlikePackages = { - "aix ppc64 BE": "@esbuild/aix-ppc64", - "android arm64 LE": "@esbuild/android-arm64", - "darwin arm64 LE": "@esbuild/darwin-arm64", - "darwin x64 LE": "@esbuild/darwin-x64", - "freebsd arm64 LE": "@esbuild/freebsd-arm64", - "freebsd x64 LE": "@esbuild/freebsd-x64", - "linux arm LE": "@esbuild/linux-arm", - "linux arm64 LE": "@esbuild/linux-arm64", - "linux ia32 LE": "@esbuild/linux-ia32", - "linux mips64el LE": "@esbuild/linux-mips64el", - "linux ppc64 LE": "@esbuild/linux-ppc64", - "linux riscv64 LE": "@esbuild/linux-riscv64", - "linux s390x BE": "@esbuild/linux-s390x", - "linux x64 LE": "@esbuild/linux-x64", - "linux loong64 LE": "@esbuild/linux-loong64", - "netbsd arm64 LE": "@esbuild/netbsd-arm64", - "netbsd x64 LE": "@esbuild/netbsd-x64", - "openbsd arm64 LE": "@esbuild/openbsd-arm64", - "openbsd x64 LE": "@esbuild/openbsd-x64", - "sunos x64 LE": "@esbuild/sunos-x64" -}; -var knownWebAssemblyFallbackPackages = { - "android arm LE": "@esbuild/android-arm", - "android x64 LE": "@esbuild/android-x64", - "openharmony arm64 LE": "@esbuild/openharmony-arm64" -}; -function pkgAndSubpathForCurrentPlatform() { - let pkg; - let subpath; - let isWASM = false; - let platformKey = `${process.platform} ${os.arch()} ${os.endianness()}`; - if (platformKey in knownWindowsPackages) { - pkg = knownWindowsPackages[platformKey]; - subpath = "esbuild.exe"; - } else if (platformKey in knownUnixlikePackages) { - pkg = knownUnixlikePackages[platformKey]; - subpath = "bin/esbuild"; - } else if (platformKey in knownWebAssemblyFallbackPackages) { - pkg = knownWebAssemblyFallbackPackages[platformKey]; - subpath = "bin/esbuild"; - isWASM = true; - } else { - throw new Error(`Unsupported platform: ${platformKey}`); - } - return { pkg, subpath, isWASM }; -} -function downloadedBinPath(pkg, subpath) { - const esbuildLibDir = path.dirname(require.resolve("esbuild")); - return path.join(esbuildLibDir, `downloaded-${pkg.replace("/", "-")}-${path.basename(subpath)}`); -} - -// lib/npm/node-install.ts -var fs2 = require("fs"); -var os2 = require("os"); -var path2 = require("path"); -var zlib = require("zlib"); -var https = require("https"); -var child_process = require("child_process"); -var versionFromPackageJSON = require(path2.join(__dirname, "package.json")).version; -var toPath = path2.join(__dirname, "bin", "esbuild"); -var isToPathJS = true; -function validateBinaryVersion(...command) { - command.push("--version"); - let stdout; - try { - stdout = child_process.execFileSync(command.shift(), command, { - // Without this, this install script strangely crashes with the error - // "EACCES: permission denied, write" but only on Ubuntu Linux when node is - // installed from the Snap Store. This is not a problem when you download - // the official version of node. The problem appears to be that stderr - // (i.e. file descriptor 2) isn't writable? - // - // More info: - // - https://snapcraft.io/ (what the Snap Store is) - // - https://nodejs.org/dist/ (download the official version of node) - // - https://github.com/evanw/esbuild/issues/1711#issuecomment-1027554035 - // - stdio: "pipe" - }).toString().trim(); - } catch (err) { - if (os2.platform() === "darwin" && /_SecTrustEvaluateWithError/.test(err + "")) { - let os3 = "this version of macOS"; - try { - os3 = "macOS " + child_process.execFileSync("sw_vers", ["-productVersion"]).toString().trim(); - } catch { - } - throw new Error(`The "esbuild" package cannot be installed because ${os3} is too outdated. - -The Go compiler (which esbuild relies on) no longer supports ${os3}, -which means the "esbuild" binary executable can't be run. You can either: - - * Update your version of macOS to one that the Go compiler supports - * Use the "esbuild-wasm" package instead of the "esbuild" package - * Build esbuild yourself using an older version of the Go compiler -`); - } - throw err; - } - if (stdout !== versionFromPackageJSON) { - throw new Error(`Expected ${JSON.stringify(versionFromPackageJSON)} but got ${JSON.stringify(stdout)}`); - } -} -function isYarn() { - const { npm_config_user_agent } = process.env; - if (npm_config_user_agent) { - return /\byarn\//.test(npm_config_user_agent); - } - return false; -} -function fetch(url) { - return new Promise((resolve, reject) => { - https.get(url, (res) => { - if ((res.statusCode === 301 || res.statusCode === 302) && res.headers.location) - return fetch(res.headers.location).then(resolve, reject); - if (res.statusCode !== 200) - return reject(new Error(`Server responded with ${res.statusCode}`)); - let chunks = []; - res.on("data", (chunk) => chunks.push(chunk)); - res.on("end", () => resolve(Buffer.concat(chunks))); - }).on("error", reject); - }); -} -function extractFileFromTarGzip(buffer, subpath) { - try { - buffer = zlib.unzipSync(buffer); - } catch (err) { - throw new Error(`Invalid gzip data in archive: ${err && err.message || err}`); - } - let str = (i, n) => String.fromCharCode(...buffer.subarray(i, i + n)).replace(/\0.*$/, ""); - let offset = 0; - subpath = `package/${subpath}`; - while (offset < buffer.length) { - let name = str(offset, 100); - let size = parseInt(str(offset + 124, 12), 8); - offset += 512; - if (!isNaN(size)) { - if (name === subpath) return buffer.subarray(offset, offset + size); - offset += size + 511 & ~511; - } - } - throw new Error(`Could not find ${JSON.stringify(subpath)} in archive`); -} -function installUsingNPM(pkg, subpath, binPath) { - const env = { ...process.env, npm_config_global: void 0 }; - const esbuildLibDir = path2.dirname(require.resolve("esbuild")); - const installDir = path2.join(esbuildLibDir, "npm-install"); - fs2.mkdirSync(installDir); - try { - fs2.writeFileSync(path2.join(installDir, "package.json"), "{}"); - child_process.execSync( - `npm install --loglevel=error --prefer-offline --no-audit --progress=false ${pkg}@${versionFromPackageJSON}`, - { cwd: installDir, stdio: "pipe", env } - ); - const installedBinPath = path2.join(installDir, "node_modules", pkg, subpath); - fs2.renameSync(installedBinPath, binPath); - } finally { - try { - removeRecursive(installDir); - } catch { - } - } -} -function removeRecursive(dir) { - for (const entry of fs2.readdirSync(dir)) { - const entryPath = path2.join(dir, entry); - let stats; - try { - stats = fs2.lstatSync(entryPath); - } catch { - continue; - } - if (stats.isDirectory()) removeRecursive(entryPath); - else fs2.unlinkSync(entryPath); - } - fs2.rmdirSync(dir); -} -function applyManualBinaryPathOverride(overridePath) { - const pathString = JSON.stringify(overridePath); - fs2.writeFileSync(toPath, `#!/usr/bin/env node -require('child_process').execFileSync(${pathString}, process.argv.slice(2), { stdio: 'inherit' }); -`); - const libMain = path2.join(__dirname, "lib", "main.js"); - const code = fs2.readFileSync(libMain, "utf8"); - fs2.writeFileSync(libMain, `var ESBUILD_BINARY_PATH = ${pathString}; -${code}`); -} -function maybeOptimizePackage(binPath) { - const { isWASM } = pkgAndSubpathForCurrentPlatform(); - if (os2.platform() !== "win32" && !isYarn() && !isWASM) { - const tempPath = path2.join(__dirname, "bin-esbuild"); - try { - fs2.linkSync(binPath, tempPath); - fs2.renameSync(tempPath, toPath); - isToPathJS = false; - fs2.unlinkSync(tempPath); - } catch { - } - } -} -async function downloadDirectlyFromNPM(pkg, subpath, binPath) { - const url = `https://registry.npmjs.org/${pkg}/-/${pkg.replace("@esbuild/", "")}-${versionFromPackageJSON}.tgz`; - console.error(`[esbuild] Trying to download ${JSON.stringify(url)}`); - try { - fs2.writeFileSync(binPath, extractFileFromTarGzip(await fetch(url), subpath)); - fs2.chmodSync(binPath, 493); - } catch (e) { - console.error(`[esbuild] Failed to download ${JSON.stringify(url)}: ${e && e.message || e}`); - throw e; - } -} -async function checkAndPreparePackage() { - if (isValidBinaryPath(ESBUILD_BINARY_PATH)) { - if (!fs2.existsSync(ESBUILD_BINARY_PATH)) { - console.warn(`[esbuild] Ignoring bad configuration: ESBUILD_BINARY_PATH=${ESBUILD_BINARY_PATH}`); - } else { - applyManualBinaryPathOverride(ESBUILD_BINARY_PATH); - return; - } - } - const { pkg, subpath } = pkgAndSubpathForCurrentPlatform(); - let binPath; - try { - binPath = require.resolve(`${pkg}/${subpath}`); - } catch (e) { - console.error(`[esbuild] Failed to find package "${pkg}" on the file system - -This can happen if you use the "--no-optional" flag. The "optionalDependencies" -package.json feature is used by esbuild to install the correct binary executable -for your current platform. This install script will now attempt to work around -this. If that fails, you need to remove the "--no-optional" flag to use esbuild. -`); - binPath = downloadedBinPath(pkg, subpath); - try { - console.error(`[esbuild] Trying to install package "${pkg}" using npm`); - installUsingNPM(pkg, subpath, binPath); - } catch (e2) { - console.error(`[esbuild] Failed to install package "${pkg}" using npm: ${e2 && e2.message || e2}`); - try { - await downloadDirectlyFromNPM(pkg, subpath, binPath); - } catch (e3) { - throw new Error(`Failed to install package "${pkg}"`); - } - } - } - maybeOptimizePackage(binPath); -} -checkAndPreparePackage().then(() => { - if (isToPathJS) { - validateBinaryVersion(process.execPath, toPath); - } else { - validateBinaryVersion(toPath); - } -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/package.json deleted file mode 100644 index 13a9813ee..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/esbuild/package.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "esbuild", - "version": "0.27.4", - "description": "An extremely fast JavaScript and CSS bundler and minifier.", - "repository": { - "type": "git", - "url": "git+https://github.com/evanw/esbuild.git" - }, - "scripts": { - "postinstall": "node install.js" - }, - "main": "lib/main.js", - "types": "lib/main.d.ts", - "engines": { - "node": ">=18" - }, - "bin": { - "esbuild": "bin/esbuild" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.4", - "@esbuild/android-arm": "0.27.4", - "@esbuild/android-arm64": "0.27.4", - "@esbuild/android-x64": "0.27.4", - "@esbuild/darwin-arm64": "0.27.4", - "@esbuild/darwin-x64": "0.27.4", - "@esbuild/freebsd-arm64": "0.27.4", - "@esbuild/freebsd-x64": "0.27.4", - "@esbuild/linux-arm": "0.27.4", - "@esbuild/linux-arm64": "0.27.4", - "@esbuild/linux-ia32": "0.27.4", - "@esbuild/linux-loong64": "0.27.4", - "@esbuild/linux-mips64el": "0.27.4", - "@esbuild/linux-ppc64": "0.27.4", - "@esbuild/linux-riscv64": "0.27.4", - "@esbuild/linux-s390x": "0.27.4", - "@esbuild/linux-x64": "0.27.4", - "@esbuild/netbsd-arm64": "0.27.4", - "@esbuild/netbsd-x64": "0.27.4", - "@esbuild/openbsd-arm64": "0.27.4", - "@esbuild/openbsd-x64": "0.27.4", - "@esbuild/openharmony-arm64": "0.27.4", - "@esbuild/sunos-x64": "0.27.4", - "@esbuild/win32-arm64": "0.27.4", - "@esbuild/win32-ia32": "0.27.4", - "@esbuild/win32-x64": "0.27.4" - }, - "license": "MIT" -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/LICENSE deleted file mode 100644 index 82f30788b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 Espen Hovlandsdal - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/README.md deleted file mode 100644 index fdd64f77f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/README.md +++ /dev/null @@ -1,126 +0,0 @@ -# eventsource-parser - -[![npm version](https://img.shields.io/npm/v/eventsource-parser.svg?style=flat-square)](https://www.npmjs.com/package/eventsource-parser)[![npm bundle size](https://img.shields.io/bundlephobia/minzip/eventsource-parser?style=flat-square)](https://bundlephobia.com/result?p=eventsource-parser)[![npm weekly downloads](https://img.shields.io/npm/dw/eventsource-parser.svg?style=flat-square)](https://www.npmjs.com/package/eventsource-parser) - -A streaming parser for [server-sent events/eventsource](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events), without any assumptions about how the actual stream of data is retrieved. It is intended to be a building block for [clients](https://github.com/rexxars/eventsource-client) and polyfills in javascript environments such as browsers, node.js and deno. - -If you are looking for a modern client implementation, see [eventsource-client](https://github.com/rexxars/eventsource-client). - -You create an instance of the parser, and _feed_ it chunks of data - partial or complete, and the parse emits parsed messages once it receives a complete message. A [TransformStream variant](#stream-usage) is also available for environments that support it (modern browsers, Node 18 and higher). - -Other modules in the EventSource family: - -- [eventsource-client](https://github.com/rexxars/eventsource-client): modern, feature rich eventsource client for browsers, node.js, bun, deno and other modern JavaScript environments. -- [eventsource-encoder](https://github.com/rexxars/eventsource-encoder): encodes messages in the EventSource/Server-Sent Events format. -- [eventsource](https://github.com/eventsource/eventsource): Node.js polyfill for the WhatWG EventSource API. - -> [!NOTE] -> Migrating from eventsource-parser 1.x/2.x? See the [migration guide](./MIGRATE-v3.md). - -## Installation - -```bash -npm install --save eventsource-parser -``` - -## Usage - -```ts -import {createParser, type EventSourceMessage} from 'eventsource-parser' - -function onEvent(event: EventSourceMessage) { - console.log('Received event!') - console.log('id: %s', event.id || '') - console.log('event: %s', event.event || '') - console.log('data: %s', event.data) -} - -const parser = createParser({onEvent}) -const sseStream = getSomeReadableStream() - -for await (const chunk of sseStream) { - parser.feed(chunk) -} - -// If you want to re-use the parser for a new stream of events, make sure to reset it! -parser.reset() -console.log('Done!') -``` - -### Retry intervals - -If the server sends a `retry` field in the event stream, the parser will call any `onRetry` callback specified to the `createParser` function: - -```ts -const parser = createParser({ - onRetry(retryInterval) { - console.log('Server requested retry interval of %dms', retryInterval) - }, - onEvent(event) { - // … - }, -}) -``` - -### Parse errors - -If the parser encounters an error while parsing, it will call any `onError` callback provided to the `createParser` function: - -```ts -import {type ParseError} from 'eventsource-parser' - -const parser = createParser({ - onError(error: ParseError) { - console.error('Error parsing event:', error) - if (error.type === 'invalid-field') { - console.error('Field name:', error.field) - console.error('Field value:', error.value) - console.error('Line:', error.line) - } else if (error.type === 'invalid-retry') { - console.error('Invalid retry interval:', error.value) - } - }, - onEvent(event) { - // … - }, -}) -``` - -Note that `invalid-field` errors will usually be called for any invalid data - not only data shaped as `field: value`. This is because the EventSource specification says to treat anything prior to a `:` as the field name. Use the `error.line` property to get the full line that caused the error. - -> [!NOTE] -> When encountering the end of a stream, calling `.reset({consume: true})` on the parser to flush any remaining data and reset the parser state. This will trigger the `onError` callback if the pending data is not a valid event. - -### Comments - -The parser will ignore comments (lines starting with `:`) by default. If you want to handle comments, you can provide an `onComment` callback to the `createParser` function: - -```ts -const parser = createParser({ - onComment(comment) { - console.log('Received comment:', comment) - }, - onEvent(event) { - // … - }, -}) -``` - -> [!NOTE] -> Leading whitespace is not stripped from comments, eg `: comment` will give ` comment` as the comment value, not `comment` (note the leading space). - -## Stream usage - -```ts -import {EventSourceParserStream} from 'eventsource-parser/stream' - -const eventStream = response.body - .pipeThrough(new TextDecoderStream()) - .pipeThrough(new EventSourceParserStream()) -``` - -Note that the TransformStream is exposed under a separate export (`eventsource-parser/stream`), in order to maximize compatibility with environments that do not have the `TransformStream` constructor available. - -## License - -MIT © [Espen Hovlandsdal](https://espen.codes/) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/package.json deleted file mode 100644 index e8a363510..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/package.json +++ /dev/null @@ -1,115 +0,0 @@ -{ - "name": "eventsource-parser", - "version": "3.0.6", - "description": "Streaming, source-agnostic EventSource/Server-Sent Events parser", - "sideEffects": false, - "type": "module", - "types": "./dist/index.d.ts", - "module": "./dist/index.js", - "main": "./dist/index.cjs", - "exports": { - ".": { - "source": "./src/index.ts", - "import": "./dist/index.js", - "require": "./dist/index.cjs", - "default": "./dist/index.js" - }, - "./stream": { - "source": "./src/stream.ts", - "import": "./dist/stream.js", - "require": "./dist/stream.cjs", - "default": "./dist/stream.js" - }, - "./package.json": "./package.json" - }, - "typesVersions": { - "*": { - "stream": [ - "./dist/stream.d.ts" - ] - } - }, - "engines": { - "node": ">=18.0.0" - }, - "browserslist": [ - "node >= 20", - "chrome >= 71", - "safari >= 14.1", - "firefox >= 105", - "edge >= 79" - ], - "files": [ - "dist", - "!dist/stats.html", - "src", - "stream.js" - ], - "scripts": { - "build": "pkg-utils build && pkg-utils --strict", - "clean": "rimraf dist coverage", - "lint": "eslint . && tsc --noEmit", - "posttest": "npm run lint", - "prebuild": "npm run clean", - "prepublishOnly": "npm run build", - "test": "npm run test:node", - "test:bun": "bun test", - "test:deno": "deno run --allow-write --allow-net --allow-run --allow-sys --allow-ffi --allow-env --allow-read npm:vitest", - "test:node": "vitest --reporter=verbose" - }, - "author": "Espen Hovlandsdal ", - "keywords": [ - "sse", - "eventsource", - "server-sent-events" - ], - "devDependencies": { - "@sanity/pkg-utils": "^8.0.0", - "@sanity/semantic-release-preset": "^5.0.0", - "@types/node": "^20.19.0", - "@typescript-eslint/eslint-plugin": "^7.0.0", - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.51.0", - "eslint-config-prettier": "^9.1.0", - "eslint-config-sanity": "^7.1.2", - "eventsource-encoder": "^1.0.1", - "prettier": "^3.5.3", - "rimraf": "^6.0.1", - "rollup-plugin-visualizer": "^6.0.3", - "semantic-release": "^24.2.3", - "typescript": "^5.8.3", - "vitest": "^3.1.3" - }, - "homepage": "https://github.com/rexxars/eventsource-parser#readme", - "bugs": { - "url": "https://github.com/rexxars/eventsource-parser/issues" - }, - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/rexxars/eventsource-parser.git" - }, - "license": "MIT", - "prettier": { - "bracketSpacing": false, - "printWidth": 100, - "semi": false, - "singleQuote": true - }, - "eslintConfig": { - "parserOptions": { - "ecmaFeatures": { - "modules": true - }, - "ecmaVersion": 9, - "sourceType": "module" - }, - "extends": [ - "sanity", - "sanity/typescript", - "prettier" - ], - "ignorePatterns": [ - "lib/**/" - ] - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/errors.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/errors.ts deleted file mode 100644 index 04cd292db..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/errors.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The type of error that occurred. - * @public - */ -export type ErrorType = 'invalid-retry' | 'unknown-field' - -/** - * Error thrown when encountering an issue during parsing. - * - * @public - */ -export class ParseError extends Error { - /** - * The type of error that occurred. - */ - type: ErrorType - - /** - * In the case of an unknown field encountered in the stream, this will be the field name. - */ - field?: string | undefined - - /** - * In the case of an unknown field encountered in the stream, this will be the value of the field. - */ - value?: string | undefined - - /** - * The line that caused the error, if available. - */ - line?: string | undefined - - constructor( - message: string, - options: {type: ErrorType; field?: string; value?: string; line?: string}, - ) { - super(message) - this.name = 'ParseError' - this.type = options.type - this.field = options.field - this.value = options.value - this.line = options.line - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/index.ts deleted file mode 100644 index ac3328ef2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export {type ErrorType, ParseError} from './errors.ts' -export {createParser} from './parse.ts' -export type {EventSourceMessage, EventSourceParser, ParserCallbacks} from './types.ts' diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/parse.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/parse.ts deleted file mode 100644 index 872309407..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/parse.ts +++ /dev/null @@ -1,232 +0,0 @@ -/** - * EventSource/Server-Sent Events parser - * @see https://html.spec.whatwg.org/multipage/server-sent-events.html - */ -import {ParseError} from './errors.ts' -import type {EventSourceParser, ParserCallbacks} from './types.ts' - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function noop(_arg: unknown) { - // intentional noop -} - -/** - * Creates a new EventSource parser. - * - * @param callbacks - Callbacks to invoke on different parsing events: - * - `onEvent` when a new event is parsed - * - `onError` when an error occurs - * - `onRetry` when a new reconnection interval has been sent from the server - * - `onComment` when a comment is encountered in the stream - * - * @returns A new EventSource parser, with `parse` and `reset` methods. - * @public - */ -export function createParser(callbacks: ParserCallbacks): EventSourceParser { - if (typeof callbacks === 'function') { - throw new TypeError( - '`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?', - ) - } - - const {onEvent = noop, onError = noop, onRetry = noop, onComment} = callbacks - - let incompleteLine = '' - - let isFirstChunk = true - let id: string | undefined - let data = '' - let eventType = '' - - function feed(newChunk: string) { - // Strip any UTF8 byte order mark (BOM) at the start of the stream - const chunk = isFirstChunk ? newChunk.replace(/^\xEF\xBB\xBF/, '') : newChunk - - // If there was a previous incomplete line, append it to the new chunk, - // so we may process it together as a new (hopefully complete) chunk. - const [complete, incomplete] = splitLines(`${incompleteLine}${chunk}`) - - for (const line of complete) { - parseLine(line) - } - - incompleteLine = incomplete - isFirstChunk = false - } - - function parseLine(line: string) { - // If the line is empty (a blank line), dispatch the event - if (line === '') { - dispatchEvent() - return - } - - // If the line starts with a U+003A COLON character (:), ignore the line. - if (line.startsWith(':')) { - if (onComment) { - onComment(line.slice(line.startsWith(': ') ? 2 : 1)) - } - return - } - - // If the line contains a U+003A COLON character (:) - const fieldSeparatorIndex = line.indexOf(':') - if (fieldSeparatorIndex !== -1) { - // Collect the characters on the line before the first U+003A COLON character (:), - // and let `field` be that string. - const field = line.slice(0, fieldSeparatorIndex) - - // Collect the characters on the line after the first U+003A COLON character (:), - // and let `value` be that string. If value starts with a U+0020 SPACE character, - // remove it from value. - const offset = line[fieldSeparatorIndex + 1] === ' ' ? 2 : 1 - const value = line.slice(fieldSeparatorIndex + offset) - - processField(field, value, line) - return - } - - // Otherwise, the string is not empty but does not contain a U+003A COLON character (:) - // Process the field using the whole line as the field name, and an empty string as the field value. - // 👆 This is according to spec. That means that a line that has the value `data` will result in - // a newline being added to the current `data` buffer, for instance. - processField(line, '', line) - } - - function processField(field: string, value: string, line: string) { - // Field names must be compared literally, with no case folding performed. - switch (field) { - case 'event': - // Set the `event type` buffer to field value - eventType = value - break - case 'data': - // Append the field value to the `data` buffer, then append a single U+000A LINE FEED(LF) - // character to the `data` buffer. - data = `${data}${value}\n` - break - case 'id': - // If the field value does not contain U+0000 NULL, then set the `ID` buffer to - // the field value. Otherwise, ignore the field. - id = value.includes('\0') ? undefined : value - break - case 'retry': - // If the field value consists of only ASCII digits, then interpret the field value as an - // integer in base ten, and set the event stream's reconnection time to that integer. - // Otherwise, ignore the field. - if (/^\d+$/.test(value)) { - onRetry(parseInt(value, 10)) - } else { - onError( - new ParseError(`Invalid \`retry\` value: "${value}"`, { - type: 'invalid-retry', - value, - line, - }), - ) - } - break - default: - // Otherwise, the field is ignored. - onError( - new ParseError( - `Unknown field "${field.length > 20 ? `${field.slice(0, 20)}…` : field}"`, - {type: 'unknown-field', field, value, line}, - ), - ) - break - } - } - - function dispatchEvent() { - const shouldDispatch = data.length > 0 - if (shouldDispatch) { - onEvent({ - id, - event: eventType || undefined, - // If the data buffer's last character is a U+000A LINE FEED (LF) character, - // then remove the last character from the data buffer. - data: data.endsWith('\n') ? data.slice(0, -1) : data, - }) - } - - // Reset for the next event - id = undefined - data = '' - eventType = '' - } - - function reset(options: {consume?: boolean} = {}) { - if (incompleteLine && options.consume) { - parseLine(incompleteLine) - } - - isFirstChunk = true - id = undefined - data = '' - eventType = '' - incompleteLine = '' - } - - return {feed, reset} -} - -/** - * For the given `chunk`, split it into lines according to spec, and return any remaining incomplete line. - * - * @param chunk - The chunk to split into lines - * @returns A tuple containing an array of complete lines, and any remaining incomplete line - * @internal - */ -function splitLines(chunk: string): [complete: Array, incomplete: string] { - /** - * According to the spec, a line is terminated by either: - * - U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF) character pair - * - a single U+000A LINE FEED(LF) character not preceded by a U+000D CARRIAGE RETURN(CR) character - * - a single U+000D CARRIAGE RETURN(CR) character not followed by a U+000A LINE FEED(LF) character - */ - const lines: Array = [] - let incompleteLine = '' - let searchIndex = 0 - - while (searchIndex < chunk.length) { - // Find next line terminator - const crIndex = chunk.indexOf('\r', searchIndex) - const lfIndex = chunk.indexOf('\n', searchIndex) - - // Determine line end - let lineEnd = -1 - if (crIndex !== -1 && lfIndex !== -1) { - // CRLF case - lineEnd = Math.min(crIndex, lfIndex) - } else if (crIndex !== -1) { - // CR at the end of a chunk might be part of a CRLF sequence that spans chunks, - // so we shouldn't treat it as a line terminator (yet) - if (crIndex === chunk.length - 1) { - lineEnd = -1 - } else { - lineEnd = crIndex - } - } else if (lfIndex !== -1) { - lineEnd = lfIndex - } - - // Extract line if terminator found - if (lineEnd === -1) { - // No terminator found, rest is incomplete - incompleteLine = chunk.slice(searchIndex) - break - } else { - const line = chunk.slice(searchIndex, lineEnd) - lines.push(line) - - // Move past line terminator - searchIndex = lineEnd + 1 - if (chunk[searchIndex - 1] === '\r' && chunk[searchIndex] === '\n') { - searchIndex++ - } - } - } - - return [lines, incompleteLine] -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/stream.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/stream.ts deleted file mode 100644 index 29887d5f8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/stream.ts +++ /dev/null @@ -1,88 +0,0 @@ -import {createParser} from './parse.ts' -import type {EventSourceMessage, EventSourceParser} from './types.ts' - -/** - * Options for the EventSourceParserStream. - * - * @public - */ -export interface StreamOptions { - /** - * Behavior when a parsing error occurs. - * - * - A custom function can be provided to handle the error. - * - `'terminate'` will error the stream and stop parsing. - * - Any other value will ignore the error and continue parsing. - * - * @defaultValue `undefined` - */ - onError?: ('terminate' | ((error: Error) => void)) | undefined - - /** - * Callback for when a reconnection interval is sent from the server. - * - * @param retry - The number of milliseconds to wait before reconnecting. - */ - onRetry?: ((retry: number) => void) | undefined - - /** - * Callback for when a comment is encountered in the stream. - * - * @param comment - The comment encountered in the stream. - */ - onComment?: ((comment: string) => void) | undefined -} - -/** - * A TransformStream that ingests a stream of strings and produces a stream of `EventSourceMessage`. - * - * @example Basic usage - * ``` - * const eventStream = - * response.body - * .pipeThrough(new TextDecoderStream()) - * .pipeThrough(new EventSourceParserStream()) - * ``` - * - * @example Terminate stream on parsing errors - * ``` - * const eventStream = - * response.body - * .pipeThrough(new TextDecoderStream()) - * .pipeThrough(new EventSourceParserStream({terminateOnError: true})) - * ``` - * - * @public - */ -export class EventSourceParserStream extends TransformStream { - constructor({onError, onRetry, onComment}: StreamOptions = {}) { - let parser!: EventSourceParser - - super({ - start(controller) { - parser = createParser({ - onEvent: (event) => { - controller.enqueue(event) - }, - onError(error) { - if (onError === 'terminate') { - controller.error(error) - } else if (typeof onError === 'function') { - onError(error) - } - - // Ignore by default - }, - onRetry, - onComment, - }) - }, - transform(chunk) { - parser.feed(chunk) - }, - }) - } -} - -export {type ErrorType, ParseError} from './errors.ts' -export type {EventSourceMessage} from './types.ts' diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/types.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/types.ts deleted file mode 100644 index 2c87def86..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/src/types.ts +++ /dev/null @@ -1,97 +0,0 @@ -import type {ParseError} from './errors.ts' - -/** - * EventSource parser instance. - * - * Needs to be reset between reconnections/when switching data source, using the `reset()` method. - * - * @public - */ -export interface EventSourceParser { - /** - * Feeds the parser another chunk. The method _does not_ return a parsed message. - * Instead, callbacks passed when creating the parser will be triggered once we see enough data - * for a valid/invalid parsing step (see {@link ParserCallbacks}). - * - * @param chunk - The chunk to parse. Can be a partial, eg in the case of streaming messages. - * @public - */ - feed(chunk: string): void - - /** - * Resets the parser state. This is required when you have a new stream of messages - - * for instance in the case of a client being disconnected and reconnecting. - * - * Previously received, incomplete data will NOT be parsed unless you pass `consume: true`, - * which tells the parser to attempt to consume any incomplete data as if it ended with a newline - * character. This is useful for cases when a server sends a non-EventSource message that you - * want to be able to react to in an `onError` callback. - * - * @public - */ - reset(options?: {consume?: boolean}): void -} - -/** - * A parsed EventSource message event - * - * @public - */ -export interface EventSourceMessage { - /** - * The event type sent from the server. Note that this differs from the browser `EventSource` - * implementation in that browsers will default this to `message`, whereas this parser will - * leave this as `undefined` if not explicitly declared. - */ - event?: string | undefined - - /** - * ID of the message, if any was provided by the server. Can be used by clients to keep the - * last received message ID in sync when reconnecting. - */ - id?: string | undefined - - /** - * The data received for this message - */ - data: string -} - -/** - * Callbacks that can be passed to the parser to handle different types of parsed messages - * and errors. - * - * @public - */ -export interface ParserCallbacks { - /** - * Callback for when a new event/message is parsed from the stream. - * This is the main callback that clients will use to handle incoming messages. - * - * @param event - The parsed event/message - */ - onEvent?: ((event: EventSourceMessage) => void) | undefined - - /** - * Callback for when the server sends a new reconnection interval through the `retry` field. - * - * @param retry - The number of milliseconds to wait before reconnecting. - */ - onRetry?: ((retry: number) => void) | undefined - - /** - * Callback for when a comment is encountered in the stream. - * - * @param comment - The comment encountered in the stream. - */ - onComment?: ((comment: string) => void) | undefined - - /** - * Callback for when an error occurs during parsing. This is a catch-all for any errors - * that occur during parsing, and can be used to handle them in a custom way. Most clients - * tend to silently ignore any errors and instead retry, but it can be helpful to log/debug. - * - * @param error - The error that occurred during parsing - */ - onError?: ((error: ParseError) => void) | undefined -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/stream.js b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/stream.js deleted file mode 100644 index 98d74bcf3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/eventsource-parser/stream.js +++ /dev/null @@ -1,2 +0,0 @@ -/* included for compatibility with react-native without package exports support */ -module.exports = require('./dist/stream.cjs') diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/LICENSE deleted file mode 100644 index 5d70441c3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -MIT License ------------ - -Copyright (C) 2010-2020 by Philipp Dunkel, Ben Noordhuis, Elan Shankar, Paul Miller - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/README.md deleted file mode 100644 index 50373a035..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# fsevents - -Native access to MacOS FSEvents in [Node.js](https://nodejs.org/) - -The FSEvents API in MacOS allows applications to register for notifications of -changes to a given directory tree. It is a very fast and lightweight alternative -to kqueue. - -This is a low-level library. For a cross-platform file watching module that -uses fsevents, check out [Chokidar](https://github.com/paulmillr/chokidar). - -## Usage - -```sh -npm install fsevents -``` - -Supports only **Node.js v8.16 and higher**. - -```js -const fsevents = require('fsevents'); - -// To start observation -const stop = fsevents.watch(__dirname, (path, flags, id) => { - const info = fsevents.getInfo(path, flags); -}); - -// To end observation -stop(); -``` - -> **Important note:** The API behaviour is slightly different from typical JS APIs. The `stop` function **must** be -> retrieved and stored somewhere, even if you don't plan to stop the watcher. If you forget it, the garbage collector -> will eventually kick in, the watcher will be unregistered, and your callbacks won't be called anymore. - -The callback passed as the second parameter to `.watch` get's called whenever the operating system detects a -a change in the file system. It takes three arguments: - -###### `fsevents.watch(dirname: string, (path: string, flags: number, id: string) => void): () => Promise` - - * `path: string` - the item in the filesystem that have been changed - * `flags: number` - a numeric value describing what the change was - * `id: string` - an unique-id identifying this specific event - - Returns closer callback which when called returns a Promise resolving when the watcher process has been shut down. - -###### `fsevents.getInfo(path: string, flags: number, id: string): FsEventInfo` - -The `getInfo` function takes the `path`, `flags` and `id` arguments and converts those parameters into a structure -that is easier to digest to determine what the change was. - -The `FsEventsInfo` has the following shape: - -```js -/** - * @typedef {'created'|'modified'|'deleted'|'moved'|'root-changed'|'cloned'|'unknown'} FsEventsEvent - * @typedef {'file'|'directory'|'symlink'} FsEventsType - */ -{ - "event": "created", // {FsEventsEvent} - "path": "file.txt", - "type": "file", // {FsEventsType} - "changes": { - "inode": true, // Had iNode Meta-Information changed - "finder": false, // Had Finder Meta-Data changed - "access": false, // Had access permissions changed - "xattrs": false // Had xAttributes changed - }, - "flags": 0x100000000 -} -``` - -## Changelog - -- v2.3 supports Apple Silicon ARM CPUs -- v2 supports node 8.16+ and reduces package size massively -- v1.2.8 supports node 6+ -- v1.2.7 supports node 4+ - -## Troubleshooting - -- I'm getting `EBADPLATFORM` `Unsupported platform for fsevents` error. -- It's fine, nothing is broken. fsevents is macos-only. Other platforms are skipped. If you want to hide this warning, report a bug to NPM bugtracker asking them to hide ebadplatform warnings by default. - -## License - -The MIT License Copyright (C) 2010-2020 by Philipp Dunkel, Ben Noordhuis, Elan Shankar, Paul Miller — see LICENSE file. - -Visit our [GitHub page](https://github.com/fsevents/fsevents) and [NPM Page](https://npmjs.org/package/fsevents) diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/fsevents.d.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/fsevents.d.ts deleted file mode 100644 index 2723c048a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/fsevents.d.ts +++ /dev/null @@ -1,46 +0,0 @@ -declare type Event = "created" | "cloned" | "modified" | "deleted" | "moved" | "root-changed" | "unknown"; -declare type Type = "file" | "directory" | "symlink"; -declare type FileChanges = { - inode: boolean; - finder: boolean; - access: boolean; - xattrs: boolean; -}; -declare type Info = { - event: Event; - path: string; - type: Type; - changes: FileChanges; - flags: number; -}; -declare type WatchHandler = (path: string, flags: number, id: string) => void; -export declare function watch(path: string, handler: WatchHandler): () => Promise; -export declare function watch(path: string, since: number, handler: WatchHandler): () => Promise; -export declare function getInfo(path: string, flags: number): Info; -export declare const constants: { - None: 0x00000000; - MustScanSubDirs: 0x00000001; - UserDropped: 0x00000002; - KernelDropped: 0x00000004; - EventIdsWrapped: 0x00000008; - HistoryDone: 0x00000010; - RootChanged: 0x00000020; - Mount: 0x00000040; - Unmount: 0x00000080; - ItemCreated: 0x00000100; - ItemRemoved: 0x00000200; - ItemInodeMetaMod: 0x00000400; - ItemRenamed: 0x00000800; - ItemModified: 0x00001000; - ItemFinderInfoMod: 0x00002000; - ItemChangeOwner: 0x00004000; - ItemXattrMod: 0x00008000; - ItemIsFile: 0x00010000; - ItemIsDir: 0x00020000; - ItemIsSymlink: 0x00040000; - ItemIsHardlink: 0x00100000; - ItemIsLastHardlink: 0x00200000; - OwnEvent: 0x00080000; - ItemCloned: 0x00400000; -}; -export {}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/fsevents.js b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/fsevents.js deleted file mode 100644 index 198da98e7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/fsevents.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - ** © 2020 by Philipp Dunkel, Ben Noordhuis, Elan Shankar, Paul Miller - ** Licensed under MIT License. - */ - -/* jshint node:true */ -"use strict"; - -if (process.platform !== "darwin") { - throw new Error(`Module 'fsevents' is not compatible with platform '${process.platform}'`); -} - -const Native = require("./fsevents.node"); -const events = Native.constants; - -function watch(path, since, handler) { - if (typeof path !== "string") { - throw new TypeError(`fsevents argument 1 must be a string and not a ${typeof path}`); - } - if ("function" === typeof since && "undefined" === typeof handler) { - handler = since; - since = Native.flags.SinceNow; - } - if (typeof since !== "number") { - throw new TypeError(`fsevents argument 2 must be a number and not a ${typeof since}`); - } - if (typeof handler !== "function") { - throw new TypeError(`fsevents argument 3 must be a function and not a ${typeof handler}`); - } - - let instance = Native.start(Native.global, path, since, handler); - if (!instance) throw new Error(`could not watch: ${path}`); - return () => { - const result = instance ? Promise.resolve(instance).then(Native.stop) : Promise.resolve(undefined); - instance = undefined; - return result; - }; -} - -function getInfo(path, flags) { - return { - path, - flags, - event: getEventType(flags), - type: getFileType(flags), - changes: getFileChanges(flags), - }; -} - -function getFileType(flags) { - if (events.ItemIsFile & flags) return "file"; - if (events.ItemIsDir & flags) return "directory"; - if (events.MustScanSubDirs & flags) return "directory"; - if (events.ItemIsSymlink & flags) return "symlink"; -} -function anyIsTrue(obj) { - for (let key in obj) { - if (obj[key]) return true; - } - return false; -} -function getEventType(flags) { - if (events.ItemRemoved & flags) return "deleted"; - if (events.ItemRenamed & flags) return "moved"; - if (events.ItemCreated & flags) return "created"; - if (events.ItemModified & flags) return "modified"; - if (events.RootChanged & flags) return "root-changed"; - if (events.ItemCloned & flags) return "cloned"; - if (anyIsTrue(flags)) return "modified"; - return "unknown"; -} -function getFileChanges(flags) { - return { - inode: !!(events.ItemInodeMetaMod & flags), - finder: !!(events.ItemFinderInfoMod & flags), - access: !!(events.ItemChangeOwner & flags), - xattrs: !!(events.ItemXattrMod & flags), - }; -} - -exports.watch = watch; -exports.getInfo = getInfo; -exports.constants = events; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/fsevents.node b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/fsevents.node deleted file mode 100755 index 1cc3345ea..000000000 Binary files a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/fsevents.node and /dev/null differ diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/package.json deleted file mode 100644 index 5d0ee15e6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/fsevents/package.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "fsevents", - "version": "2.3.3", - "description": "Native Access to MacOS FSEvents", - "main": "fsevents.js", - "types": "fsevents.d.ts", - "os": [ - "darwin" - ], - "files": [ - "fsevents.d.ts", - "fsevents.js", - "fsevents.node" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - }, - "scripts": { - "clean": "node-gyp clean && rm -f fsevents.node", - "build": "node-gyp clean && rm -f fsevents.node && node-gyp rebuild && node-gyp clean", - "test": "/bin/bash ./test.sh 2>/dev/null", - "prepublishOnly": "npm run build" - }, - "repository": { - "type": "git", - "url": "https://github.com/fsevents/fsevents.git" - }, - "keywords": [ - "fsevents", - "mac" - ], - "contributors": [ - { - "name": "Philipp Dunkel", - "email": "pip@pipobscure.com" - }, - { - "name": "Ben Noordhuis", - "email": "info@bnoordhuis.nl" - }, - { - "name": "Elan Shankar", - "email": "elan.shanker@gmail.com" - }, - { - "name": "Miroslav Bajtoš", - "email": "mbajtoss@gmail.com" - }, - { - "name": "Paul Miller", - "url": "https://paulmillr.com" - } - ], - "license": "MIT", - "bugs": { - "url": "https://github.com/fsevents/fsevents/issues" - }, - "homepage": "https://github.com/fsevents/fsevents", - "devDependencies": { - "node-gyp": "^9.4.0" - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/get-tsconfig/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/get-tsconfig/LICENSE deleted file mode 100644 index 51e4fd864..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/get-tsconfig/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) Hiroki Osame - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/get-tsconfig/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/get-tsconfig/README.md deleted file mode 100644 index b5861e372..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/get-tsconfig/README.md +++ /dev/null @@ -1,235 +0,0 @@ -

- -

-

- get-tsconfig -
- -

- -Find and parse `tsconfig.json` files. - -### Features -- Zero dependency (not even TypeScript) -- Tested against TypeScript for correctness -- Supports comments & dangling commas in `tsconfig.json` -- Resolves [`extends`](https://www.typescriptlang.org/tsconfig/#extends) -- Fully typed `tsconfig.json` -- Validates and throws parsing errors -- Tiny! `7 kB` Minified + Gzipped - -
- -

- - -

-

Already a sponsor? Join the discussion in the Development repo!

- -## Install - -```bash -npm install get-tsconfig -``` - -## Why? -For TypeScript related tooling to correctly parse `tsconfig.json` file without depending on TypeScript. - -## API - -### getTsconfig(searchPath?, configName?, cache?) - -Searches for a tsconfig file (defaults to `tsconfig.json`) in the `searchPath` and parses it. (If you already know the tsconfig path, use [`parseTsconfig`](#parsetsconfigtsconfigpath-cache) instead). Returns `null` if a config file cannot be found, or an object containing the path and parsed TSConfig object if found. - -Returns: - -```ts -type TsconfigResult = { - - /** - * The path to the tsconfig.json file - */ - path: string - - /** - * The resolved tsconfig.json file - */ - config: TsConfigJsonResolved -} -``` - -#### searchPath -Type: `string` - -Default: `process.cwd()` - -Accepts a path to a file or directory to search up for a `tsconfig.json` file. - -#### configName -Type: `string` - -Default: `tsconfig.json` - -The file name of the TypeScript config file. - -#### cache -Type: `Map` - -Default: `new Map()` - -Optional cache for fs operations. - -#### Example - -```ts -import { getTsconfig } from 'get-tsconfig' - -// Searches for tsconfig.json starting in the current directory -console.log(getTsconfig()) - -// Find tsconfig.json from a TypeScript file path -console.log(getTsconfig('./path/to/index.ts')) - -// Find tsconfig.json from a directory file path -console.log(getTsconfig('./path/to/directory')) - -// Explicitly pass in tsconfig.json path -console.log(getTsconfig('./path/to/tsconfig.json')) - -// Search for jsconfig.json - https://code.visualstudio.com/docs/languages/jsconfig -console.log(getTsconfig('.', 'jsconfig.json')) -``` - ---- - -### parseTsconfig(tsconfigPath, cache?) - -Parse the tsconfig file provided. Used internally by `getTsconfig`. Returns the parsed tsconfig as `TsConfigJsonResolved`. - -#### tsconfigPath -Type: `string` - -Required path to the tsconfig file. - -#### cache -Type: `Map` - -Default: `new Map()` - -Optional cache for fs operations. - -#### Example - -```ts -import { parseTsconfig } from 'get-tsconfig' - -// Must pass in a path to an existing tsconfig.json file -console.log(parseTsconfig('./path/to/tsconfig.custom.json')) -``` - ---- - -### createFileMatcher(tsconfig: TsconfigResult, caseSensitivePaths?: boolean) - -Given a `tsconfig.json` file, it returns a file-matcher function that determines whether it should apply to a file path. - -```ts -type FileMatcher = (filePath: string) => TsconfigResult['config'] | undefined -``` - -#### tsconfig -Type: `TsconfigResult` - -Pass in the return value from `getTsconfig`, or a `TsconfigResult` object. - -#### caseSensitivePaths -Type: `boolean` - -By default, it uses [`is-fs-case-sensitive`](https://github.com/privatenumber/is-fs-case-sensitive) to detect whether the file-system is case-sensitive. - -Pass in `true` to make it case-sensitive. - -#### Example - -For example, if it's called with a `tsconfig.json` file that has `include`/`exclude`/`files` defined, the file-matcher will return the config for files that match `include`/`files`, and return `undefined` for files that don't match or match `exclude`. - -```ts -const tsconfig = getTsconfig() -const fileMatcher = tsconfig && createFileMatcher(tsconfig) - -/* - * Returns tsconfig.json if it matches the file, - * undefined if not - */ -const configForFile = fileMatcher?.('/path/to/file.ts') -const distCode = compileTypescript({ - code: sourceCode, - tsconfig: configForFile -}) -``` - ---- - -### createPathsMatcher(tsconfig: TsconfigResult) - -Given a tsconfig with [`compilerOptions.paths`](https://www.typescriptlang.org/tsconfig#paths) defined, it returns a matcher function. - -The matcher function accepts an [import specifier (the path to resolve)](https://nodejs.org/api/esm.html#terminology), checks it against `compilerOptions.paths`, and returns an array of possible paths to check: -```ts -function pathsMatcher(specifier: string): string[] -``` - -This function only returns possible paths and doesn't actually do any resolution. This helps increase compatibility wtih file/build systems which usually have their own resolvers. - -#### Example - -```ts -import { getTsconfig, createPathsMatcher } from 'get-tsconfig' - -const tsconfig = getTsconfig() -const pathsMatcher = createPathsMatcher(tsconfig) - -const exampleResolver = (request: string) => { - if (pathsMatcher) { - const tryPaths = pathsMatcher(request) - - // Check if paths in `tryPaths` exist - } -} -``` - -## FAQ - -### How can I use TypeScript to parse `tsconfig.json`? -This package is a re-implementation of TypeScript's `tsconfig.json` parser. - -However, if you already have TypeScript as a dependency, you can simply use it's API: - -```ts -import { - sys as tsSys, - findConfigFile, - readConfigFile, - parseJsonConfigFileContent -} from 'typescript' - -// Find tsconfig.json file -const tsconfigPath = findConfigFile(process.cwd(), tsSys.fileExists, 'tsconfig.json') - -// Read tsconfig.json file -const tsconfigFile = readConfigFile(tsconfigPath, tsSys.readFile) - -// Resolve extends -const parsedTsconfig = parseJsonConfigFileContent( - tsconfigFile.config, - tsSys, - path.dirname(tsconfigPath) -) -``` - -## Sponsors -

- - - -

diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/get-tsconfig/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/get-tsconfig/package.json deleted file mode 100644 index fc78eca9f..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/get-tsconfig/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "get-tsconfig", - "version": "4.13.7", - "description": "Find and parse the tsconfig.json file from a directory path", - "keywords": [ - "get-tsconfig", - "get", - "typescript", - "tsconfig", - "tsconfig.json" - ], - "license": "MIT", - "repository": "privatenumber/get-tsconfig", - "funding": "https://github.com/privatenumber/get-tsconfig?sponsor=1", - "author": { - "name": "Hiroki Osame", - "email": "hiroki.osame@gmail.com" - }, - "files": [ - "dist" - ], - "type": "module", - "main": "./dist/index.cjs", - "module": "./dist/index.mjs", - "types": "./dist/index.d.cts", - "exports": { - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - }, - "import": { - "types": "./dist/index.d.mts", - "default": "./dist/index.mjs" - } - }, - "imports": { - "#get-tsconfig": { - "types": "./src/index.ts", - "development": "./src/index.ts", - "default": "./dist/index.mjs" - } - }, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - } -} \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/headroom-ai/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/headroom-ai/README.md deleted file mode 100644 index 8923a1a89..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/headroom-ai/README.md +++ /dev/null @@ -1,108 +0,0 @@ -# headroom-ai - -Compress LLM context. Save tokens. Fit more into every request. - -## Install - -```bash -npm install headroom-ai -``` - -## Quick Start - -```typescript -import { compress } from 'headroom-ai'; - -const result = await compress(messages, { model: 'gpt-4o' }); -console.log(`Saved ${result.tokensSaved} tokens (${((1 - result.compressionRatio) * 100).toFixed(0)}%)`); - -// Use compressed messages with any LLM client -const response = await openai.chat.completions.create({ - model: 'gpt-4o', - messages: result.messages, -}); -``` - -Requires a running Headroom proxy (`headroom proxy`) or Headroom Cloud API key. - -## Framework Adapters - -### Vercel AI SDK - -```typescript -import { headroomMiddleware } from 'headroom-ai/vercel-ai'; -import { wrapLanguageModel, generateText } from 'ai'; -import { openai } from '@ai-sdk/openai'; - -const model = wrapLanguageModel({ - model: openai('gpt-4o'), - middleware: headroomMiddleware(), -}); - -const { text } = await generateText({ model, messages }); -``` - -### OpenAI SDK - -```typescript -import { withHeadroom } from 'headroom-ai/openai'; -import OpenAI from 'openai'; - -const client = withHeadroom(new OpenAI()); -const response = await client.chat.completions.create({ - model: 'gpt-4o', - messages: longConversation, -}); -``` - -### Anthropic SDK - -```typescript -import { withHeadroom } from 'headroom-ai/anthropic'; -import Anthropic from '@anthropic-ai/sdk'; - -const client = withHeadroom(new Anthropic()); -const response = await client.messages.create({ - model: 'claude-sonnet-4-5-20250929', - messages: longConversation, - max_tokens: 1024, -}); -``` - -## Configuration - -```typescript -import { compress } from 'headroom-ai'; - -const result = await compress(messages, { - model: 'gpt-4o', - baseUrl: 'http://localhost:8787', // or https://api.headroom.ai - apiKey: 'hr_...', // for Headroom Cloud - timeout: 30000, // ms - fallback: true, // return uncompressed if proxy is down (default) - retries: 1, // retry on transient failures (default) -}); -``` - -Or use environment variables: -- `HEADROOM_BASE_URL` — proxy/cloud URL -- `HEADROOM_API_KEY` — Cloud API key - -## Reusable Client - -```typescript -import { HeadroomClient } from 'headroom-ai'; - -const client = new HeadroomClient({ - baseUrl: 'http://localhost:8787', - apiKey: 'hr_...', -}); - -// Reuse across many calls -const r1 = await client.compress(messages1, { model: 'gpt-4o' }); -const r2 = await client.compress(messages2, { model: 'gpt-4o' }); -``` - -## License - -Apache-2.0 diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/headroom-ai/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/headroom-ai/package.json deleted file mode 100644 index 7f798a2ad..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/headroom-ai/package.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "name": "headroom-ai", - "version": "0.1.0", - "description": "Compress LLM context. Save tokens. Fit more into every request.", - "type": "module", - "main": "./dist/index.cjs", - "module": "./dist/index.js", - "types": "./dist/index.d.ts", - "files": [ - "dist", - "README.md", - "LICENSE" - ], - "exports": { - ".": { - "import": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - } - }, - "./vercel-ai": { - "import": { - "types": "./dist/adapters/vercel-ai.d.ts", - "default": "./dist/adapters/vercel-ai.js" - }, - "require": { - "types": "./dist/adapters/vercel-ai.d.cts", - "default": "./dist/adapters/vercel-ai.cjs" - } - }, - "./openai": { - "import": { - "types": "./dist/adapters/openai.d.ts", - "default": "./dist/adapters/openai.js" - }, - "require": { - "types": "./dist/adapters/openai.d.cts", - "default": "./dist/adapters/openai.cjs" - } - }, - "./anthropic": { - "import": { - "types": "./dist/adapters/anthropic.d.ts", - "default": "./dist/adapters/anthropic.js" - }, - "require": { - "types": "./dist/adapters/anthropic.d.cts", - "default": "./dist/adapters/anthropic.cjs" - } - } - }, - "engines": { - "node": ">=18.0.0" - }, - "scripts": { - "build": "tsup", - "test": "vitest run", - "test:watch": "vitest", - "typecheck": "tsc --noEmit" - }, - "peerDependencies": { - "@ai-sdk/provider": ">=1.0.0", - "@anthropic-ai/sdk": ">=0.30.0", - "ai": ">=6.0.0", - "openai": ">=4.0.0" - }, - "peerDependenciesMeta": { - "ai": { - "optional": true - }, - "@ai-sdk/provider": { - "optional": true - }, - "openai": { - "optional": true - }, - "@anthropic-ai/sdk": { - "optional": true - } - }, - "devDependencies": { - "@ai-sdk/anthropic": "^3.0.64", - "@ai-sdk/openai": "^3.0.48", - "@ai-sdk/provider": "^1.0.0", - "@anthropic-ai/sdk": "^0.39.0", - "ai": "^6.0.0", - "dotenv": "^17.3.1", - "openai": "^4.80.0", - "tsup": "^8.0.0", - "typescript": "^5.5.0", - "vitest": "^2.0.0" - }, - "license": "Apache-2.0" -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/json-schema/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/json-schema/LICENSE deleted file mode 100644 index 824c87fa6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/json-schema/LICENSE +++ /dev/null @@ -1,195 +0,0 @@ -Dojo is available under *either* the terms of the BSD 3-Clause "New" License *or* the -Academic Free License version 2.1. As a recipient of Dojo, you may choose which -license to receive this code under (except as noted in per-module LICENSE -files). Some modules may not be the copyright of the Dojo Foundation. These -modules contain explicit declarations of copyright in both the LICENSE files in -the directories in which they reside and in the code itself. No external -contributions are allowed under licenses which are fundamentally incompatible -with the AFL-2.1 OR and BSD-3-Clause licenses that Dojo is distributed under. - -The text of the AFL-2.1 and BSD-3-Clause licenses is reproduced below. - -------------------------------------------------------------------------------- -BSD 3-Clause "New" License: -********************** - -Copyright (c) 2005-2015, The Dojo Foundation -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Dojo Foundation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -------------------------------------------------------------------------------- -The Academic Free License, v. 2.1: -********************************** - -This Academic Free License (the "License") applies to any original work of -authorship (the "Original Work") whose owner (the "Licensor") has placed the -following notice immediately following the copyright notice for the Original -Work: - -Licensed under the Academic Free License version 2.1 - -1) Grant of Copyright License. Licensor hereby grants You a world-wide, -royalty-free, non-exclusive, perpetual, sublicenseable license to do the -following: - -a) to reproduce the Original Work in copies; - -b) to prepare derivative works ("Derivative Works") based upon the Original -Work; - -c) to distribute copies of the Original Work and Derivative Works to the -public; - -d) to perform the Original Work publicly; and - -e) to display the Original Work publicly. - -2) Grant of Patent License. Licensor hereby grants You a world-wide, -royalty-free, non-exclusive, perpetual, sublicenseable license, under patent -claims owned or controlled by the Licensor that are embodied in the Original -Work as furnished by the Licensor, to make, use, sell and offer for sale the -Original Work and Derivative Works. - -3) Grant of Source Code License. The term "Source Code" means the preferred -form of the Original Work for making modifications to it and all available -documentation describing how to modify the Original Work. Licensor hereby -agrees to provide a machine-readable copy of the Source Code of the Original -Work along with each copy of the Original Work that Licensor distributes. -Licensor reserves the right to satisfy this obligation by placing a -machine-readable copy of the Source Code in an information repository -reasonably calculated to permit inexpensive and convenient access by You for as -long as Licensor continues to distribute the Original Work, and by publishing -the address of that information repository in a notice immediately following -the copyright notice that applies to the Original Work. - -4) Exclusions From License Grant. Neither the names of Licensor, nor the names -of any contributors to the Original Work, nor any of their trademarks or -service marks, may be used to endorse or promote products derived from this -Original Work without express prior written permission of the Licensor. Nothing -in this License shall be deemed to grant any rights to trademarks, copyrights, -patents, trade secrets or any other intellectual property of Licensor except as -expressly stated herein. No patent license is granted to make, use, sell or -offer to sell embodiments of any patent claims other than the licensed claims -defined in Section 2. No right is granted to the trademarks of Licensor even if -such marks are included in the Original Work. Nothing in this License shall be -interpreted to prohibit Licensor from licensing under different terms from this -License any Original Work that Licensor otherwise would have a right to -license. - -5) This section intentionally omitted. - -6) Attribution Rights. You must retain, in the Source Code of any Derivative -Works that You create, all copyright, patent or trademark notices from the -Source Code of the Original Work, as well as any notices of licensing and any -descriptive text identified therein as an "Attribution Notice." You must cause -the Source Code for any Derivative Works that You create to carry a prominent -Attribution Notice reasonably calculated to inform recipients that You have -modified the Original Work. - -7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that -the copyright in and to the Original Work and the patent rights granted herein -by Licensor are owned by the Licensor or are sublicensed to You under the terms -of this License with the permission of the contributor(s) of those copyrights -and patent rights. Except as expressly stated in the immediately proceeding -sentence, the Original Work is provided under this License on an "AS IS" BASIS -and WITHOUT WARRANTY, either express or implied, including, without limitation, -the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. -This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No -license to Original Work is granted hereunder except under this disclaimer. - -8) Limitation of Liability. Under no circumstances and under no legal theory, -whether in tort (including negligence), contract, or otherwise, shall the -Licensor be liable to any person for any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License -or the use of the Original Work including, without limitation, damages for loss -of goodwill, work stoppage, computer failure or malfunction, or any and all -other commercial damages or losses. This limitation of liability shall not -apply to liability for death or personal injury resulting from Licensor's -negligence to the extent applicable law prohibits such limitation. Some -jurisdictions do not allow the exclusion or limitation of incidental or -consequential damages, so this exclusion and limitation may not apply to You. - -9) Acceptance and Termination. If You distribute copies of the Original Work or -a Derivative Work, You must make a reasonable effort under the circumstances to -obtain the express assent of recipients to the terms of this License. Nothing -else but this License (or another written agreement between Licensor and You) -grants You permission to create Derivative Works based upon the Original Work -or to exercise any of the rights granted in Section 1 herein, and any attempt -to do so except under the terms of this License (or another written agreement -between Licensor and You) is expressly prohibited by U.S. copyright law, the -equivalent laws of other countries, and by international treaty. Therefore, by -exercising any of the rights granted to You in Section 1 herein, You indicate -Your acceptance of this License and all of its terms and conditions. - -10) Termination for Patent Action. This License shall terminate automatically -and You may no longer exercise any of the rights granted to You by this License -as of the date You commence an action, including a cross-claim or counterclaim, -against Licensor or any licensee alleging that the Original Work infringes a -patent. This termination provision shall not apply for an action alleging -patent infringement by combinations of the Original Work with other software or -hardware. - -11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this -License may be brought only in the courts of a jurisdiction wherein the -Licensor resides or in which Licensor conducts its primary business, and under -the laws of that jurisdiction excluding its conflict-of-law provisions. The -application of the United Nations Convention on Contracts for the International -Sale of Goods is expressly excluded. Any use of the Original Work outside the -scope of this License or after its termination shall be subject to the -requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et -seq., the equivalent laws of other countries, and international treaty. This -section shall survive the termination of this License. - -12) Attorneys Fees. In any action to enforce the terms of this License or -seeking damages relating thereto, the prevailing party shall be entitled to -recover its costs and expenses, including, without limitation, reasonable -attorneys' fees and costs incurred in connection with such action, including -any appeal of such action. This section shall survive the termination of this -License. - -13) Miscellaneous. This License represents the complete agreement concerning -the subject matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent necessary to -make it enforceable. - -14) Definition of "You" in This License. "You" throughout this License, whether -in upper or lower case, means an individual or a legal entity exercising rights -under, and complying with all of the terms of, this License. For legal -entities, "You" includes any entity that controls, is controlled by, or is -under common control with you. For purposes of this definition, "control" means -(i) the power, direct or indirect, to cause the direction or management of such -entity, whether by contract or otherwise, or (ii) ownership of fifty percent -(50%) or more of the outstanding shares, or (iii) beneficial ownership of such -entity. - -15) Right to Use. You may use the Original Work in all ways not otherwise -restricted or conditioned by this License or by law, and Licensor promises not -to interfere with or be responsible for such uses by You. - -This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. -Permission is hereby granted to copy and distribute this license without -modification. This license may not be modified without the express written -permission of its copyright owner. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/json-schema/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/json-schema/README.md deleted file mode 100644 index b58623908..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/json-schema/README.md +++ /dev/null @@ -1,3 +0,0 @@ -This is a historical repository for the early development of the JSON Schema specification and implementation. This package is considered "finished": it holds the earlier draft specification and a simple, efficient, lightweight implementation of the original core elements of JSON Schema. This repository does not house the latest specifications nor does it implement the latest versions of JSON Schema. This package seeks to maintain the stability (in behavior and size) of this original implementation for the sake of the numerous packages that rely on it. For the latest JSON Schema specifications and implementations, please visit the [JSON Schema site](https://json-schema.org/) (or the [respository](https://github.com/json-schema-org/json-schema-spec)). - -Code is licensed under the AFL or BSD 3-Clause license. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/json-schema/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/json-schema/package.json deleted file mode 100644 index 8c1f89980..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/json-schema/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "json-schema", - "version": "0.4.0", - "author": "Kris Zyp", - "description": "JSON Schema validation and specifications", - "maintainers":[ - {"name": "Kris Zyp", "email": "kriszyp@gmail.com"}], - "keywords": [ - "json", - "schema" - ], - "files": [ - "lib" - ], - "license": "(AFL-2.1 OR BSD-3-Clause)", - "repository": { - "type":"git", - "url":"http://github.com/kriszyp/json-schema" - }, - "directories": { "lib": "./lib" }, - "main": "./lib/validate.js", - "devDependencies": { "vows": "*" }, - "scripts": { "test": "vows --spec test/*.js" } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/resolve-pkg-maps/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/resolve-pkg-maps/LICENSE deleted file mode 100644 index 51e4fd864..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/resolve-pkg-maps/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) Hiroki Osame - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/resolve-pkg-maps/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/resolve-pkg-maps/README.md deleted file mode 100644 index 2469b1b20..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/resolve-pkg-maps/README.md +++ /dev/null @@ -1,216 +0,0 @@ -# resolve-pkg-maps - -Utils to resolve `package.json` subpath & conditional [`exports`](https://nodejs.org/api/packages.html#exports)/[`imports`](https://nodejs.org/api/packages.html#imports) in resolvers. - -Implements the [ESM resolution algorithm](https://nodejs.org/api/esm.html#resolver-algorithm-specification). Tested [against Node.js](/tests/) for accuracy. - -Support this project by ⭐️ starring and sharing it. [Follow me](https://github.com/privatenumber) to see what other cool projects I'm working on! ❤️ - -## Usage - -### Resolving `exports` - -_utils/package.json_ -```json5 -{ - // ... - "exports": { - "./reverse": { - "require": "./file.cjs", - "default": "./file.mjs" - } - }, - // ... -} -``` - -```ts -import { resolveExports } from 'resolve-pkg-maps' - -const [packageName, packageSubpath] = parseRequest('utils/reverse') - -const resolvedPaths: string[] = resolveExports( - getPackageJson(packageName).exports, - packageSubpath, - ['import', ...otherConditions] -) -// => ['./file.mjs'] -``` - -### Resolving `imports` - -_package.json_ -```json5 -{ - // ... - "imports": { - "#supports-color": { - "node": "./index.js", - "default": "./browser.js" - } - }, - // ... -} -``` - -```ts -import { resolveImports } from 'resolve-pkg-maps' - -const resolvedPaths: string[] = resolveImports( - getPackageJson('.').imports, - '#supports-color', - ['node', ...otherConditions] -) -// => ['./index.js'] -``` - -## API - -### resolveExports(exports, request, conditions) - -Returns: `string[]` - -Resolves the `request` based on `exports` and `conditions`. Returns an array of paths (e.g. in case a fallback array is matched). - -#### exports - -Type: -```ts -type Exports = PathOrMap | readonly PathOrMap[] - -type PathOrMap = string | PathConditionsMap - -type PathConditionsMap = { - [condition: string]: PathConditions | null -} -``` - -The [`exports` property](https://nodejs.org/api/packages.html#exports) value in `package.json`. - -#### request - -Type: `string` - -The package subpath to resolve. Assumes a normalized path is passed in (eg. [repeating slashes `//`](https://github.com/nodejs/node/issues/44316)). - -It _should not_ start with `/` or `./`. - -Example: if the full import path is `some-package/subpath/file`, the request is `subpath/file`. - - -#### conditions - -Type: `readonly string[]` - -An array of conditions to use when resolving the request. For reference, Node.js's default conditions are [`['node', 'import']`](https://nodejs.org/api/esm.html#:~:text=defaultConditions%20is%20the%20conditional%20environment%20name%20array%2C%20%5B%22node%22%2C%20%22import%22%5D.). - -The order of this array does not matter; the order of condition keys in the export map is what matters instead. - -Not all conditions in the array need to be met to resolve the request. It just needs enough to resolve to a path. - ---- - -### resolveImports(imports, request, conditions) - -Returns: `string[]` - -Resolves the `request` based on `imports` and `conditions`. Returns an array of paths (e.g. in case a fallback array is matched). - -#### imports - -Type: -```ts -type Imports = { - [condition: string]: PathOrMap | readonly PathOrMap[] | null -} - -type PathOrMap = string | Imports -``` - -The [`imports` property](https://nodejs.org/api/packages.html#imports) value in `package.json`. - - -#### request - -Type: `string` - -The request resolve. Assumes a normalized path is passed in (eg. [repeating slashes `//`](https://github.com/nodejs/node/issues/44316)). - -> **Note:** In Node.js, imports resolutions are limited to requests prefixed with `#`. However, this package does not enforce that requirement in case you want to add custom support for non-prefixed entries. - -#### conditions - -Type: `readonly string[]` - -An array of conditions to use when resolving the request. For reference, Node.js's default conditions are [`['node', 'import']`](https://nodejs.org/api/esm.html#:~:text=defaultConditions%20is%20the%20conditional%20environment%20name%20array%2C%20%5B%22node%22%2C%20%22import%22%5D.). - -The order of this array does not matter; the order of condition keys in the import map is what matters instead. - -Not all conditions in the array need to be met to resolve the request. It just needs enough to resolve to a path. - ---- - -### Errors - -#### `ERR_PACKAGE_PATH_NOT_EXPORTED` - - If the request is not exported by the export map - -#### `ERR_PACKAGE_IMPORT_NOT_DEFINED` - - If the request is not defined by the import map - -#### `ERR_INVALID_PACKAGE_CONFIG` - - - If an object contains properties that are both paths and conditions (e.g. start with and without `.`) - - If an object contains numeric properties - -#### `ERR_INVALID_PACKAGE_TARGET` - - If a resolved exports path is not a valid path (e.g. not relative or has protocol) - - If a resolved path includes `..` or `node_modules` - - If a resolved path is a type that cannot be parsed - -## FAQ - -### Why do the APIs return an array of paths? - -`exports`/`imports` supports passing in a [fallback array](https://github.com/jkrems/proposal-pkg-exports/#:~:text=Whenever%20there%20is,to%20new%20cases.) to provide fallback paths if the previous one is invalid: - -```json5 -{ - "exports": { - "./feature": [ - "./file.js", - "./fallback.js" - ] - } -} -``` - -Node.js's implementation [picks the first valid path (without attempting to resolve it)](https://github.com/nodejs/node/issues/44282#issuecomment-1220151715) and throws an error if it can't be resolved. Node.js's fallback array is designed for [forward compatibility with features](https://github.com/jkrems/proposal-pkg-exports/#:~:text=providing%20forwards%20compatiblitiy%20for%20new%20features) (e.g. protocols) that can be immediately/inexpensively validated: - -```json5 -{ - "exports": { - "./core-polyfill": ["std:core-module", "./core-polyfill.js"] - } -} -``` - -However, [Webpack](https://webpack.js.org/guides/package-exports/#alternatives) and [TypeScript](https://github.com/microsoft/TypeScript/blob/71e852922888337ef51a0e48416034a94a6c34d9/src/compiler/moduleSpecifiers.ts#L695) have deviated from this behavior and attempts to resolve the next path if a path cannot be resolved. - -By returning an array of matched paths instead of just the first one, the user can decide which behavior to adopt. - -### How is it different from [`resolve.exports`](https://github.com/lukeed/resolve.exports)? - -`resolve.exports` only resolves `exports`, whereas this package resolves both `exports` & `imports`. This comparison will only cover resolving `exports`. - -- Despite it's name, `resolve.exports` handles more than just `exports`. It takes in the entire `package.json` object to handle resolving `.` and [self-references](https://nodejs.org/api/packages.html#self-referencing-a-package-using-its-name). This package only accepts `exports`/`imports` maps from `package.json` and is scoped to only resolving what's defined in the maps. - -- `resolve.exports` accepts the full request (e.g. `foo/bar`), whereas this package only accepts the requested subpath (e.g. `bar`). - -- `resolve.exports` only returns the first result in a fallback array. This package returns an array of results for the user to decide how to handle it. - -- `resolve.exports` supports [subpath folder mapping](https://nodejs.org/docs/latest-v16.x/api/packages.html#subpath-folder-mappings) (deprecated in Node.js v16 & removed in v17) but seems to [have a bug](https://github.com/lukeed/resolve.exports/issues/7). This package does not support subpath folder mapping because Node.js has removed it in favor of using subpath patterns. - -- Neither resolvers rely on a file-system - -This package also addresses many of the bugs in `resolve.exports`, demonstrated in [this test](/tests/exports/compare-resolve.exports.ts). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/resolve-pkg-maps/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/resolve-pkg-maps/package.json deleted file mode 100644 index 720d98492..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/resolve-pkg-maps/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "resolve-pkg-maps", - "version": "1.0.0", - "description": "Resolve package.json exports & imports maps", - "keywords": [ - "node.js", - "package.json", - "exports", - "imports" - ], - "license": "MIT", - "repository": "privatenumber/resolve-pkg-maps", - "funding": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1", - "author": { - "name": "Hiroki Osame", - "email": "hiroki.osame@gmail.com" - }, - "type": "module", - "files": [ - "dist" - ], - "main": "./dist/index.cjs", - "module": "./dist/index.mjs", - "types": "./dist/index.d.cts", - "exports": { - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - }, - "import": { - "types": "./dist/index.d.mts", - "default": "./dist/index.mjs" - } - }, - "imports": { - "#resolve-pkg-maps": { - "types": "./src/index.ts", - "development": "./src/index.ts", - "default": "./dist/index.mjs" - } - } -} \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/tsx/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/tsx/LICENSE deleted file mode 100644 index bf183d2f5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/tsx/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) Hiroki Osame - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/tsx/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/tsx/README.md deleted file mode 100644 index b269d1cc3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/tsx/README.md +++ /dev/null @@ -1,32 +0,0 @@ -

-
- - - tsx - -

- -

- -

-TypeScript Execute (tsx): The easiest way to run TypeScript in Node.js -

-Documentation    |    Getting started → -

- -
- -

- - -

-

Already a sponsor? Join the discussion in the Development repo!

- -## Sponsors - -

- - - -

- diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/tsx/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/tsx/package.json deleted file mode 100644 index 51a3ee6c2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/tsx/package.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "name": "tsx", - "version": "4.21.0", - "description": "TypeScript Execute (tsx): Node.js enhanced with esbuild to run TypeScript & ESM files", - "keywords": [ - "cli", - "runtime", - "node", - "cjs", - "commonjs", - "esm", - "typescript", - "typescript runner" - ], - "license": "MIT", - "repository": "privatenumber/tsx", - "author": { - "name": "Hiroki Osame", - "email": "hiroki.osame@gmail.com" - }, - "files": [ - "dist" - ], - "type": "module", - "bin": "./dist/cli.mjs", - "exports": { - "./package.json": "./package.json", - ".": "./dist/loader.mjs", - "./patch-repl": "./dist/patch-repl.cjs", - "./cjs": "./dist/cjs/index.cjs", - "./cjs/api": { - "import": { - "types": "./dist/cjs/api/index.d.mts", - "default": "./dist/cjs/api/index.mjs" - }, - "require": { - "types": "./dist/cjs/api/index.d.cts", - "default": "./dist/cjs/api/index.cjs" - } - }, - "./esm": "./dist/esm/index.mjs", - "./esm/api": { - "import": { - "types": "./dist/esm/api/index.d.mts", - "default": "./dist/esm/api/index.mjs" - }, - "require": { - "types": "./dist/esm/api/index.d.cts", - "default": "./dist/esm/api/index.cjs" - } - }, - "./cli": "./dist/cli.mjs", - "./suppress-warnings": "./dist/suppress-warnings.cjs", - "./preflight": "./dist/preflight.cjs", - "./repl": "./dist/repl.mjs" - }, - "homepage": "https://tsx.is", - "engines": { - "node": ">=18.0.0" - }, - "dependencies": { - "esbuild": "~0.27.0", - "get-tsconfig": "^4.7.5" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } -} \ No newline at end of file diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/LICENSE.txt b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/LICENSE.txt deleted file mode 100644 index 8746124b2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/LICENSE.txt +++ /dev/null @@ -1,55 +0,0 @@ -Apache License - -Version 2.0, January 2004 - -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. - -"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: - -You must give any other recipients of the Work or Derivative Works a copy of this License; and - -You must cause any modified files to carry prominent notices stating that You changed the files; and - -You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and - -If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/README.md deleted file mode 100644 index b6505f736..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/README.md +++ /dev/null @@ -1,50 +0,0 @@ - -# TypeScript - -[![CI](https://github.com/microsoft/TypeScript/actions/workflows/ci.yml/badge.svg)](https://github.com/microsoft/TypeScript/actions/workflows/ci.yml) -[![npm version](https://badge.fury.io/js/typescript.svg)](https://www.npmjs.com/package/typescript) -[![Downloads](https://img.shields.io/npm/dm/typescript.svg)](https://www.npmjs.com/package/typescript) -[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/microsoft/TypeScript/badge)](https://securityscorecards.dev/viewer/?uri=github.com/microsoft/TypeScript) - - -[TypeScript](https://www.typescriptlang.org/) is a language for application-scale JavaScript. TypeScript adds optional types to JavaScript that support tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript. Try it out at the [playground](https://www.typescriptlang.org/play/), and stay up to date via [our blog](https://blogs.msdn.microsoft.com/typescript) and [Twitter account](https://twitter.com/typescript). - -Find others who are using TypeScript at [our community page](https://www.typescriptlang.org/community/). - -## Installing - -For the latest stable version: - -```bash -npm install -D typescript -``` - -For our nightly builds: - -```bash -npm install -D typescript@next -``` - -## Contribute - -There are many ways to [contribute](https://github.com/microsoft/TypeScript/blob/main/CONTRIBUTING.md) to TypeScript. -* [Submit bugs](https://github.com/microsoft/TypeScript/issues) and help us verify fixes as they are checked in. -* Review the [source code changes](https://github.com/microsoft/TypeScript/pulls). -* Engage with other TypeScript users and developers on [StackOverflow](https://stackoverflow.com/questions/tagged/typescript). -* Help each other in the [TypeScript Community Discord](https://discord.gg/typescript). -* Join the [#typescript](https://twitter.com/search?q=%23TypeScript) discussion on Twitter. -* [Contribute bug fixes](https://github.com/microsoft/TypeScript/blob/main/CONTRIBUTING.md). - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see -the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) -with any additional questions or comments. - -## Documentation - -* [TypeScript in 5 minutes](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html) -* [Programming handbook](https://www.typescriptlang.org/docs/handbook/intro.html) -* [Homepage](https://www.typescriptlang.org/) - -## Roadmap - -For details on our planned features and future direction, please refer to our [roadmap](https://github.com/microsoft/TypeScript/wiki/Roadmap). diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/SECURITY.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/SECURITY.md deleted file mode 100644 index d8e8bb9ca..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/SECURITY.md +++ /dev/null @@ -1,39 +0,0 @@ - - -## Security - -Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations. - -If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below. - -## Reporting Security Issues - -**Please do not report security vulnerabilities through public GitHub issues.** - -Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report). - -You should receive a response within 24 hours. If for some reason you do not, please follow up using the messaging functionality found at the bottom of the Activity tab on your vulnerability report on [https://msrc.microsoft.com/report/vulnerability](https://msrc.microsoft.com/report/vulnerability/) or via email as described in the instructions at the bottom of [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report). Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc) or on MSRC's [FAQ page for reporting an issue](https://www.microsoft.com/en-us/msrc/faqs-report-an-issue). - -Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: - - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue - -This information will help us triage your report more quickly. - -If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs. - -## Preferred Languages - -We prefer all communications to be in English. - -## Policy - -Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd). - - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/ThirdPartyNoticeText.txt b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/ThirdPartyNoticeText.txt deleted file mode 100644 index a857fb3ce..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/ThirdPartyNoticeText.txt +++ /dev/null @@ -1,193 +0,0 @@ -/*!----------------- TypeScript ThirdPartyNotices ------------------------------------------------------- - -The TypeScript software incorporates third party material from the projects listed below. The original copyright notice and the license under which Microsoft received such third party material are set forth below. Microsoft reserves all other rights not expressly granted, whether by implication, estoppel or otherwise. - ---------------------------------------------- -Third Party Code Components --------------------------------------------- - -------------------- DefinitelyTyped -------------------- -This file is based on or incorporates material from the projects listed below (collectively "Third Party Code"). Microsoft is not the original author of the Third Party Code. The original copyright notice and the license, under which Microsoft received such Third Party Code, are set forth below. Such licenses and notices are provided for informational purposes only. Microsoft, not the third party, licenses the Third Party Code to you under the terms set forth in the EULA for the Microsoft Product. Microsoft reserves all other rights not expressly granted under this agreement, whether by implication, estoppel or otherwise. -DefinitelyTyped -This project is licensed under the MIT license. Copyrights are respective of each contributor listed at the beginning of each definition file. Provided for Informational Purposes Only - -MIT License -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------------------------------------- - -------------------- Unicode -------------------- -UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE - -Unicode Data Files include all data files under the directories -http://www.unicode.org/Public/, http://www.unicode.org/reports/, -http://www.unicode.org/cldr/data/, http://source.icu-project.org/repos/icu/, and -http://www.unicode.org/utility/trac/browser/. - -Unicode Data Files do not include PDF online code charts under the -directory http://www.unicode.org/Public/. - -Software includes any source code published in the Unicode Standard -or under the directories -http://www.unicode.org/Public/, http://www.unicode.org/reports/, -http://www.unicode.org/cldr/data/, http://source.icu-project.org/repos/icu/, and -http://www.unicode.org/utility/trac/browser/. - -NOTICE TO USER: Carefully read the following legal agreement. -BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S -DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), -YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE -TERMS AND CONDITIONS OF THIS AGREEMENT. -IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE -THE DATA FILES OR SOFTWARE. - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1991-2017 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that either -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, or -(b) this copyright and permission notice appear in associated -Documentation. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. -------------------------------------------------------------------------------------- - --------------------Document Object Model----------------------------- -DOM - -W3C License -This work is being provided by the copyright holders under the following license. -By obtaining and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions. -Permission to copy, modify, and distribute this work, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following -on ALL copies of the work or portions thereof, including modifications: -* The full text of this NOTICE in a location viewable to users of the redistributed or derivative work. -* Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, the W3C Software and Document Short Notice should be included. -* Notice of any changes or modifications, through a copyright statement on the new code or document such as "This software or document includes material copied from or derived -from [title and URI of the W3C document]. Copyright © [YEAR] W3C® (MIT, ERCIM, Keio, Beihang)." -Disclaimers -THIS WORK IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR -FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. -COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT. -The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the work without specific, written prior permission. -Title to copyright in this work will at all times remain with copyright holders. - ---------- - -DOM -Copyright © 2018 WHATWG (Apple, Google, Mozilla, Microsoft). This work is licensed under a Creative Commons Attribution 4.0 International License: Attribution 4.0 International -======================================================================= -Creative Commons Corporation ("Creative Commons") is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an "as-is" basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. Using Creative Commons Public Licenses Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC- licensed material, or material used under an exception or limitation to copyright. More considerations for licensors: - -wiki.creativecommons.org/Considerations_for_licensors Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor's permission is not necessary for any reason--for example, because of any applicable exception or limitation to copyright--then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More_considerations for the public: wiki.creativecommons.org/Considerations_for_licensees ======================================================================= -Creative Commons Attribution 4.0 International Public License By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. Section 1 -- Definitions. a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. c. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. d. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. e. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. f. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. g. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. h. Licensor means the individual(s) or entity(ies) granting rights under this Public License. i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. Section 2 -- Scope. a. License grant. 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: a. reproduce and Share the Licensed Material, in whole or in part; and b. produce, reproduce, and Share Adapted Material. 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 3. Term. The term of this Public License is specified in Section 6(a). 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a) (4) never produces Adapted Material. 5. Downstream recipients. a. Offer from the Licensor -- Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. b. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). b. Other rights. 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 2. Patent and trademark rights are not licensed under this Public License. 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. Section 3 -- License Conditions. Your exercise of the Licensed Rights is expressly made subject to the following conditions. a. Attribution. 1. If You Share the Licensed Material (including in modified form), You must: a. retain the following if it is supplied by the Licensor with the Licensed Material: i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); ii. a copyright notice; iii. a notice that refers to this Public License; iv. a notice that refers to the disclaimer of warranties; v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; b. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and c. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. Section 4 -- Sui Generis Database Rights. Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. Section 5 -- Disclaimer of Warranties and Limitation of Liability. a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. Section 6 -- Term and Termination. a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 2. upon express reinstatement by the Licensor. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. Section 7 -- Other Terms and Conditions. a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. Section 8 -- Interpretation. a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. ======================================================================= Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the "Licensor." Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. Creative Commons may be contacted at creativecommons.org. - --------------------------------------------------------------------------------- - -----------------------Web Background Synchronization------------------------------ - -Web Background Synchronization Specification -Portions of spec © by W3C - -W3C Community Final Specification Agreement -To secure commitments from participants for the full text of a Community or Business Group Report, the group may call for voluntary commitments to the following terms; a "summary" is -available. See also the related "W3C Community Contributor License Agreement". -1. The Purpose of this Agreement. -This Agreement sets forth the terms under which I make certain copyright and patent rights available to you for your implementation of the Specification. -Any other capitalized terms not specifically defined herein have the same meaning as those terms have in the "W3C Patent Policy", and if not defined there, in the "W3C Process Document". -2. Copyrights. -2.1. Copyright Grant. I grant to you a perpetual (for the duration of the applicable copyright), worldwide, non-exclusive, no-charge, royalty-free, copyright license, without any obligation for accounting to me, to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, distribute, and implement the Specification to the full extent of my copyright interest in the Specification. -2.2. Attribution. As a condition of the copyright grant, you must include an attribution to the Specification in any derivative work you make based on the Specification. That attribution must include, at minimum, the Specification name and version number. -3. Patents. -3.1. Patent Licensing Commitment. I agree to license my Essential Claims under the W3C Community RF Licensing Requirements. This requirement includes Essential Claims that I own and any that I have the right to license without obligation of payment or other consideration to an unrelated third party. W3C Community RF Licensing Requirements obligations made concerning the Specification and described in this policy are binding on me for the life of the patents in question and encumber the patents containing Essential Claims, regardless of changes in participation status or W3C Membership. I also agree to license my Essential Claims under the W3C Community RF Licensing Requirements in derivative works of the Specification so long as all normative portions of the Specification are maintained and that this licensing commitment does not extend to any portion of the derivative work that was not included in the Specification. -3.2. Optional, Additional Patent Grant. In addition to the provisions of Section 3.1, I may also, at my option, make certain intellectual property rights infringed by implementations of the Specification, including Essential Claims, available by providing those terms via the W3C Web site. -4. No Other Rights. Except as specifically set forth in this Agreement, no other express or implied patent, trademark, copyright, or other property rights are granted under this Agreement, including by implication, waiver, or estoppel. -5. Antitrust Compliance. I acknowledge that I may compete with other participants, that I am under no obligation to implement the Specification, that each participant is free to develop competing technologies and standards, and that each party is free to license its patent rights to third parties, including for the purpose of enabling competing technologies and standards. -6. Non-Circumvention. I agree that I will not intentionally take or willfully assist any third party to take any action for the purpose of circumventing my obligations under this Agreement. -7. Transition to W3C Recommendation Track. The Specification developed by the Project may transition to the W3C Recommendation Track. The W3C Team is responsible for notifying me that a Corresponding Working Group has been chartered. I have no obligation to join the Corresponding Working Group. If the Specification developed by the Project transitions to the W3C Recommendation Track, the following terms apply: -7.1. If I join the Corresponding Working Group. If I join the Corresponding Working Group, I will be subject to all W3C rules, obligations, licensing commitments, and policies that govern that Corresponding Working Group. -7.2. If I Do Not Join the Corresponding Working Group. -7.2.1. Licensing Obligations to Resulting Specification. If I do not join the Corresponding Working Group, I agree to offer patent licenses according to the W3C Royalty-Free licensing requirements described in Section 5 of the W3C Patent Policy for the portions of the Specification included in the resulting Recommendation. This licensing commitment does not extend to any portion of an implementation of the Recommendation that was not included in the Specification. This licensing commitment may not be revoked but may be modified through the exclusion process defined in Section 4 of the W3C Patent Policy. I am not required to join the Corresponding Working Group to exclude patents from the W3C Royalty-Free licensing commitment, but must otherwise follow the normal exclusion procedures defined by the W3C Patent Policy. The W3C Team will notify me of any Call for Exclusion in the Corresponding Working Group as set forth in Section 4.5 of the W3C Patent Policy. -7.2.2. No Disclosure Obligation. If I do not join the Corresponding Working Group, I have no patent disclosure obligations outside of those set forth in Section 6 of the W3C Patent Policy. -8. Conflict of Interest. I will disclose significant relationships when those relationships might reasonably be perceived as creating a conflict of interest with my role. I will notify W3C of any change in my affiliation using W3C-provided mechanisms. -9. Representations, Warranties and Disclaimers. I represent and warrant that I am legally entitled to grant the rights and promises set forth in this Agreement. IN ALL OTHER RESPECTS THE SPECIFICATION IS PROVIDED “AS IS.” The entire risk as to implementing or otherwise using the Specification is assumed by the implementer and user. Except as stated herein, I expressly disclaim any warranties (express, implied, or otherwise), including implied warranties of merchantability, non-infringement, fitness for a particular purpose, or title, related to the Specification. IN NO EVENT WILL ANY PARTY BE LIABLE TO ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES OF ACTION OF ANY KIND WITH RESPECT TO THIS AGREEMENT, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR NOT THE OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. All of my obligations under Section 3 regarding the transfer, successors in interest, or assignment of Granted Claims will be satisfied if I notify the transferee or assignee of any patent that I know contains Granted Claims of the obligations under Section 3. Nothing in this Agreement requires me to undertake a patent search. -10. Definitions. -10.1. Agreement. “Agreement” means this W3C Community Final Specification Agreement. -10.2. Corresponding Working Group. “Corresponding Working Group” is a W3C Working Group that is chartered to develop a Recommendation, as defined in the W3C Process Document, that takes the Specification as an input. -10.3. Essential Claims. “Essential Claims” shall mean all claims in any patent or patent application in any jurisdiction in the world that would necessarily be infringed by implementation of the Specification. A claim is necessarily infringed hereunder only when it is not possible to avoid infringing it because there is no non-infringing alternative for implementing the normative portions of the Specification. Existence of a non-infringing alternative shall be judged based on the state of the art at the time of the publication of the Specification. The following are expressly excluded from and shall not be deemed to constitute Essential Claims: -10.3.1. any claims other than as set forth above even if contained in the same patent as Essential Claims; and -10.3.2. claims which would be infringed only by: -portions of an implementation that are not specified in the normative portions of the Specification, or -enabling technologies that may be necessary to make or use any product or portion thereof that complies with the Specification and are not themselves expressly set forth in the Specification (e.g., semiconductor manufacturing technology, compiler technology, object-oriented technology, basic operating system technology, and the like); or -the implementation of technology developed elsewhere and merely incorporated by reference in the body of the Specification. -10.3.3. design patents and design registrations. -For purposes of this definition, the normative portions of the Specification shall be deemed to include only architectural and interoperability requirements. Optional features in the RFC 2119 sense are considered normative unless they are specifically identified as informative. Implementation examples or any other material that merely illustrate the requirements of the Specification are informative, rather than normative. -10.4. I, Me, or My. “I,” “me,” or “my” refers to the signatory. -10.5 Project. “Project” means the W3C Community Group or Business Group for which I executed this Agreement. -10.6. Specification. “Specification” means the Specification identified by the Project as the target of this agreement in a call for Final Specification Commitments. W3C shall provide the authoritative mechanisms for the identification of this Specification. -10.7. W3C Community RF Licensing Requirements. “W3C Community RF Licensing Requirements” license shall mean a non-assignable, non-sublicensable license to make, have made, use, sell, have sold, offer to sell, import, and distribute and dispose of implementations of the Specification that: -10.7.1. shall be available to all, worldwide, whether or not they are W3C Members; -10.7.2. shall extend to all Essential Claims owned or controlled by me; -10.7.3. may be limited to implementations of the Specification, and to what is required by the Specification; -10.7.4. may be conditioned on a grant of a reciprocal RF license (as defined in this policy) to all Essential Claims owned or controlled by the licensee. A reciprocal license may be required to be available to all, and a reciprocal license may itself be conditioned on a further reciprocal license from all. -10.7.5. may not be conditioned on payment of royalties, fees or other consideration; -10.7.6. may be suspended with respect to any licensee when licensor issued by licensee for infringement of claims essential to implement the Specification or any W3C Recommendation; -10.7.7. may not impose any further conditions or restrictions on the use of any technology, intellectual property rights, or other restrictions on behavior of the licensee, but may include reasonable, customary terms relating to operation or maintenance of the license relationship such as the following: choice of law and dispute resolution; -10.7.8. shall not be considered accepted by an implementer who manifests an intent not to accept the terms of the W3C Community RF Licensing Requirements license as offered by the licensor. -10.7.9. The RF license conforming to the requirements in this policy shall be made available by the licensor as long as the Specification is in effect. The term of such license shall be for the life of the patents in question. -I am encouraged to provide a contact from which licensing information can be obtained and other relevant licensing information. Any such information will be made publicly available. -10.8. You or Your. “You,” “you,” or “your” means any person or entity who exercises copyright or patent rights granted under this Agreement, and any person that person or entity controls. - -------------------------------------------------------------------------------------- - -------------------- WebGL ----------------------------- -Copyright (c) 2018 The Khronos Group Inc. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and/or associated documentation files (the -"Materials"), to deal in the Materials without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Materials, and to -permit persons to whom the Materials are furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Materials. - -THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. ------------------------------------------------------- - -------------- End of ThirdPartyNotices ------------------------------------------- */ - diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/bin/tsc b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/bin/tsc deleted file mode 100755 index 19c62bf7a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/bin/tsc +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env node -require('../lib/tsc.js') diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/bin/tsserver b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/bin/tsserver deleted file mode 100755 index 7143b6a73..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/bin/tsserver +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env node -require('../lib/tsserver.js') diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/package.json deleted file mode 100644 index fe2244bb4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/typescript/package.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "name": "typescript", - "author": "Microsoft Corp.", - "homepage": "https://www.typescriptlang.org/", - "version": "6.0.2", - "license": "Apache-2.0", - "description": "TypeScript is a language for application scale JavaScript development", - "keywords": [ - "TypeScript", - "Microsoft", - "compiler", - "language", - "javascript" - ], - "bugs": { - "url": "https://github.com/microsoft/TypeScript/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/microsoft/TypeScript.git" - }, - "main": "./lib/typescript.js", - "typings": "./lib/typescript.d.ts", - "bin": { - "tsc": "./bin/tsc", - "tsserver": "./bin/tsserver" - }, - "engines": { - "node": ">=14.17" - }, - "files": [ - "bin", - "lib", - "!lib/enu", - "LICENSE.txt", - "README.md", - "SECURITY.md", - "ThirdPartyNoticeText.txt", - "!**/.gitattributes" - ], - "devDependencies": { - "@dprint/formatter": "^0.4.1", - "@dprint/typescript": "0.93.4", - "@esfx/canceltoken": "^1.0.0", - "@eslint/js": "^10.0.1", - "@octokit/rest": "^22.0.1", - "@types/chai": "^4.3.20", - "@types/minimist": "^1.2.5", - "@types/mocha": "^10.0.10", - "@types/ms": "^2.1.0", - "@types/node": "latest", - "@types/source-map-support": "^0.5.10", - "@types/which": "^3.0.4", - "@typescript-eslint/rule-tester": "^8.56.1", - "@typescript-eslint/type-utils": "^8.56.1", - "@typescript-eslint/utils": "^8.56.1", - "azure-devops-node-api": "^15.1.3", - "c8": "^10.1.3", - "chai": "^4.5.0", - "chokidar": "^4.0.3", - "diff": "^8.0.3", - "dprint": "^0.49.1", - "esbuild": "^0.27.3", - "eslint": "^10.0.2", - "eslint-plugin-regexp": "^3.0.0", - "fast-xml-parser": "^5.4.1", - "glob": "^10.5.0", - "globals": "^17.4.0", - "hereby": "^1.12.0", - "jsonc-parser": "^3.3.1", - "knip": "^5.85.0", - "minimist": "^1.2.8", - "mocha": "^10.8.2", - "mocha-fivemat-progress-reporter": "^0.1.0", - "monocart-coverage-reports": "^2.12.9", - "ms": "^2.1.3", - "picocolors": "^1.1.1", - "playwright": "^1.58.2", - "source-map-support": "^0.5.21", - "tslib": "^2.8.1", - "typescript": "^5.9.3", - "typescript-eslint": "^8.56.1", - "which": "^3.0.1" - }, - "overrides": { - "typescript@*": "$typescript" - }, - "scripts": { - "test": "hereby runtests-parallel --light=false", - "test:eslint-rules": "hereby run-eslint-rules-tests", - "build": "npm run build:compiler && npm run build:tests", - "build:compiler": "hereby local", - "build:tests": "hereby tests", - "build:tests:notypecheck": "hereby tests --no-typecheck", - "clean": "hereby clean", - "gulp": "hereby", - "lint": "hereby lint", - "knip": "hereby knip", - "format": "dprint fmt", - "setup-hooks": "node scripts/link-hooks.mjs" - }, - "browser": { - "fs": false, - "os": false, - "path": false, - "crypto": false, - "buffer": false, - "source-map-support": false, - "inspector": false, - "perf_hooks": false - }, - "packageManager": "npm@8.19.4", - "volta": { - "node": "22.22.0", - "npm": "8.19.4" - }, - "gitHead": "607a22a90d1a5a1b507ce01bb8cd7ec020f954e7" -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/LICENSE b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/LICENSE deleted file mode 100644 index c06579627..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 Colin McDonnell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/README.md b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/README.md deleted file mode 100644 index 305059e6d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/README.md +++ /dev/null @@ -1,208 +0,0 @@ -

- Zod logo -

Zod

-

- TypeScript-first schema validation with static type inference -
- by @colinhacks -

-

-
- -

-Zod CI status -License -npm -discord server -stars -

- -
- Docs -   •   - Discord -   •   - 𝕏 -   •   - Bluesky -
-
- -
-
- -

Featured sponsor: Jazz

- -
- - - - jazz logo - - -
-

Learn more about featured sponsorships

-
- -
-
-
- -### [Read the docs →](https://zod.dev/api) - -
-
- -## What is Zod? - -Zod is a TypeScript-first validation library. Define a schema and parse some data with it. You'll get back a strongly typed, validated result. - -```ts -import * as z from "zod"; - -const User = z.object({ - name: z.string(), -}); - -// some untrusted data... -const input = { - /* stuff */ -}; - -// the parsed result is validated and type safe! -const data = User.parse(input); - -// so you can use it with confidence :) -console.log(data.name); -``` - -
- -## Features - -- Zero external dependencies -- Works in Node.js and all modern browsers -- Tiny: `2kb` core bundle (gzipped) -- Immutable API: methods return a new instance -- Concise interface -- Works with TypeScript and plain JS -- Built-in JSON Schema conversion -- Extensive ecosystem - -
- -## Installation - -```sh -npm install zod -``` - -
- -## Basic usage - -Before you can do anything else, you need to define a schema. For the purposes of this guide, we'll use a simple object schema. - -```ts -import * as z from "zod"; - -const Player = z.object({ - username: z.string(), - xp: z.number(), -}); -``` - -### Parsing data - -Given any Zod schema, use `.parse` to validate an input. If it's valid, Zod returns a strongly-typed _deep clone_ of the input. - -```ts -Player.parse({ username: "billie", xp: 100 }); -// => returns { username: "billie", xp: 100 } -``` - -**Note** — If your schema uses certain asynchronous APIs like `async` [refinements](https://zod.dev/api#refinements) or [transforms](https://zod.dev/api#transforms), you'll need to use the `.parseAsync()` method instead. - -```ts -const schema = z.string().refine(async (val) => val.length <= 8); - -await schema.parseAsync("hello"); -// => "hello" -``` - -### Handling errors - -When validation fails, the `.parse()` method will throw a `ZodError` instance with granular information about the validation issues. - -```ts -try { - Player.parse({ username: 42, xp: "100" }); -} catch (err) { - if (err instanceof z.ZodError) { - err.issues; - /* [ - { - expected: 'string', - code: 'invalid_type', - path: [ 'username' ], - message: 'Invalid input: expected string' - }, - { - expected: 'number', - code: 'invalid_type', - path: [ 'xp' ], - message: 'Invalid input: expected number' - } - ] */ - } -} -``` - -To avoid a `try/catch` block, you can use the `.safeParse()` method to get back a plain result object containing either the successfully parsed data or a `ZodError`. The result type is a [discriminated union](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions), so you can handle both cases conveniently. - -```ts -const result = Player.safeParse({ username: 42, xp: "100" }); -if (!result.success) { - result.error; // ZodError instance -} else { - result.data; // { username: string; xp: number } -} -``` - -**Note** — If your schema uses certain asynchronous APIs like `async` [refinements](#refine) or [transforms](#transform), you'll need to use the `.safeParseAsync()` method instead. - -```ts -const schema = z.string().refine(async (val) => val.length <= 8); - -await schema.safeParseAsync("hello"); -// => { success: true; data: "hello" } -``` - -### Inferring types - -Zod infers a static type from your schema definitions. You can extract this type with the `z.infer<>` utility and use it however you like. - -```ts -const Player = z.object({ - username: z.string(), - xp: z.number(), -}); - -// extract the inferred type -type Player = z.infer; - -// use it in your code -const player: Player = { username: "billie", xp: 100 }; -``` - -In some cases, the input & output types of a schema can diverge. For instance, the `.transform()` API can convert the input from one type to another. In these cases, you can extract the input and output types independently: - -```ts -const mySchema = z.string().transform((val) => val.length); - -type MySchemaIn = z.input; -// => string - -type MySchemaOut = z.output; // equivalent to z.infer -// number -``` diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/index.cjs b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/index.cjs deleted file mode 100644 index 3e30380fb..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/index.cjs +++ /dev/null @@ -1,33 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.z = void 0; -const z = __importStar(require("./v4/classic/external.cjs")); -exports.z = z; -__exportStar(require("./v4/classic/external.cjs"), exports); -exports.default = z; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/index.d.cts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/index.d.cts deleted file mode 100644 index ed2f3c30c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/index.d.cts +++ /dev/null @@ -1,4 +0,0 @@ -import * as z from "./v4/classic/external.cjs"; -export * from "./v4/classic/external.cjs"; -export { z }; -export default z; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/index.d.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/index.d.ts deleted file mode 100644 index b0bbaefb7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/index.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as z from "./v4/classic/external.js"; -export * from "./v4/classic/external.js"; -export { z }; -export default z; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/index.js b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/index.js deleted file mode 100644 index b0bbaefb7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/index.js +++ /dev/null @@ -1,4 +0,0 @@ -import * as z from "./v4/classic/external.js"; -export * from "./v4/classic/external.js"; -export { z }; -export default z; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/index.cjs b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/index.cjs deleted file mode 100644 index 65f2079f7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/index.cjs +++ /dev/null @@ -1,17 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -__exportStar(require("../v4/locales/index.cjs"), exports); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/index.d.cts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/index.d.cts deleted file mode 100644 index cd70ce63d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/index.d.cts +++ /dev/null @@ -1 +0,0 @@ -export * from "../v4/locales/index.cjs"; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/index.d.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/index.d.ts deleted file mode 100644 index e6e7dd67c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "../v4/locales/index.js"; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/index.js b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/index.js deleted file mode 100644 index e6e7dd67c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/index.js +++ /dev/null @@ -1 +0,0 @@ -export * from "../v4/locales/index.js"; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/package.json deleted file mode 100644 index 6cc7aaea8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/locales/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "type": "module", - "main": "./index.cjs", - "module": "./index.js", - "types": "./index.d.cts" -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/index.cjs b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/index.cjs deleted file mode 100644 index 90a31e2ce..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/index.cjs +++ /dev/null @@ -1,32 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.z = void 0; -const z = __importStar(require("../v4/mini/external.cjs")); -exports.z = z; -__exportStar(require("../v4/mini/external.cjs"), exports); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/index.d.cts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/index.d.cts deleted file mode 100644 index bca69bd60..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/index.d.cts +++ /dev/null @@ -1,3 +0,0 @@ -import * as z from "../v4/mini/external.cjs"; -export * from "../v4/mini/external.cjs"; -export { z }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/index.d.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/index.d.ts deleted file mode 100644 index bb95da0a2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as z from "../v4/mini/external.js"; -export * from "../v4/mini/external.js"; -export { z }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/index.js b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/index.js deleted file mode 100644 index bb95da0a2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import * as z from "../v4/mini/external.js"; -export * from "../v4/mini/external.js"; -export { z }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/package.json deleted file mode 100644 index 6cc7aaea8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/mini/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "type": "module", - "main": "./index.cjs", - "module": "./index.js", - "types": "./index.d.cts" -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/package.json b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/package.json deleted file mode 100644 index d6bf83535..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/package.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "name": "zod", - "version": "4.3.6", - "type": "module", - "license": "MIT", - "author": "Colin McDonnell ", - "description": "TypeScript-first schema declaration and validation library with static type inference", - "homepage": "https://zod.dev", - "llms": "https://zod.dev/llms.txt", - "llmsFull": "https://zod.dev/llms-full.txt", - "mcpServer": "https://mcp.inkeep.com/zod/mcp", - "funding": "https://github.com/sponsors/colinhacks", - "sideEffects": false, - "files": [ - "src", - "**/*.js", - "**/*.mjs", - "**/*.cjs", - "**/*.d.ts", - "**/*.d.mts", - "**/*.d.cts", - "**/package.json" - ], - "keywords": [ - "typescript", - "schema", - "validation", - "type", - "inference" - ], - "main": "./index.cjs", - "types": "./index.d.cts", - "module": "./index.js", - "zshy": { - "exports": { - "./package.json": "./package.json", - ".": "./src/index.ts", - "./mini": "./src/mini/index.ts", - "./locales": "./src/locales/index.ts", - "./v3": "./src/v3/index.ts", - "./v4": "./src/v4/index.ts", - "./v4-mini": "./src/v4-mini/index.ts", - "./v4/mini": "./src/v4/mini/index.ts", - "./v4/core": "./src/v4/core/index.ts", - "./v4/locales": "./src/v4/locales/index.ts", - "./v4/locales/*": "./src/v4/locales/*" - }, - "conditions": { - "@zod/source": "src" - } - }, - "exports": { - "./package.json": "./package.json", - ".": { - "@zod/source": "./src/index.ts", - "types": "./index.d.cts", - "import": "./index.js", - "require": "./index.cjs" - }, - "./mini": { - "@zod/source": "./src/mini/index.ts", - "types": "./mini/index.d.cts", - "import": "./mini/index.js", - "require": "./mini/index.cjs" - }, - "./locales": { - "@zod/source": "./src/locales/index.ts", - "types": "./locales/index.d.cts", - "import": "./locales/index.js", - "require": "./locales/index.cjs" - }, - "./v3": { - "@zod/source": "./src/v3/index.ts", - "types": "./v3/index.d.cts", - "import": "./v3/index.js", - "require": "./v3/index.cjs" - }, - "./v4": { - "@zod/source": "./src/v4/index.ts", - "types": "./v4/index.d.cts", - "import": "./v4/index.js", - "require": "./v4/index.cjs" - }, - "./v4-mini": { - "@zod/source": "./src/v4-mini/index.ts", - "types": "./v4-mini/index.d.cts", - "import": "./v4-mini/index.js", - "require": "./v4-mini/index.cjs" - }, - "./v4/mini": { - "@zod/source": "./src/v4/mini/index.ts", - "types": "./v4/mini/index.d.cts", - "import": "./v4/mini/index.js", - "require": "./v4/mini/index.cjs" - }, - "./v4/core": { - "@zod/source": "./src/v4/core/index.ts", - "types": "./v4/core/index.d.cts", - "import": "./v4/core/index.js", - "require": "./v4/core/index.cjs" - }, - "./v4/locales": { - "@zod/source": "./src/v4/locales/index.ts", - "types": "./v4/locales/index.d.cts", - "import": "./v4/locales/index.js", - "require": "./v4/locales/index.cjs" - }, - "./v4/locales/*": { - "@zod/source": "./src/v4/locales/*", - "types": "./v4/locales/*", - "import": "./v4/locales/*", - "require": "./v4/locales/*" - } - }, - "repository": { - "type": "git", - "url": "git+https://github.com/colinhacks/zod.git" - }, - "bugs": { - "url": "https://github.com/colinhacks/zod/issues" - }, - "support": { - "backing": { - "npm-funding": true - } - }, - "scripts": { - "clean": "git clean -xdf . -e node_modules", - "build": "zshy --project tsconfig.build.json", - "postbuild": "tsx ../../scripts/write-stub-package-jsons.ts && pnpm biome check --write .", - "test:watch": "pnpm vitest", - "test": "pnpm vitest run", - "prepublishOnly": "tsx ../../scripts/check-versions.ts" - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/index.ts deleted file mode 100644 index b0bbaefb7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as z from "./v4/classic/external.js"; -export * from "./v4/classic/external.js"; -export { z }; -export default z; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/locales/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/locales/index.ts deleted file mode 100644 index e6e7dd67c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/locales/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "../v4/locales/index.js"; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/mini/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/mini/index.ts deleted file mode 100644 index bb95da0a2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/mini/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as z from "../v4/mini/external.js"; -export * from "../v4/mini/external.js"; -export { z }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/ZodError.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/ZodError.ts deleted file mode 100644 index b4c6865c4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/ZodError.ts +++ /dev/null @@ -1,330 +0,0 @@ -import type { Primitive } from "./helpers/typeAliases.js"; -import { util, type ZodParsedType } from "./helpers/util.js"; -import type { TypeOf, ZodType } from "./index.js"; - -type allKeys = T extends any ? keyof T : never; - -export type inferFlattenedErrors, U = string> = typeToFlattenedError, U>; -export type typeToFlattenedError = { - formErrors: U[]; - fieldErrors: { - [P in allKeys]?: U[]; - }; -}; - -export const ZodIssueCode = util.arrayToEnum([ - "invalid_type", - "invalid_literal", - "custom", - "invalid_union", - "invalid_union_discriminator", - "invalid_enum_value", - "unrecognized_keys", - "invalid_arguments", - "invalid_return_type", - "invalid_date", - "invalid_string", - "too_small", - "too_big", - "invalid_intersection_types", - "not_multiple_of", - "not_finite", -]); - -export type ZodIssueCode = keyof typeof ZodIssueCode; - -export type ZodIssueBase = { - path: (string | number)[]; - message?: string | undefined; -}; - -export interface ZodInvalidTypeIssue extends ZodIssueBase { - code: typeof ZodIssueCode.invalid_type; - expected: ZodParsedType; - received: ZodParsedType; -} - -export interface ZodInvalidLiteralIssue extends ZodIssueBase { - code: typeof ZodIssueCode.invalid_literal; - expected: unknown; - received: unknown; -} - -export interface ZodUnrecognizedKeysIssue extends ZodIssueBase { - code: typeof ZodIssueCode.unrecognized_keys; - keys: string[]; -} - -export interface ZodInvalidUnionIssue extends ZodIssueBase { - code: typeof ZodIssueCode.invalid_union; - unionErrors: ZodError[]; -} - -export interface ZodInvalidUnionDiscriminatorIssue extends ZodIssueBase { - code: typeof ZodIssueCode.invalid_union_discriminator; - options: Primitive[]; -} - -export interface ZodInvalidEnumValueIssue extends ZodIssueBase { - received: string | number; - code: typeof ZodIssueCode.invalid_enum_value; - options: (string | number)[]; -} - -export interface ZodInvalidArgumentsIssue extends ZodIssueBase { - code: typeof ZodIssueCode.invalid_arguments; - argumentsError: ZodError; -} - -export interface ZodInvalidReturnTypeIssue extends ZodIssueBase { - code: typeof ZodIssueCode.invalid_return_type; - returnTypeError: ZodError; -} - -export interface ZodInvalidDateIssue extends ZodIssueBase { - code: typeof ZodIssueCode.invalid_date; -} - -export type StringValidation = - | "email" - | "url" - | "emoji" - | "uuid" - | "nanoid" - | "regex" - | "cuid" - | "cuid2" - | "ulid" - | "datetime" - | "date" - | "time" - | "duration" - | "ip" - | "cidr" - | "base64" - | "jwt" - | "base64url" - | { includes: string; position?: number | undefined } - | { startsWith: string } - | { endsWith: string }; - -export interface ZodInvalidStringIssue extends ZodIssueBase { - code: typeof ZodIssueCode.invalid_string; - validation: StringValidation; -} - -export interface ZodTooSmallIssue extends ZodIssueBase { - code: typeof ZodIssueCode.too_small; - minimum: number | bigint; - inclusive: boolean; - exact?: boolean; - type: "array" | "string" | "number" | "set" | "date" | "bigint"; -} - -export interface ZodTooBigIssue extends ZodIssueBase { - code: typeof ZodIssueCode.too_big; - maximum: number | bigint; - inclusive: boolean; - exact?: boolean; - type: "array" | "string" | "number" | "set" | "date" | "bigint"; -} - -export interface ZodInvalidIntersectionTypesIssue extends ZodIssueBase { - code: typeof ZodIssueCode.invalid_intersection_types; -} - -export interface ZodNotMultipleOfIssue extends ZodIssueBase { - code: typeof ZodIssueCode.not_multiple_of; - multipleOf: number | bigint; -} - -export interface ZodNotFiniteIssue extends ZodIssueBase { - code: typeof ZodIssueCode.not_finite; -} - -export interface ZodCustomIssue extends ZodIssueBase { - code: typeof ZodIssueCode.custom; - params?: { [k: string]: any }; -} - -export type DenormalizedError = { [k: string]: DenormalizedError | string[] }; - -export type ZodIssueOptionalMessage = - | ZodInvalidTypeIssue - | ZodInvalidLiteralIssue - | ZodUnrecognizedKeysIssue - | ZodInvalidUnionIssue - | ZodInvalidUnionDiscriminatorIssue - | ZodInvalidEnumValueIssue - | ZodInvalidArgumentsIssue - | ZodInvalidReturnTypeIssue - | ZodInvalidDateIssue - | ZodInvalidStringIssue - | ZodTooSmallIssue - | ZodTooBigIssue - | ZodInvalidIntersectionTypesIssue - | ZodNotMultipleOfIssue - | ZodNotFiniteIssue - | ZodCustomIssue; - -export type ZodIssue = ZodIssueOptionalMessage & { - fatal?: boolean | undefined; - message: string; -}; - -export const quotelessJson = (obj: any) => { - const json = JSON.stringify(obj, null, 2); - return json.replace(/"([^"]+)":/g, "$1:"); -}; - -type recursiveZodFormattedError = T extends [any, ...any[]] - ? { [K in keyof T]?: ZodFormattedError } - : T extends any[] - ? { [k: number]: ZodFormattedError } - : T extends object - ? { [K in keyof T]?: ZodFormattedError } - : unknown; - -export type ZodFormattedError = { - _errors: U[]; -} & recursiveZodFormattedError>; - -export type inferFormattedError, U = string> = ZodFormattedError, U>; - -export class ZodError extends Error { - issues: ZodIssue[] = []; - - get errors() { - return this.issues; - } - - constructor(issues: ZodIssue[]) { - super(); - - const actualProto = new.target.prototype; - if (Object.setPrototypeOf) { - // eslint-disable-next-line ban/ban - Object.setPrototypeOf(this, actualProto); - } else { - (this as any).__proto__ = actualProto; - } - this.name = "ZodError"; - this.issues = issues; - } - - format(): ZodFormattedError; - format(mapper: (issue: ZodIssue) => U): ZodFormattedError; - format(_mapper?: any) { - const mapper: (issue: ZodIssue) => any = - _mapper || - function (issue: ZodIssue) { - return issue.message; - }; - const fieldErrors: ZodFormattedError = { _errors: [] } as any; - const processError = (error: ZodError) => { - for (const issue of error.issues) { - if (issue.code === "invalid_union") { - issue.unionErrors.map(processError); - } else if (issue.code === "invalid_return_type") { - processError(issue.returnTypeError); - } else if (issue.code === "invalid_arguments") { - processError(issue.argumentsError); - } else if (issue.path.length === 0) { - (fieldErrors as any)._errors.push(mapper(issue)); - } else { - let curr: any = fieldErrors; - let i = 0; - while (i < issue.path.length) { - const el = issue.path[i]!; - const terminal = i === issue.path.length - 1; - - if (!terminal) { - curr[el] = curr[el] || { _errors: [] }; - // if (typeof el === "string") { - // curr[el] = curr[el] || { _errors: [] }; - // } else if (typeof el === "number") { - // const errorArray: any = []; - // errorArray._errors = []; - // curr[el] = curr[el] || errorArray; - // } - } else { - curr[el] = curr[el] || { _errors: [] }; - curr[el]._errors.push(mapper(issue)); - } - - curr = curr[el]; - i++; - } - } - } - }; - - processError(this); - return fieldErrors; - } - - static create = (issues: ZodIssue[]) => { - const error = new ZodError(issues); - return error; - }; - - static assert(value: unknown): asserts value is ZodError { - if (!(value instanceof ZodError)) { - throw new Error(`Not a ZodError: ${value}`); - } - } - - override toString() { - return this.message; - } - override get message() { - return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2); - } - - get isEmpty(): boolean { - return this.issues.length === 0; - } - - addIssue = (sub: ZodIssue) => { - this.issues = [...this.issues, sub]; - }; - - addIssues = (subs: ZodIssue[] = []) => { - this.issues = [...this.issues, ...subs]; - }; - - flatten(): typeToFlattenedError; - flatten(mapper?: (issue: ZodIssue) => U): typeToFlattenedError; - flatten(mapper: (issue: ZodIssue) => U = (issue: ZodIssue) => issue.message as any): any { - const fieldErrors: any = Object.create(null); - const formErrors: U[] = []; - for (const sub of this.issues) { - if (sub.path.length > 0) { - const firstEl = sub.path[0]!; - fieldErrors[firstEl] = fieldErrors[firstEl] || []; - fieldErrors[firstEl].push(mapper(sub)); - } else { - formErrors.push(mapper(sub)); - } - } - return { formErrors, fieldErrors }; - } - - get formErrors() { - return this.flatten(); - } -} - -type stripPath = T extends any ? util.OmitKeys : never; - -export type IssueData = stripPath & { - path?: (string | number)[]; - fatal?: boolean | undefined; -}; - -export type ErrorMapCtx = { - defaultError: string; - data: any; -}; - -export type ZodErrorMap = (issue: ZodIssueOptionalMessage, _ctx: ErrorMapCtx) => { message: string }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/datetime.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/datetime.ts deleted file mode 100644 index 85552c254..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/datetime.ts +++ /dev/null @@ -1,58 +0,0 @@ -import Benchmark from "benchmark"; - -const datetimeValidationSuite = new Benchmark.Suite("datetime"); - -const DATA = "2021-01-01"; -const MONTHS_31 = new Set([1, 3, 5, 7, 8, 10, 12]); -const MONTHS_30 = new Set([4, 6, 9, 11]); - -const simpleDatetimeRegex = /^(\d{4})-(\d{2})-(\d{2})$/; -const datetimeRegexNoLeapYearValidation = - /^\d{4}-((0[13578]|10|12)-31|(0[13-9]|1[0-2])-30|(0[1-9]|1[0-2])-(0[1-9]|1\d|2\d))$/; -const datetimeRegexWithLeapYearValidation = - /^((\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\d|3[01])|(0[469]|11)-(0[1-9]|[12]\d|30)|(02)-(0[1-9]|1\d|2[0-8])))$/; - -datetimeValidationSuite - .add("new Date()", () => { - return !Number.isNaN(new Date(DATA).getTime()); - }) - .add("regex (no validation)", () => { - return simpleDatetimeRegex.test(DATA); - }) - .add("regex (no leap year)", () => { - return datetimeRegexNoLeapYearValidation.test(DATA); - }) - .add("regex (w/ leap year)", () => { - return datetimeRegexWithLeapYearValidation.test(DATA); - }) - .add("capture groups + code", () => { - const match = DATA.match(simpleDatetimeRegex); - if (!match) return false; - - // Extract year, month, and day from the capture groups - const year = Number.parseInt(match[1], 10); - const month = Number.parseInt(match[2], 10); // month is 0-indexed in JavaScript Date, so subtract 1 - const day = Number.parseInt(match[3], 10); - - if (month === 2) { - if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) { - return day <= 29; - } - return day <= 28; - } - if (MONTHS_30.has(month)) { - return day <= 30; - } - if (MONTHS_31.has(month)) { - return day <= 31; - } - return false; - }) - - .on("cycle", (e: Benchmark.Event) => { - console.log(`${datetimeValidationSuite.name!}: ${e.target}`); - }); - -export default { - suites: [datetimeValidationSuite], -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/discriminatedUnion.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/discriminatedUnion.ts deleted file mode 100644 index 47737e6c3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/discriminatedUnion.ts +++ /dev/null @@ -1,80 +0,0 @@ -import Benchmark from "benchmark"; - -import { z } from "zod/v3"; - -const doubleSuite = new Benchmark.Suite("z.discriminatedUnion: double"); -const manySuite = new Benchmark.Suite("z.discriminatedUnion: many"); - -const aSchema = z.object({ - type: z.literal("a"), -}); -const objA = { - type: "a", -}; - -const bSchema = z.object({ - type: z.literal("b"), -}); -const objB = { - type: "b", -}; - -const cSchema = z.object({ - type: z.literal("c"), -}); -const objC = { - type: "c", -}; - -const dSchema = z.object({ - type: z.literal("d"), -}); - -const double = z.discriminatedUnion("type", [aSchema, bSchema]); -const many = z.discriminatedUnion("type", [aSchema, bSchema, cSchema, dSchema]); - -doubleSuite - .add("valid: a", () => { - double.parse(objA); - }) - .add("valid: b", () => { - double.parse(objB); - }) - .add("invalid: null", () => { - try { - double.parse(null); - } catch (_err) {} - }) - .add("invalid: wrong shape", () => { - try { - double.parse(objC); - } catch (_err) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`${(doubleSuite as any).name}: ${e.target}`); - }); - -manySuite - .add("valid: a", () => { - many.parse(objA); - }) - .add("valid: c", () => { - many.parse(objC); - }) - .add("invalid: null", () => { - try { - many.parse(null); - } catch (_err) {} - }) - .add("invalid: wrong shape", () => { - try { - many.parse({ type: "unknown" }); - } catch (_err) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`${(manySuite as any).name}: ${e.target}`); - }); - -export default { - suites: [doubleSuite, manySuite], -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/index.ts deleted file mode 100644 index ca81c5bb9..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -import type Benchmark from "benchmark"; - -import datetimeBenchmarks from "./datetime.js"; -import discriminatedUnionBenchmarks from "./discriminatedUnion.js"; -import ipv4Benchmarks from "./ipv4.js"; -import objectBenchmarks from "./object.js"; -import primitiveBenchmarks from "./primitives.js"; -import realworld from "./realworld.js"; -import stringBenchmarks from "./string.js"; -import unionBenchmarks from "./union.js"; - -const argv = process.argv.slice(2); -let suites: Benchmark.Suite[] = []; - -if (!argv.length) { - suites = [ - ...realworld.suites, - ...primitiveBenchmarks.suites, - ...stringBenchmarks.suites, - ...objectBenchmarks.suites, - ...unionBenchmarks.suites, - ...discriminatedUnionBenchmarks.suites, - ]; -} else { - if (argv.includes("--realworld")) { - suites.push(...realworld.suites); - } - if (argv.includes("--primitives")) { - suites.push(...primitiveBenchmarks.suites); - } - if (argv.includes("--string")) { - suites.push(...stringBenchmarks.suites); - } - if (argv.includes("--object")) { - suites.push(...objectBenchmarks.suites); - } - if (argv.includes("--union")) { - suites.push(...unionBenchmarks.suites); - } - if (argv.includes("--discriminatedUnion")) { - suites.push(...datetimeBenchmarks.suites); - } - if (argv.includes("--datetime")) { - suites.push(...datetimeBenchmarks.suites); - } - if (argv.includes("--ipv4")) { - suites.push(...ipv4Benchmarks.suites); - } -} - -for (const suite of suites) { - suite.run({}); -} - -// exit on Ctrl-C -process.on("SIGINT", function () { - console.log("Exiting..."); - process.exit(); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/ipv4.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/ipv4.ts deleted file mode 100644 index 913ffd416..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/ipv4.ts +++ /dev/null @@ -1,57 +0,0 @@ -import Benchmark from "benchmark"; - -const suite = new Benchmark.Suite("ipv4"); - -const DATA = "127.0.0.1"; -const ipv4RegexA = - /^(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))$/; -const ipv4RegexB = - /^(?:(?:(?=(25[0-5]))\1|(?=(2[0-4][0-9]))\2|(?=(1[0-9]{2}))\3|(?=([0-9]{1,2}))\4)\.){3}(?:(?=(25[0-5]))\5|(?=(2[0-4][0-9]))\6|(?=(1[0-9]{2}))\7|(?=([0-9]{1,2}))\8)$/; -const ipv4RegexC = /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/; -const ipv4RegexD = /^(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/; -const ipv4RegexE = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.){3}(25[0-5]|(2[0-4]|1\d|[1-9]|)\d)$/; -const ipv4RegexF = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/; -const ipv4RegexG = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$/; -const ipv4RegexH = /^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$/; -const ipv4RegexI = - /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/; - -suite - .add("A", () => { - return ipv4RegexA.test(DATA); - }) - .add("B", () => { - return ipv4RegexB.test(DATA); - }) - .add("C", () => { - return ipv4RegexC.test(DATA); - }) - .add("D", () => { - return ipv4RegexD.test(DATA); - }) - .add("E", () => { - return ipv4RegexE.test(DATA); - }) - .add("F", () => { - return ipv4RegexF.test(DATA); - }) - .add("G", () => { - return ipv4RegexG.test(DATA); - }) - .add("H", () => { - return ipv4RegexH.test(DATA); - }) - .add("I", () => { - return ipv4RegexI.test(DATA); - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`${suite.name!}: ${e.target}`); - }); - -export default { - suites: [suite], -}; - -if (require.main === module) { - suite.run(); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/object.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/object.ts deleted file mode 100644 index 3c1da1022..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/object.ts +++ /dev/null @@ -1,69 +0,0 @@ -import Benchmark from "benchmark"; - -import { z } from "zod/v3"; - -const emptySuite = new Benchmark.Suite("z.object: empty"); -const shortSuite = new Benchmark.Suite("z.object: short"); -const longSuite = new Benchmark.Suite("z.object: long"); - -const empty = z.object({}); -const short = z.object({ - string: z.string(), -}); -const long = z.object({ - string: z.string(), - number: z.number(), - boolean: z.boolean(), -}); - -emptySuite - .add("valid", () => { - empty.parse({}); - }) - .add("valid: extra keys", () => { - empty.parse({ string: "string" }); - }) - .add("invalid: null", () => { - try { - empty.parse(null); - } catch (_err) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`${(emptySuite as any).name}: ${e.target}`); - }); - -shortSuite - .add("valid", () => { - short.parse({ string: "string" }); - }) - .add("valid: extra keys", () => { - short.parse({ string: "string", number: 42 }); - }) - .add("invalid: null", () => { - try { - short.parse(null); - } catch (_err) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`${(shortSuite as any).name}: ${e.target}`); - }); - -longSuite - .add("valid", () => { - long.parse({ string: "string", number: 42, boolean: true }); - }) - .add("valid: extra keys", () => { - long.parse({ string: "string", number: 42, boolean: true, list: [] }); - }) - .add("invalid: null", () => { - try { - long.parse(null); - } catch (_err) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`${(longSuite as any).name}: ${e.target}`); - }); - -export default { - suites: [emptySuite, shortSuite, longSuite], -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/primitives.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/primitives.ts deleted file mode 100644 index fd61b38fe..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/primitives.ts +++ /dev/null @@ -1,162 +0,0 @@ -import Benchmark from "benchmark"; - -import { z } from "zod/v3"; -import { Mocker } from "../tests/Mocker.js"; - -const val = new Mocker(); - -const enumSuite = new Benchmark.Suite("z.enum"); -const enumSchema = z.enum(["a", "b", "c"]); - -enumSuite - .add("valid", () => { - enumSchema.parse("a"); - }) - .add("invalid", () => { - try { - enumSchema.parse("x"); - } catch (_e: any) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`z.enum: ${e.target}`); - }); - -const longEnumSuite = new Benchmark.Suite("long z.enum"); -const longEnumSchema = z.enum([ - "one", - "two", - "three", - "four", - "five", - "six", - "seven", - "eight", - "nine", - "ten", - "eleven", - "twelve", - "thirteen", - "fourteen", - "fifteen", - "sixteen", - "seventeen", -]); - -longEnumSuite - .add("valid", () => { - longEnumSchema.parse("five"); - }) - .add("invalid", () => { - try { - longEnumSchema.parse("invalid"); - } catch (_e: any) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`long z.enum: ${e.target}`); - }); - -const undefinedSuite = new Benchmark.Suite("z.undefined"); -const undefinedSchema = z.undefined(); - -undefinedSuite - .add("valid", () => { - undefinedSchema.parse(undefined); - }) - .add("invalid", () => { - try { - undefinedSchema.parse(1); - } catch (_e: any) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`z.undefined: ${e.target}`); - }); - -const literalSuite = new Benchmark.Suite("z.literal"); -const short = "short"; -const bad = "bad"; -const literalSchema = z.literal("short"); - -literalSuite - .add("valid", () => { - literalSchema.parse(short); - }) - .add("invalid", () => { - try { - literalSchema.parse(bad); - } catch (_e: any) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`z.literal: ${e.target}`); - }); - -const numberSuite = new Benchmark.Suite("z.number"); -const numberSchema = z.number().int(); - -numberSuite - .add("valid", () => { - numberSchema.parse(1); - }) - .add("invalid type", () => { - try { - numberSchema.parse("bad"); - } catch (_e: any) {} - }) - .add("invalid number", () => { - try { - numberSchema.parse(0.5); - } catch (_e: any) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`z.number: ${e.target}`); - }); - -const dateSuite = new Benchmark.Suite("z.date"); - -const plainDate = z.date(); -const minMaxDate = z.date().min(new Date("2021-01-01")).max(new Date("2030-01-01")); - -dateSuite - .add("valid", () => { - plainDate.parse(new Date()); - }) - .add("invalid", () => { - try { - plainDate.parse(1); - } catch (_e: any) {} - }) - .add("valid min and max", () => { - minMaxDate.parse(new Date("2023-01-01")); - }) - .add("invalid min", () => { - try { - minMaxDate.parse(new Date("2019-01-01")); - } catch (_e: any) {} - }) - .add("invalid max", () => { - try { - minMaxDate.parse(new Date("2031-01-01")); - } catch (_e: any) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`z.date: ${e.target}`); - }); - -const symbolSuite = new Benchmark.Suite("z.symbol"); -const symbolSchema = z.symbol(); - -symbolSuite - .add("valid", () => { - symbolSchema.parse(val.symbol); - }) - .add("invalid", () => { - try { - symbolSchema.parse(1); - } catch (_e: any) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`z.symbol: ${e.target}`); - }); - -export default { - suites: [enumSuite, longEnumSuite, undefinedSuite, literalSuite, numberSuite, dateSuite, symbolSuite], -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/realworld.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/realworld.ts deleted file mode 100644 index d64c4f0d0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/realworld.ts +++ /dev/null @@ -1,63 +0,0 @@ -import Benchmark from "benchmark"; - -import { z } from "zod/v3"; - -const shortSuite = new Benchmark.Suite("realworld"); - -const People = z.array( - z.object({ - type: z.literal("person"), - hair: z.enum(["blue", "brown"]), - active: z.boolean(), - name: z.string(), - age: z.number().int(), - hobbies: z.array(z.string()), - address: z.object({ - street: z.string(), - zip: z.string(), - country: z.string(), - }), - }) -); - -let i = 0; - -function num() { - return ++i; -} - -function str() { - return (++i % 100).toString(16); -} - -function array(fn: () => T): T[] { - return Array.from({ length: ++i % 10 }, () => fn()); -} - -const people = Array.from({ length: 100 }, () => { - return { - type: "person", - hair: i % 2 ? "blue" : "brown", - active: !!(i % 2), - name: str(), - age: num(), - hobbies: array(str), - address: { - street: str(), - zip: str(), - country: str(), - }, - }; -}); - -shortSuite - .add("valid", () => { - People.parse(people); - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`${(shortSuite as any).name}: ${e.target}`); - }); - -export default { - suites: [shortSuite], -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/string.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/string.ts deleted file mode 100644 index 6b3d29f94..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/string.ts +++ /dev/null @@ -1,55 +0,0 @@ -import Benchmark from "benchmark"; - -import { z } from "zod/v3"; - -const SUITE_NAME = "z.string"; -const suite = new Benchmark.Suite(SUITE_NAME); - -const empty = ""; -const short = "short"; -const long = "long".repeat(256); -const manual = (str: unknown) => { - if (typeof str !== "string") { - throw new Error("Not a string"); - } - - return str; -}; -const stringSchema = z.string(); -const optionalStringSchema = z.string().optional(); -const optionalNullableStringSchema = z.string().optional().nullable(); - -suite - .add("empty string", () => { - stringSchema.parse(empty); - }) - .add("short string", () => { - stringSchema.parse(short); - }) - .add("long string", () => { - stringSchema.parse(long); - }) - .add("optional string", () => { - optionalStringSchema.parse(long); - }) - .add("nullable string", () => { - optionalNullableStringSchema.parse(long); - }) - .add("nullable (null) string", () => { - optionalNullableStringSchema.parse(null); - }) - .add("invalid: null", () => { - try { - stringSchema.parse(null); - } catch (_err) {} - }) - .add("manual parser: long", () => { - manual(long); - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`${SUITE_NAME}: ${e.target}`); - }); - -export default { - suites: [suite], -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/union.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/union.ts deleted file mode 100644 index d716dcef0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/benchmarks/union.ts +++ /dev/null @@ -1,80 +0,0 @@ -import Benchmark from "benchmark"; - -import { z } from "zod/v3"; - -const doubleSuite = new Benchmark.Suite("z.union: double"); -const manySuite = new Benchmark.Suite("z.union: many"); - -const aSchema = z.object({ - type: z.literal("a"), -}); -const objA = { - type: "a", -}; - -const bSchema = z.object({ - type: z.literal("b"), -}); -const objB = { - type: "b", -}; - -const cSchema = z.object({ - type: z.literal("c"), -}); -const objC = { - type: "c", -}; - -const dSchema = z.object({ - type: z.literal("d"), -}); - -const double = z.union([aSchema, bSchema]); -const many = z.union([aSchema, bSchema, cSchema, dSchema]); - -doubleSuite - .add("valid: a", () => { - double.parse(objA); - }) - .add("valid: b", () => { - double.parse(objB); - }) - .add("invalid: null", () => { - try { - double.parse(null); - } catch (_err) {} - }) - .add("invalid: wrong shape", () => { - try { - double.parse(objC); - } catch (_err) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`${(doubleSuite as any).name}: ${e.target}`); - }); - -manySuite - .add("valid: a", () => { - many.parse(objA); - }) - .add("valid: c", () => { - many.parse(objC); - }) - .add("invalid: null", () => { - try { - many.parse(null); - } catch (_err) {} - }) - .add("invalid: wrong shape", () => { - try { - many.parse({ type: "unknown" }); - } catch (_err) {} - }) - .on("cycle", (e: Benchmark.Event) => { - console.log(`${(manySuite as any).name}: ${e.target}`); - }); - -export default { - suites: [doubleSuite, manySuite], -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/errors.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/errors.ts deleted file mode 100644 index 3c0dae659..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/errors.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { ZodErrorMap } from "./ZodError.js"; -import defaultErrorMap from "./locales/en.js"; - -let overrideErrorMap = defaultErrorMap; -export { defaultErrorMap }; - -export function setErrorMap(map: ZodErrorMap) { - overrideErrorMap = map; -} - -export function getErrorMap() { - return overrideErrorMap; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/external.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/external.ts deleted file mode 100644 index f0a4be4c7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/external.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from "./errors.js"; -export * from "./helpers/parseUtil.js"; -export * from "./helpers/typeAliases.js"; -export * from "./helpers/util.js"; -export * from "./types.js"; -export * from "./ZodError.js"; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/enumUtil.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/enumUtil.ts deleted file mode 100644 index 526b22736..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/enumUtil.ts +++ /dev/null @@ -1,17 +0,0 @@ -export namespace enumUtil { - type UnionToIntersectionFn = (T extends unknown ? (k: () => T) => void : never) extends ( - k: infer Intersection - ) => void - ? Intersection - : never; - - type GetUnionLast = UnionToIntersectionFn extends () => infer Last ? Last : never; - - type UnionToTuple = [T] extends [never] - ? Tuple - : UnionToTuple>, [GetUnionLast, ...Tuple]>; - - type CastToStringTuple = T extends [string, ...string[]] ? T : never; - - export type UnionToTupleString = CastToStringTuple>; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/errorUtil.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/errorUtil.ts deleted file mode 100644 index 319ef6b74..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/errorUtil.ts +++ /dev/null @@ -1,8 +0,0 @@ -export namespace errorUtil { - export type ErrMessage = string | { message?: string | undefined }; - export const errToObj = (message?: ErrMessage): { message?: string | undefined } => - typeof message === "string" ? { message } : message || {}; - // biome-ignore lint: - export const toString = (message?: ErrMessage): string | undefined => - typeof message === "string" ? message : message?.message; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/parseUtil.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/parseUtil.ts deleted file mode 100644 index 1076ad9de..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/parseUtil.ts +++ /dev/null @@ -1,176 +0,0 @@ -import type { IssueData, ZodErrorMap, ZodIssue } from "../ZodError.js"; -import { getErrorMap } from "../errors.js"; -import defaultErrorMap from "../locales/en.js"; -import type { ZodParsedType } from "./util.js"; - -export const makeIssue = (params: { - data: any; - path: (string | number)[]; - errorMaps: ZodErrorMap[]; - issueData: IssueData; -}): ZodIssue => { - const { data, path, errorMaps, issueData } = params; - const fullPath = [...path, ...(issueData.path || [])]; - const fullIssue = { - ...issueData, - path: fullPath, - }; - - if (issueData.message !== undefined) { - return { - ...issueData, - path: fullPath, - message: issueData.message, - }; - } - - let errorMessage = ""; - const maps = errorMaps - .filter((m) => !!m) - .slice() - .reverse(); - for (const map of maps) { - errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message; - } - - return { - ...issueData, - path: fullPath, - message: errorMessage, - }; -}; - -export type ParseParams = { - path: (string | number)[]; - errorMap: ZodErrorMap; - async: boolean; -}; - -export type ParsePathComponent = string | number; -export type ParsePath = ParsePathComponent[]; -export const EMPTY_PATH: ParsePath = []; - -export interface ParseContext { - readonly common: { - readonly issues: ZodIssue[]; - readonly contextualErrorMap?: ZodErrorMap | undefined; - readonly async: boolean; - }; - readonly path: ParsePath; - readonly schemaErrorMap?: ZodErrorMap | undefined; - readonly parent: ParseContext | null; - readonly data: any; - readonly parsedType: ZodParsedType; -} - -export type ParseInput = { - data: any; - path: (string | number)[]; - parent: ParseContext; -}; - -export function addIssueToContext(ctx: ParseContext, issueData: IssueData): void { - const overrideMap = getErrorMap(); - const issue = makeIssue({ - issueData: issueData, - data: ctx.data, - path: ctx.path, - errorMaps: [ - ctx.common.contextualErrorMap, // contextual error map is first priority - ctx.schemaErrorMap, // then schema-bound map if available - overrideMap, // then global override map - overrideMap === defaultErrorMap ? undefined : defaultErrorMap, // then global default map - ].filter((x) => !!x), - }); - ctx.common.issues.push(issue); -} - -export type ObjectPair = { - key: SyncParseReturnType; - value: SyncParseReturnType; -}; -export class ParseStatus { - value: "aborted" | "dirty" | "valid" = "valid"; - dirty(): void { - if (this.value === "valid") this.value = "dirty"; - } - abort(): void { - if (this.value !== "aborted") this.value = "aborted"; - } - - static mergeArray(status: ParseStatus, results: SyncParseReturnType[]): SyncParseReturnType { - const arrayValue: any[] = []; - for (const s of results) { - if (s.status === "aborted") return INVALID; - if (s.status === "dirty") status.dirty(); - arrayValue.push(s.value); - } - - return { status: status.value, value: arrayValue }; - } - - static async mergeObjectAsync( - status: ParseStatus, - pairs: { key: ParseReturnType; value: ParseReturnType }[] - ): Promise> { - const syncPairs: ObjectPair[] = []; - for (const pair of pairs) { - const key = await pair.key; - const value = await pair.value; - syncPairs.push({ - key, - value, - }); - } - return ParseStatus.mergeObjectSync(status, syncPairs); - } - - static mergeObjectSync( - status: ParseStatus, - pairs: { - key: SyncParseReturnType; - value: SyncParseReturnType; - alwaysSet?: boolean; - }[] - ): SyncParseReturnType { - const finalObject: any = {}; - for (const pair of pairs) { - const { key, value } = pair; - if (key.status === "aborted") return INVALID; - if (value.status === "aborted") return INVALID; - if (key.status === "dirty") status.dirty(); - if (value.status === "dirty") status.dirty(); - - if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) { - finalObject[key.value] = value.value; - } - } - - return { status: status.value, value: finalObject }; - } -} -export interface ParseResult { - status: "aborted" | "dirty" | "valid"; - data: any; -} - -export type INVALID = { status: "aborted" }; -export const INVALID: INVALID = Object.freeze({ - status: "aborted", -}); - -export type DIRTY = { status: "dirty"; value: T }; -export const DIRTY = (value: T): DIRTY => ({ status: "dirty", value }); - -export type OK = { status: "valid"; value: T }; -export const OK = (value: T): OK => ({ status: "valid", value }); - -export type SyncParseReturnType = OK | DIRTY | INVALID; -export type AsyncParseReturnType = Promise>; -export type ParseReturnType = SyncParseReturnType | AsyncParseReturnType; - -export const isAborted = (x: ParseReturnType): x is INVALID => (x as any).status === "aborted"; -export const isDirty = (x: ParseReturnType): x is OK | DIRTY => (x as any).status === "dirty"; -export const isValid = (x: ParseReturnType): x is OK => (x as any).status === "valid"; -export const isAsync = (x: ParseReturnType): x is AsyncParseReturnType => - typeof Promise !== "undefined" && x instanceof Promise; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/partialUtil.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/partialUtil.ts deleted file mode 100644 index 0eff8ff34..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/partialUtil.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { - ZodArray, - ZodNullable, - ZodObject, - ZodOptional, - ZodRawShape, - ZodTuple, - ZodTupleItems, - ZodTypeAny, -} from "../types.js"; - -export namespace partialUtil { - export type DeepPartial = T extends ZodObject - ? ZodObject< - { [k in keyof T["shape"]]: ZodOptional> }, - T["_def"]["unknownKeys"], - T["_def"]["catchall"] - > - : T extends ZodArray - ? ZodArray, Card> - : T extends ZodOptional - ? ZodOptional> - : T extends ZodNullable - ? ZodNullable> - : T extends ZodTuple - ? { - [k in keyof Items]: Items[k] extends ZodTypeAny ? DeepPartial : never; - } extends infer PI - ? PI extends ZodTupleItems - ? ZodTuple - : never - : never - : T; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/typeAliases.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/typeAliases.ts deleted file mode 100644 index 32df022ca..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/typeAliases.ts +++ /dev/null @@ -1,2 +0,0 @@ -export type Primitive = string | number | symbol | bigint | boolean | null | undefined; -export type Scalars = Primitive | Primitive[]; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/util.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/util.ts deleted file mode 100644 index 030ea821b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/helpers/util.ts +++ /dev/null @@ -1,224 +0,0 @@ -export namespace util { - type AssertEqual = (() => V extends T ? 1 : 2) extends () => V extends U ? 1 : 2 ? true : false; - - export type isAny = 0 extends 1 & T ? true : false; - export const assertEqual = (_: AssertEqual): void => {}; - export function assertIs(_arg: T): void {} - export function assertNever(_x: never): never { - throw new Error(); - } - - export type Omit = Pick>; - export type OmitKeys = Pick>; - export type MakePartial = Omit & Partial>; - export type Exactly = T & Record, never>; - export type InexactPartial = { [k in keyof T]?: T[k] | undefined }; - export const arrayToEnum = (items: U): { [k in U[number]]: k } => { - const obj: any = {}; - for (const item of items) { - obj[item] = item; - } - return obj; - }; - - export const getValidEnumValues = (obj: any): any[] => { - const validKeys = objectKeys(obj).filter((k: any) => typeof obj[obj[k]] !== "number"); - const filtered: any = {}; - for (const k of validKeys) { - filtered[k] = obj[k]; - } - return objectValues(filtered); - }; - - export const objectValues = (obj: any): any[] => { - return objectKeys(obj).map(function (e) { - return obj[e]; - }); - }; - - export const objectKeys: ObjectConstructor["keys"] = - typeof Object.keys === "function" // eslint-disable-line ban/ban - ? (obj: any) => Object.keys(obj) // eslint-disable-line ban/ban - : (object: any) => { - const keys = []; - for (const key in object) { - if (Object.prototype.hasOwnProperty.call(object, key)) { - keys.push(key); - } - } - return keys; - }; - - export const find = (arr: T[], checker: (arg: T) => any): T | undefined => { - for (const item of arr) { - if (checker(item)) return item; - } - return undefined; - }; - - export type identity = objectUtil.identity; - export type flatten = objectUtil.flatten; - - export type noUndefined = T extends undefined ? never : T; - - export const isInteger: NumberConstructor["isInteger"] = - typeof Number.isInteger === "function" - ? (val) => Number.isInteger(val) // eslint-disable-line ban/ban - : (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val; - - export function joinValues(array: T, separator = " | "): string { - return array.map((val) => (typeof val === "string" ? `'${val}'` : val)).join(separator); - } - - export const jsonStringifyReplacer = (_: string, value: any): any => { - if (typeof value === "bigint") { - return value.toString(); - } - return value; - }; -} - -export namespace objectUtil { - export type MergeShapes = - // fast path when there is no keys overlap - keyof U & keyof V extends never - ? U & V - : { - [k in Exclude]: U[k]; - } & V; - - type optionalKeys = { - [k in keyof T]: undefined extends T[k] ? k : never; - }[keyof T]; - type requiredKeys = { - [k in keyof T]: undefined extends T[k] ? never : k; - }[keyof T]; - export type addQuestionMarks = { - [K in requiredKeys]: T[K]; - } & { - [K in optionalKeys]?: T[K]; - } & { [k in keyof T]?: unknown }; - - export type identity = T; - export type flatten = identity<{ [k in keyof T]: T[k] }>; - - export type noNeverKeys = { - [k in keyof T]: [T[k]] extends [never] ? never : k; - }[keyof T]; - - export type noNever = identity<{ - [k in noNeverKeys]: k extends keyof T ? T[k] : never; - }>; - - export const mergeShapes = (first: U, second: T): T & U => { - return { - ...first, - ...second, // second overwrites first - }; - }; - - export type extendShape = keyof A & keyof B extends never // fast path when there is no keys overlap - ? A & B - : { - [K in keyof A as K extends keyof B ? never : K]: A[K]; - } & { - [K in keyof B]: B[K]; - }; -} - -export const ZodParsedType: { - string: "string"; - nan: "nan"; - number: "number"; - integer: "integer"; - float: "float"; - boolean: "boolean"; - date: "date"; - bigint: "bigint"; - symbol: "symbol"; - function: "function"; - undefined: "undefined"; - null: "null"; - array: "array"; - object: "object"; - unknown: "unknown"; - promise: "promise"; - void: "void"; - never: "never"; - map: "map"; - set: "set"; -} = util.arrayToEnum([ - "string", - "nan", - "number", - "integer", - "float", - "boolean", - "date", - "bigint", - "symbol", - "function", - "undefined", - "null", - "array", - "object", - "unknown", - "promise", - "void", - "never", - "map", - "set", -]); - -export type ZodParsedType = keyof typeof ZodParsedType; - -export const getParsedType = (data: any): ZodParsedType => { - const t = typeof data; - - switch (t) { - case "undefined": - return ZodParsedType.undefined; - - case "string": - return ZodParsedType.string; - - case "number": - return Number.isNaN(data) ? ZodParsedType.nan : ZodParsedType.number; - - case "boolean": - return ZodParsedType.boolean; - - case "function": - return ZodParsedType.function; - - case "bigint": - return ZodParsedType.bigint; - - case "symbol": - return ZodParsedType.symbol; - - case "object": - if (Array.isArray(data)) { - return ZodParsedType.array; - } - if (data === null) { - return ZodParsedType.null; - } - if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { - return ZodParsedType.promise; - } - if (typeof Map !== "undefined" && data instanceof Map) { - return ZodParsedType.map; - } - if (typeof Set !== "undefined" && data instanceof Set) { - return ZodParsedType.set; - } - if (typeof Date !== "undefined" && data instanceof Date) { - return ZodParsedType.date; - } - return ZodParsedType.object; - - default: - return ZodParsedType.unknown; - } -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/index.ts deleted file mode 100644 index a9dab5738..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as z from "./external.js"; -export * from "./external.js"; -export { z }; -export default z; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/locales/en.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/locales/en.ts deleted file mode 100644 index 0264f82ef..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/locales/en.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { type ZodErrorMap, ZodIssueCode } from "../ZodError.js"; -import { util, ZodParsedType } from "../helpers/util.js"; - -const errorMap: ZodErrorMap = (issue, _ctx) => { - let message: string; - switch (issue.code) { - case ZodIssueCode.invalid_type: - if (issue.received === ZodParsedType.undefined) { - message = "Required"; - } else { - message = `Expected ${issue.expected}, received ${issue.received}`; - } - break; - case ZodIssueCode.invalid_literal: - message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`; - break; - case ZodIssueCode.unrecognized_keys: - message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, ", ")}`; - break; - case ZodIssueCode.invalid_union: - message = `Invalid input`; - break; - case ZodIssueCode.invalid_union_discriminator: - message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`; - break; - case ZodIssueCode.invalid_enum_value: - message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`; - break; - case ZodIssueCode.invalid_arguments: - message = `Invalid function arguments`; - break; - case ZodIssueCode.invalid_return_type: - message = `Invalid function return type`; - break; - case ZodIssueCode.invalid_date: - message = `Invalid date`; - break; - case ZodIssueCode.invalid_string: - if (typeof issue.validation === "object") { - if ("includes" in issue.validation) { - message = `Invalid input: must include "${issue.validation.includes}"`; - - if (typeof issue.validation.position === "number") { - message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`; - } - } else if ("startsWith" in issue.validation) { - message = `Invalid input: must start with "${issue.validation.startsWith}"`; - } else if ("endsWith" in issue.validation) { - message = `Invalid input: must end with "${issue.validation.endsWith}"`; - } else { - util.assertNever(issue.validation); - } - } else if (issue.validation !== "regex") { - message = `Invalid ${issue.validation}`; - } else { - message = "Invalid"; - } - break; - case ZodIssueCode.too_small: - if (issue.type === "array") - message = `Array must contain ${ - issue.exact ? "exactly" : issue.inclusive ? `at least` : `more than` - } ${issue.minimum} element(s)`; - else if (issue.type === "string") - message = `String must contain ${ - issue.exact ? "exactly" : issue.inclusive ? `at least` : `over` - } ${issue.minimum} character(s)`; - else if (issue.type === "number") - message = `Number must be ${ - issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than ` - }${issue.minimum}`; - else if (issue.type === "bigint") - message = `Number must be ${ - issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than ` - }${issue.minimum}`; - else if (issue.type === "date") - message = `Date must be ${ - issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than ` - }${new Date(Number(issue.minimum))}`; - else message = "Invalid input"; - break; - case ZodIssueCode.too_big: - if (issue.type === "array") - message = `Array must contain ${ - issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than` - } ${issue.maximum} element(s)`; - else if (issue.type === "string") - message = `String must contain ${ - issue.exact ? `exactly` : issue.inclusive ? `at most` : `under` - } ${issue.maximum} character(s)`; - else if (issue.type === "number") - message = `Number must be ${ - issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than` - } ${issue.maximum}`; - else if (issue.type === "bigint") - message = `BigInt must be ${ - issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than` - } ${issue.maximum}`; - else if (issue.type === "date") - message = `Date must be ${ - issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than` - } ${new Date(Number(issue.maximum))}`; - else message = "Invalid input"; - break; - case ZodIssueCode.custom: - message = `Invalid input`; - break; - case ZodIssueCode.invalid_intersection_types: - message = `Intersection results could not be merged`; - break; - case ZodIssueCode.not_multiple_of: - message = `Number must be a multiple of ${issue.multipleOf}`; - break; - case ZodIssueCode.not_finite: - message = "Number must be finite"; - break; - default: - message = _ctx.defaultError; - util.assertNever(issue); - } - return { message }; -}; - -export default errorMap; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/standard-schema.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/standard-schema.ts deleted file mode 100644 index 07193fd13..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/standard-schema.ts +++ /dev/null @@ -1,113 +0,0 @@ -/** - * The Standard Schema interface. - */ -export type StandardSchemaV1 = { - /** - * The Standard Schema properties. - */ - readonly "~standard": StandardSchemaV1.Props; -}; - -export declare namespace StandardSchemaV1 { - /** - * The Standard Schema properties interface. - */ - export interface Props { - /** - * The version number of the standard. - */ - readonly version: 1; - /** - * The vendor name of the schema library. - */ - readonly vendor: string; - /** - * Validates unknown input values. - */ - readonly validate: (value: unknown) => Result | Promise>; - /** - * Inferred types associated with the schema. - */ - readonly types?: Types | undefined; - } - - /** - * The result interface of the validate function. - */ - export type Result = SuccessResult | FailureResult; - - /** - * The result interface if validation succeeds. - */ - export interface SuccessResult { - /** - * The typed output value. - */ - readonly value: Output; - /** - * The non-existent issues. - */ - readonly issues?: undefined; - } - - /** - * The result interface if validation fails. - */ - export interface FailureResult { - /** - * The issues of failed validation. - */ - readonly issues: ReadonlyArray; - } - - /** - * The issue interface of the failure output. - */ - export interface Issue { - /** - * The error message of the issue. - */ - readonly message: string; - /** - * The path of the issue, if any. - */ - readonly path?: ReadonlyArray | undefined; - } - - /** - * The path segment interface of the issue. - */ - export interface PathSegment { - /** - * The key representing a path segment. - */ - readonly key: PropertyKey; - } - - /** - * The Standard Schema types interface. - */ - export interface Types { - /** - * The input type of the schema. - */ - readonly input: Input; - /** - * The output type of the schema. - */ - readonly output: Output; - } - - /** - * Infers the input type of a Standard Schema. - */ - export type InferInput = NonNullable["input"]; - - /** - * Infers the output type of a Standard Schema. - */ - export type InferOutput = NonNullable["output"]; - - // biome-ignore lint/complexity/noUselessEmptyExport: needed for granular visibility control of TS namespace - export {}; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/Mocker.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/Mocker.ts deleted file mode 100644 index c9fbdd51a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/Mocker.ts +++ /dev/null @@ -1,54 +0,0 @@ -function getRandomInt(max: number) { - return Math.floor(Math.random() * Math.floor(max)); -} - -const testSymbol = Symbol("test"); - -export class Mocker { - pick = (...args: any[]): any => { - return args[getRandomInt(args.length)]; - }; - - get string(): string { - return Math.random().toString(36).substring(7); - } - get number(): number { - return Math.random() * 100; - } - get bigint(): bigint { - return BigInt(Math.floor(Math.random() * 10000)); - } - get boolean(): boolean { - return Math.random() < 0.5; - } - get date(): Date { - return new Date(Math.floor(Date.now() * Math.random())); - } - get symbol(): symbol { - return testSymbol; - } - get null(): null { - return null; - } - get undefined(): undefined { - return undefined; - } - get stringOptional(): string | undefined { - return this.pick(this.string, this.undefined); - } - get stringNullable(): string | null { - return this.pick(this.string, this.null); - } - get numberOptional(): number | undefined { - return this.pick(this.number, this.undefined); - } - get numberNullable(): number | null { - return this.pick(this.number, this.null); - } - get booleanOptional(): boolean | undefined { - return this.pick(this.boolean, this.undefined); - } - get booleanNullable(): boolean | null { - return this.pick(this.boolean, this.null); - } -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/all-errors.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/all-errors.test.ts deleted file mode 100644 index 8fdf8f426..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/all-errors.test.ts +++ /dev/null @@ -1,157 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -const Test = z.object({ - f1: z.number(), - f2: z.string().optional(), - f3: z.string().nullable(), - f4: z.array(z.object({ t: z.union([z.string(), z.boolean()]) })), -}); -type TestFlattenedErrors = z.inferFlattenedErrors; -type TestFormErrors = z.inferFlattenedErrors; - -test("default flattened errors type inference", () => { - type TestTypeErrors = { - formErrors: string[]; - fieldErrors: { [P in keyof z.TypeOf]?: string[] | undefined }; - }; - - util.assertEqual, TestTypeErrors>(true); - util.assertEqual, TestTypeErrors>(false); -}); - -test("custom flattened errors type inference", () => { - type ErrorType = { message: string; code: number }; - type TestTypeErrors = { - formErrors: ErrorType[]; - fieldErrors: { - [P in keyof z.TypeOf]?: ErrorType[] | undefined; - }; - }; - - util.assertEqual, TestTypeErrors>(false); - util.assertEqual, TestTypeErrors>(true); - util.assertEqual, TestTypeErrors>(false); -}); - -test("form errors type inference", () => { - type TestTypeErrors = { - formErrors: string[]; - fieldErrors: { [P in keyof z.TypeOf]?: string[] | undefined }; - }; - - util.assertEqual, TestTypeErrors>(true); -}); - -test(".flatten() type assertion", () => { - const parsed = Test.safeParse({}) as z.SafeParseError; - const validFlattenedErrors: TestFlattenedErrors = parsed.error.flatten(() => ({ message: "", code: 0 })); - // @ts-expect-error should fail assertion between `TestFlattenedErrors` and unmapped `flatten()`. - const invalidFlattenedErrors: TestFlattenedErrors = parsed.error.flatten(); - const validFormErrors: TestFormErrors = parsed.error.flatten(); - // @ts-expect-error should fail assertion between `TestFormErrors` and mapped `flatten()`. - const invalidFormErrors: TestFormErrors = parsed.error.flatten(() => ({ - message: "string", - code: 0, - })); - - [validFlattenedErrors, invalidFlattenedErrors, validFormErrors, invalidFormErrors]; -}); - -test(".formErrors type assertion", () => { - const parsed = Test.safeParse({}) as z.SafeParseError; - const validFormErrors: TestFormErrors = parsed.error.formErrors; - // @ts-expect-error should fail assertion between `TestFlattenedErrors` and `.formErrors`. - const invalidFlattenedErrors: TestFlattenedErrors = parsed.error.formErrors; - - [validFormErrors, invalidFlattenedErrors]; -}); - -test("all errors", () => { - const propertySchema = z.string(); - const schema = z - .object({ - a: propertySchema, - b: propertySchema, - }) - .refine( - (val) => { - return val.a === val.b; - }, - { message: "Must be equal" } - ); - - try { - schema.parse({ - a: "asdf", - b: "qwer", - }); - } catch (error) { - if (error instanceof z.ZodError) { - expect(error.flatten()).toEqual({ - formErrors: ["Must be equal"], - fieldErrors: {}, - }); - } - } - - try { - schema.parse({ - a: null, - b: null, - }); - } catch (_error) { - const error = _error as z.ZodError; - expect(error.flatten()).toEqual({ - formErrors: [], - fieldErrors: { - a: ["Expected string, received null"], - b: ["Expected string, received null"], - }, - }); - - expect(error.flatten((iss) => iss.message.toUpperCase())).toEqual({ - formErrors: [], - fieldErrors: { - a: ["EXPECTED STRING, RECEIVED NULL"], - b: ["EXPECTED STRING, RECEIVED NULL"], - }, - }); - // Test identity - - expect(error.flatten((i: z.ZodIssue) => i)).toEqual({ - formErrors: [], - fieldErrors: { - a: [ - { - code: "invalid_type", - expected: "string", - message: "Expected string, received null", - path: ["a"], - received: "null", - }, - ], - b: [ - { - code: "invalid_type", - expected: "string", - message: "Expected string, received null", - path: ["b"], - received: "null", - }, - ], - }, - }); - // Test mapping - expect(error.flatten((i: z.ZodIssue) => i.message.length)).toEqual({ - formErrors: [], - fieldErrors: { - a: ["Expected string, received null".length], - b: ["Expected string, received null".length], - }, - }); - } -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/anyunknown.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/anyunknown.test.ts deleted file mode 100644 index 49d07db2c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/anyunknown.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -test("check any inference", () => { - const t1 = z.any(); - t1.optional(); - t1.nullable(); - type t1 = z.infer; - util.assertEqual(true); -}); - -test("check unknown inference", () => { - const t1 = z.unknown(); - t1.optional(); - t1.nullable(); - type t1 = z.infer; - util.assertEqual(true); -}); - -test("check never inference", () => { - const t1 = z.never(); - expect(() => t1.parse(undefined)).toThrow(); - expect(() => t1.parse("asdf")).toThrow(); - expect(() => t1.parse(null)).toThrow(); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/array.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/array.test.ts deleted file mode 100644 index df5b9d373..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/array.test.ts +++ /dev/null @@ -1,71 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -const minTwo = z.string().array().min(2); -const maxTwo = z.string().array().max(2); -const justTwo = z.string().array().length(2); -const intNum = z.string().array().nonempty(); -const nonEmptyMax = z.string().array().nonempty().max(2); - -type t1 = z.infer; -util.assertEqual<[string, ...string[]], t1>(true); - -type t2 = z.infer; -util.assertEqual(true); - -test("passing validations", () => { - minTwo.parse(["a", "a"]); - minTwo.parse(["a", "a", "a"]); - maxTwo.parse(["a", "a"]); - maxTwo.parse(["a"]); - justTwo.parse(["a", "a"]); - intNum.parse(["a"]); - nonEmptyMax.parse(["a"]); -}); - -test("failing validations", () => { - expect(() => minTwo.parse(["a"])).toThrow(); - expect(() => maxTwo.parse(["a", "a", "a"])).toThrow(); - expect(() => justTwo.parse(["a"])).toThrow(); - expect(() => justTwo.parse(["a", "a", "a"])).toThrow(); - expect(() => intNum.parse([])).toThrow(); - expect(() => nonEmptyMax.parse([])).toThrow(); - expect(() => nonEmptyMax.parse(["a", "a", "a"])).toThrow(); -}); - -test("parse empty array in nonempty", () => { - expect(() => - z - .array(z.string()) - .nonempty() - .parse([] as any) - ).toThrow(); -}); - -test("get element", () => { - justTwo.element.parse("asdf"); - expect(() => justTwo.element.parse(12)).toThrow(); -}); - -test("continue parsing despite array size error", () => { - const schema = z.object({ - people: z.string().array().min(2), - }); - - const result = schema.safeParse({ - people: [123], - }); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues.length).toEqual(2); - } -}); - -test("parse should fail given sparse array", () => { - const schema = z.array(z.string()).nonempty().min(1).max(3); - - expect(() => schema.parse(new Array(3))).toThrow(); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/async-parsing.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/async-parsing.test.ts deleted file mode 100644 index 01dbc4f1e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/async-parsing.test.ts +++ /dev/null @@ -1,388 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -/// string -const stringSchema = z.string(); - -test("string async parse", async () => { - const goodData = "XXX"; - const badData = 12; - - const goodResult = await stringSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await stringSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// number -const numberSchema = z.number(); -test("number async parse", async () => { - const goodData = 1234.2353; - const badData = "1234"; - - const goodResult = await numberSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await numberSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// bigInt -const bigIntSchema = z.bigint(); -test("bigInt async parse", async () => { - const goodData = BigInt(145); - const badData = 134; - - const goodResult = await bigIntSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await bigIntSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// boolean -const booleanSchema = z.boolean(); -test("boolean async parse", async () => { - const goodData = true; - const badData = 1; - - const goodResult = await booleanSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await booleanSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// date -const dateSchema = z.date(); -test("date async parse", async () => { - const goodData = new Date(); - const badData = new Date().toISOString(); - - const goodResult = await dateSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await dateSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// undefined -const undefinedSchema = z.undefined(); -test("undefined async parse", async () => { - const goodData = undefined; - const badData = "XXX"; - - const goodResult = await undefinedSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(undefined); - - const badResult = await undefinedSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// null -const nullSchema = z.null(); -test("null async parse", async () => { - const goodData = null; - const badData = undefined; - - const goodResult = await nullSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await nullSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// any -const anySchema = z.any(); -test("any async parse", async () => { - const goodData = [{}]; - // const badData = 'XXX'; - - const goodResult = await anySchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - // const badResult = await anySchema.safeParseAsync(badData); - // expect(badResult.success).toBe(false); - // if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// unknown -const unknownSchema = z.unknown(); -test("unknown async parse", async () => { - const goodData = ["asdf", 124, () => {}]; - // const badData = 'XXX'; - - const goodResult = await unknownSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - // const badResult = await unknownSchema.safeParseAsync(badData); - // expect(badResult.success).toBe(false); - // if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// void -const voidSchema = z.void(); -test("void async parse", async () => { - const goodData = undefined; - const badData = 0; - - const goodResult = await voidSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await voidSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// array -const arraySchema = z.array(z.string()); -test("array async parse", async () => { - const goodData = ["XXX"]; - const badData = "XXX"; - - const goodResult = await arraySchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await arraySchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// object -const objectSchema = z.object({ string: z.string() }); -test("object async parse", async () => { - const goodData = { string: "XXX" }; - const badData = { string: 12 }; - - const goodResult = await objectSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await objectSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// union -const unionSchema = z.union([z.string(), z.undefined()]); -test("union async parse", async () => { - const goodData = undefined; - const badData = null; - - const goodResult = await unionSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await unionSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// record -const recordSchema = z.record(z.object({})); -test("record async parse", async () => { - const goodData = { adsf: {}, asdf: {} }; - const badData = [{}]; - - const goodResult = await recordSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await recordSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// function -const functionSchema = z.function(); -test("function async parse", async () => { - const goodData = () => {}; - const badData = "XXX"; - - const goodResult = await functionSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(typeof goodResult.data).toEqual("function"); - - const badResult = await functionSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// literal -const literalSchema = z.literal("asdf"); -test("literal async parse", async () => { - const goodData = "asdf"; - const badData = "asdff"; - - const goodResult = await literalSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await literalSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// enum -const enumSchema = z.enum(["fish", "whale"]); -test("enum async parse", async () => { - const goodData = "whale"; - const badData = "leopard"; - - const goodResult = await enumSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await enumSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// nativeEnum -enum nativeEnumTest { - asdf = "qwer", -} -// @ts-ignore -const nativeEnumSchema = z.nativeEnum(nativeEnumTest); -test("nativeEnum async parse", async () => { - const goodData = nativeEnumTest.asdf; - const badData = "asdf"; - - const goodResult = await nativeEnumSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) expect(goodResult.data).toEqual(goodData); - - const badResult = await nativeEnumSchema.safeParseAsync(badData); - expect(badResult.success).toBe(false); - if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); -}); - -/// promise -const promiseSchema = z.promise(z.number()); -test("promise async parse good", async () => { - const goodData = Promise.resolve(123); - - const goodResult = await promiseSchema.safeParseAsync(goodData); - expect(goodResult.success).toBe(true); - if (goodResult.success) { - expect(goodResult.data).toBeInstanceOf(Promise); - const data = await goodResult.data; - expect(data).toEqual(123); - // expect(goodResult.data).resolves.toEqual(124); - // return goodResult.data; - } else { - throw new Error("success should be true"); - } -}); - -test("promise async parse bad", async () => { - const badData = Promise.resolve("XXX"); - const badResult = await promiseSchema.safeParseAsync(badData); - expect(badResult.success).toBe(true); - if (badResult.success) { - await expect(badResult.data).rejects.toBeInstanceOf(z.ZodError); - } else { - throw new Error("success should be true"); - } -}); - -test("async validation non-empty strings", async () => { - const base = z.object({ - hello: z.string().refine((x) => x && x.length > 0), - foo: z.string().refine((x) => x && x.length > 0), - }); - - const testval = { hello: "", foo: "" }; - const result1 = base.safeParse(testval); - const result2 = base.safeParseAsync(testval); - - const r1 = result1; - await result2.then((r2) => { - if (r1.success === false && r2.success === false) expect(r1.error.issues.length).toBe(r2.error.issues.length); // <--- r1 has length 2, r2 has length 1 - }); -}); - -test("async validation multiple errors 1", async () => { - const base = z.object({ - hello: z.string(), - foo: z.number(), - }); - - const testval = { hello: 3, foo: "hello" }; - const result1 = base.safeParse(testval); - const result2 = base.safeParseAsync(testval); - - const r1 = result1; - await result2.then((r2) => { - if (r1.success === false && r2.success === false) expect(r2.error.issues.length).toBe(r1.error.issues.length); - }); -}); - -test("async validation multiple errors 2", async () => { - const base = (is_async?: boolean) => - z.object({ - hello: z.string(), - foo: z.object({ - bar: z.number().refine(is_async ? async () => false : () => false), - }), - }); - - const testval = { hello: 3, foo: { bar: 4 } }; - const result1 = base().safeParse(testval); - const result2 = base(true).safeParseAsync(testval); - - const r1 = result1; - await result2.then((r2) => { - if (r1.success === false && r2.success === false) expect(r2.error.issues.length).toBe(r1.error.issues.length); - }); -}); - -test("ensure early async failure prevents follow-up refinement checks", async () => { - let count = 0; - const base = z.object({ - hello: z.string(), - foo: z - .number() - .refine(async () => { - count++; - return true; - }) - .refine(async () => { - count++; - return true; - }, "Good"), - }); - - const testval = { hello: "bye", foo: 3 }; - const result = await base.safeParseAsync(testval); - if (result.success === false) { - expect(result.error.issues.length).toBe(1); - expect(count).toBe(1); - } - - // await result.then((r) => { - // if (r.success === false) expect(r.error.issues.length).toBe(1); - // expect(count).toBe(2); - // }); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/async-refinements.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/async-refinements.test.ts deleted file mode 100644 index 509475db6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/async-refinements.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -test("parse async test", async () => { - const schema1 = z.string().refine(async (_val) => false); - expect(() => schema1.parse("asdf")).toThrow(); - - const schema2 = z.string().refine((_val) => Promise.resolve(true)); - return await expect(() => schema2.parse("asdf")).toThrow(); -}); - -test("parseAsync async test", async () => { - const schema1 = z.string().refine(async (_val) => true); - await schema1.parseAsync("asdf"); - - const schema2 = z.string().refine(async (_val) => false); - return await expect(schema2.parseAsync("asdf")).rejects.toBeDefined(); - // expect(async () => await schema2.parseAsync('asdf')).toThrow(); -}); - -test("parseAsync async test", async () => { - // expect.assertions(2); - - const schema1 = z.string().refine((_val) => Promise.resolve(true)); - const v1 = await schema1.parseAsync("asdf"); - expect(v1).toEqual("asdf"); - - const schema2 = z.string().refine((_val) => Promise.resolve(false)); - await expect(schema2.parseAsync("asdf")).rejects.toBeDefined(); - - const schema3 = z.string().refine((_val) => Promise.resolve(true)); - await expect(schema3.parseAsync("asdf")).resolves.toEqual("asdf"); - return await expect(schema3.parseAsync("qwer")).resolves.toEqual("qwer"); -}); - -test("parseAsync async with value", async () => { - const schema1 = z.string().refine(async (val) => { - return val.length > 5; - }); - await expect(schema1.parseAsync("asdf")).rejects.toBeDefined(); - - const v = await schema1.parseAsync("asdf123"); - return await expect(v).toEqual("asdf123"); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/base.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/base.test.ts deleted file mode 100644 index ab743d565..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/base.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -test("type guard", () => { - const stringToNumber = z.string().transform((arg) => arg.length); - - const s1 = z.object({ - stringToNumber, - }); - type t1 = z.input; - - const data = { stringToNumber: "asdf" }; - const parsed = s1.safeParse(data); - if (parsed.success) { - util.assertEqual(true); - } -}); - -test("test this binding", () => { - const callback = (predicate: (val: string) => boolean) => { - return predicate("hello"); - }; - - expect(callback((value) => z.string().safeParse(value).success)).toBe(true); // true - expect(callback((value) => z.string().safeParse(value).success)).toBe(true); // true -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/bigint.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/bigint.test.ts deleted file mode 100644 index 9692f5700..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/bigint.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -const gtFive = z.bigint().gt(BigInt(5)); -const gteFive = z.bigint().gte(BigInt(5)); -const ltFive = z.bigint().lt(BigInt(5)); -const lteFive = z.bigint().lte(BigInt(5)); -const positive = z.bigint().positive(); -const negative = z.bigint().negative(); -const nonnegative = z.bigint().nonnegative(); -const nonpositive = z.bigint().nonpositive(); -const multipleOfFive = z.bigint().multipleOf(BigInt(5)); - -test("passing validations", () => { - z.bigint().parse(BigInt(1)); - z.bigint().parse(BigInt(0)); - z.bigint().parse(BigInt(-1)); - gtFive.parse(BigInt(6)); - gteFive.parse(BigInt(5)); - gteFive.parse(BigInt(6)); - ltFive.parse(BigInt(4)); - lteFive.parse(BigInt(5)); - lteFive.parse(BigInt(4)); - positive.parse(BigInt(3)); - negative.parse(BigInt(-2)); - nonnegative.parse(BigInt(0)); - nonnegative.parse(BigInt(7)); - nonpositive.parse(BigInt(0)); - nonpositive.parse(BigInt(-12)); - multipleOfFive.parse(BigInt(15)); -}); - -test("failing validations", () => { - expect(() => gtFive.parse(BigInt(5))).toThrow(); - expect(() => gteFive.parse(BigInt(4))).toThrow(); - expect(() => ltFive.parse(BigInt(5))).toThrow(); - expect(() => lteFive.parse(BigInt(6))).toThrow(); - expect(() => positive.parse(BigInt(0))).toThrow(); - expect(() => positive.parse(BigInt(-2))).toThrow(); - expect(() => negative.parse(BigInt(0))).toThrow(); - expect(() => negative.parse(BigInt(3))).toThrow(); - expect(() => nonnegative.parse(BigInt(-1))).toThrow(); - expect(() => nonpositive.parse(BigInt(1))).toThrow(); - expect(() => multipleOfFive.parse(BigInt(13))).toThrow(); -}); - -test("min max getters", () => { - expect(z.bigint().min(BigInt(5)).minValue).toEqual(BigInt(5)); - expect(z.bigint().min(BigInt(5)).min(BigInt(10)).minValue).toEqual(BigInt(10)); - - expect(z.bigint().max(BigInt(5)).maxValue).toEqual(BigInt(5)); - expect(z.bigint().max(BigInt(5)).max(BigInt(1)).maxValue).toEqual(BigInt(1)); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/branded.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/branded.test.ts deleted file mode 100644 index b19786cf6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/branded.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -// @ts-ignore TS6133 -import { test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -test("branded types", () => { - const mySchema = z - .object({ - name: z.string(), - }) - .brand<"superschema">(); - - // simple branding - type MySchema = z.infer; - util.assertEqual(true); - - const doStuff = (arg: MySchema) => arg; - doStuff(mySchema.parse({ name: "hello there" })); - - // inheritance - const extendedSchema = mySchema.brand<"subschema">(); - type ExtendedSchema = z.infer; - util.assertEqual & z.BRAND<"subschema">>(true); - - doStuff(extendedSchema.parse({ name: "hello again" })); - - // number branding - const numberSchema = z.number().brand<42>(); - type NumberSchema = z.infer; - util.assertEqual(true); - - // symbol branding - const MyBrand: unique symbol = Symbol("hello"); - type MyBrand = typeof MyBrand; - const symbolBrand = z.number().brand<"sup">().brand(); - type SymbolBrand = z.infer; - // number & { [z.BRAND]: { sup: true, [MyBrand]: true } } - util.assertEqual & z.BRAND>(true); - - // keeping brands out of input types - const age = z.number().brand<"age">(); - - type Age = z.infer; - type AgeInput = z.input; - - util.assertEqual(false); - util.assertEqual(true); - util.assertEqual, Age>(true); - - // @ts-expect-error - doStuff({ name: "hello there!" }); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/catch.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/catch.test.ts deleted file mode 100644 index 94d12aa2b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/catch.test.ts +++ /dev/null @@ -1,220 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import { z } from "zod/v3"; -import { util } from "../helpers/util.js"; - -test("basic catch", () => { - expect(z.string().catch("default").parse(undefined)).toBe("default"); -}); - -test("catch fn does not run when parsing succeeds", () => { - let isCalled = false; - const cb = () => { - isCalled = true; - return "asdf"; - }; - expect(z.string().catch(cb).parse("test")).toBe("test"); - expect(isCalled).toEqual(false); -}); - -test("basic catch async", async () => { - const result = await z.string().catch("default").parseAsync(1243); - expect(result).toBe("default"); -}); - -test("catch replace wrong types", () => { - expect(z.string().catch("default").parse(true)).toBe("default"); - expect(z.string().catch("default").parse(true)).toBe("default"); - expect(z.string().catch("default").parse(15)).toBe("default"); - expect(z.string().catch("default").parse([])).toBe("default"); - expect(z.string().catch("default").parse(new Map())).toBe("default"); - expect(z.string().catch("default").parse(new Set())).toBe("default"); - expect(z.string().catch("default").parse({})).toBe("default"); -}); - -test("catch with transform", () => { - const stringWithDefault = z - .string() - .transform((val) => val.toUpperCase()) - .catch("default"); - expect(stringWithDefault.parse(undefined)).toBe("default"); - expect(stringWithDefault.parse(15)).toBe("default"); - expect(stringWithDefault).toBeInstanceOf(z.ZodCatch); - expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodEffects); - expect(stringWithDefault._def.innerType._def.schema).toBeInstanceOf(z.ZodSchema); - - type inp = z.input; - util.assertEqual(true); - type out = z.output; - util.assertEqual(true); -}); - -test("catch on existing optional", () => { - const stringWithDefault = z.string().optional().catch("asdf"); - expect(stringWithDefault.parse(undefined)).toBe(undefined); - expect(stringWithDefault.parse(15)).toBe("asdf"); - expect(stringWithDefault).toBeInstanceOf(z.ZodCatch); - expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodOptional); - expect(stringWithDefault._def.innerType._def.innerType).toBeInstanceOf(z.ZodString); - - type inp = z.input; - util.assertEqual(true); - type out = z.output; - util.assertEqual(true); -}); - -test("optional on catch", () => { - const stringWithDefault = z.string().catch("asdf").optional(); - - type inp = z.input; - util.assertEqual(true); - type out = z.output; - util.assertEqual(true); -}); - -test("complex chain example", () => { - const complex = z - .string() - .catch("asdf") - .transform((val) => val + "!") - .transform((val) => val.toUpperCase()) - .catch("qwer") - .removeCatch() - .optional() - .catch("asdfasdf"); - - expect(complex.parse("qwer")).toBe("QWER!"); - expect(complex.parse(15)).toBe("ASDF!"); - expect(complex.parse(true)).toBe("ASDF!"); -}); - -test("removeCatch", () => { - const stringWithRemovedDefault = z.string().catch("asdf").removeCatch(); - - type out = z.output; - util.assertEqual(true); -}); - -test("nested", () => { - const inner = z.string().catch("asdf"); - const outer = z.object({ inner }).catch({ - inner: "asdf", - }); - type input = z.input; - util.assertEqual(true); - type out = z.output; - util.assertEqual(true); - expect(outer.parse(undefined)).toEqual({ inner: "asdf" }); - expect(outer.parse({})).toEqual({ inner: "asdf" }); - expect(outer.parse({ inner: undefined })).toEqual({ inner: "asdf" }); -}); - -test("chained catch", () => { - const stringWithDefault = z.string().catch("inner").catch("outer"); - const result = stringWithDefault.parse(undefined); - expect(result).toEqual("inner"); - const resultDiff = stringWithDefault.parse(5); - expect(resultDiff).toEqual("inner"); -}); - -test("factory", () => { - z.ZodCatch.create(z.string(), { - catch: "asdf", - }).parse(undefined); -}); - -test("native enum", () => { - enum Fruits { - apple = "apple", - orange = "orange", - } - - const schema = z.object({ - fruit: z.nativeEnum(Fruits).catch(Fruits.apple), - }); - - expect(schema.parse({})).toEqual({ fruit: Fruits.apple }); - expect(schema.parse({ fruit: 15 })).toEqual({ fruit: Fruits.apple }); -}); - -test("enum", () => { - const schema = z.object({ - fruit: z.enum(["apple", "orange"]).catch("apple"), - }); - - expect(schema.parse({})).toEqual({ fruit: "apple" }); - expect(schema.parse({ fruit: true })).toEqual({ fruit: "apple" }); - expect(schema.parse({ fruit: 15 })).toEqual({ fruit: "apple" }); -}); - -test("reported issues with nested usage", () => { - const schema = z.object({ - string: z.string(), - obj: z.object({ - sub: z.object({ - lit: z.literal("a"), - subCatch: z.number().catch(23), - }), - midCatch: z.number().catch(42), - }), - number: z.number().catch(0), - bool: z.boolean(), - }); - - try { - schema.parse({ - string: {}, - obj: { - sub: { - lit: "b", - subCatch: "24", - }, - midCatch: 444, - }, - number: "", - bool: "yes", - }); - } catch (error) { - const issues = (error as z.ZodError).issues; - - expect(issues.length).toEqual(3); - expect(issues[0].message).toMatch("string"); - expect(issues[1].message).toMatch("literal"); - expect(issues[2].message).toMatch("boolean"); - } -}); - -test("catch error", () => { - let catchError: z.ZodError | undefined = undefined; - - const schema = z.object({ - age: z.number(), - name: z.string().catch((ctx) => { - catchError = ctx.error; - - return "John Doe"; - }), - }); - - const result = schema.safeParse({ - age: null, - name: null, - }); - - expect(result.success).toEqual(false); - expect(!result.success && result.error.issues.length).toEqual(1); - expect(!result.success && result.error.issues[0].message).toMatch("number"); - - expect(catchError).toBeInstanceOf(z.ZodError); - expect(catchError !== undefined && (catchError as z.ZodError).issues.length).toEqual(1); - expect(catchError !== undefined && (catchError as z.ZodError).issues[0].message).toMatch("string"); -}); - -test("ctx.input", () => { - const schema = z.string().catch((ctx) => { - return String(ctx.input); - }); - - expect(schema.parse(123)).toEqual("123"); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/coerce.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/coerce.test.ts deleted file mode 100644 index 1f5300416..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/coerce.test.ts +++ /dev/null @@ -1,133 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -test("string coercion", () => { - const schema = z.coerce.string(); - expect(schema.parse("sup")).toEqual("sup"); - expect(schema.parse("")).toEqual(""); - expect(schema.parse(12)).toEqual("12"); - expect(schema.parse(0)).toEqual("0"); - expect(schema.parse(-12)).toEqual("-12"); - expect(schema.parse(3.14)).toEqual("3.14"); - expect(schema.parse(BigInt(15))).toEqual("15"); - expect(schema.parse(Number.NaN)).toEqual("NaN"); - expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual("Infinity"); - expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual("-Infinity"); - expect(schema.parse(true)).toEqual("true"); - expect(schema.parse(false)).toEqual("false"); - expect(schema.parse(null)).toEqual("null"); - expect(schema.parse(undefined)).toEqual("undefined"); - expect(schema.parse({ hello: "world!" })).toEqual("[object Object]"); - expect(schema.parse(["item", "another_item"])).toEqual("item,another_item"); - expect(schema.parse([])).toEqual(""); - expect(schema.parse(new Date("2022-01-01T00:00:00.000Z"))).toEqual(new Date("2022-01-01T00:00:00.000Z").toString()); -}); - -test("number coercion", () => { - const schema = z.coerce.number(); - expect(schema.parse("12")).toEqual(12); - expect(schema.parse("0")).toEqual(0); - expect(schema.parse("-12")).toEqual(-12); - expect(schema.parse("3.14")).toEqual(3.14); - expect(schema.parse("")).toEqual(0); - expect(() => schema.parse("NOT_A_NUMBER")).toThrow(); // z.ZodError - expect(schema.parse(12)).toEqual(12); - expect(schema.parse(0)).toEqual(0); - expect(schema.parse(-12)).toEqual(-12); - expect(schema.parse(3.14)).toEqual(3.14); - expect(schema.parse(BigInt(15))).toEqual(15); - expect(() => schema.parse(Number.NaN)).toThrow(); // z.ZodError - expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual(Number.POSITIVE_INFINITY); - expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual(Number.NEGATIVE_INFINITY); - expect(schema.parse(true)).toEqual(1); - expect(schema.parse(false)).toEqual(0); - expect(schema.parse(null)).toEqual(0); - expect(() => schema.parse(undefined)).toThrow(); // z.ZodError - expect(() => schema.parse({ hello: "world!" })).toThrow(); // z.ZodError - expect(() => schema.parse(["item", "another_item"])).toThrow(); // z.ZodError - expect(schema.parse([])).toEqual(0); - expect(schema.parse(new Date(1670139203496))).toEqual(1670139203496); -}); - -test("boolean coercion", () => { - const schema = z.coerce.boolean(); - expect(schema.parse("true")).toEqual(true); - expect(schema.parse("false")).toEqual(true); - expect(schema.parse("0")).toEqual(true); - expect(schema.parse("1")).toEqual(true); - expect(schema.parse("")).toEqual(false); - expect(schema.parse(1)).toEqual(true); - expect(schema.parse(0)).toEqual(false); - expect(schema.parse(-1)).toEqual(true); - expect(schema.parse(3.14)).toEqual(true); - expect(schema.parse(BigInt(15))).toEqual(true); - expect(schema.parse(Number.NaN)).toEqual(false); - expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual(true); - expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual(true); - expect(schema.parse(true)).toEqual(true); - expect(schema.parse(false)).toEqual(false); - expect(schema.parse(null)).toEqual(false); - expect(schema.parse(undefined)).toEqual(false); - expect(schema.parse({ hello: "world!" })).toEqual(true); - expect(schema.parse(["item", "another_item"])).toEqual(true); - expect(schema.parse([])).toEqual(true); - expect(schema.parse(new Date(1670139203496))).toEqual(true); -}); - -test("bigint coercion", () => { - const schema = z.coerce.bigint(); - expect(schema.parse("5")).toEqual(BigInt(5)); - expect(schema.parse("0")).toEqual(BigInt(0)); - expect(schema.parse("-5")).toEqual(BigInt(-5)); - expect(() => schema.parse("3.14")).toThrow(); // not a z.ZodError! - expect(schema.parse("")).toEqual(BigInt(0)); - expect(() => schema.parse("NOT_A_NUMBER")).toThrow(); // not a z.ZodError! - expect(schema.parse(5)).toEqual(BigInt(5)); - expect(schema.parse(0)).toEqual(BigInt(0)); - expect(schema.parse(-5)).toEqual(BigInt(-5)); - expect(() => schema.parse(3.14)).toThrow(); // not a z.ZodError! - expect(schema.parse(BigInt(5))).toEqual(BigInt(5)); - expect(() => schema.parse(Number.NaN)).toThrow(); // not a z.ZodError! - expect(() => schema.parse(Number.POSITIVE_INFINITY)).toThrow(); // not a z.ZodError! - expect(() => schema.parse(Number.NEGATIVE_INFINITY)).toThrow(); // not a z.ZodError! - expect(schema.parse(true)).toEqual(BigInt(1)); - expect(schema.parse(false)).toEqual(BigInt(0)); - expect(() => schema.parse(null)).toThrow(); // not a z.ZodError! - expect(() => schema.parse(undefined)).toThrow(); // not a z.ZodError! - expect(() => schema.parse({ hello: "world!" })).toThrow(); // not a z.ZodError! - expect(() => schema.parse(["item", "another_item"])).toThrow(); // not a z.ZodError! - expect(schema.parse([])).toEqual(BigInt(0)); - expect(schema.parse(new Date(1670139203496))).toEqual(BigInt(1670139203496)); -}); - -test("date coercion", () => { - const schema = z.coerce.date(); - expect(schema.parse(new Date().toDateString())).toBeInstanceOf(Date); - expect(schema.parse(new Date().toISOString())).toBeInstanceOf(Date); - expect(schema.parse(new Date().toUTCString())).toBeInstanceOf(Date); - expect(schema.parse("5")).toBeInstanceOf(Date); - expect(schema.parse("2000-01-01")).toBeInstanceOf(Date); - // expect(schema.parse("0")).toBeInstanceOf(Date); - // expect(schema.parse("-5")).toBeInstanceOf(Date); - // expect(schema.parse("3.14")).toBeInstanceOf(Date); - expect(() => schema.parse("")).toThrow(); // z.ZodError - expect(() => schema.parse("NOT_A_DATE")).toThrow(); // z.ZodError - expect(schema.parse(5)).toBeInstanceOf(Date); - expect(schema.parse(0)).toBeInstanceOf(Date); - expect(schema.parse(-5)).toBeInstanceOf(Date); - expect(schema.parse(3.14)).toBeInstanceOf(Date); - expect(() => schema.parse(BigInt(5))).toThrow(); // not a z.ZodError! - expect(() => schema.parse(Number.NaN)).toThrow(); // z.ZodError - expect(() => schema.parse(Number.POSITIVE_INFINITY)).toThrow(); // z.ZodError - expect(() => schema.parse(Number.NEGATIVE_INFINITY)).toThrow(); // z.ZodError - expect(schema.parse(true)).toBeInstanceOf(Date); - expect(schema.parse(false)).toBeInstanceOf(Date); - expect(schema.parse(null)).toBeInstanceOf(Date); - expect(() => schema.parse(undefined)).toThrow(); // z.ZodError - expect(() => schema.parse({ hello: "world!" })).toThrow(); // z.ZodError - expect(() => schema.parse(["item", "another_item"])).toThrow(); // z.ZodError - expect(() => schema.parse([])).toThrow(); // z.ZodError - expect(schema.parse(new Date())).toBeInstanceOf(Date); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/complex.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/complex.test.ts deleted file mode 100644 index 1d0303320..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/complex.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { expect, test } from "vitest"; -import * as z from "zod/v3"; - -const crazySchema = z.object({ - tuple: z.tuple([ - z.string().nullable().optional(), - z.number().nullable().optional(), - z.boolean().nullable().optional(), - z.null().nullable().optional(), - z.undefined().nullable().optional(), - z.literal("1234").nullable().optional(), - ]), - merged: z - .object({ - k1: z.string().optional(), - }) - .merge(z.object({ k1: z.string().nullable(), k2: z.number() })), - union: z.array(z.union([z.literal("asdf"), z.literal(12)])).nonempty(), - array: z.array(z.number()), - // sumTransformer: z.transformer(z.array(z.number()), z.number(), (arg) => { - // return arg.reduce((a, b) => a + b, 0); - // }), - sumMinLength: z.array(z.number()).refine((arg) => arg.length > 5), - intersection: z.intersection(z.object({ p1: z.string().optional() }), z.object({ p1: z.number().optional() })), - enum: z.intersection(z.enum(["zero", "one"]), z.enum(["one", "two"])), - nonstrict: z.object({ points: z.number() }).nonstrict(), - numProm: z.promise(z.number()), - lenfun: z.function(z.tuple([z.string()]), z.boolean()), -}); - -// const asyncCrazySchema = crazySchema.extend({ -// // async_transform: z.transformer( -// // z.array(z.number()), -// // z.number(), -// // async (arg) => { -// // return arg.reduce((a, b) => a + b, 0); -// // } -// // ), -// async_refine: z.array(z.number()).refine(async (arg) => arg.length > 5), -// }); - -test("parse", () => { - const input = { - tuple: ["asdf", 1234, true, null, undefined, "1234"], - merged: { k1: "asdf", k2: 12 }, - union: ["asdf", 12, "asdf", 12, "asdf", 12], - array: [12, 15, 16], - // sumTransformer: [12, 15, 16], - sumMinLength: [12, 15, 16, 98, 24, 63], - intersection: {}, - enum: "one", - nonstrict: { points: 1234 }, - numProm: Promise.resolve(12), - lenfun: (x: string) => x.length, - }; - - const result = crazySchema.parse(input); - - // Verify the parsed result structure - expect(result.tuple).toEqual(input.tuple); - expect(result.merged).toEqual(input.merged); - expect(result.union).toEqual(input.union); - expect(result.array).toEqual(input.array); - expect(result.sumMinLength).toEqual(input.sumMinLength); - expect(result.intersection).toEqual(input.intersection); - expect(result.enum).toEqual(input.enum); - expect(result.nonstrict).toEqual(input.nonstrict); - expect(result.numProm).toBeInstanceOf(Promise); - expect(typeof result.lenfun).toBe("function"); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/custom.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/custom.test.ts deleted file mode 100644 index b24b6762d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/custom.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -test("passing validations", () => { - const example1 = z.custom((x) => typeof x === "number"); - example1.parse(1234); - expect(() => example1.parse({})).toThrow(); -}); - -test("string params", () => { - const example1 = z.custom((x) => typeof x !== "number", "customerr"); - const result = example1.safeParse(1234); - expect(result.success).toEqual(false); - // @ts-ignore - expect(JSON.stringify(result.error).includes("customerr")).toEqual(true); -}); - -test("async validations", async () => { - const example1 = z.custom(async (x) => { - return typeof x === "number"; - }); - const r1 = await example1.safeParseAsync(1234); - expect(r1.success).toEqual(true); - expect(r1.data).toEqual(1234); - - const r2 = await example1.safeParseAsync("asdf"); - expect(r2.success).toEqual(false); - expect(r2.error!.issues.length).toEqual(1); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/date.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/date.test.ts deleted file mode 100644 index c86dc84fc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/date.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -const beforeBenchmarkDate = new Date(2022, 10, 4); -const benchmarkDate = new Date(2022, 10, 5); -const afterBenchmarkDate = new Date(2022, 10, 6); - -const minCheck = z.date().min(benchmarkDate); -const maxCheck = z.date().max(benchmarkDate); - -test("passing validations", () => { - minCheck.parse(benchmarkDate); - minCheck.parse(afterBenchmarkDate); - - maxCheck.parse(benchmarkDate); - maxCheck.parse(beforeBenchmarkDate); -}); - -test("failing validations", () => { - expect(() => minCheck.parse(beforeBenchmarkDate)).toThrow(); - expect(() => maxCheck.parse(afterBenchmarkDate)).toThrow(); -}); - -test("min max getters", () => { - expect(minCheck.minDate).toEqual(benchmarkDate); - expect(minCheck.min(afterBenchmarkDate).minDate).toEqual(afterBenchmarkDate); - - expect(maxCheck.maxDate).toEqual(benchmarkDate); - expect(maxCheck.max(beforeBenchmarkDate).maxDate).toEqual(beforeBenchmarkDate); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/deepmasking.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/deepmasking.test.ts deleted file mode 100644 index d707e79a0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/deepmasking.test.ts +++ /dev/null @@ -1,186 +0,0 @@ -// @ts-ignore TS6133 -import { test } from "vitest"; - -import * as z from "zod/v3"; - -test("test", () => { - z; -}); - -// const fish = z.object({ -// name: z.string(), -// props: z.object({ -// color: z.string(), -// numScales: z.number(), -// }), -// }); - -// const nonStrict = z -// .object({ -// name: z.string(), -// color: z.string(), -// }) -// .nonstrict(); - -// test('object pick type', () => { -// const modNonStrictFish = nonStrict.omit({ name: true }); -// modNonStrictFish.parse({ color: 'asdf' }); - -// const bad1 = () => fish.pick({ props: { unknown: true } } as any); -// const bad2 = () => fish.omit({ name: true, props: { unknown: true } } as any); - -// expect(bad1).toThrow(); -// expect(bad2).toThrow(); -// }); - -// test('f1', () => { -// const f1 = fish.pick(true); -// f1.parse({ name: 'a', props: { color: 'b', numScales: 3 } }); -// }); -// test('f2', () => { -// const f2 = fish.pick({ props: true }); -// f2.parse({ props: { color: 'asdf', numScales: 1 } }); -// const badcheck2 = () => f2.parse({ name: 'a', props: { color: 'b', numScales: 3 } } as any); -// expect(badcheck2).toThrow(); -// }); -// test('f3', () => { -// const f3 = fish.pick({ props: { color: true } }); -// f3.parse({ props: { color: 'b' } }); -// const badcheck3 = () => f3.parse({ name: 'a', props: { color: 'b', numScales: 3 } } as any); -// expect(badcheck3).toThrow(); -// }); -// test('f4', () => { -// const badcheck4 = () => fish.pick({ props: { color: true, unknown: true } }); -// expect(badcheck4).toThrow(); -// }); -// test('f6', () => { -// const f6 = fish.omit({ props: true }); -// const badcheck6 = () => f6.parse({ name: 'a', props: { color: 'b', numScales: 3 } } as any); -// f6.parse({ name: 'adsf' }); -// expect(badcheck6).toThrow(); -// }); -// test('f7', () => { -// const f7 = fish.omit({ props: { color: true } }); -// f7.parse({ name: 'a', props: { numScales: 3 } }); -// const badcheck7 = () => f7.parse({ name: 'a', props: { color: 'b', numScales: 3 } } as any); -// expect(badcheck7).toThrow(); -// }); -// test('f8', () => { -// const badcheck8 = () => fish.omit({ props: { color: true, unknown: true } }); -// expect(badcheck8).toThrow(); -// }); -// test('f9', () => { -// const f9 = nonStrict.pick(true); -// f9.parse({ name: 'a', color: 'asdf' }); -// }); -// test('f10', () => { -// const f10 = nonStrict.pick({ name: true }); -// f10.parse({ name: 'a' }); -// const val = f10.parse({ name: 'a', color: 'b' }); -// expect(val).toEqual({ name: 'a' }); -// }); -// test('f12', () => { -// const badfcheck12 = () => nonStrict.omit({ color: true, asdf: true }); -// expect(badfcheck12).toThrow(); -// }); - -// test('array masking', () => { -// const fishArray = z.array(fish); -// const modFishArray = fishArray.pick({ -// name: true, -// props: { -// numScales: true, -// }, -// }); - -// modFishArray.parse([{ name: 'fish', props: { numScales: 12 } }]); -// const bad1 = () => modFishArray.parse([{ name: 'fish', props: { numScales: 12, color: 'asdf' } }] as any); -// expect(bad1).toThrow(); -// }); - -// test('array masking', () => { -// const fishArray = z.array(fish); -// const fail = () => -// fishArray.pick({ -// name: true, -// props: { -// whatever: true, -// }, -// } as any); -// expect(fail).toThrow(); -// }); - -// test('array masking', () => { -// const fishArray = z.array(fish); -// const fail = () => -// fishArray.omit({ -// whateve: true, -// } as any); -// expect(fail).toThrow(); -// }); - -// test('array masking', () => { -// const fishArray = z.array(fish); -// const modFishList = fishArray.omit({ -// name: true, -// props: { -// color: true, -// }, -// }); - -// modFishList.parse([{ props: { numScales: 12 } }]); -// const fail = () => modFishList.parse([{ name: 'hello', props: { numScales: 12 } }] as any); -// expect(fail).toThrow(); -// }); - -// test('primitive array masking', () => { -// const fishArray = z.array(z.number()); -// const fail = () => fishArray.pick({} as any); -// expect(fail).toThrow(); -// }); - -// test('other array masking', () => { -// const fishArray = z.array(z.array(z.number())); -// const fail = () => fishArray.pick({} as any); -// expect(fail).toThrow(); -// }); - -// test('invalid mask #1', () => { -// const fail = () => fish.pick(1 as any); -// expect(fail).toThrow(); -// }); - -// test('invalid mask #2', () => { -// const fail = () => fish.pick([] as any); -// expect(fail).toThrow(); -// }); - -// test('invalid mask #3', () => { -// const fail = () => fish.pick(false as any); -// expect(fail).toThrow(); -// }); - -// test('invalid mask #4', () => { -// const fail = () => fish.pick('asdf' as any); -// expect(fail).toThrow(); -// }); - -// test('invalid mask #5', () => { -// const fail = () => fish.omit(1 as any); -// expect(fail).toThrow(); -// }); - -// test('invalid mask #6', () => { -// const fail = () => fish.omit([] as any); -// expect(fail).toThrow(); -// }); - -// test('invalid mask #7', () => { -// const fail = () => fish.omit(false as any); -// expect(fail).toThrow(); -// }); - -// test('invalid mask #8', () => { -// const fail = () => fish.omit('asdf' as any); -// expect(fail).toThrow(); -// }); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/default.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/default.test.ts deleted file mode 100644 index 29e007c93..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/default.test.ts +++ /dev/null @@ -1,112 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import { z } from "zod/v3"; -import { util } from "../helpers/util.js"; - -test("basic defaults", () => { - expect(z.string().default("default").parse(undefined)).toBe("default"); -}); - -test("default with transform", () => { - const stringWithDefault = z - .string() - .transform((val) => val.toUpperCase()) - .default("default"); - expect(stringWithDefault.parse(undefined)).toBe("DEFAULT"); - expect(stringWithDefault).toBeInstanceOf(z.ZodDefault); - expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodEffects); - expect(stringWithDefault._def.innerType._def.schema).toBeInstanceOf(z.ZodSchema); - - type inp = z.input; - util.assertEqual(true); - type out = z.output; - util.assertEqual(true); -}); - -test("default on existing optional", () => { - const stringWithDefault = z.string().optional().default("asdf"); - expect(stringWithDefault.parse(undefined)).toBe("asdf"); - expect(stringWithDefault).toBeInstanceOf(z.ZodDefault); - expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodOptional); - expect(stringWithDefault._def.innerType._def.innerType).toBeInstanceOf(z.ZodString); - - type inp = z.input; - util.assertEqual(true); - type out = z.output; - util.assertEqual(true); -}); - -test("optional on default", () => { - const stringWithDefault = z.string().default("asdf").optional(); - - type inp = z.input; - util.assertEqual(true); - type out = z.output; - util.assertEqual(true); -}); - -test("complex chain example", () => { - const complex = z - .string() - .default("asdf") - .transform((val) => val.toUpperCase()) - .default("qwer") - .removeDefault() - .optional() - .default("asdfasdf"); - - expect(complex.parse(undefined)).toBe("ASDFASDF"); -}); - -test("removeDefault", () => { - const stringWithRemovedDefault = z.string().default("asdf").removeDefault(); - - type out = z.output; - util.assertEqual(true); -}); - -test("nested", () => { - const inner = z.string().default("asdf"); - const outer = z.object({ inner }).default({ - inner: undefined, - }); - type input = z.input; - util.assertEqual(true); - type out = z.output; - util.assertEqual(true); - expect(outer.parse(undefined)).toEqual({ inner: "asdf" }); - expect(outer.parse({})).toEqual({ inner: "asdf" }); - expect(outer.parse({ inner: undefined })).toEqual({ inner: "asdf" }); -}); - -test("chained defaults", () => { - const stringWithDefault = z.string().default("inner").default("outer"); - const result = stringWithDefault.parse(undefined); - expect(result).toEqual("outer"); -}); - -test("factory", () => { - expect(z.ZodDefault.create(z.string(), { default: "asdf" }).parse(undefined)).toEqual("asdf"); -}); - -test("native enum", () => { - enum Fruits { - apple = "apple", - orange = "orange", - } - - const schema = z.object({ - fruit: z.nativeEnum(Fruits).default(Fruits.apple), - }); - - expect(schema.parse({})).toEqual({ fruit: Fruits.apple }); -}); - -test("enum", () => { - const schema = z.object({ - fruit: z.enum(["apple", "orange"]).default("apple"), - }); - - expect(schema.parse({})).toEqual({ fruit: "apple" }); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/description.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/description.test.ts deleted file mode 100644 index 1edaa1cc2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/description.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -const description = "a description"; - -test("passing `description` to schema should add a description", () => { - expect(z.string({ description }).description).toEqual(description); - expect(z.number({ description }).description).toEqual(description); - expect(z.boolean({ description }).description).toEqual(description); -}); - -test("`.describe` should add a description", () => { - expect(z.string().describe(description).description).toEqual(description); - expect(z.number().describe(description).description).toEqual(description); - expect(z.boolean().describe(description).description).toEqual(description); -}); - -test("description should carry over to chained schemas", () => { - const schema = z.string({ description }); - expect(schema.description).toEqual(description); - expect(schema.optional().description).toEqual(description); - expect(schema.optional().nullable().default("default").description).toEqual(description); -}); - -test("description should not carry over to chained array schema", () => { - const schema = z.string().describe(description); - - expect(schema.description).toEqual(description); - expect(schema.array().description).toEqual(undefined); - expect(z.array(schema).description).toEqual(undefined); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/discriminated-unions.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/discriminated-unions.test.ts deleted file mode 100644 index 7fb5cfefe..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/discriminated-unions.test.ts +++ /dev/null @@ -1,315 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -test("valid", () => { - expect( - z - .discriminatedUnion("type", [ - z.object({ type: z.literal("a"), a: z.string() }), - z.object({ type: z.literal("b"), b: z.string() }), - ]) - .parse({ type: "a", a: "abc" }) - ).toEqual({ type: "a", a: "abc" }); -}); - -test("valid - discriminator value of various primitive types", () => { - const schema = z.discriminatedUnion("type", [ - z.object({ type: z.literal("1"), val: z.literal(1) }), - z.object({ type: z.literal(1), val: z.literal(2) }), - z.object({ type: z.literal(BigInt(1)), val: z.literal(3) }), - z.object({ type: z.literal("true"), val: z.literal(4) }), - z.object({ type: z.literal(true), val: z.literal(5) }), - z.object({ type: z.literal("null"), val: z.literal(6) }), - z.object({ type: z.literal(null), val: z.literal(7) }), - z.object({ type: z.literal("undefined"), val: z.literal(8) }), - z.object({ type: z.literal(undefined), val: z.literal(9) }), - z.object({ type: z.literal("transform"), val: z.literal(10) }), - z.object({ type: z.literal("refine"), val: z.literal(11) }), - z.object({ type: z.literal("superRefine"), val: z.literal(12) }), - ]); - - expect(schema.parse({ type: "1", val: 1 })).toEqual({ type: "1", val: 1 }); - expect(schema.parse({ type: 1, val: 2 })).toEqual({ type: 1, val: 2 }); - expect(schema.parse({ type: BigInt(1), val: 3 })).toEqual({ - type: BigInt(1), - val: 3, - }); - expect(schema.parse({ type: "true", val: 4 })).toEqual({ - type: "true", - val: 4, - }); - expect(schema.parse({ type: true, val: 5 })).toEqual({ - type: true, - val: 5, - }); - expect(schema.parse({ type: "null", val: 6 })).toEqual({ - type: "null", - val: 6, - }); - expect(schema.parse({ type: null, val: 7 })).toEqual({ - type: null, - val: 7, - }); - expect(schema.parse({ type: "undefined", val: 8 })).toEqual({ - type: "undefined", - val: 8, - }); - expect(schema.parse({ type: undefined, val: 9 })).toEqual({ - type: undefined, - val: 9, - }); -}); - -test("invalid - null", () => { - try { - z.discriminatedUnion("type", [ - z.object({ type: z.literal("a"), a: z.string() }), - z.object({ type: z.literal("b"), b: z.string() }), - ]).parse(null); - throw new Error(); - } catch (e: any) { - expect(JSON.parse(e.message)).toEqual([ - { - code: z.ZodIssueCode.invalid_type, - expected: z.ZodParsedType.object, - message: "Expected object, received null", - received: z.ZodParsedType.null, - path: [], - }, - ]); - } -}); - -test("invalid discriminator value", () => { - try { - z.discriminatedUnion("type", [ - z.object({ type: z.literal("a"), a: z.string() }), - z.object({ type: z.literal("b"), b: z.string() }), - ]).parse({ type: "x", a: "abc" }); - throw new Error(); - } catch (e: any) { - expect(JSON.parse(e.message)).toEqual([ - { - code: z.ZodIssueCode.invalid_union_discriminator, - options: ["a", "b"], - message: "Invalid discriminator value. Expected 'a' | 'b'", - path: ["type"], - }, - ]); - } -}); - -test("valid discriminator value, invalid data", () => { - try { - z.discriminatedUnion("type", [ - z.object({ type: z.literal("a"), a: z.string() }), - z.object({ type: z.literal("b"), b: z.string() }), - ]).parse({ type: "a", b: "abc" }); - throw new Error(); - } catch (e: any) { - expect(JSON.parse(e.message)).toEqual([ - { - code: z.ZodIssueCode.invalid_type, - expected: z.ZodParsedType.string, - message: "Required", - path: ["a"], - received: z.ZodParsedType.undefined, - }, - ]); - } -}); - -test("wrong schema - missing discriminator", () => { - try { - z.discriminatedUnion("type", [ - z.object({ type: z.literal("a"), a: z.string() }), - z.object({ b: z.string() }) as any, - ]); - throw new Error(); - } catch (e: any) { - expect(e.message.includes("could not be extracted")).toBe(true); - } -}); - -test("wrong schema - duplicate discriminator values", () => { - try { - z.discriminatedUnion("type", [ - z.object({ type: z.literal("a"), a: z.string() }), - z.object({ type: z.literal("a"), b: z.string() }), - ]); - throw new Error(); - } catch (e: any) { - expect(e.message.includes("has duplicate value")).toEqual(true); - } -}); - -test("async - valid", async () => { - expect( - await z - .discriminatedUnion("type", [ - z.object({ - type: z.literal("a"), - a: z - .string() - .refine(async () => true) - .transform(async (val) => Number(val)), - }), - z.object({ - type: z.literal("b"), - b: z.string(), - }), - ]) - .parseAsync({ type: "a", a: "1" }) - ).toEqual({ type: "a", a: 1 }); -}); - -test("async - invalid", async () => { - try { - await z - .discriminatedUnion("type", [ - z.object({ - type: z.literal("a"), - a: z - .string() - .refine(async () => true) - .transform(async (val) => val), - }), - z.object({ - type: z.literal("b"), - b: z.string(), - }), - ]) - .parseAsync({ type: "a", a: 1 }); - throw new Error(); - } catch (e: any) { - expect(JSON.parse(e.message)).toEqual([ - { - code: "invalid_type", - expected: "string", - received: "number", - path: ["a"], - message: "Expected string, received number", - }, - ]); - } -}); - -test("valid - literals with .default or .preprocess", () => { - const schema = z.discriminatedUnion("type", [ - z.object({ - type: z.literal("foo").default("foo"), - a: z.string(), - }), - z.object({ - type: z.literal("custom"), - method: z.string(), - }), - z.object({ - type: z.preprocess((val) => String(val), z.literal("bar")), - c: z.string(), - }), - ]); - expect(schema.parse({ type: "foo", a: "foo" })).toEqual({ - type: "foo", - a: "foo", - }); -}); - -test("enum and nativeEnum", () => { - enum MyEnum { - d = 0, - e = "e", - } - - const schema = z.discriminatedUnion("key", [ - z.object({ - key: z.literal("a"), - // Add other properties specific to this option - }), - z.object({ - key: z.enum(["b", "c"]), - // Add other properties specific to this option - }), - z.object({ - key: z.nativeEnum(MyEnum), - // Add other properties specific to this option - }), - ]); - - // type schema = z.infer; - - schema.parse({ key: "a" }); - schema.parse({ key: "b" }); - schema.parse({ key: "c" }); - schema.parse({ key: MyEnum.d }); - schema.parse({ key: MyEnum.e }); - schema.parse({ key: "e" }); -}); - -test("branded", () => { - const schema = z.discriminatedUnion("key", [ - z.object({ - key: z.literal("a"), - // Add other properties specific to this option - }), - z.object({ - key: z.literal("b").brand("asdfaf"), - // Add other properties specific to this option - }), - ]); - - // type schema = z.infer; - - schema.parse({ key: "a" }); - schema.parse({ key: "b" }); - expect(() => { - schema.parse({ key: "c" }); - }).toThrow(); -}); - -test("optional and nullable", () => { - const schema = z.discriminatedUnion("key", [ - z.object({ - key: z.literal("a").optional(), - a: z.literal(true), - }), - z.object({ - key: z.literal("b").nullable(), - b: z.literal(true), - // Add other properties specific to this option - }), - ]); - - type schema = z.infer; - z.util.assertEqual(true); - - schema.parse({ key: "a", a: true }); - schema.parse({ key: undefined, a: true }); - schema.parse({ key: "b", b: true }); - schema.parse({ key: null, b: true }); - expect(() => { - schema.parse({ key: null, a: true }); - }).toThrow(); - expect(() => { - schema.parse({ key: "b", a: true }); - }).toThrow(); - - const value = schema.parse({ key: null, b: true }); - - if (!("key" in value)) value.a; - if (value.key === undefined) value.a; - if (value.key === "a") value.a; - if (value.key === "b") value.b; - if (value.key === null) value.b; -}); - -test("readonly array of options", () => { - const options = [ - z.object({ type: z.literal("x"), val: z.literal(1) }), - z.object({ type: z.literal("y"), val: z.literal(2) }), - ] as const; - - expect(z.discriminatedUnion("type", options).parse({ type: "x", val: 1 })).toEqual({ type: "x", val: 1 }); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/enum.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/enum.test.ts deleted file mode 100644 index 53f4a3e84..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/enum.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -test("create enum", () => { - const MyEnum = z.enum(["Red", "Green", "Blue"]); - expect(MyEnum.Values.Red).toEqual("Red"); - expect(MyEnum.Enum.Red).toEqual("Red"); - expect(MyEnum.enum.Red).toEqual("Red"); -}); - -test("infer enum", () => { - const MyEnum = z.enum(["Red", "Green", "Blue"]); - type MyEnum = z.infer; - util.assertEqual(true); -}); - -test("get options", () => { - expect(z.enum(["tuna", "trout"]).options).toEqual(["tuna", "trout"]); -}); - -test("readonly enum", () => { - const HTTP_SUCCESS = ["200", "201"] as const; - const arg = z.enum(HTTP_SUCCESS); - type arg = z.infer; - util.assertEqual(true); - - arg.parse("201"); - expect(() => arg.parse("202")).toThrow(); -}); - -test("error params", () => { - const result = z.enum(["test"], { required_error: "REQUIRED" }).safeParse(undefined); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].message).toEqual("REQUIRED"); - } -}); - -test("extract/exclude", () => { - const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"] as const; - const FoodEnum = z.enum(foods); - const ItalianEnum = FoodEnum.extract(["Pasta", "Pizza"]); - const UnhealthyEnum = FoodEnum.exclude(["Salad"]); - const EmptyFoodEnum = FoodEnum.exclude(foods); - - util.assertEqual, "Pasta" | "Pizza">(true); - util.assertEqual, "Pasta" | "Pizza" | "Tacos" | "Burgers">(true); - // @ts-expect-error TS2344 - util.assertEqual>(true); - util.assertEqual, never>(true); -}); - -test("error map in extract/exclude", () => { - const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"] as const; - const FoodEnum = z.enum(foods, { - errorMap: () => ({ message: "This is not food!" }), - }); - const ItalianEnum = FoodEnum.extract(["Pasta", "Pizza"]); - const foodsError = FoodEnum.safeParse("Cucumbers"); - const italianError = ItalianEnum.safeParse("Tacos"); - if (!foodsError.success && !italianError.success) { - expect(foodsError.error.issues[0].message).toEqual(italianError.error.issues[0].message); - } - - const UnhealthyEnum = FoodEnum.exclude(["Salad"], { - errorMap: () => ({ message: "This is not healthy food!" }), - }); - const unhealthyError = UnhealthyEnum.safeParse("Salad"); - if (!unhealthyError.success) { - expect(unhealthyError.error.issues[0].message).toEqual("This is not healthy food!"); - } -}); - -test("readonly in ZodEnumDef", () => { - let _t!: z.ZodEnumDef; - _t; -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/error.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/error.test.ts deleted file mode 100644 index 5caaa6d81..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/error.test.ts +++ /dev/null @@ -1,551 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { ZodError, ZodIssueCode } from "../ZodError.js"; -import { ZodParsedType } from "../helpers/util.js"; - -test("error creation", () => { - const err1 = ZodError.create([]); - err1.addIssue({ - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.object, - received: ZodParsedType.string, - path: [], - message: "", - fatal: true, - }); - err1.isEmpty; - - const err2 = ZodError.create(err1.issues); - const err3 = new ZodError([]); - err3.addIssues(err1.issues); - err3.addIssue(err1.issues[0]); - err1.message; - err2.message; - err3.message; -}); - -const errorMap: z.ZodErrorMap = (error, ctx) => { - if (error.code === ZodIssueCode.invalid_type) { - if (error.expected === "string") { - return { message: "bad type!" }; - } - } - if (error.code === ZodIssueCode.custom) { - return { message: `less-than-${error.params?.minimum}` }; - } - return { message: ctx.defaultError }; -}; - -test("type error with custom error map", () => { - try { - z.string().parse(234, { errorMap }); - } catch (err) { - const zerr: z.ZodError = err as any; - - expect(zerr.issues[0].code).toEqual(z.ZodIssueCode.invalid_type); - expect(zerr.issues[0].message).toEqual(`bad type!`); - } -}); - -test("refinement fail with params", () => { - try { - z.number() - .refine((val) => val >= 3, { - params: { minimum: 3 }, - }) - .parse(2, { errorMap }); - } catch (err) { - const zerr: z.ZodError = err as any; - expect(zerr.issues[0].code).toEqual(z.ZodIssueCode.custom); - expect(zerr.issues[0].message).toEqual(`less-than-3`); - } -}); - -test("custom error with custom errormap", () => { - try { - z.string() - .refine((val) => val.length > 12, { - params: { minimum: 13 }, - message: "override", - }) - .parse("asdf", { errorMap }); - } catch (err) { - const zerr: z.ZodError = err as any; - expect(zerr.issues[0].message).toEqual("override"); - } -}); - -test("default error message", () => { - try { - z.number() - .refine((x) => x > 3) - .parse(2); - } catch (err) { - const zerr: z.ZodError = err as any; - expect(zerr.issues.length).toEqual(1); - expect(zerr.issues[0].message).toEqual("Invalid input"); - } -}); - -test("override error in refine", () => { - try { - z.number() - .refine((x) => x > 3, "override") - .parse(2); - } catch (err) { - const zerr: z.ZodError = err as any; - expect(zerr.issues.length).toEqual(1); - expect(zerr.issues[0].message).toEqual("override"); - } -}); - -test("override error in refinement", () => { - try { - z.number() - .refine((x) => x > 3, { - message: "override", - }) - .parse(2); - } catch (err) { - const zerr: z.ZodError = err as any; - expect(zerr.issues.length).toEqual(1); - expect(zerr.issues[0].message).toEqual("override"); - } -}); - -test("array minimum", () => { - try { - z.array(z.string()).min(3, "tooshort").parse(["asdf", "qwer"]); - } catch (err) { - const zerr: ZodError = err as any; - expect(zerr.issues[0].code).toEqual(ZodIssueCode.too_small); - expect(zerr.issues[0].message).toEqual("tooshort"); - } - try { - z.array(z.string()).min(3).parse(["asdf", "qwer"]); - } catch (err) { - const zerr: ZodError = err as any; - expect(zerr.issues[0].code).toEqual(ZodIssueCode.too_small); - expect(zerr.issues[0].message).toEqual(`Array must contain at least 3 element(s)`); - } -}); - -// implement test for semi-smart union logic that checks for type error on either left or right -// test("union smart errors", () => { -// // expect.assertions(2); - -// const p1 = z -// .union([z.string(), z.number().refine((x) => x > 0)]) -// .safeParse(-3.2); - -// if (p1.success === true) throw new Error(); -// expect(p1.success).toBe(false); -// expect(p1.error.issues[0].code).toEqual(ZodIssueCode.custom); - -// const p2 = z.union([z.string(), z.number()]).safeParse(false); -// // .catch(err => expect(err.issues[0].code).toEqual(ZodIssueCode.invalid_union)); -// if (p2.success === true) throw new Error(); -// expect(p2.success).toBe(false); -// expect(p2.error.issues[0].code).toEqual(ZodIssueCode.invalid_union); -// }); - -test("custom path in custom error map", () => { - const schema = z.object({ - items: z.array(z.string()).refine((data) => data.length > 3, { - path: ["items-too-few"], - }), - }); - - const errorMap: z.ZodErrorMap = (error) => { - expect(error.path.length).toBe(2); - return { message: "doesnt matter" }; - }; - const result = schema.safeParse({ items: ["first"] }, { errorMap }); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].path).toEqual(["items", "items-too-few"]); - } -}); - -test("error metadata from value", () => { - const dynamicRefine = z.string().refine( - (val) => val === val.toUpperCase(), - (val) => ({ params: { val } }) - ); - - const result = dynamicRefine.safeParse("asdf"); - expect(result.success).toEqual(false); - if (!result.success) { - const sub = result.error.issues[0]; - expect(result.error.issues[0].code).toEqual("custom"); - if (sub.code === "custom") { - expect(sub.params!.val).toEqual("asdf"); - } - } -}); - -// test("don't call refine after validation failed", () => { -// const asdf = z -// .union([ -// z.number(), -// z.string().transform(z.number(), (val) => { -// return parseFloat(val); -// }), -// ]) -// .refine((v) => v >= 1); - -// expect(() => asdf.safeParse("foo")).not.toThrow(); -// }); - -test("root level formatting", () => { - const schema = z.string().email(); - const result = schema.safeParse("asdfsdf"); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.format()._errors).toEqual(["Invalid email"]); - } -}); - -test("custom path", () => { - const schema = z - .object({ - password: z.string(), - confirm: z.string(), - }) - .refine((val) => val.confirm === val.password, { path: ["confirm"] }); - - const result = schema.safeParse({ - password: "peanuts", - confirm: "qeanuts", - }); - - expect(result.success).toEqual(false); - if (!result.success) { - // nested errors - const error = result.error.format(); - expect(error._errors).toEqual([]); - expect(error.password?._errors).toEqual(undefined); - expect(error.confirm?._errors).toEqual(["Invalid input"]); - } -}); - -test("custom path", () => { - const schema = z - .object({ - password: z.string().min(6), - confirm: z.string().min(6), - }) - .refine((val) => val.confirm === val.password); - - const result = schema.safeParse({ - password: "qwer", - confirm: "asdf", - }); - - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues.length).toEqual(3); - } -}); - -const schema = z.object({ - inner: z.object({ - name: z - .string() - .refine((val) => val.length > 5) - .array() - .refine((val) => val.length <= 1), - }), -}); - -test("no abort early on refinements", () => { - const invalidItem = { - inner: { name: ["aasd", "asdfasdfasfd"] }, - }; - - const result1 = schema.safeParse(invalidItem); - expect(result1.success).toEqual(false); - if (!result1.success) { - expect(result1.error.issues.length).toEqual(2); - } -}); -test("formatting", () => { - const invalidItem = { - inner: { name: ["aasd", "asdfasdfasfd"] }, - }; - const invalidArray = { - inner: { name: ["asdfasdf", "asdfasdfasfd"] }, - }; - const result1 = schema.safeParse(invalidItem); - const result2 = schema.safeParse(invalidArray); - - expect(result1.success).toEqual(false); - expect(result2.success).toEqual(false); - if (!result1.success) { - const error = result1.error.format(); - - expect(error._errors).toEqual([]); - expect(error.inner?._errors).toEqual([]); - // expect(error.inner?.name?._errors).toEqual(["Invalid input"]); - // expect(error.inner?.name?.[0]._errors).toEqual(["Invalid input"]); - expect(error.inner?.name?.[1]).toEqual(undefined); - } - if (!result2.success) { - type FormattedError = z.inferFormattedError; - const error: FormattedError = result2.error.format(); - expect(error._errors).toEqual([]); - expect(error.inner?._errors).toEqual([]); - expect(error.inner?.name?._errors).toEqual(["Invalid input"]); - expect(error.inner?.name?.[0]).toEqual(undefined); - expect(error.inner?.name?.[1]).toEqual(undefined); - expect(error.inner?.name?.[2]).toEqual(undefined); - } - - // test custom mapper - if (!result2.success) { - type FormattedError = z.inferFormattedError; - const error: FormattedError = result2.error.format(() => 5); - expect(error._errors).toEqual([]); - expect(error.inner?._errors).toEqual([]); - expect(error.inner?.name?._errors).toEqual([5]); - } -}); - -test("formatting with nullable and optional fields", () => { - const nameSchema = z.string().refine((val) => val.length > 5); - const schema = z.object({ - nullableObject: z.object({ name: nameSchema }).nullable(), - nullableArray: z.array(nameSchema).nullable(), - nullableTuple: z.tuple([nameSchema, nameSchema, z.number()]).nullable(), - optionalObject: z.object({ name: nameSchema }).optional(), - optionalArray: z.array(nameSchema).optional(), - optionalTuple: z.tuple([nameSchema, nameSchema, z.number()]).optional(), - }); - const invalidItem = { - nullableObject: { name: "abcd" }, - nullableArray: ["abcd"], - nullableTuple: ["abcd", "abcd", 1], - optionalObject: { name: "abcd" }, - optionalArray: ["abcd"], - optionalTuple: ["abcd", "abcd", 1], - }; - const result = schema.safeParse(invalidItem); - expect(result.success).toEqual(false); - if (!result.success) { - type FormattedError = z.inferFormattedError; - const error: FormattedError = result.error.format(); - expect(error._errors).toEqual([]); - expect(error.nullableObject?._errors).toEqual([]); - expect(error.nullableObject?.name?._errors).toEqual(["Invalid input"]); - expect(error.nullableArray?._errors).toEqual([]); - expect(error.nullableArray?.[0]?._errors).toEqual(["Invalid input"]); - expect(error.nullableTuple?._errors).toEqual([]); - expect(error.nullableTuple?.[0]?._errors).toEqual(["Invalid input"]); - expect(error.nullableTuple?.[1]?._errors).toEqual(["Invalid input"]); - expect(error.optionalObject?._errors).toEqual([]); - expect(error.optionalObject?.name?._errors).toEqual(["Invalid input"]); - expect(error.optionalArray?._errors).toEqual([]); - expect(error.optionalArray?.[0]?._errors).toEqual(["Invalid input"]); - expect(error.optionalTuple?._errors).toEqual([]); - expect(error.optionalTuple?.[0]?._errors).toEqual(["Invalid input"]); - expect(error.optionalTuple?.[1]?._errors).toEqual(["Invalid input"]); - } -}); - -const stringWithCustomError = z.string({ - errorMap: (issue, ctx) => ({ - message: issue.code === "invalid_type" ? (ctx.data ? "Invalid name" : "Name is required") : ctx.defaultError, - }), -}); - -test("schema-bound error map", () => { - const result = stringWithCustomError.safeParse(1234); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].message).toEqual("Invalid name"); - } - - const result2 = stringWithCustomError.safeParse(undefined); - expect(result2.success).toEqual(false); - if (!result2.success) { - expect(result2.error.issues[0].message).toEqual("Name is required"); - } - - // support contextual override - const result3 = stringWithCustomError.safeParse(undefined, { - errorMap: () => ({ message: "OVERRIDE" }), - }); - expect(result3.success).toEqual(false); - if (!result3.success) { - expect(result3.error.issues[0].message).toEqual("OVERRIDE"); - } -}); - -test("overrideErrorMap", () => { - // support overrideErrorMap - z.setErrorMap(() => ({ message: "OVERRIDE" })); - const result4 = stringWithCustomError.min(10).safeParse("tooshort"); - expect(result4.success).toEqual(false); - if (!result4.success) { - expect(result4.error.issues[0].message).toEqual("OVERRIDE"); - } - z.setErrorMap(z.defaultErrorMap); -}); - -test("invalid and required", () => { - const str = z.string({ - invalid_type_error: "Invalid name", - required_error: "Name is required", - }); - const result1 = str.safeParse(1234); - expect(result1.success).toEqual(false); - if (!result1.success) { - expect(result1.error.issues[0].message).toEqual("Invalid name"); - } - const result2 = str.safeParse(undefined); - expect(result2.success).toEqual(false); - if (!result2.success) { - expect(result2.error.issues[0].message).toEqual("Name is required"); - } -}); - -test("Fallback to default required error", () => { - const str = z.string({ - invalid_type_error: "Invalid name", - // required_error: "Name is required", - }); - - const result2 = str.safeParse(undefined); - expect(result2.success).toEqual(false); - if (!result2.success) { - expect(result2.error.issues[0].message).toEqual("Required"); - } -}); - -test("invalid and required and errorMap", () => { - expect(() => { - return z.string({ - invalid_type_error: "Invalid name", - required_error: "Name is required", - errorMap: () => ({ message: "OVERRIDE" }), - }); - }).toThrow(); -}); - -test("strict error message", () => { - const errorMsg = "Invalid object"; - const obj = z.object({ x: z.string() }).strict(errorMsg); - const result = obj.safeParse({ x: "a", y: "b" }); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].message).toEqual(errorMsg); - } -}); - -test("enum error message, invalid enum elementstring", () => { - try { - z.enum(["Tuna", "Trout"]).parse("Salmon"); - } catch (err) { - const zerr: z.ZodError = err as any; - expect(zerr.issues.length).toEqual(1); - expect(zerr.issues[0].message).toEqual("Invalid enum value. Expected 'Tuna' | 'Trout', received 'Salmon'"); - } -}); - -test("enum error message, invalid type", () => { - try { - z.enum(["Tuna", "Trout"]).parse(12); - } catch (err) { - const zerr: z.ZodError = err as any; - expect(zerr.issues.length).toEqual(1); - expect(zerr.issues[0].message).toEqual("Expected 'Tuna' | 'Trout', received number"); - } -}); - -test("nativeEnum default error message", () => { - enum Fish { - Tuna = "Tuna", - Trout = "Trout", - } - try { - z.nativeEnum(Fish).parse("Salmon"); - } catch (err) { - const zerr: z.ZodError = err as any; - expect(zerr.issues.length).toEqual(1); - expect(zerr.issues[0].message).toEqual("Invalid enum value. Expected 'Tuna' | 'Trout', received 'Salmon'"); - } -}); - -test("literal default error message", () => { - try { - z.literal("Tuna").parse("Trout"); - } catch (err) { - const zerr: z.ZodError = err as any; - expect(zerr.issues.length).toEqual(1); - expect(zerr.issues[0].message).toEqual(`Invalid literal value, expected "Tuna"`); - } -}); - -test("literal bigint default error message", () => { - try { - z.literal(BigInt(12)).parse(BigInt(13)); - } catch (err) { - const zerr: z.ZodError = err as any; - expect(zerr.issues.length).toEqual(1); - expect(zerr.issues[0].message).toEqual(`Invalid literal value, expected "12"`); - } -}); - -test("enum with message returns the custom error message", () => { - const schema = z.enum(["apple", "banana"], { - message: "the value provided is invalid", - }); - - const result1 = schema.safeParse("berries"); - expect(result1.success).toEqual(false); - if (!result1.success) { - expect(result1.error.issues[0].message).toEqual("the value provided is invalid"); - } - - const result2 = schema.safeParse(undefined); - expect(result2.success).toEqual(false); - if (!result2.success) { - expect(result2.error.issues[0].message).toEqual("the value provided is invalid"); - } - - const result3 = schema.safeParse("banana"); - expect(result3.success).toEqual(true); - - const result4 = schema.safeParse(null); - expect(result4.success).toEqual(false); - if (!result4.success) { - expect(result4.error.issues[0].message).toEqual("the value provided is invalid"); - } -}); - -test("when the message is falsy, it is used as is provided", () => { - const schema = z.string().max(1, { message: "" }); - const result = schema.safeParse("asdf"); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].message).toEqual(""); - } -}); - -// test("dont short circuit on continuable errors", () => { -// const user = z -// .object({ -// password: z.string().min(6), -// confirm: z.string(), -// }) -// .refine((data) => data.password === data.confirm, { -// message: "Passwords don't match", -// path: ["confirm"], -// }); -// const result = user.safeParse({ password: "asdf", confirm: "qwer" }); -// if (!result.success) { -// expect(result.error.issues.length).toEqual(2); -// } -// }); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/firstparty.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/firstparty.test.ts deleted file mode 100644 index 017a1c13e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/firstparty.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -// @ts-ignore TS6133 -import { test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -test("first party switch", () => { - const myType = z.string() as z.ZodFirstPartySchemaTypes; - const def = myType._def; - - switch (def.typeName) { - case z.ZodFirstPartyTypeKind.ZodString: - break; - case z.ZodFirstPartyTypeKind.ZodNumber: - break; - case z.ZodFirstPartyTypeKind.ZodNaN: - break; - case z.ZodFirstPartyTypeKind.ZodBigInt: - break; - case z.ZodFirstPartyTypeKind.ZodBoolean: - break; - case z.ZodFirstPartyTypeKind.ZodDate: - break; - case z.ZodFirstPartyTypeKind.ZodUndefined: - break; - case z.ZodFirstPartyTypeKind.ZodNull: - break; - case z.ZodFirstPartyTypeKind.ZodAny: - break; - case z.ZodFirstPartyTypeKind.ZodUnknown: - break; - case z.ZodFirstPartyTypeKind.ZodNever: - break; - case z.ZodFirstPartyTypeKind.ZodVoid: - break; - case z.ZodFirstPartyTypeKind.ZodArray: - break; - case z.ZodFirstPartyTypeKind.ZodObject: - break; - case z.ZodFirstPartyTypeKind.ZodUnion: - break; - case z.ZodFirstPartyTypeKind.ZodDiscriminatedUnion: - break; - case z.ZodFirstPartyTypeKind.ZodIntersection: - break; - case z.ZodFirstPartyTypeKind.ZodTuple: - break; - case z.ZodFirstPartyTypeKind.ZodRecord: - break; - case z.ZodFirstPartyTypeKind.ZodMap: - break; - case z.ZodFirstPartyTypeKind.ZodSet: - break; - case z.ZodFirstPartyTypeKind.ZodFunction: - break; - case z.ZodFirstPartyTypeKind.ZodLazy: - break; - case z.ZodFirstPartyTypeKind.ZodLiteral: - break; - case z.ZodFirstPartyTypeKind.ZodEnum: - break; - case z.ZodFirstPartyTypeKind.ZodEffects: - break; - case z.ZodFirstPartyTypeKind.ZodNativeEnum: - break; - case z.ZodFirstPartyTypeKind.ZodOptional: - break; - case z.ZodFirstPartyTypeKind.ZodNullable: - break; - case z.ZodFirstPartyTypeKind.ZodDefault: - break; - case z.ZodFirstPartyTypeKind.ZodCatch: - break; - case z.ZodFirstPartyTypeKind.ZodPromise: - break; - case z.ZodFirstPartyTypeKind.ZodBranded: - break; - case z.ZodFirstPartyTypeKind.ZodPipeline: - break; - case z.ZodFirstPartyTypeKind.ZodSymbol: - break; - case z.ZodFirstPartyTypeKind.ZodReadonly: - break; - default: - util.assertNever(def); - } -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/firstpartyschematypes.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/firstpartyschematypes.test.ts deleted file mode 100644 index ad397d8b8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/firstpartyschematypes.test.ts +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-ignore TS6133 -import { test } from "vitest"; - -import type { ZodFirstPartySchemaTypes, ZodFirstPartyTypeKind } from "zod/v3"; -import { util } from "../helpers/util.js"; - -test("Identify missing [ZodFirstPartySchemaTypes]", () => { - type ZodFirstPartySchemaForType = ZodFirstPartySchemaTypes extends infer Schema - ? Schema extends { _def: { typeName: T } } - ? Schema - : never - : never; - type ZodMappedTypes = { - [key in ZodFirstPartyTypeKind]: ZodFirstPartySchemaForType; - }; - type ZodFirstPartySchemaTypesMissingFromUnion = keyof { - [key in keyof ZodMappedTypes as ZodMappedTypes[key] extends { _def: never } ? key : never]: unknown; - }; - - util.assertEqual(true); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/function.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/function.test.ts deleted file mode 100644 index 9a9e193bf..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/function.test.ts +++ /dev/null @@ -1,261 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -const args1 = z.tuple([z.string()]); -const returns1 = z.number(); -const func1 = z.function(args1, returns1); - -test("function parsing", () => { - const parsed = func1.parse((arg: any) => arg.length); - const result = parsed("asdf"); - expect(result).toBe(4); -}); - -test("parsed function fail 1", () => { - const parsed = func1.parse((x: string) => x); - expect(() => parsed("asdf")).toThrow(); -}); - -test("parsed function fail 2", () => { - const parsed = func1.parse((x: string) => x); - expect(() => parsed(13 as any)).toThrow(); -}); - -test("function inference 1", () => { - type func1 = z.TypeOf; - util.assertEqual number>(true); -}); - -test("method parsing", () => { - const methodObject = z.object({ - property: z.number(), - method: z.function().args(z.string()).returns(z.number()), - }); - const methodInstance = { - property: 3, - method: function (s: string) { - return s.length + this.property; - }, - }; - const parsed = methodObject.parse(methodInstance); - expect(parsed.method("length=8")).toBe(11); // 8 length + 3 property -}); - -test("async method parsing", async () => { - const methodObject = z.object({ - property: z.number(), - method: z.function().args(z.string()).returns(z.promise(z.number())), - }); - const methodInstance = { - property: 3, - method: async function (s: string) { - return s.length + this.property; - }, - }; - const parsed = methodObject.parse(methodInstance); - expect(await parsed.method("length=8")).toBe(11); // 8 length + 3 property -}); - -test("args method", () => { - const t1 = z.function(); - type t1 = z.infer; - util.assertEqual unknown>(true); - - const t2 = t1.args(z.string()); - type t2 = z.infer; - util.assertEqual unknown>(true); - - const t3 = t2.returns(z.boolean()); - type t3 = z.infer; - util.assertEqual boolean>(true); -}); - -const args2 = z.tuple([ - z.object({ - f1: z.number(), - f2: z.string().nullable(), - f3: z.array(z.boolean().optional()).optional(), - }), -]); -const returns2 = z.union([z.string(), z.number()]); - -const func2 = z.function(args2, returns2); - -test("function inference 2", () => { - type func2 = z.TypeOf; - util.assertEqual< - func2, - (arg: { - f1: number; - f2: string | null; - f3?: (boolean | undefined)[] | undefined; - }) => string | number - >(true); -}); - -test("valid function run", () => { - const validFunc2Instance = func2.validate((_x) => { - return "adf" as any; - }); - - const checker = () => { - validFunc2Instance({ - f1: 21, - f2: "asdf", - f3: [true, false], - }); - }; - - checker(); -}); - -test("input validation error", () => { - const invalidFuncInstance = func2.validate((_x) => { - return "adf" as any; - }); - - const checker = () => { - invalidFuncInstance("Invalid_input" as any); - }; - - expect(checker).toThrow(); -}); - -test("output validation error", () => { - const invalidFuncInstance = func2.validate((_x) => { - return ["this", "is", "not", "valid", "output"] as any; - }); - - const checker = () => { - invalidFuncInstance({ - f1: 21, - f2: "asdf", - f3: [true, false], - }); - }; - - expect(checker).toThrow(); -}); - -z.function(z.tuple([z.string()])).args()._def.args; - -test("special function error codes", () => { - const checker = z.function(z.tuple([z.string()]), z.boolean()).implement((arg) => { - return arg.length as any; - }); - try { - checker("12" as any); - } catch (err) { - const zerr = err as z.ZodError; - const first = zerr.issues[0]; - if (first.code !== z.ZodIssueCode.invalid_return_type) throw new Error(); - - expect(first.returnTypeError).toBeInstanceOf(z.ZodError); - } - - try { - checker(12 as any); - } catch (err) { - const zerr = err as z.ZodError; - const first = zerr.issues[0]; - if (first.code !== z.ZodIssueCode.invalid_arguments) throw new Error(); - expect(first.argumentsError).toBeInstanceOf(z.ZodError); - } -}); - -test("function with async refinements", async () => { - const func = z - .function() - .args(z.string().refine(async (val) => val.length > 10)) - .returns(z.promise(z.number().refine(async (val) => val > 10))) - .implement(async (val) => { - return val.length; - }); - const results = []; - try { - await func("asdfasdf"); - results.push("success"); - } catch (_err) { - results.push("fail"); - } - try { - await func("asdflkjasdflkjsf"); - results.push("success"); - } catch (_err) { - results.push("fail"); - } - - expect(results).toEqual(["fail", "success"]); -}); - -test("non async function with async refinements should fail", async () => { - const func = z - .function() - .args(z.string().refine(async (val) => val.length > 10)) - .returns(z.number().refine(async (val) => val > 10)) - .implement((val) => { - return val.length; - }); - - const results = []; - try { - await func("asdasdfasdffasdf"); - results.push("success"); - } catch (_err) { - results.push("fail"); - } - - expect(results).toEqual(["fail"]); -}); - -test("allow extra parameters", () => { - const maxLength5 = z - .function() - .args(z.string()) - .returns(z.boolean()) - .implement((str, _arg, _qewr) => { - return str.length <= 5; - }); - - const filteredList = ["apple", "orange", "pear", "banana", "strawberry"].filter(maxLength5); - expect(filteredList.length).toEqual(2); -}); - -test("params and returnType getters", () => { - const func = z.function().args(z.string()).returns(z.string()); - - const paramResult = func.parameters().items[0].parse("asdf"); - expect(paramResult).toBe("asdf"); - - const returnResult = func.returnType().parse("asdf"); - expect(returnResult).toBe("asdf"); -}); - -test("inference with transforms", () => { - const funcSchema = z - .function() - .args(z.string().transform((val) => val.length)) - .returns(z.object({ val: z.number() })); - const myFunc = funcSchema.implement((val) => { - return { val, extra: "stuff" }; - }); - myFunc("asdf"); - - util.assertEqual { val: number; extra: string }>(true); -}); - -test("fallback to OuterTypeOfFunction", () => { - const funcSchema = z - .function() - .args(z.string().transform((val) => val.length)) - .returns(z.object({ arg: z.number() }).transform((val) => val.arg)); - - const myFunc = funcSchema.implement((val) => { - return { arg: val, arg2: false }; - }); - - util.assertEqual number>(true); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/generics.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/generics.test.ts deleted file mode 100644 index e0af470f0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/generics.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -test("generics", () => { - async function stripOuter(schema: TData, data: unknown) { - return z - .object({ - nested: schema, // as z.ZodTypeAny, - }) - .transform((data) => { - return data.nested!; - }) - .parse({ nested: data }); - } - - const result = stripOuter(z.object({ a: z.string() }), { a: "asdf" }); - util.assertEqual>(true); -}); - -// test("assignability", () => { -// const createSchemaAndParse = ( -// key: K, -// valueSchema: VS, -// data: unknown -// ) => { -// const schema = z.object({ -// [key]: valueSchema, -// } as { [k in K]: VS }); -// return { [key]: valueSchema }; -// const parsed = schema.parse(data); -// return parsed; -// // const inferred: z.infer> = parsed; -// // return inferred; -// }; -// const parsed = createSchemaAndParse("foo", z.string(), { foo: "" }); -// util.assertEqual(true); -// }); - -test("nested no undefined", () => { - const inner = z.string().or(z.array(z.string())); - const outer = z.object({ inner }); - type outerSchema = z.infer; - z.util.assertEqual(true); - expect(outer.safeParse({ inner: undefined }).success).toEqual(false); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/instanceof.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/instanceof.test.ts deleted file mode 100644 index de66f3f09..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/instanceof.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -test("instanceof", async () => { - class Test {} - class Subtest extends Test {} - abstract class AbstractBar { - constructor(public val: string) {} - } - class Bar extends AbstractBar {} - - const TestSchema = z.instanceof(Test); - const SubtestSchema = z.instanceof(Subtest); - const AbstractSchema = z.instanceof(AbstractBar); - const BarSchema = z.instanceof(Bar); - - TestSchema.parse(new Test()); - TestSchema.parse(new Subtest()); - SubtestSchema.parse(new Subtest()); - AbstractSchema.parse(new Bar("asdf")); - const bar = BarSchema.parse(new Bar("asdf")); - expect(bar.val).toEqual("asdf"); - - await expect(() => SubtestSchema.parse(new Test())).toThrow(/Input not instance of Subtest/); - await expect(() => TestSchema.parse(12)).toThrow(/Input not instance of Test/); - - util.assertEqual>(true); -}); - -test("instanceof fatal", () => { - const schema = z.instanceof(Date).refine((d) => d.toString()); - const res = schema.safeParse(null); - expect(res.success).toBe(false); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/intersection.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/intersection.test.ts deleted file mode 100644 index 6d7936c19..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/intersection.test.ts +++ /dev/null @@ -1,110 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -test("object intersection", () => { - const BaseTeacher = z.object({ - subjects: z.array(z.string()), - }); - const HasID = z.object({ id: z.string() }); - - const Teacher = z.intersection(BaseTeacher.passthrough(), HasID); // BaseTeacher.merge(HasID); - const data = { - subjects: ["math"], - id: "asdfasdf", - }; - expect(Teacher.parse(data)).toEqual(data); - expect(() => Teacher.parse({ subject: data.subjects })).toThrow(); - expect(Teacher.parse({ ...data, extra: 12 })).toEqual({ ...data, extra: 12 }); - - expect(() => z.intersection(BaseTeacher.strict(), HasID).parse({ ...data, extra: 12 })).toThrow(); -}); - -test("deep intersection", () => { - const Animal = z.object({ - properties: z.object({ - is_animal: z.boolean(), - }), - }); - const Cat = z - .object({ - properties: z.object({ - jumped: z.boolean(), - }), - }) - .and(Animal); - - type _Cat = z.infer; - // const cat:Cat = 'asdf' as any; - const cat = Cat.parse({ properties: { is_animal: true, jumped: true } }); - expect(cat.properties).toEqual({ is_animal: true, jumped: true }); -}); - -test("deep intersection of arrays", async () => { - const Author = z.object({ - posts: z.array( - z.object({ - post_id: z.number(), - }) - ), - }); - const Registry = z - .object({ - posts: z.array( - z.object({ - title: z.string(), - }) - ), - }) - .and(Author); - - const posts = [ - { post_id: 1, title: "Novels" }, - { post_id: 2, title: "Fairy tales" }, - ]; - const cat = Registry.parse({ posts }); - expect(cat.posts).toEqual(posts); - const asyncCat = await Registry.parseAsync({ posts }); - expect(asyncCat.posts).toEqual(posts); -}); - -test("invalid intersection types", async () => { - const numberIntersection = z.intersection( - z.number(), - z.number().transform((x) => x + 1) - ); - - const syncResult = numberIntersection.safeParse(1234); - expect(syncResult.success).toEqual(false); - if (!syncResult.success) { - expect(syncResult.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_intersection_types); - } - - const asyncResult = await numberIntersection.spa(1234); - expect(asyncResult.success).toEqual(false); - if (!asyncResult.success) { - expect(asyncResult.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_intersection_types); - } -}); - -test("invalid array merge", async () => { - const stringArrInt = z.intersection( - z.string().array(), - z - .string() - .array() - .transform((val) => [...val, "asdf"]) - ); - const syncResult = stringArrInt.safeParse(["asdf", "qwer"]); - expect(syncResult.success).toEqual(false); - if (!syncResult.success) { - expect(syncResult.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_intersection_types); - } - - const asyncResult = await stringArrInt.spa(["asdf", "qwer"]); - expect(asyncResult.success).toEqual(false); - if (!asyncResult.success) { - expect(asyncResult.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_intersection_types); - } -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/language-server.source.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/language-server.source.ts deleted file mode 100644 index cbe818bb3..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/language-server.source.ts +++ /dev/null @@ -1,76 +0,0 @@ -import * as z from "zod/v3"; - -export const filePath = __filename; - -// z.object() - -export const Test = z.object({ - f1: z.number(), -}); - -export type Test = z.infer; - -export const instanceOfTest: Test = { - f1: 1, -}; - -// z.object().merge() - -export const TestMerge = z - .object({ - f2: z.string().optional(), - }) - .merge(Test); - -export type TestMerge = z.infer; - -export const instanceOfTestMerge: TestMerge = { - f1: 1, - f2: "string", -}; - -// z.union() - -export const TestUnion = z.union([ - z.object({ - f2: z.string().optional(), - }), - Test, -]); - -export type TestUnion = z.infer; - -export const instanceOfTestUnion: TestUnion = { - f1: 1, - f2: "string", -}; - -// z.object().partial() - -export const TestPartial = Test.partial(); - -export type TestPartial = z.infer; - -export const instanceOfTestPartial: TestPartial = { - f1: 1, -}; - -// z.object().pick() - -export const TestPick = TestMerge.pick({ f1: true }); - -export type TestPick = z.infer; - -export const instanceOfTestPick: TestPick = { - f1: 1, -}; - -// z.object().omit() - -export const TestOmit = TestMerge.omit({ f2: true }); - -export type TestOmit = z.infer; - -export const instanceOfTestOmit: TestOmit = { - f1: 1, -}; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/language-server.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/language-server.test.ts deleted file mode 100644 index 851fdc483..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/language-server.test.ts +++ /dev/null @@ -1,207 +0,0 @@ -import { test } from "vitest"; -// import path from "path"; -// import { Node, Project, SyntaxKind } from "ts-morph"; - -// import { filePath } from "./language-server.source"; - -// The following tool is helpful for understanding the TypeScript AST associated with these tests: -// https://ts-ast-viewer.com/ (just copy the contents of language-server.source into the viewer) - -test("", () => {}); -// describe("Executing Go To Definition (and therefore Find Usages and Rename Refactoring) using an IDE works on inferred object properties", () => { -// // Compile file developmentEnvironment.source -// const project = new Project({ -// tsConfigFilePath: path.join(__dirname, "..", "..", "tsconfig.json"), -// skipAddingFilesFromTsConfig: true, -// }); -// const sourceFile = project.addSourceFileAtPath(filePath); - -// test("works for object properties inferred from z.object()", () => { -// // Find usage of Test.f1 property -// const instanceVariable = -// sourceFile.getVariableDeclarationOrThrow("instanceOfTest"); -// const propertyBeingAssigned = getPropertyBeingAssigned( -// instanceVariable, -// "f1" -// ); - -// // Find definition of Test.f1 property -// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; -// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( -// SyntaxKind.VariableDeclaration -// ); - -// // Assert that find definition returned the Zod definition of Test -// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()"); -// expect(parentOfProperty?.getName()).toEqual("Test"); -// }); - -// // test("works for first object properties inferred from z.object().merge()", () => { -// // // Find usage of TestMerge.f1 property -// // const instanceVariable = sourceFile.getVariableDeclarationOrThrow( -// // "instanceOfTestMerge" -// // ); -// // const propertyBeingAssigned = getPropertyBeingAssigned( -// // instanceVariable, -// // "f1" -// // ); - -// // // Find definition of TestMerge.f1 property -// // const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; -// // const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( -// // SyntaxKind.VariableDeclaration -// // ); - -// // // Assert that find definition returned the Zod definition of Test -// // expect(definitionOfProperty?.getText()).toEqual("f1: z.number()"); -// // expect(parentOfProperty?.getName()).toEqual("Test"); -// // }); - -// // test("works for second object properties inferred from z.object().merge()", () => { -// // // Find usage of TestMerge.f2 property -// // const instanceVariable = sourceFile.getVariableDeclarationOrThrow( -// // "instanceOfTestMerge" -// // ); -// // const propertyBeingAssigned = getPropertyBeingAssigned( -// // instanceVariable, -// // "f2" -// // ); - -// // // Find definition of TestMerge.f2 property -// // const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; -// // const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( -// // SyntaxKind.VariableDeclaration -// // ); - -// // // Assert that find definition returned the Zod definition of TestMerge -// // expect(definitionOfProperty?.getText()).toEqual( -// // "f2: z.string().optional()" -// // ); -// // expect(parentOfProperty?.getName()).toEqual("TestMerge"); -// // }); - -// test("works for first object properties inferred from z.union()", () => { -// // Find usage of TestUnion.f1 property -// const instanceVariable = sourceFile.getVariableDeclarationOrThrow( -// "instanceOfTestUnion" -// ); -// const propertyBeingAssigned = getPropertyBeingAssigned( -// instanceVariable, -// "f1" -// ); - -// // Find definition of TestUnion.f1 property -// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; -// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( -// SyntaxKind.VariableDeclaration -// ); - -// // Assert that find definition returned the Zod definition of Test -// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()"); -// expect(parentOfProperty?.getName()).toEqual("Test"); -// }); - -// test("works for second object properties inferred from z.union()", () => { -// // Find usage of TestUnion.f2 property -// const instanceVariable = sourceFile.getVariableDeclarationOrThrow( -// "instanceOfTestUnion" -// ); -// const propertyBeingAssigned = getPropertyBeingAssigned( -// instanceVariable, -// "f2" -// ); - -// // Find definition of TestUnion.f2 property -// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; -// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( -// SyntaxKind.VariableDeclaration -// ); - -// // Assert that find definition returned the Zod definition of TestUnion -// expect(definitionOfProperty?.getText()).toEqual( -// "f2: z.string().optional()" -// ); -// expect(parentOfProperty?.getName()).toEqual("TestUnion"); -// }); - -// test("works for object properties inferred from z.object().partial()", () => { -// // Find usage of TestPartial.f1 property -// const instanceVariable = sourceFile.getVariableDeclarationOrThrow( -// "instanceOfTestPartial" -// ); -// const propertyBeingAssigned = getPropertyBeingAssigned( -// instanceVariable, -// "f1" -// ); - -// // Find definition of TestPartial.f1 property -// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; -// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( -// SyntaxKind.VariableDeclaration -// ); - -// // Assert that find definition returned the Zod definition of Test -// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()"); -// expect(parentOfProperty?.getName()).toEqual("Test"); -// }); - -// test("works for object properties inferred from z.object().pick()", () => { -// // Find usage of TestPick.f1 property -// const instanceVariable = -// sourceFile.getVariableDeclarationOrThrow("instanceOfTestPick"); -// const propertyBeingAssigned = getPropertyBeingAssigned( -// instanceVariable, -// "f1" -// ); - -// // Find definition of TestPick.f1 property -// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; -// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( -// SyntaxKind.VariableDeclaration -// ); - -// // Assert that find definition returned the Zod definition of Test -// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()"); -// expect(parentOfProperty?.getName()).toEqual("Test"); -// }); - -// test("works for object properties inferred from z.object().omit()", () => { -// // Find usage of TestOmit.f1 property -// const instanceVariable = -// sourceFile.getVariableDeclarationOrThrow("instanceOfTestOmit"); -// const propertyBeingAssigned = getPropertyBeingAssigned( -// instanceVariable, -// "f1" -// ); - -// // Find definition of TestOmit.f1 property -// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; -// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( -// SyntaxKind.VariableDeclaration -// ); - -// // Assert that find definition returned the Zod definition of Test -// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()"); -// expect(parentOfProperty?.getName()).toEqual("Test"); -// }); -// }); - -// const getPropertyBeingAssigned = (node: Node, name: string) => { -// const propertyAssignment = node.forEachDescendant((descendent) => -// Node.isPropertyAssignment(descendent) && descendent.getName() == name -// ? descendent -// : undefined -// ); - -// if (propertyAssignment == null) -// fail(`Could not find property assignment with name ${name}`); - -// const propertyLiteral = propertyAssignment.getFirstDescendantByKind( -// SyntaxKind.Identifier -// ); - -// if (propertyLiteral == null) -// fail(`Could not find property literal with name ${name}`); - -// return propertyLiteral; -// }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/literal.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/literal.test.ts deleted file mode 100644 index d166a24f2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/literal.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -const literalTuna = z.literal("tuna"); -const literalFortyTwo = z.literal(42); -const literalTrue = z.literal(true); - -const terrificSymbol = Symbol("terrific"); -const literalTerrificSymbol = z.literal(terrificSymbol); - -test("passing validations", () => { - literalTuna.parse("tuna"); - literalFortyTwo.parse(42); - literalTrue.parse(true); - literalTerrificSymbol.parse(terrificSymbol); -}); - -test("failing validations", () => { - expect(() => literalTuna.parse("shark")).toThrow(); - expect(() => literalFortyTwo.parse(43)).toThrow(); - expect(() => literalTrue.parse(false)).toThrow(); - expect(() => literalTerrificSymbol.parse(Symbol("terrific"))).toThrow(); -}); - -test("invalid_literal should have `received` field with data", () => { - const data = "shark"; - const result = literalTuna.safeParse(data); - if (!result.success) { - const issue = result.error.issues[0]; - if (issue.code === "invalid_literal") { - expect(issue.received).toBe(data); - } - } -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/map.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/map.test.ts deleted file mode 100644 index 947181903..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/map.test.ts +++ /dev/null @@ -1,110 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { ZodIssueCode } from "zod/v3"; -import { util } from "../helpers/util.js"; - -const stringMap = z.map(z.string(), z.string()); -type stringMap = z.infer; - -test("type inference", () => { - util.assertEqual>(true); -}); - -test("valid parse", () => { - const result = stringMap.safeParse( - new Map([ - ["first", "foo"], - ["second", "bar"], - ]) - ); - expect(result.success).toEqual(true); - if (result.success) { - expect(result.data.has("first")).toEqual(true); - expect(result.data.has("second")).toEqual(true); - expect(result.data.get("first")).toEqual("foo"); - expect(result.data.get("second")).toEqual("bar"); - } -}); - -test("valid parse async", async () => { - const result = await stringMap.spa( - new Map([ - ["first", "foo"], - ["second", "bar"], - ]) - ); - expect(result.success).toEqual(true); - if (result.success) { - expect(result.data.has("first")).toEqual(true); - expect(result.data.has("second")).toEqual(true); - expect(result.data.get("first")).toEqual("foo"); - expect(result.data.get("second")).toEqual("bar"); - } -}); - -test("throws when a Set is given", () => { - const result = stringMap.safeParse(new Set([])); - expect(result.success).toEqual(false); - if (result.success === false) { - expect(result.error.issues.length).toEqual(1); - expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type); - } -}); - -test("throws when the given map has invalid key and invalid input", () => { - const result = stringMap.safeParse(new Map([[42, Symbol()]])); - expect(result.success).toEqual(false); - if (result.success === false) { - expect(result.error.issues.length).toEqual(2); - expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type); - expect(result.error.issues[0].path).toEqual([0, "key"]); - expect(result.error.issues[1].code).toEqual(ZodIssueCode.invalid_type); - expect(result.error.issues[1].path).toEqual([0, "value"]); - } -}); - -test("throws when the given map has multiple invalid entries", () => { - // const result = stringMap.safeParse(new Map([[42, Symbol()]])); - - const result = stringMap.safeParse( - new Map([ - [1, "foo"], - ["bar", 2], - ] as [any, any][]) as Map - ); - - // const result = stringMap.safeParse(new Map([[42, Symbol()]])); - expect(result.success).toEqual(false); - if (result.success === false) { - expect(result.error.issues.length).toEqual(2); - expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type); - expect(result.error.issues[0].path).toEqual([0, "key"]); - expect(result.error.issues[1].code).toEqual(ZodIssueCode.invalid_type); - expect(result.error.issues[1].path).toEqual([1, "value"]); - } -}); - -test("dirty", async () => { - const map = z.map( - z.string().refine((val) => val === val.toUpperCase(), { - message: "Keys must be uppercase", - }), - z.string() - ); - const result = await map.spa( - new Map([ - ["first", "foo"], - ["second", "bar"], - ]) - ); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues.length).toEqual(2); - expect(result.error.issues[0].code).toEqual(z.ZodIssueCode.custom); - expect(result.error.issues[0].message).toEqual("Keys must be uppercase"); - expect(result.error.issues[1].code).toEqual(z.ZodIssueCode.custom); - expect(result.error.issues[1].message).toEqual("Keys must be uppercase"); - } -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/masking.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/masking.test.ts deleted file mode 100644 index 63817e2c1..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/masking.test.ts +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-ignore TS6133 -import { test } from "vitest"; - -test("masking test", () => {}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/mocker.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/mocker.test.ts deleted file mode 100644 index 3a2506b90..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/mocker.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -// @ts-ignore TS6133 -import { test } from "vitest"; - -import { Mocker } from "./Mocker.js"; - -test("mocker", () => { - const mocker = new Mocker(); - mocker.string; - mocker.number; - mocker.boolean; - mocker.null; - mocker.undefined; - mocker.stringOptional; - mocker.stringNullable; - mocker.numberOptional; - mocker.numberNullable; - mocker.booleanOptional; - mocker.booleanNullable; -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/nan.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/nan.test.ts deleted file mode 100644 index ce1214eb8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/nan.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -const schema = z.nan(); - -test("passing validations", () => { - const result1 = schema.parse(Number.NaN); - expect(Number.isNaN(result1)).toBe(true); - - const result2 = schema.parse(Number("Not a number")); - expect(Number.isNaN(result2)).toBe(true); -}); - -test("failing validations", () => { - expect(() => schema.parse(5)).toThrow(); - expect(() => schema.parse("John")).toThrow(); - expect(() => schema.parse(true)).toThrow(); - expect(() => schema.parse(null)).toThrow(); - expect(() => schema.parse(undefined)).toThrow(); - expect(() => schema.parse({})).toThrow(); - expect(() => schema.parse([])).toThrow(); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/nativeEnum.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/nativeEnum.test.ts deleted file mode 100644 index 61eb37a13..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/nativeEnum.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -test("nativeEnum test with consts", () => { - const Fruits: { Apple: "apple"; Banana: "banana" } = { - Apple: "apple", - Banana: "banana", - }; - const fruitEnum = z.nativeEnum(Fruits); - type fruitEnum = z.infer; - fruitEnum.parse("apple"); - fruitEnum.parse("banana"); - fruitEnum.parse(Fruits.Apple); - fruitEnum.parse(Fruits.Banana); - util.assertEqual(true); -}); - -test("nativeEnum test with real enum", () => { - enum Fruits { - Apple = "apple", - Banana = "banana", - } - // @ts-ignore - const fruitEnum = z.nativeEnum(Fruits); - type fruitEnum = z.infer; - fruitEnum.parse("apple"); - fruitEnum.parse("banana"); - fruitEnum.parse(Fruits.Apple); - fruitEnum.parse(Fruits.Banana); - util.assertIs(true); -}); - -test("nativeEnum test with const with numeric keys", () => { - const FruitValues = { - Apple: 10, - Banana: 20, - // @ts-ignore - } as const; - const fruitEnum = z.nativeEnum(FruitValues); - type fruitEnum = z.infer; - fruitEnum.parse(10); - fruitEnum.parse(20); - fruitEnum.parse(FruitValues.Apple); - fruitEnum.parse(FruitValues.Banana); - util.assertEqual(true); -}); - -test("from enum", () => { - enum Fruits { - Cantaloupe = 0, - Apple = "apple", - Banana = "banana", - } - - const FruitEnum = z.nativeEnum(Fruits as any); - type _FruitEnum = z.infer; - FruitEnum.parse(Fruits.Cantaloupe); - FruitEnum.parse(Fruits.Apple); - FruitEnum.parse("apple"); - FruitEnum.parse(0); - expect(() => FruitEnum.parse(1)).toThrow(); - expect(() => FruitEnum.parse("Apple")).toThrow(); - expect(() => FruitEnum.parse("Cantaloupe")).toThrow(); -}); - -test("from const", () => { - const Greek = { - Alpha: "a", - Beta: "b", - Gamma: 3, - // @ts-ignore - } as const; - - const GreekEnum = z.nativeEnum(Greek); - type _GreekEnum = z.infer; - GreekEnum.parse("a"); - GreekEnum.parse("b"); - GreekEnum.parse(3); - expect(() => GreekEnum.parse("v")).toThrow(); - expect(() => GreekEnum.parse("Alpha")).toThrow(); - expect(() => GreekEnum.parse(2)).toThrow(); - - expect(GreekEnum.enum.Alpha).toEqual("a"); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/nullable.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/nullable.test.ts deleted file mode 100644 index 90c1eed4d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/nullable.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -function checkErrors(a: z.ZodTypeAny, bad: any) { - let expected: any; - try { - a.parse(bad); - } catch (error) { - expected = (error as z.ZodError).formErrors; - } - try { - a.nullable().parse(bad); - } catch (error) { - expect((error as z.ZodError).formErrors).toEqual(expected); - } -} - -test("Should have error messages appropriate for the underlying type", () => { - checkErrors(z.string().min(2), 1); - z.string().min(2).nullable().parse(null); - checkErrors(z.number().gte(2), 1); - z.number().gte(2).nullable().parse(null); - checkErrors(z.boolean(), ""); - z.boolean().nullable().parse(null); - checkErrors(z.null(), null); - z.null().nullable().parse(null); - checkErrors(z.null(), {}); - z.null().nullable().parse(null); - checkErrors(z.object({}), 1); - z.object({}).nullable().parse(null); - checkErrors(z.tuple([]), 1); - z.tuple([]).nullable().parse(null); - checkErrors(z.unknown(), 1); - z.unknown().nullable().parse(null); -}); - -test("unwrap", () => { - const unwrapped = z.string().nullable().unwrap(); - expect(unwrapped).toBeInstanceOf(z.ZodString); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/number.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/number.test.ts deleted file mode 100644 index db3f73b2d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/number.test.ts +++ /dev/null @@ -1,176 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -const gtFive = z.number().gt(5); -const gteFive = z.number().gte(-5).gte(5); -const minFive = z.number().min(0).min(5); -const ltFive = z.number().lte(10).lt(5); -const lteFive = z.number().lte(5); -const maxFive = z.number().max(10).max(5); -const intNum = z.number().int(); -const positive = z.number().positive(); -const negative = z.number().negative(); -const nonpositive = z.number().nonpositive(); -const nonnegative = z.number().nonnegative(); -const multipleOfFive = z.number().multipleOf(5); -const multipleOfNegativeFive = z.number().multipleOf(-5); -const finite = z.number().finite(); -const safe = z.number().safe(); -const stepPointOne = z.number().step(0.1); -const stepPointZeroZeroZeroOne = z.number().step(0.0001); -const stepSixPointFour = z.number().step(6.4); - -test("passing validations", () => { - z.number().parse(1); - z.number().parse(1.5); - z.number().parse(0); - z.number().parse(-1.5); - z.number().parse(-1); - z.number().parse(Number.POSITIVE_INFINITY); - z.number().parse(Number.NEGATIVE_INFINITY); - gtFive.parse(6); - gtFive.parse(Number.POSITIVE_INFINITY); - gteFive.parse(5); - gteFive.parse(Number.POSITIVE_INFINITY); - minFive.parse(5); - minFive.parse(Number.POSITIVE_INFINITY); - ltFive.parse(4); - ltFive.parse(Number.NEGATIVE_INFINITY); - lteFive.parse(5); - lteFive.parse(Number.NEGATIVE_INFINITY); - maxFive.parse(5); - maxFive.parse(Number.NEGATIVE_INFINITY); - intNum.parse(4); - positive.parse(1); - positive.parse(Number.POSITIVE_INFINITY); - negative.parse(-1); - negative.parse(Number.NEGATIVE_INFINITY); - nonpositive.parse(0); - nonpositive.parse(-1); - nonpositive.parse(Number.NEGATIVE_INFINITY); - nonnegative.parse(0); - nonnegative.parse(1); - nonnegative.parse(Number.POSITIVE_INFINITY); - multipleOfFive.parse(15); - multipleOfFive.parse(-15); - multipleOfNegativeFive.parse(-15); - multipleOfNegativeFive.parse(15); - finite.parse(123); - safe.parse(Number.MIN_SAFE_INTEGER); - safe.parse(Number.MAX_SAFE_INTEGER); - stepPointOne.parse(6); - stepPointOne.parse(6.1); - stepPointOne.parse(6.1); - stepSixPointFour.parse(12.8); - stepPointZeroZeroZeroOne.parse(3.01); -}); - -test("failing validations", () => { - expect(() => ltFive.parse(5)).toThrow(); - expect(() => lteFive.parse(6)).toThrow(); - expect(() => maxFive.parse(6)).toThrow(); - expect(() => gtFive.parse(5)).toThrow(); - expect(() => gteFive.parse(4)).toThrow(); - expect(() => minFive.parse(4)).toThrow(); - expect(() => intNum.parse(3.14)).toThrow(); - expect(() => positive.parse(0)).toThrow(); - expect(() => positive.parse(-1)).toThrow(); - expect(() => negative.parse(0)).toThrow(); - expect(() => negative.parse(1)).toThrow(); - expect(() => nonpositive.parse(1)).toThrow(); - expect(() => nonnegative.parse(-1)).toThrow(); - expect(() => multipleOfFive.parse(7.5)).toThrow(); - expect(() => multipleOfFive.parse(-7.5)).toThrow(); - expect(() => multipleOfNegativeFive.parse(-7.5)).toThrow(); - expect(() => multipleOfNegativeFive.parse(7.5)).toThrow(); - expect(() => finite.parse(Number.POSITIVE_INFINITY)).toThrow(); - expect(() => finite.parse(Number.NEGATIVE_INFINITY)).toThrow(); - expect(() => safe.parse(Number.MIN_SAFE_INTEGER - 1)).toThrow(); - expect(() => safe.parse(Number.MAX_SAFE_INTEGER + 1)).toThrow(); - - expect(() => stepPointOne.parse(6.11)).toThrow(); - expect(() => stepPointOne.parse(6.1000000001)).toThrow(); - expect(() => stepSixPointFour.parse(6.41)).toThrow(); -}); - -test("parse NaN", () => { - expect(() => z.number().parse(Number.NaN)).toThrow(); -}); - -test("min max getters", () => { - expect(z.number().minValue).toBeNull; - expect(ltFive.minValue).toBeNull; - expect(lteFive.minValue).toBeNull; - expect(maxFive.minValue).toBeNull; - expect(negative.minValue).toBeNull; - expect(nonpositive.minValue).toBeNull; - expect(intNum.minValue).toBeNull; - expect(multipleOfFive.minValue).toBeNull; - expect(finite.minValue).toBeNull; - expect(gtFive.minValue).toEqual(5); - expect(gteFive.minValue).toEqual(5); - expect(minFive.minValue).toEqual(5); - expect(minFive.min(10).minValue).toEqual(10); - expect(positive.minValue).toEqual(0); - expect(nonnegative.minValue).toEqual(0); - expect(safe.minValue).toEqual(Number.MIN_SAFE_INTEGER); - - expect(z.number().maxValue).toBeNull; - expect(gtFive.maxValue).toBeNull; - expect(gteFive.maxValue).toBeNull; - expect(minFive.maxValue).toBeNull; - expect(positive.maxValue).toBeNull; - expect(nonnegative.maxValue).toBeNull; - expect(intNum.minValue).toBeNull; - expect(multipleOfFive.minValue).toBeNull; - expect(finite.minValue).toBeNull; - expect(ltFive.maxValue).toEqual(5); - expect(lteFive.maxValue).toEqual(5); - expect(maxFive.maxValue).toEqual(5); - expect(maxFive.max(1).maxValue).toEqual(1); - expect(negative.maxValue).toEqual(0); - expect(nonpositive.maxValue).toEqual(0); - expect(safe.maxValue).toEqual(Number.MAX_SAFE_INTEGER); -}); - -test("int getter", () => { - expect(z.number().isInt).toEqual(false); - expect(z.number().multipleOf(1.5).isInt).toEqual(false); - expect(gtFive.isInt).toEqual(false); - expect(gteFive.isInt).toEqual(false); - expect(minFive.isInt).toEqual(false); - expect(positive.isInt).toEqual(false); - expect(nonnegative.isInt).toEqual(false); - expect(finite.isInt).toEqual(false); - expect(ltFive.isInt).toEqual(false); - expect(lteFive.isInt).toEqual(false); - expect(maxFive.isInt).toEqual(false); - expect(negative.isInt).toEqual(false); - expect(nonpositive.isInt).toEqual(false); - expect(safe.isInt).toEqual(false); - - expect(intNum.isInt).toEqual(true); - expect(multipleOfFive.isInt).toEqual(true); -}); - -test("finite getter", () => { - expect(z.number().isFinite).toEqual(false); - expect(gtFive.isFinite).toEqual(false); - expect(gteFive.isFinite).toEqual(false); - expect(minFive.isFinite).toEqual(false); - expect(positive.isFinite).toEqual(false); - expect(nonnegative.isFinite).toEqual(false); - expect(ltFive.isFinite).toEqual(false); - expect(lteFive.isFinite).toEqual(false); - expect(maxFive.isFinite).toEqual(false); - expect(negative.isFinite).toEqual(false); - expect(nonpositive.isFinite).toEqual(false); - - expect(finite.isFinite).toEqual(true); - expect(intNum.isFinite).toEqual(true); - expect(multipleOfFive.isFinite).toEqual(true); - expect(z.number().min(5).max(10).isFinite).toEqual(true); - expect(safe.isFinite).toEqual(true); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/object-augmentation.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/object-augmentation.test.ts deleted file mode 100644 index 964ea3dae..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/object-augmentation.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -test("object augmentation", () => { - const Animal = z - .object({ - species: z.string(), - }) - .augment({ - population: z.number(), - }); - // overwrites `species` - const ModifiedAnimal = Animal.augment({ - species: z.array(z.string()), - }); - ModifiedAnimal.parse({ - species: ["asd"], - population: 1324, - }); - - const bad = () => - ModifiedAnimal.parse({ - species: "asdf", - population: 1324, - } as any); - expect(bad).toThrow(); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/object-in-es5-env.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/object-in-es5-env.test.ts deleted file mode 100644 index 293ebf0c7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/object-in-es5-env.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -const RealSet = Set; -const RealMap = Map; -const RealDate = Date; - -test("doesn’t throw when Date is undefined", () => { - delete (globalThis as any).Date; - const result = z.object({}).safeParse({}); - expect(result.success).toEqual(true); - globalThis.Date = RealDate; -}); - -test("doesn’t throw when Set is undefined", () => { - delete (globalThis as any).Set; - const result = z.object({}).safeParse({}); - expect(result.success).toEqual(true); - globalThis.Set = RealSet; -}); - -test("doesn’t throw when Map is undefined", () => { - delete (globalThis as any).Map; - const result = z.object({}).safeParse({}); - expect(result.success).toEqual(true); - globalThis.Map = RealMap; -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/object.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/object.test.ts deleted file mode 100644 index 1427dc278..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/object.test.ts +++ /dev/null @@ -1,434 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -const Test = z.object({ - f1: z.number(), - f2: z.string().optional(), - f3: z.string().nullable(), - f4: z.array(z.object({ t: z.union([z.string(), z.boolean()]) })), -}); - -test("object type inference", () => { - type TestType = { - f1: number; - f2?: string | undefined; - f3: string | null; - f4: { t: string | boolean }[]; - }; - - util.assertEqual, TestType>(true); -}); - -test("unknown throw", () => { - const asdf: unknown = 35; - expect(() => Test.parse(asdf)).toThrow(); -}); - -test("shape() should return schema of particular key", () => { - const f1Schema = Test.shape.f1; - const f2Schema = Test.shape.f2; - const f3Schema = Test.shape.f3; - const f4Schema = Test.shape.f4; - - expect(f1Schema).toBeInstanceOf(z.ZodNumber); - expect(f2Schema).toBeInstanceOf(z.ZodOptional); - expect(f3Schema).toBeInstanceOf(z.ZodNullable); - expect(f4Schema).toBeInstanceOf(z.ZodArray); -}); - -test("correct parsing", () => { - Test.parse({ - f1: 12, - f2: "string", - f3: "string", - f4: [ - { - t: "string", - }, - ], - }); - - Test.parse({ - f1: 12, - f3: null, - f4: [ - { - t: false, - }, - ], - }); -}); - -test("incorrect #1", () => { - expect(() => Test.parse({} as any)).toThrow(); -}); - -test("nonstrict by default", () => { - z.object({ points: z.number() }).parse({ - points: 2314, - unknown: "asdf", - }); -}); - -const data = { - points: 2314, - unknown: "asdf", -}; - -test("strip by default", () => { - const val = z.object({ points: z.number() }).parse(data); - expect(val).toEqual({ points: 2314 }); -}); - -test("unknownkeys override", () => { - const val = z.object({ points: z.number() }).strict().passthrough().strip().nonstrict().parse(data); - - expect(val).toEqual(data); -}); - -test("passthrough unknown", () => { - const val = z.object({ points: z.number() }).passthrough().parse(data); - - expect(val).toEqual(data); -}); - -test("strip unknown", () => { - const val = z.object({ points: z.number() }).strip().parse(data); - - expect(val).toEqual({ points: 2314 }); -}); - -test("strict", () => { - const val = z.object({ points: z.number() }).strict().safeParse(data); - - expect(val.success).toEqual(false); -}); - -test("catchall inference", () => { - const o1 = z - .object({ - first: z.string(), - }) - .catchall(z.number()); - - const d1 = o1.parse({ first: "asdf", num: 1243 }); - util.assertEqual(true); - util.assertEqual(true); -}); - -test("catchall overrides strict", () => { - const o1 = z.object({ first: z.string().optional() }).strict().catchall(z.number()); - - // should run fine - // setting a catchall overrides the unknownKeys behavior - o1.parse({ - asdf: 1234, - }); - - // should only run catchall validation - // against unknown keys - o1.parse({ - first: "asdf", - asdf: 1234, - }); -}); - -test("catchall overrides strict", () => { - const o1 = z - .object({ - first: z.string(), - }) - .strict() - .catchall(z.number()); - - // should run fine - // setting a catchall overrides the unknownKeys behavior - o1.parse({ - first: "asdf", - asdf: 1234, - }); -}); - -test("test that optional keys are unset", () => { - const SNamedEntity = z.object({ - id: z.string(), - set: z.string().optional(), - unset: z.string().optional(), - }); - const result = SNamedEntity.parse({ - id: "asdf", - set: undefined, - }); - // eslint-disable-next-line ban/ban - expect(Object.keys(result)).toEqual(["id", "set"]); -}); - -test("test catchall parsing", async () => { - const result = z.object({ name: z.string() }).catchall(z.number()).parse({ name: "Foo", validExtraKey: 61 }); - - expect(result).toEqual({ name: "Foo", validExtraKey: 61 }); - - const result2 = z - .object({ name: z.string() }) - .catchall(z.number()) - .safeParse({ name: "Foo", validExtraKey: 61, invalid: "asdf" }); - - expect(result2.success).toEqual(false); -}); - -test("test nonexistent keys", async () => { - const Schema = z.union([z.object({ a: z.string() }), z.object({ b: z.number() })]); - const obj = { a: "A" }; - const result = await Schema.spa(obj); // Works with 1.11.10, breaks with 2.0.0-beta.21 - expect(result.success).toBe(true); -}); - -test("test async union", async () => { - const Schema2 = z.union([ - z.object({ - ty: z.string(), - }), - z.object({ - ty: z.number(), - }), - ]); - - const obj = { ty: "A" }; - const result = await Schema2.spa(obj); // Works with 1.11.10, breaks with 2.0.0-beta.21 - expect(result.success).toEqual(true); -}); - -test("test inferred merged type", async () => { - const asdf = z.object({ a: z.string() }).merge(z.object({ a: z.number() })); - type asdf = z.infer; - util.assertEqual(true); -}); - -test("inferred merged object type with optional properties", async () => { - const Merged = z - .object({ a: z.string(), b: z.string().optional() }) - .merge(z.object({ a: z.string().optional(), b: z.string() })); - type Merged = z.infer; - util.assertEqual(true); - // todo - // util.assertEqual(true); -}); - -test("inferred unioned object type with optional properties", async () => { - const Unioned = z.union([ - z.object({ a: z.string(), b: z.string().optional() }), - z.object({ a: z.string().optional(), b: z.string() }), - ]); - type Unioned = z.infer; - util.assertEqual(true); -}); - -test("inferred enum type", async () => { - const Enum = z.object({ a: z.string(), b: z.string().optional() }).keyof(); - - expect(Enum.Values).toEqual({ - a: "a", - b: "b", - }); - expect(Enum.enum).toEqual({ - a: "a", - b: "b", - }); - expect(Enum._def.values).toEqual(["a", "b"]); - type Enum = z.infer; - util.assertEqual(true); -}); - -test("inferred partial object type with optional properties", async () => { - const Partial = z.object({ a: z.string(), b: z.string().optional() }).partial(); - type Partial = z.infer; - util.assertEqual(true); -}); - -test("inferred picked object type with optional properties", async () => { - const Picked = z.object({ a: z.string(), b: z.string().optional() }).pick({ b: true }); - type Picked = z.infer; - util.assertEqual(true); -}); - -test("inferred type for unknown/any keys", () => { - const myType = z.object({ - anyOptional: z.any().optional(), - anyRequired: z.any(), - unknownOptional: z.unknown().optional(), - unknownRequired: z.unknown(), - }); - type myType = z.infer; - util.assertEqual< - myType, - { - anyOptional?: any; - anyRequired?: any; - unknownOptional?: unknown; - unknownRequired?: unknown; - } - >(true); -}); - -test("setKey", () => { - const base = z.object({ name: z.string() }); - const withNewKey = base.setKey("age", z.number()); - - type withNewKey = z.infer; - util.assertEqual(true); - withNewKey.parse({ name: "asdf", age: 1234 }); -}); - -test("strictcreate", async () => { - const strictObj = z.strictObject({ - name: z.string(), - }); - - const syncResult = strictObj.safeParse({ name: "asdf", unexpected: 13 }); - expect(syncResult.success).toEqual(false); - - const asyncResult = await strictObj.spa({ name: "asdf", unexpected: 13 }); - expect(asyncResult.success).toEqual(false); -}); - -test("object with refine", async () => { - const schema = z - .object({ - a: z.string().default("foo"), - b: z.number(), - }) - .refine(() => true); - expect(schema.parse({ b: 5 })).toEqual({ b: 5, a: "foo" }); - const result = await schema.parseAsync({ b: 5 }); - expect(result).toEqual({ b: 5, a: "foo" }); -}); - -test("intersection of object with date", async () => { - const schema = z.object({ - a: z.date(), - }); - expect(schema.and(schema).parse({ a: new Date(1637353595983) })).toEqual({ - a: new Date(1637353595983), - }); - const result = await schema.parseAsync({ a: new Date(1637353595983) }); - expect(result).toEqual({ a: new Date(1637353595983) }); -}); - -test("intersection of object with refine with date", async () => { - const schema = z - .object({ - a: z.date(), - }) - .refine(() => true); - expect(schema.and(schema).parse({ a: new Date(1637353595983) })).toEqual({ - a: new Date(1637353595983), - }); - const result = await schema.parseAsync({ a: new Date(1637353595983) }); - expect(result).toEqual({ a: new Date(1637353595983) }); -}); - -test("constructor key", () => { - const person = z - .object({ - name: z.string(), - }) - .strict(); - - expect(() => - person.parse({ - name: "bob dylan", - constructor: 61, - }) - ).toThrow(); -}); - -test("constructor key", () => { - const Example = z.object({ - prop: z.string(), - opt: z.number().optional(), - arr: z.string().array(), - }); - - type Example = z.infer; - util.assertEqual(true); -}); - -test("unknownkeys merging", () => { - // This one is "strict" - const schemaA = z - .object({ - a: z.string(), - }) - .strict(); - - // This one is "strip" - const schemaB = z - .object({ - b: z.string(), - }) - .catchall(z.string()); - - const mergedSchema = schemaA.merge(schemaB); - type mergedSchema = typeof mergedSchema; - util.assertEqual(true); - expect(mergedSchema._def.unknownKeys).toEqual("strip"); - - util.assertEqual(true); - expect(mergedSchema._def.catchall instanceof z.ZodString).toEqual(true); -}); - -const personToExtend = z.object({ - firstName: z.string(), - lastName: z.string(), -}); - -test("extend() should return schema with new key", () => { - const PersonWithNickname = personToExtend.extend({ nickName: z.string() }); - type PersonWithNickname = z.infer; - - const expected = { firstName: "f", nickName: "n", lastName: "l" }; - const actual = PersonWithNickname.parse(expected); - - expect(actual).toEqual(expected); - util.assertEqual(true); - util.assertEqual(true); -}); - -test("extend() should have power to override existing key", () => { - const PersonWithNumberAsLastName = personToExtend.extend({ - lastName: z.number(), - }); - type PersonWithNumberAsLastName = z.infer; - - const expected = { firstName: "f", lastName: 42 }; - const actual = PersonWithNumberAsLastName.parse(expected); - - expect(actual).toEqual(expected); - util.assertEqual(true); -}); - -test("passthrough index signature", () => { - const a = z.object({ a: z.string() }); - type a = z.infer; - util.assertEqual<{ a: string }, a>(true); - const b = a.passthrough(); - type b = z.infer; - util.assertEqual<{ a: string } & { [k: string]: unknown }, b>(true); -}); - -test("xor", () => { - type Without = { [P in Exclude]?: never }; - type XOR = T extends object ? (U extends object ? (Without & U) | (Without & T) : U) : T; - - type A = { name: string; a: number }; - type B = { name: string; b: number }; - type C = XOR; - type Outer = { data: C }; - - const _Outer: z.ZodType = z.object({ - data: z.union([z.object({ name: z.string(), a: z.number() }), z.object({ name: z.string(), b: z.number() })]), - }); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/optional.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/optional.test.ts deleted file mode 100644 index 016c954fc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/optional.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -function checkErrors(a: z.ZodTypeAny, bad: any) { - let expected: any; - try { - a.parse(bad); - } catch (error) { - expected = (error as z.ZodError).formErrors; - } - try { - a.optional().parse(bad); - } catch (error) { - expect((error as z.ZodError).formErrors).toEqual(expected); - } -} - -test("Should have error messages appropriate for the underlying type", () => { - checkErrors(z.string().min(2), 1); - z.string().min(2).optional().parse(undefined); - checkErrors(z.number().gte(2), 1); - z.number().gte(2).optional().parse(undefined); - checkErrors(z.boolean(), ""); - z.boolean().optional().parse(undefined); - checkErrors(z.undefined(), null); - z.undefined().optional().parse(undefined); - checkErrors(z.null(), {}); - z.null().optional().parse(undefined); - checkErrors(z.object({}), 1); - z.object({}).optional().parse(undefined); - checkErrors(z.tuple([]), 1); - z.tuple([]).optional().parse(undefined); - checkErrors(z.unknown(), 1); - z.unknown().optional().parse(undefined); -}); - -test("unwrap", () => { - const unwrapped = z.string().optional().unwrap(); - expect(unwrapped).toBeInstanceOf(z.ZodString); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/parseUtil.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/parseUtil.test.ts deleted file mode 100644 index 8882d4c34..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/parseUtil.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import { type SyncParseReturnType, isAborted, isDirty, isValid } from "../helpers/parseUtil.js"; - -test("parseUtil isInvalid should use structural typing", () => { - // Test for issue #556: https://github.com/colinhacks/zod/issues/556 - const aborted: SyncParseReturnType = { status: "aborted" }; - const dirty: SyncParseReturnType = { status: "dirty", value: "whatever" }; - const valid: SyncParseReturnType = { status: "valid", value: "whatever" }; - - expect(isAborted(aborted)).toBe(true); - expect(isAborted(dirty)).toBe(false); - expect(isAborted(valid)).toBe(false); - - expect(isDirty(aborted)).toBe(false); - expect(isDirty(dirty)).toBe(true); - expect(isDirty(valid)).toBe(false); - - expect(isValid(aborted)).toBe(false); - expect(isValid(dirty)).toBe(false); - expect(isValid(valid)).toBe(true); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/parser.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/parser.test.ts deleted file mode 100644 index 6e685f9f5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/parser.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -test("parse strict object with unknown keys", () => { - expect(() => - z - .object({ name: z.string() }) - .strict() - .parse({ name: "bill", unknownKey: 12 } as any) - ).toThrow(); -}); - -test("parse nonstrict object with unknown keys", () => { - z.object({ name: z.string() }).nonstrict().parse({ name: "bill", unknownKey: 12 }); -}); - -test("invalid left side of intersection", () => { - expect(() => z.intersection(z.string(), z.number()).parse(12 as any)).toThrow(); -}); - -test("invalid right side of intersection", () => { - expect(() => z.intersection(z.string(), z.number()).parse("12" as any)).toThrow(); -}); - -test("parsing non-array in tuple schema", () => { - expect(() => z.tuple([]).parse("12" as any)).toThrow(); -}); - -test("incorrect num elements in tuple", () => { - expect(() => z.tuple([]).parse(["asdf"] as any)).toThrow(); -}); - -test("invalid enum value", () => { - expect(() => z.enum(["Blue"]).parse("Red" as any)).toThrow(); -}); - -test("parsing unknown", () => { - z.string().parse("Red" as unknown); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/partials.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/partials.test.ts deleted file mode 100644 index a2fb6ed9c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/partials.test.ts +++ /dev/null @@ -1,243 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { ZodNullable, ZodOptional } from "zod/v3"; -import { util } from "../helpers/util.js"; - -const nested = z.object({ - name: z.string(), - age: z.number(), - outer: z.object({ - inner: z.string(), - }), - array: z.array(z.object({ asdf: z.string() })), -}); - -test("shallow inference", () => { - const shallow = nested.partial(); - type shallow = z.infer; - type correct = { - name?: string | undefined; - age?: number | undefined; - outer?: { inner: string } | undefined; - array?: { asdf: string }[]; - }; - util.assertEqual(true); -}); - -test("shallow partial parse", () => { - const shallow = nested.partial(); - shallow.parse({}); - shallow.parse({ - name: "asdf", - age: 23143, - }); -}); - -test("deep partial inference", () => { - const deep = nested.deepPartial(); - const asdf = deep.shape.array.unwrap().element.shape.asdf.unwrap(); - asdf.parse("asdf"); - type deep = z.infer; - type correct = { - array?: { asdf?: string }[]; - name?: string | undefined; - age?: number | undefined; - outer?: { inner?: string | undefined } | undefined; - }; - - util.assertEqual(true); -}); - -test("deep partial parse", () => { - const deep = nested.deepPartial(); - - expect(deep.shape.name instanceof z.ZodOptional).toBe(true); - expect(deep.shape.outer instanceof z.ZodOptional).toBe(true); - expect(deep.shape.outer._def.innerType instanceof z.ZodObject).toBe(true); - expect(deep.shape.outer._def.innerType.shape.inner instanceof z.ZodOptional).toBe(true); - expect(deep.shape.outer._def.innerType.shape.inner._def.innerType instanceof z.ZodString).toBe(true); -}); - -test("deep partial runtime tests", () => { - const deep = nested.deepPartial(); - deep.parse({}); - deep.parse({ - outer: {}, - }); - deep.parse({ - name: "asdf", - age: 23143, - outer: { - inner: "adsf", - }, - }); -}); - -test("deep partial optional/nullable", () => { - const schema = z - .object({ - name: z.string().optional(), - age: z.number().nullable(), - }) - .deepPartial(); - - expect(schema.shape.name.unwrap()).toBeInstanceOf(ZodOptional); - expect(schema.shape.age.unwrap()).toBeInstanceOf(ZodNullable); -}); - -test("deep partial tuple", () => { - const schema = z - .object({ - tuple: z.tuple([ - z.object({ - name: z.string().optional(), - age: z.number().nullable(), - }), - ]), - }) - .deepPartial(); - - expect(schema.shape.tuple.unwrap().items[0].shape.name).toBeInstanceOf(ZodOptional); -}); - -test("deep partial inference", () => { - const mySchema = z.object({ - name: z.string(), - array: z.array(z.object({ asdf: z.string() })), - tuple: z.tuple([z.object({ value: z.string() })]), - }); - - const partialed = mySchema.deepPartial(); - type partialed = z.infer; - type expected = { - name?: string | undefined; - array?: - | { - asdf?: string | undefined; - }[] - | undefined; - tuple?: [{ value?: string }] | undefined; - }; - util.assertEqual(true); -}); - -test("required", () => { - const object = z.object({ - name: z.string(), - age: z.number().optional(), - field: z.string().optional().default("asdf"), - nullableField: z.number().nullable(), - nullishField: z.string().nullish(), - }); - - const requiredObject = object.required(); - expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString); - expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNumber); - expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault); - expect(requiredObject.shape.nullableField).toBeInstanceOf(z.ZodNullable); - expect(requiredObject.shape.nullishField).toBeInstanceOf(z.ZodNullable); -}); - -test("required inference", () => { - const object = z.object({ - name: z.string(), - age: z.number().optional(), - field: z.string().optional().default("asdf"), - nullableField: z.number().nullable(), - nullishField: z.string().nullish(), - }); - - const requiredObject = object.required(); - - type required = z.infer; - type expected = { - name: string; - age: number; - field: string; - nullableField: number | null; - nullishField: string | null; - }; - util.assertEqual(true); -}); - -test("required with mask", () => { - const object = z.object({ - name: z.string(), - age: z.number().optional(), - field: z.string().optional().default("asdf"), - country: z.string().optional(), - }); - - const requiredObject = object.required({ age: true }); - expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString); - expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNumber); - expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault); - expect(requiredObject.shape.country).toBeInstanceOf(z.ZodOptional); -}); - -test("required with mask -- ignore falsy values", () => { - const object = z.object({ - name: z.string(), - age: z.number().optional(), - field: z.string().optional().default("asdf"), - country: z.string().optional(), - }); - - // @ts-expect-error - const requiredObject = object.required({ age: true, country: false }); - expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString); - expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNumber); - expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault); - expect(requiredObject.shape.country).toBeInstanceOf(z.ZodOptional); -}); - -test("partial with mask", async () => { - const object = z.object({ - name: z.string(), - age: z.number().optional(), - field: z.string().optional().default("asdf"), - country: z.string(), - }); - - const masked = object.partial({ age: true, field: true, name: true }).strict(); - - expect(masked.shape.name).toBeInstanceOf(z.ZodOptional); - expect(masked.shape.age).toBeInstanceOf(z.ZodOptional); - expect(masked.shape.field).toBeInstanceOf(z.ZodOptional); - expect(masked.shape.country).toBeInstanceOf(z.ZodString); - - masked.parse({ country: "US" }); - await masked.parseAsync({ country: "US" }); -}); - -test("partial with mask -- ignore falsy values", async () => { - const object = z.object({ - name: z.string(), - age: z.number().optional(), - field: z.string().optional().default("asdf"), - country: z.string(), - }); - - // @ts-expect-error - const masked = object.partial({ name: true, country: false }).strict(); - - expect(masked.shape.name).toBeInstanceOf(z.ZodOptional); - expect(masked.shape.age).toBeInstanceOf(z.ZodOptional); - expect(masked.shape.field).toBeInstanceOf(z.ZodDefault); - expect(masked.shape.country).toBeInstanceOf(z.ZodString); - - masked.parse({ country: "US" }); - await masked.parseAsync({ country: "US" }); -}); - -test("deeppartial array", () => { - const schema = z.object({ array: z.string().array().min(42) }).deepPartial(); - - // works as expected - schema.parse({}); - - // should be false, but is true - expect(schema.safeParse({ array: [] }).success).toBe(false); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/pickomit.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/pickomit.test.ts deleted file mode 100644 index b1056e5af..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/pickomit.test.ts +++ /dev/null @@ -1,111 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -const fish = z.object({ - name: z.string(), - age: z.number(), - nested: z.object({}), -}); - -test("pick type inference", () => { - const nameonlyFish = fish.pick({ name: true }); - type nameonlyFish = z.infer; - util.assertEqual(true); -}); - -test("pick parse - success", () => { - const nameonlyFish = fish.pick({ name: true }); - nameonlyFish.parse({ name: "bob" }); - - // @ts-expect-error checking runtime picks `name` only. - const anotherNameonlyFish = fish.pick({ name: true, age: false }); - anotherNameonlyFish.parse({ name: "bob" }); -}); - -test("pick parse - fail", () => { - fish.pick({ name: true }).parse({ name: "12" } as any); - fish.pick({ name: true }).parse({ name: "bob", age: 12 } as any); - fish.pick({ age: true }).parse({ age: 12 } as any); - - const nameonlyFish = fish.pick({ name: true }).strict(); - const bad1 = () => nameonlyFish.parse({ name: 12 } as any); - const bad2 = () => nameonlyFish.parse({ name: "bob", age: 12 } as any); - const bad3 = () => nameonlyFish.parse({ age: 12 } as any); - - // @ts-expect-error checking runtime picks `name` only. - const anotherNameonlyFish = fish.pick({ name: true, age: false }).strict(); - const bad4 = () => anotherNameonlyFish.parse({ name: "bob", age: 12 } as any); - - expect(bad1).toThrow(); - expect(bad2).toThrow(); - expect(bad3).toThrow(); - expect(bad4).toThrow(); -}); - -test("omit type inference", () => { - const nonameFish = fish.omit({ name: true }); - type nonameFish = z.infer; - util.assertEqual(true); -}); - -test("omit parse - success", () => { - const nonameFish = fish.omit({ name: true }); - nonameFish.parse({ age: 12, nested: {} }); - - // @ts-expect-error checking runtime omits `name` only. - const anotherNonameFish = fish.omit({ name: true, age: false }); - anotherNonameFish.parse({ age: 12, nested: {} }); -}); - -test("omit parse - fail", () => { - const nonameFish = fish.omit({ name: true }); - const bad1 = () => nonameFish.parse({ name: 12 } as any); - const bad2 = () => nonameFish.parse({ age: 12 } as any); - const bad3 = () => nonameFish.parse({} as any); - - // @ts-expect-error checking runtime omits `name` only. - const anotherNonameFish = fish.omit({ name: true, age: false }); - const bad4 = () => anotherNonameFish.parse({ nested: {} } as any); - - expect(bad1).toThrow(); - expect(bad2).toThrow(); - expect(bad3).toThrow(); - expect(bad4).toThrow(); -}); - -test("nonstrict inference", () => { - const laxfish = fish.pick({ name: true }).catchall(z.any()); - type laxfish = z.infer; - util.assertEqual(true); -}); - -test("nonstrict parsing - pass", () => { - const laxfish = fish.passthrough().pick({ name: true }); - laxfish.parse({ name: "asdf", whatever: "asdf" }); - laxfish.parse({ name: "asdf", age: 12, nested: {} }); -}); - -test("nonstrict parsing - fail", () => { - const laxfish = fish.passthrough().pick({ name: true }); - const bad = () => laxfish.parse({ whatever: "asdf" } as any); - expect(bad).toThrow(); -}); - -test("pick/omit/required/partial - do not allow unknown keys", () => { - const schema = z.object({ - name: z.string(), - age: z.number(), - }); - - // @ts-expect-error - schema.pick({ $unknown: true }); - // @ts-expect-error - schema.omit({ $unknown: true }); - // @ts-expect-error - schema.required({ $unknown: true }); - // @ts-expect-error - schema.partial({ $unknown: true }); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/pipeline.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/pipeline.test.ts deleted file mode 100644 index cc94fc554..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/pipeline.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -test("string to number pipeline", () => { - const schema = z.string().transform(Number).pipe(z.number()); - expect(schema.parse("1234")).toEqual(1234); -}); - -test("string to number pipeline async", async () => { - const schema = z - .string() - .transform(async (val) => Number(val)) - .pipe(z.number()); - expect(await schema.parseAsync("1234")).toEqual(1234); -}); - -test("break if dirty", () => { - const schema = z - .string() - .refine((c) => c === "1234") - .transform(async (val) => Number(val)) - .pipe(z.number().refine((v) => v < 100)); - const r1: any = schema.safeParse("12345"); - expect(r1.error.issues.length).toBe(1); - const r2: any = schema.safeParse("3"); - expect(r2.error.issues.length).toBe(1); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/preprocess.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/preprocess.test.ts deleted file mode 100644 index 7e1b5a1d7..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/preprocess.test.ts +++ /dev/null @@ -1,186 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -test("preprocess", () => { - const schema = z.preprocess((data) => [data], z.string().array()); - - const value = schema.parse("asdf"); - expect(value).toEqual(["asdf"]); - util.assertEqual<(typeof schema)["_input"], unknown>(true); -}); - -test("async preprocess", async () => { - const schema = z.preprocess(async (data) => [data], z.string().array()); - - const value = await schema.parseAsync("asdf"); - expect(value).toEqual(["asdf"]); -}); - -test("preprocess ctx.addIssue with parse", () => { - expect(() => { - z.preprocess((data, ctx) => { - ctx.addIssue({ - code: "custom", - message: `${data} is not one of our allowed strings`, - }); - return data; - }, z.string()).parse("asdf"); - }).toThrow( - JSON.stringify( - [ - { - code: "custom", - message: "asdf is not one of our allowed strings", - path: [], - }, - ], - null, - 2 - ) - ); -}); - -test("preprocess ctx.addIssue non-fatal by default", () => { - try { - z.preprocess((data, ctx) => { - ctx.addIssue({ - code: "custom", - message: `custom error`, - }); - return data; - }, z.string()).parse(1234); - } catch (err) { - z.ZodError.assert(err); - expect(err.issues.length).toEqual(2); - } -}); - -test("preprocess ctx.addIssue fatal true", () => { - try { - z.preprocess((data, ctx) => { - ctx.addIssue({ - code: "custom", - message: `custom error`, - fatal: true, - }); - return data; - }, z.string()).parse(1234); - } catch (err) { - z.ZodError.assert(err); - expect(err.issues.length).toEqual(1); - } -}); - -test("async preprocess ctx.addIssue with parse", async () => { - const schema = z.preprocess(async (data, ctx) => { - ctx.addIssue({ - code: "custom", - message: `custom error`, - }); - return data; - }, z.string()); - - expect(await schema.safeParseAsync("asdf")).toMatchInlineSnapshot(` - { - "error": [ZodError: [ - { - "code": "custom", - "message": "custom error", - "path": [] - } - ]], - "success": false, - } - `); -}); - -test("preprocess ctx.addIssue with parseAsync", async () => { - const result = await z - .preprocess(async (data, ctx) => { - ctx.addIssue({ - code: "custom", - message: `${data} is not one of our allowed strings`, - }); - return data; - }, z.string()) - .safeParseAsync("asdf"); - - expect(JSON.parse(JSON.stringify(result))).toEqual({ - success: false, - error: { - issues: [ - { - code: "custom", - message: "asdf is not one of our allowed strings", - path: [], - }, - ], - name: "ZodError", - }, - }); -}); - -test("z.NEVER in preprocess", () => { - const foo = z.preprocess((val, ctx) => { - if (!val) { - ctx.addIssue({ code: z.ZodIssueCode.custom, message: "bad" }); - return z.NEVER; - } - return val; - }, z.number()); - - type foo = z.infer; - util.assertEqual(true); - const arg = foo.safeParse(undefined); - expect(arg.error!.issues).toHaveLength(2); - expect(arg.error!.issues[0].message).toEqual("bad"); -}); -test("preprocess as the second property of object", () => { - const schema = z.object({ - nonEmptyStr: z.string().min(1), - positiveNum: z.preprocess((v) => Number(v), z.number().positive()), - }); - const result = schema.safeParse({ - nonEmptyStr: "", - positiveNum: "", - }); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues.length).toEqual(2); - expect(result.error.issues[0].code).toEqual(z.ZodIssueCode.too_small); - expect(result.error.issues[1].code).toEqual(z.ZodIssueCode.too_small); - } -}); - -test("preprocess validates with sibling errors", () => { - expect(() => { - z.object({ - // Must be first - missing: z.string().refine(() => false), - preprocess: z.preprocess((data: any) => data?.trim(), z.string().regex(/ asdf/)), - }).parse({ preprocess: " asdf" }); - }).toThrow( - JSON.stringify( - [ - { - code: "invalid_type", - expected: "string", - received: "undefined", - path: ["missing"], - message: "Required", - }, - { - validation: "regex", - code: "invalid_string", - message: "Invalid", - path: ["preprocess"], - }, - ], - null, - 2 - ) - ); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/primitive.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/primitive.test.ts deleted file mode 100644 index 48e36a21c..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/primitive.test.ts +++ /dev/null @@ -1,440 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; -import { Mocker } from "./Mocker.js"; - -const literalStringSchema = z.literal("asdf"); -const literalNumberSchema = z.literal(12); -const literalBooleanSchema = z.literal(true); -const literalBigIntSchema = z.literal(BigInt(42)); -const MySymbol = Symbol("stuff"); -const literalSymbolSchema = z.literal(MySymbol); -const stringSchema = z.string(); -const numberSchema = z.number(); -const bigintSchema = z.bigint(); -const booleanSchema = z.boolean(); -const dateSchema = z.date(); -const symbolSchema = z.symbol(); - -const nullSchema = z.null(); -const undefinedSchema = z.undefined(); -const stringSchemaOptional = z.string().optional(); -const stringSchemaNullable = z.string().nullable(); -const numberSchemaOptional = z.number().optional(); -const numberSchemaNullable = z.number().nullable(); -const bigintSchemaOptional = z.bigint().optional(); -const bigintSchemaNullable = z.bigint().nullable(); -const booleanSchemaOptional = z.boolean().optional(); -const booleanSchemaNullable = z.boolean().nullable(); -const dateSchemaOptional = z.date().optional(); -const dateSchemaNullable = z.date().nullable(); -const symbolSchemaOptional = z.symbol().optional(); -const symbolSchemaNullable = z.symbol().nullable(); - -const val = new Mocker(); - -test("literal string correct", () => { - expect(literalStringSchema.parse("asdf")).toBe("asdf"); -}); - -test("literal string incorrect", () => { - const f = () => literalStringSchema.parse("not_asdf"); - expect(f).toThrow(); -}); - -test("literal string number", () => { - const f = () => literalStringSchema.parse(123); - expect(f).toThrow(); -}); - -test("literal string boolean", () => { - const f = () => literalStringSchema.parse(true); - expect(f).toThrow(); -}); - -test("literal string boolean", () => { - const f = () => literalStringSchema.parse(true); - expect(f).toThrow(); -}); - -test("literal string object", () => { - const f = () => literalStringSchema.parse({}); - expect(f).toThrow(); -}); - -test("literal number correct", () => { - expect(literalNumberSchema.parse(12)).toBe(12); -}); - -test("literal number incorrect", () => { - const f = () => literalNumberSchema.parse(13); - expect(f).toThrow(); -}); - -test("literal number number", () => { - const f = () => literalNumberSchema.parse(val.string); - expect(f).toThrow(); -}); - -test("literal number boolean", () => { - const f = () => literalNumberSchema.parse(val.boolean); - expect(f).toThrow(); -}); - -test("literal number object", () => { - const f = () => literalStringSchema.parse({}); - expect(f).toThrow(); -}); - -test("literal boolean correct", () => { - expect(literalBooleanSchema.parse(true)).toBe(true); -}); - -test("literal boolean incorrect", () => { - const f = () => literalBooleanSchema.parse(false); - expect(f).toThrow(); -}); - -test("literal boolean number", () => { - const f = () => literalBooleanSchema.parse("asdf"); - expect(f).toThrow(); -}); - -test("literal boolean boolean", () => { - const f = () => literalBooleanSchema.parse(123); - expect(f).toThrow(); -}); - -test("literal boolean object", () => { - const f = () => literalBooleanSchema.parse({}); - expect(f).toThrow(); -}); - -test("literal bigint correct", () => { - expect(literalBigIntSchema.parse(BigInt(42))).toBe(BigInt(42)); -}); - -test("literal bigint incorrect", () => { - const f = () => literalBigIntSchema.parse(BigInt(43)); - expect(f).toThrow(); -}); - -test("literal bigint number", () => { - const f = () => literalBigIntSchema.parse("asdf"); - expect(f).toThrow(); -}); - -test("literal bigint boolean", () => { - const f = () => literalBigIntSchema.parse(123); - expect(f).toThrow(); -}); - -test("literal bigint object", () => { - const f = () => literalBigIntSchema.parse({}); - expect(f).toThrow(); -}); - -test("literal symbol", () => { - util.assertEqual, typeof MySymbol>(true); - literalSymbolSchema.parse(MySymbol); - expect(() => literalSymbolSchema.parse(Symbol("asdf"))).toThrow(); -}); - -test("parse stringSchema string", () => { - stringSchema.parse(val.string); -}); - -test("parse stringSchema number", () => { - const f = () => stringSchema.parse(val.number); - expect(f).toThrow(); -}); - -test("parse stringSchema boolean", () => { - const f = () => stringSchema.parse(val.boolean); - expect(f).toThrow(); -}); - -test("parse stringSchema undefined", () => { - const f = () => stringSchema.parse(val.undefined); - expect(f).toThrow(); -}); - -test("parse stringSchema null", () => { - const f = () => stringSchema.parse(val.null); - expect(f).toThrow(); -}); - -test("parse numberSchema string", () => { - const f = () => numberSchema.parse(val.string); - expect(f).toThrow(); -}); - -test("parse numberSchema number", () => { - numberSchema.parse(val.number); -}); - -test("parse numberSchema bigint", () => { - const f = () => numberSchema.parse(val.bigint); - expect(f).toThrow(); -}); - -test("parse numberSchema boolean", () => { - const f = () => numberSchema.parse(val.boolean); - expect(f).toThrow(); -}); - -test("parse numberSchema undefined", () => { - const f = () => numberSchema.parse(val.undefined); - expect(f).toThrow(); -}); - -test("parse numberSchema null", () => { - const f = () => numberSchema.parse(val.null); - expect(f).toThrow(); -}); - -test("parse bigintSchema string", () => { - const f = () => bigintSchema.parse(val.string); - expect(f).toThrow(); -}); - -test("parse bigintSchema number", () => { - const f = () => bigintSchema.parse(val.number); - expect(f).toThrow(); -}); - -test("parse bigintSchema bigint", () => { - bigintSchema.parse(val.bigint); -}); - -test("parse bigintSchema boolean", () => { - const f = () => bigintSchema.parse(val.boolean); - expect(f).toThrow(); -}); - -test("parse bigintSchema undefined", () => { - const f = () => bigintSchema.parse(val.undefined); - expect(f).toThrow(); -}); - -test("parse bigintSchema null", () => { - const f = () => bigintSchema.parse(val.null); - expect(f).toThrow(); -}); - -test("parse booleanSchema string", () => { - const f = () => booleanSchema.parse(val.string); - expect(f).toThrow(); -}); - -test("parse booleanSchema number", () => { - const f = () => booleanSchema.parse(val.number); - expect(f).toThrow(); -}); - -test("parse booleanSchema boolean", () => { - booleanSchema.parse(val.boolean); -}); - -test("parse booleanSchema undefined", () => { - const f = () => booleanSchema.parse(val.undefined); - expect(f).toThrow(); -}); - -test("parse booleanSchema null", () => { - const f = () => booleanSchema.parse(val.null); - expect(f).toThrow(); -}); - -// ============== - -test("parse dateSchema string", () => { - const f = () => dateSchema.parse(val.string); - expect(f).toThrow(); -}); - -test("parse dateSchema number", () => { - const f = () => dateSchema.parse(val.number); - expect(f).toThrow(); -}); - -test("parse dateSchema boolean", () => { - const f = () => dateSchema.parse(val.boolean); - expect(f).toThrow(); -}); - -test("parse dateSchema date", () => { - dateSchema.parse(val.date); -}); - -test("parse dateSchema undefined", () => { - const f = () => dateSchema.parse(val.undefined); - expect(f).toThrow(); -}); - -test("parse dateSchema null", () => { - const f = () => dateSchema.parse(val.null); - expect(f).toThrow(); -}); - -test("parse dateSchema invalid date", async () => { - try { - await dateSchema.parseAsync(new Date("invalid")); - } catch (err) { - expect((err as z.ZodError).issues[0].code).toEqual(z.ZodIssueCode.invalid_date); - } -}); -// ============== - -test("parse symbolSchema string", () => { - const f = () => symbolSchema.parse(val.string); - expect(f).toThrow(); -}); - -test("parse symbolSchema number", () => { - const f = () => symbolSchema.parse(val.number); - expect(f).toThrow(); -}); - -test("parse symbolSchema boolean", () => { - const f = () => symbolSchema.parse(val.boolean); - expect(f).toThrow(); -}); - -test("parse symbolSchema date", () => { - const f = () => symbolSchema.parse(val.date); - expect(f).toThrow(); -}); - -test("parse symbolSchema symbol", () => { - symbolSchema.parse(val.symbol); -}); - -test("parse symbolSchema undefined", () => { - const f = () => symbolSchema.parse(val.undefined); - expect(f).toThrow(); -}); - -test("parse symbolSchema null", () => { - const f = () => symbolSchema.parse(val.null); - expect(f).toThrow(); -}); - -// ============== - -test("parse undefinedSchema string", () => { - const f = () => undefinedSchema.parse(val.string); - expect(f).toThrow(); -}); - -test("parse undefinedSchema number", () => { - const f = () => undefinedSchema.parse(val.number); - expect(f).toThrow(); -}); - -test("parse undefinedSchema boolean", () => { - const f = () => undefinedSchema.parse(val.boolean); - expect(f).toThrow(); -}); - -test("parse undefinedSchema undefined", () => { - undefinedSchema.parse(val.undefined); -}); - -test("parse undefinedSchema null", () => { - const f = () => undefinedSchema.parse(val.null); - expect(f).toThrow(); -}); - -test("parse nullSchema string", () => { - const f = () => nullSchema.parse(val.string); - expect(f).toThrow(); -}); - -test("parse nullSchema number", () => { - const f = () => nullSchema.parse(val.number); - expect(f).toThrow(); -}); - -test("parse nullSchema boolean", () => { - const f = () => nullSchema.parse(val.boolean); - expect(f).toThrow(); -}); - -test("parse nullSchema undefined", () => { - const f = () => nullSchema.parse(val.undefined); - expect(f).toThrow(); -}); - -test("parse nullSchema null", () => { - nullSchema.parse(val.null); -}); - -test("primitive inference", () => { - util.assertEqual, "asdf">(true); - util.assertEqual, 12>(true); - util.assertEqual, true>(true); - util.assertEqual, bigint>(true); - util.assertEqual, string>(true); - util.assertEqual, number>(true); - util.assertEqual, bigint>(true); - util.assertEqual, boolean>(true); - util.assertEqual, Date>(true); - util.assertEqual, symbol>(true); - - util.assertEqual, null>(true); - util.assertEqual, undefined>(true); - util.assertEqual, string | undefined>(true); - util.assertEqual, string | null>(true); - util.assertEqual, number | undefined>(true); - util.assertEqual, number | null>(true); - util.assertEqual, bigint | undefined>(true); - util.assertEqual, bigint | null>(true); - util.assertEqual, boolean | undefined>(true); - util.assertEqual, boolean | null>(true); - util.assertEqual, Date | undefined>(true); - util.assertEqual, Date | null>(true); - util.assertEqual, symbol | undefined>(true); - util.assertEqual, symbol | null>(true); - - // [ - // literalStringSchemaTest, - // literalNumberSchemaTest, - // literalBooleanSchemaTest, - // literalBigIntSchemaTest, - // stringSchemaTest, - // numberSchemaTest, - // bigintSchemaTest, - // booleanSchemaTest, - // dateSchemaTest, - // symbolSchemaTest, - - // nullSchemaTest, - // undefinedSchemaTest, - // stringSchemaOptionalTest, - // stringSchemaNullableTest, - // numberSchemaOptionalTest, - // numberSchemaNullableTest, - // bigintSchemaOptionalTest, - // bigintSchemaNullableTest, - // booleanSchemaOptionalTest, - // booleanSchemaNullableTest, - // dateSchemaOptionalTest, - // dateSchemaNullableTest, - // symbolSchemaOptionalTest, - // symbolSchemaNullableTest, - - // ]; -}); - -test("get literal value", () => { - expect(literalStringSchema.value).toEqual("asdf"); -}); - -test("optional convenience method", () => { - z.ostring().parse(undefined); - z.onumber().parse(undefined); - z.oboolean().parse(undefined); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/promise.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/promise.test.ts deleted file mode 100644 index 23b6de178..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/promise.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -const promSchema = z.promise( - z.object({ - name: z.string(), - age: z.number(), - }) -); - -test("promise inference", () => { - type promSchemaType = z.infer; - util.assertEqual>(true); -}); - -test("promise parsing success", async () => { - const pr = promSchema.parse(Promise.resolve({ name: "Bobby", age: 10 })); - expect(pr).toBeInstanceOf(Promise); - const result = await pr; - expect(typeof result).toBe("object"); - expect(typeof result.age).toBe("number"); - expect(typeof result.name).toBe("string"); -}); - -test("promise parsing success 2", () => { - const fakePromise = { - then() { - return this; - }, - catch() { - return this; - }, - }; - promSchema.parse(fakePromise); -}); - -test("promise parsing fail", async () => { - const bad = promSchema.parse(Promise.resolve({ name: "Bobby", age: "10" })); - // return await expect(bad).resolves.toBe({ name: 'Bobby', age: '10' }); - return await expect(bad).rejects.toBeInstanceOf(z.ZodError); - // done(); -}); - -test("promise parsing fail 2", async () => { - const failPromise = promSchema.parse(Promise.resolve({ name: "Bobby", age: "10" })); - await expect(failPromise).rejects.toBeInstanceOf(z.ZodError); - // done();/z -}); - -test("promise parsing fail", () => { - const bad = () => promSchema.parse({ then: () => {}, catch: {} }); - expect(bad).toThrow(); -}); - -// test('sync promise parsing', () => { -// expect(() => z.promise(z.string()).parse(Promise.resolve('asfd'))).toThrow(); -// }); - -const asyncFunction = z.function(z.tuple([]), promSchema); - -test("async function pass", async () => { - const validatedFunction = asyncFunction.implement(async () => { - return { name: "jimmy", age: 14 }; - }); - await expect(validatedFunction()).resolves.toEqual({ - name: "jimmy", - age: 14, - }); -}); - -test("async function fail", async () => { - const validatedFunction = asyncFunction.implement(() => { - return Promise.resolve("asdf" as any); - }); - await expect(validatedFunction()).rejects.toBeInstanceOf(z.ZodError); -}); - -test("async promise parsing", () => { - const res = z.promise(z.number()).parseAsync(Promise.resolve(12)); - expect(res).toBeInstanceOf(Promise); -}); - -test("resolves", () => { - const foo = z.literal("foo"); - const res = z.promise(foo); - expect(res.unwrap()).toEqual(foo); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/readonly.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/readonly.test.ts deleted file mode 100644 index 5078955f4..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/readonly.test.ts +++ /dev/null @@ -1,194 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -enum testEnum { - A = 0, - B = 1, -} - -const schemas = [ - z.string().readonly(), - z.number().readonly(), - z.nan().readonly(), - z.bigint().readonly(), - z.boolean().readonly(), - z.date().readonly(), - z.undefined().readonly(), - z.null().readonly(), - z.any().readonly(), - z.unknown().readonly(), - z.void().readonly(), - z.function().args(z.string(), z.number()).readonly(), - - z.array(z.string()).readonly(), - z.tuple([z.string(), z.number()]).readonly(), - z.map(z.string(), z.date()).readonly(), - z.set(z.promise(z.string())).readonly(), - z.record(z.string()).readonly(), - z.record(z.string(), z.number()).readonly(), - z.object({ a: z.string(), 1: z.number() }).readonly(), - z.nativeEnum(testEnum).readonly(), - z.promise(z.string()).readonly(), -] as const; - -test("flat inference", () => { - util.assertEqual, string>(true); - util.assertEqual, number>(true); - util.assertEqual, number>(true); - util.assertEqual, bigint>(true); - util.assertEqual, boolean>(true); - util.assertEqual, Date>(true); - util.assertEqual, undefined>(true); - util.assertEqual, null>(true); - util.assertEqual, any>(true); - util.assertEqual, Readonly>(true); - util.assertEqual, void>(true); - util.assertEqual, (args_0: string, args_1: number, ...args_2: unknown[]) => unknown>( - true - ); - util.assertEqual, readonly string[]>(true); - - util.assertEqual, readonly [string, number]>(true); - util.assertEqual, ReadonlyMap>(true); - util.assertEqual, ReadonlySet>>(true); - util.assertEqual, Readonly>>(true); - util.assertEqual, Readonly>>(true); - util.assertEqual, { readonly a: string; readonly 1: number }>(true); - util.assertEqual, Readonly>(true); - util.assertEqual, Promise>(true); -}); - -// test("deep inference", () => { -// util.assertEqual, string>(true); -// util.assertEqual, number>(true); -// util.assertEqual, number>(true); -// util.assertEqual, bigint>(true); -// util.assertEqual, boolean>(true); -// util.assertEqual, Date>(true); -// util.assertEqual, undefined>(true); -// util.assertEqual, null>(true); -// util.assertEqual, any>(true); -// util.assertEqual< -// z.infer<(typeof deepReadonlySchemas_0)[9]>, -// Readonly -// >(true); -// util.assertEqual, void>(true); -// util.assertEqual< -// z.infer<(typeof deepReadonlySchemas_0)[11]>, -// (args_0: string, args_1: number, ...args_2: unknown[]) => unknown -// >(true); -// util.assertEqual< -// z.infer<(typeof deepReadonlySchemas_0)[12]>, -// readonly string[] -// >(true); -// util.assertEqual< -// z.infer<(typeof deepReadonlySchemas_0)[13]>, -// readonly [string, number] -// >(true); -// util.assertEqual< -// z.infer<(typeof deepReadonlySchemas_0)[14]>, -// ReadonlyMap -// >(true); -// util.assertEqual< -// z.infer<(typeof deepReadonlySchemas_0)[15]>, -// ReadonlySet> -// >(true); -// util.assertEqual< -// z.infer<(typeof deepReadonlySchemas_0)[16]>, -// Readonly> -// >(true); -// util.assertEqual< -// z.infer<(typeof deepReadonlySchemas_0)[17]>, -// Readonly> -// >(true); -// util.assertEqual< -// z.infer<(typeof deepReadonlySchemas_0)[18]>, -// { readonly a: string; readonly 1: number } -// >(true); -// util.assertEqual< -// z.infer<(typeof deepReadonlySchemas_0)[19]>, -// Readonly -// >(true); -// util.assertEqual< -// z.infer<(typeof deepReadonlySchemas_0)[20]>, -// Promise -// >(true); - -// util.assertEqual< -// z.infer, -// ReadonlyMap< -// ReadonlySet, -// { -// readonly a: { -// readonly [x: string]: readonly any[]; -// }; -// readonly b: { -// readonly c: { -// readonly d: { -// readonly e: { -// readonly f: { -// readonly g?: {}; -// }; -// }; -// }; -// }; -// }; -// } -// > -// >(true); -// }); - -test("object freezing", () => { - expect(Object.isFrozen(z.array(z.string()).readonly().parse(["a"]))).toBe(true); - expect(Object.isFrozen(z.tuple([z.string(), z.number()]).readonly().parse(["a", 1]))).toBe(true); - expect( - Object.isFrozen( - z - .map(z.string(), z.date()) - .readonly() - .parse(new Map([["a", new Date()]])) - ) - ).toBe(true); - expect( - Object.isFrozen( - z - .set(z.promise(z.string())) - .readonly() - .parse(new Set([Promise.resolve("a")])) - ) - ).toBe(true); - expect(Object.isFrozen(z.record(z.string()).readonly().parse({ a: "b" }))).toBe(true); - expect(Object.isFrozen(z.record(z.string(), z.number()).readonly().parse({ a: 1 }))).toBe(true); - expect(Object.isFrozen(z.object({ a: z.string(), 1: z.number() }).readonly().parse({ a: "b", 1: 2 }))).toBe(true); - expect(Object.isFrozen(z.promise(z.string()).readonly().parse(Promise.resolve("a")))).toBe(true); -}); - -test("async object freezing", async () => { - expect(Object.isFrozen(await z.array(z.string()).readonly().parseAsync(["a"]))).toBe(true); - expect(Object.isFrozen(await z.tuple([z.string(), z.number()]).readonly().parseAsync(["a", 1]))).toBe(true); - expect( - Object.isFrozen( - await z - .map(z.string(), z.date()) - .readonly() - .parseAsync(new Map([["a", new Date()]])) - ) - ).toBe(true); - expect( - Object.isFrozen( - await z - .set(z.promise(z.string())) - .readonly() - .parseAsync(new Set([Promise.resolve("a")])) - ) - ).toBe(true); - expect(Object.isFrozen(await z.record(z.string()).readonly().parseAsync({ a: "b" }))).toBe(true); - expect(Object.isFrozen(await z.record(z.string(), z.number()).readonly().parseAsync({ a: 1 }))).toBe(true); - expect( - Object.isFrozen(await z.object({ a: z.string(), 1: z.number() }).readonly().parseAsync({ a: "b", 1: 2 })) - ).toBe(true); - expect(Object.isFrozen(await z.promise(z.string()).readonly().parseAsync(Promise.resolve("a")))).toBe(true); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/record.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/record.test.ts deleted file mode 100644 index 83c363f33..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/record.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -const booleanRecord = z.record(z.boolean()); -type booleanRecord = z.infer; - -const recordWithEnumKeys = z.record(z.enum(["Tuna", "Salmon"]), z.string()); -type recordWithEnumKeys = z.infer; - -const recordWithLiteralKeys = z.record(z.union([z.literal("Tuna"), z.literal("Salmon")]), z.string()); -type recordWithLiteralKeys = z.infer; - -test("type inference", () => { - util.assertEqual>(true); - - util.assertEqual>>(true); - - util.assertEqual>>(true); -}); - -test("methods", () => { - booleanRecord.optional(); - booleanRecord.nullable(); -}); - -test("string record parse - pass", () => { - booleanRecord.parse({ - k1: true, - k2: false, - 1234: false, - }); -}); - -test("string record parse - fail", () => { - const badCheck = () => - booleanRecord.parse({ - asdf: 1234, - } as any); - expect(badCheck).toThrow(); - - expect(() => booleanRecord.parse("asdf")).toThrow(); -}); - -test("string record parse - fail", () => { - const badCheck = () => - booleanRecord.parse({ - asdf: {}, - } as any); - expect(badCheck).toThrow(); -}); - -test("string record parse - fail", () => { - const badCheck = () => - booleanRecord.parse({ - asdf: [], - } as any); - expect(badCheck).toThrow(); -}); - -test("key schema", () => { - const result1 = recordWithEnumKeys.parse({ - Tuna: "asdf", - Salmon: "asdf", - }); - expect(result1).toEqual({ - Tuna: "asdf", - Salmon: "asdf", - }); - - const result2 = recordWithLiteralKeys.parse({ - Tuna: "asdf", - Salmon: "asdf", - }); - expect(result2).toEqual({ - Tuna: "asdf", - Salmon: "asdf", - }); - - // shouldn't require us to specify all props in record - const result3 = recordWithEnumKeys.parse({ - Tuna: "abcd", - }); - expect(result3).toEqual({ - Tuna: "abcd", - }); - - // shouldn't require us to specify all props in record - const result4 = recordWithLiteralKeys.parse({ - Salmon: "abcd", - }); - expect(result4).toEqual({ - Salmon: "abcd", - }); - - expect(() => - recordWithEnumKeys.parse({ - Tuna: "asdf", - Salmon: "asdf", - Trout: "asdf", - }) - ).toThrow(); - - expect(() => - recordWithLiteralKeys.parse({ - Tuna: "asdf", - Salmon: "asdf", - - Trout: "asdf", - }) - ).toThrow(); -}); - -// test("record element", () => { -// expect(booleanRecord.element).toBeInstanceOf(z.ZodBoolean); -// }); - -test("key and value getters", () => { - const rec = z.record(z.string(), z.number()); - - rec.keySchema.parse("asdf"); - rec.valueSchema.parse(1234); - rec.element.parse(1234); -}); - -test("is not vulnerable to prototype pollution", async () => { - const rec = z.record( - z.object({ - a: z.string(), - }) - ); - - const data = JSON.parse(` - { - "__proto__": { - "a": "evil" - }, - "b": { - "a": "good" - } - } - `); - - const obj1 = rec.parse(data); - expect(obj1.a).toBeUndefined(); - - const obj2 = rec.safeParse(data); - expect(obj2.success).toBe(true); - if (obj2.success) { - expect(obj2.data.a).toBeUndefined(); - } - - const obj3 = await rec.parseAsync(data); - expect(obj3.a).toBeUndefined(); - - const obj4 = await rec.safeParseAsync(data); - expect(obj4.success).toBe(true); - if (obj4.success) { - expect(obj4.data.a).toBeUndefined(); - } -}); - -test("dont parse undefined values", () => { - const result1 = z.record(z.any()).parse({ foo: undefined }); - - expect(result1).toEqual({ - foo: undefined, - }); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/recursive.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/recursive.test.ts deleted file mode 100644 index f5bb1088a..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/recursive.test.ts +++ /dev/null @@ -1,197 +0,0 @@ -// @ts-ignore TS6133 -import { test } from "vitest"; - -import { z } from "zod/v3"; - -interface Category { - name: string; - subcategories: Category[]; -} - -const testCategory: Category = { - name: "I", - subcategories: [ - { - name: "A", - subcategories: [ - { - name: "1", - subcategories: [ - { - name: "a", - subcategories: [], - }, - ], - }, - ], - }, - ], -}; - -test("recursion with z.late.object", () => { - const Category: z.ZodType = z.late.object(() => ({ - name: z.string(), - subcategories: z.array(Category), - })); - Category.parse(testCategory); -}); - -test("recursion with z.lazy", () => { - const Category: z.ZodType = z.lazy(() => - z.object({ - name: z.string(), - subcategories: z.array(Category), - }) - ); - Category.parse(testCategory); -}); - -test("schema getter", () => { - z.lazy(() => z.string()).schema.parse("asdf"); -}); - -type LinkedList = null | { value: number; next: LinkedList }; - -const linkedListExample = { - value: 1, - next: { - value: 2, - next: { - value: 3, - next: { - value: 4, - next: null, - }, - }, - }, -}; - -test("recursion involving union type", () => { - const LinkedListSchema: z.ZodType = z.lazy(() => - z.union([ - z.null(), - z.object({ - value: z.number(), - next: LinkedListSchema, - }), - ]) - ); - LinkedListSchema.parse(linkedListExample); -}); - -// interface A { -// val: number; -// b: B; -// } - -// interface B { -// val: number; -// a: A; -// } - -// const A: z.ZodType = z.late.object(() => ({ -// val: z.number(), -// b: B, -// })); - -// const B: z.ZodType = z.late.object(() => ({ -// val: z.number(), -// a: A, -// })); - -// const Alazy: z.ZodType = z.lazy(() => z.object({ -// val: z.number(), -// b: B, -// })); - -// const Blazy: z.ZodType = z.lazy(() => z.object({ -// val: z.number(), -// a: A, -// })); - -// const a: any = { val: 1 }; -// const b: any = { val: 2 }; -// a.b = b; -// b.a = a; - -// test('valid check', () => { -// A.parse(a); -// B.parse(b); -// }); - -// test("valid check lazy", () => { -// A.parse({val:1, b:}); -// B.parse(b); -// }); - -// test('masking check', () => { -// const FragmentOnA = z -// .object({ -// val: z.number(), -// b: z -// .object({ -// val: z.number(), -// a: z -// .object({ -// val: z.number(), -// }) -// .nonstrict(), -// }) -// .nonstrict(), -// }) -// .nonstrict(); - -// const fragment = FragmentOnA.parse(a); -// fragment; -// }); - -// test('invalid check', () => { -// expect(() => A.parse({} as any)).toThrow(); -// }); - -// test('schema getter', () => { -// (A as z.ZodLazy).schema; -// }); - -// test("self recursion with cyclical data", () => { -// interface Category { -// name: string; -// subcategories: Category[]; -// } - -// const Category: z.ZodType = z.late.object(() => ({ -// name: z.string(), -// subcategories: z.array(Category), -// })); - -// const untypedCategory: any = { -// name: "Category A", -// }; -// // creating a cycle -// untypedCategory.subcategories = [untypedCategory]; -// Category.parse(untypedCategory); -// }); - -// test("self recursion with base type", () => { -// const BaseCategory = z.object({ -// name: z.string(), -// }); -// type BaseCategory = z.infer; - -// type Category = BaseCategory & { subcategories: Category[] }; - -// const Category: z.ZodType = z.late -// .object(() => ({ -// subcategories: z.array(Category), -// })) -// .extend({ -// name: z.string(), -// }); - -// const untypedCategory: any = { -// name: "Category A", -// }; -// // creating a cycle -// untypedCategory.subcategories = [untypedCategory]; -// Category.parse(untypedCategory); // parses successfully -// }); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/refine.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/refine.test.ts deleted file mode 100644 index 55c27fea5..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/refine.test.ts +++ /dev/null @@ -1,313 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { ZodIssueCode } from "../ZodError.js"; -import { util } from "../helpers/util.js"; - -test("refinement", () => { - const obj1 = z.object({ - first: z.string(), - second: z.string(), - }); - const obj2 = obj1.partial().strict(); - - const obj3 = obj2.refine((data) => data.first || data.second, "Either first or second should be filled in."); - - expect(obj1 === (obj2 as any)).toEqual(false); - expect(obj2 === (obj3 as any)).toEqual(false); - - expect(() => obj1.parse({})).toThrow(); - expect(() => obj2.parse({ third: "adsf" })).toThrow(); - expect(() => obj3.parse({})).toThrow(); - obj3.parse({ first: "a" }); - obj3.parse({ second: "a" }); - obj3.parse({ first: "a", second: "a" }); -}); - -test("refinement 2", () => { - const validationSchema = z - .object({ - email: z.string().email(), - password: z.string(), - confirmPassword: z.string(), - }) - .refine((data) => data.password === data.confirmPassword, "Both password and confirmation must match"); - - expect(() => - validationSchema.parse({ - email: "aaaa@gmail.com", - password: "aaaaaaaa", - confirmPassword: "bbbbbbbb", - }) - ).toThrow(); -}); - -test("refinement type guard", () => { - const validationSchema = z.object({ - a: z.string().refine((s): s is "a" => s === "a"), - }); - type Input = z.input; - type Schema = z.infer; - - util.assertEqual<"a", Input["a"]>(false); - util.assertEqual(true); - - util.assertEqual<"a", Schema["a"]>(true); - util.assertEqual(false); -}); - -test("refinement Promise", async () => { - const validationSchema = z - .object({ - email: z.string().email(), - password: z.string(), - confirmPassword: z.string(), - }) - .refine( - (data) => Promise.resolve().then(() => data.password === data.confirmPassword), - "Both password and confirmation must match" - ); - - await validationSchema.parseAsync({ - email: "aaaa@gmail.com", - password: "password", - confirmPassword: "password", - }); -}); - -test("custom path", async () => { - const result = await z - .object({ - password: z.string(), - confirm: z.string(), - }) - .refine((data) => data.confirm === data.password, { path: ["confirm"] }) - .spa({ password: "asdf", confirm: "qewr" }); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].path).toEqual(["confirm"]); - } -}); - -test("use path in refinement context", async () => { - const noNested = z.string()._refinement((_val, ctx) => { - if (ctx.path.length > 0) { - ctx.addIssue({ - code: ZodIssueCode.custom, - message: `schema cannot be nested. path: ${ctx.path.join(".")}`, - }); - return false; - } else { - return true; - } - }); - - const data = z.object({ - foo: noNested, - }); - - const t1 = await noNested.spa("asdf"); - const t2 = await data.spa({ foo: "asdf" }); - - expect(t1.success).toBe(true); - expect(t2.success).toBe(false); - if (t2.success === false) { - expect(t2.error.issues[0].message).toEqual("schema cannot be nested. path: foo"); - } -}); - -test("superRefine", () => { - const Strings = z.array(z.string()).superRefine((val, ctx) => { - if (val.length > 3) { - ctx.addIssue({ - code: z.ZodIssueCode.too_big, - maximum: 3, - type: "array", - inclusive: true, - exact: true, - message: "Too many items 😡", - }); - } - - if (val.length !== new Set(val).size) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: `No duplicates allowed.`, - }); - } - }); - - const result = Strings.safeParse(["asfd", "asfd", "asfd", "asfd"]); - - expect(result.success).toEqual(false); - if (!result.success) expect(result.error.issues.length).toEqual(2); - - Strings.parse(["asfd", "qwer"]); -}); - -test("superRefine async", async () => { - const Strings = z.array(z.string()).superRefine(async (val, ctx) => { - if (val.length > 3) { - ctx.addIssue({ - code: z.ZodIssueCode.too_big, - maximum: 3, - type: "array", - inclusive: true, - exact: true, - message: "Too many items 😡", - }); - } - - if (val.length !== new Set(val).size) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: `No duplicates allowed.`, - }); - } - }); - - const result = await Strings.safeParseAsync(["asfd", "asfd", "asfd", "asfd"]); - - expect(result.success).toEqual(false); - if (!result.success) expect(result.error.issues.length).toEqual(2); - - Strings.parseAsync(["asfd", "qwer"]); -}); - -test("superRefine - type narrowing", () => { - type NarrowType = { type: string; age: number }; - const schema = z - .object({ - type: z.string(), - age: z.number(), - }) - .nullable() - .superRefine((arg, ctx): arg is NarrowType => { - if (!arg) { - // still need to make a call to ctx.addIssue - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: "cannot be null", - fatal: true, - }); - return false; - } - return true; - }); - - util.assertEqual, NarrowType>(true); - - expect(schema.safeParse({ type: "test", age: 0 }).success).toEqual(true); - expect(schema.safeParse(null).success).toEqual(false); -}); - -test("chained mixed refining types", () => { - type firstRefinement = { first: string; second: number; third: true }; - type secondRefinement = { first: "bob"; second: number; third: true }; - type thirdRefinement = { first: "bob"; second: 33; third: true }; - const schema = z - .object({ - first: z.string(), - second: z.number(), - third: z.boolean(), - }) - .nullable() - .refine((arg): arg is firstRefinement => !!arg?.third) - .superRefine((arg, ctx): arg is secondRefinement => { - util.assertEqual(true); - if (arg.first !== "bob") { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: "`first` property must be `bob`", - }); - return false; - } - return true; - }) - .refine((arg): arg is thirdRefinement => { - util.assertEqual(true); - return arg.second === 33; - }); - - util.assertEqual, thirdRefinement>(true); -}); - -test("get inner type", () => { - z.string() - .refine(() => true) - .innerType() - .parse("asdf"); -}); - -test("chained refinements", () => { - const objectSchema = z - .object({ - length: z.number(), - size: z.number(), - }) - .refine(({ length }) => length > 5, { - path: ["length"], - message: "length greater than 5", - }) - .refine(({ size }) => size > 7, { - path: ["size"], - message: "size greater than 7", - }); - const r1 = objectSchema.safeParse({ - length: 4, - size: 9, - }); - expect(r1.success).toEqual(false); - if (!r1.success) expect(r1.error.issues.length).toEqual(1); - - const r2 = objectSchema.safeParse({ - length: 4, - size: 3, - }); - expect(r2.success).toEqual(false); - if (!r2.success) expect(r2.error.issues.length).toEqual(2); -}); - -test("fatal superRefine", () => { - const Strings = z - .string() - .superRefine((val, ctx) => { - if (val === "") { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: "foo", - fatal: true, - }); - } - }) - .superRefine((val, ctx) => { - if (val !== " ") { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: "bar", - }); - } - }); - - const result = Strings.safeParse(""); - - expect(result.success).toEqual(false); - if (!result.success) expect(result.error.issues.length).toEqual(1); -}); - -test("superRefine after skipped transform", () => { - const schema = z - .string() - .regex(/^\d+$/) - .transform((val) => Number(val)) - .superRefine((val) => { - if (typeof val !== "number") { - throw new Error("Called without transform"); - } - }); - - const result = schema.safeParse(""); - - expect(result.success).toEqual(false); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/safeparse.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/safeparse.test.ts deleted file mode 100644 index 950a2df5e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/safeparse.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -const stringSchema = z.string(); - -test("safeparse fail", () => { - const safe = stringSchema.safeParse(12); - expect(safe.success).toEqual(false); - expect(safe.error).toBeInstanceOf(z.ZodError); -}); - -test("safeparse pass", () => { - const safe = stringSchema.safeParse("12"); - expect(safe.success).toEqual(true); - expect(safe.data).toEqual("12"); -}); - -test("safeparse unexpected error", () => { - expect(() => - stringSchema - .refine((data) => { - throw new Error(data); - }) - .safeParse("12") - ).toThrow(); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/set.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/set.test.ts deleted file mode 100644 index 890cdd205..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/set.test.ts +++ /dev/null @@ -1,142 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { ZodIssueCode } from "zod/v3"; -import { util } from "../helpers/util.js"; - -const stringSet = z.set(z.string()); -type stringSet = z.infer; - -const minTwo = z.set(z.string()).min(2); -const maxTwo = z.set(z.string()).max(2); -const justTwo = z.set(z.string()).size(2); -const nonEmpty = z.set(z.string()).nonempty(); -const nonEmptyMax = z.set(z.string()).nonempty().max(2); - -test("type inference", () => { - util.assertEqual>(true); -}); - -test("valid parse", () => { - const result = stringSet.safeParse(new Set(["first", "second"])); - expect(result.success).toEqual(true); - if (result.success) { - expect(result.data.has("first")).toEqual(true); - expect(result.data.has("second")).toEqual(true); - expect(result.data.has("third")).toEqual(false); - } - - expect(() => { - minTwo.parse(new Set(["a", "b"])); - minTwo.parse(new Set(["a", "b", "c"])); - maxTwo.parse(new Set(["a", "b"])); - maxTwo.parse(new Set(["a"])); - justTwo.parse(new Set(["a", "b"])); - nonEmpty.parse(new Set(["a"])); - nonEmptyMax.parse(new Set(["a"])); - }).not.toThrow(); -}); - -test("valid parse async", async () => { - const result = await stringSet.spa(new Set(["first", "second"])); - expect(result.success).toEqual(true); - if (result.success) { - expect(result.data.has("first")).toEqual(true); - expect(result.data.has("second")).toEqual(true); - expect(result.data.has("third")).toEqual(false); - } - - const asyncResult = await stringSet.safeParse(new Set(["first", "second"])); - expect(asyncResult.success).toEqual(true); - if (asyncResult.success) { - expect(asyncResult.data.has("first")).toEqual(true); - expect(asyncResult.data.has("second")).toEqual(true); - expect(asyncResult.data.has("third")).toEqual(false); - } -}); - -test("valid parse: size-related methods", () => { - expect(() => { - minTwo.parse(new Set(["a", "b"])); - minTwo.parse(new Set(["a", "b", "c"])); - maxTwo.parse(new Set(["a", "b"])); - maxTwo.parse(new Set(["a"])); - justTwo.parse(new Set(["a", "b"])); - nonEmpty.parse(new Set(["a"])); - nonEmptyMax.parse(new Set(["a"])); - }).not.toThrow(); - - const sizeZeroResult = stringSet.parse(new Set()); - expect(sizeZeroResult.size).toBe(0); - - const sizeTwoResult = minTwo.parse(new Set(["a", "b"])); - expect(sizeTwoResult.size).toBe(2); -}); - -test("failing when parsing empty set in nonempty ", () => { - const result = nonEmpty.safeParse(new Set()); - expect(result.success).toEqual(false); - - if (result.success === false) { - expect(result.error.issues.length).toEqual(1); - expect(result.error.issues[0].code).toEqual(ZodIssueCode.too_small); - } -}); - -test("failing when set is smaller than min() ", () => { - const result = minTwo.safeParse(new Set(["just_one"])); - expect(result.success).toEqual(false); - - if (result.success === false) { - expect(result.error.issues.length).toEqual(1); - expect(result.error.issues[0].code).toEqual(ZodIssueCode.too_small); - } -}); - -test("failing when set is bigger than max() ", () => { - const result = maxTwo.safeParse(new Set(["one", "two", "three"])); - expect(result.success).toEqual(false); - - if (result.success === false) { - expect(result.error.issues.length).toEqual(1); - expect(result.error.issues[0].code).toEqual(ZodIssueCode.too_big); - } -}); - -test("doesn’t throw when an empty set is given", () => { - const result = stringSet.safeParse(new Set([])); - expect(result.success).toEqual(true); -}); - -test("throws when a Map is given", () => { - const result = stringSet.safeParse(new Map([])); - expect(result.success).toEqual(false); - if (result.success === false) { - expect(result.error.issues.length).toEqual(1); - expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type); - } -}); - -test("throws when the given set has invalid input", () => { - const result = stringSet.safeParse(new Set([Symbol()])); - expect(result.success).toEqual(false); - if (result.success === false) { - expect(result.error.issues.length).toEqual(1); - expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type); - expect(result.error.issues[0].path).toEqual([0]); - } -}); - -test("throws when the given set has multiple invalid entries", () => { - const result = stringSet.safeParse(new Set([1, 2] as any[]) as Set); - - expect(result.success).toEqual(false); - if (result.success === false) { - expect(result.error.issues.length).toEqual(2); - expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type); - expect(result.error.issues[0].path).toEqual([0]); - expect(result.error.issues[1].code).toEqual(ZodIssueCode.invalid_type); - expect(result.error.issues[1].path).toEqual([1]); - } -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/standard-schema.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/standard-schema.test.ts deleted file mode 100644 index 74b3d2ba6..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/standard-schema.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -// import type { StandardSchemaV1 } from "@standard-schema/spec"; -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; -import type { StandardSchemaV1 } from "../standard-schema.js"; - -test("assignability", () => { - const _s1: StandardSchemaV1 = z.string(); - const _s2: StandardSchemaV1 = z.string(); - const _s3: StandardSchemaV1 = z.string(); - const _s4: StandardSchemaV1 = z.string(); - [_s1, _s2, _s3, _s4]; -}); - -test("type inference", () => { - const stringToNumber = z.string().transform((x) => x.length); - type input = StandardSchemaV1.InferInput; - util.assertEqual(true); - type output = StandardSchemaV1.InferOutput; - util.assertEqual(true); -}); - -test("valid parse", () => { - const schema = z.string(); - const result = schema["~standard"].validate("hello"); - if (result instanceof Promise) { - throw new Error("Expected sync result"); - } - expect(result.issues).toEqual(undefined); - if (result.issues) { - throw new Error("Expected no issues"); - } else { - expect(result.value).toEqual("hello"); - } -}); - -test("invalid parse", () => { - const schema = z.string(); - const result = schema["~standard"].validate(1234); - if (result instanceof Promise) { - throw new Error("Expected sync result"); - } - expect(result.issues).toBeDefined(); - if (!result.issues) { - throw new Error("Expected issues"); - } - expect(result.issues.length).toEqual(1); - expect(result.issues[0].path).toEqual([]); -}); - -test("valid parse async", async () => { - const schema = z.string().refine(async () => true); - const _result = schema["~standard"].validate("hello"); - if (_result instanceof Promise) { - const result = await _result; - expect(result.issues).toEqual(undefined); - if (result.issues) { - throw new Error("Expected no issues"); - } else { - expect(result.value).toEqual("hello"); - } - } else { - throw new Error("Expected async result"); - } -}); - -test("invalid parse async", async () => { - const schema = z.string().refine(async () => false); - const _result = schema["~standard"].validate("hello"); - if (_result instanceof Promise) { - const result = await _result; - expect(result.issues).toBeDefined(); - if (!result.issues) { - throw new Error("Expected issues"); - } - expect(result.issues.length).toEqual(1); - expect(result.issues[0].path).toEqual([]); - } else { - throw new Error("Expected async result"); - } -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/string.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/string.test.ts deleted file mode 100644 index 2d712e10d..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/string.test.ts +++ /dev/null @@ -1,916 +0,0 @@ -import { Buffer } from "node:buffer"; -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -const minFive = z.string().min(5, "min5"); -const maxFive = z.string().max(5, "max5"); -const justFive = z.string().length(5); -const nonempty = z.string().nonempty("nonempty"); -const includes = z.string().includes("includes"); -const includesFromIndex2 = z.string().includes("includes", { position: 2 }); -const startsWith = z.string().startsWith("startsWith"); -const endsWith = z.string().endsWith("endsWith"); - -test("passing validations", () => { - minFive.parse("12345"); - minFive.parse("123456"); - maxFive.parse("12345"); - maxFive.parse("1234"); - nonempty.parse("1"); - justFive.parse("12345"); - includes.parse("XincludesXX"); - includesFromIndex2.parse("XXXincludesXX"); - startsWith.parse("startsWithX"); - endsWith.parse("XendsWith"); -}); - -test("failing validations", () => { - expect(() => minFive.parse("1234")).toThrow(); - expect(() => maxFive.parse("123456")).toThrow(); - expect(() => nonempty.parse("")).toThrow(); - expect(() => justFive.parse("1234")).toThrow(); - expect(() => justFive.parse("123456")).toThrow(); - expect(() => includes.parse("XincludeXX")).toThrow(); - expect(() => includesFromIndex2.parse("XincludesXX")).toThrow(); - expect(() => startsWith.parse("x")).toThrow(); - expect(() => endsWith.parse("x")).toThrow(); -}); - -test("email validations", () => { - const validEmails = [ - `email@domain.com`, - `firstname.lastname@domain.com`, - `email@subdomain.domain.com`, - `firstname+lastname@domain.com`, - `1234567890@domain.com`, - `email@domain-one.com`, - `_______@domain.com`, - `email@domain.name`, - `email@domain.co.jp`, - `firstname-lastname@domain.com`, - `very.common@example.com`, - `disposable.style.email.with+symbol@example.com`, - `other.email-with-hyphen@example.com`, - `fully-qualified-domain@example.com`, - `user.name+tag+sorting@example.com`, - `x@example.com`, - `mojojojo@asdf.example.com`, - `example-indeed@strange-example.com`, - `example@s.example`, - `user-@example.org`, - `user@my-example.com`, - `a@b.cd`, - `work+user@mail.com`, - `tom@test.te-st.com`, - `something@subdomain.domain-with-hyphens.tld`, - `common'name@domain.com`, - `francois@etu.inp-n7.fr`, - ]; - const invalidEmails = [ - // no "printable characters" - // `user%example.com@example.org`, - // `mailhost!username@example.org`, - // `test/test@test.com`, - - // double @ - `francois@@etu.inp-n7.fr`, - // do not support quotes - `"email"@domain.com`, - `"e asdf sadf ?<>ail"@domain.com`, - `" "@example.org`, - `"john..doe"@example.org`, - `"very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual"@strange.example.com`, - // do not support comma - `a,b@domain.com`, - - // do not support IPv4 - `email@123.123.123.123`, - `email@[123.123.123.123]`, - `postmaster@123.123.123.123`, - `user@[68.185.127.196]`, - `ipv4@[85.129.96.247]`, - `valid@[79.208.229.53]`, - `valid@[255.255.255.255]`, - `valid@[255.0.55.2]`, - `valid@[255.0.55.2]`, - - // do not support ipv6 - `hgrebert0@[IPv6:4dc8:ac7:ce79:8878:1290:6098:5c50:1f25]`, - `bshapiro4@[IPv6:3669:c709:e981:4884:59a3:75d1:166b:9ae]`, - `jsmith@[IPv6:2001:db8::1]`, - `postmaster@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:7334]`, - `postmaster@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:192.168.1.1]`, - - // microsoft test cases - `plainaddress`, - `#@%^%#$@#$@#.com`, - `@domain.com`, - `Joe Smith <email@domain.com>`, - `email.domain.com`, - `email@domain@domain.com`, - `.email@domain.com`, - `email.@domain.com`, - `email..email@domain.com`, - `あいうえお@domain.com`, - `email@domain.com (Joe Smith)`, - `email@domain`, - `email@-domain.com`, - `email@111.222.333.44444`, - `email@domain..com`, - `Abc.example.com`, - `A@b@c@example.com`, - `colin..hacks@domain.com`, - `a"b(c)d,e:f;gi[j\k]l@example.com`, - `just"not"right@example.com`, - `this is"not\allowed@example.com`, - `this\ still\"not\\allowed@example.com`, - - // random - `i_like_underscore@but_its_not_allowed_in_this_part.example.com`, - `QA[icon]CHOCOLATE[icon]@test.com`, - `invalid@-start.com`, - `invalid@end.com-`, - `a.b@c.d`, - `invalid@[1.1.1.-1]`, - `invalid@[68.185.127.196.55]`, - `temp@[192.168.1]`, - `temp@[9.18.122.]`, - `double..point@test.com`, - `asdad@test..com`, - `asdad@hghg...sd...au`, - `asdad@hghg........au`, - `invalid@[256.2.2.48]`, - `invalid@[256.2.2.48]`, - `invalid@[999.465.265.1]`, - `jkibbey4@[IPv6:82c4:19a8::70a9:2aac:557::ea69:d985:28d]`, - `mlivesay3@[9952:143f:b4df:2179:49a1:5e82:b92e:6b6]`, - `gbacher0@[IPv6:bc37:4d3f:5048:2e26:37cc:248e:df8e:2f7f:af]`, - `invalid@[IPv6:5348:4ed3:5d38:67fb:e9b:acd2:c13:192.168.256.1]`, - `test@.com`, - `aaaaaaaaaaaaaaalongemailthatcausesregexDoSvulnerability@test.c`, - ]; - const emailSchema = z.string().email(); - - expect( - validEmails.every((email) => { - return emailSchema.safeParse(email).success; - }) - ).toBe(true); - expect( - invalidEmails.every((email) => { - return emailSchema.safeParse(email).success === false; - }) - ).toBe(true); -}); - -const validBase64Strings = [ - "SGVsbG8gV29ybGQ=", // "Hello World" - "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==", // "This is an encoded string" - "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms=", // "Many hands make light work" - "UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // "Patience is the key to success" - "QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // "Base64 encoding is fun" - "MTIzNDU2Nzg5MA==", // "1234567890" - "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=", // "abcdefghijklmnopqrstuvwxyz" - "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=", // "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "ISIkJSMmJyonKCk=", // "!\"#$%&'()*" - "", // Empty string is technically valid base64 - "w7/Dv8O+w74K", // ÿÿþþ -]; - -for (const str of validBase64Strings) { - test(`base64 should accept ${str}`, () => { - expect(z.string().base64().safeParse(str).success).toBe(true); - }); -} - -const invalidBase64Strings = [ - "12345", // Not padded correctly, not a multiple of 4 characters - "12345===", // Not padded correctly - "SGVsbG8gV29ybGQ", // Missing padding - "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw", // Missing padding - "!UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // Invalid character '!' - "?QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // Invalid character '?' - ".MTIzND2Nzg5MC4=", // Invalid character '.' - "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo", // Missing padding - "w7_Dv8O-w74K", // Has - and _ characters (is base64url) -]; - -for (const str of invalidBase64Strings) { - test(`base64 should reject ${str}`, () => { - expect(z.string().base64().safeParse(str).success).toBe(false); - }); -} - -const validBase64URLStrings = [ - "SGVsbG8gV29ybGQ", // "Hello World" - "SGVsbG8gV29ybGQ=", // "Hello World" with padding - "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw", // "This is an encoded string" - "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==", // "This is an encoded string" with padding - "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms", // "Many hands make light work" - "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms=", // "Many hands make light work" with padding - "UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // "Patience is the key to success" - "QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg", // "Base64 encoding is fun" - "QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // "Base64 encoding is fun" with padding - "MTIzNDU2Nzg5MA", // "1234567890" - "MTIzNDU2Nzg5MA==", // "1234567890" with padding - "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo", // "abcdefghijklmnopqrstuvwxyz" - "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=", // "abcdefghijklmnopqrstuvwxyz with padding" - "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo", // "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=", // "ABCDEFGHIJKLMNOPQRSTUVWXYZ" with padding - "ISIkJSMmJyonKCk", // "!\"#$%&'()*" - "ISIkJSMmJyonKCk=", // "!\"#$%&'()*" with padding - "", // Empty string is technically valid base64url - "w7_Dv8O-w74K", // ÿÿþþ - "123456", -]; - -for (const str of validBase64URLStrings) { - test(`base64url should accept ${str}`, () => { - expect(z.string().base64url().safeParse(str).success).toBe(true); - }); -} - -const invalidBase64URLStrings = [ - "w7/Dv8O+w74K", // Has + and / characters (is base64) - "12345", // Invalid length (not a multiple of 4 characters when adding allowed number of padding characters) - "12345===", // Not padded correctly - "!UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // Invalid character '!' - "?QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // Invalid character '?' - ".MTIzND2Nzg5MC4=", // Invalid character '.' -]; - -for (const str of invalidBase64URLStrings) { - test(`base64url should reject ${str}`, () => { - expect(z.string().base64url().safeParse(str).success).toBe(false); - }); -} - -function makeJwt(header: object, payload: object) { - const headerBase64 = Buffer.from(JSON.stringify(header)).toString("base64url"); - const payloadBase64 = Buffer.from(JSON.stringify(payload)).toString("base64url"); - const signature = "signature"; // Placeholder for the signature - return `${headerBase64}.${payloadBase64}.${signature}`; -} - -test("jwt validations", () => { - const jwt = z.string().jwt(); - const jwtWithAlg = z.string().jwt({ alg: "HS256" }); - - expect(() => jwt.parse("invalid")).toThrow(); - expect(() => jwt.parse("invalid.invalid")).toThrow(); - expect(() => jwt.parse("invalid.invalid.invalid")).toThrow(); - - // Valid JWTs - const d1 = makeJwt({ typ: "JWT", alg: "HS256" }, {}); - expect(() => jwt.parse(d1)).not.toThrow(); - expect(() => jwtWithAlg.parse(d1)).not.toThrow(); - - // Invalid header - const d2 = makeJwt({}, {}); - expect(() => jwt.parse(d2)).toThrow(); - - // Wrong algorithm - const d3 = makeJwt({ typ: "JWT", alg: "RS256" }, {}); - expect(() => jwtWithAlg.parse(d3)).toThrow(); - - // missing typ is fine - const d4 = makeJwt({ alg: "HS256" }, {}); - jwt.parse(d4); - - // type isn't JWT - const d5 = makeJwt({ typ: "SUP", alg: "HS256" }, { foo: "bar" }); - expect(() => jwt.parse(d5)).toThrow(); - - // Custom error message - const customMsg = "Invalid JWT token"; - const jwtWithMsg = z.string().jwt({ message: customMsg }); - try { - jwtWithMsg.parse("invalid"); - } catch (error) { - expect((error as z.ZodError).issues[0].message).toBe(customMsg); - } -}); - -test("url validations", () => { - const url = z.string().url(); - url.parse("http://google.com"); - url.parse("https://google.com/asdf?asdf=ljk3lk4&asdf=234#asdf"); - expect(() => url.parse("asdf")).toThrow(); - expect(() => url.parse("https:/")).toThrow(); - expect(() => url.parse("asdfj@lkjsdf.com")).toThrow(); -}); - -test("url error overrides", () => { - try { - z.string().url().parse("https"); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("Invalid url"); - } - try { - z.string().url("badurl").parse("https"); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("badurl"); - } - try { - z.string().url({ message: "badurl" }).parse("https"); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("badurl"); - } -}); - -test("emoji validations", () => { - const emoji = z.string().emoji(); - - emoji.parse("👋👋👋👋"); - emoji.parse("🍺👩‍🚀🫡"); - emoji.parse("💚💙💜💛❤️"); - emoji.parse("🐛🗝🐏🍡🎦🚢🏨💫🎌☘🗡😹🔒🎬➡️🍹🗂🚨⚜🕑〽️🚦🌊🍴💍🍌💰😳🌺🍃"); - emoji.parse("🇹🇷🤽🏿‍♂️"); - emoji.parse( - "😀😁😂🤣😃😄😅😆😉😊😋😎😍😘🥰😗😙😚☺️☺🙂🤗🤩🤔🤨😐😑😶🙄😏😣😥😮🤐😯😪😫😴😌😛😜😝🤤😒😓😔😕🙃🤑😲☹️☹🙁😖😞😟😤😢😭😦😧😨😩🤯😬😰😱🥵🥶😳🤪😵😡😠🤬😷🤒🤕🤢🤮🤧😇🤠🥳🥴🥺🤥🤫🤭🧐🤓😈👿🤡👹👺💀☠️☠👻👽👾🤖💩😺😸😹😻😼😽🙀😿😾🙈🙉🙊🏻🏼🏽🏾🏿👶👶🏻👶🏼👶🏽👶🏾👶🏿🧒🧒🏻🧒🏼🧒🏽🧒🏾🧒🏿👦👦🏻👦🏼👦🏽👦🏾👦🏿👧👧🏻👧🏼👧🏽👧🏾👧🏿🧑🧑🏻🧑🏼🧑🏽🧑🏾🧑🏿👨👨🏻👨🏼👨🏽👨🏾👨🏿👩👩🏻👩🏼👩🏽👩🏾👩🏿🧓🧓🏻🧓🏼🧓🏽🧓🏾🧓🏿👴👴🏻👴🏼👴🏽👴🏾👴🏿👵👵🏻👵🏼👵🏽👵🏾👵🏿👨‍⚕️👨‍⚕👨🏻‍⚕️👨🏻‍⚕👨🏼‍⚕️👨🏼‍⚕👨🏽‍⚕️👨🏽‍⚕👨🏾‍⚕️👨🏾‍⚕👨🏿‍⚕️👨🏿‍⚕👩‍⚕️👩‍⚕👩🏻‍⚕️👩🏻‍⚕👩🏼‍⚕️👩🏼‍⚕👩🏽‍⚕️👩🏽‍⚕👩🏾‍⚕️👩🏾‍⚕👩🏿‍⚕️👩🏿‍⚕👨‍🎓👨🏻‍🎓👨🏼‍🎓👨🏽‍🎓👨🏾‍🎓👨🏿‍🎓👩‍🎓👩🏻‍🎓👩🏼‍🎓👩🏽‍🎓👩🏾‍🎓👩🏿‍🎓👨‍🏫👨🏻‍🏫👨🏼‍🏫👨🏽‍🏫👨🏾‍🏫👨🏿‍🏫👩‍🏫👩🏻‍🏫👩🏼‍🏫👩🏽‍🏫👩🏾‍🏫👩🏿‍🏫👨‍⚖️👨‍⚖👨🏻‍⚖️👨🏻‍⚖👨🏼‍⚖️👨🏼‍⚖👨🏽‍⚖️👨🏽‍⚖👨🏾‍⚖️👨🏾‍⚖👨🏿‍⚖️👨🏿‍⚖👩‍⚖️👩‍⚖👩🏻‍⚖️👩🏻‍⚖👩🏼‍⚖️👩🏼‍⚖👩🏽‍⚖️👩🏽‍⚖👩🏾‍⚖️👩🏾‍⚖👩🏿‍⚖️👩🏿‍⚖👨‍🌾👨🏻‍🌾👨🏼‍🌾👨🏽‍🌾👨🏾‍🌾👨🏿‍🌾👩‍🌾👩🏻‍🌾👩🏼‍🌾👩🏽‍🌾👩🏾‍🌾👩🏿‍🌾👨‍🍳👨🏻‍🍳👨🏼‍🍳👨🏽‍🍳👨🏾‍🍳👨🏿‍🍳👩‍🍳👩🏻‍🍳👩🏼‍🍳👩🏽‍🍳👩🏾‍🍳👩🏿‍🍳👨‍🔧👨🏻‍🔧👨🏼‍🔧👨🏽‍🔧👨🏾‍🔧👨🏿‍🔧👩‍🔧👩🏻‍🔧👩🏼‍🔧👩🏽‍🔧👩🏾‍🔧👩🏿‍🔧👨‍🏭👨🏻‍🏭👨🏼‍🏭👨🏽‍🏭👨🏾‍🏭👨🏿‍🏭👩‍🏭👩🏻‍🏭👩🏼‍🏭👩🏽‍🏭👩🏾‍🏭👩🏿‍🏭👨‍💼👨🏻‍💼👨🏼‍💼👨🏽‍💼👨🏾‍💼👨🏿‍💼👩‍💼👩🏻‍💼👩🏼‍💼👩🏽‍💼👩🏾‍💼👩🏿‍💼👨‍🔬👨🏻‍🔬👨🏼‍🔬👨🏽‍🔬👨🏾‍🔬👨🏿‍🔬👩‍🔬👩🏻‍🔬👩🏼‍🔬👩🏽‍🔬👩🏾‍🔬👩🏿‍🔬👨‍💻👨🏻‍💻👨🏼‍💻👨🏽‍💻👨🏾‍💻👨🏿‍💻👩‍💻👩🏻‍💻👩🏼‍💻👩🏽‍💻👩🏾‍💻👩🏿‍💻👨‍🎤👨🏻‍🎤👨🏼‍🎤👨🏽‍🎤👨🏾‍🎤👨🏿‍🎤👩‍🎤👩🏻‍🎤👩🏼‍🎤👩🏽‍🎤👩🏾‍🎤👩🏿‍🎤👨‍🎨👨🏻‍🎨👨🏼‍🎨👨🏽‍🎨👨🏾‍🎨👨🏿‍🎨👩‍🎨👩🏻‍🎨👩🏼‍🎨👩🏽‍🎨👩🏾‍🎨👩🏿‍🎨👨‍✈️👨‍✈👨🏻‍✈️👨🏻‍✈👨🏼‍✈️👨🏼‍✈👨🏽‍✈️👨🏽‍✈👨🏾‍✈️👨🏾‍✈👨🏿‍✈️👨🏿‍✈👩‍✈️👩‍✈👩🏻‍✈️👩🏻‍✈👩🏼‍✈️👩🏼‍✈👩🏽‍✈️👩🏽‍✈👩🏾‍✈️👩🏾‍✈👩🏿‍✈️👩🏿‍✈👨‍🚀👨🏻‍🚀👨🏼‍🚀👨🏽‍🚀👨🏾‍🚀👨🏿‍🚀👩‍🚀👩🏻‍🚀👩🏼‍🚀👩🏽‍🚀👩🏾‍🚀👩🏿‍🚀👨‍🚒👨🏻‍🚒👨🏼‍🚒👨🏽‍🚒👨🏾‍🚒👨🏿‍🚒👩‍🚒👩🏻‍🚒👩🏼‍🚒👩🏽‍🚒👩🏾‍🚒👩🏿‍🚒👮👮🏻👮🏼👮🏽👮🏾👮🏿👮‍♂️👮‍♂👮🏻‍♂️👮🏻‍♂👮🏼‍♂️👮🏼‍♂👮🏽‍♂️👮🏽‍♂👮🏾‍♂️👮🏾‍♂👮🏿‍♂️👮🏿‍♂👮‍♀️👮‍♀👮🏻‍♀️👮🏻‍♀👮🏼‍♀️👮🏼‍♀👮🏽‍♀️👮🏽‍♀👮🏾‍♀️👮🏾‍♀👮🏿‍♀️👮🏿‍♀🕵️🕵🕵🏻🕵🏼🕵🏽🕵🏾🕵🏿🕵️‍♂️🕵‍♂️🕵️‍♂🕵‍♂🕵🏻‍♂️🕵🏻‍♂🕵🏼‍♂️🕵🏼‍♂🕵🏽‍♂️🕵🏽‍♂🕵🏾‍♂️🕵🏾‍♂🕵🏿‍♂️🕵🏿‍♂🕵️‍♀️🕵‍♀️🕵️‍♀🕵‍♀🕵🏻‍♀️🕵🏻‍♀🕵🏼‍♀️🕵🏼‍♀🕵🏽‍♀️🕵🏽‍♀🕵🏾‍♀️🕵🏾‍♀🕵🏿‍♀️🕵🏿‍♀💂💂🏻💂🏼💂🏽💂🏾💂🏿💂‍♂️💂‍♂💂🏻‍♂️💂🏻‍♂💂🏼‍♂️💂🏼‍♂💂🏽‍♂️💂🏽‍♂💂🏾‍♂️💂🏾‍♂💂🏿‍♂️💂🏿‍♂💂‍♀️💂‍♀💂🏻‍♀️💂🏻‍♀💂🏼‍♀️💂🏼‍♀💂🏽‍♀️💂🏽‍♀💂🏾‍♀️💂🏾‍♀💂🏿‍♀️💂🏿‍♀👷👷🏻👷🏼👷🏽👷🏾👷🏿👷‍♂️👷‍♂👷🏻‍♂️👷🏻‍♂👷🏼‍♂️👷🏼‍♂👷🏽‍♂️👷🏽‍♂👷🏾‍♂️👷🏾‍♂👷🏿‍♂️👷🏿‍♂👷‍♀️👷‍♀👷🏻‍♀️👷🏻‍♀👷🏼‍♀️👷🏼‍♀👷🏽‍♀️👷🏽‍♀👷🏾‍♀️👷🏾‍♀👷🏿‍♀️👷🏿‍♀🤴🤴🏻🤴🏼🤴🏽🤴🏾🤴🏿👸👸🏻👸🏼👸🏽👸🏾👸🏿👳👳🏻👳🏼👳🏽👳🏾👳🏿👳‍♂️👳‍♂👳🏻‍♂️👳🏻‍♂👳🏼‍♂️👳🏼‍♂👳🏽‍♂️👳🏽‍♂👳🏾‍♂️👳🏾‍♂👳🏿‍♂️👳🏿‍♂👳‍♀️👳‍♀👳🏻‍♀️👳🏻‍♀👳🏼‍♀️👳🏼‍♀👳🏽‍♀️👳🏽‍♀👳🏾‍♀️👳🏾‍♀👳🏿‍♀️👳🏿‍♀👲👲🏻👲🏼👲🏽👲🏾👲🏿🧕🧕🏻🧕🏼🧕🏽🧕🏾🧕🏿🧔🧔🏻🧔🏼🧔🏽🧔🏾🧔🏿👱👱🏻👱🏼👱🏽👱🏾👱🏿👱‍♂️👱‍♂👱🏻‍♂️👱🏻‍♂👱🏼‍♂️👱🏼‍♂👱🏽‍♂️👱🏽‍♂👱🏾‍♂️👱🏾‍♂👱🏿‍♂️👱🏿‍♂👱‍♀️👱‍♀👱🏻‍♀️👱🏻‍♀👱🏼‍♀️👱🏼‍♀👱🏽‍♀️👱🏽‍♀👱🏾‍♀️👱🏾‍♀👱🏿‍♀️👱🏿‍♀👨‍🦰👨🏻‍🦰👨🏼‍🦰👨🏽‍🦰👨🏾‍🦰👨🏿‍🦰👩‍🦰👩🏻‍🦰👩🏼‍🦰👩🏽‍🦰👩🏾‍🦰👩🏿‍🦰👨‍🦱👨🏻‍🦱👨🏼‍🦱👨🏽‍🦱👨🏾‍🦱👨🏿‍🦱👩‍🦱👩🏻‍🦱👩🏼‍🦱👩🏽‍🦱👩🏾‍🦱👩🏿‍🦱👨‍🦲👨🏻‍🦲👨🏼‍🦲👨🏽‍🦲👨🏾‍🦲👨🏿‍🦲👩‍🦲👩🏻‍🦲👩🏼‍🦲👩🏽‍🦲👩🏾‍🦲👩🏿‍🦲👨‍🦳👨🏻‍🦳👨🏼‍🦳👨🏽‍🦳👨🏾‍🦳👨🏿‍🦳👩‍🦳👩🏻‍🦳👩🏼‍🦳👩🏽‍🦳👩🏾‍🦳👩🏿‍🦳🤵🤵🏻🤵🏼🤵🏽🤵🏾🤵🏿👰👰🏻👰🏼👰🏽👰🏾👰🏿🤰🤰🏻🤰🏼🤰🏽🤰🏾🤰🏿🤱🤱🏻🤱🏼🤱🏽🤱🏾🤱🏿👼👼🏻👼🏼👼🏽👼🏾👼🏿🎅🎅🏻🎅🏼🎅🏽🎅🏾🎅🏿🤶🤶🏻🤶🏼🤶🏽🤶🏾🤶🏿🦸🦸🏻🦸🏼🦸🏽🦸🏾🦸🏿🦸‍♀️🦸‍♀🦸🏻‍♀️🦸🏻‍♀🦸🏼‍♀️🦸🏼‍♀🦸🏽‍♀️🦸🏽‍♀🦸🏾‍♀️🦸🏾‍♀🦸🏿‍♀️🦸🏿‍♀🦸‍♂️🦸‍♂🦸🏻‍♂️🦸🏻‍♂🦸🏼‍♂️🦸🏼‍♂🦸🏽‍♂️🦸🏽‍♂🦸🏾‍♂️🦸🏾‍♂🦸🏿‍♂️🦸🏿‍♂🦹🦹🏻🦹🏼🦹🏽🦹🏾🦹🏿🦹‍♀️🦹‍♀🦹🏻‍♀️🦹🏻‍♀🦹🏼‍♀️🦹🏼‍♀🦹🏽‍♀️🦹🏽‍♀🦹🏾‍♀️🦹🏾‍♀🦹🏿‍♀️🦹🏿‍♀🦹‍♂️🦹‍♂🦹🏻‍♂️🦹🏻‍♂🦹🏼‍♂️🦹🏼‍♂🦹🏽‍♂️🦹🏽‍♂🦹🏾‍♂️🦹🏾‍♂🦹🏿‍♂️🦹🏿‍♂🧙🧙🏻🧙🏼🧙🏽🧙🏾🧙🏿🧙‍♀️🧙‍♀🧙🏻‍♀️🧙🏻‍♀🧙🏼‍♀️🧙🏼‍♀🧙🏽‍♀️🧙🏽‍♀🧙🏾‍♀️🧙🏾‍♀🧙🏿‍♀️🧙🏿‍♀🧙‍♂️🧙‍♂🧙🏻‍♂️🧙🏻‍♂🧙🏼‍♂️🧙🏼‍♂🧙🏽‍♂️🧙🏽‍♂🧙🏾‍♂️🧙🏾‍♂🧙🏿‍♂️🧙🏿‍♂🧚🧚🏻🧚🏼🧚🏽🧚🏾🧚🏿🧚‍♀️🧚‍♀🧚🏻‍♀️🧚🏻‍♀🧚🏼‍♀️🧚🏼‍♀🧚🏽‍♀️🧚🏽‍♀🧚🏾‍♀️🧚🏾‍♀🧚🏿‍♀️🧚🏿‍♀🧚‍♂️🧚‍♂🧚🏻‍♂️🧚🏻‍♂🧚🏼‍♂️🧚🏼‍♂🧚🏽‍♂️🧚🏽‍♂🧚🏾‍♂️🧚🏾‍♂🧚🏿‍♂️🧚🏿‍♂🧛🧛🏻🧛🏼🧛🏽🧛🏾🧛🏿🧛‍♀️🧛‍♀🧛🏻‍♀️🧛🏻‍♀🧛🏼‍♀️🧛🏼‍♀🧛🏽‍♀️🧛🏽‍♀🧛🏾‍♀️🧛🏾‍♀🧛🏿‍♀️🧛🏿‍♀🧛‍♂️🧛‍♂🧛🏻‍♂️🧛🏻‍♂🧛🏼‍♂️🧛🏼‍♂🧛🏽‍♂️🧛🏽‍♂🧛🏾‍♂️🧛🏾‍♂🧛🏿‍♂️🧛🏿‍♂🧜🧜🏻🧜🏼🧜🏽🧜🏾🧜🏿🧜‍♀️🧜‍♀🧜🏻‍♀️🧜🏻‍♀🧜🏼‍♀️🧜🏼‍♀🧜🏽‍♀️🧜🏽‍♀🧜🏾‍♀️🧜🏾‍♀🧜🏿‍♀️🧜🏿‍♀🧜‍♂️🧜‍♂🧜🏻‍♂️🧜🏻‍♂🧜🏼‍♂️🧜🏼‍♂🧜🏽‍♂️🧜🏽‍♂🧜🏾‍♂️🧜🏾‍♂🧜🏿‍♂️🧜🏿‍♂🧝🧝🏻🧝🏼🧝🏽🧝🏾🧝🏿🧝‍♀️🧝‍♀🧝🏻‍♀️🧝🏻‍♀🧝🏼‍♀️🧝🏼‍♀🧝🏽‍♀️🧝🏽‍♀🧝🏾‍♀️🧝🏾‍♀🧝🏿‍♀️🧝🏿‍♀🧝‍♂️🧝‍♂🧝🏻‍♂️🧝🏻‍♂🧝🏼‍♂️🧝🏼‍♂🧝🏽‍♂️🧝🏽‍♂🧝🏾‍♂️🧝🏾‍♂🧝🏿‍♂️🧝🏿‍♂🧞🧞‍♀️🧞‍♀🧞‍♂️🧞‍♂🧟🧟‍♀️🧟‍♀🧟‍♂️🧟‍♂🙍🙍🏻🙍🏼🙍🏽🙍🏾🙍🏿🙍‍♂️🙍‍♂🙍🏻‍♂️🙍🏻‍♂🙍🏼‍♂️🙍🏼‍♂🙍🏽‍♂️🙍🏽‍♂🙍🏾‍♂️🙍🏾‍♂🙍🏿‍♂️🙍🏿‍♂🙍‍♀️🙍‍♀🙍🏻‍♀️🙍🏻‍♀🙍🏼‍♀️🙍🏼‍♀🙍🏽‍♀️🙍🏽‍♀🙍🏾‍♀️🙍🏾‍♀🙍🏿‍♀️🙍🏿‍♀🙎🙎🏻🙎🏼🙎🏽🙎🏾🙎🏿🙎‍♂️🙎‍♂🙎🏻‍♂️🙎🏻‍♂🙎🏼‍♂️🙎🏼‍♂🙎🏽‍♂️🙎🏽‍♂🙎🏾‍♂️🙎🏾‍♂🙎🏿‍♂️🙎🏿‍♂🙎‍♀️🙎‍♀🙎🏻‍♀️🙎🏻‍♀🙎🏼‍♀️🙎🏼‍♀🙎🏽‍♀️🙎🏽‍♀🙎🏾‍♀️🙎🏾‍♀🙎🏿‍♀️🙎🏿‍♀🙅🙅🏻🙅🏼🙅🏽🙅🏾🙅🏿🙅‍♂️🙅‍♂🙅🏻‍♂️🙅🏻‍♂🙅🏼‍♂️🙅🏼‍♂🙅🏽‍♂️🙅🏽‍♂🙅🏾‍♂️🙅🏾‍♂🙅🏿‍♂️🙅🏿‍♂🙅‍♀️🙅‍♀🙅🏻‍♀️🙅🏻‍♀🙅🏼‍♀️🙅🏼‍♀🙅🏽‍♀️🙅🏽‍♀🙅🏾‍♀️🙅🏾‍♀🙅🏿‍♀️🙅🏿‍♀🙆🙆🏻🙆🏼🙆🏽🙆🏾🙆🏿🙆‍♂️🙆‍♂🙆🏻‍♂️🙆🏻‍♂🙆🏼‍♂️🙆🏼‍♂🙆🏽‍♂️🙆🏽‍♂🙆🏾‍♂️🙆🏾‍♂🙆🏿‍♂️🙆🏿‍♂🙆‍♀️🙆‍♀🙆🏻‍♀️🙆🏻‍♀🙆🏼‍♀️🙆🏼‍♀🙆🏽‍♀️🙆🏽‍♀🙆🏾‍♀️🙆🏾‍♀🙆🏿‍♀️🙆🏿‍♀💁💁🏻💁🏼💁🏽💁🏾💁🏿💁‍♂️💁‍♂💁🏻‍♂️💁🏻‍♂💁🏼‍♂️💁🏼‍♂💁🏽‍♂️💁🏽‍♂💁🏾‍♂️💁🏾‍♂💁🏿‍♂️💁🏿‍♂💁‍♀️💁‍♀💁🏻‍♀️💁🏻‍♀💁🏼‍♀️💁🏼‍♀💁🏽‍♀️💁🏽‍♀💁🏾‍♀️💁🏾‍♀💁🏿‍♀️💁🏿‍♀🙋🙋🏻🙋🏼🙋🏽🙋🏾🙋🏿🙋‍♂️🙋‍♂🙋🏻‍♂️🙋🏻‍♂🙋🏼‍♂️🙋🏼‍♂🙋🏽‍♂️🙋🏽‍♂🙋🏾‍♂️🙋🏾‍♂🙋🏿‍♂️🙋🏿‍♂🙋‍♀️🙋‍♀🙋🏻‍♀️🙋🏻‍♀🙋🏼‍♀️🙋🏼‍♀🙋🏽‍♀️🙋🏽‍♀🙋🏾‍♀️🙋🏾‍♀🙋🏿‍♀️🙋🏿‍♀🙇🙇🏻🙇🏼🙇🏽🙇🏾🙇🏿🙇‍♂️🙇‍♂🙇🏻‍♂️🙇🏻‍♂🙇🏼‍♂️🙇🏼‍♂🙇🏽‍♂️🙇🏽‍♂🙇🏾‍♂️🙇🏾‍♂🙇🏿‍♂️🙇🏿‍♂🙇‍♀️🙇‍♀🙇🏻‍♀️🙇🏻‍♀🙇🏼‍♀️🙇🏼‍♀🙇🏽‍♀️🙇🏽‍♀🙇🏾‍♀️🙇🏾‍♀🙇🏿‍♀️🙇🏿‍♀🤦🤦🏻🤦🏼🤦🏽🤦🏾🤦🏿🤦‍♂️🤦‍♂🤦🏻‍♂️🤦🏻‍♂🤦🏼‍♂️🤦🏼‍♂🤦🏽‍♂️🤦🏽‍♂🤦🏾‍♂️🤦🏾‍♂🤦🏿‍♂️🤦🏿‍♂🤦‍♀️🤦‍♀🤦🏻‍♀️🤦🏻‍♀🤦🏼‍♀️🤦🏼‍♀🤦🏽‍♀️🤦🏽‍♀🤦🏾‍♀️🤦🏾‍♀🤦🏿‍♀️🤦🏿‍♀🤷🤷🏻🤷🏼🤷🏽🤷🏾🤷🏿🤷‍♂️🤷‍♂🤷🏻‍♂️🤷🏻‍♂🤷🏼‍♂️🤷🏼‍♂🤷🏽‍♂️🤷🏽‍♂🤷🏾‍♂️🤷🏾‍♂🤷🏿‍♂️🤷🏿‍♂🤷‍♀️🤷‍♀🤷🏻‍♀️🤷🏻‍♀🤷🏼‍♀️🤷🏼‍♀🤷🏽‍♀️🤷🏽‍♀🤷🏾‍♀️🤷🏾‍♀🤷🏿‍♀️🤷🏿‍♀💆💆🏻💆🏼💆🏽💆🏾💆🏿💆‍♂️💆‍♂💆🏻‍♂️💆🏻‍♂💆🏼‍♂️💆🏼‍♂💆🏽‍♂️💆🏽‍♂💆🏾‍♂️💆🏾‍♂💆🏿‍♂️💆🏿‍♂💆‍♀️💆‍♀💆🏻‍♀️💆🏻‍♀💆🏼‍♀️💆🏼‍♀💆🏽‍♀️💆🏽‍♀💆🏾‍♀️💆🏾‍♀💆🏿‍♀️💆🏿‍♀💇💇🏻💇🏼💇🏽💇🏾💇🏿💇‍♂️💇‍♂💇🏻‍♂️💇🏻‍♂💇🏼‍♂️💇🏼‍♂💇🏽‍♂️💇🏽‍♂💇🏾‍♂️💇🏾‍♂💇🏿‍♂️💇🏿‍♂💇‍♀️💇‍♀💇🏻‍♀️💇🏻‍♀💇🏼‍♀️💇🏼‍♀💇🏽‍♀️💇🏽‍♀💇🏾‍♀️💇🏾‍♀💇🏿‍♀️💇🏿‍♀🚶🚶🏻🚶🏼🚶🏽🚶🏾🚶🏿🚶‍♂️🚶‍♂🚶🏻‍♂️🚶🏻‍♂🚶🏼‍♂️🚶🏼‍♂🚶🏽‍♂️🚶🏽‍♂🚶🏾‍♂️🚶🏾‍♂🚶🏿‍♂️🚶🏿‍♂🚶‍♀️🚶‍♀🚶🏻‍♀️🚶🏻‍♀🚶🏼‍♀️🚶🏼‍♀🚶🏽‍♀️🚶🏽‍♀🚶🏾‍♀️🚶🏾‍♀🚶🏿‍♀️🚶🏿‍♀🏃🏃🏻🏃🏼🏃🏽🏃🏾🏃🏿🏃‍♂️🏃‍♂🏃🏻‍♂️🏃🏻‍♂🏃🏼‍♂️🏃🏼‍♂🏃🏽‍♂️🏃🏽‍♂🏃🏾‍♂️🏃🏾‍♂🏃🏿‍♂️🏃🏿‍♂🏃‍♀️🏃‍♀🏃🏻‍♀️🏃🏻‍♀🏃🏼‍♀️🏃🏼‍♀🏃🏽‍♀️🏃🏽‍♀🏃🏾‍♀️🏃🏾‍♀🏃🏿‍♀️🏃🏿‍♀💃💃🏻💃🏼💃🏽💃🏾💃🏿🕺🕺🏻🕺🏼🕺🏽🕺🏾🕺🏿👯👯‍♂️👯‍♂👯‍♀️👯‍♀🧖🧖🏻🧖🏼🧖🏽🧖🏾🧖🏿🧖‍♀️🧖‍♀🧖🏻‍♀️🧖🏻‍♀🧖🏼‍♀️🧖🏼‍♀🧖🏽‍♀️🧖🏽‍♀🧖🏾‍♀️🧖🏾‍♀🧖🏿‍♀️🧖🏿‍♀🧖‍♂️🧖‍♂🧖🏻‍♂️🧖🏻‍♂🧖🏼‍♂️🧖🏼‍♂🧖🏽‍♂️🧖🏽‍♂🧖🏾‍♂️🧖🏾‍♂🧖🏿‍♂️🧖🏿‍♂🧗🧗🏻🧗🏼🧗🏽🧗🏾🧗🏿🧗‍♀️🧗‍♀🧗🏻‍♀️🧗🏻‍♀🧗🏼‍♀️🧗🏼‍♀🧗🏽‍♀️🧗🏽‍♀🧗🏾‍♀️🧗🏾‍♀🧗🏿‍♀️🧗🏿‍♀🧗‍♂️🧗‍♂🧗🏻‍♂️🧗🏻‍♂🧗🏼‍♂️🧗🏼‍♂🧗🏽‍♂️🧗🏽‍♂🧗🏾‍♂️🧗🏾‍♂🧗🏿‍♂️🧗🏿‍♂🧘🧘🏻🧘🏼🧘🏽🧘🏾🧘🏿🧘‍♀️🧘‍♀🧘🏻‍♀️🧘🏻‍♀🧘🏼‍♀️🧘🏼‍♀🧘🏽‍♀️🧘🏽‍♀🧘🏾‍♀️🧘🏾‍♀🧘🏿‍♀️🧘🏿‍♀🧘‍♂️🧘‍♂🧘🏻‍♂️🧘🏻‍♂🧘🏼‍♂️🧘🏼‍♂🧘🏽‍♂️🧘🏽‍♂🧘🏾‍♂️🧘🏾‍♂🧘🏿‍♂️🧘🏿‍♂🛀🛀🏻🛀🏼🛀🏽🛀🏾🛀🏿🛌🛌🏻🛌🏼🛌🏽🛌🏾🛌🏿🕴️🕴🕴🏻🕴🏼🕴🏽🕴🏾🕴🏿🗣️🗣👤👥🤺🏇🏇🏻🏇🏼🏇🏽🏇🏾🏇🏿⛷️⛷🏂🏂🏻🏂🏼🏂🏽🏂🏾🏂🏿🏌️🏌🏌🏻🏌🏼🏌🏽🏌🏾🏌🏿🏌️‍♂️🏌‍♂️🏌️‍♂🏌‍♂🏌🏻‍♂️🏌🏻‍♂🏌🏼‍♂️🏌🏼‍♂🏌🏽‍♂️🏌🏽‍♂🏌🏾‍♂️🏌🏾‍♂🏌🏿‍♂️🏌🏿‍♂🏌️‍♀️🏌‍♀️🏌️‍♀🏌‍♀🏌🏻‍♀️🏌🏻‍♀🏌🏼‍♀️🏌🏼‍♀🏌🏽‍♀️🏌🏽‍♀🏌🏾‍♀️🏌🏾‍♀🏌🏿‍♀️🏌🏿‍♀🏄🏄🏻🏄🏼🏄🏽🏄🏾🏄🏿🏄‍♂️🏄‍♂🏄🏻‍♂️🏄🏻‍♂🏄🏼‍♂️🏄🏼‍♂🏄🏽‍♂️🏄🏽‍♂🏄🏾‍♂️🏄🏾‍♂🏄🏿‍♂️🏄🏿‍♂🏄‍♀️🏄‍♀🏄🏻‍♀️🏄🏻‍♀🏄🏼‍♀️🏄🏼‍♀🏄🏽‍♀️🏄🏽‍♀🏄🏾‍♀️🏄🏾‍♀🏄🏿‍♀️🏄🏿‍♀🚣🚣🏻🚣🏼🚣🏽🚣🏾🚣🏿🚣‍♂️🚣‍♂🚣🏻‍♂️🚣🏻‍♂🚣🏼‍♂️🚣🏼‍♂🚣🏽‍♂️🚣🏽‍♂🚣🏾‍♂️🚣🏾‍♂🚣🏿‍♂️🚣🏿‍♂🚣‍♀️🚣‍♀🚣🏻‍♀️🚣🏻‍♀🚣🏼‍♀️🚣🏼‍♀🚣🏽‍♀️🚣🏽‍♀🚣🏾‍♀️🚣🏾‍♀🚣🏿‍♀️🚣🏿‍♀🏊🏊🏻🏊🏼🏊🏽🏊🏾🏊🏿🏊‍♂️🏊‍♂🏊🏻‍♂️🏊🏻‍♂🏊🏼‍♂️🏊🏼‍♂🏊🏽‍♂️🏊🏽‍♂🏊🏾‍♂️🏊🏾‍♂🏊🏿‍♂️🏊🏿‍♂🏊‍♀️🏊‍♀🏊🏻‍♀️🏊🏻‍♀🏊🏼‍♀️🏊🏼‍♀🏊🏽‍♀️🏊🏽‍♀🏊🏾‍♀️🏊🏾‍♀🏊🏿‍♀️🏊🏿‍♀⛹️⛹⛹🏻⛹🏼⛹🏽⛹🏾⛹🏿⛹️‍♂️⛹‍♂️⛹️‍♂⛹‍♂⛹🏻‍♂️⛹🏻‍♂⛹🏼‍♂️⛹🏼‍♂⛹🏽‍♂️⛹🏽‍♂⛹🏾‍♂️⛹🏾‍♂⛹🏿‍♂️⛹🏿‍♂⛹️‍♀️⛹‍♀️⛹️‍♀⛹‍♀⛹🏻‍♀️⛹🏻‍♀⛹🏼‍♀️⛹🏼‍♀⛹🏽‍♀️⛹🏽‍♀⛹🏾‍♀️⛹🏾‍♀⛹🏿‍♀️⛹🏿‍♀🏋️🏋🏋🏻🏋🏼🏋🏽🏋🏾🏋🏿🏋️‍♂️🏋‍♂️🏋️‍♂🏋‍♂🏋🏻‍♂️🏋🏻‍♂🏋🏼‍♂️🏋🏼‍♂🏋🏽‍♂️🏋🏽‍♂🏋🏾‍♂️🏋🏾‍♂🏋🏿‍♂️🏋🏿‍♂🏋️‍♀️🏋‍♀️🏋️‍♀🏋‍♀🏋🏻‍♀️🏋🏻‍♀🏋🏼‍♀️🏋🏼‍♀🏋🏽‍♀️🏋🏽‍♀🏋🏾‍♀️🏋🏾‍♀🏋🏿‍♀️🏋🏿‍♀🚴🚴🏻🚴🏼🚴🏽🚴🏾🚴🏿🚴‍♂️🚴‍♂🚴🏻‍♂️🚴🏻‍♂🚴🏼‍♂️🚴🏼‍♂🚴🏽‍♂️🚴🏽‍♂🚴🏾‍♂️🚴🏾‍♂🚴🏿‍♂️🚴🏿‍♂🚴‍♀️🚴‍♀🚴🏻‍♀️🚴🏻‍♀🚴🏼‍♀️🚴🏼‍♀🚴🏽‍♀️🚴🏽‍♀🚴🏾‍♀️🚴🏾‍♀🚴🏿‍♀️🚴🏿‍♀🚵🚵🏻🚵🏼🚵🏽🚵🏾🚵🏿🚵‍♂️🚵‍♂🚵🏻‍♂️🚵🏻‍♂🚵🏼‍♂️🚵🏼‍♂🚵🏽‍♂️🚵🏽‍♂🚵🏾‍♂️🚵🏾‍♂🚵🏿‍♂️🚵🏿‍♂🚵‍♀️🚵‍♀🚵🏻‍♀️🚵🏻‍♀🚵🏼‍♀️🚵🏼‍♀🚵🏽‍♀️🚵🏽‍♀🚵🏾‍♀️🚵🏾‍♀🚵🏿‍♀️🚵🏿‍♀🏎️🏎🏍️🏍🤸🤸🏻🤸🏼🤸🏽🤸🏾🤸🏿🤸‍♂️🤸‍♂🤸🏻‍♂️🤸🏻‍♂🤸🏼‍♂️🤸🏼‍♂🤸🏽‍♂️🤸🏽‍♂🤸🏾‍♂️🤸🏾‍♂🤸🏿‍♂️🤸🏿‍♂🤸‍♀️🤸‍♀🤸🏻‍♀️🤸🏻‍♀🤸🏼‍♀️🤸🏼‍♀🤸🏽‍♀️🤸🏽‍♀🤸🏾‍♀️🤸🏾‍♀🤸🏿‍♀️🤸🏿‍♀🤼🤼‍♂️🤼‍♂🤼‍♀️🤼‍♀🤽🤽🏻🤽🏼🤽🏽🤽🏾🤽🏿🤽‍♂️🤽‍♂🤽🏻‍♂️🤽🏻‍♂🤽🏼‍♂️🤽🏼‍♂🤽🏽‍♂️🤽🏽‍♂🤽🏾‍♂️🤽🏾‍♂🤽🏿‍♂️🤽🏿‍♂🤽‍♀️🤽‍♀🤽🏻‍♀️🤽🏻‍♀🤽🏼‍♀️🤽🏼‍♀🤽🏽‍♀️🤽🏽‍♀🤽🏾‍♀️🤽🏾‍♀🤽🏿‍♀️🤽🏿‍♀🤾🤾🏻🤾🏼🤾🏽🤾🏾🤾🏿🤾‍♂️🤾‍♂🤾🏻‍♂️🤾🏻‍♂🤾🏼‍♂️🤾🏼‍♂🤾🏽‍♂️🤾🏽‍♂🤾🏾‍♂️🤾🏾‍♂🤾🏿‍♂️🤾🏿‍♂🤾‍♀️🤾‍♀🤾🏻‍♀️🤾🏻‍♀🤾🏼‍♀️🤾🏼‍♀🤾🏽‍♀️🤾🏽‍♀🤾🏾‍♀️🤾🏾‍♀🤾🏿‍♀️🤾🏿‍♀🤹🤹🏻🤹🏼🤹🏽🤹🏾🤹🏿🤹‍♂️🤹‍♂🤹🏻‍♂️🤹🏻‍♂🤹🏼‍♂️🤹🏼‍♂🤹🏽‍♂️🤹🏽‍♂🤹🏾‍♂️🤹🏾‍♂🤹🏿‍♂️🤹🏿‍♂🤹‍♀️🤹‍♀🤹🏻‍♀️🤹🏻‍♀🤹🏼‍♀️🤹🏼‍♀🤹🏽‍♀️🤹🏽‍♀🤹🏾‍♀️🤹🏾‍♀🤹🏿‍♀️🤹🏿‍♀👫👬👭💏👩‍❤️‍💋‍👨👩‍❤‍💋‍👨👨‍❤️‍💋‍👨👨‍❤‍💋‍👨👩‍❤️‍💋‍👩👩‍❤‍💋‍👩💑👩‍❤️‍👨👩‍❤‍👨👨‍❤️‍👨👨‍❤‍👨👩‍❤️‍👩👩‍❤‍👩👪👨‍👩‍👦👨‍👩‍👧👨‍👩‍👧‍👦👨‍👩‍👦‍👦👨‍👩‍👧‍👧👨‍👨‍👦👨‍👨‍👧👨‍👨‍👧‍👦👨‍👨‍👦‍👦👨‍👨‍👧‍👧👩‍👩‍👦👩‍👩‍👧👩‍👩‍👧‍👦👩‍👩‍👦‍👦👩‍👩‍👧‍👧👨‍👦👨‍👦‍👦👨‍👧👨‍👧‍👦👨‍👧‍👧👩‍👦👩‍👦‍👦👩‍👧👩‍👧‍👦👩‍👧‍👧🤳🤳🏻🤳🏼🤳🏽🤳🏾🤳🏿💪💪🏻💪🏼💪🏽💪🏾💪🏿🦵🦵🏻🦵🏼🦵🏽🦵🏾🦵🏿🦶🦶🏻🦶🏼🦶🏽🦶🏾🦶🏿👈👈🏻👈🏼👈🏽👈🏾👈🏿👉👉🏻👉🏼👉🏽👉🏾👉🏿☝️☝☝🏻☝🏼☝🏽☝🏾☝🏿👆👆🏻👆🏼👆🏽👆🏾👆🏿🖕🖕🏻🖕🏼🖕🏽🖕🏾🖕🏿👇👇🏻👇🏼👇🏽👇🏾👇🏿✌️✌✌🏻✌🏼✌🏽✌🏾✌🏿🤞🤞🏻🤞🏼🤞🏽🤞🏾🤞🏿🖖🖖🏻🖖🏼🖖🏽🖖🏾🖖🏿🤘🤘🏻🤘🏼🤘🏽🤘🏾🤘🏿🤙🤙🏻🤙🏼🤙🏽🤙🏾🤙🏿🖐️🖐🖐🏻🖐🏼🖐🏽🖐🏾🖐🏿✋✋🏻✋🏼✋🏽✋🏾✋🏿👌👌🏻👌🏼👌🏽👌🏾👌🏿👍👍🏻👍🏼👍🏽👍🏾👍🏿👎👎🏻👎🏼👎🏽👎🏾👎🏿✊✊🏻✊🏼✊🏽✊🏾✊🏿👊👊🏻👊🏼👊🏽👊🏾👊🏿🤛🤛🏻🤛🏼🤛🏽🤛🏾🤛🏿🤜🤜🏻🤜🏼🤜🏽🤜🏾🤜🏿🤚🤚🏻🤚🏼🤚🏽🤚🏾🤚🏿👋👋🏻👋🏼👋🏽👋🏾👋🏿🤟🤟🏻🤟🏼🤟🏽🤟🏾🤟🏿✍️✍✍🏻✍🏼✍🏽✍🏾✍🏿👏👏🏻👏🏼👏🏽👏🏾👏🏿👐👐🏻👐🏼👐🏽👐🏾👐🏿🙌🙌🏻🙌🏼🙌🏽🙌🏾🙌🏿🤲🤲🏻🤲🏼🤲🏽🤲🏾🤲🏿🙏🙏🏻🙏🏼🙏🏽🙏🏾🙏🏿🤝💅💅🏻💅🏼💅🏽💅🏾💅🏿👂👂🏻👂🏼👂🏽👂🏾👂🏿👃👃🏻👃🏼👃🏽👃🏾👃🏿🦰🦱🦲🦳👣👀👁️👁👁️‍🗨️👁‍🗨️👁️‍🗨👁‍🗨🧠🦴🦷👅👄💋💘❤️❤💓💔💕💖💗💙💚💛🧡💜🖤💝💞💟❣️❣💌💤💢💣💥💦💨💫💬🗨️🗨🗯️🗯💭🕳️🕳👓🕶️🕶🥽🥼👔👕👖🧣🧤🧥🧦👗👘👙👚👛👜👝🛍️🛍🎒👞👟🥾🥿👠👡👢👑👒🎩🎓🧢⛑️⛑📿💄💍💎🐵🐒🦍🐶🐕🐩🐺🦊🦝🐱🐈🦁🐯🐅🐆🐴🐎🦄🦓🦌🐮🐂🐃🐄🐷🐖🐗🐽🐏🐑🐐🐪🐫🦙🦒🐘🦏🦛🐭🐁🐀🐹🐰🐇🐿️🐿🦔🦇🐻🐨🐼🦘🦡🐾🦃🐔🐓🐣🐤🐥🐦🐧🕊️🕊🦅🦆🦢🦉🦚🦜🐸🐊🐢🦎🐍🐲🐉🦕🦖🐳🐋🐬🐟🐠🐡🦈🐙🐚🦀🦞🦐🦑🐌🦋🐛🐜🐝🐞🦗🕷️🕷🕸️🕸🦂🦟🦠💐🌸💮🏵️🏵🌹🥀🌺🌻🌼🌷🌱🌲🌳🌴🌵🌾🌿☘️☘🍀🍁🍂🍃🍇🍈🍉🍊🍋🍌🍍🥭🍎🍏🍐🍑🍒🍓🥝🍅🥥🥑🍆🥔🥕🌽🌶️🌶🥒🥬🥦🍄🥜🌰🍞🥐🥖🥨🥯🥞🧀🍖🍗🥩🥓🍔🍟🍕🌭🥪🌮🌯🥙🥚🍳🥘🍲🥣🥗🍿🧂🥫🍱🍘🍙🍚🍛🍜🍝🍠🍢🍣🍤🍥🥮🍡🥟🥠🥡🍦🍧🍨🍩🍪🎂🍰🧁🥧🍫🍬🍭🍮🍯🍼🥛☕🍵🍶🍾🍷🍸🍹🍺🍻🥂🥃🥤🥢🍽️🍽🍴🥄🔪🏺🌍🌎🌏🌐🗺️🗺🗾🧭🏔️🏔⛰️⛰🌋🗻🏕️🏕🏖️🏖🏜️🏜🏝️🏝🏞️🏞🏟️🏟🏛️🏛🏗️🏗🧱🏘️🏘🏚️🏚🏠🏡🏢🏣🏤🏥🏦🏨🏩🏪🏫🏬🏭🏯🏰💒🗼🗽⛪🕌🕍⛩️⛩🕋⛲⛺🌁🌃🏙️🏙🌄🌅🌆🌇🌉♨️♨🌌🎠🎡🎢💈🎪🚂🚃🚄🚅🚆🚇🚈🚉🚊🚝🚞🚋🚌🚍🚎🚐🚑🚒🚓🚔🚕🚖🚗🚘🚙🚚🚛🚜🚲🛴🛹🛵🚏🛣️🛣🛤️🛤🛢️🛢⛽🚨🚥🚦🛑🚧⚓⛵🛶🚤🛳️🛳⛴️⛴🛥️🛥🚢✈️✈🛩️🛩🛫🛬💺🚁🚟🚠🚡🛰️🛰🚀🛸🛎️🛎🧳⌛⏳⌚⏰⏱️⏱⏲️⏲🕰️🕰🕛🕧🕐🕜🕑🕝🕒🕞🕓🕟🕔🕠🕕🕡🕖🕢🕗🕣🕘🕤🕙🕥🕚🕦🌑🌒🌓🌔🌕🌖🌗🌘🌙🌚🌛🌜🌡️🌡☀️☀🌝🌞⭐🌟🌠☁️☁⛅⛈️⛈🌤️🌤🌥️🌥🌦️🌦🌧️🌧🌨️🌨🌩️🌩🌪️🌪🌫️🌫🌬️🌬🌀🌈🌂☂️☂☔⛱️⛱⚡❄️❄☃️☃⛄☄️☄🔥💧🌊🎃🎄🎆🎇🧨✨🎈🎉🎊🎋🎍🎎🎏🎐🎑🧧🎀🎁🎗️🎗🎟️🎟🎫🎖️🎖🏆🏅🥇🥈🥉⚽⚾🥎🏀🏐🏈🏉🎾🥏🎳🏏🏑🏒🥍🏓🏸🥊🥋🥅⛳⛸️⛸🎣🎽🎿🛷🥌🎯🎱🔮🧿🎮🕹️🕹🎰🎲🧩🧸♠️♠♥️♥♦️♦♣️♣♟️♟🃏🀄🎴🎭🖼️🖼🎨🧵🧶🔇🔈🔉🔊📢📣📯🔔🔕🎼🎵🎶🎙️🎙🎚️🎚🎛️🎛🎤🎧📻🎷🎸🎹🎺🎻🥁📱📲☎️☎📞📟📠🔋🔌💻🖥️🖥🖨️🖨⌨️⌨🖱️🖱🖲️🖲💽💾💿📀🧮🎥🎞️🎞📽️📽🎬📺📷📸📹📼🔍🔎🕯️🕯💡🔦🏮📔📕📖📗📘📙📚📓📒📃📜📄📰🗞️🗞📑🔖🏷️🏷💰💴💵💶💷💸💳🧾💹💱💲✉️✉📧📨📩📤📥📦📫📪📬📭📮🗳️🗳✏️✏✒️✒🖋️🖋🖊️🖊🖌️🖌🖍️🖍📝💼📁📂🗂️🗂📅📆🗒️🗒🗓️🗓📇📈📉📊📋📌📍📎🖇️🖇📏📐✂️✂🗃️🗃🗄️🗄🗑️🗑🔒🔓🔏🔐🔑🗝️🗝🔨⛏️⛏⚒️⚒🛠️🛠🗡️🗡⚔️⚔🔫🏹🛡️🛡🔧🔩⚙️⚙🗜️🗜⚖️⚖🔗⛓️⛓🧰🧲⚗️⚗🧪🧫🧬🔬🔭📡💉💊🚪🛏️🛏🛋️🛋🚽🚿🛁🧴🧷🧹🧺🧻🧼🧽🧯🛒🚬⚰️⚰⚱️⚱🗿🏧🚮🚰♿🚹🚺🚻🚼🚾🛂🛃🛄🛅⚠️⚠🚸⛔🚫🚳🚭🚯🚱🚷📵🔞☢️☢☣️☣⬆️⬆↗️↗➡️➡↘️↘⬇️⬇↙️↙⬅️⬅↖️↖↕️↕↔️↔↩️↩↪️↪⤴️⤴⤵️⤵🔃🔄🔙🔚🔛🔜🔝🛐⚛️⚛🕉️🕉✡️✡☸️☸☯️☯✝️✝☦️☦☪️☪☮️☮🕎🔯♈♉♊♋♌♍♎♏♐♑♒♓⛎🔀🔁🔂▶️▶⏩⏭️⏭⏯️⏯◀️◀⏪⏮️⏮🔼⏫🔽⏬⏸️⏸⏹️⏹⏺️⏺⏏️⏏🎦🔅🔆📶📳📴♀️♀♂️♂⚕️⚕♾️♾♻️♻⚜️⚜🔱📛🔰⭕✅☑️☑✔️✔✖️✖❌❎➕➖➗➰➿〽️〽✳️✳✴️✴❇️❇‼️‼⁉️⁉❓❔❕❗〰️〰©️©®️®™️™#️⃣#⃣*️⃣*⃣0️⃣0⃣1️⃣1⃣2️⃣2⃣3️⃣3⃣4️⃣4⃣5️⃣5⃣6️⃣6⃣7️⃣7⃣8️⃣8⃣9️⃣9⃣🔟💯🔠🔡🔢🔣🔤🅰️🅰🆎🅱️🅱🆑🆒🆓ℹ️ℹ🆔Ⓜ️Ⓜ🆕🆖🅾️🅾🆗🅿️🅿🆘🆙🆚🈁🈂️🈂🈷️🈷🈶🈯🉐🈹🈚🈲🉑🈸🈴🈳㊗️㊗㊙️㊙🈺🈵▪️▪▫️▫◻️◻◼️◼◽◾⬛⬜🔶🔷🔸🔹🔺🔻💠🔘🔲🔳⚪⚫🔴🔵🏁🚩🎌🏴🏳️🏳🏳️‍🌈🏳‍🌈🏴‍☠️🏴‍☠🇦🇨🇦🇩🇦🇪🇦🇫🇦🇬🇦🇮🇦🇱🇦🇲🇦🇴🇦🇶🇦🇷🇦🇸🇦🇹🇦🇺🇦🇼🇦🇽🇦🇿🇧🇦🇧🇧🇧🇩🇧🇪🇧🇫🇧🇬🇧🇭🇧🇮🇧🇯🇧🇱🇧🇲🇧🇳🇧🇴🇧🇶🇧🇷🇧🇸🇧🇹🇧🇻🇧🇼🇧🇾🇧🇿🇨🇦🇨🇨🇨🇩🇨🇫🇨🇬🇨🇭🇨🇮🇨🇰🇨🇱🇨🇲🇨🇳🇨🇴🇨🇵🇨🇷🇨🇺🇨🇻🇨🇼🇨🇽🇨🇾🇨🇿🇩🇪🇩🇬🇩🇯🇩🇰🇩🇲🇩🇴🇩🇿🇪🇦🇪🇨🇪🇪🇪🇬🇪🇭🇪🇷🇪🇸🇪🇹🇪🇺🇫🇮🇫🇯🇫🇰🇫🇲🇫🇴🇫🇷🇬🇦🇬🇧🇬🇩🇬🇪🇬🇫🇬🇬🇬🇭🇬🇮🇬🇱🇬🇲🇬🇳🇬🇵🇬🇶🇬🇷🇬🇸🇬🇹🇬🇺🇬🇼🇬🇾🇭🇰🇭🇲🇭🇳🇭🇷🇭🇹🇭🇺🇮🇨🇮🇩🇮🇪🇮🇱🇮🇲🇮🇳🇮🇴🇮🇶🇮🇷🇮🇸🇮🇹🇯🇪🇯🇲🇯🇴🇯🇵🇰🇪🇰🇬🇰🇭🇰🇮🇰🇲🇰🇳🇰🇵🇰🇷🇰🇼🇰🇾🇰🇿🇱🇦🇱🇧🇱🇨🇱🇮🇱🇰🇱🇷🇱🇸🇱🇹🇱🇺🇱🇻🇱🇾🇲🇦🇲🇨🇲🇩🇲🇪🇲🇫🇲🇬🇲🇭🇲🇰🇲🇱🇲🇲🇲🇳🇲🇴🇲🇵🇲🇶🇲🇷🇲🇸🇲🇹🇲🇺🇲🇻🇲🇼🇲🇽🇲🇾🇲🇿🇳🇦🇳🇨🇳🇪🇳🇫🇳🇬🇳🇮🇳🇱🇳🇴🇳🇵🇳🇷🇳🇺🇳🇿🇴🇲🇵🇦🇵🇪🇵🇫🇵🇬🇵🇭🇵🇰🇵🇱🇵🇲🇵🇳🇵🇷🇵🇸🇵🇹🇵🇼🇵🇾🇶🇦🇷🇪🇷🇴🇷🇸🇷🇺🇷🇼🇸🇦🇸🇧🇸🇨🇸🇩🇸🇪🇸🇬🇸🇭🇸🇮🇸🇯🇸🇰🇸🇱🇸🇲🇸🇳🇸🇴🇸🇷🇸🇸🇸🇹🇸🇻🇸🇽🇸🇾🇸🇿🇹🇦🇹🇨🇹🇩🇹🇫🇹🇬🇹🇭🇹🇯🇹🇰🇹🇱🇹🇲🇹🇳🇹🇴🇹🇷🇹🇹🇹🇻🇹🇼🇹🇿🇺🇦🇺🇬🇺🇲🇺🇳🇺🇸🇺🇾🇺🇿🇻🇦🇻🇨🇻🇪🇻🇬🇻🇮🇻🇳🇻🇺🇼🇫🇼🇸🇽🇰🇾🇪🇾🇹🇿🇦🇿🇲🇿🇼🏴󠁧󠁢󠁥󠁮󠁧󠁿🏴󠁧󠁢󠁳󠁣󠁴󠁿🏴󠁧󠁢󠁷󠁬󠁳󠁿" - ); - expect(() => emoji.parse(":-)")).toThrow(); - expect(() => emoji.parse("😀 is an emoji")).toThrow(); - expect(() => emoji.parse("😀stuff")).toThrow(); - expect(() => emoji.parse("stuff😀")).toThrow(); -}); - -test("uuid", () => { - const uuid = z.string().uuid("custom error"); - uuid.parse("9491d710-3185-4e06-bea0-6a2f275345e0"); - uuid.parse("d89e7b01-7598-ed11-9d7a-0022489382fd"); // new sequential id - uuid.parse("00000000-0000-0000-0000-000000000000"); - uuid.parse("b3ce60f8-e8b9-40f5-1150-172ede56ff74"); // Variant 0 - RFC 9562/4122: Reserved, NCS backward compatibility - uuid.parse("92e76bf9-28b3-4730-cd7f-cb6bc51f8c09"); // Variant 2 - RFC 9562/4122: Reserved, Microsoft Corporation backward compatibility - const result = uuid.safeParse("9491d710-3185-4e06-bea0-6a2f275345e0X"); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].message).toEqual("custom error"); - } -}); - -test("bad uuid", () => { - const uuid = z.string().uuid("custom error"); - uuid.parse("9491d710-3185-4e06-bea0-6a2f275345e0"); - const result = uuid.safeParse("invalid uuid"); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].message).toEqual("custom error"); - } -}); - -test("nanoid", () => { - const nanoid = z.string().nanoid("custom error"); - nanoid.parse("lfNZluvAxMkf7Q8C5H-QS"); - nanoid.parse("mIU_4PJWikaU8fMbmkouz"); - nanoid.parse("Hb9ZUtUa2JDm_dD-47EGv"); - nanoid.parse("5Noocgv_8vQ9oPijj4ioQ"); - const result = nanoid.safeParse("Xq90uDyhddC53KsoASYJGX"); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].message).toEqual("custom error"); - } -}); - -test("bad nanoid", () => { - const nanoid = z.string().nanoid("custom error"); - nanoid.parse("ySh_984wpDUu7IQRrLXAp"); - const result = nanoid.safeParse("invalid nanoid"); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].message).toEqual("custom error"); - } -}); - -test("cuid", () => { - const cuid = z.string().cuid(); - cuid.parse("ckopqwooh000001la8mbi2im9"); - const result = cuid.safeParse("cifjhdsfhsd-invalid-cuid"); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].message).toEqual("Invalid cuid"); - } -}); - -test("cuid2", () => { - const cuid2 = z.string().cuid2(); - const validStrings = [ - "a", // short string - "tz4a98xxat96iws9zmbrgj3a", // normal string - "kf5vz6ssxe4zjcb409rjgo747tc5qjazgptvotk6", // longer than require("@paralleldrive/cuid2").bigLength - ]; - for (const s of validStrings) { - cuid2.parse(s); - } - - const invalidStrings = [ - "", // empty string - "tz4a98xxat96iws9zMbrgj3a", // include uppercase - "tz4a98xxat96iws-zmbrgj3a", // involve symbols - ]; - const results = invalidStrings.map((s) => cuid2.safeParse(s)); - expect(results.every((r) => !r.success)).toEqual(true); - if (!results[0].success) { - expect(results[0].error.issues[0].message).toEqual("Invalid cuid2"); - } -}); - -test("ulid", () => { - const ulid = z.string().ulid(); - ulid.parse("01ARZ3NDEKTSV4RRFFQ69G5FAV"); - const result = ulid.safeParse("invalidulid"); - expect(result.success).toEqual(false); - const tooLong = "01ARZ3NDEKTSV4RRFFQ69G5FAVA"; - expect(ulid.safeParse(tooLong).success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].message).toEqual("Invalid ulid"); - } - const caseInsensitive = ulid.safeParse("01arZ3nDeKTsV4RRffQ69G5FAV"); - expect(caseInsensitive.success).toEqual(true); -}); - -test("regex", () => { - z.string() - .regex(/^moo+$/) - .parse("mooooo"); - expect(() => z.string().uuid().parse("purr")).toThrow(); -}); - -test("regexp error message", () => { - const result = z - .string() - .regex(/^moo+$/) - .safeParse("boooo"); - if (!result.success) { - expect(result.error.issues[0].message).toEqual("Invalid"); - } else { - throw new Error("validation should have failed"); - } - - expect(() => z.string().uuid().parse("purr")).toThrow(); -}); - -test("regex lastIndex reset", () => { - const schema = z.string().regex(/^\d+$/g); - expect(schema.safeParse("123").success).toEqual(true); - expect(schema.safeParse("123").success).toEqual(true); - expect(schema.safeParse("123").success).toEqual(true); - expect(schema.safeParse("123").success).toEqual(true); - expect(schema.safeParse("123").success).toEqual(true); -}); - -test("checks getters", () => { - expect(z.string().email().isEmail).toEqual(true); - expect(z.string().email().isURL).toEqual(false); - expect(z.string().email().isCUID).toEqual(false); - expect(z.string().email().isCUID2).toEqual(false); - expect(z.string().email().isUUID).toEqual(false); - expect(z.string().email().isNANOID).toEqual(false); - expect(z.string().email().isIP).toEqual(false); - expect(z.string().email().isCIDR).toEqual(false); - expect(z.string().email().isULID).toEqual(false); - - expect(z.string().url().isEmail).toEqual(false); - expect(z.string().url().isURL).toEqual(true); - expect(z.string().url().isCUID).toEqual(false); - expect(z.string().url().isCUID2).toEqual(false); - expect(z.string().url().isUUID).toEqual(false); - expect(z.string().url().isNANOID).toEqual(false); - expect(z.string().url().isIP).toEqual(false); - expect(z.string().url().isCIDR).toEqual(false); - expect(z.string().url().isULID).toEqual(false); - - expect(z.string().cuid().isEmail).toEqual(false); - expect(z.string().cuid().isURL).toEqual(false); - expect(z.string().cuid().isCUID).toEqual(true); - expect(z.string().cuid().isCUID2).toEqual(false); - expect(z.string().cuid().isUUID).toEqual(false); - expect(z.string().cuid().isNANOID).toEqual(false); - expect(z.string().cuid().isIP).toEqual(false); - expect(z.string().cuid().isCIDR).toEqual(false); - expect(z.string().cuid().isULID).toEqual(false); - - expect(z.string().cuid2().isEmail).toEqual(false); - expect(z.string().cuid2().isURL).toEqual(false); - expect(z.string().cuid2().isCUID).toEqual(false); - expect(z.string().cuid2().isCUID2).toEqual(true); - expect(z.string().cuid2().isUUID).toEqual(false); - expect(z.string().cuid2().isNANOID).toEqual(false); - expect(z.string().cuid2().isIP).toEqual(false); - expect(z.string().cuid2().isCIDR).toEqual(false); - expect(z.string().cuid2().isULID).toEqual(false); - - expect(z.string().uuid().isEmail).toEqual(false); - expect(z.string().uuid().isURL).toEqual(false); - expect(z.string().uuid().isCUID).toEqual(false); - expect(z.string().uuid().isCUID2).toEqual(false); - expect(z.string().uuid().isUUID).toEqual(true); - expect(z.string().uuid().isNANOID).toEqual(false); - expect(z.string().uuid().isIP).toEqual(false); - expect(z.string().uuid().isCIDR).toEqual(false); - expect(z.string().uuid().isULID).toEqual(false); - - expect(z.string().nanoid().isEmail).toEqual(false); - expect(z.string().nanoid().isURL).toEqual(false); - expect(z.string().nanoid().isCUID).toEqual(false); - expect(z.string().nanoid().isCUID2).toEqual(false); - expect(z.string().nanoid().isUUID).toEqual(false); - expect(z.string().nanoid().isNANOID).toEqual(true); - expect(z.string().nanoid().isIP).toEqual(false); - expect(z.string().nanoid().isCIDR).toEqual(false); - expect(z.string().nanoid().isULID).toEqual(false); - - expect(z.string().ip().isEmail).toEqual(false); - expect(z.string().ip().isURL).toEqual(false); - expect(z.string().ip().isCUID).toEqual(false); - expect(z.string().ip().isCUID2).toEqual(false); - expect(z.string().ip().isUUID).toEqual(false); - expect(z.string().ip().isNANOID).toEqual(false); - expect(z.string().ip().isIP).toEqual(true); - expect(z.string().ip().isCIDR).toEqual(false); - expect(z.string().ip().isULID).toEqual(false); - - expect(z.string().cidr().isEmail).toEqual(false); - expect(z.string().cidr().isURL).toEqual(false); - expect(z.string().cidr().isCUID).toEqual(false); - expect(z.string().cidr().isCUID2).toEqual(false); - expect(z.string().cidr().isUUID).toEqual(false); - expect(z.string().cidr().isNANOID).toEqual(false); - expect(z.string().cidr().isIP).toEqual(false); - expect(z.string().cidr().isCIDR).toEqual(true); - expect(z.string().cidr().isULID).toEqual(false); - - expect(z.string().ulid().isEmail).toEqual(false); - expect(z.string().ulid().isURL).toEqual(false); - expect(z.string().ulid().isCUID).toEqual(false); - expect(z.string().ulid().isCUID2).toEqual(false); - expect(z.string().ulid().isUUID).toEqual(false); - expect(z.string().ulid().isNANOID).toEqual(false); - expect(z.string().ulid().isIP).toEqual(false); - expect(z.string().ulid().isCIDR).toEqual(false); - expect(z.string().ulid().isULID).toEqual(true); -}); - -test("min max getters", () => { - expect(z.string().min(5).minLength).toEqual(5); - expect(z.string().min(5).min(10).minLength).toEqual(10); - expect(z.string().minLength).toEqual(null); - - expect(z.string().max(5).maxLength).toEqual(5); - expect(z.string().max(5).max(1).maxLength).toEqual(1); - expect(z.string().maxLength).toEqual(null); -}); - -test("trim", () => { - expect(z.string().trim().min(2).parse(" 12 ")).toEqual("12"); - - // ordering of methods is respected - expect(z.string().min(2).trim().parse(" 1 ")).toEqual("1"); - expect(() => z.string().trim().min(2).parse(" 1 ")).toThrow(); -}); - -test("lowerCase", () => { - expect(z.string().toLowerCase().parse("ASDF")).toEqual("asdf"); - expect(z.string().toUpperCase().parse("asdf")).toEqual("ASDF"); -}); - -test("datetime", () => { - const a = z.string().datetime({}); - expect(a.isDatetime).toEqual(true); - - const b = z.string().datetime({ offset: true }); - expect(b.isDatetime).toEqual(true); - - const c = z.string().datetime({ precision: 3 }); - expect(c.isDatetime).toEqual(true); - - const d = z.string().datetime({ offset: true, precision: 0 }); - expect(d.isDatetime).toEqual(true); - - const { isDatetime } = z.string().datetime(); - expect(isDatetime).toEqual(true); -}); - -test("datetime parsing", () => { - const datetime = z.string().datetime(); - datetime.parse("1970-01-01T00:00:00.000Z"); - datetime.parse("2022-10-13T09:52:31.816Z"); - datetime.parse("2022-10-13T09:52:31.8162314Z"); - datetime.parse("1970-01-01T00:00:00Z"); - datetime.parse("2022-10-13T09:52:31Z"); - datetime.parse("2022-10-13T09:52Z"); - expect(() => datetime.parse("")).toThrow(); - expect(() => datetime.parse("foo")).toThrow(); - expect(() => datetime.parse("2020-10-14")).toThrow(); - expect(() => datetime.parse("T18:45:12.123")).toThrow(); - expect(() => datetime.parse("2020-10-14T17:42:29+00:00")).toThrow(); - expect(() => datetime.parse("2020-10-14T17:42.123+00:00")).toThrow(); - - const datetimeNoMs = z.string().datetime({ precision: 0 }); - datetimeNoMs.parse("1970-01-01T00:00:00Z"); - datetimeNoMs.parse("2022-10-13T09:52:31Z"); - datetimeNoMs.parse("2022-10-13T09:52Z"); - expect(() => datetimeNoMs.parse("tuna")).toThrow(); - expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.000Z")).toThrow(); - expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.Z")).toThrow(); - expect(() => datetimeNoMs.parse("2022-10-13T09:52:31.816Z")).toThrow(); - - const datetime3Ms = z.string().datetime({ precision: 3 }); - datetime3Ms.parse("1970-01-01T00:00:00.000Z"); - datetime3Ms.parse("2022-10-13T09:52:31.123Z"); - expect(() => datetime3Ms.parse("tuna")).toThrow(); - expect(() => datetime3Ms.parse("1970-01-01T00:00:00.1Z")).toThrow(); - expect(() => datetime3Ms.parse("1970-01-01T00:00:00.12Z")).toThrow(); - expect(() => datetime3Ms.parse("2022-10-13T09:52:31Z")).toThrow(); - expect(() => datetime3Ms.parse("2022-10-13T09:52Z")).toThrow(); - - const datetimeOffset = z.string().datetime({ offset: true }); - datetimeOffset.parse("1970-01-01T00:00:00.000Z"); - datetimeOffset.parse("2022-10-13T09:52:31.816234134Z"); - datetimeOffset.parse("1970-01-01T00:00:00Z"); - datetimeOffset.parse("2022-10-13T09:52:31.4Z"); - datetimeOffset.parse("2020-10-14T17:42:29+00:00"); - datetimeOffset.parse("2020-10-14T17:42:29+03:15"); - datetimeOffset.parse("2020-10-14T17:42:29+0315"); - datetimeOffset.parse("2020-10-14T17:42+0315"); - expect(() => datetimeOffset.parse("2020-10-14T17:42:29+03")); - expect(() => datetimeOffset.parse("tuna")).toThrow(); - expect(() => datetimeOffset.parse("2022-10-13T09:52:31.Z")).toThrow(); - - const datetimeOffsetNoMs = z.string().datetime({ offset: true, precision: 0 }); - datetimeOffsetNoMs.parse("1970-01-01T00:00:00Z"); - datetimeOffsetNoMs.parse("2022-10-13T09:52:31Z"); - datetimeOffsetNoMs.parse("2020-10-14T17:42:29+00:00"); - datetimeOffsetNoMs.parse("2020-10-14T17:42:29+0000"); - datetimeOffsetNoMs.parse("2020-10-14T17:42+0000"); - expect(() => datetimeOffsetNoMs.parse("2020-10-14T17:42:29+00")).toThrow(); - expect(() => datetimeOffsetNoMs.parse("tuna")).toThrow(); - expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00:00.000Z")).toThrow(); - expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00:00.Z")).toThrow(); - expect(() => datetimeOffsetNoMs.parse("2022-10-13T09:52:31.816Z")).toThrow(); - expect(() => datetimeOffsetNoMs.parse("2020-10-14T17:42:29.124+00:00")).toThrow(); - - const datetimeOffset4Ms = z.string().datetime({ offset: true, precision: 4 }); - datetimeOffset4Ms.parse("1970-01-01T00:00:00.1234Z"); - datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00:00"); - datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+0000"); - expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00")).toThrow(); - expect(() => datetimeOffset4Ms.parse("tuna")).toThrow(); - expect(() => datetimeOffset4Ms.parse("1970-01-01T00:00:00.123Z")).toThrow(); - expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42:29.124+00:00")).toThrow(); - expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42+00:00")).toThrow(); -}); - -test("date", () => { - const a = z.string().date(); - expect(a.isDate).toEqual(true); -}); - -test("date parsing", () => { - const date = z.string().date(); - date.parse("1970-01-01"); - date.parse("2022-01-31"); - date.parse("2022-03-31"); - date.parse("2022-04-30"); - date.parse("2022-05-31"); - date.parse("2022-06-30"); - date.parse("2022-07-31"); - date.parse("2022-08-31"); - date.parse("2022-09-30"); - date.parse("2022-10-31"); - date.parse("2022-11-30"); - date.parse("2022-12-31"); - - date.parse("2000-02-29"); - date.parse("2400-02-29"); - expect(() => date.parse("2022-02-29")).toThrow(); - expect(() => date.parse("2100-02-29")).toThrow(); - expect(() => date.parse("2200-02-29")).toThrow(); - expect(() => date.parse("2300-02-29")).toThrow(); - expect(() => date.parse("2500-02-29")).toThrow(); - - expect(() => date.parse("")).toThrow(); - expect(() => date.parse("foo")).toThrow(); - expect(() => date.parse("200-01-01")).toThrow(); - expect(() => date.parse("20000-01-01")).toThrow(); - expect(() => date.parse("2000-0-01")).toThrow(); - expect(() => date.parse("2000-011-01")).toThrow(); - expect(() => date.parse("2000-01-0")).toThrow(); - expect(() => date.parse("2000-01-011")).toThrow(); - expect(() => date.parse("2000/01/01")).toThrow(); - expect(() => date.parse("01-01-2022")).toThrow(); - expect(() => date.parse("01/01/2022")).toThrow(); - expect(() => date.parse("2000-01-01 00:00:00Z")).toThrow(); - expect(() => date.parse("2020-10-14T17:42:29+00:00")).toThrow(); - expect(() => date.parse("2020-10-14T17:42:29Z")).toThrow(); - expect(() => date.parse("2020-10-14T17:42:29")).toThrow(); - expect(() => date.parse("2020-10-14T17:42:29.123Z")).toThrow(); - - expect(() => date.parse("2000-00-12")).toThrow(); - expect(() => date.parse("2000-12-00")).toThrow(); - expect(() => date.parse("2000-01-32")).toThrow(); - expect(() => date.parse("2000-13-01")).toThrow(); - expect(() => date.parse("2000-21-01")).toThrow(); - - expect(() => date.parse("2000-02-30")).toThrow(); - expect(() => date.parse("2000-02-31")).toThrow(); - expect(() => date.parse("2000-04-31")).toThrow(); - expect(() => date.parse("2000-06-31")).toThrow(); - expect(() => date.parse("2000-09-31")).toThrow(); - expect(() => date.parse("2000-11-31")).toThrow(); -}); - -test("time", () => { - const a = z.string().time(); - expect(a.isTime).toEqual(true); -}); - -test("time parsing", () => { - const time = z.string().time(); - time.parse("00:00:00"); - time.parse("23:00:00"); - time.parse("00:59:00"); - time.parse("00:00:59"); - time.parse("23:59:59"); - time.parse("09:52:31"); - time.parse("23:59:59.9999999"); - time.parse("23:59"); - expect(() => time.parse("")).toThrow(); - expect(() => time.parse("foo")).toThrow(); - expect(() => time.parse("00:00:00Z")).toThrow(); - expect(() => time.parse("0:00:00")).toThrow(); - expect(() => time.parse("00:0:00")).toThrow(); - expect(() => time.parse("00:00:0")).toThrow(); - expect(() => time.parse("00:00:00.000+00:00")).toThrow(); - - expect(() => time.parse("24:00:00")).toThrow(); - expect(() => time.parse("00:60:00")).toThrow(); - expect(() => time.parse("00:00:60")).toThrow(); - expect(() => time.parse("24:60:60")).toThrow(); - expect(() => time.parse("24:60")).toThrow(); - - const time2 = z.string().time({ precision: 2 }); - time2.parse("00:00:00.00"); - time2.parse("09:52:31.12"); - time2.parse("23:59:59.99"); - expect(() => time2.parse("")).toThrow(); - expect(() => time2.parse("foo")).toThrow(); - expect(() => time2.parse("00:00:00")).toThrow(); - expect(() => time2.parse("00:00:00.00Z")).toThrow(); - expect(() => time2.parse("00:00:00.0")).toThrow(); - expect(() => time2.parse("00:00:00.000")).toThrow(); - expect(() => time2.parse("00:00:00.00+00:00")).toThrow(); - expect(() => time2.parse("23:59")).toThrow(); - - // const time3 = z.string().time({ offset: true }); - // time3.parse("00:00:00Z"); - // time3.parse("09:52:31Z"); - // time3.parse("00:00:00+00:00"); - // time3.parse("00:00:00+0000"); - // time3.parse("00:00:00.000Z"); - // time3.parse("00:00:00.000+00:00"); - // time3.parse("00:00:00.000+0000"); - // expect(() => time3.parse("")).toThrow(); - // expect(() => time3.parse("foo")).toThrow(); - // expect(() => time3.parse("00:00:00")).toThrow(); - // expect(() => time3.parse("00:00:00.000")).toThrow(); - - // const time4 = z.string().time({ offset: true, precision: 0 }); - // time4.parse("00:00:00Z"); - // time4.parse("09:52:31Z"); - // time4.parse("00:00:00+00:00"); - // time4.parse("00:00:00+0000"); - // expect(() => time4.parse("")).toThrow(); - // expect(() => time4.parse("foo")).toThrow(); - // expect(() => time4.parse("00:00:00.0")).toThrow(); - // expect(() => time4.parse("00:00:00.000")).toThrow(); - // expect(() => time4.parse("00:00:00.000+00:00")).toThrow(); -}); - -test("duration", () => { - const duration = z.string().duration(); - expect(duration.isDuration).toEqual(true); - - const validDurations = [ - "P3Y6M4DT12H30M5S", - "P2Y9M3DT12H31M8.001S", - "+P3Y6M4DT12H30M5S", - "-PT0.001S", - "+PT0.001S", - "PT0,001S", - "PT12H30M5S", - "-P2M1D", - "P-2M-1D", - "-P5DT10H", - "P-5DT-10H", - "P1Y", - "P2MT30M", - "PT6H", - "P5W", - "P0.5Y", - "P0,5Y", - "P42YT7.004M", - ]; - - const invalidDurations = ["foo bar", "", " ", "P", "T1H", "P0.5Y1D", "P0,5Y6M", "P1YT"]; - - for (const val of validDurations) { - const result = duration.safeParse(val); - if (!result.success) { - throw Error(`Valid duration could not be parsed: ${val}`); - } - } - - for (const val of invalidDurations) { - const result = duration.safeParse(val); - - if (result.success) { - throw Error(`Invalid duration was successful parsed: ${val}`); - } - - expect(result.error.issues[0].message).toEqual("Invalid duration"); - } -}); - -test("IP validation", () => { - const ip = z.string().ip(); - expect(ip.safeParse("122.122.122.122").success).toBe(true); - - const ipv4 = z.string().ip({ version: "v4" }); - expect(() => ipv4.parse("6097:adfa:6f0b:220d:db08:5021:6191:7990")).toThrow(); - - const ipv6 = z.string().ip({ version: "v6" }); - expect(() => ipv6.parse("254.164.77.1")).toThrow(); - - const validIPs = [ - "1e5e:e6c8:daac:514b:114b:e360:d8c0:682c", - "9d4:c956:420f:5788:4339:9b3b:2418:75c3", - "474f:4c83::4e40:a47:ff95:0cda", - "d329:0:25b4:db47:a9d1:0:4926:0000", - "e48:10fb:1499:3e28:e4b6:dea5:4692:912c", - "114.71.82.94", - "0.0.0.0", - "37.85.236.115", - "2001:4888:50:ff00:500:d::", - "2001:4888:50:ff00:0500:000d:000:0000", - "2001:4888:50:ff00:0500:000d:0000:0000", - ]; - - const invalidIPs = [ - "d329:1be4:25b4:db47:a9d1:dc71:4926:992c:14af", - "d5e7:7214:2b78::3906:85e6:53cc:709:32ba", - "8f69::c757:395e:976e::3441", - "54cb::473f:d516:0.255.256.22", - "54cb::473f:d516:192.168.1", - "256.0.4.4", - "-1.0.555.4", - "0.0.0.0.0", - "1.1.1", - ]; - // no parameters check IPv4 or IPv6 - const ipSchema = z.string().ip(); - expect(validIPs.every((ip) => ipSchema.safeParse(ip).success)).toBe(true); - expect(invalidIPs.every((ip) => ipSchema.safeParse(ip).success === false)).toBe(true); -}); - -test("CIDR validation", () => { - const ipv4Cidr = z.string().cidr({ version: "v4" }); - expect(() => ipv4Cidr.parse("2001:0db8:85a3::8a2e:0370:7334/64")).toThrow(); - - const ipv6Cidr = z.string().cidr({ version: "v6" }); - expect(() => ipv6Cidr.parse("192.168.0.1/24")).toThrow(); - - const validCidrs = [ - "192.168.0.0/24", - "10.0.0.0/8", - "203.0.113.0/24", - "192.0.2.0/24", - "127.0.0.0/8", - "172.16.0.0/12", - "192.168.1.0/24", - "fc00::/7", - "fd00::/8", - "2001:db8::/32", - "2607:f0d0:1002:51::4/64", - "2001:0db8:85a3:0000:0000:8a2e:0370:7334/128", - "2001:0db8:1234:0000::/64", - ]; - - const invalidCidrs = [ - "192.168.1.1/33", - "10.0.0.1/-1", - "192.168.1.1/24/24", - "192.168.1.0/abc", - "2001:db8::1/129", - "2001:db8::1/-1", - "2001:db8::1/64/64", - "2001:db8::1/abc", - ]; - - // no parameters check IPv4 or IPv6 - const cidrSchema = z.string().cidr(); - expect(validCidrs.every((ip) => cidrSchema.safeParse(ip).success)).toBe(true); - expect(invalidCidrs.every((ip) => cidrSchema.safeParse(ip).success === false)).toBe(true); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/transformer.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/transformer.test.ts deleted file mode 100644 index ddd9e9a63..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/transformer.test.ts +++ /dev/null @@ -1,233 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; - -const stringToNumber = z.string().transform((arg) => Number.parseFloat(arg)); -// const numberToString = z -// .transformer(z.number()) -// .transform((n) => String(n)); -const asyncNumberToString = z.number().transform(async (n) => String(n)); - -test("transform ctx.addIssue with parse", () => { - const strs = ["foo", "bar"]; - - expect(() => { - z.string() - .transform((data, ctx) => { - const i = strs.indexOf(data); - if (i === -1) { - ctx.addIssue({ - code: "custom", - message: `${data} is not one of our allowed strings`, - }); - } - return data.length; - }) - .parse("asdf"); - }).toThrow( - JSON.stringify( - [ - { - code: "custom", - message: "asdf is not one of our allowed strings", - path: [], - }, - ], - null, - 2 - ) - ); -}); - -test("transform ctx.addIssue with parseAsync", async () => { - const strs = ["foo", "bar"]; - - const result = await z - .string() - .transform(async (data, ctx) => { - const i = strs.indexOf(data); - if (i === -1) { - ctx.addIssue({ - code: "custom", - message: `${data} is not one of our allowed strings`, - }); - } - return data.length; - }) - .safeParseAsync("asdf"); - - expect(JSON.parse(JSON.stringify(result))).toEqual({ - success: false, - error: { - issues: [ - { - code: "custom", - message: "asdf is not one of our allowed strings", - path: [], - }, - ], - name: "ZodError", - }, - }); -}); - -test("z.NEVER in transform", () => { - const foo = z - .number() - .optional() - .transform((val, ctx) => { - if (!val) { - ctx.addIssue({ code: z.ZodIssueCode.custom, message: "bad" }); - return z.NEVER; - } - return val; - }); - type foo = z.infer; - util.assertEqual(true); - const arg = foo.safeParse(undefined); - if (!arg.success) { - expect(arg.error.issues[0].message).toEqual("bad"); - } -}); - -test("basic transformations", () => { - const r1 = z - .string() - .transform((data) => data.length) - .parse("asdf"); - expect(r1).toEqual(4); -}); - -test("coercion", () => { - const numToString = z.number().transform((n) => String(n)); - const data = z - .object({ - id: numToString, - }) - .parse({ id: 5 }); - - expect(data).toEqual({ id: "5" }); -}); - -test("async coercion", async () => { - const numToString = z.number().transform(async (n) => String(n)); - const data = await z - .object({ - id: numToString, - }) - .parseAsync({ id: 5 }); - - expect(data).toEqual({ id: "5" }); -}); - -test("sync coercion async error", async () => { - expect(() => - z - .object({ - id: asyncNumberToString, - }) - .parse({ id: 5 }) - ).toThrow(); - // expect(data).toEqual({ id: '5' }); -}); - -test("default", () => { - const data = z.string().default("asdf").parse(undefined); // => "asdf" - expect(data).toEqual("asdf"); -}); - -test("dynamic default", () => { - const data = z - .string() - .default(() => "string") - .parse(undefined); // => "asdf" - expect(data).toEqual("string"); -}); - -test("default when property is null or undefined", () => { - const data = z - .object({ - foo: z.boolean().nullable().default(true), - bar: z.boolean().default(true), - }) - .parse({ foo: null }); - - expect(data).toEqual({ foo: null, bar: true }); -}); - -test("default with falsy values", () => { - const schema = z.object({ - emptyStr: z.string().default("def"), - zero: z.number().default(5), - falseBoolean: z.boolean().default(true), - }); - const input = { emptyStr: "", zero: 0, falseBoolean: true }; - const output = schema.parse(input); - // defaults are not supposed to be used - expect(output).toEqual(input); -}); - -test("object typing", () => { - const t1 = z.object({ - stringToNumber, - }); - - type t1 = z.input; - type t2 = z.output; - - util.assertEqual(true); - util.assertEqual(true); -}); - -test("transform method overloads", () => { - const t1 = z.string().transform((val) => val.toUpperCase()); - expect(t1.parse("asdf")).toEqual("ASDF"); - - const t2 = z.string().transform((val) => val.length); - expect(t2.parse("asdf")).toEqual(4); -}); - -test("multiple transformers", () => { - const doubler = stringToNumber.transform((val) => { - return val * 2; - }); - expect(doubler.parse("5")).toEqual(10); -}); - -test("short circuit on dirty", () => { - const schema = z - .string() - .refine(() => false) - .transform((val) => val.toUpperCase()); - const result = schema.safeParse("asdf"); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].code).toEqual(z.ZodIssueCode.custom); - } - - const result2 = schema.safeParse(1234); - expect(result2.success).toEqual(false); - if (!result2.success) { - expect(result2.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_type); - } -}); - -test("async short circuit on dirty", async () => { - const schema = z - .string() - .refine(() => false) - .transform((val) => val.toUpperCase()); - const result = await schema.spa("asdf"); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues[0].code).toEqual(z.ZodIssueCode.custom); - } - - const result2 = await schema.spa(1234); - expect(result2.success).toEqual(false); - if (!result2.success) { - expect(result2.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_type); - } -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/tuple.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/tuple.test.ts deleted file mode 100644 index e525d3f45..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/tuple.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { ZodError } from "../ZodError.js"; -import { util } from "../helpers/util.js"; - -const testTuple = z.tuple([z.string(), z.object({ name: z.literal("Rudy") }), z.array(z.literal("blue"))]); -const testData = ["asdf", { name: "Rudy" }, ["blue"]]; -const badData = [123, { name: "Rudy2" }, ["blue", "red"]]; - -test("tuple inference", () => { - const args1 = z.tuple([z.string()]); - const returns1 = z.number(); - const func1 = z.function(args1, returns1); - type func1 = z.TypeOf; - util.assertEqual number>(true); -}); - -test("successful validation", () => { - const val = testTuple.parse(testData); - expect(val).toEqual(["asdf", { name: "Rudy" }, ["blue"]]); -}); - -test("successful async validation", async () => { - const val = await testTuple.parseAsync(testData); - return expect(val).toEqual(testData); -}); - -test("failed validation", () => { - const checker = () => { - testTuple.parse([123, { name: "Rudy2" }, ["blue", "red"]] as any); - }; - try { - checker(); - } catch (err) { - if (err instanceof ZodError) { - expect(err.issues.length).toEqual(3); - } - } -}); - -test("failed async validation", async () => { - const res = await testTuple.safeParse(badData); - expect(res.success).toEqual(false); - if (!res.success) { - expect(res.error.issues.length).toEqual(3); - } - // try { - // checker(); - // } catch (err) { - // if (err instanceof ZodError) { - // expect(err.issues.length).toEqual(3); - // } - // } -}); - -test("tuple with transformers", () => { - const stringToNumber = z.string().transform((val) => val.length); - const val = z.tuple([stringToNumber]); - - type t1 = z.input; - util.assertEqual(true); - type t2 = z.output; - util.assertEqual(true); - expect(val.parse(["1234"])).toEqual([4]); -}); - -test("tuple with rest schema", () => { - const myTuple = z.tuple([z.string(), z.number()]).rest(z.boolean()); - expect(myTuple.parse(["asdf", 1234, true, false, true])).toEqual(["asdf", 1234, true, false, true]); - - expect(myTuple.parse(["asdf", 1234])).toEqual(["asdf", 1234]); - - expect(() => myTuple.parse(["asdf", 1234, "asdf"])).toThrow(); - type t1 = z.output; - - util.assertEqual(true); -}); - -test("parse should fail given sparse array as tuple", () => { - expect(() => testTuple.parse(new Array(3))).toThrow(); -}); - -// test('tuple with optional elements', () => { -// const result = z -// .tuple([z.string(), z.number().optional()]) -// .safeParse(['asdf']); -// expect(result).toEqual(['asdf']); -// }); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/unions.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/unions.test.ts deleted file mode 100644 index 2c3dc6775..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/unions.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -test("function parsing", () => { - const schema = z.union([z.string().refine(() => false), z.number().refine(() => false)]); - const result = schema.safeParse("asdf"); - expect(result.success).toEqual(false); -}); - -test("union 2", () => { - const result = z.union([z.number(), z.string().refine(() => false)]).safeParse("a"); - expect(result.success).toEqual(false); -}); - -test("return valid over invalid", () => { - const schema = z.union([ - z.object({ - email: z.string().email(), - }), - z.string(), - ]); - expect(schema.parse("asdf")).toEqual("asdf"); - expect(schema.parse({ email: "asdlkjf@lkajsdf.com" })).toEqual({ - email: "asdlkjf@lkajsdf.com", - }); -}); - -test("return dirty result over aborted", () => { - const result = z.union([z.number(), z.string().refine(() => false)]).safeParse("a"); - expect(result.success).toEqual(false); - if (!result.success) { - expect(result.error.issues).toEqual([ - { - code: "custom", - message: "Invalid input", - path: [], - }, - ]); - } -}); - -test("options getter", async () => { - const union = z.union([z.string(), z.number()]); - union.options[0].parse("asdf"); - union.options[1].parse(1234); - await union.options[0].parseAsync("asdf"); - await union.options[1].parseAsync(1234); -}); - -test("readonly union", async () => { - const options = [z.string(), z.number()] as const; - const union = z.union(options); - union.parse("asdf"); - union.parse(12); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/validations.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/validations.test.ts deleted file mode 100644 index 66f41dabc..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/validations.test.ts +++ /dev/null @@ -1,133 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; - -test("array min", async () => { - try { - await z.array(z.string()).min(4).parseAsync([]); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("Array must contain at least 4 element(s)"); - } -}); - -test("array max", async () => { - try { - await z.array(z.string()).max(2).parseAsync(["asdf", "asdf", "asdf"]); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("Array must contain at most 2 element(s)"); - } -}); - -test("array length", async () => { - try { - await z.array(z.string()).length(2).parseAsync(["asdf", "asdf", "asdf"]); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("Array must contain exactly 2 element(s)"); - } - - try { - await z.array(z.string()).length(2).parseAsync(["asdf"]); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("Array must contain exactly 2 element(s)"); - } -}); - -test("string length", async () => { - try { - await z.string().length(4).parseAsync("asd"); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("String must contain exactly 4 character(s)"); - } - - try { - await z.string().length(4).parseAsync("asdaa"); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("String must contain exactly 4 character(s)"); - } -}); - -test("string min", async () => { - try { - await z.string().min(4).parseAsync("asd"); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("String must contain at least 4 character(s)"); - } -}); - -test("string max", async () => { - try { - await z.string().max(4).parseAsync("aasdfsdfsd"); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("String must contain at most 4 character(s)"); - } -}); - -test("number min", async () => { - try { - await z.number().gte(3).parseAsync(2); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("Number must be greater than or equal to 3"); - } -}); - -test("number max", async () => { - try { - await z.number().lte(3).parseAsync(4); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("Number must be less than or equal to 3"); - } -}); - -test("number nonnegative", async () => { - try { - await z.number().nonnegative().parseAsync(-1); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("Number must be greater than or equal to 0"); - } -}); - -test("number nonpositive", async () => { - try { - await z.number().nonpositive().parseAsync(1); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("Number must be less than or equal to 0"); - } -}); - -test("number negative", async () => { - try { - await z.number().negative().parseAsync(1); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("Number must be less than 0"); - } -}); - -test("number positive", async () => { - try { - await z.number().positive().parseAsync(-1); - } catch (err) { - expect((err as z.ZodError).issues[0].message).toEqual("Number must be greater than 0"); - } -}); - -test("instantiation", () => { - z.string().min(5); - z.string().max(5); - z.string().length(5); - z.string().email(); - z.string().url(); - z.string().uuid(); - z.string().min(5, { message: "Must be 5 or more characters long" }); - z.string().max(5, { message: "Must be 5 or fewer characters long" }); - z.string().length(5, { message: "Must be exactly 5 characters long" }); - z.string().email({ message: "Invalid email address." }); - z.string().url({ message: "Invalid url" }); - z.string().uuid({ message: "Invalid UUID" }); -}); - -test("int", async () => { - const int = z.number().int(); - int.parse(4); - expect(() => int.parse(3.5)).toThrow(); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/void.test.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/void.test.ts deleted file mode 100644 index b128f1177..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/tests/void.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-ignore TS6133 -import { expect, test } from "vitest"; - -import * as z from "zod/v3"; -import { util } from "../helpers/util.js"; -test("void", () => { - const v = z.void(); - v.parse(undefined); - - expect(() => v.parse(null)).toThrow(); - expect(() => v.parse("")).toThrow(); - - type v = z.infer; - util.assertEqual(true); -}); diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/types.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/types.ts deleted file mode 100644 index f4028549b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v3/types.ts +++ /dev/null @@ -1,5138 +0,0 @@ -import { - type IssueData, - type StringValidation, - type ZodCustomIssue, - ZodError, - type ZodErrorMap, - type ZodIssue, - ZodIssueCode, -} from "./ZodError.js"; -import { defaultErrorMap, getErrorMap } from "./errors.js"; -import type { enumUtil } from "./helpers/enumUtil.js"; -import { errorUtil } from "./helpers/errorUtil.js"; -import { - type AsyncParseReturnType, - DIRTY, - INVALID, - OK, - type ParseContext, - type ParseInput, - type ParseParams, - type ParsePath, - type ParseReturnType, - ParseStatus, - type SyncParseReturnType, - addIssueToContext, - isAborted, - isAsync, - isDirty, - isValid, - makeIssue, -} from "./helpers/parseUtil.js"; -import type { partialUtil } from "./helpers/partialUtil.js"; -import type { Primitive } from "./helpers/typeAliases.js"; -import { util, ZodParsedType, getParsedType, type objectUtil } from "./helpers/util.js"; -import type { StandardSchemaV1 } from "./standard-schema.js"; - -/////////////////////////////////////// -/////////////////////////////////////// -////////// ////////// -////////// ZodType ////////// -////////// ////////// -/////////////////////////////////////// -/////////////////////////////////////// - -export interface RefinementCtx { - addIssue: (arg: IssueData) => void; - path: (string | number)[]; -} -export type ZodRawShape = { [k: string]: ZodTypeAny }; -export type ZodTypeAny = ZodType; -export type TypeOf> = T["_output"]; -export type input> = T["_input"]; -export type output> = T["_output"]; -export type { TypeOf as infer }; - -export type CustomErrorParams = Partial>; -export interface ZodTypeDef { - errorMap?: ZodErrorMap | undefined; - description?: string | undefined; -} - -class ParseInputLazyPath implements ParseInput { - parent: ParseContext; - data: any; - _path: ParsePath; - _key: string | number | (string | number)[]; - _cachedPath: ParsePath = []; - constructor(parent: ParseContext, value: any, path: ParsePath, key: string | number | (string | number)[]) { - this.parent = parent; - this.data = value; - this._path = path; - this._key = key; - } - get path() { - if (!this._cachedPath.length) { - if (Array.isArray(this._key)) { - this._cachedPath.push(...this._path, ...this._key); - } else { - this._cachedPath.push(...this._path, this._key); - } - } - - return this._cachedPath; - } -} - -const handleResult = ( - ctx: ParseContext, - result: SyncParseReturnType -): { success: true; data: Output } | { success: false; error: ZodError } => { - if (isValid(result)) { - return { success: true, data: result.value }; - } else { - if (!ctx.common.issues.length) { - throw new Error("Validation failed but no issues detected."); - } - - return { - success: false, - get error() { - if ((this as any)._error) return (this as any)._error as Error; - const error = new ZodError(ctx.common.issues); - (this as any)._error = error; - return (this as any)._error; - }, - }; - } -}; - -export type RawCreateParams = - | { - errorMap?: ZodErrorMap | undefined; - invalid_type_error?: string | undefined; - required_error?: string | undefined; - message?: string | undefined; - description?: string | undefined; - } - | undefined; -export type ProcessedCreateParams = { - errorMap?: ZodErrorMap | undefined; - description?: string | undefined; -}; -function processCreateParams(params: RawCreateParams): ProcessedCreateParams { - if (!params) return {}; - const { errorMap, invalid_type_error, required_error, description } = params; - if (errorMap && (invalid_type_error || required_error)) { - throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`); - } - if (errorMap) return { errorMap: errorMap, description }; - const customMap: ZodErrorMap = (iss, ctx) => { - const { message } = params; - - if (iss.code === "invalid_enum_value") { - return { message: message ?? ctx.defaultError }; - } - if (typeof ctx.data === "undefined") { - return { message: message ?? required_error ?? ctx.defaultError }; - } - if (iss.code !== "invalid_type") return { message: ctx.defaultError }; - return { message: message ?? invalid_type_error ?? ctx.defaultError }; - }; - return { errorMap: customMap, description }; -} - -export type SafeParseSuccess = { - success: true; - data: Output; - error?: never; -}; -export type SafeParseError = { - success: false; - error: ZodError; - data?: never; -}; - -export type SafeParseReturnType = SafeParseSuccess | SafeParseError; - -export abstract class ZodType { - readonly _type!: Output; - readonly _output!: Output; - readonly _input!: Input; - readonly _def!: Def; - - get description(): string | undefined { - return this._def.description; - } - - "~standard": StandardSchemaV1.Props; - - abstract _parse(input: ParseInput): ParseReturnType; - - _getType(input: ParseInput): string { - return getParsedType(input.data); - } - - _getOrReturnCtx(input: ParseInput, ctx?: ParseContext | undefined): ParseContext { - return ( - ctx || { - common: input.parent.common, - data: input.data, - - parsedType: getParsedType(input.data), - - schemaErrorMap: this._def.errorMap, - path: input.path, - parent: input.parent, - } - ); - } - - _processInputParams(input: ParseInput): { - status: ParseStatus; - ctx: ParseContext; - } { - return { - status: new ParseStatus(), - ctx: { - common: input.parent.common, - data: input.data, - - parsedType: getParsedType(input.data), - - schemaErrorMap: this._def.errorMap, - path: input.path, - parent: input.parent, - }, - }; - } - - _parseSync(input: ParseInput): SyncParseReturnType { - const result = this._parse(input); - if (isAsync(result)) { - throw new Error("Synchronous parse encountered promise."); - } - return result; - } - - _parseAsync(input: ParseInput): AsyncParseReturnType { - const result = this._parse(input); - return Promise.resolve(result); - } - - parse(data: unknown, params?: util.InexactPartial): Output { - const result = this.safeParse(data, params); - if (result.success) return result.data; - throw result.error; - } - - safeParse(data: unknown, params?: util.InexactPartial): SafeParseReturnType { - const ctx: ParseContext = { - common: { - issues: [], - async: params?.async ?? false, - contextualErrorMap: params?.errorMap, - }, - path: params?.path || [], - schemaErrorMap: this._def.errorMap, - parent: null, - data, - parsedType: getParsedType(data), - }; - const result = this._parseSync({ data, path: ctx.path, parent: ctx }); - - return handleResult(ctx, result); - } - - "~validate"(data: unknown): StandardSchemaV1.Result | Promise> { - const ctx: ParseContext = { - common: { - issues: [], - async: !!(this["~standard"] as any).async, - }, - path: [], - schemaErrorMap: this._def.errorMap, - parent: null, - data, - parsedType: getParsedType(data), - }; - - if (!(this["~standard"] as any).async) { - try { - const result = this._parseSync({ data, path: [], parent: ctx }); - return isValid(result) - ? { - value: result.value, - } - : { - issues: ctx.common.issues, - }; - } catch (err: any) { - if ((err as Error)?.message?.toLowerCase()?.includes("encountered")) { - (this["~standard"] as any).async = true; - } - (ctx as any).common = { - issues: [], - async: true, - }; - } - } - - return this._parseAsync({ data, path: [], parent: ctx }).then((result) => - isValid(result) - ? { - value: result.value, - } - : { - issues: ctx.common.issues, - } - ); - } - - async parseAsync(data: unknown, params?: util.InexactPartial): Promise { - const result = await this.safeParseAsync(data, params); - if (result.success) return result.data; - throw result.error; - } - - async safeParseAsync( - data: unknown, - params?: util.InexactPartial - ): Promise> { - const ctx: ParseContext = { - common: { - issues: [], - contextualErrorMap: params?.errorMap, - async: true, - }, - path: params?.path || [], - schemaErrorMap: this._def.errorMap, - parent: null, - data, - parsedType: getParsedType(data), - }; - - const maybeAsyncResult = this._parse({ data, path: ctx.path, parent: ctx }); - const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); - return handleResult(ctx, result); - } - - /** Alias of safeParseAsync */ - spa = this.safeParseAsync; - - refine( - check: (arg: Output) => arg is RefinedOutput, - message?: string | CustomErrorParams | ((arg: Output) => CustomErrorParams) - ): ZodEffects; - refine( - check: (arg: Output) => unknown | Promise, - message?: string | CustomErrorParams | ((arg: Output) => CustomErrorParams) - ): ZodEffects; - refine( - check: (arg: Output) => unknown, - message?: string | CustomErrorParams | ((arg: Output) => CustomErrorParams) - ): ZodEffects { - const getIssueProperties = (val: Output) => { - if (typeof message === "string" || typeof message === "undefined") { - return { message }; - } else if (typeof message === "function") { - return message(val); - } else { - return message; - } - }; - return this._refinement((val, ctx) => { - const result = check(val); - const setError = () => - ctx.addIssue({ - code: ZodIssueCode.custom, - ...getIssueProperties(val), - }); - if (typeof Promise !== "undefined" && result instanceof Promise) { - return result.then((data) => { - if (!data) { - setError(); - return false; - } else { - return true; - } - }); - } - if (!result) { - setError(); - return false; - } else { - return true; - } - }); - } - - refinement( - check: (arg: Output) => arg is RefinedOutput, - refinementData: IssueData | ((arg: Output, ctx: RefinementCtx) => IssueData) - ): ZodEffects; - refinement( - check: (arg: Output) => boolean, - refinementData: IssueData | ((arg: Output, ctx: RefinementCtx) => IssueData) - ): ZodEffects; - refinement( - check: (arg: Output) => unknown, - refinementData: IssueData | ((arg: Output, ctx: RefinementCtx) => IssueData) - ): ZodEffects { - return this._refinement((val, ctx) => { - if (!check(val)) { - ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData); - return false; - } else { - return true; - } - }); - } - - _refinement(refinement: RefinementEffect["refinement"]): ZodEffects { - return new ZodEffects({ - schema: this, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect: { type: "refinement", refinement }, - }); - } - - superRefine( - refinement: (arg: Output, ctx: RefinementCtx) => arg is RefinedOutput - ): ZodEffects; - superRefine(refinement: (arg: Output, ctx: RefinementCtx) => void): ZodEffects; - superRefine(refinement: (arg: Output, ctx: RefinementCtx) => Promise): ZodEffects; - superRefine( - refinement: (arg: Output, ctx: RefinementCtx) => unknown | Promise - ): ZodEffects { - return this._refinement(refinement); - } - - constructor(def: Def) { - this._def = def; - this.parse = this.parse.bind(this); - this.safeParse = this.safeParse.bind(this); - this.parseAsync = this.parseAsync.bind(this); - this.safeParseAsync = this.safeParseAsync.bind(this); - this.spa = this.spa.bind(this); - this.refine = this.refine.bind(this); - this.refinement = this.refinement.bind(this); - this.superRefine = this.superRefine.bind(this); - this.optional = this.optional.bind(this); - this.nullable = this.nullable.bind(this); - this.nullish = this.nullish.bind(this); - this.array = this.array.bind(this); - this.promise = this.promise.bind(this); - this.or = this.or.bind(this); - this.and = this.and.bind(this); - this.transform = this.transform.bind(this); - this.brand = this.brand.bind(this); - this.default = this.default.bind(this); - this.catch = this.catch.bind(this); - this.describe = this.describe.bind(this); - this.pipe = this.pipe.bind(this); - this.readonly = this.readonly.bind(this); - this.isNullable = this.isNullable.bind(this); - this.isOptional = this.isOptional.bind(this); - this["~standard"] = { - version: 1, - vendor: "zod", - validate: (data) => this["~validate"](data), - }; - } - - optional(): ZodOptional { - return ZodOptional.create(this, this._def) as any; - } - nullable(): ZodNullable { - return ZodNullable.create(this, this._def) as any; - } - nullish(): ZodOptional> { - return this.nullable().optional(); - } - array(): ZodArray { - return ZodArray.create(this); - } - promise(): ZodPromise { - return ZodPromise.create(this, this._def); - } - - or(option: T): ZodUnion<[this, T]> { - return ZodUnion.create([this, option], this._def) as any; - } - - and(incoming: T): ZodIntersection { - return ZodIntersection.create(this, incoming, this._def); - } - - transform( - transform: (arg: Output, ctx: RefinementCtx) => NewOut | Promise - ): ZodEffects { - return new ZodEffects({ - ...processCreateParams(this._def), - schema: this, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect: { type: "transform", transform }, - }) as any; - } - - default(def: util.noUndefined): ZodDefault; - default(def: () => util.noUndefined): ZodDefault; - default(def: any) { - const defaultValueFunc = typeof def === "function" ? def : () => def; - - return new ZodDefault({ - ...processCreateParams(this._def), - innerType: this, - defaultValue: defaultValueFunc, - typeName: ZodFirstPartyTypeKind.ZodDefault, - }) as any; - } - - brand(brand?: B): ZodBranded; - brand(): ZodBranded { - return new ZodBranded({ - typeName: ZodFirstPartyTypeKind.ZodBranded, - type: this, - ...processCreateParams(this._def), - }); - } - - catch(def: Output): ZodCatch; - catch(def: (ctx: { error: ZodError; input: Input }) => Output): ZodCatch; - catch(def: any) { - const catchValueFunc = typeof def === "function" ? def : () => def; - - return new ZodCatch({ - ...processCreateParams(this._def), - innerType: this, - catchValue: catchValueFunc, - typeName: ZodFirstPartyTypeKind.ZodCatch, - }) as any; - } - - describe(description: string): this { - const This = (this as any).constructor; - return new This({ - ...this._def, - description, - }); - } - - pipe(target: T): ZodPipeline { - return ZodPipeline.create(this, target); - } - readonly(): ZodReadonly { - return ZodReadonly.create(this); - } - - isOptional(): boolean { - return this.safeParse(undefined).success; - } - isNullable(): boolean { - return this.safeParse(null).success; - } -} - -///////////////////////////////////////// -///////////////////////////////////////// -////////// ////////// -////////// ZodString ////////// -////////// ////////// -///////////////////////////////////////// -///////////////////////////////////////// -export type IpVersion = "v4" | "v6"; -export type ZodStringCheck = - | { kind: "min"; value: number; message?: string | undefined } - | { kind: "max"; value: number; message?: string | undefined } - | { kind: "length"; value: number; message?: string | undefined } - | { kind: "email"; message?: string | undefined } - | { kind: "url"; message?: string | undefined } - | { kind: "emoji"; message?: string | undefined } - | { kind: "uuid"; message?: string | undefined } - | { kind: "nanoid"; message?: string | undefined } - | { kind: "cuid"; message?: string | undefined } - | { kind: "includes"; value: string; position?: number | undefined; message?: string | undefined } - | { kind: "cuid2"; message?: string | undefined } - | { kind: "ulid"; message?: string | undefined } - | { kind: "startsWith"; value: string; message?: string | undefined } - | { kind: "endsWith"; value: string; message?: string | undefined } - | { kind: "regex"; regex: RegExp; message?: string | undefined } - | { kind: "trim"; message?: string | undefined } - | { kind: "toLowerCase"; message?: string | undefined } - | { kind: "toUpperCase"; message?: string | undefined } - | { kind: "jwt"; alg?: string; message?: string | undefined } - | { - kind: "datetime"; - offset: boolean; - local: boolean; - precision: number | null; - message?: string | undefined; - } - | { - kind: "date"; - // withDate: true; - message?: string | undefined; - } - | { - kind: "time"; - precision: number | null; - message?: string | undefined; - } - | { kind: "duration"; message?: string | undefined } - | { kind: "ip"; version?: IpVersion | undefined; message?: string | undefined } - | { kind: "cidr"; version?: IpVersion | undefined; message?: string | undefined } - | { kind: "base64"; message?: string | undefined } - | { kind: "base64url"; message?: string | undefined }; - -export interface ZodStringDef extends ZodTypeDef { - checks: ZodStringCheck[]; - typeName: ZodFirstPartyTypeKind.ZodString; - coerce: boolean; -} - -const cuidRegex = /^c[^\s-]{8,}$/i; -const cuid2Regex = /^[0-9a-z]+$/; -const ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/i; -// const uuidRegex = -// /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i; -const uuidRegex = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i; -const nanoidRegex = /^[a-z0-9_-]{21}$/i; -const jwtRegex = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/; -const durationRegex = - /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/; - -// from https://stackoverflow.com/a/46181/1550155 -// old version: too slow, didn't support unicode -// const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; -//old email regex -// const emailRegex = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@((?!-)([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{1,})[^-<>()[\].,;:\s@"]$/i; -// eslint-disable-next-line -// const emailRegex = -// /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\])|(\[IPv6:(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))\])|([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])*(\.[A-Za-z]{2,})+))$/; -// const emailRegex = -// /^[a-zA-Z0-9\.\!\#\$\%\&\'\*\+\/\=\?\^\_\`\{\|\}\~\-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; -// const emailRegex = -// /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/i; -const emailRegex = /^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i; -// const emailRegex = -// /^[a-z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-z0-9-]+(?:\.[a-z0-9\-]+)*$/i; - -// from https://thekevinscott.com/emojis-in-javascript/#writing-a-regular-expression -const _emojiRegex = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`; -let emojiRegex: RegExp; - -// faster, simpler, safer -const ipv4Regex = - /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/; -const ipv4CidrRegex = - /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/; - -// const ipv6Regex = -// /^(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$/; -const ipv6Regex = - /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/; -const ipv6CidrRegex = - /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/; - -// https://stackoverflow.com/questions/7860392/determine-if-string-is-in-base64-using-javascript -const base64Regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/; - -// https://base64.guru/standards/base64url -const base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/; - -// simple -// const dateRegexSource = `\\d{4}-\\d{2}-\\d{2}`; -// no leap year validation -// const dateRegexSource = `\\d{4}-((0[13578]|10|12)-31|(0[13-9]|1[0-2])-30|(0[1-9]|1[0-2])-(0[1-9]|1\\d|2\\d))`; -// with leap year validation -const dateRegexSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`; -const dateRegex = new RegExp(`^${dateRegexSource}$`); - -function timeRegexSource(args: { precision?: number | null }) { - let secondsRegexSource = `[0-5]\\d`; - if (args.precision) { - secondsRegexSource = `${secondsRegexSource}\\.\\d{${args.precision}}`; - } else if (args.precision == null) { - secondsRegexSource = `${secondsRegexSource}(\\.\\d+)?`; - } - - const secondsQuantifier = args.precision ? "+" : "?"; // require seconds if precision is nonzero - return `([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`; -} - -function timeRegex(args: { - offset?: boolean; - local?: boolean; - precision?: number | null; -}) { - return new RegExp(`^${timeRegexSource(args)}$`); -} - -// Adapted from https://stackoverflow.com/a/3143231 -export function datetimeRegex(args: { - precision?: number | null; - offset?: boolean; - local?: boolean; -}) { - let regex = `${dateRegexSource}T${timeRegexSource(args)}`; - - const opts: string[] = []; - opts.push(args.local ? `Z?` : `Z`); - if (args.offset) opts.push(`([+-]\\d{2}:?\\d{2})`); - regex = `${regex}(${opts.join("|")})`; - return new RegExp(`^${regex}$`); -} - -function isValidIP(ip: string, version?: IpVersion) { - if ((version === "v4" || !version) && ipv4Regex.test(ip)) { - return true; - } - if ((version === "v6" || !version) && ipv6Regex.test(ip)) { - return true; - } - - return false; -} - -function isValidJWT(jwt: string, alg?: string): boolean { - if (!jwtRegex.test(jwt)) return false; - try { - const [header] = jwt.split("."); - if (!header) return false; - // Convert base64url to base64 - const base64 = header - .replace(/-/g, "+") - .replace(/_/g, "/") - .padEnd(header.length + ((4 - (header.length % 4)) % 4), "="); - // @ts-ignore - const decoded = JSON.parse(atob(base64)); - if (typeof decoded !== "object" || decoded === null) return false; - if ("typ" in decoded && decoded?.typ !== "JWT") return false; - if (!decoded.alg) return false; - if (alg && decoded.alg !== alg) return false; - return true; - } catch { - return false; - } -} - -function isValidCidr(ip: string, version?: IpVersion) { - if ((version === "v4" || !version) && ipv4CidrRegex.test(ip)) { - return true; - } - if ((version === "v6" || !version) && ipv6CidrRegex.test(ip)) { - return true; - } - - return false; -} - -export class ZodString extends ZodType { - _parse(input: ParseInput): ParseReturnType { - if (this._def.coerce) { - input.data = String(input.data); - } - const parsedType = this._getType(input); - - if (parsedType !== ZodParsedType.string) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.string, - received: ctx.parsedType, - }); - return INVALID; - } - - const status = new ParseStatus(); - let ctx: undefined | ParseContext = undefined; - - for (const check of this._def.checks) { - if (check.kind === "min") { - if (input.data.length < check.value) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.too_small, - minimum: check.value, - type: "string", - inclusive: true, - exact: false, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "max") { - if (input.data.length > check.value) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.too_big, - maximum: check.value, - type: "string", - inclusive: true, - exact: false, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "length") { - const tooBig = input.data.length > check.value; - const tooSmall = input.data.length < check.value; - if (tooBig || tooSmall) { - ctx = this._getOrReturnCtx(input, ctx); - if (tooBig) { - addIssueToContext(ctx, { - code: ZodIssueCode.too_big, - maximum: check.value, - type: "string", - inclusive: true, - exact: true, - message: check.message, - }); - } else if (tooSmall) { - addIssueToContext(ctx, { - code: ZodIssueCode.too_small, - minimum: check.value, - type: "string", - inclusive: true, - exact: true, - message: check.message, - }); - } - status.dirty(); - } - } else if (check.kind === "email") { - if (!emailRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "email", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "emoji") { - if (!emojiRegex) { - emojiRegex = new RegExp(_emojiRegex, "u"); - } - if (!emojiRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "emoji", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "uuid") { - if (!uuidRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "uuid", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "nanoid") { - if (!nanoidRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "nanoid", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "cuid") { - if (!cuidRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "cuid", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "cuid2") { - if (!cuid2Regex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "cuid2", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "ulid") { - if (!ulidRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "ulid", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "url") { - try { - // @ts-ignore - new URL(input.data); - } catch { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "url", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "regex") { - check.regex.lastIndex = 0; - const testResult = check.regex.test(input.data); - if (!testResult) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "regex", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "trim") { - input.data = input.data.trim(); - } else if (check.kind === "includes") { - if (!(input.data as string).includes(check.value, check.position)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_string, - validation: { includes: check.value, position: check.position }, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "toLowerCase") { - input.data = input.data.toLowerCase(); - } else if (check.kind === "toUpperCase") { - input.data = input.data.toUpperCase(); - } else if (check.kind === "startsWith") { - if (!(input.data as string).startsWith(check.value)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_string, - validation: { startsWith: check.value }, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "endsWith") { - if (!(input.data as string).endsWith(check.value)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_string, - validation: { endsWith: check.value }, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "datetime") { - const regex = datetimeRegex(check); - - if (!regex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_string, - validation: "datetime", - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "date") { - const regex = dateRegex; - - if (!regex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_string, - validation: "date", - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "time") { - const regex = timeRegex(check); - - if (!regex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_string, - validation: "time", - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "duration") { - if (!durationRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "duration", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "ip") { - if (!isValidIP(input.data, check.version)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "ip", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "jwt") { - if (!isValidJWT(input.data, check.alg)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "jwt", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "cidr") { - if (!isValidCidr(input.data, check.version)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "cidr", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "base64") { - if (!base64Regex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "base64", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "base64url") { - if (!base64urlRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - validation: "base64url", - code: ZodIssueCode.invalid_string, - message: check.message, - }); - status.dirty(); - } - } else { - util.assertNever(check); - } - } - - return { status: status.value, value: input.data }; - } - - protected _regex(regex: RegExp, validation: StringValidation, message?: errorUtil.ErrMessage) { - return this.refinement((data) => regex.test(data), { - validation, - code: ZodIssueCode.invalid_string, - ...errorUtil.errToObj(message), - }); - } - - _addCheck(check: ZodStringCheck) { - return new ZodString({ - ...this._def, - checks: [...this._def.checks, check], - }); - } - - email(message?: errorUtil.ErrMessage) { - return this._addCheck({ kind: "email", ...errorUtil.errToObj(message) }); - } - - url(message?: errorUtil.ErrMessage) { - return this._addCheck({ kind: "url", ...errorUtil.errToObj(message) }); - } - - emoji(message?: errorUtil.ErrMessage) { - return this._addCheck({ kind: "emoji", ...errorUtil.errToObj(message) }); - } - - uuid(message?: errorUtil.ErrMessage) { - return this._addCheck({ kind: "uuid", ...errorUtil.errToObj(message) }); - } - nanoid(message?: errorUtil.ErrMessage) { - return this._addCheck({ kind: "nanoid", ...errorUtil.errToObj(message) }); - } - cuid(message?: errorUtil.ErrMessage) { - return this._addCheck({ kind: "cuid", ...errorUtil.errToObj(message) }); - } - - cuid2(message?: errorUtil.ErrMessage) { - return this._addCheck({ kind: "cuid2", ...errorUtil.errToObj(message) }); - } - ulid(message?: errorUtil.ErrMessage) { - return this._addCheck({ kind: "ulid", ...errorUtil.errToObj(message) }); - } - base64(message?: errorUtil.ErrMessage) { - return this._addCheck({ kind: "base64", ...errorUtil.errToObj(message) }); - } - base64url(message?: errorUtil.ErrMessage) { - // base64url encoding is a modification of base64 that can safely be used in URLs and filenames - return this._addCheck({ - kind: "base64url", - ...errorUtil.errToObj(message), - }); - } - - jwt(options?: { alg?: string; message?: string | undefined }) { - return this._addCheck({ kind: "jwt", ...errorUtil.errToObj(options) }); - } - - ip(options?: string | { version?: IpVersion; message?: string | undefined }) { - return this._addCheck({ kind: "ip", ...errorUtil.errToObj(options) }); - } - - cidr(options?: string | { version?: IpVersion; message?: string | undefined }) { - return this._addCheck({ kind: "cidr", ...errorUtil.errToObj(options) }); - } - - datetime( - options?: - | string - | { - message?: string | undefined; - precision?: number | null; - offset?: boolean; - local?: boolean; - } - ) { - if (typeof options === "string") { - return this._addCheck({ - kind: "datetime", - precision: null, - offset: false, - local: false, - message: options, - }); - } - return this._addCheck({ - kind: "datetime", - - precision: typeof options?.precision === "undefined" ? null : options?.precision, - offset: options?.offset ?? false, - local: options?.local ?? false, - ...errorUtil.errToObj(options?.message), - }); - } - - date(message?: string) { - return this._addCheck({ kind: "date", message }); - } - - time( - options?: - | string - | { - message?: string | undefined; - precision?: number | null; - } - ) { - if (typeof options === "string") { - return this._addCheck({ - kind: "time", - precision: null, - message: options, - }); - } - return this._addCheck({ - kind: "time", - precision: typeof options?.precision === "undefined" ? null : options?.precision, - ...errorUtil.errToObj(options?.message), - }); - } - - duration(message?: errorUtil.ErrMessage) { - return this._addCheck({ kind: "duration", ...errorUtil.errToObj(message) }); - } - - regex(regex: RegExp, message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "regex", - regex: regex, - ...errorUtil.errToObj(message), - }); - } - - includes(value: string, options?: { message?: string; position?: number }) { - return this._addCheck({ - kind: "includes", - value: value, - position: options?.position, - ...errorUtil.errToObj(options?.message), - }); - } - - startsWith(value: string, message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "startsWith", - value: value, - ...errorUtil.errToObj(message), - }); - } - - endsWith(value: string, message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "endsWith", - value: value, - ...errorUtil.errToObj(message), - }); - } - - min(minLength: number, message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "min", - value: minLength, - ...errorUtil.errToObj(message), - }); - } - - max(maxLength: number, message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "max", - value: maxLength, - ...errorUtil.errToObj(message), - }); - } - - length(len: number, message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "length", - value: len, - ...errorUtil.errToObj(message), - }); - } - - /** - * Equivalent to `.min(1)` - */ - nonempty(message?: errorUtil.ErrMessage) { - return this.min(1, errorUtil.errToObj(message)); - } - - trim() { - return new ZodString({ - ...this._def, - checks: [...this._def.checks, { kind: "trim" }], - }); - } - - toLowerCase() { - return new ZodString({ - ...this._def, - checks: [...this._def.checks, { kind: "toLowerCase" }], - }); - } - - toUpperCase() { - return new ZodString({ - ...this._def, - checks: [...this._def.checks, { kind: "toUpperCase" }], - }); - } - - get isDatetime() { - return !!this._def.checks.find((ch) => ch.kind === "datetime"); - } - - get isDate() { - return !!this._def.checks.find((ch) => ch.kind === "date"); - } - - get isTime() { - return !!this._def.checks.find((ch) => ch.kind === "time"); - } - get isDuration() { - return !!this._def.checks.find((ch) => ch.kind === "duration"); - } - - get isEmail() { - return !!this._def.checks.find((ch) => ch.kind === "email"); - } - - get isURL() { - return !!this._def.checks.find((ch) => ch.kind === "url"); - } - - get isEmoji() { - return !!this._def.checks.find((ch) => ch.kind === "emoji"); - } - - get isUUID() { - return !!this._def.checks.find((ch) => ch.kind === "uuid"); - } - get isNANOID() { - return !!this._def.checks.find((ch) => ch.kind === "nanoid"); - } - get isCUID() { - return !!this._def.checks.find((ch) => ch.kind === "cuid"); - } - - get isCUID2() { - return !!this._def.checks.find((ch) => ch.kind === "cuid2"); - } - get isULID() { - return !!this._def.checks.find((ch) => ch.kind === "ulid"); - } - get isIP() { - return !!this._def.checks.find((ch) => ch.kind === "ip"); - } - get isCIDR() { - return !!this._def.checks.find((ch) => ch.kind === "cidr"); - } - get isBase64() { - return !!this._def.checks.find((ch) => ch.kind === "base64"); - } - get isBase64url() { - // base64url encoding is a modification of base64 that can safely be used in URLs and filenames - return !!this._def.checks.find((ch) => ch.kind === "base64url"); - } - - get minLength() { - let min: number | null = null; - for (const ch of this._def.checks) { - if (ch.kind === "min") { - if (min === null || ch.value > min) min = ch.value; - } - } - return min; - } - - get maxLength() { - let max: number | null = null; - for (const ch of this._def.checks) { - if (ch.kind === "max") { - if (max === null || ch.value < max) max = ch.value; - } - } - return max; - } - - static create = (params?: RawCreateParams & { coerce?: true }): ZodString => { - return new ZodString({ - checks: [], - typeName: ZodFirstPartyTypeKind.ZodString, - coerce: params?.coerce ?? false, - ...processCreateParams(params), - }); - }; -} - -///////////////////////////////////////// -///////////////////////////////////////// -////////// ////////// -////////// ZodNumber ////////// -////////// ////////// -///////////////////////////////////////// -///////////////////////////////////////// -export type ZodNumberCheck = - | { kind: "min"; value: number; inclusive: boolean; message?: string | undefined } - | { kind: "max"; value: number; inclusive: boolean; message?: string | undefined } - | { kind: "int"; message?: string | undefined } - | { kind: "multipleOf"; value: number; message?: string | undefined } - | { kind: "finite"; message?: string | undefined }; - -// https://stackoverflow.com/questions/3966484/why-does-modulus-operator-return-fractional-number-in-javascript/31711034#31711034 -function floatSafeRemainder(val: number, step: number) { - const valDecCount = (val.toString().split(".")[1] || "").length; - const stepDecCount = (step.toString().split(".")[1] || "").length; - const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount; - const valInt = Number.parseInt(val.toFixed(decCount).replace(".", "")); - const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", "")); - return (valInt % stepInt) / 10 ** decCount; -} - -export interface ZodNumberDef extends ZodTypeDef { - checks: ZodNumberCheck[]; - typeName: ZodFirstPartyTypeKind.ZodNumber; - coerce: boolean; -} - -export class ZodNumber extends ZodType { - _parse(input: ParseInput): ParseReturnType { - if (this._def.coerce) { - input.data = Number(input.data); - } - const parsedType = this._getType(input); - if (parsedType !== ZodParsedType.number) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.number, - received: ctx.parsedType, - }); - return INVALID; - } - - let ctx: undefined | ParseContext = undefined; - const status = new ParseStatus(); - - for (const check of this._def.checks) { - if (check.kind === "int") { - if (!util.isInteger(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: "integer", - received: "float", - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "min") { - const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value; - if (tooSmall) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.too_small, - minimum: check.value, - type: "number", - inclusive: check.inclusive, - exact: false, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "max") { - const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value; - if (tooBig) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.too_big, - maximum: check.value, - type: "number", - inclusive: check.inclusive, - exact: false, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "multipleOf") { - if (floatSafeRemainder(input.data, check.value) !== 0) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.not_multiple_of, - multipleOf: check.value, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "finite") { - if (!Number.isFinite(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.not_finite, - message: check.message, - }); - status.dirty(); - } - } else { - util.assertNever(check); - } - } - - return { status: status.value, value: input.data }; - } - - static create = (params?: RawCreateParams & { coerce?: boolean }): ZodNumber => { - return new ZodNumber({ - checks: [], - typeName: ZodFirstPartyTypeKind.ZodNumber, - coerce: params?.coerce || false, - ...processCreateParams(params), - }); - }; - - gte(value: number, message?: errorUtil.ErrMessage) { - return this.setLimit("min", value, true, errorUtil.toString(message)); - } - min = this.gte; - - gt(value: number, message?: errorUtil.ErrMessage) { - return this.setLimit("min", value, false, errorUtil.toString(message)); - } - - lte(value: number, message?: errorUtil.ErrMessage) { - return this.setLimit("max", value, true, errorUtil.toString(message)); - } - max = this.lte; - - lt(value: number, message?: errorUtil.ErrMessage) { - return this.setLimit("max", value, false, errorUtil.toString(message)); - } - - protected setLimit(kind: "min" | "max", value: number, inclusive: boolean, message?: string) { - return new ZodNumber({ - ...this._def, - checks: [ - ...this._def.checks, - { - kind, - value, - inclusive, - message: errorUtil.toString(message), - }, - ], - }); - } - - _addCheck(check: ZodNumberCheck) { - return new ZodNumber({ - ...this._def, - checks: [...this._def.checks, check], - }); - } - - int(message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "int", - message: errorUtil.toString(message), - }); - } - - positive(message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "min", - value: 0, - inclusive: false, - message: errorUtil.toString(message), - }); - } - - negative(message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "max", - value: 0, - inclusive: false, - message: errorUtil.toString(message), - }); - } - - nonpositive(message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "max", - value: 0, - inclusive: true, - message: errorUtil.toString(message), - }); - } - - nonnegative(message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "min", - value: 0, - inclusive: true, - message: errorUtil.toString(message), - }); - } - - multipleOf(value: number, message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "multipleOf", - value: value, - message: errorUtil.toString(message), - }); - } - step = this.multipleOf; - - finite(message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "finite", - message: errorUtil.toString(message), - }); - } - - safe(message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "min", - inclusive: true, - value: Number.MIN_SAFE_INTEGER, - message: errorUtil.toString(message), - })._addCheck({ - kind: "max", - inclusive: true, - value: Number.MAX_SAFE_INTEGER, - message: errorUtil.toString(message), - }); - } - - get minValue() { - let min: number | null = null; - for (const ch of this._def.checks) { - if (ch.kind === "min") { - if (min === null || ch.value > min) min = ch.value; - } - } - return min; - } - - get maxValue() { - let max: number | null = null; - for (const ch of this._def.checks) { - if (ch.kind === "max") { - if (max === null || ch.value < max) max = ch.value; - } - } - return max; - } - - get isInt() { - return !!this._def.checks.find((ch) => ch.kind === "int" || (ch.kind === "multipleOf" && util.isInteger(ch.value))); - } - - get isFinite() { - let max: number | null = null; - let min: number | null = null; - for (const ch of this._def.checks) { - if (ch.kind === "finite" || ch.kind === "int" || ch.kind === "multipleOf") { - return true; - } else if (ch.kind === "min") { - if (min === null || ch.value > min) min = ch.value; - } else if (ch.kind === "max") { - if (max === null || ch.value < max) max = ch.value; - } - } - return Number.isFinite(min) && Number.isFinite(max); - } -} - -///////////////////////////////////////// -///////////////////////////////////////// -////////// ////////// -////////// ZodBigInt ////////// -////////// ////////// -///////////////////////////////////////// -///////////////////////////////////////// -export type ZodBigIntCheck = - | { kind: "min"; value: bigint; inclusive: boolean; message?: string | undefined } - | { kind: "max"; value: bigint; inclusive: boolean; message?: string | undefined } - | { kind: "multipleOf"; value: bigint; message?: string | undefined }; - -export interface ZodBigIntDef extends ZodTypeDef { - checks: ZodBigIntCheck[]; - typeName: ZodFirstPartyTypeKind.ZodBigInt; - coerce: boolean; -} - -export class ZodBigInt extends ZodType { - _parse(input: ParseInput): ParseReturnType { - if (this._def.coerce) { - try { - input.data = BigInt(input.data); - } catch { - return this._getInvalidInput(input); - } - } - const parsedType = this._getType(input); - if (parsedType !== ZodParsedType.bigint) { - return this._getInvalidInput(input); - } - - let ctx: undefined | ParseContext = undefined; - const status = new ParseStatus(); - - for (const check of this._def.checks) { - if (check.kind === "min") { - const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value; - if (tooSmall) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.too_small, - type: "bigint", - minimum: check.value, - inclusive: check.inclusive, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "max") { - const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value; - if (tooBig) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.too_big, - type: "bigint", - maximum: check.value, - inclusive: check.inclusive, - message: check.message, - }); - status.dirty(); - } - } else if (check.kind === "multipleOf") { - if (input.data % check.value !== BigInt(0)) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.not_multiple_of, - multipleOf: check.value, - message: check.message, - }); - status.dirty(); - } - } else { - util.assertNever(check); - } - } - - return { status: status.value, value: input.data }; - } - - _getInvalidInput(input: ParseInput) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.bigint, - received: ctx.parsedType, - }); - return INVALID; - } - - static create = (params?: RawCreateParams & { coerce?: boolean }): ZodBigInt => { - return new ZodBigInt({ - checks: [], - typeName: ZodFirstPartyTypeKind.ZodBigInt, - coerce: params?.coerce ?? false, - ...processCreateParams(params), - }); - }; - - gte(value: bigint, message?: errorUtil.ErrMessage) { - return this.setLimit("min", value, true, errorUtil.toString(message)); - } - min = this.gte; - - gt(value: bigint, message?: errorUtil.ErrMessage) { - return this.setLimit("min", value, false, errorUtil.toString(message)); - } - - lte(value: bigint, message?: errorUtil.ErrMessage) { - return this.setLimit("max", value, true, errorUtil.toString(message)); - } - max = this.lte; - - lt(value: bigint, message?: errorUtil.ErrMessage) { - return this.setLimit("max", value, false, errorUtil.toString(message)); - } - - protected setLimit(kind: "min" | "max", value: bigint, inclusive: boolean, message?: string) { - return new ZodBigInt({ - ...this._def, - checks: [ - ...this._def.checks, - { - kind, - value, - inclusive, - message: errorUtil.toString(message), - }, - ], - }); - } - - _addCheck(check: ZodBigIntCheck) { - return new ZodBigInt({ - ...this._def, - checks: [...this._def.checks, check], - }); - } - - positive(message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "min", - value: BigInt(0), - inclusive: false, - message: errorUtil.toString(message), - }); - } - - negative(message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "max", - value: BigInt(0), - inclusive: false, - message: errorUtil.toString(message), - }); - } - - nonpositive(message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "max", - value: BigInt(0), - inclusive: true, - message: errorUtil.toString(message), - }); - } - - nonnegative(message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "min", - value: BigInt(0), - inclusive: true, - message: errorUtil.toString(message), - }); - } - - multipleOf(value: bigint, message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "multipleOf", - value, - message: errorUtil.toString(message), - }); - } - - get minValue() { - let min: bigint | null = null; - for (const ch of this._def.checks) { - if (ch.kind === "min") { - if (min === null || ch.value > min) min = ch.value; - } - } - return min; - } - - get maxValue() { - let max: bigint | null = null; - for (const ch of this._def.checks) { - if (ch.kind === "max") { - if (max === null || ch.value < max) max = ch.value; - } - } - return max; - } -} - -////////////////////////////////////////// -////////////////////////////////////////// -////////// /////////// -////////// ZodBoolean ////////// -////////// /////////// -////////////////////////////////////////// -////////////////////////////////////////// -export interface ZodBooleanDef extends ZodTypeDef { - typeName: ZodFirstPartyTypeKind.ZodBoolean; - coerce: boolean; -} - -export class ZodBoolean extends ZodType { - _parse(input: ParseInput): ParseReturnType { - if (this._def.coerce) { - input.data = Boolean(input.data); - } - const parsedType = this._getType(input); - - if (parsedType !== ZodParsedType.boolean) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.boolean, - received: ctx.parsedType, - }); - return INVALID; - } - return OK(input.data); - } - - static create = (params?: RawCreateParams & { coerce?: boolean }): ZodBoolean => { - return new ZodBoolean({ - typeName: ZodFirstPartyTypeKind.ZodBoolean, - coerce: params?.coerce || false, - ...processCreateParams(params), - }); - }; -} - -/////////////////////////////////////// -/////////////////////////////////////// -////////// //////// -////////// ZodDate //////// -////////// //////// -/////////////////////////////////////// -/////////////////////////////////////// -export type ZodDateCheck = - | { kind: "min"; value: number; message?: string | undefined } - | { kind: "max"; value: number; message?: string | undefined }; -export interface ZodDateDef extends ZodTypeDef { - checks: ZodDateCheck[]; - coerce: boolean; - typeName: ZodFirstPartyTypeKind.ZodDate; -} - -export class ZodDate extends ZodType { - _parse(input: ParseInput): ParseReturnType { - if (this._def.coerce) { - input.data = new Date(input.data); - } - const parsedType = this._getType(input); - - if (parsedType !== ZodParsedType.date) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.date, - received: ctx.parsedType, - }); - return INVALID; - } - - if (Number.isNaN(input.data.getTime())) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_date, - }); - return INVALID; - } - - const status = new ParseStatus(); - let ctx: undefined | ParseContext = undefined; - - for (const check of this._def.checks) { - if (check.kind === "min") { - if (input.data.getTime() < check.value) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.too_small, - message: check.message, - inclusive: true, - exact: false, - minimum: check.value, - type: "date", - }); - status.dirty(); - } - } else if (check.kind === "max") { - if (input.data.getTime() > check.value) { - ctx = this._getOrReturnCtx(input, ctx); - addIssueToContext(ctx, { - code: ZodIssueCode.too_big, - message: check.message, - inclusive: true, - exact: false, - maximum: check.value, - type: "date", - }); - status.dirty(); - } - } else { - util.assertNever(check); - } - } - - return { - status: status.value, - value: new Date((input.data as Date).getTime()), - }; - } - - _addCheck(check: ZodDateCheck) { - return new ZodDate({ - ...this._def, - checks: [...this._def.checks, check], - }); - } - - min(minDate: Date, message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "min", - value: minDate.getTime(), - message: errorUtil.toString(message), - }); - } - - max(maxDate: Date, message?: errorUtil.ErrMessage) { - return this._addCheck({ - kind: "max", - value: maxDate.getTime(), - message: errorUtil.toString(message), - }); - } - - get minDate() { - let min: number | null = null; - for (const ch of this._def.checks) { - if (ch.kind === "min") { - if (min === null || ch.value > min) min = ch.value; - } - } - - return min != null ? new Date(min) : null; - } - - get maxDate() { - let max: number | null = null; - for (const ch of this._def.checks) { - if (ch.kind === "max") { - if (max === null || ch.value < max) max = ch.value; - } - } - - return max != null ? new Date(max) : null; - } - - static create = (params?: RawCreateParams & { coerce?: boolean }): ZodDate => { - return new ZodDate({ - checks: [], - coerce: params?.coerce || false, - typeName: ZodFirstPartyTypeKind.ZodDate, - ...processCreateParams(params), - }); - }; -} - -//////////////////////////////////////////// -//////////////////////////////////////////// -////////// ////////// -////////// ZodSymbol ////////// -////////// ////////// -//////////////////////////////////////////// -//////////////////////////////////////////// -export interface ZodSymbolDef extends ZodTypeDef { - typeName: ZodFirstPartyTypeKind.ZodSymbol; -} - -export class ZodSymbol extends ZodType { - _parse(input: ParseInput): ParseReturnType { - const parsedType = this._getType(input); - if (parsedType !== ZodParsedType.symbol) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.symbol, - received: ctx.parsedType, - }); - return INVALID; - } - - return OK(input.data); - } - - static create = (params?: RawCreateParams): ZodSymbol => { - return new ZodSymbol({ - typeName: ZodFirstPartyTypeKind.ZodSymbol, - ...processCreateParams(params), - }); - }; -} - -//////////////////////////////////////////// -//////////////////////////////////////////// -////////// ////////// -////////// ZodUndefined ////////// -////////// ////////// -//////////////////////////////////////////// -//////////////////////////////////////////// -export interface ZodUndefinedDef extends ZodTypeDef { - typeName: ZodFirstPartyTypeKind.ZodUndefined; -} - -export class ZodUndefined extends ZodType { - _parse(input: ParseInput): ParseReturnType { - const parsedType = this._getType(input); - if (parsedType !== ZodParsedType.undefined) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.undefined, - received: ctx.parsedType, - }); - return INVALID; - } - return OK(input.data); - } - params?: RawCreateParams; - - static create = (params?: RawCreateParams): ZodUndefined => { - return new ZodUndefined({ - typeName: ZodFirstPartyTypeKind.ZodUndefined, - ...processCreateParams(params), - }); - }; -} - -/////////////////////////////////////// -/////////////////////////////////////// -////////// ////////// -////////// ZodNull ////////// -////////// ////////// -/////////////////////////////////////// -/////////////////////////////////////// -export interface ZodNullDef extends ZodTypeDef { - typeName: ZodFirstPartyTypeKind.ZodNull; -} - -export class ZodNull extends ZodType { - _parse(input: ParseInput): ParseReturnType { - const parsedType = this._getType(input); - if (parsedType !== ZodParsedType.null) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.null, - received: ctx.parsedType, - }); - return INVALID; - } - return OK(input.data); - } - static create = (params?: RawCreateParams): ZodNull => { - return new ZodNull({ - typeName: ZodFirstPartyTypeKind.ZodNull, - ...processCreateParams(params), - }); - }; -} - -////////////////////////////////////// -////////////////////////////////////// -////////// ////////// -////////// ZodAny ////////// -////////// ////////// -////////////////////////////////////// -////////////////////////////////////// -export interface ZodAnyDef extends ZodTypeDef { - typeName: ZodFirstPartyTypeKind.ZodAny; -} - -export class ZodAny extends ZodType { - // to prevent instances of other classes from extending ZodAny. this causes issues with catchall in ZodObject. - _any = true as const; - _parse(input: ParseInput): ParseReturnType { - return OK(input.data); - } - static create = (params?: RawCreateParams): ZodAny => { - return new ZodAny({ - typeName: ZodFirstPartyTypeKind.ZodAny, - ...processCreateParams(params), - }); - }; -} - -////////////////////////////////////////// -////////////////////////////////////////// -////////// ////////// -////////// ZodUnknown ////////// -////////// ////////// -////////////////////////////////////////// -////////////////////////////////////////// -export interface ZodUnknownDef extends ZodTypeDef { - typeName: ZodFirstPartyTypeKind.ZodUnknown; -} - -export class ZodUnknown extends ZodType { - // required - _unknown = true as const; - _parse(input: ParseInput): ParseReturnType { - return OK(input.data); - } - - static create = (params?: RawCreateParams): ZodUnknown => { - return new ZodUnknown({ - typeName: ZodFirstPartyTypeKind.ZodUnknown, - ...processCreateParams(params), - }); - }; -} - -//////////////////////////////////////// -//////////////////////////////////////// -////////// ////////// -////////// ZodNever ////////// -////////// ////////// -//////////////////////////////////////// -//////////////////////////////////////// -export interface ZodNeverDef extends ZodTypeDef { - typeName: ZodFirstPartyTypeKind.ZodNever; -} - -export class ZodNever extends ZodType { - _parse(input: ParseInput): ParseReturnType { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.never, - received: ctx.parsedType, - }); - return INVALID; - } - static create = (params?: RawCreateParams): ZodNever => { - return new ZodNever({ - typeName: ZodFirstPartyTypeKind.ZodNever, - ...processCreateParams(params), - }); - }; -} - -/////////////////////////////////////// -/////////////////////////////////////// -////////// ////////// -////////// ZodVoid ////////// -////////// ////////// -/////////////////////////////////////// -/////////////////////////////////////// -export interface ZodVoidDef extends ZodTypeDef { - typeName: ZodFirstPartyTypeKind.ZodVoid; -} - -export class ZodVoid extends ZodType { - _parse(input: ParseInput): ParseReturnType { - const parsedType = this._getType(input); - if (parsedType !== ZodParsedType.undefined) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.void, - received: ctx.parsedType, - }); - return INVALID; - } - return OK(input.data); - } - - static create = (params?: RawCreateParams): ZodVoid => { - return new ZodVoid({ - typeName: ZodFirstPartyTypeKind.ZodVoid, - ...processCreateParams(params), - }); - }; -} - -//////////////////////////////////////// -//////////////////////////////////////// -////////// ////////// -////////// ZodArray ////////// -////////// ////////// -//////////////////////////////////////// -//////////////////////////////////////// -export interface ZodArrayDef extends ZodTypeDef { - type: T; - typeName: ZodFirstPartyTypeKind.ZodArray; - exactLength: { value: number; message?: string | undefined } | null; - minLength: { value: number; message?: string | undefined } | null; - maxLength: { value: number; message?: string | undefined } | null; -} - -export type ArrayCardinality = "many" | "atleastone"; -export type arrayOutputType< - T extends ZodTypeAny, - Cardinality extends ArrayCardinality = "many", -> = Cardinality extends "atleastone" ? [T["_output"], ...T["_output"][]] : T["_output"][]; - -export class ZodArray extends ZodType< - arrayOutputType, - ZodArrayDef, - Cardinality extends "atleastone" ? [T["_input"], ...T["_input"][]] : T["_input"][] -> { - _parse(input: ParseInput): ParseReturnType { - const { ctx, status } = this._processInputParams(input); - - const def = this._def; - - if (ctx.parsedType !== ZodParsedType.array) { - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.array, - received: ctx.parsedType, - }); - return INVALID; - } - - if (def.exactLength !== null) { - const tooBig = ctx.data.length > def.exactLength.value; - const tooSmall = ctx.data.length < def.exactLength.value; - if (tooBig || tooSmall) { - addIssueToContext(ctx, { - code: tooBig ? ZodIssueCode.too_big : ZodIssueCode.too_small, - minimum: (tooSmall ? def.exactLength.value : undefined) as number, - maximum: (tooBig ? def.exactLength.value : undefined) as number, - type: "array", - inclusive: true, - exact: true, - message: def.exactLength.message, - }); - status.dirty(); - } - } - - if (def.minLength !== null) { - if (ctx.data.length < def.minLength.value) { - addIssueToContext(ctx, { - code: ZodIssueCode.too_small, - minimum: def.minLength.value, - type: "array", - inclusive: true, - exact: false, - message: def.minLength.message, - }); - status.dirty(); - } - } - - if (def.maxLength !== null) { - if (ctx.data.length > def.maxLength.value) { - addIssueToContext(ctx, { - code: ZodIssueCode.too_big, - maximum: def.maxLength.value, - type: "array", - inclusive: true, - exact: false, - message: def.maxLength.message, - }); - status.dirty(); - } - } - - if (ctx.common.async) { - return Promise.all( - ([...ctx.data] as any[]).map((item, i) => { - return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i)); - }) - ).then((result) => { - return ParseStatus.mergeArray(status, result); - }); - } - - const result = ([...ctx.data] as any[]).map((item, i) => { - return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i)); - }); - - return ParseStatus.mergeArray(status, result); - } - - get element() { - return this._def.type; - } - - min(minLength: number, message?: errorUtil.ErrMessage): this { - return new ZodArray({ - ...this._def, - minLength: { value: minLength, message: errorUtil.toString(message) }, - }) as any; - } - - max(maxLength: number, message?: errorUtil.ErrMessage): this { - return new ZodArray({ - ...this._def, - maxLength: { value: maxLength, message: errorUtil.toString(message) }, - }) as any; - } - - length(len: number, message?: errorUtil.ErrMessage): this { - return new ZodArray({ - ...this._def, - exactLength: { value: len, message: errorUtil.toString(message) }, - }) as any; - } - - nonempty(message?: errorUtil.ErrMessage): ZodArray { - return this.min(1, message) as any; - } - - static create = (schema: El, params?: RawCreateParams): ZodArray => { - return new ZodArray({ - type: schema, - minLength: null, - maxLength: null, - exactLength: null, - typeName: ZodFirstPartyTypeKind.ZodArray, - ...processCreateParams(params), - }); - }; -} - -export type ZodNonEmptyArray = ZodArray; - -///////////////////////////////////////// -///////////////////////////////////////// -////////// ////////// -////////// ZodObject ////////// -////////// ////////// -///////////////////////////////////////// -///////////////////////////////////////// - -export type UnknownKeysParam = "passthrough" | "strict" | "strip"; - -export interface ZodObjectDef< - T extends ZodRawShape = ZodRawShape, - UnknownKeys extends UnknownKeysParam = UnknownKeysParam, - Catchall extends ZodTypeAny = ZodTypeAny, -> extends ZodTypeDef { - typeName: ZodFirstPartyTypeKind.ZodObject; - shape: () => T; - catchall: Catchall; - unknownKeys: UnknownKeys; -} - -export type mergeTypes = { - [k in keyof A | keyof B]: k extends keyof B ? B[k] : k extends keyof A ? A[k] : never; -}; - -export type objectOutputType< - Shape extends ZodRawShape, - Catchall extends ZodTypeAny, - UnknownKeys extends UnknownKeysParam = UnknownKeysParam, -> = objectUtil.flatten>> & - CatchallOutput & - PassthroughType; - -export type baseObjectOutputType = { - [k in keyof Shape]: Shape[k]["_output"]; -}; - -export type objectInputType< - Shape extends ZodRawShape, - Catchall extends ZodTypeAny, - UnknownKeys extends UnknownKeysParam = UnknownKeysParam, -> = objectUtil.flatten> & CatchallInput & PassthroughType; -export type baseObjectInputType = objectUtil.addQuestionMarks<{ - [k in keyof Shape]: Shape[k]["_input"]; -}>; - -export type CatchallOutput = ZodType extends T ? unknown : { [k: string]: T["_output"] }; - -export type CatchallInput = ZodType extends T ? unknown : { [k: string]: T["_input"] }; - -export type PassthroughType = T extends "passthrough" ? { [k: string]: unknown } : unknown; - -export type deoptional = T extends ZodOptional - ? deoptional - : T extends ZodNullable - ? ZodNullable> - : T; - -export type SomeZodObject = ZodObject; - -export type noUnrecognized = { - [k in keyof Obj]: k extends keyof Shape ? Obj[k] : never; -}; - -function deepPartialify(schema: ZodTypeAny): any { - if (schema instanceof ZodObject) { - const newShape: any = {}; - - for (const key in schema.shape) { - const fieldSchema = schema.shape[key]; - newShape[key] = ZodOptional.create(deepPartialify(fieldSchema)); - } - return new ZodObject({ - ...schema._def, - shape: () => newShape, - }) as any; - } else if (schema instanceof ZodArray) { - return new ZodArray({ - ...schema._def, - type: deepPartialify(schema.element), - }); - } else if (schema instanceof ZodOptional) { - return ZodOptional.create(deepPartialify(schema.unwrap())); - } else if (schema instanceof ZodNullable) { - return ZodNullable.create(deepPartialify(schema.unwrap())); - } else if (schema instanceof ZodTuple) { - return ZodTuple.create(schema.items.map((item: any) => deepPartialify(item))); - } else { - return schema; - } -} - -export class ZodObject< - T extends ZodRawShape, - UnknownKeys extends UnknownKeysParam = UnknownKeysParam, - Catchall extends ZodTypeAny = ZodTypeAny, - Output = objectOutputType, - Input = objectInputType, -> extends ZodType, Input> { - _cached: { shape: T; keys: string[] } | null = null; - - _getCached(): { shape: T; keys: string[] } { - if (this._cached !== null) return this._cached; - const shape = this._def.shape(); - const keys = util.objectKeys(shape); - this._cached = { shape, keys }; - return this._cached; - } - - _parse(input: ParseInput): ParseReturnType { - const parsedType = this._getType(input); - if (parsedType !== ZodParsedType.object) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.object, - received: ctx.parsedType, - }); - return INVALID; - } - - const { status, ctx } = this._processInputParams(input); - - const { shape, keys: shapeKeys } = this._getCached(); - const extraKeys: string[] = []; - - if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === "strip")) { - for (const key in ctx.data) { - if (!shapeKeys.includes(key)) { - extraKeys.push(key); - } - } - } - - const pairs: { - key: ParseReturnType; - value: ParseReturnType; - alwaysSet?: boolean; - }[] = []; - for (const key of shapeKeys) { - const keyValidator = shape[key]!; - const value = ctx.data[key]; - pairs.push({ - key: { status: "valid", value: key }, - value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)), - alwaysSet: key in ctx.data, - }); - } - - if (this._def.catchall instanceof ZodNever) { - const unknownKeys = this._def.unknownKeys; - - if (unknownKeys === "passthrough") { - for (const key of extraKeys) { - pairs.push({ - key: { status: "valid", value: key }, - value: { status: "valid", value: ctx.data[key] }, - }); - } - } else if (unknownKeys === "strict") { - if (extraKeys.length > 0) { - addIssueToContext(ctx, { - code: ZodIssueCode.unrecognized_keys, - keys: extraKeys, - }); - status.dirty(); - } - } else if (unknownKeys === "strip") { - } else { - throw new Error(`Internal ZodObject error: invalid unknownKeys value.`); - } - } else { - // run catchall validation - const catchall = this._def.catchall; - - for (const key of extraKeys) { - const value = ctx.data[key]; - pairs.push({ - key: { status: "valid", value: key }, - value: catchall._parse( - new ParseInputLazyPath(ctx, value, ctx.path, key) //, ctx.child(key), value, getParsedType(value) - ), - alwaysSet: key in ctx.data, - }); - } - } - - if (ctx.common.async) { - return Promise.resolve() - .then(async () => { - const syncPairs: any[] = []; - for (const pair of pairs) { - const key = await pair.key; - const value = await pair.value; - syncPairs.push({ - key, - value, - alwaysSet: pair.alwaysSet, - }); - } - return syncPairs; - }) - .then((syncPairs) => { - return ParseStatus.mergeObjectSync(status, syncPairs); - }); - } else { - return ParseStatus.mergeObjectSync(status, pairs as any); - } - } - - get shape() { - return this._def.shape(); - } - - strict(message?: errorUtil.ErrMessage): ZodObject { - errorUtil.errToObj; - return new ZodObject({ - ...this._def, - unknownKeys: "strict", - ...(message !== undefined - ? { - errorMap: (issue, ctx) => { - const defaultError = this._def.errorMap?.(issue, ctx).message ?? ctx.defaultError; - if (issue.code === "unrecognized_keys") - return { - message: errorUtil.errToObj(message).message ?? defaultError, - }; - return { - message: defaultError, - }; - }, - } - : {}), - }) as any; - } - - strip(): ZodObject { - return new ZodObject({ - ...this._def, - unknownKeys: "strip", - }) as any; - } - - passthrough(): ZodObject { - return new ZodObject({ - ...this._def, - unknownKeys: "passthrough", - }) as any; - } - - /** - * @deprecated In most cases, this is no longer needed - unknown properties are now silently stripped. - * If you want to pass through unknown properties, use `.passthrough()` instead. - */ - nonstrict = this.passthrough; - - // const AugmentFactory = - // (def: Def) => - // ( - // augmentation: Augmentation - // ): ZodObject< - // extendShape, Augmentation>, - // Def["unknownKeys"], - // Def["catchall"] - // > => { - // return new ZodObject({ - // ...def, - // shape: () => ({ - // ...def.shape(), - // ...augmentation, - // }), - // }) as any; - // }; - extend( - augmentation: Augmentation - ): ZodObject, UnknownKeys, Catchall> { - return new ZodObject({ - ...this._def, - shape: () => ({ - ...this._def.shape(), - ...augmentation, - }), - }) as any; - } - // extend< - // Augmentation extends ZodRawShape, - // NewOutput extends util.flatten<{ - // [k in keyof Augmentation | keyof Output]: k extends keyof Augmentation - // ? Augmentation[k]["_output"] - // : k extends keyof Output - // ? Output[k] - // : never; - // }>, - // NewInput extends util.flatten<{ - // [k in keyof Augmentation | keyof Input]: k extends keyof Augmentation - // ? Augmentation[k]["_input"] - // : k extends keyof Input - // ? Input[k] - // : never; - // }> - // >( - // augmentation: Augmentation - // ): ZodObject< - // extendShape, - // UnknownKeys, - // Catchall, - // NewOutput, - // NewInput - // > { - // return new ZodObject({ - // ...this._def, - // shape: () => ({ - // ...this._def.shape(), - // ...augmentation, - // }), - // }) as any; - // } - /** - * @deprecated Use `.extend` instead - * */ - augment = this.extend; - - /** - * Prior to zod@1.0.12 there was a bug in the - * inferred type of merged objects. Please - * upgrade if you are experiencing issues. - */ - merge( - merging: Incoming - ): ZodObject, Incoming["_def"]["unknownKeys"], Incoming["_def"]["catchall"]> { - const merged: any = new ZodObject({ - unknownKeys: merging._def.unknownKeys, - catchall: merging._def.catchall, - shape: () => ({ - ...this._def.shape(), - ...merging._def.shape(), - }), - typeName: ZodFirstPartyTypeKind.ZodObject, - }) as any; - return merged; - } - // merge< - // Incoming extends AnyZodObject, - // Augmentation extends Incoming["shape"], - // NewOutput extends { - // [k in keyof Augmentation | keyof Output]: k extends keyof Augmentation - // ? Augmentation[k]["_output"] - // : k extends keyof Output - // ? Output[k] - // : never; - // }, - // NewInput extends { - // [k in keyof Augmentation | keyof Input]: k extends keyof Augmentation - // ? Augmentation[k]["_input"] - // : k extends keyof Input - // ? Input[k] - // : never; - // } - // >( - // merging: Incoming - // ): ZodObject< - // extendShape>, - // Incoming["_def"]["unknownKeys"], - // Incoming["_def"]["catchall"], - // NewOutput, - // NewInput - // > { - // const merged: any = new ZodObject({ - // unknownKeys: merging._def.unknownKeys, - // catchall: merging._def.catchall, - // shape: () => - // objectUtil.mergeShapes(this._def.shape(), merging._def.shape()), - // typeName: ZodFirstPartyTypeKind.ZodObject, - // }) as any; - // return merged; - // } - - setKey( - key: Key, - schema: Schema - ): ZodObject { - return this.augment({ [key]: schema }) as any; - } - // merge( - // merging: Incoming - // ): //ZodObject = (merging) => { - // ZodObject< - // extendShape>, - // Incoming["_def"]["unknownKeys"], - // Incoming["_def"]["catchall"] - // > { - // // const mergedShape = objectUtil.mergeShapes( - // // this._def.shape(), - // // merging._def.shape() - // // ); - // const merged: any = new ZodObject({ - // unknownKeys: merging._def.unknownKeys, - // catchall: merging._def.catchall, - // shape: () => - // objectUtil.mergeShapes(this._def.shape(), merging._def.shape()), - // typeName: ZodFirstPartyTypeKind.ZodObject, - // }) as any; - // return merged; - // } - - catchall(index: Index): ZodObject { - return new ZodObject({ - ...this._def, - catchall: index, - }) as any; - } - - pick>( - mask: Mask - ): ZodObject>, UnknownKeys, Catchall> { - const shape: any = {}; - - for (const key of util.objectKeys(mask)) { - if (mask[key] && this.shape[key]) { - shape[key] = this.shape[key]; - } - } - - return new ZodObject({ - ...this._def, - shape: () => shape, - }) as any; - } - - omit>( - mask: Mask - ): ZodObject, UnknownKeys, Catchall> { - const shape: any = {}; - - for (const key of util.objectKeys(this.shape)) { - if (!mask[key]) { - shape[key] = this.shape[key]; - } - } - - return new ZodObject({ - ...this._def, - shape: () => shape, - }) as any; - } - - /** - * @deprecated - */ - deepPartial(): partialUtil.DeepPartial { - return deepPartialify(this); - } - - partial(): ZodObject<{ [k in keyof T]: ZodOptional }, UnknownKeys, Catchall>; - partial>( - mask: Mask - ): ZodObject< - objectUtil.noNever<{ - [k in keyof T]: k extends keyof Mask ? ZodOptional : T[k]; - }>, - UnknownKeys, - Catchall - >; - partial(mask?: any) { - const newShape: any = {}; - - for (const key of util.objectKeys(this.shape)) { - const fieldSchema = this.shape[key]!; - - if (mask && !mask[key]) { - newShape[key] = fieldSchema; - } else { - newShape[key] = fieldSchema.optional(); - } - } - - return new ZodObject({ - ...this._def, - shape: () => newShape, - }) as any; - } - - required(): ZodObject<{ [k in keyof T]: deoptional }, UnknownKeys, Catchall>; - required>( - mask: Mask - ): ZodObject< - objectUtil.noNever<{ - [k in keyof T]: k extends keyof Mask ? deoptional : T[k]; - }>, - UnknownKeys, - Catchall - >; - required(mask?: any) { - const newShape: any = {}; - - for (const key of util.objectKeys(this.shape)) { - if (mask && !mask[key]) { - newShape[key] = this.shape[key]; - } else { - const fieldSchema = this.shape[key]; - let newField = fieldSchema; - - while (newField instanceof ZodOptional) { - newField = (newField as ZodOptional)._def.innerType; - } - - newShape[key] = newField; - } - } - - return new ZodObject({ - ...this._def, - shape: () => newShape, - }) as any; - } - - keyof(): ZodEnum> { - return createZodEnum(util.objectKeys(this.shape) as [string, ...string[]]) as any; - } - - static create = ( - shape: Shape, - params?: RawCreateParams - ): ZodObject< - Shape, - "strip", - ZodTypeAny, - objectOutputType, - objectInputType - > => { - return new ZodObject({ - shape: () => shape, - unknownKeys: "strip", - catchall: ZodNever.create(), - typeName: ZodFirstPartyTypeKind.ZodObject, - ...processCreateParams(params), - }) as any; - }; - - static strictCreate = ( - shape: Shape, - params?: RawCreateParams - ): ZodObject => { - return new ZodObject({ - shape: () => shape, - unknownKeys: "strict", - catchall: ZodNever.create(), - typeName: ZodFirstPartyTypeKind.ZodObject, - ...processCreateParams(params), - }) as any; - }; - - static lazycreate = ( - shape: () => Shape, - params?: RawCreateParams - ): ZodObject => { - return new ZodObject({ - shape, - unknownKeys: "strip", - catchall: ZodNever.create(), - typeName: ZodFirstPartyTypeKind.ZodObject, - ...processCreateParams(params), - }) as any; - }; -} - -export type AnyZodObject = ZodObject; - -//////////////////////////////////////// -//////////////////////////////////////// -////////// ////////// -////////// ZodUnion ////////// -////////// ////////// -//////////////////////////////////////// -//////////////////////////////////////// -export type ZodUnionOptions = Readonly<[ZodTypeAny, ...ZodTypeAny[]]>; -export interface ZodUnionDef> - extends ZodTypeDef { - options: T; - typeName: ZodFirstPartyTypeKind.ZodUnion; -} - -export class ZodUnion extends ZodType< - T[number]["_output"], - ZodUnionDef, - T[number]["_input"] -> { - _parse(input: ParseInput): ParseReturnType { - const { ctx } = this._processInputParams(input); - const options = this._def.options; - - function handleResults(results: { ctx: ParseContext; result: SyncParseReturnType }[]) { - // return first issue-free validation if it exists - for (const result of results) { - if (result.result.status === "valid") { - return result.result; - } - } - - for (const result of results) { - if (result.result.status === "dirty") { - // add issues from dirty option - - ctx.common.issues.push(...result.ctx.common.issues); - return result.result; - } - } - - // return invalid - const unionErrors = results.map((result) => new ZodError(result.ctx.common.issues)); - - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_union, - unionErrors, - }); - return INVALID; - } - - if (ctx.common.async) { - return Promise.all( - options.map(async (option) => { - const childCtx: ParseContext = { - ...ctx, - common: { - ...ctx.common, - issues: [], - }, - parent: null, - }; - return { - result: await option._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: childCtx, - }), - ctx: childCtx, - }; - }) - ).then(handleResults); - } else { - let dirty: undefined | { result: DIRTY; ctx: ParseContext } = undefined; - const issues: ZodIssue[][] = []; - for (const option of options) { - const childCtx: ParseContext = { - ...ctx, - common: { - ...ctx.common, - issues: [], - }, - parent: null, - }; - const result = option._parseSync({ - data: ctx.data, - path: ctx.path, - parent: childCtx, - }); - - if (result.status === "valid") { - return result; - } else if (result.status === "dirty" && !dirty) { - dirty = { result, ctx: childCtx }; - } - - if (childCtx.common.issues.length) { - issues.push(childCtx.common.issues); - } - } - - if (dirty) { - ctx.common.issues.push(...dirty.ctx.common.issues); - return dirty.result; - } - - const unionErrors = issues.map((issues) => new ZodError(issues)); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_union, - unionErrors, - }); - - return INVALID; - } - } - - get options() { - return this._def.options; - } - - static create = >( - types: Options, - params?: RawCreateParams - ): ZodUnion => { - return new ZodUnion({ - options: types, - typeName: ZodFirstPartyTypeKind.ZodUnion, - ...processCreateParams(params), - }); - }; -} - -///////////////////////////////////////////////////// -///////////////////////////////////////////////////// -////////// ////////// -////////// ZodDiscriminatedUnion ////////// -////////// ////////// -///////////////////////////////////////////////////// -///////////////////////////////////////////////////// - -const getDiscriminator = (type: T): Primitive[] => { - if (type instanceof ZodLazy) { - return getDiscriminator(type.schema); - } else if (type instanceof ZodEffects) { - return getDiscriminator(type.innerType()); - } else if (type instanceof ZodLiteral) { - return [type.value]; - } else if (type instanceof ZodEnum) { - return type.options; - } else if (type instanceof ZodNativeEnum) { - // eslint-disable-next-line ban/ban - return util.objectValues(type.enum); - } else if (type instanceof ZodDefault) { - return getDiscriminator(type._def.innerType); - } else if (type instanceof ZodUndefined) { - return [undefined]; - } else if (type instanceof ZodNull) { - return [null]; - } else if (type instanceof ZodOptional) { - return [undefined, ...getDiscriminator(type.unwrap())]; - } else if (type instanceof ZodNullable) { - return [null, ...getDiscriminator(type.unwrap())]; - } else if (type instanceof ZodBranded) { - return getDiscriminator(type.unwrap()); - } else if (type instanceof ZodReadonly) { - return getDiscriminator(type.unwrap()); - } else if (type instanceof ZodCatch) { - return getDiscriminator(type._def.innerType); - } else { - return []; - } -}; - -export type ZodDiscriminatedUnionOption = ZodObject< - { [key in Discriminator]: ZodTypeAny } & ZodRawShape, - UnknownKeysParam, - ZodTypeAny ->; - -export interface ZodDiscriminatedUnionDef< - Discriminator extends string, - Options extends readonly ZodDiscriminatedUnionOption[] = ZodDiscriminatedUnionOption[], -> extends ZodTypeDef { - discriminator: Discriminator; - options: Options; - optionsMap: Map>; - typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion; -} - -export class ZodDiscriminatedUnion< - Discriminator extends string, - Options extends readonly ZodDiscriminatedUnionOption[], -> extends ZodType, ZodDiscriminatedUnionDef, input> { - _parse(input: ParseInput): ParseReturnType { - const { ctx } = this._processInputParams(input); - - if (ctx.parsedType !== ZodParsedType.object) { - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.object, - received: ctx.parsedType, - }); - return INVALID; - } - - const discriminator = this.discriminator; - - const discriminatorValue: string = ctx.data[discriminator]; - - const option = this.optionsMap.get(discriminatorValue); - - if (!option) { - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_union_discriminator, - options: Array.from(this.optionsMap.keys()), - path: [discriminator], - }); - return INVALID; - } - - if (ctx.common.async) { - return option._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx, - }) as any; - } else { - return option._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx, - }) as any; - } - } - - get discriminator() { - return this._def.discriminator; - } - - get options() { - return this._def.options; - } - - get optionsMap() { - return this._def.optionsMap; - } - - /** - * The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor. - * However, it only allows a union of objects, all of which need to share a discriminator property. This property must - * have a different value for each object in the union. - * @param discriminator the name of the discriminator property - * @param types an array of object schemas - * @param params - */ - static create< - Discriminator extends string, - Types extends readonly [ - ZodDiscriminatedUnionOption, - ...ZodDiscriminatedUnionOption[], - ], - >( - discriminator: Discriminator, - options: Types, - params?: RawCreateParams - ): ZodDiscriminatedUnion { - // Get all the valid discriminator values - const optionsMap: Map = new Map(); - - // try { - for (const type of options) { - const discriminatorValues = getDiscriminator(type.shape[discriminator]); - if (!discriminatorValues.length) { - throw new Error( - `A discriminator value for key \`${discriminator}\` could not be extracted from all schema options` - ); - } - for (const value of discriminatorValues) { - if (optionsMap.has(value)) { - throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`); - } - - optionsMap.set(value, type); - } - } - - return new ZodDiscriminatedUnion< - Discriminator, - // DiscriminatorValue, - Types - >({ - typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion, - discriminator, - options, - optionsMap, - ...processCreateParams(params), - }); - } -} - -/////////////////////////////////////////////// -/////////////////////////////////////////////// -////////// ////////// -////////// ZodIntersection ////////// -////////// ////////// -/////////////////////////////////////////////// -/////////////////////////////////////////////// -export interface ZodIntersectionDef - extends ZodTypeDef { - left: T; - right: U; - typeName: ZodFirstPartyTypeKind.ZodIntersection; -} - -function mergeValues(a: any, b: any): { valid: true; data: any } | { valid: false } { - const aType = getParsedType(a); - const bType = getParsedType(b); - - if (a === b) { - return { valid: true, data: a }; - } else if (aType === ZodParsedType.object && bType === ZodParsedType.object) { - const bKeys = util.objectKeys(b); - const sharedKeys = util.objectKeys(a).filter((key) => bKeys.indexOf(key) !== -1); - - const newObj: any = { ...a, ...b }; - for (const key of sharedKeys) { - const sharedValue = mergeValues(a[key], b[key]); - if (!sharedValue.valid) { - return { valid: false }; - } - newObj[key] = sharedValue.data; - } - - return { valid: true, data: newObj }; - } else if (aType === ZodParsedType.array && bType === ZodParsedType.array) { - if (a.length !== b.length) { - return { valid: false }; - } - - const newArray: unknown[] = []; - for (let index = 0; index < a.length; index++) { - const itemA = a[index]; - const itemB = b[index]; - const sharedValue = mergeValues(itemA, itemB); - - if (!sharedValue.valid) { - return { valid: false }; - } - - newArray.push(sharedValue.data); - } - - return { valid: true, data: newArray }; - } else if (aType === ZodParsedType.date && bType === ZodParsedType.date && +a === +b) { - return { valid: true, data: a }; - } else { - return { valid: false }; - } -} - -export class ZodIntersection extends ZodType< - T["_output"] & U["_output"], - ZodIntersectionDef, - T["_input"] & U["_input"] -> { - _parse(input: ParseInput): ParseReturnType { - const { status, ctx } = this._processInputParams(input); - const handleParsed = ( - parsedLeft: SyncParseReturnType, - parsedRight: SyncParseReturnType - ): SyncParseReturnType => { - if (isAborted(parsedLeft) || isAborted(parsedRight)) { - return INVALID; - } - - const merged = mergeValues(parsedLeft.value, parsedRight.value); - - if (!merged.valid) { - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_intersection_types, - }); - return INVALID; - } - - if (isDirty(parsedLeft) || isDirty(parsedRight)) { - status.dirty(); - } - - return { status: status.value, value: merged.data }; - }; - - if (ctx.common.async) { - return Promise.all([ - this._def.left._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx, - }), - this._def.right._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx, - }), - ]).then(([left, right]: any) => handleParsed(left, right)); - } else { - return handleParsed( - this._def.left._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx, - }), - this._def.right._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx, - }) - ); - } - } - - static create = ( - left: TSchema, - right: USchema, - params?: RawCreateParams - ): ZodIntersection => { - return new ZodIntersection({ - left: left, - right: right, - typeName: ZodFirstPartyTypeKind.ZodIntersection, - ...processCreateParams(params), - }); - }; -} - -//////////////////////////////////////// -//////////////////////////////////////// -////////// ////////// -////////// ZodTuple ////////// -////////// ////////// -//////////////////////////////////////// -//////////////////////////////////////// -export type ZodTupleItems = [ZodTypeAny, ...ZodTypeAny[]]; -export type AssertArray = T extends any[] ? T : never; -export type OutputTypeOfTuple = AssertArray<{ - [k in keyof T]: T[k] extends ZodType ? T[k]["_output"] : never; -}>; -export type OutputTypeOfTupleWithRest< - T extends ZodTupleItems | [], - Rest extends ZodTypeAny | null = null, -> = Rest extends ZodTypeAny ? [...OutputTypeOfTuple, ...Rest["_output"][]] : OutputTypeOfTuple; - -export type InputTypeOfTuple = AssertArray<{ - [k in keyof T]: T[k] extends ZodType ? T[k]["_input"] : never; -}>; -export type InputTypeOfTupleWithRest< - T extends ZodTupleItems | [], - Rest extends ZodTypeAny | null = null, -> = Rest extends ZodTypeAny ? [...InputTypeOfTuple, ...Rest["_input"][]] : InputTypeOfTuple; - -export interface ZodTupleDef - extends ZodTypeDef { - items: T; - rest: Rest; - typeName: ZodFirstPartyTypeKind.ZodTuple; -} - -export type AnyZodTuple = ZodTuple<[ZodTypeAny, ...ZodTypeAny[]] | [], ZodTypeAny | null>; -// type ZodTupleItems = [ZodTypeAny, ...ZodTypeAny[]]; -export class ZodTuple< - T extends ZodTupleItems | [] = ZodTupleItems, - Rest extends ZodTypeAny | null = null, -> extends ZodType, ZodTupleDef, InputTypeOfTupleWithRest> { - _parse(input: ParseInput): ParseReturnType { - const { status, ctx } = this._processInputParams(input); - if (ctx.parsedType !== ZodParsedType.array) { - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.array, - received: ctx.parsedType, - }); - return INVALID; - } - - if (ctx.data.length < this._def.items.length) { - addIssueToContext(ctx, { - code: ZodIssueCode.too_small, - minimum: this._def.items.length, - inclusive: true, - exact: false, - type: "array", - }); - - return INVALID; - } - - const rest = this._def.rest; - - if (!rest && ctx.data.length > this._def.items.length) { - addIssueToContext(ctx, { - code: ZodIssueCode.too_big, - maximum: this._def.items.length, - inclusive: true, - exact: false, - type: "array", - }); - status.dirty(); - } - - const items = ([...ctx.data] as any[]) - .map((item, itemIndex) => { - const schema = this._def.items[itemIndex] || this._def.rest; - if (!schema) return null as any as SyncParseReturnType; - return schema._parse(new ParseInputLazyPath(ctx, item, ctx.path, itemIndex)); - }) - .filter((x) => !!x); // filter nulls - - if (ctx.common.async) { - return Promise.all(items).then((results) => { - return ParseStatus.mergeArray(status, results); - }); - } else { - return ParseStatus.mergeArray(status, items as SyncParseReturnType[]); - } - } - - get items() { - return this._def.items; - } - - rest(rest: RestSchema): ZodTuple { - return new ZodTuple({ - ...this._def, - rest, - }); - } - - static create = ( - schemas: Items, - params?: RawCreateParams - ): ZodTuple => { - if (!Array.isArray(schemas)) { - throw new Error("You must pass an array of schemas to z.tuple([ ... ])"); - } - return new ZodTuple({ - items: schemas, - typeName: ZodFirstPartyTypeKind.ZodTuple, - rest: null, - ...processCreateParams(params), - }); - }; -} - -///////////////////////////////////////// -///////////////////////////////////////// -////////// ////////// -////////// ZodRecord ////////// -////////// ////////// -///////////////////////////////////////// -///////////////////////////////////////// -export interface ZodRecordDef - extends ZodTypeDef { - valueType: Value; - keyType: Key; - typeName: ZodFirstPartyTypeKind.ZodRecord; -} - -export type KeySchema = ZodType; -export type RecordType = [string] extends [K] - ? Record - : [number] extends [K] - ? Record - : [symbol] extends [K] - ? Record - : [BRAND] extends [K] - ? Record - : Partial>; -export class ZodRecord extends ZodType< - RecordType, - ZodRecordDef, - RecordType -> { - get keySchema() { - return this._def.keyType; - } - get valueSchema() { - return this._def.valueType; - } - _parse(input: ParseInput): ParseReturnType { - const { status, ctx } = this._processInputParams(input); - if (ctx.parsedType !== ZodParsedType.object) { - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.object, - received: ctx.parsedType, - }); - return INVALID; - } - - const pairs: { - key: ParseReturnType; - value: ParseReturnType; - alwaysSet: boolean; - }[] = []; - - const keyType = this._def.keyType; - const valueType = this._def.valueType; - - for (const key in ctx.data) { - pairs.push({ - key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)), - value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)), - alwaysSet: key in ctx.data, - }); - } - - if (ctx.common.async) { - return ParseStatus.mergeObjectAsync(status, pairs); - } else { - return ParseStatus.mergeObjectSync(status, pairs as any); - } - } - - get element() { - return this._def.valueType; - } - - static create(valueType: Value, params?: RawCreateParams): ZodRecord; - static create( - keySchema: Keys, - valueType: Value, - params?: RawCreateParams - ): ZodRecord; - static create(first: any, second?: any, third?: any): ZodRecord { - if (second instanceof ZodType) { - return new ZodRecord({ - keyType: first, - valueType: second, - typeName: ZodFirstPartyTypeKind.ZodRecord, - ...processCreateParams(third), - }); - } - - return new ZodRecord({ - keyType: ZodString.create(), - valueType: first, - typeName: ZodFirstPartyTypeKind.ZodRecord, - ...processCreateParams(second), - }); - } -} - -////////////////////////////////////// -////////////////////////////////////// -////////// ////////// -////////// ZodMap ////////// -////////// ////////// -////////////////////////////////////// -////////////////////////////////////// -export interface ZodMapDef - extends ZodTypeDef { - valueType: Value; - keyType: Key; - typeName: ZodFirstPartyTypeKind.ZodMap; -} - -export class ZodMap extends ZodType< - Map, - ZodMapDef, - Map -> { - get keySchema() { - return this._def.keyType; - } - get valueSchema() { - return this._def.valueType; - } - _parse(input: ParseInput): ParseReturnType { - const { status, ctx } = this._processInputParams(input); - if (ctx.parsedType !== ZodParsedType.map) { - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.map, - received: ctx.parsedType, - }); - return INVALID; - } - - const keyType = this._def.keyType; - const valueType = this._def.valueType; - - const pairs = [...(ctx.data as Map).entries()].map(([key, value], index) => { - return { - key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])), - value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])), - }; - }); - - if (ctx.common.async) { - const finalMap = new Map(); - return Promise.resolve().then(async () => { - for (const pair of pairs) { - const key = await pair.key; - const value = await pair.value; - if (key.status === "aborted" || value.status === "aborted") { - return INVALID; - } - if (key.status === "dirty" || value.status === "dirty") { - status.dirty(); - } - - finalMap.set(key.value, value.value); - } - return { status: status.value, value: finalMap }; - }); - } else { - const finalMap = new Map(); - for (const pair of pairs) { - const key = pair.key as SyncParseReturnType; - const value = pair.value as SyncParseReturnType; - if (key.status === "aborted" || value.status === "aborted") { - return INVALID; - } - if (key.status === "dirty" || value.status === "dirty") { - status.dirty(); - } - - finalMap.set(key.value, value.value); - } - return { status: status.value, value: finalMap }; - } - } - static create = ( - keyType: KeySchema, - valueType: ValueSchema, - params?: RawCreateParams - ): ZodMap => { - return new ZodMap({ - valueType, - keyType, - typeName: ZodFirstPartyTypeKind.ZodMap, - ...processCreateParams(params), - }); - }; -} - -////////////////////////////////////// -////////////////////////////////////// -////////// ////////// -////////// ZodSet ////////// -////////// ////////// -////////////////////////////////////// -////////////////////////////////////// -export interface ZodSetDef extends ZodTypeDef { - valueType: Value; - typeName: ZodFirstPartyTypeKind.ZodSet; - minSize: { value: number; message?: string | undefined } | null; - maxSize: { value: number; message?: string | undefined } | null; -} - -export class ZodSet extends ZodType< - Set, - ZodSetDef, - Set -> { - _parse(input: ParseInput): ParseReturnType { - const { status, ctx } = this._processInputParams(input); - if (ctx.parsedType !== ZodParsedType.set) { - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.set, - received: ctx.parsedType, - }); - return INVALID; - } - - const def = this._def; - - if (def.minSize !== null) { - if (ctx.data.size < def.minSize.value) { - addIssueToContext(ctx, { - code: ZodIssueCode.too_small, - minimum: def.minSize.value, - type: "set", - inclusive: true, - exact: false, - message: def.minSize.message, - }); - status.dirty(); - } - } - - if (def.maxSize !== null) { - if (ctx.data.size > def.maxSize.value) { - addIssueToContext(ctx, { - code: ZodIssueCode.too_big, - maximum: def.maxSize.value, - type: "set", - inclusive: true, - exact: false, - message: def.maxSize.message, - }); - status.dirty(); - } - } - - const valueType = this._def.valueType; - - function finalizeSet(elements: SyncParseReturnType[]) { - const parsedSet = new Set(); - for (const element of elements) { - if (element.status === "aborted") return INVALID; - if (element.status === "dirty") status.dirty(); - parsedSet.add(element.value); - } - return { status: status.value, value: parsedSet }; - } - - const elements = [...(ctx.data as Set).values()].map((item, i) => - valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i)) - ); - - if (ctx.common.async) { - return Promise.all(elements).then((elements) => finalizeSet(elements)); - } else { - return finalizeSet(elements as SyncParseReturnType[]); - } - } - - min(minSize: number, message?: errorUtil.ErrMessage): this { - return new ZodSet({ - ...this._def, - minSize: { value: minSize, message: errorUtil.toString(message) }, - }) as any; - } - - max(maxSize: number, message?: errorUtil.ErrMessage): this { - return new ZodSet({ - ...this._def, - maxSize: { value: maxSize, message: errorUtil.toString(message) }, - }) as any; - } - - size(size: number, message?: errorUtil.ErrMessage): this { - return this.min(size, message).max(size, message) as any; - } - - nonempty(message?: errorUtil.ErrMessage): ZodSet { - return this.min(1, message) as any; - } - - static create = ( - valueType: ValueSchema, - params?: RawCreateParams - ): ZodSet => { - return new ZodSet({ - valueType, - minSize: null, - maxSize: null, - typeName: ZodFirstPartyTypeKind.ZodSet, - ...processCreateParams(params), - }); - }; -} - -/////////////////////////////////////////// -/////////////////////////////////////////// -////////// ////////// -////////// ZodFunction ////////// -////////// ////////// -/////////////////////////////////////////// -/////////////////////////////////////////// -export interface ZodFunctionDef< - Args extends ZodTuple = ZodTuple, - Returns extends ZodTypeAny = ZodTypeAny, -> extends ZodTypeDef { - args: Args; - returns: Returns; - typeName: ZodFirstPartyTypeKind.ZodFunction; -} - -export type OuterTypeOfFunction< - Args extends ZodTuple, - Returns extends ZodTypeAny, -> = Args["_input"] extends Array ? (...args: Args["_input"]) => Returns["_output"] : never; - -export type InnerTypeOfFunction< - Args extends ZodTuple, - Returns extends ZodTypeAny, -> = Args["_output"] extends Array ? (...args: Args["_output"]) => Returns["_input"] : never; - -export class ZodFunction, Returns extends ZodTypeAny> extends ZodType< - OuterTypeOfFunction, - ZodFunctionDef, - InnerTypeOfFunction -> { - _parse(input: ParseInput): ParseReturnType { - const { ctx } = this._processInputParams(input); - if (ctx.parsedType !== ZodParsedType.function) { - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.function, - received: ctx.parsedType, - }); - return INVALID; - } - - function makeArgsIssue(args: any, error: ZodError): ZodIssue { - return makeIssue({ - data: args, - path: ctx.path, - errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), defaultErrorMap].filter( - (x) => !!x - ), - issueData: { - code: ZodIssueCode.invalid_arguments, - argumentsError: error, - }, - }); - } - - function makeReturnsIssue(returns: any, error: ZodError): ZodIssue { - return makeIssue({ - data: returns, - path: ctx.path, - errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), defaultErrorMap].filter( - (x) => !!x - ), - issueData: { - code: ZodIssueCode.invalid_return_type, - returnTypeError: error, - }, - }); - } - - const params = { errorMap: ctx.common.contextualErrorMap }; - const fn = ctx.data; - - if (this._def.returns instanceof ZodPromise) { - // Would love a way to avoid disabling this rule, but we need - // an alias (using an arrow function was what caused 2651). - // eslint-disable-next-line @typescript-eslint/no-this-alias - const me = this; - return OK(async function (this: any, ...args: any[]) { - const error = new ZodError([]); - const parsedArgs = await me._def.args.parseAsync(args, params).catch((e) => { - error.addIssue(makeArgsIssue(args, e)); - throw error; - }); - const result = await Reflect.apply(fn, this, parsedArgs as any); - const parsedReturns = await (me._def.returns as unknown as ZodPromise)._def.type - .parseAsync(result, params) - .catch((e) => { - error.addIssue(makeReturnsIssue(result, e)); - throw error; - }); - return parsedReturns; - }); - } else { - // Would love a way to avoid disabling this rule, but we need - // an alias (using an arrow function was what caused 2651). - // eslint-disable-next-line @typescript-eslint/no-this-alias - const me = this; - return OK(function (this: any, ...args: any[]) { - const parsedArgs = me._def.args.safeParse(args, params); - if (!parsedArgs.success) { - throw new ZodError([makeArgsIssue(args, parsedArgs.error)]); - } - const result = Reflect.apply(fn, this, parsedArgs.data); - const parsedReturns = me._def.returns.safeParse(result, params); - if (!parsedReturns.success) { - throw new ZodError([makeReturnsIssue(result, parsedReturns.error)]); - } - return parsedReturns.data; - }) as any; - } - } - - parameters() { - return this._def.args; - } - - returnType() { - return this._def.returns; - } - - args[0]>( - ...items: Items - ): ZodFunction, Returns> { - return new ZodFunction({ - ...this._def, - args: ZodTuple.create(items).rest(ZodUnknown.create()) as any, - }); - } - - returns>(returnType: NewReturnType): ZodFunction { - return new ZodFunction({ - ...this._def, - returns: returnType, - }); - } - - implement>( - func: F - ): ReturnType extends Returns["_output"] - ? (...args: Args["_input"]) => ReturnType - : OuterTypeOfFunction { - const validatedFunc = this.parse(func); - return validatedFunc as any; - } - - strictImplement(func: InnerTypeOfFunction): InnerTypeOfFunction { - const validatedFunc = this.parse(func); - return validatedFunc as any; - } - - validate = this.implement; - - static create(): ZodFunction, ZodUnknown>; - static create>(args: T): ZodFunction; - static create(args: T, returns: U): ZodFunction; - static create, U extends ZodTypeAny = ZodUnknown>( - args: T, - returns: U, - params?: RawCreateParams - ): ZodFunction; - static create(args?: AnyZodTuple, returns?: ZodTypeAny, params?: RawCreateParams) { - return new ZodFunction({ - args: (args ? args : ZodTuple.create([]).rest(ZodUnknown.create())) as any, - returns: returns || ZodUnknown.create(), - typeName: ZodFirstPartyTypeKind.ZodFunction, - ...processCreateParams(params), - }) as any; - } -} - -/////////////////////////////////////// -/////////////////////////////////////// -////////// ////////// -////////// ZodLazy ////////// -////////// ////////// -/////////////////////////////////////// -/////////////////////////////////////// -export interface ZodLazyDef extends ZodTypeDef { - getter: () => T; - typeName: ZodFirstPartyTypeKind.ZodLazy; -} - -export class ZodLazy extends ZodType, ZodLazyDef, input> { - get schema(): T { - return this._def.getter(); - } - - _parse(input: ParseInput): ParseReturnType { - const { ctx } = this._processInputParams(input); - const lazySchema = this._def.getter(); - return lazySchema._parse({ data: ctx.data, path: ctx.path, parent: ctx }); - } - - static create = (getter: () => Inner, params?: RawCreateParams): ZodLazy => { - return new ZodLazy({ - getter: getter, - typeName: ZodFirstPartyTypeKind.ZodLazy, - ...processCreateParams(params), - }); - }; -} - -////////////////////////////////////////// -////////////////////////////////////////// -////////// ////////// -////////// ZodLiteral ////////// -////////// ////////// -////////////////////////////////////////// -////////////////////////////////////////// -export interface ZodLiteralDef extends ZodTypeDef { - value: T; - typeName: ZodFirstPartyTypeKind.ZodLiteral; -} - -export class ZodLiteral extends ZodType, T> { - _parse(input: ParseInput): ParseReturnType { - if (input.data !== this._def.value) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - received: ctx.data, - code: ZodIssueCode.invalid_literal, - expected: this._def.value, - }); - return INVALID; - } - return { status: "valid", value: input.data }; - } - - get value() { - return this._def.value; - } - - static create = (value: Value, params?: RawCreateParams): ZodLiteral => { - return new ZodLiteral({ - value: value, - typeName: ZodFirstPartyTypeKind.ZodLiteral, - ...processCreateParams(params), - }); - }; -} - -/////////////////////////////////////// -/////////////////////////////////////// -////////// ////////// -////////// ZodEnum ////////// -////////// ////////// -/////////////////////////////////////// -/////////////////////////////////////// -export type ArrayKeys = keyof any[]; -export type Indices = Exclude; - -export type EnumValues = readonly [T, ...T[]]; - -export type Values = { - [k in T[number]]: k; -}; - -export interface ZodEnumDef extends ZodTypeDef { - values: T; - typeName: ZodFirstPartyTypeKind.ZodEnum; -} - -export type Writeable = { -readonly [P in keyof T]: T[P] }; - -export type FilterEnum = Values extends [] - ? [] - : Values extends [infer Head, ...infer Rest] - ? Head extends ToExclude - ? FilterEnum - : [Head, ...FilterEnum] - : never; - -export type typecast = A extends T ? A : never; - -function createZodEnum>( - values: T, - params?: RawCreateParams -): ZodEnum>; -function createZodEnum(values: T, params?: RawCreateParams): ZodEnum; -function createZodEnum(values: [string, ...string[]], params?: RawCreateParams) { - return new ZodEnum({ - values, - typeName: ZodFirstPartyTypeKind.ZodEnum, - ...processCreateParams(params), - }); -} - -export class ZodEnum extends ZodType, T[number]> { - _cache: Set | undefined; - - _parse(input: ParseInput): ParseReturnType { - if (typeof input.data !== "string") { - const ctx = this._getOrReturnCtx(input); - const expectedValues = this._def.values; - addIssueToContext(ctx, { - expected: util.joinValues(expectedValues) as "string", - received: ctx.parsedType, - code: ZodIssueCode.invalid_type, - }); - return INVALID; - } - - if (!this._cache) { - this._cache = new Set(this._def.values); - } - - if (!this._cache.has(input.data)) { - const ctx = this._getOrReturnCtx(input); - const expectedValues = this._def.values; - - addIssueToContext(ctx, { - received: ctx.data, - code: ZodIssueCode.invalid_enum_value, - options: expectedValues, - }); - return INVALID; - } - return OK(input.data); - } - - get options() { - return this._def.values; - } - - get enum(): Values { - const enumValues: any = {}; - for (const val of this._def.values) { - enumValues[val] = val; - } - return enumValues; - } - - get Values(): Values { - const enumValues: any = {}; - for (const val of this._def.values) { - enumValues[val] = val; - } - return enumValues; - } - - get Enum(): Values { - const enumValues: any = {}; - for (const val of this._def.values) { - enumValues[val] = val; - } - return enumValues; - } - - extract( - values: ToExtract, - newDef: RawCreateParams = this._def - ): ZodEnum> { - return ZodEnum.create(values, { - ...this._def, - ...newDef, - }) as any; - } - - exclude( - values: ToExclude, - newDef: RawCreateParams = this._def - ): ZodEnum>, [string, ...string[]]>> { - return ZodEnum.create(this.options.filter((opt) => !values.includes(opt)) as FilterEnum, { - ...this._def, - ...newDef, - }) as any; - } - - static create = createZodEnum; -} - -///////////////////////////////////////////// -///////////////////////////////////////////// -////////// ////////// -////////// ZodNativeEnum ////////// -////////// ////////// -///////////////////////////////////////////// -///////////////////////////////////////////// -export interface ZodNativeEnumDef extends ZodTypeDef { - values: T; - typeName: ZodFirstPartyTypeKind.ZodNativeEnum; -} - -export type EnumLike = { [k: string]: string | number; [nu: number]: string }; - -export class ZodNativeEnum extends ZodType, T[keyof T]> { - _cache: Set | undefined; - _parse(input: ParseInput): ParseReturnType { - const nativeEnumValues = util.getValidEnumValues(this._def.values); - - const ctx = this._getOrReturnCtx(input); - if (ctx.parsedType !== ZodParsedType.string && ctx.parsedType !== ZodParsedType.number) { - const expectedValues = util.objectValues(nativeEnumValues); - addIssueToContext(ctx, { - expected: util.joinValues(expectedValues) as "string", - received: ctx.parsedType, - code: ZodIssueCode.invalid_type, - }); - return INVALID; - } - - if (!this._cache) { - this._cache = new Set(util.getValidEnumValues(this._def.values)); - } - - if (!this._cache.has(input.data)) { - const expectedValues = util.objectValues(nativeEnumValues); - - addIssueToContext(ctx, { - received: ctx.data, - code: ZodIssueCode.invalid_enum_value, - options: expectedValues, - }); - return INVALID; - } - return OK(input.data); - } - - get enum() { - return this._def.values; - } - - static create = (values: Elements, params?: RawCreateParams): ZodNativeEnum => { - return new ZodNativeEnum({ - values: values, - typeName: ZodFirstPartyTypeKind.ZodNativeEnum, - ...processCreateParams(params), - }); - }; -} - -////////////////////////////////////////// -////////////////////////////////////////// -////////// ////////// -////////// ZodPromise ////////// -////////// ////////// -////////////////////////////////////////// -////////////////////////////////////////// -export interface ZodPromiseDef extends ZodTypeDef { - type: T; - typeName: ZodFirstPartyTypeKind.ZodPromise; -} - -export class ZodPromise extends ZodType< - Promise, - ZodPromiseDef, - Promise -> { - unwrap() { - return this._def.type; - } - - _parse(input: ParseInput): ParseReturnType { - const { ctx } = this._processInputParams(input); - if (ctx.parsedType !== ZodParsedType.promise && ctx.common.async === false) { - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.promise, - received: ctx.parsedType, - }); - return INVALID; - } - - const promisified = ctx.parsedType === ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data); - - return OK( - promisified.then((data: any) => { - return this._def.type.parseAsync(data, { - path: ctx.path, - errorMap: ctx.common.contextualErrorMap, - }); - }) - ); - } - - static create = (schema: Inner, params?: RawCreateParams): ZodPromise => { - return new ZodPromise({ - type: schema, - typeName: ZodFirstPartyTypeKind.ZodPromise, - ...processCreateParams(params), - }); - }; -} - -////////////////////////////////////////////// -////////////////////////////////////////////// -////////// ////////// -////////// ZodEffects ////////// -////////// ////////// -////////////////////////////////////////////// -////////////////////////////////////////////// - -export type Refinement = (arg: T, ctx: RefinementCtx) => any; -export type SuperRefinement = (arg: T, ctx: RefinementCtx) => void | Promise; - -export type RefinementEffect = { - type: "refinement"; - refinement: (arg: T, ctx: RefinementCtx) => any; -}; -export type TransformEffect = { - type: "transform"; - transform: (arg: T, ctx: RefinementCtx) => any; -}; -export type PreprocessEffect = { - type: "preprocess"; - transform: (arg: T, ctx: RefinementCtx) => any; -}; -export type Effect = RefinementEffect | TransformEffect | PreprocessEffect; - -export interface ZodEffectsDef extends ZodTypeDef { - schema: T; - typeName: ZodFirstPartyTypeKind.ZodEffects; - effect: Effect; -} - -export class ZodEffects, Input = input> extends ZodType< - Output, - ZodEffectsDef, - Input -> { - innerType() { - return this._def.schema; - } - - sourceType(): T { - return this._def.schema._def.typeName === ZodFirstPartyTypeKind.ZodEffects - ? (this._def.schema as unknown as ZodEffects).sourceType() - : (this._def.schema as T); - } - - _parse(input: ParseInput): ParseReturnType { - const { status, ctx } = this._processInputParams(input); - - const effect = this._def.effect || null; - - const checkCtx: RefinementCtx = { - addIssue: (arg: IssueData) => { - addIssueToContext(ctx, arg); - if (arg.fatal) { - status.abort(); - } else { - status.dirty(); - } - }, - get path() { - return ctx.path; - }, - }; - - checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx); - - if (effect.type === "preprocess") { - const processed = effect.transform(ctx.data, checkCtx); - - if (ctx.common.async) { - return Promise.resolve(processed).then(async (processed) => { - if (status.value === "aborted") return INVALID; - - const result = await this._def.schema._parseAsync({ - data: processed, - path: ctx.path, - parent: ctx, - }); - if (result.status === "aborted") return INVALID; - if (result.status === "dirty") return DIRTY(result.value); - if (status.value === "dirty") return DIRTY(result.value); - return result; - }); - } else { - if (status.value === "aborted") return INVALID; - const result = this._def.schema._parseSync({ - data: processed, - path: ctx.path, - parent: ctx, - }); - if (result.status === "aborted") return INVALID; - if (result.status === "dirty") return DIRTY(result.value); - if (status.value === "dirty") return DIRTY(result.value); - return result; - } - } - if (effect.type === "refinement") { - const executeRefinement = (acc: unknown): any => { - const result = effect.refinement(acc, checkCtx); - if (ctx.common.async) { - return Promise.resolve(result); - } - if (result instanceof Promise) { - throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead."); - } - return acc; - }; - - if (ctx.common.async === false) { - const inner = this._def.schema._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx, - }); - if (inner.status === "aborted") return INVALID; - if (inner.status === "dirty") status.dirty(); - - // return value is ignored - executeRefinement(inner.value); - return { status: status.value, value: inner.value }; - } else { - return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((inner) => { - if (inner.status === "aborted") return INVALID; - if (inner.status === "dirty") status.dirty(); - - return executeRefinement(inner.value).then(() => { - return { status: status.value, value: inner.value }; - }); - }); - } - } - - if (effect.type === "transform") { - if (ctx.common.async === false) { - const base = this._def.schema._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx, - }); - - if (!isValid(base)) return INVALID; - - const result = effect.transform(base.value, checkCtx); - if (result instanceof Promise) { - throw new Error( - `Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.` - ); - } - - return { status: status.value, value: result }; - } else { - return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base) => { - if (!isValid(base)) return INVALID; - - return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({ - status: status.value, - value: result, - })); - }); - } - } - - util.assertNever(effect); - } - - static create = ( - schema: I, - effect: Effect, - params?: RawCreateParams - ): ZodEffects => { - return new ZodEffects({ - schema, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect, - ...processCreateParams(params), - }); - }; - - static createWithPreprocess = ( - preprocess: (arg: unknown, ctx: RefinementCtx) => unknown, - schema: I, - params?: RawCreateParams - ): ZodEffects => { - return new ZodEffects({ - schema, - effect: { type: "preprocess", transform: preprocess }, - typeName: ZodFirstPartyTypeKind.ZodEffects, - ...processCreateParams(params), - }); - }; -} - -export { ZodEffects as ZodTransformer }; - -/////////////////////////////////////////// -/////////////////////////////////////////// -////////// ////////// -////////// ZodOptional ////////// -////////// ////////// -/////////////////////////////////////////// -/////////////////////////////////////////// -export interface ZodOptionalDef extends ZodTypeDef { - innerType: T; - typeName: ZodFirstPartyTypeKind.ZodOptional; -} - -export type ZodOptionalType = ZodOptional; - -export class ZodOptional extends ZodType< - T["_output"] | undefined, - ZodOptionalDef, - T["_input"] | undefined -> { - _parse(input: ParseInput): ParseReturnType { - const parsedType = this._getType(input); - if (parsedType === ZodParsedType.undefined) { - return OK(undefined); - } - return this._def.innerType._parse(input); - } - - unwrap() { - return this._def.innerType; - } - - static create = (type: Inner, params?: RawCreateParams): ZodOptional => { - return new ZodOptional({ - innerType: type, - typeName: ZodFirstPartyTypeKind.ZodOptional, - ...processCreateParams(params), - }) as any; - }; -} - -/////////////////////////////////////////// -/////////////////////////////////////////// -////////// ////////// -////////// ZodNullable ////////// -////////// ////////// -/////////////////////////////////////////// -/////////////////////////////////////////// -export interface ZodNullableDef extends ZodTypeDef { - innerType: T; - typeName: ZodFirstPartyTypeKind.ZodNullable; -} - -export type ZodNullableType = ZodNullable; - -export class ZodNullable extends ZodType< - T["_output"] | null, - ZodNullableDef, - T["_input"] | null -> { - _parse(input: ParseInput): ParseReturnType { - const parsedType = this._getType(input); - if (parsedType === ZodParsedType.null) { - return OK(null); - } - return this._def.innerType._parse(input); - } - - unwrap() { - return this._def.innerType; - } - - static create = (type: Inner, params?: RawCreateParams): ZodNullable => { - return new ZodNullable({ - innerType: type, - typeName: ZodFirstPartyTypeKind.ZodNullable, - ...processCreateParams(params), - }) as any; - }; -} - -//////////////////////////////////////////// -//////////////////////////////////////////// -////////// ////////// -////////// ZodDefault ////////// -////////// ////////// -//////////////////////////////////////////// -//////////////////////////////////////////// -export interface ZodDefaultDef extends ZodTypeDef { - innerType: T; - defaultValue: () => util.noUndefined; - typeName: ZodFirstPartyTypeKind.ZodDefault; -} - -export class ZodDefault extends ZodType< - util.noUndefined, - ZodDefaultDef, - T["_input"] | undefined -> { - _parse(input: ParseInput): ParseReturnType { - const { ctx } = this._processInputParams(input); - let data = ctx.data; - if (ctx.parsedType === ZodParsedType.undefined) { - data = this._def.defaultValue(); - } - return this._def.innerType._parse({ - data, - path: ctx.path, - parent: ctx, - }); - } - - removeDefault() { - return this._def.innerType; - } - - static create = ( - type: Inner, - params: RawCreateParams & { - default: Inner["_input"] | (() => util.noUndefined); - } - ): ZodDefault => { - return new ZodDefault({ - innerType: type, - typeName: ZodFirstPartyTypeKind.ZodDefault, - defaultValue: typeof params.default === "function" ? params.default : () => params.default as any, - ...processCreateParams(params), - }) as any; - }; -} - -////////////////////////////////////////// -////////////////////////////////////////// -////////// ////////// -////////// ZodCatch ////////// -////////// ////////// -////////////////////////////////////////// -////////////////////////////////////////// -export interface ZodCatchDef extends ZodTypeDef { - innerType: T; - catchValue: (ctx: { error: ZodError; input: unknown }) => T["_input"]; - typeName: ZodFirstPartyTypeKind.ZodCatch; -} - -export class ZodCatch extends ZodType< - T["_output"], - ZodCatchDef, - unknown // any input will pass validation // T["_input"] -> { - _parse(input: ParseInput): ParseReturnType { - const { ctx } = this._processInputParams(input); - - // newCtx is used to not collect issues from inner types in ctx - const newCtx: ParseContext = { - ...ctx, - common: { - ...ctx.common, - issues: [], - }, - }; - - const result = this._def.innerType._parse({ - data: newCtx.data, - path: newCtx.path, - parent: { - ...newCtx, - }, - }); - - if (isAsync(result)) { - return result.then((result) => { - return { - status: "valid", - value: - result.status === "valid" - ? result.value - : this._def.catchValue({ - get error() { - return new ZodError(newCtx.common.issues); - }, - input: newCtx.data, - }), - }; - }); - } else { - return { - status: "valid", - value: - result.status === "valid" - ? result.value - : this._def.catchValue({ - get error() { - return new ZodError(newCtx.common.issues); - }, - input: newCtx.data, - }), - }; - } - } - - removeCatch() { - return this._def.innerType; - } - - static create = ( - type: Inner, - params: RawCreateParams & { - catch: Inner["_output"] | (() => Inner["_output"]); - } - ): ZodCatch => { - return new ZodCatch({ - innerType: type, - typeName: ZodFirstPartyTypeKind.ZodCatch, - catchValue: typeof params.catch === "function" ? params.catch : () => params.catch, - ...processCreateParams(params), - }); - }; -} - -///////////////////////////////////////// -///////////////////////////////////////// -////////// ////////// -////////// ZodNaN ////////// -////////// ////////// -///////////////////////////////////////// -///////////////////////////////////////// - -export interface ZodNaNDef extends ZodTypeDef { - typeName: ZodFirstPartyTypeKind.ZodNaN; -} - -export class ZodNaN extends ZodType { - _parse(input: ParseInput): ParseReturnType { - const parsedType = this._getType(input); - if (parsedType !== ZodParsedType.nan) { - const ctx = this._getOrReturnCtx(input); - addIssueToContext(ctx, { - code: ZodIssueCode.invalid_type, - expected: ZodParsedType.nan, - received: ctx.parsedType, - }); - return INVALID; - } - - return { status: "valid", value: input.data }; - } - - static create = (params?: RawCreateParams): ZodNaN => { - return new ZodNaN({ - typeName: ZodFirstPartyTypeKind.ZodNaN, - ...processCreateParams(params), - }); - }; -} - -////////////////////////////////////////// -////////////////////////////////////////// -////////// ////////// -////////// ZodBranded ////////// -////////// ////////// -////////////////////////////////////////// -////////////////////////////////////////// - -export interface ZodBrandedDef extends ZodTypeDef { - type: T; - typeName: ZodFirstPartyTypeKind.ZodBranded; -} - -export const BRAND: unique symbol = Symbol("zod_brand"); -export type BRAND = { - [BRAND]: { [k in T]: true }; -}; - -export class ZodBranded extends ZodType< - T["_output"] & BRAND, - ZodBrandedDef, - T["_input"] -> { - _parse(input: ParseInput): ParseReturnType { - const { ctx } = this._processInputParams(input); - const data = ctx.data; - return this._def.type._parse({ - data, - path: ctx.path, - parent: ctx, - }); - } - - unwrap() { - return this._def.type; - } -} - -//////////////////////////////////////////// -//////////////////////////////////////////// -////////// ////////// -////////// ZodPipeline ////////// -////////// ////////// -//////////////////////////////////////////// -//////////////////////////////////////////// - -export interface ZodPipelineDef extends ZodTypeDef { - in: A; - out: B; - typeName: ZodFirstPartyTypeKind.ZodPipeline; -} - -export class ZodPipeline extends ZodType< - B["_output"], - ZodPipelineDef, - A["_input"] -> { - _parse(input: ParseInput): ParseReturnType { - const { status, ctx } = this._processInputParams(input); - if (ctx.common.async) { - const handleAsync = async () => { - const inResult = await this._def.in._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx, - }); - if (inResult.status === "aborted") return INVALID; - if (inResult.status === "dirty") { - status.dirty(); - return DIRTY(inResult.value); - } else { - return this._def.out._parseAsync({ - data: inResult.value, - path: ctx.path, - parent: ctx, - }); - } - }; - return handleAsync(); - } else { - const inResult = this._def.in._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx, - }); - if (inResult.status === "aborted") return INVALID; - if (inResult.status === "dirty") { - status.dirty(); - return { - status: "dirty", - value: inResult.value, - }; - } else { - return this._def.out._parseSync({ - data: inResult.value, - path: ctx.path, - parent: ctx, - }); - } - } - } - - static create( - a: ASchema, - b: BSchema - ): ZodPipeline { - return new ZodPipeline({ - in: a, - out: b, - typeName: ZodFirstPartyTypeKind.ZodPipeline, - }); - } -} - -/////////////////////////////////////////// -/////////////////////////////////////////// -////////// ////////// -////////// ZodReadonly ////////// -////////// ////////// -/////////////////////////////////////////// -/////////////////////////////////////////// -type BuiltIn = - | (((...args: any[]) => any) | (new (...args: any[]) => any)) - | { readonly [Symbol.toStringTag]: string } - | Date - | Error - | Generator - | Promise - | RegExp; - -type MakeReadonly = T extends Map - ? ReadonlyMap - : T extends Set - ? ReadonlySet - : T extends [infer Head, ...infer Tail] - ? readonly [Head, ...Tail] - : T extends Array - ? ReadonlyArray - : T extends BuiltIn - ? T - : Readonly; - -export interface ZodReadonlyDef extends ZodTypeDef { - innerType: T; - typeName: ZodFirstPartyTypeKind.ZodReadonly; -} - -export class ZodReadonly extends ZodType< - MakeReadonly, - ZodReadonlyDef, - MakeReadonly -> { - _parse(input: ParseInput): ParseReturnType { - const result = this._def.innerType._parse(input); - const freeze = (data: ParseReturnType) => { - if (isValid(data)) { - data.value = Object.freeze(data.value); - } - return data; - }; - return isAsync(result) ? result.then((data) => freeze(data)) : freeze(result); - } - - static create = (type: Inner, params?: RawCreateParams): ZodReadonly => { - return new ZodReadonly({ - innerType: type, - typeName: ZodFirstPartyTypeKind.ZodReadonly, - ...processCreateParams(params), - }) as any; - }; - - unwrap() { - return this._def.innerType; - } -} - -//////////////////////////////////////// -//////////////////////////////////////// -////////// ////////// -////////// z.custom ////////// -////////// ////////// -//////////////////////////////////////// -//////////////////////////////////////// -function cleanParams(params: unknown, data: unknown) { - const p = typeof params === "function" ? params(data) : typeof params === "string" ? { message: params } : params; - - const p2 = typeof p === "string" ? { message: p } : p; - return p2; -} -type CustomParams = CustomErrorParams & { fatal?: boolean }; -export function custom( - check?: (data: any) => any, - _params: string | CustomParams | ((input: any) => CustomParams) = {}, - /** - * @deprecated - * - * Pass `fatal` into the params object instead: - * - * ```ts - * z.string().custom((val) => val.length > 5, { fatal: false }) - * ``` - * - */ - fatal?: boolean -): ZodType { - if (check) - return ZodAny.create().superRefine((data, ctx) => { - const r = check(data); - if (r instanceof Promise) { - return r.then((r) => { - if (!r) { - const params = cleanParams(_params, data); - const _fatal = params.fatal ?? fatal ?? true; - ctx.addIssue({ code: "custom", ...params, fatal: _fatal }); - } - }); - } - if (!r) { - const params = cleanParams(_params, data); - const _fatal = params.fatal ?? fatal ?? true; - ctx.addIssue({ code: "custom", ...params, fatal: _fatal }); - } - return; - }); - return ZodAny.create(); -} - -export { ZodType as Schema, ZodType as ZodSchema }; - -export const late = { - object: ZodObject.lazycreate, -}; - -export enum ZodFirstPartyTypeKind { - ZodString = "ZodString", - ZodNumber = "ZodNumber", - ZodNaN = "ZodNaN", - ZodBigInt = "ZodBigInt", - ZodBoolean = "ZodBoolean", - ZodDate = "ZodDate", - ZodSymbol = "ZodSymbol", - ZodUndefined = "ZodUndefined", - ZodNull = "ZodNull", - ZodAny = "ZodAny", - ZodUnknown = "ZodUnknown", - ZodNever = "ZodNever", - ZodVoid = "ZodVoid", - ZodArray = "ZodArray", - ZodObject = "ZodObject", - ZodUnion = "ZodUnion", - ZodDiscriminatedUnion = "ZodDiscriminatedUnion", - ZodIntersection = "ZodIntersection", - ZodTuple = "ZodTuple", - ZodRecord = "ZodRecord", - ZodMap = "ZodMap", - ZodSet = "ZodSet", - ZodFunction = "ZodFunction", - ZodLazy = "ZodLazy", - ZodLiteral = "ZodLiteral", - ZodEnum = "ZodEnum", - ZodEffects = "ZodEffects", - ZodNativeEnum = "ZodNativeEnum", - ZodOptional = "ZodOptional", - ZodNullable = "ZodNullable", - ZodDefault = "ZodDefault", - ZodCatch = "ZodCatch", - ZodPromise = "ZodPromise", - ZodBranded = "ZodBranded", - ZodPipeline = "ZodPipeline", - ZodReadonly = "ZodReadonly", -} -export type ZodFirstPartySchemaTypes = - | ZodString - | ZodNumber - | ZodNaN - | ZodBigInt - | ZodBoolean - | ZodDate - | ZodUndefined - | ZodNull - | ZodAny - | ZodUnknown - | ZodNever - | ZodVoid - | ZodArray - | ZodObject - | ZodUnion - | ZodDiscriminatedUnion - | ZodIntersection - | ZodTuple - | ZodRecord - | ZodMap - | ZodSet - | ZodFunction - | ZodLazy - | ZodLiteral - | ZodEnum - | ZodEffects - | ZodNativeEnum - | ZodOptional - | ZodNullable - | ZodDefault - | ZodCatch - | ZodPromise - | ZodBranded - | ZodPipeline - | ZodReadonly - | ZodSymbol; - -// requires TS 4.4+ -abstract class Class { - constructor(..._: any[]) {} -} -const instanceOfType = ( - // const instanceOfType = any>( - cls: T, - params: CustomParams = { - message: `Input not instance of ${cls.name}`, - } -) => custom>((data) => data instanceof cls, params); - -const stringType = ZodString.create; -const numberType = ZodNumber.create; -const nanType = ZodNaN.create; -const bigIntType = ZodBigInt.create; -const booleanType = ZodBoolean.create; -const dateType = ZodDate.create; -const symbolType = ZodSymbol.create; -const undefinedType = ZodUndefined.create; -const nullType = ZodNull.create; -const anyType = ZodAny.create; -const unknownType = ZodUnknown.create; -const neverType = ZodNever.create; -const voidType = ZodVoid.create; -const arrayType = ZodArray.create; -const objectType = ZodObject.create; -const strictObjectType = ZodObject.strictCreate; -const unionType = ZodUnion.create; -const discriminatedUnionType = ZodDiscriminatedUnion.create; -const intersectionType = ZodIntersection.create; -const tupleType = ZodTuple.create; -const recordType = ZodRecord.create; -const mapType = ZodMap.create; -const setType = ZodSet.create; -const functionType = ZodFunction.create; -const lazyType = ZodLazy.create; -const literalType = ZodLiteral.create; -const enumType = ZodEnum.create; -const nativeEnumType = ZodNativeEnum.create; -const promiseType = ZodPromise.create; -const effectsType = ZodEffects.create; -const optionalType = ZodOptional.create; -const nullableType = ZodNullable.create; -const preprocessType = ZodEffects.createWithPreprocess; -const pipelineType = ZodPipeline.create; -const ostring = () => stringType().optional(); -const onumber = () => numberType().optional(); -const oboolean = () => booleanType().optional(); - -export const coerce = { - string: ((arg) => ZodString.create({ ...arg, coerce: true })) as (typeof ZodString)["create"], - number: ((arg) => ZodNumber.create({ ...arg, coerce: true })) as (typeof ZodNumber)["create"], - boolean: ((arg) => - ZodBoolean.create({ - ...arg, - coerce: true, - })) as (typeof ZodBoolean)["create"], - bigint: ((arg) => ZodBigInt.create({ ...arg, coerce: true })) as (typeof ZodBigInt)["create"], - date: ((arg) => ZodDate.create({ ...arg, coerce: true })) as (typeof ZodDate)["create"], -}; - -export { - anyType as any, - arrayType as array, - bigIntType as bigint, - booleanType as boolean, - dateType as date, - discriminatedUnionType as discriminatedUnion, - effectsType as effect, - enumType as enum, - functionType as function, - instanceOfType as instanceof, - intersectionType as intersection, - lazyType as lazy, - literalType as literal, - mapType as map, - nanType as nan, - nativeEnumType as nativeEnum, - neverType as never, - nullType as null, - nullableType as nullable, - numberType as number, - objectType as object, - oboolean, - onumber, - optionalType as optional, - ostring, - pipelineType as pipeline, - preprocessType as preprocess, - promiseType as promise, - recordType as record, - setType as set, - strictObjectType as strictObject, - stringType as string, - symbolType as symbol, - effectsType as transformer, - tupleType as tuple, - undefinedType as undefined, - unionType as union, - unknownType as unknown, - voidType as void, -}; - -export const NEVER = INVALID as never; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4-mini/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4-mini/index.ts deleted file mode 100644 index bb95da0a2..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4-mini/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as z from "../v4/mini/external.js"; -export * from "../v4/mini/external.js"; -export { z }; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/checks.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/checks.ts deleted file mode 100644 index cd78c0e45..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/checks.ts +++ /dev/null @@ -1,32 +0,0 @@ -export { - _lt as lt, - _lte as lte, - _gt as gt, - _gte as gte, - _positive as positive, - _negative as negative, - _nonpositive as nonpositive, - _nonnegative as nonnegative, - _multipleOf as multipleOf, - _maxSize as maxSize, - _minSize as minSize, - _size as size, - _maxLength as maxLength, - _minLength as minLength, - _length as length, - _regex as regex, - _lowercase as lowercase, - _uppercase as uppercase, - _includes as includes, - _startsWith as startsWith, - _endsWith as endsWith, - _property as property, - _mime as mime, - _overwrite as overwrite, - _normalize as normalize, - _trim as trim, - _toLowerCase as toLowerCase, - _toUpperCase as toUpperCase, - _slugify as slugify, - type $RefinementCtx as RefinementCtx, -} from "../core/index.js"; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/coerce.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/coerce.ts deleted file mode 100644 index cc400e0d8..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/coerce.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as core from "../core/index.js"; -import * as schemas from "./schemas.js"; - -export interface ZodCoercedString extends schemas._ZodString> {} -export function string(params?: string | core.$ZodStringParams): ZodCoercedString { - return core._coercedString(schemas.ZodString, params) as any; -} - -export interface ZodCoercedNumber extends schemas._ZodNumber> {} -export function number(params?: string | core.$ZodNumberParams): ZodCoercedNumber { - return core._coercedNumber(schemas.ZodNumber, params) as ZodCoercedNumber; -} - -export interface ZodCoercedBoolean extends schemas._ZodBoolean> {} -export function boolean(params?: string | core.$ZodBooleanParams): ZodCoercedBoolean { - return core._coercedBoolean(schemas.ZodBoolean, params) as ZodCoercedBoolean; -} - -export interface ZodCoercedBigInt extends schemas._ZodBigInt> {} -export function bigint(params?: string | core.$ZodBigIntParams): ZodCoercedBigInt { - return core._coercedBigint(schemas.ZodBigInt, params) as ZodCoercedBigInt; -} - -export interface ZodCoercedDate extends schemas._ZodDate> {} -export function date(params?: string | core.$ZodDateParams): ZodCoercedDate { - return core._coercedDate(schemas.ZodDate, params) as ZodCoercedDate; -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/compat.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/compat.ts deleted file mode 100644 index 86a5813a0..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/compat.ts +++ /dev/null @@ -1,70 +0,0 @@ -// Zod 3 compat layer - -import * as core from "../core/index.js"; -import type { ZodType } from "./schemas.js"; - -export type { - /** @deprecated Use `z.output` instead. */ - output as TypeOf, - /** @deprecated Use `z.output` instead. */ - output as Infer, - /** @deprecated Use `z.core.$$ZodFirstPartyTypes` instead */ - $ZodTypes as ZodFirstPartySchemaTypes, -} from "../core/index.js"; - -/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */ -export const ZodIssueCode = { - invalid_type: "invalid_type", - too_big: "too_big", - too_small: "too_small", - invalid_format: "invalid_format", - not_multiple_of: "not_multiple_of", - unrecognized_keys: "unrecognized_keys", - invalid_union: "invalid_union", - invalid_key: "invalid_key", - invalid_element: "invalid_element", - invalid_value: "invalid_value", - custom: "custom", -} as const; - -/** @deprecated Use `z.$ZodFlattenedError` */ -export type inferFlattenedErrors = core.$ZodFlattenedError, U>; - -/** @deprecated Use `z.$ZodFormattedError` */ -export type inferFormattedError, U = string> = core.$ZodFormattedError< - core.output, - U ->; - -/** Use `z.$brand` instead */ -export type BRAND = { - [core.$brand]: { [k in T]: true }; -}; -export { $brand, config } from "../core/index.js"; - -/** @deprecated Use `z.config(params)` instead. */ -export function setErrorMap(map: core.$ZodErrorMap): void { - core.config({ - customError: map, - }); -} - -/** @deprecated Use `z.config()` instead. */ -export function getErrorMap(): core.$ZodErrorMap | undefined { - return core.config().customError; -} - -export type { - /** @deprecated Use z.ZodType (without generics) instead. */ - ZodType as ZodTypeAny, - /** @deprecated Use `z.ZodType` */ - ZodType as ZodSchema, - /** @deprecated Use `z.ZodType` */ - ZodType as Schema, -}; - -/** Included for Zod 3 compatibility */ -export type ZodRawShape = core.$ZodShape; - -/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */ -export enum ZodFirstPartyTypeKind {} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/errors.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/errors.ts deleted file mode 100644 index 695a53433..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/errors.ts +++ /dev/null @@ -1,82 +0,0 @@ -import * as core from "../core/index.js"; -import { $ZodError } from "../core/index.js"; -import * as util from "../core/util.js"; - -/** @deprecated Use `z.core.$ZodIssue` from `@zod/core` instead, especially if you are building a library on top of Zod. */ -export type ZodIssue = core.$ZodIssue; - -/** An Error-like class used to store Zod validation issues. */ -export interface ZodError extends $ZodError { - /** @deprecated Use the `z.treeifyError(err)` function instead. */ - format(): core.$ZodFormattedError; - format(mapper: (issue: core.$ZodIssue) => U): core.$ZodFormattedError; - /** @deprecated Use the `z.treeifyError(err)` function instead. */ - flatten(): core.$ZodFlattenedError; - flatten(mapper: (issue: core.$ZodIssue) => U): core.$ZodFlattenedError; - /** @deprecated Push directly to `.issues` instead. */ - addIssue(issue: core.$ZodIssue): void; - /** @deprecated Push directly to `.issues` instead. */ - addIssues(issues: core.$ZodIssue[]): void; - - /** @deprecated Check `err.issues.length === 0` instead. */ - isEmpty: boolean; -} - -const initializer = (inst: ZodError, issues: core.$ZodIssue[]) => { - $ZodError.init(inst, issues); - inst.name = "ZodError"; - Object.defineProperties(inst, { - format: { - value: (mapper: any) => core.formatError(inst, mapper), - // enumerable: false, - }, - flatten: { - value: (mapper: any) => core.flattenError(inst, mapper), - // enumerable: false, - }, - addIssue: { - value: (issue: any) => { - inst.issues.push(issue); - inst.message = JSON.stringify(inst.issues, util.jsonStringifyReplacer, 2); - }, - // enumerable: false, - }, - addIssues: { - value: (issues: any) => { - inst.issues.push(...issues); - inst.message = JSON.stringify(inst.issues, util.jsonStringifyReplacer, 2); - }, - // enumerable: false, - }, - isEmpty: { - get() { - return inst.issues.length === 0; - }, - // enumerable: false, - }, - }); - // Object.defineProperty(inst, "isEmpty", { - // get() { - // return inst.issues.length === 0; - // }, - // }); -}; -export const ZodError: core.$constructor = core.$constructor("ZodError", initializer); -export const ZodRealError: core.$constructor = core.$constructor("ZodError", initializer, { - Parent: Error, -}); - -export type { - /** @deprecated Use `z.core.$ZodFlattenedError` instead. */ - $ZodFlattenedError as ZodFlattenedError, - /** @deprecated Use `z.core.$ZodFormattedError` instead. */ - $ZodFormattedError as ZodFormattedError, - /** @deprecated Use `z.core.$ZodErrorMap` instead. */ - $ZodErrorMap as ZodErrorMap, -} from "../core/index.js"; - -/** @deprecated Use `z.core.$ZodRawIssue` instead. */ -export type IssueData = core.$ZodRawIssue; - -// /** @deprecated Use `z.core.$ZodErrorMapCtx` instead. */ -// export type ErrorMapCtx = core.$ZodErrorMapCtx; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/external.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/external.ts deleted file mode 100644 index 084deaa5b..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/external.ts +++ /dev/null @@ -1,51 +0,0 @@ -export * as core from "../core/index.js"; -export * from "./schemas.js"; -export * from "./checks.js"; -export * from "./errors.js"; -export * from "./parse.js"; -export * from "./compat.js"; - -// zod-specified -import { config } from "../core/index.js"; -import en from "../locales/en.js"; -config(en()); - -export type { infer, output, input } from "../core/index.js"; -export { - globalRegistry, - type GlobalMeta, - registry, - config, - $output, - $input, - $brand, - clone, - regexes, - treeifyError, - prettifyError, - formatError, - flattenError, - TimePrecision, - util, - NEVER, -} from "../core/index.js"; -export { toJSONSchema } from "../core/json-schema-processors.js"; -export { fromJSONSchema } from "./from-json-schema.js"; - -export * as locales from "../locales/index.js"; - -// iso -// must be exported from top-level -// https://github.com/colinhacks/zod/issues/4491 -export { ZodISODateTime, ZodISODate, ZodISOTime, ZodISODuration } from "./iso.js"; -export * as iso from "./iso.js"; - -// coerce -export type { - ZodCoercedString, - ZodCoercedNumber, - ZodCoercedBigInt, - ZodCoercedBoolean, - ZodCoercedDate, -} from "./coerce.js"; -export * as coerce from "./coerce.js"; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/from-json-schema.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/from-json-schema.ts deleted file mode 100644 index b2c806ecf..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/from-json-schema.ts +++ /dev/null @@ -1,643 +0,0 @@ -import type * as JSONSchema from "../core/json-schema.js"; -import { type $ZodRegistry, globalRegistry } from "../core/registries.js"; -import * as _checks from "./checks.js"; -import * as _iso from "./iso.js"; -import * as _schemas from "./schemas.js"; -import type { ZodNumber, ZodString, ZodType } from "./schemas.js"; - -// Local z object to avoid circular dependency with ../index.js -const z = { - ..._schemas, - ..._checks, - iso: _iso, -}; - -type JSONSchemaVersion = "draft-2020-12" | "draft-7" | "draft-4" | "openapi-3.0"; - -interface FromJSONSchemaParams { - defaultTarget?: JSONSchemaVersion; - registry?: $ZodRegistry; -} - -interface ConversionContext { - version: JSONSchemaVersion; - defs: Record; - refs: Map; - processing: Set; - rootSchema: JSONSchema.JSONSchema; - registry: $ZodRegistry; -} - -// Keys that are recognized and handled by the conversion logic -const RECOGNIZED_KEYS = new Set([ - // Schema identification - "$schema", - "$ref", - "$defs", - "definitions", - // Core schema keywords - "$id", - "id", - "$comment", - "$anchor", - "$vocabulary", - "$dynamicRef", - "$dynamicAnchor", - // Type - "type", - "enum", - "const", - // Composition - "anyOf", - "oneOf", - "allOf", - "not", - // Object - "properties", - "required", - "additionalProperties", - "patternProperties", - "propertyNames", - "minProperties", - "maxProperties", - // Array - "items", - "prefixItems", - "additionalItems", - "minItems", - "maxItems", - "uniqueItems", - "contains", - "minContains", - "maxContains", - // String - "minLength", - "maxLength", - "pattern", - "format", - // Number - "minimum", - "maximum", - "exclusiveMinimum", - "exclusiveMaximum", - "multipleOf", - // Already handled metadata - "description", - "default", - // Content - "contentEncoding", - "contentMediaType", - "contentSchema", - // Unsupported (error-throwing) - "unevaluatedItems", - "unevaluatedProperties", - "if", - "then", - "else", - "dependentSchemas", - "dependentRequired", - // OpenAPI - "nullable", - "readOnly", -]); - -function detectVersion(schema: JSONSchema.JSONSchema, defaultTarget?: JSONSchemaVersion): JSONSchemaVersion { - const $schema = schema.$schema; - - if ($schema === "https://json-schema.org/draft/2020-12/schema") { - return "draft-2020-12"; - } - if ($schema === "http://json-schema.org/draft-07/schema#") { - return "draft-7"; - } - if ($schema === "http://json-schema.org/draft-04/schema#") { - return "draft-4"; - } - - // Use defaultTarget if provided, otherwise default to draft-2020-12 - return defaultTarget ?? "draft-2020-12"; -} - -function resolveRef(ref: string, ctx: ConversionContext): JSONSchema.JSONSchema { - if (!ref.startsWith("#")) { - throw new Error("External $ref is not supported, only local refs (#/...) are allowed"); - } - - const path = ref.slice(1).split("/").filter(Boolean); - - // Handle root reference "#" - if (path.length === 0) { - return ctx.rootSchema; - } - - const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions"; - - if (path[0] === defsKey) { - const key = path[1]; - if (!key || !ctx.defs[key]) { - throw new Error(`Reference not found: ${ref}`); - } - return ctx.defs[key]!; - } - - throw new Error(`Reference not found: ${ref}`); -} - -function convertBaseSchema(schema: JSONSchema.JSONSchema, ctx: ConversionContext): ZodType { - // Handle unsupported features - if (schema.not !== undefined) { - // Special case: { not: {} } represents never - if (typeof schema.not === "object" && Object.keys(schema.not).length === 0) { - return z.never(); - } - throw new Error("not is not supported in Zod (except { not: {} } for never)"); - } - if (schema.unevaluatedItems !== undefined) { - throw new Error("unevaluatedItems is not supported"); - } - if (schema.unevaluatedProperties !== undefined) { - throw new Error("unevaluatedProperties is not supported"); - } - if (schema.if !== undefined || schema.then !== undefined || schema.else !== undefined) { - throw new Error("Conditional schemas (if/then/else) are not supported"); - } - if (schema.dependentSchemas !== undefined || schema.dependentRequired !== undefined) { - throw new Error("dependentSchemas and dependentRequired are not supported"); - } - - // Handle $ref - if (schema.$ref) { - const refPath = schema.$ref; - if (ctx.refs.has(refPath)) { - return ctx.refs.get(refPath)!; - } - - if (ctx.processing.has(refPath)) { - // Circular reference - use lazy - return z.lazy(() => { - if (!ctx.refs.has(refPath)) { - throw new Error(`Circular reference not resolved: ${refPath}`); - } - return ctx.refs.get(refPath)!; - }); - } - - ctx.processing.add(refPath); - const resolved = resolveRef(refPath, ctx); - const zodSchema = convertSchema(resolved, ctx); - ctx.refs.set(refPath, zodSchema); - ctx.processing.delete(refPath); - return zodSchema; - } - - // Handle enum - if (schema.enum !== undefined) { - const enumValues = schema.enum; - - // Special case: OpenAPI 3.0 null representation { type: "string", nullable: true, enum: [null] } - if ( - ctx.version === "openapi-3.0" && - schema.nullable === true && - enumValues.length === 1 && - enumValues[0] === null - ) { - return z.null(); - } - - if (enumValues.length === 0) { - return z.never(); - } - if (enumValues.length === 1) { - return z.literal(enumValues[0]!); - } - // Check if all values are strings - if (enumValues.every((v) => typeof v === "string")) { - return z.enum(enumValues as [string, ...string[]]); - } - // Mixed types - use union of literals - const literalSchemas = enumValues.map((v) => z.literal(v)); - if (literalSchemas.length < 2) { - return literalSchemas[0]!; - } - return z.union([literalSchemas[0]!, literalSchemas[1]!, ...literalSchemas.slice(2)] as [ - ZodType, - ZodType, - ...ZodType[], - ]); - } - - // Handle const - if (schema.const !== undefined) { - return z.literal(schema.const); - } - - // Handle type - const type = schema.type; - - if (Array.isArray(type)) { - // Expand type array into anyOf union - const typeSchemas = type.map((t) => { - const typeSchema: JSONSchema.JSONSchema = { ...schema, type: t }; - return convertBaseSchema(typeSchema, ctx); - }); - if (typeSchemas.length === 0) { - return z.never(); - } - if (typeSchemas.length === 1) { - return typeSchemas[0]!; - } - return z.union(typeSchemas as [ZodType, ZodType, ...ZodType[]]); - } - - if (!type) { - // No type specified - empty schema (any) - return z.any(); - } - - let zodSchema: ZodType; - - switch (type) { - case "string": { - let stringSchema: ZodString = z.string(); - - // Apply format using .check() with Zod format functions - if (schema.format) { - const format = schema.format; - // Map common formats to Zod check functions - if (format === "email") { - stringSchema = stringSchema.check(z.email()); - } else if (format === "uri" || format === "uri-reference") { - stringSchema = stringSchema.check(z.url()); - } else if (format === "uuid" || format === "guid") { - stringSchema = stringSchema.check(z.uuid()); - } else if (format === "date-time") { - stringSchema = stringSchema.check(z.iso.datetime()); - } else if (format === "date") { - stringSchema = stringSchema.check(z.iso.date()); - } else if (format === "time") { - stringSchema = stringSchema.check(z.iso.time()); - } else if (format === "duration") { - stringSchema = stringSchema.check(z.iso.duration()); - } else if (format === "ipv4") { - stringSchema = stringSchema.check(z.ipv4()); - } else if (format === "ipv6") { - stringSchema = stringSchema.check(z.ipv6()); - } else if (format === "mac") { - stringSchema = stringSchema.check(z.mac()); - } else if (format === "cidr") { - stringSchema = stringSchema.check(z.cidrv4()); - } else if (format === "cidr-v6") { - stringSchema = stringSchema.check(z.cidrv6()); - } else if (format === "base64") { - stringSchema = stringSchema.check(z.base64()); - } else if (format === "base64url") { - stringSchema = stringSchema.check(z.base64url()); - } else if (format === "e164") { - stringSchema = stringSchema.check(z.e164()); - } else if (format === "jwt") { - stringSchema = stringSchema.check(z.jwt()); - } else if (format === "emoji") { - stringSchema = stringSchema.check(z.emoji()); - } else if (format === "nanoid") { - stringSchema = stringSchema.check(z.nanoid()); - } else if (format === "cuid") { - stringSchema = stringSchema.check(z.cuid()); - } else if (format === "cuid2") { - stringSchema = stringSchema.check(z.cuid2()); - } else if (format === "ulid") { - stringSchema = stringSchema.check(z.ulid()); - } else if (format === "xid") { - stringSchema = stringSchema.check(z.xid()); - } else if (format === "ksuid") { - stringSchema = stringSchema.check(z.ksuid()); - } - // Note: json-string format is not currently supported by Zod - // Custom formats are ignored - keep as plain string - } - - // Apply constraints - if (typeof schema.minLength === "number") { - stringSchema = stringSchema.min(schema.minLength); - } - if (typeof schema.maxLength === "number") { - stringSchema = stringSchema.max(schema.maxLength); - } - if (schema.pattern) { - // JSON Schema patterns are not implicitly anchored (match anywhere in string) - stringSchema = stringSchema.regex(new RegExp(schema.pattern)); - } - - zodSchema = stringSchema; - break; - } - - case "number": - case "integer": { - let numberSchema: ZodNumber = type === "integer" ? z.number().int() : z.number(); - - // Apply constraints - if (typeof schema.minimum === "number") { - numberSchema = numberSchema.min(schema.minimum); - } - if (typeof schema.maximum === "number") { - numberSchema = numberSchema.max(schema.maximum); - } - if (typeof schema.exclusiveMinimum === "number") { - numberSchema = numberSchema.gt(schema.exclusiveMinimum); - } else if (schema.exclusiveMinimum === true && typeof schema.minimum === "number") { - numberSchema = numberSchema.gt(schema.minimum); - } - if (typeof schema.exclusiveMaximum === "number") { - numberSchema = numberSchema.lt(schema.exclusiveMaximum); - } else if (schema.exclusiveMaximum === true && typeof schema.maximum === "number") { - numberSchema = numberSchema.lt(schema.maximum); - } - if (typeof schema.multipleOf === "number") { - numberSchema = numberSchema.multipleOf(schema.multipleOf); - } - - zodSchema = numberSchema; - break; - } - - case "boolean": { - zodSchema = z.boolean(); - break; - } - - case "null": { - zodSchema = z.null(); - break; - } - - case "object": { - const shape: Record = {}; - const properties = schema.properties || {}; - const requiredSet = new Set(schema.required || []); - - // Convert properties - mark optional ones - for (const [key, propSchema] of Object.entries(properties)) { - const propZodSchema = convertSchema(propSchema as JSONSchema.JSONSchema, ctx); - // If not in required array, make it optional - shape[key] = requiredSet.has(key) ? propZodSchema : propZodSchema.optional(); - } - - // Handle propertyNames - if (schema.propertyNames) { - const keySchema = convertSchema(schema.propertyNames, ctx) as ZodString; - const valueSchema = - schema.additionalProperties && typeof schema.additionalProperties === "object" - ? convertSchema(schema.additionalProperties as JSONSchema.JSONSchema, ctx) - : z.any(); - - // Case A: No properties (pure record) - if (Object.keys(shape).length === 0) { - zodSchema = z.record(keySchema, valueSchema); - break; - } - - // Case B: With properties (intersection of object and looseRecord) - const objectSchema = z.object(shape).passthrough(); - const recordSchema = z.looseRecord(keySchema, valueSchema); - zodSchema = z.intersection(objectSchema, recordSchema); - break; - } - - // Handle patternProperties - if (schema.patternProperties) { - // patternProperties: keys matching pattern must satisfy corresponding schema - // Use loose records so non-matching keys pass through - const patternProps = schema.patternProperties; - const patternKeys = Object.keys(patternProps); - const looseRecords: ZodType[] = []; - - for (const pattern of patternKeys) { - const patternValue = convertSchema(patternProps[pattern] as JSONSchema.JSONSchema, ctx); - const keySchema = z.string().regex(new RegExp(pattern)); - looseRecords.push(z.looseRecord(keySchema, patternValue)); - } - - // Build intersection: object schema + all pattern property records - const schemasToIntersect: ZodType[] = []; - if (Object.keys(shape).length > 0) { - // Use passthrough so patternProperties can validate additional keys - schemasToIntersect.push(z.object(shape).passthrough()); - } - schemasToIntersect.push(...looseRecords); - - if (schemasToIntersect.length === 0) { - zodSchema = z.object({}).passthrough(); - } else if (schemasToIntersect.length === 1) { - zodSchema = schemasToIntersect[0]!; - } else { - // Chain intersections: (A & B) & C & D ... - let result = z.intersection(schemasToIntersect[0]!, schemasToIntersect[1]!); - for (let i = 2; i < schemasToIntersect.length; i++) { - result = z.intersection(result, schemasToIntersect[i]!); - } - zodSchema = result; - } - break; - } - - // Handle additionalProperties - // In JSON Schema, additionalProperties defaults to true (allow any extra properties) - // In Zod, objects strip unknown keys by default, so we need to handle this explicitly - const objectSchema = z.object(shape); - if (schema.additionalProperties === false) { - // Strict mode - no extra properties allowed - zodSchema = objectSchema.strict(); - } else if (typeof schema.additionalProperties === "object") { - // Extra properties must match the specified schema - zodSchema = objectSchema.catchall(convertSchema(schema.additionalProperties as JSONSchema.JSONSchema, ctx)); - } else { - // additionalProperties is true or undefined - allow any extra properties (passthrough) - zodSchema = objectSchema.passthrough(); - } - break; - } - - case "array": { - // TODO: uniqueItems is not supported - // TODO: contains/minContains/maxContains are not supported - // Check if this is a tuple (prefixItems or items as array) - const prefixItems = schema.prefixItems; - const items = schema.items; - - if (prefixItems && Array.isArray(prefixItems)) { - // Tuple with prefixItems (draft-2020-12) - const tupleItems = prefixItems.map((item) => convertSchema(item as JSONSchema.JSONSchema, ctx)); - const rest = - items && typeof items === "object" && !Array.isArray(items) - ? convertSchema(items as JSONSchema.JSONSchema, ctx) - : undefined; - if (rest) { - zodSchema = z.tuple(tupleItems as [ZodType, ...ZodType[]]).rest(rest); - } else { - zodSchema = z.tuple(tupleItems as [ZodType, ...ZodType[]]); - } - // Apply minItems/maxItems constraints to tuples - if (typeof schema.minItems === "number") { - zodSchema = (zodSchema as any).check(z.minLength(schema.minItems)); - } - if (typeof schema.maxItems === "number") { - zodSchema = (zodSchema as any).check(z.maxLength(schema.maxItems)); - } - } else if (Array.isArray(items)) { - // Tuple with items array (draft-7) - const tupleItems = items.map((item) => convertSchema(item as JSONSchema.JSONSchema, ctx)); - const rest = - schema.additionalItems && typeof schema.additionalItems === "object" - ? convertSchema(schema.additionalItems as JSONSchema.JSONSchema, ctx) - : undefined; // additionalItems: false means no rest, handled by default tuple behavior - if (rest) { - zodSchema = z.tuple(tupleItems as [ZodType, ...ZodType[]]).rest(rest); - } else { - zodSchema = z.tuple(tupleItems as [ZodType, ...ZodType[]]); - } - // Apply minItems/maxItems constraints to tuples - if (typeof schema.minItems === "number") { - zodSchema = (zodSchema as any).check(z.minLength(schema.minItems)); - } - if (typeof schema.maxItems === "number") { - zodSchema = (zodSchema as any).check(z.maxLength(schema.maxItems)); - } - } else if (items !== undefined) { - // Regular array - const element = convertSchema(items as JSONSchema.JSONSchema, ctx); - let arraySchema = z.array(element); - - // Apply constraints - if (typeof schema.minItems === "number") { - arraySchema = (arraySchema as any).min(schema.minItems); - } - if (typeof schema.maxItems === "number") { - arraySchema = (arraySchema as any).max(schema.maxItems); - } - - zodSchema = arraySchema; - } else { - // No items specified - array of any - zodSchema = z.array(z.any()); - } - break; - } - - default: - throw new Error(`Unsupported type: ${type}`); - } - - // Apply metadata - if (schema.description) { - zodSchema = zodSchema.describe(schema.description); - } - if (schema.default !== undefined) { - zodSchema = (zodSchema as any).default(schema.default); - } - - return zodSchema; -} - -function convertSchema(schema: JSONSchema.JSONSchema | boolean, ctx: ConversionContext): ZodType { - if (typeof schema === "boolean") { - return schema ? z.any() : z.never(); - } - - // Convert base schema first (ignoring composition keywords) - let baseSchema = convertBaseSchema(schema, ctx); - const hasExplicitType = schema.type || schema.enum !== undefined || schema.const !== undefined; - - // Process composition keywords LAST (they can appear together) - // Handle anyOf - wrap base schema with union - if (schema.anyOf && Array.isArray(schema.anyOf)) { - const options = schema.anyOf.map((s) => convertSchema(s, ctx)); - const anyOfUnion = z.union(options as [ZodType, ZodType, ...ZodType[]]); - baseSchema = hasExplicitType ? z.intersection(baseSchema, anyOfUnion) : anyOfUnion; - } - - // Handle oneOf - exclusive union (exactly one must match) - if (schema.oneOf && Array.isArray(schema.oneOf)) { - const options = schema.oneOf.map((s) => convertSchema(s, ctx)); - const oneOfUnion = z.xor(options as [ZodType, ZodType, ...ZodType[]]); - baseSchema = hasExplicitType ? z.intersection(baseSchema, oneOfUnion) : oneOfUnion; - } - - // Handle allOf - wrap base schema with intersection - if (schema.allOf && Array.isArray(schema.allOf)) { - if (schema.allOf.length === 0) { - baseSchema = hasExplicitType ? baseSchema : z.any(); - } else { - let result = hasExplicitType ? baseSchema : convertSchema(schema.allOf[0]!, ctx); - const startIdx = hasExplicitType ? 0 : 1; - for (let i = startIdx; i < schema.allOf.length; i++) { - result = z.intersection(result, convertSchema(schema.allOf[i]!, ctx)); - } - baseSchema = result; - } - } - - // Handle nullable (OpenAPI 3.0) - if (schema.nullable === true && ctx.version === "openapi-3.0") { - baseSchema = z.nullable(baseSchema); - } - - // Handle readOnly - if (schema.readOnly === true) { - baseSchema = z.readonly(baseSchema); - } - - // Collect metadata: core schema keywords and unrecognized keys - const extraMeta: Record = {}; - - // Core schema keywords that should be captured as metadata - const coreMetadataKeys = ["$id", "id", "$comment", "$anchor", "$vocabulary", "$dynamicRef", "$dynamicAnchor"]; - for (const key of coreMetadataKeys) { - if (key in schema) { - extraMeta[key] = schema[key]; - } - } - - // Content keywords - store as metadata - const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"]; - for (const key of contentMetadataKeys) { - if (key in schema) { - extraMeta[key] = schema[key]; - } - } - - // Unrecognized keys (custom metadata) - for (const key of Object.keys(schema)) { - if (!RECOGNIZED_KEYS.has(key)) { - extraMeta[key] = schema[key]; - } - } - - if (Object.keys(extraMeta).length > 0) { - ctx.registry.add(baseSchema, extraMeta); - } - - return baseSchema; -} - -/** - * Converts a JSON Schema to a Zod schema. This function should be considered semi-experimental. It's behavior is liable to change. */ -export function fromJSONSchema(schema: JSONSchema.JSONSchema | boolean, params?: FromJSONSchemaParams): ZodType { - // Handle boolean schemas - if (typeof schema === "boolean") { - return schema ? z.any() : z.never(); - } - - const version = detectVersion(schema, params?.defaultTarget); - const defs = (schema.$defs || schema.definitions || {}) as Record; - - const ctx: ConversionContext = { - version, - defs, - refs: new Map(), - processing: new Set(), - rootSchema: schema, - registry: params?.registry ?? globalRegistry, - }; - - return convertSchema(schema, ctx); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/index.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/index.ts deleted file mode 100644 index f0f7547ff..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import * as z from "./external.js"; - -export { z }; -export * from "./external.js"; -export default z; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/iso.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/iso.ts deleted file mode 100644 index b08696d67..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/iso.ts +++ /dev/null @@ -1,90 +0,0 @@ -import * as core from "../core/index.js"; -import * as schemas from "./schemas.js"; - -////////////////////////////////////////////// -////////////////////////////////////////////// -////////// ////////// -////////// ZodISODateTime ////////// -////////// ////////// -////////////////////////////////////////////// -////////////////////////////////////////////// - -export interface ZodISODateTime extends schemas.ZodStringFormat { - _zod: core.$ZodISODateTimeInternals; -} -export const ZodISODateTime: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodISODateTime", - (inst, def) => { - core.$ZodISODateTime.init(inst, def); - schemas.ZodStringFormat.init(inst, def); - } -); - -export function datetime(params?: string | core.$ZodISODateTimeParams): ZodISODateTime { - return core._isoDateTime(ZodISODateTime, params); -} - -////////////////////////////////////////// -////////////////////////////////////////// -////////// ////////// -////////// ZodISODate ////////// -////////// ////////// -////////////////////////////////////////// -////////////////////////////////////////// - -export interface ZodISODate extends schemas.ZodStringFormat { - _zod: core.$ZodISODateInternals; -} -export const ZodISODate: core.$constructor = /*@__PURE__*/ core.$constructor("ZodISODate", (inst, def) => { - core.$ZodISODate.init(inst, def); - schemas.ZodStringFormat.init(inst, def); -}); - -export function date(params?: string | core.$ZodISODateParams): ZodISODate { - return core._isoDate(ZodISODate, params); -} - -// ZodISOTime - -////////////////////////////////////////// -////////////////////////////////////////// -////////// ////////// -////////// ZodISOTime ////////// -////////// ////////// -////////////////////////////////////////// -////////////////////////////////////////// - -export interface ZodISOTime extends schemas.ZodStringFormat { - _zod: core.$ZodISOTimeInternals; -} -export const ZodISOTime: core.$constructor = /*@__PURE__*/ core.$constructor("ZodISOTime", (inst, def) => { - core.$ZodISOTime.init(inst, def); - schemas.ZodStringFormat.init(inst, def); -}); - -export function time(params?: string | core.$ZodISOTimeParams): ZodISOTime { - return core._isoTime(ZodISOTime, params); -} - -////////////////////////////////////////////// -////////////////////////////////////////////// -////////// ////////// -////////// ZodISODuration ////////// -////////// ////////// -////////////////////////////////////////////// -////////////////////////////////////////////// - -export interface ZodISODuration extends schemas.ZodStringFormat { - _zod: core.$ZodISODurationInternals; -} -export const ZodISODuration: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodISODuration", - (inst, def) => { - core.$ZodISODuration.init(inst, def); - schemas.ZodStringFormat.init(inst, def); - } -); - -export function duration(params?: string | core.$ZodISODurationParams): ZodISODuration { - return core._isoDuration(ZodISODuration, params); -} diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/parse.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/parse.ts deleted file mode 100644 index e9b88c07e..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/parse.ts +++ /dev/null @@ -1,82 +0,0 @@ -import * as core from "../core/index.js"; -import { type ZodError, ZodRealError } from "./errors.js"; - -export type ZodSafeParseResult = ZodSafeParseSuccess | ZodSafeParseError; -export type ZodSafeParseSuccess = { success: true; data: T; error?: never }; -export type ZodSafeParseError = { success: false; data?: never; error: ZodError }; - -export const parse: ( - schema: T, - value: unknown, - _ctx?: core.ParseContext, - _params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass } -) => core.output = /* @__PURE__ */ core._parse(ZodRealError) as any; - -export const parseAsync: ( - schema: T, - value: unknown, - _ctx?: core.ParseContext, - _params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass } -) => Promise> = /* @__PURE__ */ core._parseAsync(ZodRealError) as any; - -export const safeParse: ( - schema: T, - value: unknown, - _ctx?: core.ParseContext - // _params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass } -) => ZodSafeParseResult> = /* @__PURE__ */ core._safeParse(ZodRealError) as any; - -export const safeParseAsync: ( - schema: T, - value: unknown, - _ctx?: core.ParseContext -) => Promise>> = /* @__PURE__ */ core._safeParseAsync(ZodRealError) as any; - -// Codec functions -export const encode: ( - schema: T, - value: core.output, - _ctx?: core.ParseContext -) => core.input = /* @__PURE__ */ core._encode(ZodRealError) as any; - -export const decode: ( - schema: T, - value: core.input, - _ctx?: core.ParseContext -) => core.output = /* @__PURE__ */ core._decode(ZodRealError) as any; - -export const encodeAsync: ( - schema: T, - value: core.output, - _ctx?: core.ParseContext -) => Promise> = /* @__PURE__ */ core._encodeAsync(ZodRealError) as any; - -export const decodeAsync: ( - schema: T, - value: core.input, - _ctx?: core.ParseContext -) => Promise> = /* @__PURE__ */ core._decodeAsync(ZodRealError) as any; - -export const safeEncode: ( - schema: T, - value: core.output, - _ctx?: core.ParseContext -) => ZodSafeParseResult> = /* @__PURE__ */ core._safeEncode(ZodRealError) as any; - -export const safeDecode: ( - schema: T, - value: core.input, - _ctx?: core.ParseContext -) => ZodSafeParseResult> = /* @__PURE__ */ core._safeDecode(ZodRealError) as any; - -export const safeEncodeAsync: ( - schema: T, - value: core.output, - _ctx?: core.ParseContext -) => Promise>> = /* @__PURE__ */ core._safeEncodeAsync(ZodRealError) as any; - -export const safeDecodeAsync: ( - schema: T, - value: core.input, - _ctx?: core.ParseContext -) => Promise>> = /* @__PURE__ */ core._safeDecodeAsync(ZodRealError) as any; diff --git a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/schemas.ts b/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/schemas.ts deleted file mode 100644 index 481d25a17..000000000 --- a/examples/vercel-ai-sdk-pr/node-headroom-compression/node_modules/zod/src/v4/classic/schemas.ts +++ /dev/null @@ -1,2409 +0,0 @@ -import * as core from "../core/index.js"; -import { util } from "../core/index.js"; -import * as processors from "../core/json-schema-processors.js"; -import type { StandardSchemaWithJSONProps } from "../core/standard-schema.js"; -import { createStandardJSONSchemaMethod, createToJSONSchemaMethod } from "../core/to-json-schema.js"; - -import * as checks from "./checks.js"; -import * as iso from "./iso.js"; -import * as parse from "./parse.js"; - -/////////////////////////////////////////// -/////////////////////////////////////////// -//////////// //////////// -//////////// ZodType //////////// -//////////// //////////// -/////////////////////////////////////////// -/////////////////////////////////////////// - -export type ZodStandardSchemaWithJSON = StandardSchemaWithJSONProps, core.output>; -export interface ZodType< - out Output = unknown, - out Input = unknown, - out Internals extends core.$ZodTypeInternals = core.$ZodTypeInternals, -> extends core.$ZodType { - def: Internals["def"]; - type: Internals["def"]["type"]; - - /** @deprecated Use `.def` instead. */ - _def: Internals["def"]; - /** @deprecated Use `z.output` instead. */ - _output: Internals["output"]; - /** @deprecated Use `z.input` instead. */ - _input: Internals["input"]; - - "~standard": ZodStandardSchemaWithJSON; - /** Converts this schema to a JSON Schema representation. */ - toJSONSchema(params?: core.ToJSONSchemaParams): core.ZodStandardJSONSchemaPayload; - - // base methods - check(...checks: (core.CheckFn> | core.$ZodCheck>)[]): this; - with(...checks: (core.CheckFn> | core.$ZodCheck>)[]): this; - clone(def?: Internals["def"], params?: { parent: boolean }): this; - register( - registry: R, - ...meta: this extends R["_schema"] - ? undefined extends R["_meta"] - ? [core.$replace?] - : [core.$replace] - : ["Incompatible schema"] - ): this; - - brand( - value?: T - ): PropertyKey extends T ? this : core.$ZodBranded; - - // parsing - parse(data: unknown, params?: core.ParseContext): core.output; - safeParse(data: unknown, params?: core.ParseContext): parse.ZodSafeParseResult>; - parseAsync(data: unknown, params?: core.ParseContext): Promise>; - safeParseAsync( - data: unknown, - params?: core.ParseContext - ): Promise>>; - spa: ( - data: unknown, - params?: core.ParseContext - ) => Promise>>; - - // encoding/decoding - encode(data: core.output, params?: core.ParseContext): core.input; - decode(data: core.input, params?: core.ParseContext): core.output; - encodeAsync(data: core.output, params?: core.ParseContext): Promise>; - decodeAsync(data: core.input, params?: core.ParseContext): Promise>; - safeEncode( - data: core.output, - params?: core.ParseContext - ): parse.ZodSafeParseResult>; - safeDecode( - data: core.input, - params?: core.ParseContext - ): parse.ZodSafeParseResult>; - safeEncodeAsync( - data: core.output, - params?: core.ParseContext - ): Promise>>; - safeDecodeAsync( - data: core.input, - params?: core.ParseContext - ): Promise>>; - - // refinements - refine) => unknown | Promise>( - check: Ch, - params?: string | core.$ZodCustomParams - ): Ch extends (arg: any) => arg is infer R ? this & ZodType> : this; - superRefine( - refinement: (arg: core.output, ctx: core.$RefinementCtx>) => void | Promise - ): this; - overwrite(fn: (x: core.output) => core.output): this; - - // wrappers - optional(): ZodOptional; - exactOptional(): ZodExactOptional; - nonoptional(params?: string | core.$ZodNonOptionalParams): ZodNonOptional; - nullable(): ZodNullable; - nullish(): ZodOptional>; - default(def: util.NoUndefined>): ZodDefault; - default(def: () => util.NoUndefined>): ZodDefault; - prefault(def: () => core.input): ZodPrefault; - prefault(def: core.input): ZodPrefault; - array(): ZodArray; - or(option: T): ZodUnion<[this, T]>; - and(incoming: T): ZodIntersection; - transform( - transform: (arg: core.output, ctx: core.$RefinementCtx>) => NewOut | Promise - ): ZodPipe, core.output>>; - catch(def: core.output): ZodCatch; - catch(def: (ctx: core.$ZodCatchCtx) => core.output): ZodCatch; - pipe>>( - target: T | core.$ZodType> - ): ZodPipe; - readonly(): ZodReadonly; - - /** Returns a new instance that has been registered in `z.globalRegistry` with the specified description */ - describe(description: string): this; - description?: string; - /** Returns the metadata associated with this instance in `z.globalRegistry` */ - meta(): core.$replace | undefined; - /** Returns a new instance that has been registered in `z.globalRegistry` with the specified metadata */ - meta(data: core.$replace): this; - - // helpers - /** @deprecated Try safe-parsing `undefined` (this is what `isOptional` does internally): - * - * ```ts - * const schema = z.string().optional(); - * const isOptional = schema.safeParse(undefined).success; // true - * ``` - */ - isOptional(): boolean; - /** - * @deprecated Try safe-parsing `null` (this is what `isNullable` does internally): - * - * ```ts - * const schema = z.string().nullable(); - * const isNullable = schema.safeParse(null).success; // true - * ``` - */ - isNullable(): boolean; - apply(fn: (schema: this) => T): T; -} - -export interface _ZodType - extends ZodType {} - -export const ZodType: core.$constructor = /*@__PURE__*/ core.$constructor("ZodType", (inst, def) => { - core.$ZodType.init(inst, def); - Object.assign(inst["~standard"], { - jsonSchema: { - input: createStandardJSONSchemaMethod(inst, "input"), - output: createStandardJSONSchemaMethod(inst, "output"), - }, - }); - inst.toJSONSchema = createToJSONSchemaMethod(inst, {}); - - inst.def = def; - inst.type = def.type; - Object.defineProperty(inst, "_def", { value: def }); - - // base methods - inst.check = (...checks) => { - return inst.clone( - util.mergeDefs(def, { - checks: [ - ...(def.checks ?? []), - ...checks.map((ch) => - typeof ch === "function" ? { _zod: { check: ch, def: { check: "custom" }, onattach: [] } } : ch - ), - ], - }), - { - parent: true, - } - ); - }; - inst.with = inst.check; - inst.clone = (def, params) => core.clone(inst, def, params); - inst.brand = () => inst as any; - inst.register = ((reg: any, meta: any) => { - reg.add(inst, meta); - return inst; - }) as any; - - // parsing - inst.parse = (data, params) => parse.parse(inst, data, params, { callee: inst.parse }); - inst.safeParse = (data, params) => parse.safeParse(inst, data, params); - inst.parseAsync = async (data, params) => parse.parseAsync(inst, data, params, { callee: inst.parseAsync }); - inst.safeParseAsync = async (data, params) => parse.safeParseAsync(inst, data, params); - inst.spa = inst.safeParseAsync; - - // encoding/decoding - inst.encode = (data, params) => parse.encode(inst, data, params); - inst.decode = (data, params) => parse.decode(inst, data, params); - inst.encodeAsync = async (data, params) => parse.encodeAsync(inst, data, params); - inst.decodeAsync = async (data, params) => parse.decodeAsync(inst, data, params); - inst.safeEncode = (data, params) => parse.safeEncode(inst, data, params); - inst.safeDecode = (data, params) => parse.safeDecode(inst, data, params); - inst.safeEncodeAsync = async (data, params) => parse.safeEncodeAsync(inst, data, params); - inst.safeDecodeAsync = async (data, params) => parse.safeDecodeAsync(inst, data, params); - - // refinements - inst.refine = (check, params) => inst.check(refine(check, params)) as never; - inst.superRefine = (refinement) => inst.check(superRefine(refinement)); - inst.overwrite = (fn) => inst.check(checks.overwrite(fn)); - - // wrappers - inst.optional = () => optional(inst); - inst.exactOptional = () => exactOptional(inst); - inst.nullable = () => nullable(inst); - inst.nullish = () => optional(nullable(inst)); - inst.nonoptional = (params) => nonoptional(inst, params); - inst.array = () => array(inst); - inst.or = (arg) => union([inst, arg]); - inst.and = (arg) => intersection(inst, arg); - inst.transform = (tx) => pipe(inst, transform(tx as any)) as never; - inst.default = (def) => _default(inst, def); - inst.prefault = (def) => prefault(inst, def); - // inst.coalesce = (def, params) => coalesce(inst, def, params); - inst.catch = (params) => _catch(inst, params); - inst.pipe = (target) => pipe(inst, target); - inst.readonly = () => readonly(inst); - - // meta - inst.describe = (description) => { - const cl = inst.clone(); - core.globalRegistry.add(cl, { description }); - return cl; - }; - Object.defineProperty(inst, "description", { - get() { - return core.globalRegistry.get(inst)?.description; - }, - configurable: true, - }); - inst.meta = (...args: any) => { - if (args.length === 0) { - return core.globalRegistry.get(inst); - } - const cl = inst.clone(); - core.globalRegistry.add(cl, args[0]); - return cl as any; - }; - - // helpers - inst.isOptional = () => inst.safeParse(undefined).success; - inst.isNullable = () => inst.safeParse(null).success; - inst.apply = (fn) => fn(inst); - return inst; -}); - -// ZodString -export interface _ZodString = core.$ZodStringInternals> - extends _ZodType { - format: string | null; - minLength: number | null; - maxLength: number | null; - - // miscellaneous checks - regex(regex: RegExp, params?: string | core.$ZodCheckRegexParams): this; - includes(value: string, params?: string | core.$ZodCheckIncludesParams): this; - startsWith(value: string, params?: string | core.$ZodCheckStartsWithParams): this; - endsWith(value: string, params?: string | core.$ZodCheckEndsWithParams): this; - min(minLength: number, params?: string | core.$ZodCheckMinLengthParams): this; - max(maxLength: number, params?: string | core.$ZodCheckMaxLengthParams): this; - length(len: number, params?: string | core.$ZodCheckLengthEqualsParams): this; - nonempty(params?: string | core.$ZodCheckMinLengthParams): this; - lowercase(params?: string | core.$ZodCheckLowerCaseParams): this; - uppercase(params?: string | core.$ZodCheckUpperCaseParams): this; - - // transforms - trim(): this; - normalize(form?: "NFC" | "NFD" | "NFKC" | "NFKD" | (string & {})): this; - toLowerCase(): this; - toUpperCase(): this; - slugify(): this; -} - -/** @internal */ -export const _ZodString: core.$constructor<_ZodString> = /*@__PURE__*/ core.$constructor("_ZodString", (inst, def) => { - core.$ZodString.init(inst, def); - ZodType.init(inst, def); - - inst._zod.processJSONSchema = (ctx, json, params) => processors.stringProcessor(inst, ctx, json, params); - - const bag = inst._zod.bag; - inst.format = bag.format ?? null; - inst.minLength = bag.minimum ?? null; - inst.maxLength = bag.maximum ?? null; - - // validations - inst.regex = (...args) => inst.check(checks.regex(...args)); - inst.includes = (...args) => inst.check(checks.includes(...args)); - inst.startsWith = (...args) => inst.check(checks.startsWith(...args)); - inst.endsWith = (...args) => inst.check(checks.endsWith(...args)); - inst.min = (...args) => inst.check(checks.minLength(...args)); - inst.max = (...args) => inst.check(checks.maxLength(...args)); - inst.length = (...args) => inst.check(checks.length(...args)); - inst.nonempty = (...args) => inst.check(checks.minLength(1, ...args)); - inst.lowercase = (params) => inst.check(checks.lowercase(params)); - inst.uppercase = (params) => inst.check(checks.uppercase(params)); - - // transforms - inst.trim = () => inst.check(checks.trim()); - inst.normalize = (...args) => inst.check(checks.normalize(...args)); - inst.toLowerCase = () => inst.check(checks.toLowerCase()); - inst.toUpperCase = () => inst.check(checks.toUpperCase()); - inst.slugify = () => inst.check(checks.slugify()); -}); - -export interface ZodString extends _ZodString> { - // string format checks - - /** @deprecated Use `z.email()` instead. */ - email(params?: string | core.$ZodCheckEmailParams): this; - /** @deprecated Use `z.url()` instead. */ - url(params?: string | core.$ZodCheckURLParams): this; - /** @deprecated Use `z.jwt()` instead. */ - jwt(params?: string | core.$ZodCheckJWTParams): this; - /** @deprecated Use `z.emoji()` instead. */ - emoji(params?: string | core.$ZodCheckEmojiParams): this; - /** @deprecated Use `z.guid()` instead. */ - guid(params?: string | core.$ZodCheckGUIDParams): this; - /** @deprecated Use `z.uuid()` instead. */ - uuid(params?: string | core.$ZodCheckUUIDParams): this; - /** @deprecated Use `z.uuid()` instead. */ - uuidv4(params?: string | core.$ZodCheckUUIDParams): this; - /** @deprecated Use `z.uuid()` instead. */ - uuidv6(params?: string | core.$ZodCheckUUIDParams): this; - /** @deprecated Use `z.uuid()` instead. */ - uuidv7(params?: string | core.$ZodCheckUUIDParams): this; - /** @deprecated Use `z.nanoid()` instead. */ - nanoid(params?: string | core.$ZodCheckNanoIDParams): this; - /** @deprecated Use `z.guid()` instead. */ - guid(params?: string | core.$ZodCheckGUIDParams): this; - /** @deprecated Use `z.cuid()` instead. */ - cuid(params?: string | core.$ZodCheckCUIDParams): this; - /** @deprecated Use `z.cuid2()` instead. */ - cuid2(params?: string | core.$ZodCheckCUID2Params): this; - /** @deprecated Use `z.ulid()` instead. */ - ulid(params?: string | core.$ZodCheckULIDParams): this; - /** @deprecated Use `z.base64()` instead. */ - base64(params?: string | core.$ZodCheckBase64Params): this; - /** @deprecated Use `z.base64url()` instead. */ - base64url(params?: string | core.$ZodCheckBase64URLParams): this; - // /** @deprecated Use `z.jsonString()` instead. */ - // jsonString(params?: string | core.$ZodCheckJSONStringParams): this; - /** @deprecated Use `z.xid()` instead. */ - xid(params?: string | core.$ZodCheckXIDParams): this; - /** @deprecated Use `z.ksuid()` instead. */ - ksuid(params?: string | core.$ZodCheckKSUIDParams): this; - // /** @deprecated Use `z.ipv4()` or `z.ipv6()` instead. */ - // ip(params?: string | (core.$ZodCheckIPv4Params & { version?: "v4" | "v6" })): ZodUnion<[this, this]>; - /** @deprecated Use `z.ipv4()` instead. */ - ipv4(params?: string | core.$ZodCheckIPv4Params): this; - /** @deprecated Use `z.ipv6()` instead. */ - ipv6(params?: string | core.$ZodCheckIPv6Params): this; - /** @deprecated Use `z.cidrv4()` instead. */ - cidrv4(params?: string | core.$ZodCheckCIDRv4Params): this; - /** @deprecated Use `z.cidrv6()` instead. */ - cidrv6(params?: string | core.$ZodCheckCIDRv6Params): this; - /** @deprecated Use `z.e164()` instead. */ - e164(params?: string | core.$ZodCheckE164Params): this; - - // ISO 8601 checks - /** @deprecated Use `z.iso.datetime()` instead. */ - datetime(params?: string | core.$ZodCheckISODateTimeParams): this; - /** @deprecated Use `z.iso.date()` instead. */ - date(params?: string | core.$ZodCheckISODateParams): this; - /** @deprecated Use `z.iso.time()` instead. */ - time( - params?: - | string - // | { - // message?: string | undefined; - // precision?: number | null; - // } - | core.$ZodCheckISOTimeParams - ): this; - /** @deprecated Use `z.iso.duration()` instead. */ - duration(params?: string | core.$ZodCheckISODurationParams): this; -} - -export const ZodString: core.$constructor = /*@__PURE__*/ core.$constructor("ZodString", (inst, def) => { - core.$ZodString.init(inst, def); - _ZodString.init(inst, def); - - inst.email = (params) => inst.check(core._email(ZodEmail, params)); - inst.url = (params) => inst.check(core._url(ZodURL, params)); - inst.jwt = (params) => inst.check(core._jwt(ZodJWT, params)); - inst.emoji = (params) => inst.check(core._emoji(ZodEmoji, params)); - inst.guid = (params) => inst.check(core._guid(ZodGUID, params)); - inst.uuid = (params) => inst.check(core._uuid(ZodUUID, params)); - inst.uuidv4 = (params) => inst.check(core._uuidv4(ZodUUID, params)); - inst.uuidv6 = (params) => inst.check(core._uuidv6(ZodUUID, params)); - inst.uuidv7 = (params) => inst.check(core._uuidv7(ZodUUID, params)); - inst.nanoid = (params) => inst.check(core._nanoid(ZodNanoID, params)); - inst.guid = (params) => inst.check(core._guid(ZodGUID, params)); - inst.cuid = (params) => inst.check(core._cuid(ZodCUID, params)); - inst.cuid2 = (params) => inst.check(core._cuid2(ZodCUID2, params)); - inst.ulid = (params) => inst.check(core._ulid(ZodULID, params)); - inst.base64 = (params) => inst.check(core._base64(ZodBase64, params)); - inst.base64url = (params) => inst.check(core._base64url(ZodBase64URL, params)); - inst.xid = (params) => inst.check(core._xid(ZodXID, params)); - inst.ksuid = (params) => inst.check(core._ksuid(ZodKSUID, params)); - inst.ipv4 = (params) => inst.check(core._ipv4(ZodIPv4, params)); - inst.ipv6 = (params) => inst.check(core._ipv6(ZodIPv6, params)); - inst.cidrv4 = (params) => inst.check(core._cidrv4(ZodCIDRv4, params)); - inst.cidrv6 = (params) => inst.check(core._cidrv6(ZodCIDRv6, params)); - inst.e164 = (params) => inst.check(core._e164(ZodE164, params)); - - // iso - inst.datetime = (params) => inst.check(iso.datetime(params as any)); - inst.date = (params) => inst.check(iso.date(params as any)); - inst.time = (params) => inst.check(iso.time(params as any)); - inst.duration = (params) => inst.check(iso.duration(params as any)); -}); - -export function string(params?: string | core.$ZodStringParams): ZodString; -export function string(params?: string | core.$ZodStringParams): core.$ZodType; -export function string(params?: string | core.$ZodStringParams): ZodString { - return core._string(ZodString, params) as any; -} - -// ZodStringFormat -export interface ZodStringFormat - extends _ZodString> {} -export const ZodStringFormat: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodStringFormat", - (inst, def) => { - core.$ZodStringFormat.init(inst, def); - _ZodString.init(inst, def); - } -); - -// ZodEmail -export interface ZodEmail extends ZodStringFormat<"email"> { - _zod: core.$ZodEmailInternals; -} -export const ZodEmail: core.$constructor = /*@__PURE__*/ core.$constructor("ZodEmail", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodEmail.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function email(params?: string | core.$ZodEmailParams): ZodEmail { - return core._email(ZodEmail, params); -} - -// ZodGUID -export interface ZodGUID extends ZodStringFormat<"guid"> { - _zod: core.$ZodGUIDInternals; -} -export const ZodGUID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodGUID", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodGUID.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function guid(params?: string | core.$ZodGUIDParams): ZodGUID { - return core._guid(ZodGUID, params); -} - -// ZodUUID -export interface ZodUUID extends ZodStringFormat<"uuid"> { - _zod: core.$ZodUUIDInternals; -} -export const ZodUUID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodUUID", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodUUID.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function uuid(params?: string | core.$ZodUUIDParams): ZodUUID { - return core._uuid(ZodUUID, params); -} - -export function uuidv4(params?: string | core.$ZodUUIDv4Params): ZodUUID { - return core._uuidv4(ZodUUID, params); -} - -// ZodUUIDv6 - -export function uuidv6(params?: string | core.$ZodUUIDv6Params): ZodUUID { - return core._uuidv6(ZodUUID, params); -} - -// ZodUUIDv7 - -export function uuidv7(params?: string | core.$ZodUUIDv7Params): ZodUUID { - return core._uuidv7(ZodUUID, params); -} - -// ZodURL -export interface ZodURL extends ZodStringFormat<"url"> { - _zod: core.$ZodURLInternals; -} -export const ZodURL: core.$constructor = /*@__PURE__*/ core.$constructor("ZodURL", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodURL.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function url(params?: string | core.$ZodURLParams): ZodURL { - return core._url(ZodURL, params); -} - -export function httpUrl(params?: string | Omit): ZodURL { - return core._url(ZodURL, { - protocol: /^https?$/, - hostname: core.regexes.domain, - ...util.normalizeParams(params), - }); -} - -// ZodEmoji -export interface ZodEmoji extends ZodStringFormat<"emoji"> { - _zod: core.$ZodEmojiInternals; -} -export const ZodEmoji: core.$constructor = /*@__PURE__*/ core.$constructor("ZodEmoji", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodEmoji.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function emoji(params?: string | core.$ZodEmojiParams): ZodEmoji { - return core._emoji(ZodEmoji, params); -} - -// ZodNanoID -export interface ZodNanoID extends ZodStringFormat<"nanoid"> { - _zod: core.$ZodNanoIDInternals; -} -export const ZodNanoID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodNanoID", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodNanoID.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function nanoid(params?: string | core.$ZodNanoIDParams): ZodNanoID { - return core._nanoid(ZodNanoID, params); -} - -// ZodCUID -export interface ZodCUID extends ZodStringFormat<"cuid"> { - _zod: core.$ZodCUIDInternals; -} -export const ZodCUID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodCUID", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodCUID.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function cuid(params?: string | core.$ZodCUIDParams): ZodCUID { - return core._cuid(ZodCUID, params); -} - -// ZodCUID2 -export interface ZodCUID2 extends ZodStringFormat<"cuid2"> { - _zod: core.$ZodCUID2Internals; -} -export const ZodCUID2: core.$constructor = /*@__PURE__*/ core.$constructor("ZodCUID2", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodCUID2.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function cuid2(params?: string | core.$ZodCUID2Params): ZodCUID2 { - return core._cuid2(ZodCUID2, params); -} - -// ZodULID -export interface ZodULID extends ZodStringFormat<"ulid"> { - _zod: core.$ZodULIDInternals; -} -export const ZodULID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodULID", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodULID.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function ulid(params?: string | core.$ZodULIDParams): ZodULID { - return core._ulid(ZodULID, params); -} - -// ZodXID -export interface ZodXID extends ZodStringFormat<"xid"> { - _zod: core.$ZodXIDInternals; -} -export const ZodXID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodXID", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodXID.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function xid(params?: string | core.$ZodXIDParams): ZodXID { - return core._xid(ZodXID, params); -} - -// ZodKSUID -export interface ZodKSUID extends ZodStringFormat<"ksuid"> { - _zod: core.$ZodKSUIDInternals; -} -export const ZodKSUID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodKSUID", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodKSUID.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function ksuid(params?: string | core.$ZodKSUIDParams): ZodKSUID { - return core._ksuid(ZodKSUID, params); -} - -// ZodIP -// export interface ZodIP extends ZodStringFormat<"ip"> { -// _zod: core.$ZodIPInternals; -// } -// export const ZodIP: core.$constructor = /*@__PURE__*/ core.$constructor("ZodIP", (inst, def) => { -// // ZodStringFormat.init(inst, def); -// core.$ZodIP.init(inst, def); -// ZodStringFormat.init(inst, def); -// }); - -// export function ip(params?: string | core.$ZodIPParams): ZodIP { -// return core._ip(ZodIP, params); -// } - -// ZodIPv4 -export interface ZodIPv4 extends ZodStringFormat<"ipv4"> { - _zod: core.$ZodIPv4Internals; -} -export const ZodIPv4: core.$constructor = /*@__PURE__*/ core.$constructor("ZodIPv4", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodIPv4.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function ipv4(params?: string | core.$ZodIPv4Params): ZodIPv4 { - return core._ipv4(ZodIPv4, params); -} - -// ZodMAC -export interface ZodMAC extends ZodStringFormat<"mac"> { - _zod: core.$ZodMACInternals; -} -export const ZodMAC: core.$constructor = /*@__PURE__*/ core.$constructor("ZodMAC", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodMAC.init(inst, def); - ZodStringFormat.init(inst, def); -}); -export function mac(params?: string | core.$ZodMACParams): ZodMAC { - return core._mac(ZodMAC, params); -} - -// ZodIPv6 -export interface ZodIPv6 extends ZodStringFormat<"ipv6"> { - _zod: core.$ZodIPv6Internals; -} -export const ZodIPv6: core.$constructor = /*@__PURE__*/ core.$constructor("ZodIPv6", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodIPv6.init(inst, def); - ZodStringFormat.init(inst, def); -}); -export function ipv6(params?: string | core.$ZodIPv6Params): ZodIPv6 { - return core._ipv6(ZodIPv6, params); -} - -// ZodCIDRv4 -export interface ZodCIDRv4 extends ZodStringFormat<"cidrv4"> { - _zod: core.$ZodCIDRv4Internals; -} -export const ZodCIDRv4: core.$constructor = /*@__PURE__*/ core.$constructor("ZodCIDRv4", (inst, def) => { - core.$ZodCIDRv4.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function cidrv4(params?: string | core.$ZodCIDRv4Params): ZodCIDRv4 { - return core._cidrv4(ZodCIDRv4, params); -} - -// ZodCIDRv6 -export interface ZodCIDRv6 extends ZodStringFormat<"cidrv6"> { - _zod: core.$ZodCIDRv6Internals; -} -export const ZodCIDRv6: core.$constructor = /*@__PURE__*/ core.$constructor("ZodCIDRv6", (inst, def) => { - core.$ZodCIDRv6.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function cidrv6(params?: string | core.$ZodCIDRv6Params): ZodCIDRv6 { - return core._cidrv6(ZodCIDRv6, params); -} - -// ZodBase64 -export interface ZodBase64 extends ZodStringFormat<"base64"> { - _zod: core.$ZodBase64Internals; -} -export const ZodBase64: core.$constructor = /*@__PURE__*/ core.$constructor("ZodBase64", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodBase64.init(inst, def); - ZodStringFormat.init(inst, def); -}); -export function base64(params?: string | core.$ZodBase64Params): ZodBase64 { - return core._base64(ZodBase64, params); -} - -// ZodBase64URL -export interface ZodBase64URL extends ZodStringFormat<"base64url"> { - _zod: core.$ZodBase64URLInternals; -} -export const ZodBase64URL: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodBase64URL", - (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodBase64URL.init(inst, def); - ZodStringFormat.init(inst, def); - } -); -export function base64url(params?: string | core.$ZodBase64URLParams): ZodBase64URL { - return core._base64url(ZodBase64URL, params); -} - -// ZodE164 -export interface ZodE164 extends ZodStringFormat<"e164"> { - _zod: core.$ZodE164Internals; -} -export const ZodE164: core.$constructor = /*@__PURE__*/ core.$constructor("ZodE164", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodE164.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function e164(params?: string | core.$ZodE164Params): ZodE164 { - return core._e164(ZodE164, params); -} - -// ZodJWT -export interface ZodJWT extends ZodStringFormat<"jwt"> { - _zod: core.$ZodJWTInternals; -} -export const ZodJWT: core.$constructor = /*@__PURE__*/ core.$constructor("ZodJWT", (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodJWT.init(inst, def); - ZodStringFormat.init(inst, def); -}); - -export function jwt(params?: string | core.$ZodJWTParams): ZodJWT { - return core._jwt(ZodJWT, params); -} - -// ZodCustomStringFormat -export interface ZodCustomStringFormat - extends ZodStringFormat, - core.$ZodCustomStringFormat { - _zod: core.$ZodCustomStringFormatInternals; - "~standard": ZodStandardSchemaWithJSON; -} -export const ZodCustomStringFormat: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodCustomStringFormat", - (inst, def) => { - // ZodStringFormat.init(inst, def); - core.$ZodCustomStringFormat.init(inst, def); - ZodStringFormat.init(inst, def); - } -); -export function stringFormat( - format: Format, - fnOrRegex: ((arg: string) => util.MaybeAsync) | RegExp, - _params: string | core.$ZodStringFormatParams = {} -): ZodCustomStringFormat { - return core._stringFormat(ZodCustomStringFormat, format, fnOrRegex, _params) as any; -} - -export function hostname(_params?: string | core.$ZodStringFormatParams): ZodCustomStringFormat<"hostname"> { - return core._stringFormat(ZodCustomStringFormat, "hostname", core.regexes.hostname, _params) as any; -} - -export function hex(_params?: string | core.$ZodStringFormatParams): ZodCustomStringFormat<"hex"> { - return core._stringFormat(ZodCustomStringFormat, "hex", core.regexes.hex, _params) as any; -} - -export function hash( - alg: Alg, - params?: { - enc?: Enc; - } & core.$ZodStringFormatParams -): ZodCustomStringFormat<`${Alg}_${Enc}`> { - const enc = params?.enc ?? "hex"; - const format = `${alg}_${enc}` as const; - const regex = core.regexes[format as keyof typeof core.regexes] as RegExp; - if (!regex) throw new Error(`Unrecognized hash format: ${format}`); - return core._stringFormat(ZodCustomStringFormat, format, regex, params) as any; -} - -// ZodNumber -export interface _ZodNumber - extends _ZodType { - gt(value: number, params?: string | core.$ZodCheckGreaterThanParams): this; - /** Identical to .min() */ - gte(value: number, params?: string | core.$ZodCheckGreaterThanParams): this; - min(value: number, params?: string | core.$ZodCheckGreaterThanParams): this; - lt(value: number, params?: string | core.$ZodCheckLessThanParams): this; - /** Identical to .max() */ - lte(value: number, params?: string | core.$ZodCheckLessThanParams): this; - max(value: number, params?: string | core.$ZodCheckLessThanParams): this; - /** Consider `z.int()` instead. This API is considered *legacy*; it will never be removed but a better alternative exists. */ - int(params?: string | core.$ZodCheckNumberFormatParams): this; - /** @deprecated This is now identical to `.int()`. Only numbers in the safe integer range are accepted. */ - safe(params?: string | core.$ZodCheckNumberFormatParams): this; - positive(params?: string | core.$ZodCheckGreaterThanParams): this; - nonnegative(params?: string | core.$ZodCheckGreaterThanParams): this; - negative(params?: string | core.$ZodCheckLessThanParams): this; - nonpositive(params?: string | core.$ZodCheckLessThanParams): this; - multipleOf(value: number, params?: string | core.$ZodCheckMultipleOfParams): this; - /** @deprecated Use `.multipleOf()` instead. */ - step(value: number, params?: string | core.$ZodCheckMultipleOfParams): this; - - /** @deprecated In v4 and later, z.number() does not allow infinite values by default. This is a no-op. */ - finite(params?: unknown): this; - - minValue: number | null; - maxValue: number | null; - /** @deprecated Check the `format` property instead. */ - isInt: boolean; - /** @deprecated Number schemas no longer accept infinite values, so this always returns `true`. */ - isFinite: boolean; - format: string | null; -} - -export interface ZodNumber extends _ZodNumber> {} - -export const ZodNumber: core.$constructor = /*@__PURE__*/ core.$constructor("ZodNumber", (inst, def) => { - core.$ZodNumber.init(inst, def); - - ZodType.init(inst, def); - - inst._zod.processJSONSchema = (ctx, json, params) => processors.numberProcessor(inst, ctx, json, params); - - inst.gt = (value, params) => inst.check(checks.gt(value, params)); - inst.gte = (value, params) => inst.check(checks.gte(value, params)); - inst.min = (value, params) => inst.check(checks.gte(value, params)); - inst.lt = (value, params) => inst.check(checks.lt(value, params)); - inst.lte = (value, params) => inst.check(checks.lte(value, params)); - inst.max = (value, params) => inst.check(checks.lte(value, params)); - inst.int = (params) => inst.check(int(params)); - inst.safe = (params) => inst.check(int(params)); - inst.positive = (params) => inst.check(checks.gt(0, params)); - inst.nonnegative = (params) => inst.check(checks.gte(0, params)); - inst.negative = (params) => inst.check(checks.lt(0, params)); - inst.nonpositive = (params) => inst.check(checks.lte(0, params)); - inst.multipleOf = (value, params) => inst.check(checks.multipleOf(value, params)); - inst.step = (value, params) => inst.check(checks.multipleOf(value, params)); - - // inst.finite = (params) => inst.check(core.finite(params)); - inst.finite = () => inst; - - const bag = inst._zod.bag; - inst.minValue = - Math.max(bag.minimum ?? Number.NEGATIVE_INFINITY, bag.exclusiveMinimum ?? Number.NEGATIVE_INFINITY) ?? null; - inst.maxValue = - Math.min(bag.maximum ?? Number.POSITIVE_INFINITY, bag.exclusiveMaximum ?? Number.POSITIVE_INFINITY) ?? null; - inst.isInt = (bag.format ?? "").includes("int") || Number.isSafeInteger(bag.multipleOf ?? 0.5); - inst.isFinite = true; - inst.format = bag.format ?? null; -}); - -export function number(params?: string | core.$ZodNumberParams): ZodNumber { - return core._number(ZodNumber, params) as any; -} - -// ZodNumberFormat -export interface ZodNumberFormat extends ZodNumber { - _zod: core.$ZodNumberFormatInternals; -} -export const ZodNumberFormat: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodNumberFormat", - (inst, def) => { - core.$ZodNumberFormat.init(inst, def); - ZodNumber.init(inst, def); - } -); - -// int -export interface ZodInt extends ZodNumberFormat {} -export function int(params?: string | core.$ZodCheckNumberFormatParams): ZodInt { - return core._int(ZodNumberFormat, params); -} - -// float32 -export interface ZodFloat32 extends ZodNumberFormat {} -export function float32(params?: string | core.$ZodCheckNumberFormatParams): ZodFloat32 { - return core._float32(ZodNumberFormat, params); -} - -// float64 -export interface ZodFloat64 extends ZodNumberFormat {} -export function float64(params?: string | core.$ZodCheckNumberFormatParams): ZodFloat64 { - return core._float64(ZodNumberFormat, params); -} - -// int32 -export interface ZodInt32 extends ZodNumberFormat {} -export function int32(params?: string | core.$ZodCheckNumberFormatParams): ZodInt32 { - return core._int32(ZodNumberFormat, params); -} - -// uint32 -export interface ZodUInt32 extends ZodNumberFormat {} -export function uint32(params?: string | core.$ZodCheckNumberFormatParams): ZodUInt32 { - return core._uint32(ZodNumberFormat, params); -} - -// boolean -export interface _ZodBoolean extends _ZodType {} -export interface ZodBoolean extends _ZodBoolean> {} -export const ZodBoolean: core.$constructor = /*@__PURE__*/ core.$constructor("ZodBoolean", (inst, def) => { - core.$ZodBoolean.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.booleanProcessor(inst, ctx, json, params); -}); - -export function boolean(params?: string | core.$ZodBooleanParams): ZodBoolean { - return core._boolean(ZodBoolean, params) as any; -} - -// bigint -export interface _ZodBigInt extends _ZodType { - gte(value: bigint, params?: string | core.$ZodCheckGreaterThanParams): this; - /** Alias of `.gte()` */ - min(value: bigint, params?: string | core.$ZodCheckGreaterThanParams): this; - gt(value: bigint, params?: string | core.$ZodCheckGreaterThanParams): this; - /** Alias of `.lte()` */ - lte(value: bigint, params?: string | core.$ZodCheckLessThanParams): this; - max(value: bigint, params?: string | core.$ZodCheckLessThanParams): this; - lt(value: bigint, params?: string | core.$ZodCheckLessThanParams): this; - positive(params?: string | core.$ZodCheckGreaterThanParams): this; - negative(params?: string | core.$ZodCheckLessThanParams): this; - nonpositive(params?: string | core.$ZodCheckLessThanParams): this; - nonnegative(params?: string | core.$ZodCheckGreaterThanParams): this; - multipleOf(value: bigint, params?: string | core.$ZodCheckMultipleOfParams): this; - - minValue: bigint | null; - maxValue: bigint | null; - format: string | null; -} - -export interface ZodBigInt extends _ZodBigInt> {} -export const ZodBigInt: core.$constructor = /*@__PURE__*/ core.$constructor("ZodBigInt", (inst, def) => { - core.$ZodBigInt.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.bigintProcessor(inst, ctx, json, params); - - inst.gte = (value, params) => inst.check(checks.gte(value, params)); - inst.min = (value, params) => inst.check(checks.gte(value, params)); - inst.gt = (value, params) => inst.check(checks.gt(value, params)); - inst.gte = (value, params) => inst.check(checks.gte(value, params)); - inst.min = (value, params) => inst.check(checks.gte(value, params)); - inst.lt = (value, params) => inst.check(checks.lt(value, params)); - inst.lte = (value, params) => inst.check(checks.lte(value, params)); - inst.max = (value, params) => inst.check(checks.lte(value, params)); - inst.positive = (params) => inst.check(checks.gt(BigInt(0), params)); - inst.negative = (params) => inst.check(checks.lt(BigInt(0), params)); - inst.nonpositive = (params) => inst.check(checks.lte(BigInt(0), params)); - inst.nonnegative = (params) => inst.check(checks.gte(BigInt(0), params)); - inst.multipleOf = (value, params) => inst.check(checks.multipleOf(value, params)); - - const bag = inst._zod.bag; - inst.minValue = bag.minimum ?? null; - inst.maxValue = bag.maximum ?? null; - inst.format = bag.format ?? null; -}); - -export function bigint(params?: string | core.$ZodBigIntParams): ZodBigInt { - return core._bigint(ZodBigInt, params) as any; -} -// bigint formats - -// ZodBigIntFormat -export interface ZodBigIntFormat extends ZodBigInt { - _zod: core.$ZodBigIntFormatInternals; -} -export const ZodBigIntFormat: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodBigIntFormat", - (inst, def) => { - core.$ZodBigIntFormat.init(inst, def); - ZodBigInt.init(inst, def); - } -); - -// int64 -export function int64(params?: string | core.$ZodBigIntFormatParams): ZodBigIntFormat { - return core._int64(ZodBigIntFormat, params); -} - -// uint64 -export function uint64(params?: string | core.$ZodBigIntFormatParams): ZodBigIntFormat { - return core._uint64(ZodBigIntFormat, params); -} - -// symbol -export interface ZodSymbol extends _ZodType {} -export const ZodSymbol: core.$constructor = /*@__PURE__*/ core.$constructor("ZodSymbol", (inst, def) => { - core.$ZodSymbol.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.symbolProcessor(inst, ctx, json, params); -}); - -export function symbol(params?: string | core.$ZodSymbolParams): ZodSymbol { - return core._symbol(ZodSymbol, params); -} - -// ZodUndefined -export interface ZodUndefined extends _ZodType {} -export const ZodUndefined: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodUndefined", - (inst, def) => { - core.$ZodUndefined.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.undefinedProcessor(inst, ctx, json, params); - } -); - -function _undefined(params?: string | core.$ZodUndefinedParams): ZodUndefined { - return core._undefined(ZodUndefined, params); -} -export { _undefined as undefined }; - -// ZodNull -export interface ZodNull extends _ZodType {} -export const ZodNull: core.$constructor = /*@__PURE__*/ core.$constructor("ZodNull", (inst, def) => { - core.$ZodNull.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.nullProcessor(inst, ctx, json, params); -}); - -function _null(params?: string | core.$ZodNullParams): ZodNull { - return core._null(ZodNull, params); -} -export { _null as null }; - -// ZodAny -export interface ZodAny extends _ZodType {} -export const ZodAny: core.$constructor = /*@__PURE__*/ core.$constructor("ZodAny", (inst, def) => { - core.$ZodAny.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.anyProcessor(inst, ctx, json, params); -}); - -export function any(): ZodAny { - return core._any(ZodAny); -} - -// ZodUnknown -export interface ZodUnknown extends _ZodType {} -export const ZodUnknown: core.$constructor = /*@__PURE__*/ core.$constructor("ZodUnknown", (inst, def) => { - core.$ZodUnknown.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.unknownProcessor(inst, ctx, json, params); -}); - -export function unknown(): ZodUnknown { - return core._unknown(ZodUnknown); -} - -// ZodNever -export interface ZodNever extends _ZodType {} -export const ZodNever: core.$constructor = /*@__PURE__*/ core.$constructor("ZodNever", (inst, def) => { - core.$ZodNever.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.neverProcessor(inst, ctx, json, params); -}); - -export function never(params?: string | core.$ZodNeverParams): ZodNever { - return core._never(ZodNever, params); -} - -// ZodVoid -export interface ZodVoid extends _ZodType {} -export const ZodVoid: core.$constructor = /*@__PURE__*/ core.$constructor("ZodVoid", (inst, def) => { - core.$ZodVoid.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.voidProcessor(inst, ctx, json, params); -}); - -function _void(params?: string | core.$ZodVoidParams): ZodVoid { - return core._void(ZodVoid, params); -} -export { _void as void }; - -// ZodDate -export interface _ZodDate extends _ZodType { - min(value: number | Date, params?: string | core.$ZodCheckGreaterThanParams): this; - max(value: number | Date, params?: string | core.$ZodCheckLessThanParams): this; - - /** @deprecated Not recommended. */ - minDate: Date | null; - /** @deprecated Not recommended. */ - maxDate: Date | null; -} - -export interface ZodDate extends _ZodDate> {} -export const ZodDate: core.$constructor = /*@__PURE__*/ core.$constructor("ZodDate", (inst, def) => { - core.$ZodDate.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.dateProcessor(inst, ctx, json, params); - - inst.min = (value, params) => inst.check(checks.gte(value, params)); - inst.max = (value, params) => inst.check(checks.lte(value, params)); - - const c = inst._zod.bag; - inst.minDate = c.minimum ? new Date(c.minimum) : null; - inst.maxDate = c.maximum ? new Date(c.maximum) : null; -}); - -export function date(params?: string | core.$ZodDateParams): ZodDate { - return core._date(ZodDate, params); -} - -// ZodArray -export interface ZodArray - extends _ZodType>, - core.$ZodArray { - element: T; - min(minLength: number, params?: string | core.$ZodCheckMinLengthParams): this; - nonempty(params?: string | core.$ZodCheckMinLengthParams): this; - max(maxLength: number, params?: string | core.$ZodCheckMaxLengthParams): this; - length(len: number, params?: string | core.$ZodCheckLengthEqualsParams): this; - - unwrap(): T; - "~standard": ZodStandardSchemaWithJSON; -} -export const ZodArray: core.$constructor = /*@__PURE__*/ core.$constructor("ZodArray", (inst, def) => { - core.$ZodArray.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.arrayProcessor(inst, ctx, json, params); - - inst.element = def.element as any; - inst.min = (minLength, params) => inst.check(checks.minLength(minLength, params)); - inst.nonempty = (params) => inst.check(checks.minLength(1, params)); - inst.max = (maxLength, params) => inst.check(checks.maxLength(maxLength, params)); - inst.length = (len, params) => inst.check(checks.length(len, params)); - - inst.unwrap = () => inst.element; -}); - -export function array(element: T, params?: string | core.$ZodArrayParams): ZodArray { - return core._array(ZodArray, element as any, params) as any; -} - -// .keyof -export function keyof(schema: T): ZodEnum> { - const shape = schema._zod.def.shape; - return _enum(Object.keys(shape)) as any; -} - -// ZodObject - -export type SafeExtendShape = { - [K in keyof Ext]: K extends keyof Base - ? core.output extends core.output - ? core.input extends core.input - ? Ext[K] - : never - : never - : Ext[K]; -}; - -export interface ZodObject< - /** @ts-ignore Cast variance */ - out Shape extends core.$ZodShape = core.$ZodLooseShape, - out Config extends core.$ZodObjectConfig = core.$strip, -> extends _ZodType>, - core.$ZodObject { - "~standard": ZodStandardSchemaWithJSON; - shape: Shape; - - keyof(): ZodEnum>; - /** Define a schema to validate all unrecognized keys. This overrides the existing strict/loose behavior. */ - catchall(schema: T): ZodObject>; - - /** @deprecated Use `z.looseObject()` or `.loose()` instead. */ - passthrough(): ZodObject; - /** Consider `z.looseObject(A.shape)` instead */ - loose(): ZodObject; - - /** Consider `z.strictObject(A.shape)` instead */ - strict(): ZodObject; - - /** This is the default behavior. This method call is likely unnecessary. */ - strip(): ZodObject; - - extend(shape: U): ZodObject, Config>; - - safeExtend( - shape: SafeExtendShape & Partial> - ): ZodObject, Config>; - - /** - * @deprecated Use [`A.extend(B.shape)`](https://zod.dev/api?id=extend) instead. - */ - merge(other: U): ZodObject, U["_zod"]["config"]>; - - pick>( - mask: M & Record, never> - ): ZodObject>>, Config>; - - omit>( - mask: M & Record, never> - ): ZodObject>>, Config>; - - partial(): ZodObject< - { - [k in keyof Shape]: ZodOptional; - }, - Config - >; - partial>( - mask: M & Record, never> - ): ZodObject< - { - [k in keyof Shape]: k extends keyof M - ? // Shape[k] extends OptionalInSchema - // ? Shape[k] - // : - ZodOptional - : Shape[k]; - }, - Config - >; - - // required - required(): ZodObject< - { - [k in keyof Shape]: ZodNonOptional; - }, - Config - >; - required>( - mask: M & Record, never> - ): ZodObject< - { - [k in keyof Shape]: k extends keyof M ? ZodNonOptional : Shape[k]; - }, - Config - >; -} - -export const ZodObject: core.$constructor = /*@__PURE__*/ core.$constructor("ZodObject", (inst, def) => { - core.$ZodObjectJIT.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.objectProcessor(inst, ctx, json, params); - - util.defineLazy(inst, "shape", () => { - return def.shape; - }); - - inst.keyof = () => _enum(Object.keys(inst._zod.def.shape)) as any; - inst.catchall = (catchall) => inst.clone({ ...inst._zod.def, catchall: catchall as any as core.$ZodType }) as any; - inst.passthrough = () => inst.clone({ ...inst._zod.def, catchall: unknown() }); - inst.loose = () => inst.clone({ ...inst._zod.def, catchall: unknown() }); - inst.strict = () => inst.clone({ ...inst._zod.def, catchall: never() }); - inst.strip = () => inst.clone({ ...inst._zod.def, catchall: undefined }); - - inst.extend = (incoming: any) => { - return util.extend(inst, incoming); - }; - inst.safeExtend = (incoming: any) => { - return util.safeExtend(inst, incoming); - }; - inst.merge = (other) => util.merge(inst, other); - inst.pick = (mask) => util.pick(inst, mask); - inst.omit = (mask) => util.omit(inst, mask); - inst.partial = (...args: any[]) => util.partial(ZodOptional, inst, args[0] as object); - inst.required = (...args: any[]) => util.required(ZodNonOptional, inst, args[0] as object); -}); - -export function object>>( - shape?: T, - params?: string | core.$ZodObjectParams -): ZodObject, core.$strip> { - const def: core.$ZodObjectDef = { - type: "object", - shape: shape ?? {}, - ...util.normalizeParams(params), - }; - return new ZodObject(def) as any; -} - -// strictObject - -export function strictObject( - shape: T, - params?: string | core.$ZodObjectParams -): ZodObject { - return new ZodObject({ - type: "object", - shape, - catchall: never(), - ...util.normalizeParams(params), - }) as any; -} - -// looseObject - -export function looseObject( - shape: T, - params?: string | core.$ZodObjectParams -): ZodObject { - return new ZodObject({ - type: "object", - shape, - catchall: unknown(), - ...util.normalizeParams(params), - }) as any; -} - -// ZodUnion -export interface ZodUnion - extends _ZodType>, - core.$ZodUnion { - "~standard": ZodStandardSchemaWithJSON; - options: T; -} -export const ZodUnion: core.$constructor = /*@__PURE__*/ core.$constructor("ZodUnion", (inst, def) => { - core.$ZodUnion.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.unionProcessor(inst, ctx, json, params); - inst.options = def.options; -}); - -export function union( - options: T, - params?: string | core.$ZodUnionParams -): ZodUnion { - return new ZodUnion({ - type: "union", - options: options as any as core.$ZodType[], - ...util.normalizeParams(params), - }) as any; -} - -// ZodXor -export interface ZodXor - extends _ZodType>, - core.$ZodXor { - "~standard": ZodStandardSchemaWithJSON; - options: T; -} -export const ZodXor: core.$constructor = /*@__PURE__*/ core.$constructor("ZodXor", (inst, def) => { - ZodUnion.init(inst, def); - core.$ZodXor.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.unionProcessor(inst, ctx, json, params); - inst.options = def.options; -}); - -/** Creates an exclusive union (XOR) where exactly one option must match. - * Unlike regular unions that succeed when any option matches, xor fails if - * zero or more than one option matches the input. */ -export function xor( - options: T, - params?: string | core.$ZodXorParams -): ZodXor { - return new ZodXor({ - type: "union", - options: options as any as core.$ZodType[], - inclusive: false, - ...util.normalizeParams(params), - }) as any; -} - -// ZodDiscriminatedUnion -export interface ZodDiscriminatedUnion< - Options extends readonly core.SomeType[] = readonly core.$ZodType[], - Disc extends string = string, -> extends ZodUnion, - core.$ZodDiscriminatedUnion { - "~standard": ZodStandardSchemaWithJSON; - _zod: core.$ZodDiscriminatedUnionInternals; - def: core.$ZodDiscriminatedUnionDef; -} -export const ZodDiscriminatedUnion: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodDiscriminatedUnion", - (inst, def) => { - ZodUnion.init(inst, def); - core.$ZodDiscriminatedUnion.init(inst, def); - } -); - -export function discriminatedUnion< - Types extends readonly [core.$ZodTypeDiscriminable, ...core.$ZodTypeDiscriminable[]], - Disc extends string, ->( - discriminator: Disc, - options: Types, - params?: string | core.$ZodDiscriminatedUnionParams -): ZodDiscriminatedUnion { - // const [options, params] = args; - return new ZodDiscriminatedUnion({ - type: "union", - options, - discriminator, - ...util.normalizeParams(params), - }) as any; -} - -// ZodIntersection -export interface ZodIntersection - extends _ZodType>, - core.$ZodIntersection { - "~standard": ZodStandardSchemaWithJSON; -} -export const ZodIntersection: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodIntersection", - (inst, def) => { - core.$ZodIntersection.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.intersectionProcessor(inst, ctx, json, params); - } -); - -export function intersection( - left: T, - right: U -): ZodIntersection { - return new ZodIntersection({ - type: "intersection", - left: left as any as core.$ZodType, - right: right as any as core.$ZodType, - }) as any; -} - -// ZodTuple -export interface ZodTuple< - T extends util.TupleItems = readonly core.$ZodType[], - Rest extends core.SomeType | null = core.$ZodType | null, -> extends _ZodType>, - core.$ZodTuple { - "~standard": ZodStandardSchemaWithJSON; - rest(rest: Rest): ZodTuple; -} -export const ZodTuple: core.$constructor = /*@__PURE__*/ core.$constructor("ZodTuple", (inst, def) => { - core.$ZodTuple.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.tupleProcessor(inst, ctx, json, params); - inst.rest = (rest) => - inst.clone({ - ...inst._zod.def, - rest: rest as any as core.$ZodType, - }) as any; -}); - -export function tuple( - items: T, - params?: string | core.$ZodTupleParams -): ZodTuple; -export function tuple( - items: T, - rest: Rest, - params?: string | core.$ZodTupleParams -): ZodTuple; -export function tuple(items: [], params?: string | core.$ZodTupleParams): ZodTuple<[], null>; -export function tuple( - items: core.SomeType[], - _paramsOrRest?: string | core.$ZodTupleParams | core.SomeType, - _params?: string | core.$ZodTupleParams -) { - const hasRest = _paramsOrRest instanceof core.$ZodType; - const params = hasRest ? _params : _paramsOrRest; - const rest = hasRest ? _paramsOrRest : null; - return new ZodTuple({ - type: "tuple", - items: items as any as core.$ZodType[], - rest, - ...util.normalizeParams(params), - }); -} - -// ZodRecord -export interface ZodRecord< - Key extends core.$ZodRecordKey = core.$ZodRecordKey, - Value extends core.SomeType = core.$ZodType, -> extends _ZodType>, - core.$ZodRecord { - "~standard": ZodStandardSchemaWithJSON; - keyType: Key; - valueType: Value; -} -export const ZodRecord: core.$constructor = /*@__PURE__*/ core.$constructor("ZodRecord", (inst, def) => { - core.$ZodRecord.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.recordProcessor(inst, ctx, json, params); - - inst.keyType = def.keyType; - inst.valueType = def.valueType; -}); - -export function record( - keyType: Key, - valueType: Value, - params?: string | core.$ZodRecordParams -): ZodRecord { - return new ZodRecord({ - type: "record", - keyType, - valueType: valueType as any as core.$ZodType, - ...util.normalizeParams(params), - }) as any; -} -// type alksjf = core.output; -export function partialRecord( - keyType: Key, - valueType: Value, - params?: string | core.$ZodRecordParams -): ZodRecord { - const k = core.clone(keyType); - k._zod.values = undefined; - return new ZodRecord({ - type: "record", - keyType: k, - valueType: valueType as any, - ...util.normalizeParams(params), - }) as any; -} - -export function looseRecord( - keyType: Key, - valueType: Value, - params?: string | core.$ZodRecordParams -): ZodRecord { - return new ZodRecord({ - type: "record", - keyType, - valueType: valueType as any as core.$ZodType, - mode: "loose", - ...util.normalizeParams(params), - }) as any; -} - -// ZodMap -export interface ZodMap - extends _ZodType>, - core.$ZodMap { - "~standard": ZodStandardSchemaWithJSON; - keyType: Key; - valueType: Value; - min(minSize: number, params?: string | core.$ZodCheckMinSizeParams): this; - nonempty(params?: string | core.$ZodCheckMinSizeParams): this; - max(maxSize: number, params?: string | core.$ZodCheckMaxSizeParams): this; - size(size: number, params?: string | core.$ZodCheckSizeEqualsParams): this; -} -export const ZodMap: core.$constructor = /*@__PURE__*/ core.$constructor("ZodMap", (inst, def) => { - core.$ZodMap.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.mapProcessor(inst, ctx, json, params); - inst.keyType = def.keyType; - inst.valueType = def.valueType; - inst.min = (...args) => inst.check(core._minSize(...args)); - inst.nonempty = (params) => inst.check(core._minSize(1, params)); - inst.max = (...args) => inst.check(core._maxSize(...args)); - inst.size = (...args) => inst.check(core._size(...args)); -}); - -export function map( - keyType: Key, - valueType: Value, - params?: string | core.$ZodMapParams -): ZodMap { - return new ZodMap({ - type: "map", - keyType: keyType as any as core.$ZodType, - valueType: valueType as any as core.$ZodType, - ...util.normalizeParams(params), - }) as any; -} - -// ZodSet -export interface ZodSet - extends _ZodType>, - core.$ZodSet { - "~standard": ZodStandardSchemaWithJSON; - min(minSize: number, params?: string | core.$ZodCheckMinSizeParams): this; - nonempty(params?: string | core.$ZodCheckMinSizeParams): this; - max(maxSize: number, params?: string | core.$ZodCheckMaxSizeParams): this; - size(size: number, params?: string | core.$ZodCheckSizeEqualsParams): this; -} -export const ZodSet: core.$constructor = /*@__PURE__*/ core.$constructor("ZodSet", (inst, def) => { - core.$ZodSet.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.setProcessor(inst, ctx, json, params); - - inst.min = (...args) => inst.check(core._minSize(...args)); - inst.nonempty = (params) => inst.check(core._minSize(1, params)); - inst.max = (...args) => inst.check(core._maxSize(...args)); - inst.size = (...args) => inst.check(core._size(...args)); -}); - -export function set( - valueType: Value, - params?: string | core.$ZodSetParams -): ZodSet { - return new ZodSet({ - type: "set", - valueType: valueType as any as core.$ZodType, - ...util.normalizeParams(params), - }) as any; -} - -// ZodEnum -export interface ZodEnum< - /** @ts-ignore Cast variance */ - out T extends util.EnumLike = util.EnumLike, -> extends _ZodType>, - core.$ZodEnum { - "~standard": ZodStandardSchemaWithJSON; - enum: T; - options: Array; - - extract( - values: U, - params?: string | core.$ZodEnumParams - ): ZodEnum>>; - exclude( - values: U, - params?: string | core.$ZodEnumParams - ): ZodEnum>>; -} -export const ZodEnum: core.$constructor = /*@__PURE__*/ core.$constructor("ZodEnum", (inst, def) => { - core.$ZodEnum.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.enumProcessor(inst, ctx, json, params); - - inst.enum = def.entries; - inst.options = Object.values(def.entries); - - const keys = new Set(Object.keys(def.entries)); - - inst.extract = (values, params) => { - const newEntries: Record = {}; - for (const value of values) { - if (keys.has(value)) { - newEntries[value] = def.entries[value]; - } else throw new Error(`Key ${value} not found in enum`); - } - return new ZodEnum({ - ...def, - checks: [], - ...util.normalizeParams(params), - entries: newEntries, - }) as any; - }; - - inst.exclude = (values, params) => { - const newEntries: Record = { ...def.entries }; - for (const value of values) { - if (keys.has(value)) { - delete newEntries[value]; - } else throw new Error(`Key ${value} not found in enum`); - } - return new ZodEnum({ - ...def, - checks: [], - ...util.normalizeParams(params), - entries: newEntries, - }) as any; - }; -}); - -function _enum( - values: T, - params?: string | core.$ZodEnumParams -): ZodEnum>; -function _enum(entries: T, params?: string | core.$ZodEnumParams): ZodEnum; -function _enum(values: any, params?: string | core.$ZodEnumParams) { - const entries: any = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values; - - return new ZodEnum({ - type: "enum", - entries, - ...util.normalizeParams(params), - }) as any; -} -export { _enum as enum }; - -/** @deprecated This API has been merged into `z.enum()`. Use `z.enum()` instead. - * - * ```ts - * enum Colors { red, green, blue } - * z.enum(Colors); - * ``` - */ -export function nativeEnum(entries: T, params?: string | core.$ZodEnumParams): ZodEnum { - return new ZodEnum({ - type: "enum", - entries, - ...util.normalizeParams(params), - }) as any as ZodEnum; -} - -// ZodLiteral -export interface ZodLiteral - extends _ZodType>, - core.$ZodLiteral { - "~standard": ZodStandardSchemaWithJSON; - values: Set; - /** @legacy Use `.values` instead. Accessing this property will throw an error if the literal accepts multiple values. */ - value: T; -} -export const ZodLiteral: core.$constructor = /*@__PURE__*/ core.$constructor("ZodLiteral", (inst, def) => { - core.$ZodLiteral.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.literalProcessor(inst, ctx, json, params); - inst.values = new Set(def.values); - Object.defineProperty(inst, "value", { - get() { - if (def.values.length > 1) { - throw new Error("This schema contains multiple valid literal values. Use `.values` instead."); - } - return def.values[0]; - }, - }); -}); - -export function literal>( - value: T, - params?: string | core.$ZodLiteralParams -): ZodLiteral; -export function literal( - value: T, - params?: string | core.$ZodLiteralParams -): ZodLiteral; -export function literal(value: any, params: any) { - return new ZodLiteral({ - type: "literal", - values: Array.isArray(value) ? value : [value], - ...util.normalizeParams(params), - }); -} - -// ZodFile -export interface ZodFile extends _ZodType, core.$ZodFile { - "~standard": ZodStandardSchemaWithJSON; - min(size: number, params?: string | core.$ZodCheckMinSizeParams): this; - max(size: number, params?: string | core.$ZodCheckMaxSizeParams): this; - mime(types: util.MimeTypes | Array, params?: string | core.$ZodCheckMimeTypeParams): this; -} -export const ZodFile: core.$constructor = /*@__PURE__*/ core.$constructor("ZodFile", (inst, def) => { - core.$ZodFile.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.fileProcessor(inst, ctx, json, params); - - inst.min = (size, params) => inst.check(core._minSize(size, params)); - inst.max = (size, params) => inst.check(core._maxSize(size, params)); - inst.mime = (types, params) => inst.check(core._mime(Array.isArray(types) ? types : [types], params)); -}); - -export function file(params?: string | core.$ZodFileParams): ZodFile { - return core._file(ZodFile, params) as any; -} - -// ZodTransform -export interface ZodTransform - extends _ZodType>, - core.$ZodTransform { - "~standard": ZodStandardSchemaWithJSON; -} -export const ZodTransform: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodTransform", - (inst, def) => { - core.$ZodTransform.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.transformProcessor(inst, ctx, json, params); - - inst._zod.parse = (payload, _ctx) => { - if (_ctx.direction === "backward") { - throw new core.$ZodEncodeError(inst.constructor.name); - } - - (payload as core.$RefinementCtx).addIssue = (issue) => { - if (typeof issue === "string") { - payload.issues.push(util.issue(issue, payload.value, def)); - } else { - // for Zod 3 backwards compatibility - const _issue = issue as any; - - if (_issue.fatal) _issue.continue = false; - _issue.code ??= "custom"; - _issue.input ??= payload.value; - _issue.inst ??= inst; - // _issue.continue ??= true; - payload.issues.push(util.issue(_issue)); - } - }; - - const output = def.transform(payload.value, payload); - if (output instanceof Promise) { - return output.then((output) => { - payload.value = output; - return payload; - }); - } - payload.value = output; - return payload; - }; - } -); - -export function transform( - fn: (input: I, ctx: core.ParsePayload) => O -): ZodTransform, I> { - return new ZodTransform({ - type: "transform", - transform: fn as any, - }) as any; -} - -// ZodOptional -export interface ZodOptional - extends _ZodType>, - core.$ZodOptional { - "~standard": ZodStandardSchemaWithJSON; - unwrap(): T; -} -export const ZodOptional: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodOptional", - (inst, def) => { - core.$ZodOptional.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.optionalProcessor(inst, ctx, json, params); - - inst.unwrap = () => inst._zod.def.innerType; - } -); - -export function optional(innerType: T): ZodOptional { - return new ZodOptional({ - type: "optional", - innerType: innerType as any as core.$ZodType, - }) as any; -} - -// ZodExactOptional -export interface ZodExactOptional - extends _ZodType>, - core.$ZodExactOptional { - "~standard": ZodStandardSchemaWithJSON; - unwrap(): T; -} -export const ZodExactOptional: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodExactOptional", - (inst, def) => { - core.$ZodExactOptional.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.optionalProcessor(inst, ctx, json, params); - - inst.unwrap = () => inst._zod.def.innerType; - } -); - -export function exactOptional(innerType: T): ZodExactOptional { - return new ZodExactOptional({ - type: "optional", - innerType: innerType as any as core.$ZodType, - }) as any; -} - -// ZodNullable -export interface ZodNullable - extends _ZodType>, - core.$ZodNullable { - "~standard": ZodStandardSchemaWithJSON; - unwrap(): T; -} -export const ZodNullable: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodNullable", - (inst, def) => { - core.$ZodNullable.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.nullableProcessor(inst, ctx, json, params); - - inst.unwrap = () => inst._zod.def.innerType; - } -); - -export function nullable(innerType: T): ZodNullable { - return new ZodNullable({ - type: "nullable", - innerType: innerType as any as core.$ZodType, - }) as any; -} - -// nullish -export function nullish(innerType: T): ZodOptional> { - return optional(nullable(innerType)); -} - -// ZodDefault -export interface ZodDefault - extends _ZodType>, - core.$ZodDefault { - "~standard": ZodStandardSchemaWithJSON; - unwrap(): T; - /** @deprecated Use `.unwrap()` instead. */ - removeDefault(): T; -} -export const ZodDefault: core.$constructor = /*@__PURE__*/ core.$constructor("ZodDefault", (inst, def) => { - core.$ZodDefault.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.defaultProcessor(inst, ctx, json, params); - - inst.unwrap = () => inst._zod.def.innerType; - inst.removeDefault = inst.unwrap; -}); - -export function _default( - innerType: T, - defaultValue: util.NoUndefined> | (() => util.NoUndefined>) -): ZodDefault { - return new ZodDefault({ - type: "default", - innerType: innerType as any as core.$ZodType, - get defaultValue() { - return typeof defaultValue === "function" ? (defaultValue as Function)() : util.shallowClone(defaultValue); - }, - }) as any; -} - -// ZodPrefault -export interface ZodPrefault - extends _ZodType>, - core.$ZodPrefault { - "~standard": ZodStandardSchemaWithJSON; - unwrap(): T; -} -export const ZodPrefault: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodPrefault", - (inst, def) => { - core.$ZodPrefault.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.prefaultProcessor(inst, ctx, json, params); - inst.unwrap = () => inst._zod.def.innerType; - } -); - -export function prefault( - innerType: T, - defaultValue: core.input | (() => core.input) -): ZodPrefault { - return new ZodPrefault({ - type: "prefault", - innerType: innerType as any as core.$ZodType, - get defaultValue() { - return typeof defaultValue === "function" ? (defaultValue as Function)() : util.shallowClone(defaultValue); - }, - }) as any; -} - -// ZodNonOptional -export interface ZodNonOptional - extends _ZodType>, - core.$ZodNonOptional { - "~standard": ZodStandardSchemaWithJSON; - unwrap(): T; -} -export const ZodNonOptional: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodNonOptional", - (inst, def) => { - core.$ZodNonOptional.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.nonoptionalProcessor(inst, ctx, json, params); - - inst.unwrap = () => inst._zod.def.innerType; - } -); - -export function nonoptional( - innerType: T, - params?: string | core.$ZodNonOptionalParams -): ZodNonOptional { - return new ZodNonOptional({ - type: "nonoptional", - innerType: innerType as any as core.$ZodType, - ...util.normalizeParams(params), - }) as any; -} - -// ZodSuccess -export interface ZodSuccess - extends _ZodType>, - core.$ZodSuccess { - "~standard": ZodStandardSchemaWithJSON; - unwrap(): T; -} -export const ZodSuccess: core.$constructor = /*@__PURE__*/ core.$constructor("ZodSuccess", (inst, def) => { - core.$ZodSuccess.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.successProcessor(inst, ctx, json, params); - - inst.unwrap = () => inst._zod.def.innerType; -}); - -export function success(innerType: T): ZodSuccess { - return new ZodSuccess({ - type: "success", - innerType: innerType as any as core.$ZodType, - }) as any; -} - -// ZodCatch -export interface ZodCatch - extends _ZodType>, - core.$ZodCatch { - "~standard": ZodStandardSchemaWithJSON; - unwrap(): T; - /** @deprecated Use `.unwrap()` instead. */ - removeCatch(): T; -} -export const ZodCatch: core.$constructor = /*@__PURE__*/ core.$constructor("ZodCatch", (inst, def) => { - core.$ZodCatch.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.catchProcessor(inst, ctx, json, params); - - inst.unwrap = () => inst._zod.def.innerType; - inst.removeCatch = inst.unwrap; -}); - -function _catch( - innerType: T, - catchValue: core.output | ((ctx: core.$ZodCatchCtx) => core.output) -): ZodCatch { - return new ZodCatch({ - type: "catch", - innerType: innerType as any as core.$ZodType, - catchValue: (typeof catchValue === "function" ? catchValue : () => catchValue) as ( - ctx: core.$ZodCatchCtx - ) => core.output, - }) as any; -} -export { _catch as catch }; - -// ZodNaN -export interface ZodNaN extends _ZodType, core.$ZodNaN { - "~standard": ZodStandardSchemaWithJSON; -} -export const ZodNaN: core.$constructor = /*@__PURE__*/ core.$constructor("ZodNaN", (inst, def) => { - core.$ZodNaN.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.nanProcessor(inst, ctx, json, params); -}); - -export function nan(params?: string | core.$ZodNaNParams): ZodNaN { - return core._nan(ZodNaN, params); -} - -// ZodPipe -export interface ZodPipe - extends _ZodType>, - core.$ZodPipe { - "~standard": ZodStandardSchemaWithJSON; - in: A; - out: B; -} -export const ZodPipe: core.$constructor = /*@__PURE__*/ core.$constructor("ZodPipe", (inst, def) => { - core.$ZodPipe.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.pipeProcessor(inst, ctx, json, params); - - inst.in = def.in; - inst.out = def.out; -}); - -export function pipe< - const A extends core.SomeType, - B extends core.$ZodType> = core.$ZodType>, ->(in_: A, out: B | core.$ZodType>): ZodPipe; -export function pipe(in_: core.SomeType, out: core.SomeType) { - return new ZodPipe({ - type: "pipe", - in: in_ as unknown as core.$ZodType, - out: out as unknown as core.$ZodType, - // ...util.normalizeParams(params), - }); -} - -// ZodCodec -export interface ZodCodec - extends ZodPipe, - core.$ZodCodec { - "~standard": ZodStandardSchemaWithJSON; - _zod: core.$ZodCodecInternals; - def: core.$ZodCodecDef; -} -export const ZodCodec: core.$constructor = /*@__PURE__*/ core.$constructor("ZodCodec", (inst, def) => { - ZodPipe.init(inst, def); - core.$ZodCodec.init(inst, def); -}); - -export function codec( - in_: A, - out: B, - params: { - decode: (value: core.output, payload: core.ParsePayload>) => core.util.MaybeAsync>; - encode: (value: core.input, payload: core.ParsePayload>) => core.util.MaybeAsync>; - } -): ZodCodec { - return new ZodCodec({ - type: "pipe", - in: in_ as any as core.$ZodType, - out: out as any as core.$ZodType, - transform: params.decode as any, - reverseTransform: params.encode as any, - }) as any; -} - -// ZodReadonly -export interface ZodReadonly - extends _ZodType>, - core.$ZodReadonly { - "~standard": ZodStandardSchemaWithJSON; - unwrap(): T; -} -export const ZodReadonly: core.$constructor = /*@__PURE__*/ core.$constructor( - "ZodReadonly", - (inst, def) => { - core.$ZodReadonly.init(inst, def); - ZodType.init(inst, def); - inst._zod.processJSONSchema = (ctx, json, params) => processors.readonlyProcessor(inst, ctx, json, params); - - inst.unwrap = () => inst._zod.def.innerType; - } -); - -export function readonly(innerType: T): ZodReadonly { - return new ZodReadonly({ - type: "readonly", - innerType: innerType as any as core.$ZodType, - }) as any; -} - -// ZodTemplateLiteral -export interface ZodTemplateLiteral