SPB Git

spb/polyllm

Public

PolyLLM v0.1.0 — multi-provider BYOK AI workspace (OpenAI, Anthropic, Gemini, xAI)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Sep 8, 2026) Browse files

44 changed files +20,001 −0

added .env.example +35 −0
@@ -0,0 +1,35 @@
1+# --- Runtime -------------------------------------------------------------
2+NODE_ENV=production
3+PORT=3000
4+# Public origin used in emails, auth callbacks and canonical links. No trailing slash.
5+PUBLIC_APP_URL=https://www.polyllm.io
6+
7+# --- Database ------------------------------------------------------------
8+DATABASE_URL=postgres://localhost:5432/polyllm
9+DB_POOL_MAX=10
10+
11+# --- Auth ----------------------------------------------------------------
12+# 32+ random bytes, hex or base64. `openssl rand -hex 32`
13+AUTH_SECRET=
14+
15+# --- Email (Resend) ------------------------------------------------------
16+RESEND_API_KEY=
17+RESEND_FROM_EMAIL="PolyLLM <mail@spboucher.ai>"
18+# Set to 1 to log emails instead of sending (development).
19+EMAIL_DRY_RUN=0
20+
21+# --- Encryption of user provider keys (AES-256-GCM, server-side only) ----
22+# 32+ random bytes. Rotating this secret invalidates every stored key.
23+API_KEY_ENCRYPTION_SECRET=
24+
25+# --- Owner / development provider keys (TEST ONLY — never used for users) -
26+OPENAI_API_KEY=
27+ANTHROPIC_API_KEY=
28+GOOGLE_GEMINI_API_KEY=
29+XAI_API_KEY=
30+
31+# --- Admin ---------------------------------------------------------------
32+# Comma-separated emails with access to /admin.
33+ADMIN_EMAILS=
34+# Model catalog refresh interval (minutes). 0 disables the scheduler.
35+MODEL_SYNC_INTERVAL_MINUTES=360
added .gitignore +33 −0
@@ -0,0 +1,33 @@
1+# dependencies
2+node_modules/
3+.pnpm-store/
4+
5+# next
6+.next/
7+out/
8+next-env.d.ts
9+*.tsbuildinfo
10+
11+# env & secrets — never commit
12+.env
13+.env.*
14+!.env.example
15+deploy/*.mld.json
16+
17+# research scratch (installed SDKs, probe outputs)
18+research/*/node_modules/
19+research/*/out/
20+research/*/*.log
21+
22+# tests
23+coverage/
24+playwright-report/
25+test-results/
26+qa/out/
27+
28+# misc
29+.DS_Store
30+logs/
31+tmp/
32+.turbo/
33+.claude/
added CLAUDE.md +38 −0
@@ -0,0 +1,38 @@
1+# PolyLLM — repository guide
2+
3+PolyLLM (www.polyllm.io) is a BYOK multi-provider AI workspace: OpenAI, Anthropic, Gemini, xAI behind one normalized
4+adapter layer, real streaming, capability-driven configuration, Arena comparisons, usage/cost tracking.
5+The original product brief lives in `docs/SPEC-original.md`; the UI conventions in `docs/UI-BRIEF.md`.
6+
7+## Non-negotiables
8+- **Research before provider changes.** Read `docs/provider-research/<provider>.md`, re-fetch the official docs, probe the
9+ real API (`pnpm providers:matrix`), then update `src/lib/ai/providers/<provider>/catalog*.ts`. Never assume model ids,
10+ parameters, event names or limits from memory. Bump `Last documentation audit`.
11+- **Provider quirks stay inside `src/lib/ai/providers/*`.** UI and services only see `PolyModel`, `UnifiedChatRequest`,
12+ `UnifiedStreamEvent`, `PolyProviderError`.
13+- **Capabilities drive the UI.** Never branch on a model id in components; use `model.capabilities` / `model.parameters`.
14+ Never send a parameter the model does not accept (`filterSettings()` + adapter translation).
15+- **Keys.** User keys are encrypted (`src/lib/crypto/keys.ts`) and decrypted only in `getDecryptedKey()` right before a
16+ request. Never log, return or serialize them; `PublicConnection` exposes `keyHint` only. Owner keys in `.env` are for the
17+ registry sync, admin diagnostics and tests — never for user requests.
18+- **No fake integrations.** A capability is ✅ only after a real request passed (`docs/provider-test-matrix.md`).
19+- Secrets only in `.env` (gitignored) and the mld manifest on M1M32; `.env.example` documents the variables.
20+
21+## Commands
22+`pnpm dev` · `pnpm typecheck` · `pnpm lint` · `pnpm test` (vitest) · `pnpm test:e2e` (Playwright; dev server with
23+`EMAIL_DRY_RUN=1 EMAIL_DRY_RUN_PRINT=1`) · `pnpm db:generate` / `pnpm db:migrate` · `pnpm models:sync [provider]` ·
24+`pnpm providers:matrix [provider]`.
25+
26+## Deploy
27+`mld` from the laptop (see `docs/deployment-cluster.md`): `mld stage . polyllm && mld deploy polyllm --node M3U96a`.
28+Manifest with secrets: `M1M32:~/dispatch/apps/polyllm.json` (local gitignored copy `deploy/polyllm.mld.json`).
29+
30+## Gotchas
31+- React Compiler lint: no `Date.now()`/impure calls in render, no setState synchronously in effects without an explicit
32+ eslint-disable, memoize derived lists.
33+- `import "server-only"` modules are used by CLI scripts through `scripts/hooks.mjs` (tsx `--import`) and by vitest via an alias.
34+- Anthropic: adaptive thinking may legitimately produce zero thinking tokens on easy prompts; Haiku 4.5 needs `budget_tokens`.
35+- Gemini: free-tier keys have tiny per-model daily quotas (429 `limit: 20`) and some models are paid-tier only (429 `limit: 0`);
36+ thought signatures must be replayed on function-call parts.
37+- xAI: bad keys return HTTP **400** (`Incorrect API key`), `frequency/presence_penalty` always 400, web search only via `/v1/responses`.
38+- OpenAI: Responses API has no `seed`/`stop`; sampling params only when `reasoning.effort === "none"` on reasoning models.
added README.md +46 −0
@@ -0,0 +1,46 @@
1+# PolyLLM
2+
3+**One interface. Every model. Bring your own keys.** — https://www.polyllm.io
4+
5+PolyLLM is a universal control center for AI models: connect your own OpenAI, Anthropic, Google Gemini and xAI API keys,
6+discover the models your keys can reach, configure each one with only the parameters it supports, chat with real
7+token-by-token streaming, compare up to four models side by side in the Arena, and track tokens, latency and estimated
8+cost. Keys are encrypted at rest (AES-256-GCM, HKDF-derived data key, AAD-bound to the user) and only decrypted on the
9+server immediately before a provider request.
10+
11+## Stack
12+Next.js 16 (App Router, Route Handlers with SSE streaming) · React 19 · TypeScript · Tailwind v4 · PostgreSQL 17 + Drizzle ·
13+Better Auth 1.7 (Argon2id, email verification, sessions, reset, change email, delete account) · Resend · Zod ·
14+official provider SDKs (`openai`, `@anthropic-ai/sdk`, `@google/genai`; xAI through the OpenAI SDK at `api.x.ai`).
15+
16+## Layout
17+```
18+src/app routes: (marketing) landing/legal · (auth) login/signup/verify/reset · app/* workspace · admin/* · share/[id] · api/*
19+src/lib/ai/core provider-neutral contract: PolyModel, UnifiedChatRequest, UnifiedStreamEvent, errors, retry, pricing, normalization
20+src/lib/ai/providers adapters (openai, anthropic, gemini, xai) + catalogs — provider quirks live ONLY here
21+src/lib/ai/registry model registry: live listing → catalog merge → Postgres; scheduled + manual sync
22+src/lib/chat turn orchestration (edit/regenerate/continue/branch), built-in tools loop, SSE
23+src/lib/providers encrypted key storage & validation
24+src/components ui kit · app shell · chat · arena · settings · marketing
25+docs/ provider-research (per provider, dated), provider-test-matrix (generated), deployment-cluster, final-audit, UI brief
26+scripts/ sync-models, provider-matrix (real-API tests)
27+e2e/, tests/ Playwright workflows, vitest unit tests
28+```
29+
30+## Development
31+```bash
32+cp .env.example .env # fill AUTH_SECRET, API_KEY_ENCRYPTION_SECRET, RESEND_API_KEY, owner provider keys (optional)
33+createdb polyllm && pnpm install && pnpm db:migrate
34+pnpm models:sync # populate the registry with the owner keys
35+pnpm dev # http://localhost:3000
36+pnpm typecheck && pnpm lint && pnpm test
37+pnpm providers:matrix # real-API capability matrix → docs/provider-test-matrix.md
38+EMAIL_DRY_RUN=1 EMAIL_DRY_RUN_PRINT=1 pnpm dev && pnpm test:e2e # full browser workflow (links read from the dev log)
39+```
40+
41+## Deployment
42+Runs on the private MacLustr cluster behind ngrok — see `docs/deployment-cluster.md`.
43+
44+## Security notes
45+No provider key ever reaches the browser, logs or analytics (structured logger redacts key-shaped strings and sensitive
46+field names). CSP, HSTS, HttpOnly/SameSite cookies, rate limits on auth and provider endpoints, per-user audit log.
added deploy/backup/install.sh +28 −0
@@ -0,0 +1,28 @@
1+#!/bin/bash
2+# Installs the daily PostgreSQL backup for PolyLLM on the deployment node (run ON the node).
3+set -euo pipefail
4+mkdir -p ~/backups/polyllm ~/Library/LaunchAgents
5+cat > ~/backups/polyllm/backup.sh <<'SH'
6+#!/bin/bash
7+set -euo pipefail
8+export PATH="/opt/homebrew/opt/postgresql@17/bin:/opt/homebrew/bin:$PATH"
9+out=~/backups/polyllm/polyllm-$(date +%Y%m%d).sql.gz
10+pg_dump polyllm | gzip -9 > "$out.tmp" && mv "$out.tmp" "$out"
11+find ~/backups/polyllm -name 'polyllm-*.sql.gz' -mtime +14 -delete
12+echo "$(date -Iseconds) ok $(du -h "$out" | cut -f1)" >> ~/backups/polyllm/backup.log
13+SH
14+chmod +x ~/backups/polyllm/backup.sh
15+cat > ~/Library/LaunchAgents/dev.polyllm.backup.plist <<PLIST
16+<?xml version="1.0" encoding="UTF-8"?>
17+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
18+<plist version="1.0"><dict>
19+ <key>Label</key><string>dev.polyllm.backup</string>
20+ <key>ProgramArguments</key><array><string>/bin/bash</string><string>$HOME/backups/polyllm/backup.sh</string></array>
21+ <key>StartCalendarInterval</key><dict><key>Hour</key><integer>3</integer><key>Minute</key><integer>45</integer></dict>
22+ <key>StandardOutPath</key><string>$HOME/backups/polyllm/launchd.log</string>
23+ <key>StandardErrorPath</key><string>$HOME/backups/polyllm/launchd.log</string>
24+</dict></plist>
25+PLIST
26+launchctl bootout gui/$(id -u)/dev.polyllm.backup 2>/dev/null || true
27+launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/dev.polyllm.backup.plist
28+~/backups/polyllm/backup.sh && echo "backup installed + first dump done"
added docs/SPEC-original.md +3 −0
@@ -0,0 +1,3 @@
1+# PolyLLM — original product brief (CLAUDE.md provided by the owner, 2026-09-08)
2+
3+The full brief was supplied in the build session; its normative rules are reproduced in the repository `CLAUDE.md` and `docs/UI-BRIEF.md`. Key sections: research-before-implementation, live model catalog, adapter architecture, mandatory email verification, encrypted BYOK keys, unified streaming events, capability-driven configuration, Arena, usage/cost tracking, security/privacy/logging rules, cluster deployment through ngrok at https://www.polyllm.io, real-API test matrix, final audit.
added docs/UI-BRIEF.md +64 −0
@@ -0,0 +1,64 @@
1+# PolyLLM — UI brief for contributors (humans and agents)
2+
3+PolyLLM (www.polyllm.io) is a **universal control center for AI models**: users bring their own API keys
4+(OpenAI, Anthropic, Gemini, xAI), discover current models, configure them precisely, chat with real streaming,
5+compare models in the Arena and track usage/costs. Tagline: **"Your models. Your keys. One workspace."**
6+
7+## Stack & conventions
8+- Next.js 16 App Router, React 19, TypeScript strict, Tailwind v4 (tokens in `src/app/globals.css`), shadcn-style
9+ primitives in `src/components/ui/*` (button, input/textarea/label/field, badge, dialog, dropdown-menu, popover,
10+ select, slider, switch, tabs, tooltip, toast (`toast.success/error/info`), misc: Card/CardHeader/CardBody, Stat,
11+ PageHeader, EmptyState, Skeleton, CopyButton, Kbd, Spinner, Divider). Icons: `lucide-react`. Motion: `motion/react` (sparingly).
12+- Client data: `useApi<T>(url)` (SWR) and `api<T>(url, { method, json })` from `src/lib/client/api.ts`;
13+ `streamEvents(url, body, onEvent, signal)` for SSE. Types: `src/lib/client/types.ts`. Provider metadata:
14+ `src/lib/client/providers.ts` (`PROVIDERS`, `PROVIDER_ORDER`, `providerName`). Brand: `src/components/brand/logo.tsx`
15+ (`Logo`, `LogoMark`), `src/components/brand/provider-icon.tsx` (`ProviderIcon`).
16+- App state: `useApp()` from `src/components/app/store.tsx` → `{ user, preferences, updatePreferences, models, modelsByKey,
17+ favorites, recents, connectedProviders, connections, folders, toggleFavorite, refreshModels, refreshConnections,
18+ selectedModelKey, setSelectedModelKey, setPaletteOpen }`. Everything under `/app/*` is wrapped by the shell
19+ (sidebar + command palette) in `src/app/app/layout.tsx`; pages render inside `<div className="relative flex min-w-0 flex-1 flex-col">`.
20+ A page should typically be `<main className="min-h-0 flex-1 overflow-y-auto scrollbar-thin"><div className="mx-auto w-full max-w-5xl px-4 py-6 sm:px-6 lg:px-8">…</div></main>`.
21+- Auth client: `authClient`, `signIn`, `signUp`, `signOut`, `useSession` from `src/lib/auth-client.ts` (Better Auth 1.7).
22+ Server: `requireUser()` / `getSession()` in `src/lib/session.ts`.
23+- Formatting helpers: `formatUsd`, `formatTokens`, `formatMs`, `formatRelative`, `formatNumber`, `cn` in `src/lib/utils.ts`.
24+- Never render key material. Connections only expose `keyHint` like `sk-••••••••9A2K`.
25+- React Compiler lint rules apply: no setState synchronously in effects without the eslint-disable, no components defined
26+ inside render, derive state with useMemo. Run `pnpm lint` and `pnpm typecheck`.
27+
28+## Design language (must feel premium, unique, not a template)
29+- Minimal, dense-when-useful, excellent typography (Geist Sans/Mono via `font-sans`/`font-mono`), subtle borders
30+ (`border-border`), surfaces `bg-bg / bg-bg-subtle / bg-bg-muted / bg-bg-elevated`, text `text-fg / text-fg-muted / text-fg-subtle`,
31+ accent `text-accent / bg-accent / bg-accent-soft`, semantic `success/warning/danger/info` (+ `-soft`). Radii `rounded-md/lg/xl`.
32+ Provider colors: `text-openai`, `text-anthropic`, `text-gemini`, `text-xai` or `style={{color: PROVIDERS[p].colorVar}}`.
33+- Dark and light must both look great. No cheap gradients, no childish AI imagery, no huge empty whitespace, no boxed-card overload.
34+ A single restrained gradient (`.text-gradient`) is allowed for hero words. Use `.dot-grid` / `.glass` utilities sparingly.
35+- Mobile first: no horizontal overflow, 16px inputs on mobile (`text-[15px] sm:text-sm` is already in Input), safe-area aware.
36+- Keyboard-first: ⌘K palette, ⌘N new chat, ⌘Enter send, Esc stop, ⌘/ model selector, ⌘B sidebar.
37+- Accessibility: semantic HTML, labels, visible focus, aria on icon buttons, reduced motion respected.
38+
39+## API routes (all JSON unless noted; all under a verified session)
40+- `GET /api/models` → `{ models: PolyModel[], favorites: string[], recents: string[], connectedProviders }`;
41+ `POST /api/models {action:"toggle-favorite", modelKey}`; `POST /api/models/sync {provider?}` → `{results: SyncResult[]}`.
42+- `GET /api/providers` → `{connections: PublicConnection[]}`; `PUT /api/providers {provider, apiKey}` → `{ok, error?, modelsAvailable?, connections}`;
43+ `POST /api/providers {action:"validate", provider}`; `DELETE /api/providers?provider=`.
44+- `GET /api/conversations?q&provider&model&folder&archived=1&pinned=1&since&until&limit&cursor`; `POST /api/conversations`;
45+ `GET|PATCH|DELETE /api/conversations/:id`; `POST /api/conversations/:id/actions {action: duplicate|branch|export|share|unshare|share-status|delete-message}`.
46+- `POST /api/chat` (SSE) body `ChatRequestInput` → events `ChatStreamEvent` (see `src/lib/client/types.ts`).
47+- `GET /api/folders`, `POST {name,color}`, `PATCH {id,…}`, `DELETE ?id=`.
48+- `POST /api/attachments` (multipart `file`) → `{attachment}`; `GET /api/attachments?id=` streams the file.
49+- `GET /api/usage?range=today|7d|30d|all` → `{ totals, series[{bucket,requests,inputTokens,outputTokens,costUsd}], byProvider[], byModel[], recent[] }`.
50+- `GET /api/presets` → `{modelPresets, promptPresets}`; `POST /api/presets?kind=model|prompt`; `PATCH ?kind&id`; `DELETE ?kind&id`.
51+- `GET /api/preferences` / `PATCH /api/preferences` (theme, defaultModelKey, defaultSystemPrompt, enterToSend, streaming, codeWrap, showReasoning, showCosts, autoTitle, onboardingCompleted).
52+- `GET /api/arena` → `{sessions}`; `POST /api/arena {prompt, systemPrompt?, modelKeys[1..4], settings?, attachmentIds?}` → `{session}`;
53+ `POST /api/arena/stream {sessionId, modelKey}` (SSE: meta → text-delta/reasoning-delta/citation → done|error); `PATCH /api/arena {responseId, ratings}`.
54+- `GET /api/account` → `{audit}`; `GET /api/account?export=1` downloads the full account export.
55+- `GET /api/search?q=`.
56+- Admin: `GET /api/admin/providers`, `POST /api/admin/providers {action:"sync", provider?}` (owner only, `user.isAdmin`).
57+- Better Auth: `/api/auth/*` (client SDK). Email verification is mandatory: unverified users are redirected to `/verify-email`.
58+
59+## Model capability sheet (drives every configuration UI)
60+`PolyModel.capabilities` {text, vision, audioInput, audioOutput, imageGeneration, video, reasoning, tools, structuredOutput,
61+streaming, files, webSearch}; `parameters` {temperature, topP, topK, maxTokens, reasoningEffort, reasoningEffortLevels[],
62+thinkingBudget, thinkingBudgetRange, stop, seed, frequencyPenalty, presencePenalty, verbosity, temperatureRange};
63+`limits` {contextTokens, maxOutputTokens}; `pricing` {inputPerMillion, cachedInputPerMillion, outputPerMillion};
64+`status` active|preview|deprecated|unknown; `metadata.shutdownDate`, `metadata.aliases`, etc. **Never show a control the model does not support.**
added docs/deployment-cluster.md +91 −0
@@ -0,0 +1,91 @@
1+# PolyLLM — cluster deployment (MacLustr)
2+
3+Production runs on the owner's private Apple Silicon cluster and is exposed through ngrok at
4+**https://www.polyllm.io**. Everything is orchestrated by `mld` (maclustr-dispatch) from the gateway node M1M32.
5+
6+```
7+Internet → www.polyllm.io (CNAME → ngrok) → ngrok agent (PM2 polyllm-ngrok) → Next.js `next start` 0.0.0.0:8240 → PostgreSQL 17 (localhost)
8+```
9+
10+| Item | Value |
11+| --- | --- |
12+| Node | M3U96a (pinned: local PostgreSQL 17, same host as fetcha / spinza / rareindex) |
13+| Directory | `~/apps/polyllm` (rsync'd by mld from the laptop staging area) |
14+| Processes | PM2 `polyllm-web` (Next 16, port 8240, binds 0.0.0.0), PM2 `polyllm-ngrok` (`--domain www.polyllm.io`) |
15+| Database | `postgres://localhost:5432/polyllm` (created by the post-sync hook if missing) |
16+| Manifest | `M1M32:~/dispatch/apps/polyllm.json` — **the only place secrets live** (gitignored copy `deploy/polyllm.mld.json`) |
17+| Health | `GET /api/health` (liveness), `GET /api/health/ready` (DB ping; used by mld) |
18+| Registry | `mld status` / `mld status --live` |
19+
20+## Environment variables (production)
21+
22+See `.env.example`. Required: `NODE_ENV=production`, `PORT=8240`, `PUBLIC_APP_URL=https://www.polyllm.io`,
23+`DATABASE_URL`, `AUTH_SECRET` (32+ bytes), `API_KEY_ENCRYPTION_SECRET` (32+ bytes — **rotating it invalidates every
24+stored user key**), `RESEND_API_KEY`, `RESEND_FROM_EMAIL`, `ADMIN_EMAILS`. Optional owner keys
25+(`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_GEMINI_API_KEY`, `XAI_API_KEY`) are used **only** for the scheduled
26+model-registry refresh and the admin diagnostics; user requests always use the user's own encrypted key.
27+
28+## Build & deploy
29+
30+```bash
31+# laptop
32+cd ~/Desktop/Projets/apps-web/polyllm
33+pnpm typecheck && pnpm lint && pnpm test # gates
34+scp deploy/polyllm.mld.json M1M32:~/dispatch/apps/polyllm.json # first time / when secrets change
35+~/Desktop/cluster-skill/mld stage . polyllm # laptop → M1M32 staging
36+~/Desktop/cluster-skill/mld deploy polyllm --node M3U96a
37+```
38+
39+`mld deploy` runs the manifest hooks on the node: `pnpm install --frozen-lockfile` → `createdb polyllm` (if needed) +
40+`pnpm db:migrate` (Drizzle migrations in `drizzle/`, version-controlled) → `pnpm build` → PM2 start/reload of
41+`polyllm-web` and `polyllm-ngrok` → local health check (`/api/health/ready`) → public health check (`https://www.polyllm.io/api/health/ready`) → registry update.
42+
43+Restart / logs on the node:
44+
45+```bash
46+ssh M3U96a 'pm2 restart polyllm-web; pm2 logs polyllm-web --lines 100 --nostream'
47+ssh M3U96a 'pm2 logs polyllm-ngrok --lines 30 --nostream'
48+```
49+
50+Migrations are applied by the hook before the new build starts; they must stay backward compatible with the running
51+version (add columns, never drop in the same release).
52+
53+## ngrok / domain / TLS
54+
55+- DNS (GoDaddy): `www.polyllm.io` CNAME → the ngrok-cname target shown in the ngrok dashboard for the reserved domain.
56+ The apex `polyllm.io` should redirect to `https://www.polyllm.io` (GoDaddy forwarding).
57+- TLS terminates at ngrok (automatic certificate for the reserved domain). The app sees `X-Forwarded-For` /
58+ `X-Forwarded-Proto`; Better Auth is configured with `baseURL = PUBLIC_APP_URL` and secure cookies in production.
59+- The PM2 process `polyllm-ngrok` runs `ngrok http 8240 --domain www.polyllm.io`. Only port 8240 is exposed; no admin port.
60+- Streaming: SSE responses send a `: ping` heartbeat every 15 s so ngrok never closes idle long reasoning turns.
61+
62+## Process management
63+
64+PM2 with `pm2 startup` (LaunchAgent) on the node → processes survive terminal closure and reboots; `autorestart: true`,
65+`max_memory_restart: 2G`. The model-registry scheduler runs inside the web process (`src/instrumentation.ts`, every
66+`MODEL_SYNC_INTERVAL_MINUTES`, default 360) plus a startup sync.
67+
68+## Backups
69+
70+- Daily `pg_dump` at 03:45 via launchd `dev.polyllm.backup` on M3U96a → `~/backups/polyllm/polyllm-YYYYMMDD.sql.gz`,
71+ 14-day retention (`find -mtime +14 -delete`). Install with `deploy/backup/install.sh` (see that file).
72+- Restore: `gunzip -c ~/backups/polyllm/polyllm-YYYYMMDD.sql.gz | psql polyllm_restore` after `createdb polyllm_restore`;
73+ swap with `ALTER DATABASE … RENAME` during a maintenance window. Test restore on the 1st of each month into a scratch DB
74+ and run `select count(*) from users;` to validate.
75+- Encrypted user keys are only decryptable with the same `API_KEY_ENCRYPTION_SECRET`: back up the manifest too
76+ (`M1M32:~/dispatch/apps/polyllm.json` is included in the spbgit gateway backup).
77+
78+## Rollback
79+
80+```bash
81+ssh M3U96a 'cd ~/apps/polyllm && git log --oneline -5' # deployed commit
82+# redeploy the previous tag from the laptop:
83+git checkout <previous-tag> && ~/Desktop/cluster-skill/mld stage . polyllm && ~/Desktop/cluster-skill/mld deploy polyllm --node M3U96a
84+```
85+
86+If a migration must be reverted, restore last night's dump (see Backups) — Drizzle migrations are forward-only.
87+
88+## Moving to another node
89+
90+`mld move polyllm --to <node>` handles rsync, PM2 and ngrok, but the database is local: dump on M3U96a, restore on the
91+target (PostgreSQL 17 via Homebrew), then update `DATABASE_URL` in the manifest before the move.
added docs/provider-research.md +30 −0
@@ -0,0 +1,30 @@
1+# Provider research — index
2+
3+**Last documentation audit: 2026-09-08**
4+
5+PolyLLM never relies on remembered API shapes. Before each adapter was written, the CURRENT official
6+documentation was fetched and every claim that matters for the adapter was **probed against the real API**
7+with the owner's keys. The per-provider reports below contain the base URLs, auth, SDKs and versions, streaming
8+protocols and event names, tool/structured-output formats, reasoning controls, modalities, limits, parameter
9+support matrices with exact rejection strings, error schemas, rate limits, pricing, lifecycle, and the probe
10+scripts that produced the evidence.
11+
12+| Provider | Report | Model data | SDK used | Primary API | Probe scripts |
13+| --- | --- | --- | --- | --- | --- |
14+| OpenAI | [openai.md](provider-research/openai.md) | [openai.models.json](provider-research/openai.models.json) (84) | `openai` 7.10 | Responses API (`store:false`, encrypted reasoning replay) | `research/openai/` |
15+| Anthropic | [anthropic.md](provider-research/anthropic.md) | Models API (live capabilities) + `src/lib/ai/providers/anthropic/catalog.ts` (pricing) | `@anthropic-ai/sdk` 0.124 | Messages API (adaptive thinking, `output_config`) | `scripts/provider-matrix.ts` |
16+| Google Gemini | [gemini.md](provider-research/gemini.md) | [gemini.models.json](provider-research/gemini.models.json) (19) | `@google/genai` 2.21 | `generateContentStream` (thinkingLevel/budget per family, thought signatures) | `research/gemini/` |
17+| xAI | [xai.md](provider-research/xai.md) | [xai.models.json](provider-research/xai.models.json) (7) | `openai` 7.10 with `baseURL https://api.x.ai/v1` | Chat Completions (+ `/v1/responses` for server-side web search) | `research/xai/` |
18+
19+The verified behaviour is encoded in code, not prose:
20+
21+- `src/lib/ai/providers/<provider>/catalog*.ts` — capability sheets, parameter support, pricing, lifecycle.
22+- `src/lib/ai/providers/<provider>/index.ts` — request translation that only sends what the model accepts.
23+- `docs/provider-test-matrix.md` — generated by `pnpm providers:matrix` from live requests.
24+
25+## Re-audit procedure (before every release)
26+
27+1. `pnpm models:sync` — refresh the registry from the live listing endpoints; check `model_sync_runs` for removed/added ids.
28+2. Re-fetch the docs pages linked at the bottom of each report; update the catalog data when parameters, limits or prices moved.
29+3. `pnpm providers:matrix` — must be all ✅; investigate any ❌ before shipping.
30+4. Bump `Last documentation audit` in this file and in each report.
added docs/provider-research/anthropic.md +41 −0
@@ -0,0 +1,41 @@
1+# Anthropic — provider research
2+
3+**Last documentation audit: 2026-09-08** — sources: Claude Platform docs (Messages API, Models API, extended thinking,
4+structured outputs, tool use, prompt caching, pricing, errors), the bundled `claude-api` reference (models table cached
5+2026-06-24), SDK type definitions of `@anthropic-ai/sdk` 0.124.0, and live probes with the owner key (`scripts/provider-matrix.ts`
6+and `GET /v1/models`).
7+
8+## Endpoint, auth, SDK
9+- Base URL `https://api.anthropic.com`; headers `x-api-key`, `anthropic-version: 2023-06-01`. Invalid key → **401** `authentication_error`.
10+- SDK `@anthropic-ai/sdk` 0.124.0 (`client.messages.create({stream:true})` returns an async iterable of raw events; `client.models.list()` auto-paginates; `client.messages.countTokens`).
11+- Timeouts: SDK default 10 min; PolyLLM uses 10 min for chats, 20 s for validation/listing; SDK retries 1 (PolyLLM never retries mid-stream).
12+
13+## Models API (live capability metadata — verified)
14+`GET /v1/models` returns `id, display_name, created_at, max_input_tokens, max_tokens, capabilities` with
15+`thinking.types.{adaptive,enabled}`, `effort.{low,medium,high,xhigh,max}`, `image_input`, `pdf_input`, `structured_outputs`,
16+`code_execution`, `citations`, `batch`, `context_management`. 11 models for this key: `claude-fable-5-1`, `claude-opus-5`,
17+`claude-sonnet-5`, `claude-fable-5`, `claude-opus-4-8`, `claude-opus-4-7`, `claude-sonnet-4-6`, `claude-opus-4-6`,
18+`claude-opus-4-5-20251101`, `claude-haiku-4-5-20251001`, `claude-sonnet-4-5-20250929`. Aliases (`claude-haiku-4-5`) resolve to dated snapshots.
19+All current models: 1M context (Haiku 4.5: 200k), 128k max output (Haiku 4.5: 64k).
20+
21+## Verified rules encoded in the adapter
22+- **Adaptive-only generations** (`thinking.types.enabled.supported === false`: Fable 5/5.1, Opus 5/4.8/4.7, Sonnet 5) reject
23+ `temperature`/`top_p`/`top_k` (400) and `budget_tokens`; the adapter exposes none of them. Effort via `output_config.effort`.
24+ Sending `thinking:{type:"adaptive"}` to Haiku 4.5 → 400 `adaptive thinking is not supported on this model` (probed) → Haiku uses `{type:"enabled", budget_tokens}` (≥1024, < max_tokens).
25+- Fable 5.x: thinking always on, `{type:"disabled"}` → 400; forced `tool_choice` `any`/`tool` → 400 on Fable 5.1 (adapter downgrades to `auto`).
26+- Adaptive thinking decides when to think: trivial prompts produce **no thinking block and 0 thinking tokens** even at effort `high` (probed on Sonnet 5); a harder prompt produced 3.5k thinking tokens with `display:"summarized"`.
27+- Streaming events: `message_start` (input usage incl. cache), `content_block_start/delta/stop` with `text_delta`, `thinking_delta`,
28+ `signature_delta`, `input_json_delta`, `citations_delta`; `message_delta` carries `stop_reason` (`end_turn|max_tokens|stop_sequence|tool_use|pause_turn|refusal|model_context_window_exceeded`),
29+ `usage.output_tokens` and `usage.output_tokens_details.thinking_tokens`; `stop_details` on refusal.
30+- Tools: `tools[{name, description, input_schema, strict}]`; tool results as `tool_result` blocks in a **user** turn; thinking blocks replayed with signature only on the same model.
31+- Server tools: `web_search_20260209` (Opus 5/4.8/4.7/4.6, Sonnet 5/4.6; not combinable with `code_execution_20260521`), `web_search_20250305` for older models.
32+- Structured output: `output_config.format = { type: "json_schema", schema }` (Opus 4.7+, Sonnet 5, Fable — `structured_outputs.supported`).
33+- Files: PDF as `document` (base64), text files as `document` with `text/plain` source; images base64 `image` blocks.
34+- Errors: `{type:"error", error:{type, message}}`: `authentication_error`, `permission_error`, `not_found_error`, `rate_limit_error`, `overloaded_error` (529, retryable), `billing_error`, `request_too_large`, `invalid_request_error`.
35+- Pricing (USD/M, first-party): Fable 5.1 10/50 (cache read 0.25), Opus 5 5/25, Sonnet 5 2/10, Sonnet 4.6 3/15, Haiku 4.5 1/5 — see `catalog.ts`; cache reads 10 % of input.
36+- Prompt caching: `cache_control` (not used by PolyLLM v0.1; usage reports `cache_read_input_tokens`, folded into cached tokens).
37+
38+## Probe results (2026-09-08, `pnpm providers:matrix`)
39+Auth ✅ · Model list ✅ (11) · Text ✅ · Streaming ✅ · System ✅ · Vision ✅ (64×64 PNG → "Red") · Tools ✅ (streamed `input_json_delta`, args rebuilt) ·
40+Structured output ✅ · Reasoning ✅ (Sonnet 5, effort high, 3 558 thinking tokens, summary streamed) · Token usage ✅ · Invalid key ✅ (401) ·
41+Error normalization ✅ (unknown model → `not_found_error` → MODEL_NOT_FOUND) · Long response ✅ (407 words).
added docs/provider-research/gemini.md +302 −0
@@ -0,0 +1,302 @@
1+# Google Gemini (Gemini Developer API) — provider research for PolyLLM
2+
3+Last documentation audit: **2026-09-08**. SDK probed: `@google/genai` **2.21.0** (Node 25.9, tsx 4.23). Probe scripts and raw outputs: `research/gemini/*.ts`, `research/gemini/out/*.json` (keys redacted). Key used: free-tier `AQ.`-style ("auth") key.
4+
5+> Headline for the adapter: `generateContent` / `streamGenerateContent` remain **fully supported** but Google now labels them legacy and documents everything on the new **Interactions API** (`ai.interactions.create`, GA June 2026, "recommended for all new projects", all new features land there first). This audit targets `generateContent` (what the SDK's `ai.models.*` uses) and notes Interactions where relevant.
6+
7+---
8+
9+## 1. Endpoint, auth, headers
10+
11+| Item | Value (verified by probe unless marked docs) |
12+|---|---|
13+| Base URL | `https://generativelanguage.googleapis.com` |
14+| API version | `v1beta` (SDK default; needed for computer use / MCP / preview features). `v1` also works: probed `gemini-3.8-flash` + `thinkingLevel` on `v1` -> OK. Select via `new GoogleGenAI({ apiKey, httpOptions: { apiVersion: "v1" } })`. |
15+| Auth header | `x-goog-api-key: <key>` (works with `AQ.` keys). `?key=` query param also works (200). **`Authorization: Bearer <api key>` does NOT work**: 401 `UNAUTHENTICATED`, reason `ACCESS_TOKEN_TYPE_UNSUPPORTED` (Bearer is only for the OpenAI-compat endpoint). |
16+| Other headers | `Content-Type: application/json`. No rate-limit headers are returned (only `server-timing`, `vary`, `alt-svc`). |
17+| Key formats | New keys created in AI Studio are "auth keys" bound to a service account (`AQ.` prefix). Docs: **standard (legacy) keys will be rejected after September 2026** — expect BYOK users with old keys to break. Leaked keys: `"Your API key was reported as leaked. Please use another API key."` |
18+| SDK env vars | `GEMINI_API_KEY` or `GOOGLE_API_KEY` (`GOOGLE_API_KEY` wins if both). Pass `apiKey` explicitly in a BYOK app. |
19+| OpenAI-compat | `https://generativelanguage.googleapis.com/v1beta/openai/` with `Authorization: Bearer <key>`; `reasoning_effort` maps to thinking levels (3.x) or budgets 1024/8192/24576 (2.5); Gemini extras via `extra_body.google.*`. Beta. Not probed. |
20+
21+Docs: https://ai.google.dev/gemini-api/docs/api-key , https://ai.google.dev/gemini-api/docs/api-versions , https://ai.google.dev/gemini-api/docs/openai
22+
23+## 2. SDK
24+
25+```bash
26+pnpm add @google/genai@latest # 2.21.0 on 2026-09-08; Node >= 20 (3.x will require Node 22+)
27+```
28+```ts
29+import { GoogleGenAI } from "@google/genai";
30+const ai = new GoogleGenAI({ apiKey, httpOptions: { timeout: 120_000 /* ms */, apiVersion: "v1beta" } });
31+```
32+- `ai.models.generateContent / generateContentStream / countTokens / list / get`, `ai.chats.create` (client-side history helper), `ai.caches`, `ai.files`, `ai.batches`, `ai.live`, `ai.interactions` (new), `mcpToTool()`.
33+- Errors: `ApiError { name: "ApiError", status: <http>, message: <JSON string of the body> }` — message is the raw `{"error":{code,message,status,details}}` JSON; parse it. Retries: `httpOptions.retryOptions` exists (defaults not documented for JS).
34+- `config.abortSignal` supported on generate calls.
35+- Legacy `@google/generative-ai` is deprecated (since 2025-11-30) — do not use.
36+- SDK-side guard: `toolConfig.functionCallingConfig.streamFunctionCallArguments` throws `"streamFunctionCallArguments parameter is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."` (no partial-args streaming on the Developer API).
37+
38+Docs: https://github.com/googleapis/js-genai , https://ai.google.dev/gemini-api/docs/libraries
39+
40+## 3. generateContent / streamGenerateContent
41+
42+REST: `POST /v1beta/models/{model}:generateContent` and `POST /v1beta/models/{model}:streamGenerateContent?alt=sse`.
43+
44+Request body: `contents[]` (`{role:"user"|"model", parts:[...]}`), `systemInstruction` (`{parts:[{text}]}`), `tools[]`, `toolConfig`, `safetySettings[]`, `generationConfig`, `cachedContent`, `serviceTier`, `store`.
45+Response: `candidates[0].content.parts[]`, `candidates[0].finishReason`, `usageMetadata`, `modelVersion`, `responseId`, `promptFeedback`, `modelStatus`.
46+
47+Part fields seen in probes: `text`, `thought: true` (thought summary), `thoughtSignature` (base64 string, 300–700 chars), `functionCall {name, args, id}`, `functionResponse`, `inlineData {mimeType, data}`, `fileData {fileUri, mimeType}`, `executableCode {language:"PYTHON", code, id}`, `codeExecutionResult {outcome:"OUTCOME_OK", output, id}`.
48+
49+FinishReason enum (SDK 2.21): `STOP, MAX_TOKENS, SAFETY, RECITATION, LANGUAGE, OTHER, BLOCKLIST, PROHIBITED_CONTENT, SPII, MALFORMED_FUNCTION_CALL, IMAGE_SAFETY, UNEXPECTED_TOOL_CALL, TOO_MANY_TOOL_CALLS, IMAGE_PROHIBITED_CONTENT, NO_IMAGE, IMAGE_RECITATION, IMAGE_OTHER`.
50+
51+Docs: https://ai.google.dev/api/generate-content , https://ai.google.dev/gemini-api/docs/text-generation
52+
53+### 3.1 Streaming protocol (verified)
54+
55+- REST with `alt=sse`: `Content-Type: text/event-stream`; each event is `data: {GenerateContentResponse JSON}` terminated by **CRLF CRLF** (`\r\n\r\n`); no `event:` lines, no `[DONE]` sentinel — the stream simply ends. Errors before the first token come back as a normal HTTP error status (400 etc.) but still with `text/event-stream` content type and a JSON `{error}` body — check `res.ok` before parsing SSE.
56+- REST without `alt=sse`: `application/json` **JSON array** of responses (`[{...},{...}]`) streamed incrementally — avoid.
57+- SDK: `for await (const chunk of await ai.models.generateContentStream({...}))`, each chunk is a full `GenerateContentResponse` (`chunk.text` getter concatenates non-thought text).
58+- Chunk shape observed (Gemini 3.x Flash): 2–4 chunks for short answers. With `includeThoughts: true` the **first chunk** carries `parts:[{text:"…", thought:true}]`; then text chunks; the **last chunk** has `finishReason` and typically an **empty text part carrying `thoughtSignature`** (`{text:"", thoughtSignature:"…"}`) — do not render it as text, but keep it if you replay history.
59+- `usageMetadata` is present on **every** chunk. On 3.5/3.6 Flash the first chunk has only `promptTokenCount/totalTokenCount/promptTokensDetails/serviceTier`; subsequent chunks have the full set (`candidatesTokenCount`, `thoughtsTokenCount`). On 3.7 Flash all chunks were full. Rule: **take usage from the last chunk**.
60+- Function calls stream as a single chunk: `parts:[{functionCall:{name,args,id:"call_…"}, thoughtSignature:"…"}]`, followed by a final chunk with an empty `text` part and `finishReason:"STOP"` (not `FUNCTION_CALL`). Args are complete (never partial).
61+
62+### 3.2 usageMetadata fields
63+`promptTokenCount`, `candidatesTokenCount`, `thoughtsTokenCount` (absent when 0), `cachedContentTokenCount` (absent when 0), `toolUsePromptTokenCount`, `totalTokenCount` (= prompt + candidates + thoughts), `promptTokensDetails[{modality:"TEXT"|"IMAGE"|…, tokenCount}]`, `cacheTokensDetails[]`, `candidatesTokensDetails[]`, `serviceTier:"standard"`. Thinking tokens are billed as output.
64+
65+### 3.3 Exact SDK code that worked
66+
67+```ts
68+const stream = await ai.models.generateContentStream({
69+ model: "gemini-3.5-flash-lite",
70+ contents: [{ role: "user", parts: [{ text: "Count from 1 to 12, then say DONE." }] }],
71+ config: {
72+ systemInstruction: "You are terse.",
73+ maxOutputTokens: 2000, // includes thinking tokens!
74+ thinkingConfig: { includeThoughts: true, thinkingLevel: "LOW" }, // never combine with thinkingBudget
75+ },
76+});
77+let usage;
78+for await (const chunk of stream) {
79+ for (const part of chunk.candidates?.[0]?.content?.parts ?? []) {
80+ if (part.thought) emitReasoning(part.text);
81+ else if (part.text) emitText(part.text); // may be "" on the final signature-only part
82+ if (part.functionCall) emitToolCall(part.functionCall.id, part.functionCall.name, part.functionCall.args, part.thoughtSignature);
83+ }
84+ if (chunk.candidates?.[0]?.finishReason) finish = chunk.candidates[0].finishReason;
85+ usage = chunk.usageMetadata ?? usage; // last chunk wins
86+}
87+```
88+
89+## 4. generationConfig parameter support (probed matrix)
90+
91+Probed with `maxOutputTokens: 1500` on the models the free-tier key can call. Legend: OK / 400 "…" = exact server message / — = not probed (quota).
92+
93+| param | 3.8-flash | 3.5-flash | 3.5-flash-lite | 3.1-flash-lite | 3-flash-preview | gemma-4-31b-it |
94+|---|---|---|---|---|---|---|
95+| temperature 0 / 1.5 / 2 | OK | OK | OK | OK | OK | 2 OK; 0,1.5 → 500 INTERNAL (flaky) |
96+| temperature 2.5 | 400 `* GenerateContentRequest.generation_config.temperature: temperature must be in the range [0.0, 2.0].` | same | same | same | same | same |
97+| topP 0.9 | OK | OK | OK | OK | OK | 500 INTERNAL (flaky) |
98+| topK 40 | — | OK | OK | OK | OK | OK |
99+| seed 42 | — | OK | OK | OK | OK | OK |
100+| stopSequences ["DONE"] | — | OK (stopped before DONE) | OK | OK | OK | 500 INTERNAL (flaky) |
101+| frequencyPenalty 0.5 | — | 400 `Penalty is not enabled for this model` | same | same | same | same |
102+| presencePenalty 0.5 | — | 400 `Penalty is not enabled for this model` | same | same | same | same |
103+| candidateCount 2 | 400 `Multiple candidates is not enabled for this model` | same | same | same | same | same |
104+| responseMimeType application/json | — | OK | OK | OK | OK | 500 (flaky) |
105+| responseSchema (OpenAPI, `OBJECT/STRING`) | — | OK | OK | OK | OK | OK |
106+| responseJsonSchema (JSON Schema) | — | OK | OK | OK | OK | OK |
107+| responseMimeType text/x.enum + enum schema | — | OK (`blue`) | OK | OK | OK | OK |
108+| thinkingConfig.thinkingBudget 0 | — | OK (0 thoughts) | 400 `Request contains an invalid argument.` | OK | OK | 400 `Thinking budget is not supported for this model.` |
109+| thinkingBudget 1024 / -1 | — | — | OK / OK | OK / OK | OK / OK (-1 → 1436 thought tokens) | 400 same |
110+| includeThoughts true | — | OK (thought parts) | OK | OK | OK | 500 (flaky) |
111+| thinkingLevel MINIMAL | docs: **error** | — | OK (0 thoughts) | OK (0) | OK (0) | 500 (flaky) |
112+| thinkingLevel LOW / MEDIUM / HIGH | — | — | OK | OK | HIGH, MEDIUM OK; LOW — | 400 `Thinking level is not supported for this model.` (HIGH → 500) |
113+| thinkingLevel + thinkingBudget | — | — | 400 `You can only set only one of thinking budget and thinking level.` | same | same | same |
114+| responseLogprobs/logprobs | 400 `Logprobs is not enabled for this model` | — | same | same | — | same |
115+
116+Notes:
117+- **Sampling deprecation**: changelog 2026-07-21 — "The sampling parameters `temperature`, `top_p` and `top_k` are now deprecated" (for 3.6 Flash / 3.5 Flash-Lite onward; the 3.8 guide says "Strip `temperature`, `top_p`, and `top_k` from generation configs"). They are still **accepted** by `generateContent` (probed) but Google recommends not sending them; Gemini 3 guide: "strongly recommend keeping the temperature parameter at its default value of 1.0" (lower values can cause looping). Adapter: default to not sending temperature/topP/topK for Gemini 3.x unless the user overrides.
118+- Default temperature/topP/topK reported by the models endpoint: 1 / 0.95 / 64 (maxTemperature 2) for all Gemini text models.
119+- `maxOutputTokens` **includes thinking tokens**: `gemini-3.8-flash` with `maxOutputTokens: 100` returned empty text, `finishReason: MAX_TOKENS`, `thoughtsTokenCount: 97`. Give thinking models a generous budget (>= 1024 + expected answer) or disable thinking.
120+- `stopSequences` are honoured but the stop string itself is stripped.
121+
122+## 5. Reasoning controls per family
123+
124+| Family | Default | Controls | Probe evidence |
125+|---|---|---|---|
126+| Gemini 3.8 / 3.7 Flash | `thinkingLevel` **medium** | `low, medium, high`; `minimal` → error (docs). `thinkingBudget` still accepted "for backward compatibility" per Gemini 3 guide but 3.8 guide says replace it. Cannot be disabled. | 3.8: thoughts 199–330 on trivial prompts. |
127+| Gemini 3.6 Flash | medium | `minimal, low, medium, high` | stream has thought part first. |
128+| Gemini 3.5 Flash | medium (docs) | all four levels (docs); `thinkingBudget: 0` **does** disable (probed). | thoughts 136–515 by default. |
129+| Gemini 3.5 Flash-Lite / 3.1 Flash-Lite | **minimal (off)** | all four levels; `thinkingBudget` 1024 / -1 OK; `thinkingBudget: 0` rejected on 3.5-lite (use MINIMAL) but OK on 3.1-lite. | thoughts 0 unless requested. |
130+| Gemini 3 Flash Preview / 3.1 Pro Preview | high (dynamic) | `minimal, low, medium, high`; budgets 0/1024/-1 OK on 3-flash-preview. | |
131+| Gemini 2.5 Pro / Flash / Flash-Lite | on / on / off | `thinkingBudget` (Pro 128–32768 cannot disable; Flash 0–24576; Lite 512–24576; -1 dynamic) + `thinkingLevel` low/medium/high (docs). | **Not callable with new keys (404)** — docs only. |
132+| Gemma 4 | thinks by default | **no control**: both `thinkingBudget` and `thinkingLevel` → 400. | thoughts 47–430. |
133+
134+- `includeThoughts: true` → thought **summaries** as parts with `thought: true` (streamed first). Raw reasoning is never returned.
135+- Thinking tokens: `usageMetadata.thoughtsTokenCount`, billed at the output rate.
136+- SDK enum: `ThinkingLevel.MINIMAL|LOW|MEDIUM|HIGH` (strings `"MINIMAL"`… accepted; Interactions API uses lowercase).
137+
138+Docs: https://ai.google.dev/gemini-api/docs/thinking , https://ai.google.dev/gemini-api/docs/gemini-3 , https://ai.google.dev/gemini-api/docs/latest-model
139+
140+### 5.1 Thought signatures (critical for tool calling)
141+- Gemini 3.x attaches `thoughtSignature` to the **functionCall part** (and to the last text/empty part of a text answer, and to `executableCode` parts).
142+- **Function calling is strict**: replaying the model turn without the signature → 400 `INVALID_ARGUMENT`: `Function call is missing a thought_signature in functionCall parts. This is required for tools to work correctly, and missing thought_signature may lead to degraded model performance. Additional data, function call `default_api:get_weather` , position 2. Please refer to https://ai.google.dev/gemini-api/docs/thought-signatures for more details.` (probed on gemini-3.7-flash).
143+- Echoing the real signature → OK. The documented escape hatch `thoughtSignature: "skip_thought_signature_validator"` on the functionCall part → accepted (probed) — useful when importing history from another provider.
144+- Text-only multi-turn **without** signatures works (probed): signatures on text parts are optional.
145+- Adapter rule: persist `thoughtSignature` alongside each tool call (and ideally each assistant part) in the conversation store and replay it verbatim in `contents`.
146+
147+## 6. Tool calling (function declarations)
148+
149+```ts
150+const tools = [{ functionDeclarations: [{
151+ name: "get_weather", description: "Get weather for a city.",
152+ parametersJsonSchema: { type: "object", properties: { city: { type: "string" } }, required: ["city"] }, // JSON Schema (lowercase types)
153+ // or legacy: parameters: { type: "OBJECT", properties: { city: { type: "STRING" } }, required: ["city"] }
154+}]}];
155+// model turn → parts: [{ functionCall: { name, args, id: "call_88210" }, thoughtSignature }]
156+// reply:
157+contents.push({ role: "model", parts: modelPartsVerbatim }); // keep thoughtSignature!
158+contents.push({ role: "user", parts: [{ functionResponse: { name, id, response: { /* any JSON object */ } } }] });
159+```
160+- `toolConfig.functionCallingConfig`: `mode: AUTO | ANY | NONE | VALIDATED`, `allowedFunctionNames[]`. `ANY` + `allowedFunctionNames` probed OK on 3.6 Flash (forced call).
161+- Parallel calls arrive as multiple `functionCall` parts in one turn; send all `functionResponse` parts in one user turn (same order).
162+- `functionCall.id` is present on 3.x (`call_NNNNN`); echo it in `functionResponse.id`.
163+- Built-in tools **can be combined with function declarations on Gemini 3** (not on 2.5). Structured output + tools also allowed on Gemini 3.
164+- SDK automatic function calling exists (`config.automaticFunctionCalling`) — disable it in a UI adapter (`{ disable: true }`) to keep control of the loop.
165+- MCP: `mcpToTool(client)` in the SDK (experimental) and server-side `tools:[{ mcpServers: [...] }]` (v1beta, docs: HTTP transport only).
166+
167+Docs: https://ai.google.dev/gemini-api/docs/function-calling (now Interactions-only; legacy shapes verified by probe and SDK types)
168+
169+## 7. Structured output / JSON schema
170+- `responseMimeType: "application/json"` alone → valid JSON of free shape (one model returned an array).
171+- `responseJsonSchema` (standard JSON Schema: lowercase types, `additionalProperties`, `anyOf`, `$ref:"#"`, `enum`, `format` date/time, `minimum/maximum`, `items/prefixItems/minItems/maxItems`) → **preferred**; probed OK on all callable models incl. Gemma 4.
172+- `responseSchema` (legacy OpenAPI `Schema` with uppercase `TYPE`s, `propertyOrdering`) → still OK. Don't send both.
173+- `responseMimeType: "text/x.enum"` + `{type:"STRING", enum:[…]}` → bare enum value (probed).
174+- Works together with thinking (JSON is in non-thought parts) and, on Gemini 3, with tools.
175+
176+Docs: https://ai.google.dev/gemini-api/docs/structured-output
177+
178+## 8. Modalities
179+| Modality | How | Limits / notes |
180+|---|---|---|
181+| Image in | `inlineData {mimeType, data(base64)}` or `fileData {fileUri}`; PNG/JPEG/WebP/HEIC/HEIF; inline request total <= 20 MB; up to 3,600 images | Probed 2x2 PNG → `promptTokensDetails IMAGE 1089` tokens on 3.8/3.5 Flash (Gemini 3 default media resolution is high; docs' "258 tokens" applies to older models / low res). Use `mediaResolution` to cut cost. |
182+| PDF | `inlineData application/pdf` or Files API; <= 50 MB, <= 1000 pages, ~258 tokens/page | Not probed. |
183+| Audio in | wav/mp3/aiff/aac/ogg/flac/m4a/opus/webm…; 32 tokens/s; <= 9.5 h/prompt; >20 MB via Files API | Not probed. |
184+| Video in | inline <100 MB, Files API up to 2 GB (free) / 20 GB (paid), YouTube URLs via `fileData.fileUri`; ~100 tok/s low / 300 tok/s high res; 3.5+ have "agentic" video mode | Not probed. |
185+| Audio out | **Not via chat models.** TTS models (`gemini-3.1-flash-tts-preview`, `gemini-2.5-*-preview-tts`) with `responseModalities:["AUDIO"]` + `speechConfig` → `inlineData audio/L16 24 kHz PCM`; 32k context; Live API (`bidiGenerateContent`, WebSocket) for realtime voice. | Not probed. |
186+| Image out | Image models only (`gemini-3.1-flash-image`, `gemini-3.1-flash-lite-image`, `gemini-3-pro-image`, `gemini-2.5-flash-image`), `responseModalities:["TEXT","IMAGE"]`, `imageConfig {aspectRatio, imageSize "512px"/"1K"/"2K"/"4K"}` → `inlineData image/png`; SynthID watermark; priced per image (~$0.045–0.151). | Not probed. |
187+| Video out | `gemini-omni-1.1-flash` / `gemini-omni-flash-preview` (paid tier only), Veo 3.1 via `predictLongRunning`. | Not chat models. |
188+
189+Docs: image-understanding, document-processing, audio, video-understanding, speech-generation, image-generation, files pages under https://ai.google.dev/gemini-api/docs/
190+
191+## 9. Files API
192+`ai.files.upload({file, config:{mimeType}})` → `{uri, mimeType, state}`; poll until `ACTIVE`; reference with `fileData:{fileUri, mimeType}`. 48 h retention, 2 GB/file, 20 GB/project. Use when the request exceeds 20 MB (100 MB for video per newer docs). Not probed.
193+
194+## 10. System instruction
195+`config.systemInstruction` (string or `Content`) — probed OK on 3.5/3.6/3.7/3.8 Flash ("BLUE" uppercase obeyed). Not probed on Gemma 4 (historically Gemma rejected developer instructions on this API; Gemma 4 docs say the system role is now supported — verify before enabling).
196+
197+## 11. Conversation state
198+- `generateContent` is **stateless**: send the full `contents` history each turn (`ai.chats` is a client-side helper only).
199+- Server-side state exists only in the **Interactions API** (`previous_interaction_id`, `store` default true; paid tier retains 55 days, free 1 day). Probed `ai.interactions.create({model, input, generation_config:{thinking_level:"low"}, store:false})` → works with this key; response has `steps[]`, `output_text`, `usage{total_input_tokens,total_output_tokens,total_thought_tokens,total_cached_tokens,total_tool_use_tokens}`. Consider it for a later "Gemini v2" adapter; it lacks Batch, explicit caching and custom safety settings today.
200+
201+## 12. Context caching
202+- **Implicit** caching is on by default for 2.5+ (min 4,096 tokens on 3.x Flash / 3.1 Pro, 2,048 on 2.5); savings show as `usageMetadata.cachedContentTokenCount`; cached input billed at ~10 % (e.g. 3.8 Flash $0.075/M). Put static content first.
203+- **Explicit**: `ai.caches.create({model, config:{contents, systemInstruction, tools, ttl:"300s"|expireTime, displayName}})` → pass `config.cachedContent = cache.name`. Models with `createCachedContent` in `supportedGenerationMethods` (all Gemini text models; not Gemma/omni). Storage $0.50–4.50 /M tokens/hour. Probe on 2.5-flash hit the 404 (model gone); not re-probed.
204+
205+Docs: https://ai.google.dev/gemini-api/docs/caching , https://ai.google.dev/api/caching
206+
207+## 13. Built-in tools
208+- **Google Search grounding**: `tools:[{googleSearch:{}}]`. Response `candidates[0].groundingMetadata { webSearchQueries[], searchEntryPoint{renderedContent: HTML chip — must be displayed per ToS}, groundingChunks[{web:{uri,title}}], groundingSupports[{segment{startIndex,endIndex,text}, groundingChunkIndices[], confidenceScores[]}] }` (docs + SDK types; probe hit 429 on both attempts — **unverified**). Pricing: 3.x — 5,000 free requests/month shared, then $14/1,000; 2.5 — 1,500 free RPD then $35/1,000. Legacy `googleSearchRetrieval` only for 1.5.
209+- **URL context**: `tools:[{urlContext:{}}]`, <= 20 URLs, 34 MB each, `candidates[0].urlContextMetadata`; billed as input tokens.
210+- **Code execution**: `tools:[{codeExecution:{}}]` probed OK on 3.6 Flash → parts `executableCode{language:"PYTHON", code, id}` + `codeExecutionResult{outcome:"OUTCOME_OK", output, id}` (both also carry `thoughtSignature`), then text. 30 s runtime, matplotlib only for plots, billed as tokens.
211+- **File Search** (RAG): stores + `tools:[{fileSearch:{fileSearchStoreNames:[…]}}]`, citations with `media_id`/page numbers; indexing $0.15/M embedding tokens, storage free. Not probed.
212+- **Computer use**: `tools:[{computerUse:{environment:"browser"|"mobile"|"desktop"}}]` on 3.8/3.7/3.5 Flash(-Lite) (preview, documented for Interactions). Not probed.
213+- **Google Maps grounding**, **MCP servers** tool: v1beta. Not probed.
214+
215+## 14. Safety settings
216+`safetySettings:[{category, threshold}]`; categories `HARM_CATEGORY_HARASSMENT | HATE_SPEECH | SEXUALLY_EXPLICIT | DANGEROUS_CONTENT` (+ `CIVIC_INTEGRITY` in SDK enum); thresholds `OFF | BLOCK_NONE | BLOCK_ONLY_HIGH | BLOCK_MEDIUM_AND_ABOVE | BLOCK_LOW_AND_ABOVE`. Default for 2.5/3 models is **OFF**. Blocked prompt → `promptFeedback.blockReason` (`SAFETY|OTHER|BLOCKLIST|PROHIBITED_CONTENT|IMAGE_SAFETY`) with no candidates; blocked answer → `finishReason: SAFETY` + `safetyRatings`. Probe was routed to 2.5-flash-lite (404) — not re-probed. Not supported on the Interactions API.
217+
218+## 15. Rate limits and tiers
219+- Tiers: Free, Tier 1 (billing linked), Tier 2 ($100 spent + 3 days), Tier 3 ($1,000 + 30 days). Dimensions: RPM, TPM (input), RPD (resets midnight Pacific) + rolling 10-minute spend caps ($10/$50/$200). Per-model tables are only shown in AI Studio (`https://aistudio.google.com/rate-limit`), not in docs.
220+- Observed free-tier quotas (from 429 `google.rpc.QuotaFailure` details): `GenerateRequestsPerDayPerProjectPerModel-FreeTier` **quotaValue 20** for `gemini-3.8-flash`; per-minute quota trips after ~5–10 requests; `gemini-3.1-pro*`, `gemini-pro-latest`, `gemini-omni-*` → **limit 0** (paid only). Quotas are **per model**, so parallelising across models is fine.
221+- 429 body includes `details[]`: `google.rpc.Help`, `google.rpc.QuotaFailure{violations[{quotaMetric, quotaId, quotaDimensions{model,location}, quotaValue}]}`, `google.rpc.RetryInfo{retryDelay:"24s"}` → honour `retryDelay`.
222+- 503 `UNAVAILABLE` "This model is currently experiencing high demand…" was frequent on 3.8-flash and gemini-flash-latest (transient; retry with backoff). Gemma 4 returned 500 `INTERNAL` on ~50 % of calls (retry).
223+
224+Docs: https://ai.google.dev/gemini-api/docs/rate-limits
225+
226+## 16. Errors
227+Body: `{"error":{"code":<http>,"message":"…","status":"<grpc status>","details":[…]}}`. Seen:
228+
229+| HTTP | status | Example |
230+|---|---|---|
231+| 400 | INVALID_ARGUMENT | temperature range, `Penalty is not enabled for this model`, `Multiple candidates is not enabled for this model`, `Logprobs is not enabled for this model`, `You can only set only one of thinking budget and thinking level.`, missing thought_signature, `Request contains an invalid argument.` |
232+| 401 | UNAUTHENTICATED | invalid key: `Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential…`, `details[0].reason: "ACCESS_TOKEN_TYPE_UNSUPPORTED"`. (Docs list 400 `API_KEY_INVALID` for malformed keys — with `AQ.`-style bogus key we got 401.) |
233+| 403 | PERMISSION_DENIED | key lacks permission / wrong project (docs) |
234+| 404 | NOT_FOUND | unknown model: `models/gemini-9-ultra is not found for API version v1beta, or is not supported for generateContent. Call ModelService.ListModels…`; **retired-for-new-users**: `This model models/gemini-2.5-flash is no longer available to new users. Please update your code to use models/gemini-3.6-flash for the latest features and improvements. We recommend you to use the Interactions API.` |
235+| 429 | RESOURCE_EXHAUSTED | quota (see §15) |
236+| 500 | INTERNAL | `Internal error encountered.` (Gemma 4, transient) |
237+| 503 | UNAVAILABLE | high demand |
238+| 504 | DEADLINE_EXCEEDED | docs |
239+
240+Retry: exponential backoff with jitter on 429/500/503/504 (and network), honour `RetryInfo.retryDelay`; never retry 400/401/403/404. Streaming errors mid-stream: SDK throws from the iterator. Timeouts: set `httpOptions.timeout` (ms); long outputs with thinking can take >60 s — use 120 s+ for streaming.
241+
242+Docs: https://ai.google.dev/gemini-api/docs/troubleshooting , https://ai.google.dev/gemini-api/docs/api-errors (now describes Interactions snake_case codes)
243+
244+## 17. Token counting
245+`ai.models.countTokens({model, contents})` → `{totalTokens}` (free, no quota cost documented). REST `:countTokens` with `generateContentRequest{contents, systemInstruction, tools}` counts everything (probed: 11 tokens text-only → 51 with system + tool) and returns `promptTokensDetails`. Rules of thumb: ~4 chars/token; image 258 tokens (<=384 px) or per 768 px tile — but Gemini 3 high res gave 1,089 for a tiny PNG; audio 32 tok/s; video ~100–300 tok/s.
246+
247+## 18. Model listing
248+`GET /v1beta/models?pageSize=1000` (paginated via `nextPageToken`; SDK `ai.models.list()` / `ai.models.get({model})`). 54 models on 2026-09-08. Fields: `name`, `version`, `displayName`, `description`, `inputTokenLimit`, `outputTokenLimit`, `supportedGenerationMethods[]` (SDK renames to `supportedActions`), `temperature`, `maxTemperature`, `topP`, `topK`, `thinking` (boolean). Filter chat models with `supportedGenerationMethods.includes("generateContent")` and exclude by name pattern (`-image`, `-tts`, `lyria`, `veo`, `transcribe`, `live`, `native-audio`, `robotics`, `computer-use`, `deep-research`, `antigravity`, `embedding`, `aqa`). **The list includes models the key cannot call** (2.5 family → 404 for new users; paid-only → 429 limit 0), so the picker must tolerate per-model failures.
249+
250+## 19. Pricing (paid tier, USD per 1M tokens; pricing page 2026-09-08)
251+| Model | Input | Cached | Output (incl. thinking) |
252+|---|---|---|---|
253+| 3.8 / 3.7 / 3.6 Flash | 0.75 (1.50 from 2027-01-01) | 0.075 (0.15) | 3.75 (7.50) |
254+| 3.5 Flash | 1.50 | 0.15 | 9.00 |
255+| 3.5 Flash-Lite | 0.30 | 0.03 | 2.50 |
256+| 3.1 Flash-Lite | 0.25 (audio 0.50) | n/a | 1.50 |
257+| 3 Flash Preview | 0.50 (audio 1.00) | n/a | 3.00 |
258+| 3.1 Pro Preview | 2.00 / 4.00 (>200k) | 0.20 / 0.40 | 12.00 / 18.00 |
259+| 2.5 Pro | 1.25 / 2.50 | 0.125 / 0.25 | 10.00 / 15.00 |
260+| 2.5 Flash | 0.30 (audio 1.00) | 0.03 | 2.50 |
261+| 2.5 Flash-Lite | 0.10 (audio 0.30) | 0.01 | 0.40 |
262+| Omni Flash | 1.50 | n/a | 9.00 text / 17.50 video |
263+| Gemma 4 | free (free tier only; "Not available" on paid) | | |
264+Batch = 50 % off; priority tier = 1.8x; cache storage $0.50–4.50 /M/h; Search grounding see §13. Free tier: prompts may be used for product improvement.
265+
266+Docs: https://ai.google.dev/gemini-api/docs/pricing
267+
268+## 20. Lifecycle, aliases, deprecations
269+- Stable ids don't change (`gemini-3.6-flash`); previews get >= 2 weeks' notice; `-latest` aliases are hot-swapped with a 2-week email notice: `gemini-flash-latest` → 3.5 Flash (changelog), `gemini-flash-lite-latest` → 3.5 Flash-Lite (probed), `gemini-pro-latest` → 3.1 Pro (quota dimension).
270+- Shut down: all `gemini-2.0-*` (2026-06-01), `gemini-3.1-flash-lite-preview` (2026-05-25; the id still answers as 3.1-flash-lite), 2.5 previews. **Gemini 2.5 Pro/Flash/Flash-Lite are closed to new users** (404) though still listed and priced.
271+- Preview shutdown windows are 3–9 months. Legacy JS SDK deprecated 2025-11-30. Standard API keys rejected after Sept 2026.
272+
273+Docs: https://ai.google.dev/gemini-api/docs/deprecations , https://ai.google.dev/gemini-api/docs/changelog , https://ai.google.dev/gemini-api/docs/models
274+
275+## 21. Probe results summary
276+
277+| Probe | 3.8-flash | 3.7-flash | 3.6-flash | 3.5-flash | 3.5-flash-lite | 3.1-flash-lite | 3-flash-preview | gemma-4-31b-it | 3.1-pro-preview | 2.5-flash / 2.5-pro | omni-1.1-flash |
278+|---|---|---|---|---|---|---|---|---|---|---|---|
279+| generateContent + systemInstruction | OK | OK | OK | OK | OK (no sysinstr) | OK (no sysinstr) | OK (no sysinstr) | OK (no sysinstr) | 429 limit 0 | 404 gone | 429 limit 0 |
280+| stream (chunk shape, usage) | 503 then quota | OK 3 chunks, usage full each | OK 4 chunks | OK 3 chunks | — | — | — | — | — | 404 | — |
281+| params matrix | partial (RPD 20) | — | — | most | full | full | most | full (flaky 500s) | — | 404 | — |
282+| function call stream + round trip | 503/429 | OK (+signature tests) | OK | OK | OK | OK | — | — | — | 404 | — |
283+| responseJsonSchema | — | — | OK | OK | OK | OK | OK | OK | — | 404 | — |
284+| vision (inline PNG) | OK 1089 img tokens | — | — | OK | — | — | — | — | 429 | 404 | 429 |
285+| googleSearch grounding | 429 | — | 429 | — | — | — | — | — | — | 404 | — |
286+| codeExecution | 429 | — | OK | — | — | — | — | — | — | — | — |
287+| invalid key | 401 UNAUTHENTICATED (REST + SDK) | | | | | | | | | | |
288+| countTokens / models.get / v1 apiVersion / interactions.create | OK / OK / OK / OK | | | | | | | | | | |
289+
290+Not probed (docs only): audio/video/PDF input, Files API, explicit caching, safety settings behaviour, TTS/image output, Live API, File Search, computer use, MCP, Batch, 3.1 Pro & omni anything (paid tier), 2.5 anything (closed to new users).
291+
292+## 22. Gotchas for the adapter (checklist)
293+1. Use `x-goog-api-key`, never Bearer. Expect 401 (not 400/403) for bad keys.
294+2. Filter the model list by `generateContent` + name patterns, and **probe-or-handle 404 "no longer available to new users"** (2.5 family) and 429 "limit: 0" (paid-only) gracefully — hide or badge those models.
295+3. Gemini 3.x: prefer `thinkingLevel` (uppercase enum in SDK), never send both level and budget, `MINIMAL` errors on 3.7/3.8, Gemma rejects both. Map PolyLLM "reasoning effort" → level; "off" → `MINIMAL` on lite/3.5-flash-lite, `thinkingBudget: 0` on 3.5 Flash / 3.1-lite / 3-flash-preview, and "not disableable" on 3.6+/Pro.
296+4. `maxOutputTokens` includes thoughts — floor it (e.g. >= 2048) when thinking is on, or you get empty text with `MAX_TOKENS`.
297+5. Store and replay `thoughtSignature` on tool-call parts (400 otherwise); `skip_thought_signature_validator` is the documented escape hatch. Strip empty signature-only text parts from the UI but keep them in history.
298+6. Usage: read `usageMetadata` from the last chunk; thoughts = `thoughtsTokenCount`, cache hits = `cachedContentTokenCount`.
299+7. Penalties, `candidateCount > 1`, logprobs → 400 on every model: don't expose them for Gemini. Temperature/topP/topK are accepted but deprecated for 3.6+; don't send by default.
300+8. SSE events are CRLF-delimited `data:` lines with no terminator; HTTP error status can arrive with `text/event-stream` content type.
301+9. Quotas are per model; free tier is tiny (20 RPD on 3.8-flash) — surface `RetryInfo.retryDelay` to the user.
302+10. Consider a future switch to the Interactions API (server-side state, unified steps); today `generateContent` is stable and complete for chat.
added docs/provider-research/gemini.models.json +231 −0
@@ -0,0 +1,231 @@
1+[
2+ {
3+ "id": "gemini-3.8-flash",
4+ "displayName": "Gemini 3.8 Flash",
5+ "family": "gemini-3.x-flash",
6+ "contextTokens": 1048576,
7+ "maxOutputTokens": 65536,
8+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
9+ "parameters": { "temperature": "0-2 (accepted; Google recommends leaving 1.0; deprecated for 3.6+ per changelog 2026-07-21)", "topP": true, "topK": true, "maxTokens": true, "reasoningEffort": ["low", "medium", "high"], "thinkingBudget": "docs: legacy, replace with thinkingLevel; not probed (free-tier RPD=20 exhausted)", "stop": true, "seed": true, "frequencyPenalty": false, "presencePenalty": false },
10+ "pricing": { "inputPerMillion": 0.75, "cachedInputPerMillion": 0.075, "outputPerMillion": 3.75, "note": "introductory through 2026-12-31; from 2027-01-01: 1.50 / 0.15 / 7.50. >200k-token prompts not tiered." },
11+ "status": "active",
12+ "notes": "Stable, released 2026-09-02. Probed: generateContent+systemInstruction OK, vision OK (2x2 PNG = 1089 image tokens), temperature 0/1.5/2 OK, candidateCount=2 -> 400, logprobs -> 400. Default thinkingLevel medium; 'minimal' returns an error (docs). Free tier: 20 requests/day (quotaValue=20 seen in 429). Thinking tokens count against maxOutputTokens (maxOutputTokens=100 gave empty text, finishReason MAX_TOKENS, 97 thought tokens)."
13+ },
14+ {
15+ "id": "gemini-3.7-flash",
16+ "displayName": "Gemini 3.7 Flash",
17+ "family": "gemini-3.x-flash",
18+ "contextTokens": 1048576,
19+ "maxOutputTokens": 65536,
20+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
21+ "parameters": { "temperature": "0-2 (deprecated, keep 1.0)", "topP": true, "topK": true, "maxTokens": true, "reasoningEffort": ["low", "medium", "high"], "thinkingBudget": "docs-only: legacy", "stop": "docs-only", "seed": "docs-only", "frequencyPenalty": false, "presencePenalty": false },
22+ "pricing": { "inputPerMillion": 0.75, "cachedInputPerMillion": 0.075, "outputPerMillion": 3.75, "note": "same as 3.8 Flash: introductory through 2026-12-31, then 1.50 / 0.15 / 7.50" },
23+ "status": "active",
24+ "notes": "Stable, Aug 2026. Probed: generateContent+systemInstruction OK; stream 3 chunks with full usageMetadata on every chunk; function call round trip OK; thought signature on functionCall part is MANDATORY (400 'Function call is missing a thought_signature in functionCall parts...' when omitted; dummy 'skip_thought_signature_validator' accepted); text-only multi-turn without signatures OK. Param matrix not probed (family assumed = 3.8)."
25+ },
26+ {
27+ "id": "gemini-3.6-flash",
28+ "displayName": "Gemini 3.6 Flash",
29+ "family": "gemini-3.x-flash",
30+ "contextTokens": 1048576,
31+ "maxOutputTokens": 65536,
32+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
33+ "parameters": { "temperature": "0-2 (deprecated per changelog 2026-07-21, keep 1.0)", "topP": "deprecated", "topK": "deprecated", "maxTokens": true, "reasoningEffort": ["minimal", "low", "medium", "high"], "thinkingBudget": "docs-only: legacy", "stop": "docs-only", "seed": "docs-only", "frequencyPenalty": false, "presencePenalty": false },
34+ "pricing": { "inputPerMillion": 0.75, "cachedInputPerMillion": 0.075, "outputPerMillion": 3.75, "note": "same as 3.8 Flash: introductory through 2026-12-31, then 1.50 / 0.15 / 7.50" },
35+ "status": "active",
36+ "status_note": "Google's recommended replacement for gemini-2.5-flash (404 message).",
37+ "notes": "Stable, July 2026. Probed: generateContent OK; stream 4 chunks (thought summary chunk first when includeThoughts, last chunk = empty text part carrying thoughtSignature + finishReason STOP); function call streaming (1 chunk with functionCall+thoughtSignature+id, then final empty chunk) and round trip OK; responseJsonSchema OK; codeExecution tool OK (executableCode{language:'PYTHON',code,id} + codeExecutionResult{outcome:'OUTCOME_OK',output,id}); googleSearch probe hit 429 (unverified). Param matrix not probed."
38+ },
39+ {
40+ "id": "gemini-3.5-flash",
41+ "displayName": "Gemini 3.5 Flash",
42+ "family": "gemini-3.x-flash",
43+ "contextTokens": 1048576,
44+ "maxOutputTokens": 65536,
45+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
46+ "parameters": { "temperature": "0-2 probed OK (2.5 -> 400)", "topP": true, "topK": true, "maxTokens": true, "reasoningEffort": "docs: minimal/low/medium/high (default medium); levels not probed (429)", "thinkingBudget": "0 probed OK (disables thinking); 1024/-1 not probed (429)", "stop": true, "seed": true, "frequencyPenalty": false, "presencePenalty": false },
47+ "pricing": { "inputPerMillion": 1.5, "cachedInputPerMillion": 0.15, "outputPerMillion": 9.0 },
48+ "status": "active",
49+ "notes": "GA May 2026; current target of gemini-flash-latest per changelog. Probed: systemInstruction OK, stream 3 chunks (first chunk usage has only promptTokenCount; later chunks full), includeThoughts -> parts with thought:true, function call streaming + round trip OK (functionCall has id 'call_...'), responseMimeType json / responseSchema / responseJsonSchema / text/x.enum OK, penalties -> 400 'Penalty is not enabled for this model', candidateCount=2 -> 400, vision OK. Free tier RPD low (~20)."
50+ },
51+ {
52+ "id": "gemini-3.5-flash-lite",
53+ "displayName": "Gemini 3.5 Flash-Lite",
54+ "family": "gemini-3.x-flash-lite",
55+ "contextTokens": 1048576,
56+ "maxOutputTokens": 65536,
57+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
58+ "parameters": { "temperature": "0-2 probed OK (deprecated per changelog 2026-07-21)", "topP": true, "topK": true, "maxTokens": true, "reasoningEffort": ["minimal", "low", "medium", "high"], "thinkingBudget": "1024 and -1 OK; 0 -> 400 'Request contains an invalid argument.' (use thinkingLevel MINIMAL to disable)", "stop": true, "seed": true, "frequencyPenalty": false, "presencePenalty": false },
59+ "pricing": { "inputPerMillion": 0.3, "cachedInputPerMillion": 0.03, "outputPerMillion": 2.5 },
60+ "status": "active",
61+ "notes": "Stable, July 2026; default thinking OFF (thoughtsTokenCount 0 unless thinkingLevel/thinkingBudget set). Full param matrix probed: all thinkingLevel values OK (minimal=0 thoughts), thinkingLevel+thinkingBudget together -> 400 'You can only set only one of thinking budget and thinking level.', penalties/candidateCount/logprobs -> 400. Function calling + responseJsonSchema OK. gemini-flash-lite-latest currently resolves here (modelVersion)."
62+ },
63+ {
64+ "id": "gemini-3.1-flash-lite",
65+ "displayName": "Gemini 3.1 Flash-Lite",
66+ "family": "gemini-3.x-flash-lite",
67+ "contextTokens": 1048576,
68+ "maxOutputTokens": 65536,
69+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
70+ "parameters": { "temperature": "0-2 probed OK", "topP": true, "topK": true, "maxTokens": true, "reasoningEffort": ["minimal", "low", "medium", "high"], "thinkingBudget": "0 / 1024 / -1 all OK", "stop": true, "seed": true, "frequencyPenalty": false, "presencePenalty": false },
71+ "pricing": { "inputPerMillion": 0.25, "cachedInputPerMillion": null, "outputPerMillion": 1.5, "note": "audio input 0.50/M; cached price not listed on pricing page" },
72+ "status": "active",
73+ "notes": "GA May 2026; default thinkingLevel minimal (thinking off). Full param matrix probed: same acceptance pattern as 3.5-flash-lite except thinkingBudget 0 is accepted. Function calling + responseJsonSchema OK. gemini-3.1-flash-lite-preview alias still answers and reports modelVersion gemini-3.1-flash-lite (changelog says preview shut down 2026-05-25)."
74+ },
75+ {
76+ "id": "gemini-3-flash-preview",
77+ "displayName": "Gemini 3 Flash Preview",
78+ "family": "gemini-3.x-flash",
79+ "contextTokens": 1048576,
80+ "maxOutputTokens": 65536,
81+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
82+ "parameters": { "temperature": "0-2 probed OK", "topP": true, "topK": true, "maxTokens": true, "reasoningEffort": ["minimal", "low", "medium", "high"], "thinkingBudget": "0 / 1024 / -1 all OK (-1 produced 1436 thought tokens)", "stop": true, "seed": true, "frequencyPenalty": false, "presencePenalty": false },
83+ "pricing": { "inputPerMillion": 0.5, "cachedInputPerMillion": null, "outputPerMillion": 3.0, "note": "audio input 1.00/M" },
84+ "status": "preview",
85+ "notes": "Dec 2025 preview; superseded by gemini-3.5-flash (stable). Default thinking high (dynamic). Param matrix probed except thinkingLevel low / logprobs (429). No shutdown date published."
86+ },
87+ {
88+ "id": "gemini-3.1-pro-preview",
89+ "displayName": "Gemini 3.1 Pro Preview",
90+ "family": "gemini-3.x-pro",
91+ "contextTokens": 1048576,
92+ "maxOutputTokens": 65536,
93+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
94+ "parameters": { "temperature": "0-2 (2.5 -> 400 probed; keep 1.0)", "topP": "docs-only", "topK": "docs-only", "maxTokens": true, "reasoningEffort": ["minimal", "low", "medium", "high"], "thinkingBudget": "docs-only: legacy", "stop": "docs-only", "seed": "docs-only", "frequencyPenalty": "docs-only (family pattern: rejected)", "presencePenalty": "docs-only (family pattern: rejected)" },
95+ "pricing": { "inputPerMillion": 2.0, "cachedInputPerMillion": 0.2, "outputPerMillion": 12.0, "note": ">200k prompt: 4.00 in / 0.40 cached / 18.00 out; storage 4.50/M/hr" },
96+ "status": "preview",
97+ "notes": "PAID TIER ONLY: free-tier quota is 0 (429 RESOURCE_EXHAUSTED 'limit: 0', quotaId GenerateRequestsPerDayPerProjectPerModel-FreeTier). Not probed beyond that. Default thinkingLevel high. gemini-pro-latest currently resolves here (also 429 limit 0 on free tier). Google's recommended replacement for gemini-2.5-pro."
98+ },
99+ {
100+ "id": "gemini-3.1-pro-preview-customtools",
101+ "displayName": "Gemini 3.1 Pro Preview (custom tools)",
102+ "family": "gemini-3.x-pro",
103+ "contextTokens": 1048576,
104+ "maxOutputTokens": 65536,
105+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
106+ "parameters": { "temperature": "0-2", "topP": "docs-only", "topK": "docs-only", "maxTokens": true, "reasoningEffort": ["low", "medium", "high"], "thinkingBudget": "docs-only", "stop": "docs-only", "seed": "docs-only", "frequencyPenalty": false, "presencePenalty": false },
107+ "pricing": { "inputPerMillion": 2.0, "cachedInputPerMillion": 0.2, "outputPerMillion": 12.0, "note": "assumed same as gemini-3.1-pro-preview (not separately listed)" },
108+ "status": "preview",
109+ "notes": "Variant that prioritises custom (function) tools over built-ins in agentic/bash workflows; 'may see quality fluctuations'. Paid tier only (429 limit 0 on free tier). Not probed."
110+ },
111+ {
112+ "id": "gemini-2.5-pro",
113+ "displayName": "Gemini 2.5 Pro",
114+ "family": "gemini-2.5",
115+ "contextTokens": 1048576,
116+ "maxOutputTokens": 65536,
117+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
118+ "parameters": { "temperature": "0-2 (2.5 -> 400 probed)", "topP": "docs-only", "topK": "docs-only", "maxTokens": true, "reasoningEffort": "docs: thinkingLevel low/medium/high accepted; OpenAI-compat maps minimal/low=1024, medium=8192, high=24576 budget", "thinkingBudget": "docs-only: 128-32768, cannot be disabled (-1 dynamic)", "stop": "docs-only", "seed": "docs-only", "frequencyPenalty": "docs-only", "presencePenalty": "docs-only" },
119+ "pricing": { "inputPerMillion": 1.25, "cachedInputPerMillion": 0.125, "outputPerMillion": 10.0, "note": ">200k prompt: 2.50 / 0.25 / 15.00; paid tier only" },
120+ "status": "deprecated",
121+ "notes": "LISTED by /v1beta/models but generateContent returns 404 NOT_FOUND: 'This model models/gemini-2.5-pro is no longer available to new users. Please update your code to use models/gemini-3.1-pro-preview ... We recommend you to use the Interactions API.' Only pre-existing users can call it. Knowledge cutoff Jan 2025. Treat as legacy/hidden in a BYOK app unless the user's key is grandfathered (detect via 404 message)."
122+ },
123+ {
124+ "id": "gemini-2.5-flash",
125+ "displayName": "Gemini 2.5 Flash",
126+ "family": "gemini-2.5",
127+ "contextTokens": 1048576,
128+ "maxOutputTokens": 65536,
129+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
130+ "parameters": { "temperature": "0-2 (2.5 -> 400 probed)", "topP": "docs-only", "topK": "docs-only", "maxTokens": true, "reasoningEffort": "docs: low/medium/high", "thinkingBudget": "docs-only: 0 (off) to 24576, -1 dynamic", "stop": "docs-only", "seed": "docs-only", "frequencyPenalty": "docs-only", "presencePenalty": "docs-only" },
131+ "pricing": { "inputPerMillion": 0.3, "cachedInputPerMillion": 0.03, "outputPerMillion": 2.5, "note": "audio input 1.00/M, cached audio 0.10/M" },
132+ "status": "deprecated",
133+ "notes": "LISTED by /v1beta/models but generateContent, streamGenerateContent, cachedContents.create all return 404 'no longer available to new users' -> use gemini-3.6-flash. Only grandfathered keys can use it. Knowledge cutoff Jan 2025."
134+ },
135+ {
136+ "id": "gemini-2.5-flash-lite",
137+ "displayName": "Gemini 2.5 Flash-Lite",
138+ "family": "gemini-2.5",
139+ "contextTokens": 1048576,
140+ "maxOutputTokens": 65536,
141+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
142+ "parameters": { "temperature": "0-2", "topP": "docs-only", "topK": "docs-only", "maxTokens": true, "reasoningEffort": "docs: low/medium/high (default off)", "thinkingBudget": "docs-only: 512-24576, 0 off", "stop": "docs-only", "seed": "docs-only", "frequencyPenalty": "docs-only", "presencePenalty": "docs-only" },
143+ "pricing": { "inputPerMillion": 0.1, "cachedInputPerMillion": 0.01, "outputPerMillion": 0.4, "note": "audio input 0.30/M" },
144+ "status": "deprecated",
145+ "notes": "LISTED but 404 'no longer available to new users' -> use gemini-3.5-flash-lite (probed via chats + safetySettings probes)."
146+ },
147+ {
148+ "id": "gemini-flash-latest",
149+ "displayName": "Gemini Flash (latest alias)",
150+ "family": "alias",
151+ "contextTokens": 1048576,
152+ "maxOutputTokens": 65536,
153+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
154+ "parameters": { "temperature": "0-2", "topP": true, "topK": true, "maxTokens": true, "reasoningEffort": ["minimal", "low", "medium", "high"], "thinkingBudget": "legacy", "stop": true, "seed": true, "frequencyPenalty": false, "presencePenalty": false },
155+ "pricing": { "inputPerMillion": 1.5, "cachedInputPerMillion": 0.15, "outputPerMillion": 9.0, "note": "billed as the model it resolves to (currently gemini-3.5-flash per changelog May 2026); not listed on pricing page" },
156+ "status": "active",
157+ "notes": "Hot-swapped alias; Google gives 2 weeks' email notice before re-pointing. Probe returned 503 'high demand' (transient) so resolution not confirmed live; changelog says gemini-3.5-flash. Avoid as default in a registry: pin explicit ids and show alias as convenience."
158+ },
159+ {
160+ "id": "gemini-flash-lite-latest",
161+ "displayName": "Gemini Flash-Lite (latest alias)",
162+ "family": "alias",
163+ "contextTokens": 1048576,
164+ "maxOutputTokens": 65536,
165+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
166+ "parameters": { "temperature": "0-2", "topP": true, "topK": true, "maxTokens": true, "reasoningEffort": ["minimal", "low", "medium", "high"], "thinkingBudget": "1024/-1 OK, 0 rejected (as 3.5-flash-lite)", "stop": true, "seed": true, "frequencyPenalty": false, "presencePenalty": false },
167+ "pricing": { "inputPerMillion": 0.3, "cachedInputPerMillion": 0.03, "outputPerMillion": 2.5, "note": "billed as gemini-3.5-flash-lite (probe modelVersion = gemini-3.5-flash-lite)" },
168+ "status": "active",
169+ "notes": "Probed: resolves to gemini-3.5-flash-lite (modelVersion). Used for the raw REST SSE probe (works)."
170+ },
171+ {
172+ "id": "gemini-pro-latest",
173+ "displayName": "Gemini Pro (latest alias)",
174+ "family": "alias",
175+ "contextTokens": 1048576,
176+ "maxOutputTokens": 65536,
177+ "capabilities": { "text": true, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": true, "structuredOutput": true, "streaming": true, "files": true, "webSearch": true },
178+ "parameters": { "temperature": "0-2", "topP": "docs-only", "topK": "docs-only", "maxTokens": true, "reasoningEffort": ["low", "medium", "high"], "thinkingBudget": "legacy", "stop": "docs-only", "seed": "docs-only", "frequencyPenalty": false, "presencePenalty": false },
179+ "pricing": { "inputPerMillion": 2.0, "cachedInputPerMillion": 0.2, "outputPerMillion": 12.0, "note": "billed as the resolved model (429 quota dimension showed model=gemini-3.1-pro -> resolves to 3.1 Pro preview)" },
180+ "status": "active",
181+ "notes": "Paid tier only (free-tier 429 limit 0, quota dimension model=gemini-3.1-pro)."
182+ },
183+ {
184+ "id": "gemma-4-31b-it",
185+ "displayName": "Gemma 4 31B (instruction-tuned)",
186+ "family": "gemma-4",
187+ "contextTokens": 262144,
188+ "maxOutputTokens": 32768,
189+ "capabilities": { "text": true, "vision": "docs: image/video/audio input supported by Gemma 4; not probed on the API", "audioInput": null, "audioOutput": false, "imageGeneration": false, "video": null, "reasoning": true, "tools": "docs: yes; not probed", "structuredOutput": true, "streaming": true, "files": null, "webSearch": false },
190+ "parameters": { "temperature": "0-2 accepted (2 probed OK; 0/1.5 hit transient 500s)", "topP": "probed: 500 INTERNAL x2 (transient?)", "topK": true, "maxTokens": true, "reasoningEffort": false, "thinkingBudget": false, "stop": "probed: 500 INTERNAL x2 (transient?)", "seed": true, "frequencyPenalty": false, "presencePenalty": false },
191+ "pricing": { "inputPerMillion": 0, "cachedInputPerMillion": null, "outputPerMillion": 0, "note": "Free tier: 'Free of charge' (data used for product improvement). Paid tier: 'Not available'." },
192+ "status": "active",
193+ "notes": "Open model served on Gemini API. Thinks by default (thoughtsTokenCount 47-430) but thinkingConfig is rejected: thinkingBudget -> 400 'Thinking budget is not supported for this model.'; thinkingLevel -> 400 'Thinking level is not supported for this model.' responseSchema / responseJsonSchema / text/x.enum OK. ~50% of probe requests returned 500 INTERNAL 'Internal error encountered.' (flaky; retry). systemInstruction not probed. No createCachedContent / batch support (supportedGenerationMethods = generateContent, countTokens)."
194+ },
195+ {
196+ "id": "gemma-4-26b-a4b-it",
197+ "displayName": "Gemma 4 26B A4B (MoE, instruction-tuned)",
198+ "family": "gemma-4",
199+ "contextTokens": 262144,
200+ "maxOutputTokens": 32768,
201+ "capabilities": { "text": true, "vision": null, "audioInput": null, "audioOutput": false, "imageGeneration": false, "video": null, "reasoning": true, "tools": null, "structuredOutput": null, "streaming": true, "files": null, "webSearch": false },
202+ "parameters": { "temperature": "0-2", "topP": null, "topK": null, "maxTokens": true, "reasoningEffort": false, "thinkingBudget": false, "stop": null, "seed": null, "frequencyPenalty": false, "presencePenalty": false },
203+ "pricing": { "inputPerMillion": 0, "cachedInputPerMillion": null, "outputPerMillion": 0, "note": "free tier only" },
204+ "status": "active",
205+ "notes": "Probed once: 'pong' OK with 58 thought tokens. Assume same behaviour as gemma-4-31b-it (unknowns = null)."
206+ },
207+ {
208+ "id": "gemini-omni-1.1-flash",
209+ "displayName": "Gemini Omni 1.1 Flash",
210+ "family": "gemini-omni",
211+ "contextTokens": 131072,
212+ "maxOutputTokens": 65536,
213+ "capabilities": { "text": "docs: text output priced (9.00/M) but model card says output = video only", "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": null, "structuredOutput": null, "streaming": null, "files": null, "webSearch": false },
214+ "parameters": { "temperature": "0-2 (2.5 -> 400 probed)", "topP": null, "topK": null, "maxTokens": true, "reasoningEffort": null, "thinkingBudget": null, "stop": null, "seed": null, "frequencyPenalty": null, "presencePenalty": null },
215+ "pricing": { "inputPerMillion": 1.5, "cachedInputPerMillion": null, "outputPerMillion": 9.0, "note": "video output 17.50/M (~0.10/s); paid tier only" },
216+ "status": "active",
217+ "notes": "Video-generation model (GA Aug 2026; 3-10 s clips, 360p-4K). Models endpoint says inputTokenLimit 131072 (model card says 1,048,576 — endpoint value preferred). PAID TIER ONLY: free tier 429 'limit: 0'. Not usable for chat; exclude from the chat model picker or gate behind paid-tier detection."
218+ },
219+ {
220+ "id": "gemini-omni-flash-preview",
221+ "displayName": "Gemini Omni Flash Preview",
222+ "family": "gemini-omni",
223+ "contextTokens": 131072,
224+ "maxOutputTokens": 65536,
225+ "capabilities": { "text": null, "vision": true, "audioInput": true, "audioOutput": false, "imageGeneration": false, "video": true, "reasoning": true, "tools": null, "structuredOutput": null, "streaming": null, "files": null, "webSearch": false },
226+ "parameters": { "temperature": "0-2", "topP": null, "topK": null, "maxTokens": true, "reasoningEffort": null, "thinkingBudget": null, "stop": null, "seed": null, "frequencyPenalty": null, "presencePenalty": null },
227+ "pricing": { "inputPerMillion": 1.5, "cachedInputPerMillion": null, "outputPerMillion": 9.0, "note": "video output 17.50/M; paid tier only" },
228+ "status": "preview",
229+ "notes": "Preview predecessor of gemini-omni-1.1-flash (June 2026). Free tier 429 'limit: 0'. Not a chat model."
230+ }
231+]
added docs/provider-research/openai.md +390 −0
@@ -0,0 +1,390 @@
1+# OpenAI provider audit for PolyLLM
2+
3+Last documentation audit: 2026-09-08
4+SDK probed: `openai@7.10.0` (npm), Node 25.9.0, `tsx` 4.23.13. Probe scripts and raw results: `research/openai/` (`results/*.json`, no secrets).
5+Model registry produced from this audit: `docs/provider-research/openai.models.json` (84 entries).
6+
7+> Docs moved: every `platform.openai.com/docs/...` URL now 301-redirects to `https://developers.openai.com/api/docs/...`. The API reference pages there render only partially through a headless fetch (the "create response" and "streaming events" pages surfaced only the cancel endpoint), so event names, enums and parameter lists below were cross-checked against the SDK type definitions (`node_modules/openai/resources/responses/responses.d.ts`, `shared.d.ts`) and against live probes. Where docs and probes disagree, the probe wins and the disagreement is called out.
8+
9+---
10+
11+## 1. Endpoint, auth, headers
12+
13+| Item | Value |
14+|---|---|
15+| Base URL | `https://api.openai.com/v1/` (docs also mention data-residency endpoints in the SDK 7.6 release notes; not needed for BYOK) |
16+| Auth | `Authorization: Bearer <OPENAI_API_KEY>` |
17+| Optional headers | `OpenAI-Organization: org_...`, `OpenAI-Project: proj_...` (billing scope), `X-Client-Request-Id` (ASCII, <= 512 chars), `OpenAI-Safety-Identifier` (Realtime only; for HTTP use the `safety_identifier` body param) |
18+| Response headers seen | `x-request-id`, `openai-processing-ms`, `openai-version: 2020-10-01`, `openai-organization`, `openai-project`, `x-ratelimit-*` (see section 13) |
19+| Header size limits | total < 64 KiB, single custom header value < 60 KiB |
20+| `OpenAI-Beta` | Not required for Responses, Chat Completions, tools or structured outputs (none sent by SDK 7.x for these). |
21+
22+Source: https://developers.openai.com/api/docs/api-reference/introduction
23+
24+## 2. Which API: Responses vs Chat Completions
25+
26+- **Use the Responses API (`POST /v1/responses`) as the primary adapter.** Docs: "While Chat Completions remains supported, Responses is recommended for all new projects." Chat Completions is *not* labelled legacy/deprecated and has no shutdown date, but:
27+ - Pro models (`gpt-5.5-pro`, `gpt-5.4-pro`, `gpt-5.2-pro`, `gpt-5-pro`, `o3-pro`, `o1-pro`), `gpt-5.3-codex` and `gpt-5.6-cyber` are **Responses-only**.
28+ - Built-in tools (web_search, file_search, code_interpreter, MCP, image_generation, computer use) exist only in Responses (Chat Completions has only `web_search_options` on the `*-search-*` models).
29+ - Reasoning docs: "Reasoning models work better with the Responses API"; GPT-6 Astra page: "Requires Responses API for tool calling (Chat Completions available but limited)".
30+ - Reasoning summaries, encrypted reasoning, `previous_response_id`, `conversation`, background mode, `reasoning.context` are Responses-only.
31+- Chat Completions still works (verified 2026-09-08 on gpt-4.1-mini, gpt-5.5, o4-mini): chunk shape `chat.completion.chunk` with `choices[0].delta`, `usage` only in the final chunk when `stream_options.include_usage: true`; usage fields `prompt_tokens`/`completion_tokens`/`prompt_tokens_details.cached_tokens`/`completion_tokens_details.reasoning_tokens`. `max_tokens` is rejected on new models (`gpt-6-astra`: `400 unsupported_parameter "'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead."`).
32+- The Chat-Completions-only web search models (`gpt-5-search-api`, `gpt-4o-search-preview`, `gpt-4o-mini-search-preview`) return `400 model_not_found "The requested model 'gpt-5-search-api' is not supported with the Responses API."` on Responses. Do not expose them; use the `web_search` tool on a normal model.
33+- Assistants API shut down 2026-08-26 (replaced by Responses + Conversations). `v1/prompts` (reusable prompts), Evals, Agent Builder shut down 2026-11-30.
34+
35+Sources: https://developers.openai.com/api/docs/api-reference/chat , https://developers.openai.com/api/docs/guides/migrate-to-responses , https://developers.openai.com/api/docs/deprecations
36+
37+### Chat Completions -> Responses mapping (for the adapter)
38+
39+| Chat Completions | Responses |
40+|---|---|
41+| `messages` | `input` (string, or array of items: messages `{role, content}` / `function_call` / `function_call_output` / `reasoning` ...) |
42+| `system` message | `instructions` (top-level) or a `developer` (or `system`) role message; all three verified to work |
43+| `max_tokens` / `max_completion_tokens` | `max_output_tokens` (min 16; includes reasoning tokens) |
44+| `response_format` | `text.format` (`{type:"text"}` / `{type:"json_schema", name, schema, strict}` / `{type:"json_object"}`) |
45+| `tools[].function.{name,parameters}` | flattened `tools[] = {type:"function", name, description, parameters, strict}` |
46+| `tool_calls[]` in message | separate `function_call` output items (`call_id`, `name`, `arguments`) |
47+| `role:"tool"` message | `{type:"function_call_output", call_id, output}` input item |
48+| `reasoning_effort`, `verbosity` | `reasoning.effort`, `text.verbosity` |
49+| `usage.prompt_tokens` / `completion_tokens` | `usage.input_tokens` / `output_tokens` (+ `input_tokens_details.cached_tokens`, `cache_write_tokens`, `output_tokens_details.reasoning_tokens`, `total_tokens`) |
50+| `n`, `seed`, `stop`, `logprobs` (bool) | `n` removed; **`seed` and `stop` do not exist** (`400 unknown_parameter`); logprobs via `top_logprobs` + `include:["message.output_text.logprobs"]` |
51+| `stream_options.include_usage` | not needed: `response.completed` carries the full `response.usage` |
52+
53+## 3. Request shape (Responses) - parameters that matter
54+
55+From SDK `ResponseCreateParams` (7.10.0) and probes:
56+
57+`model`, `input`, `instructions`, `max_output_tokens` (>= 16), `reasoning {effort, summary, mode, context}`, `text {format, verbosity}`, `tools`, `tool_choice` (`"auto"|"none"|"required"|{type:"function",name}|{type:"allowed_tools",...}`), `parallel_tool_calls`, `temperature`, `top_p`, `top_logprobs`, `include[]`, `store` (default **true**), `previous_response_id`, `conversation`, `stream`, `stream_options {include_obfuscation}`, `background`, `truncation` (`"auto"|"disabled"`, default disabled), `metadata`, `service_tier` (`auto|default|flex|priority|fast`), `prompt_cache_key`, `prompt_cache_retention` (`in_memory|24h`, pre-5.6), `prompt_cache_options {mode, ttl:"30m"}` (5.6+), `safety_identifier`, `user`, `context_management` (compaction), `moderation`, `prompt`.
58+
59+`include` values: `file_search_call.results`, `web_search_call.results`, `web_search_call.action.sources`, `message.input_image.image_url`, `computer_call_output.output.image_url`, `code_interpreter_call.outputs`, `reasoning.encrypted_content`, `message.output_text.logprobs`.
60+
61+Response object: `id` (`resp_...`), `object:"response"`, `status` (`completed|failed|in_progress|cancelled|queued|incomplete`), `incomplete_details.reason` (`max_output_tokens|max_messages|content_filter|steered`), `error`, `model` (resolved snapshot, e.g. `gpt-5.5-2026-04-23`), `output[]` items, `usage`, plus echoes of `reasoning`, `text`, `temperature`, `top_p`, `truncation`, `store`, `service_tier`, `previous_response_id`, `tools`. The SDK adds a convenience `output_text` getter **only on non-streaming `create()` results** (the `response` object inside a `response.completed` event does not have it - accumulate deltas or read `output[].content[].text`).
62+
63+## 4. Streaming protocol
64+
65+SSE; every event is JSON with `type` and a monotonically increasing `sequence_number` (verified: strictly +1 per event). Text deltas also carry an `obfuscation` padding string (disable via `stream_options.include_obfuscation:false`).
66+
67+Event names observed in probes (exact strings):
68+
69+```
70+response.created > response.in_progress
71+ > response.output_item.added {item:{type:"reasoning"...}} (reasoning models, effort >= low)
72+ > response.reasoning_summary_part.added
73+ > response.reasoning_summary_text.delta {delta} (x N) (only when reasoning.summary is set AND the model emits one)
74+ > response.reasoning_summary_text.done {text}
75+ > response.reasoning_summary_part.done
76+ > response.output_item.done
77+ > response.output_item.added {item:{type:"message", role:"assistant"}}
78+ > response.content_part.added {part:{type:"output_text", text:"", annotations:[]}}
79+ > response.output_text.delta {delta, item_id, output_index, content_index, logprobs, obfuscation} (x N)
80+ > response.output_text.annotation.added {annotation:{type:"url_citation",...}, annotation_index} (web search)
81+ > response.output_text.done {text}
82+ > response.content_part.done
83+ > response.output_item.done
84+> response.completed {response:{...usage}} | response.incomplete | response.failed | error
85+```
86+
87+Function calls (verified on all six models):
88+
89+```
90+response.output_item.added {item:{type:"function_call", id:"fc_...", call_id:"call_...", name, arguments:"", status:"in_progress"}, output_index}
91+response.function_call_arguments.delta {delta, item_id, output_index}
92+response.function_call_arguments.done {arguments:"{...}", item_id}
93+response.output_item.done {item:{type:"function_call", ..., arguments:"{...}", status:"completed"}}
94+response.completed
95+```
96+
97+Web search: `response.web_search_call.in_progress` > `.searching` > `.completed` (item type `web_search_call`).
98+
99+Full list of event types in the SDK (for exhaustive switch statements): `response.created, response.in_progress, response.queued, response.completed, response.incomplete, response.failed, error, response.output_item.added/done, response.content_part.added/done, response.output_text.delta/done, response.output_text.annotation.added, response.refusal.delta/done, response.reasoning_text.delta/done, response.reasoning_summary_part.added/done, response.reasoning_summary_text.delta/done, response.function_call_arguments.delta/done, response.custom_tool_call_input.delta/done, response.web_search_call.in_progress/searching/completed, response.file_search_call.in_progress/searching/completed, response.code_interpreter_call.in_progress/interpreting/completed, response.code_interpreter_call_code.delta/done, response.image_generation_call.in_progress/generating/partial_image/completed, response.mcp_call.in_progress/completed/failed, response.mcp_call_arguments.delta/done, response.mcp_list_tools.in_progress/completed/failed, response.shell_call_command.added/delta/done, response.shell_call_output_content.delta/done, response.audio.delta/done, response.audio.transcript.delta/done, response.steer.*`.
100+
101+Resumable streams: with `background:true, stream:true`, reconnect with `GET /v1/responses/{id}?stream=true&starting_after={sequence_number}`.
102+
103+Sources: https://developers.openai.com/api/docs/guides/streaming-responses , https://developers.openai.com/api/docs/guides/background , SDK types.
104+
105+### Exact SDK streaming code that worked (research/openai/03-stream.ts, 05-tools-stream.ts)
106+
107+```ts
108+import OpenAI from "openai";
109+const client = new OpenAI({ maxRetries: 1, timeout: 180_000 }); // key from OPENAI_API_KEY
110+
111+const stream = await client.responses.create({
112+ model: "gpt-5.5",
113+ input: [{ role: "user", content: "Say hello in five words." }],
114+ reasoning: { effort: "low", summary: "auto" },
115+ max_output_tokens: 200,
116+ stream: true,
117+});
118+let text = "", final: OpenAI.Responses.Response | null = null;
119+for await (const ev of stream) {
120+ switch (ev.type) {
121+ case "response.output_text.delta": text += ev.delta; break;
122+ case "response.reasoning_summary_text.delta": /* show thinking */ break;
123+ case "response.function_call_arguments.delta": /* accumulate by ev.item_id */ break;
124+ case "response.output_item.done": if (ev.item.type === "function_call") { /* ev.item.call_id, name, arguments */ } break;
125+ case "response.completed": case "response.incomplete": final = ev.response; break; // final.usage, final.output
126+ case "error": throw new Error(ev.message);
127+ }
128+}
129+```
130+
131+Tool round trip (stateless): replay `[...previousInput, ...final.output, { type: "function_call_output", call_id, output: JSON.stringify(result) }]`. Replaying the *entire* `output` array (including `reasoning` items) is what the docs require for reasoning models; verified on gpt-5.5, gpt-5.4-mini, gpt-5.6-sol, gpt-6-astra, gpt-4.1-mini. Stateful alternative verified on gpt-5.4-mini: `previous_response_id: final.id, input: [function_call_output]`.
132+
133+## 5. Tool calling format
134+
135+- Definition: `{ type: "function", name, description, parameters: <JSON Schema>, strict: true }` (flattened; `strict` recommended; strict requires `additionalProperties:false` and all properties in `required`).
136+- Output item: `{ id: "fc_...", type: "function_call", status: "completed", call_id: "call_...", name, arguments: "<json string>" }` (verified shape). `call_id` is what you echo back; `id` is the item id.
137+- Result item: `{ type: "function_call_output", call_id, output: string | [content parts for images/files] }` (SDK 7.7 made the `id` optional).
138+- `tool_choice`: `"auto"` (default) | `"none"` | `"required"` | `{type:"function", name}` | `{type:"allowed_tools", mode:"auto"|"required", tools:[...]}`.
139+- `parallel_tool_calls` default true.
140+- Other tool types accepted in `tools[]`: `web_search` (and legacy `web_search_preview`), `file_search`, `code_interpreter`, `image_generation`, `mcp`, `computer` / `computer_use_preview`, `shell`, `local_shell`, `apply_patch`, `custom` (free-form text tool), `namespace` (grouping, `defer_loading`), `tool_search`, `programmatic_tool_calling`.
141+
142+Sources: https://developers.openai.com/api/docs/guides/function-calling , https://developers.openai.com/api/docs/guides/tools
143+
144+## 6. Structured output / JSON schema
145+
146+- `text: { format: { type: "json_schema", name, schema, strict: true } }` - verified on gpt-5.5, gpt-5.4-mini, gpt-5.6-sol, gpt-6-astra, gpt-4.1-mini (parsed `{name:"Marie Curie",age:66,city:"Paris"}`); o4-mini accepted it but ran out of the 200-token budget on reasoning.
147+- Schema subset: root must be `object`; every property in `required`; `additionalProperties:false`; optional fields via `type:["string","null"]`; supports `enum`, `anyOf`, `$ref`/`$defs`, recursion; no `minLength`/`pattern`/`format` etc. Numeric limits (depth/property count/enum size) exist but the page did not expose them - keep schemas modest.
148+- Refusals arrive as a `refusal` content part (`response.refusal.delta/done`) instead of JSON.
149+- `{type:"json_object"}` (JSON mode) is the fallback for gpt-4 / gpt-3.5-turbo which lack structured outputs.
150+- SDK helpers: `zodTextFormat(schema, "name")` + `client.responses.parse(...)` -> `response.output_parsed`.
151+
152+Source: https://developers.openai.com/api/docs/guides/structured-outputs
153+
154+## 7. Reasoning controls
155+
156+- `reasoning.effort` values in the SDK enum: `none | minimal | low | medium | high | xhigh | max`. **Per-model acceptance (verified, exact error strings in section 20):**
157+ - gpt-6-astra: `low, medium, high, xhigh, max` (default `medium`; `none`/`minimal` -> 400)
158+ - gpt-5.6-sol/terra/luna: `none, low, medium, high, xhigh, max` (default `medium`)
159+ - gpt-5.5: `none, low, medium, high, xhigh` (default `medium`)
160+ - gpt-5.4 / 5.4-mini / 5.4-nano, gpt-5.2: `none, low, medium, high, xhigh` (default **`none`** - verified echo)
161+ - gpt-5.1: `none, low, medium, high` (default `none`)
162+ - gpt-5 / 5-mini / 5-nano: `minimal, low, medium, high` (default `medium`; no `none`)
163+ - o3, o4-mini, o3-mini, o1: `low, medium, high` (default `medium`)
164+ - pro models: 5.5-pro `medium|high|xhigh` (default high), 5.4-pro / 5.2-pro `medium|high|xhigh`, gpt-5-pro `high` only
165+ - gpt-4.1 / gpt-4o / chat-latest: `reasoning.effort` -> `400 unsupported_parameter`
166+- `reasoning.summary`: `auto | concise | detailed` (server echoes `detailed` for `auto`). Summary text arrives in `reasoning` items' `summary[]` and via `response.reasoning_summary_*` events; gpt-5.5 and gpt-6-astra returned no summary on a trivial prompt while gpt-5.6-sol and o4-mini did. Never assume a summary will exist. Non-reasoning models silently ignore `summary`.
167+- `reasoning.mode`: `standard | pro` (GPT-5.6; pro replaces the `*-pro` models). Not probed (cost).
168+- `reasoning.context`: `current_turn | all_turns` (`all_turns` is the default on 5.6 and 6; earlier models default `current_turn`). Reasoning persists only within a family.
169+- Reasoning tokens are billed as output and count against `max_output_tokens`; `usage.output_tokens_details.reasoning_tokens` reports them. Docs recommend reserving >= 25k tokens; with tiny caps, o4-mini / gpt-5-nano return `status:"incomplete", incomplete_details.reason:"max_output_tokens"` with an empty message (verified). **Adapter rule: never cap reasoning models below ~1-2k output tokens; treat `incomplete` + empty text as "reasoning exhausted the budget".**
170+- Encrypted reasoning for stateless (store:false) multi-turn: `store:false, include:["reasoning.encrypted_content"]` -> `reasoning` items carry `encrypted_content` (~1.2 kB for a trivial turn); replaying them in the next `input` works (verified on gpt-5.5). `previous_response_id` on a `store:false` response fails: `400 previous_response_not_found`.
171+- GPT-6 Astra: mid-conversation `configuration_update` items to change effort; async tool calling (`async:true`); no `none` effort.
172+
173+Sources: https://developers.openai.com/api/docs/guides/reasoning , https://developers.openai.com/api/docs/guides/latest-model
174+
175+## 8. Sampling parameter support matrix (Responses API, verified 2026-09-08)
176+
177+| Param | gpt-6-astra | gpt-5.6-sol | gpt-5.5 | gpt-5.4-mini (default effort none) | gpt-4.1-mini | o4-mini |
178+|---|---|---|---|---|---|---|
179+| `temperature` | rejected | rejected unless `effort:"none"` (then accepted) | rejected unless `effort:"none"` | accepted | accepted | rejected |
180+| `top_p` | rejected | same as temperature | same | accepted | accepted | rejected |
181+| `frequency_penalty` | rejected | rejected (effort medium) | rejected | accepted | accepted | rejected |
182+| `presence_penalty` | rejected | rejected | rejected | accepted | accepted | rejected |
183+| `seed` | `unknown_parameter` on every model (does not exist in Responses) | | | | | |
184+| `stop` | `unknown_parameter` on every model ("Did you mean 'store'?") | | | | | |
185+| logprobs (`top_logprobs`+include) | rejected (reasoning) | rejected | rejected | accepted (`logprobs[]` on content part) | accepted | rejected |
186+| `reasoning.effort` | low..max | none..max | none..xhigh | none..xhigh | rejected | low..high |
187+| `reasoning.summary` | accepted | accepted | accepted | accepted | ignored (no error) | accepted |
188+| `text.verbosity: "low"` | accepted | accepted | accepted | accepted | rejected (`Supported values are: 'medium'`) | rejected |
189+| `max_output_tokens` | min 16 on all (`integer_below_min_value`) | | | | | |
190+| `truncation:"auto"` | accepted on all | | | | | |
191+| `store:false` + `include:["reasoning.encrypted_content"]` | accepted on all (non-reasoning models just have no reasoning item) | | | | | |
192+| `prompt_cache_key` | accepted on all | | | | | |
193+
194+Default `top_p` echoed by GPT-5.x/6 is `0.98`, by GPT-4.1 `1`. `temperature` default 1. `top_k` does not exist. There is no thinking *budget* parameter (effort only). Chat Completions on gpt-5.5: `temperature:0.3` -> `400 unsupported_value "'temperature' does not support 0.3 with this model. Only the default (1) value is supported."`
195+
196+Practical rule for the adapter: send sampling params only when (model is non-reasoning) or (reasoning-capable model with `reasoning.effort === "none"`); otherwise drop them client-side and show "not supported" in the UI. Never send `seed`/`stop` to Responses.
197+
198+## 9. Roles and instructions
199+
200+Input roles accepted: `user`, `assistant`, `developer`, `system` (both `system` and `developer` verified on gpt-5.5 and gpt-4.1-mini; docs describe `developer` as the canonical name and treat `instructions` as equivalent to a developer message). `instructions` is not inherited through `previous_response_id`; resend it each call. Content parts: `input_text`, `input_image`, `input_file`, (`input_audio` rejected, see 10); assistant output parts: `output_text`, `refusal`.
201+
202+Source: https://developers.openai.com/api/docs/guides/text
203+
204+## 10. Modalities
205+
206+| Modality | Responses API support | Notes |
207+|---|---|---|
208+| Text in/out | yes | |
209+| Image in | yes on every current model except `o3-mini`, `gpt-4`, `gpt-3.5-turbo` | `{type:"input_image", image_url:"data:image/png;base64,..." \| https URL \| file_id, detail:"low"\|"high"\|"auto"\|"original"}`. PNG/JPEG/WEBP/non-animated GIF; <= 512 MB per request, <= 1,500 images, <= 30,000 patches after resize. Tokens ~ `ceil(w/32)*ceil(h/32)` x model multiplier (1.2-2.46). Verified with a 2x2 PNG on all six probe models (31-33 input tokens). |
210+| PDF / file in | yes (vision models) | `{type:"input_file", filename, file_data:"data:application/pdf;base64,..." \| file_id \| file_url}`; <= 50 MB per file and per request; both text and page images are sent (costly). Verified on gpt-5.4-mini (answered `42` from the PDF). |
211+| Image out | via tool only | `tools:[{type:"image_generation"}]` uses `gpt-image-2`; returns base64 in an `image_generation_call` item; events `response.image_generation_call.partial_image`. Not probed. Older gpt-image-1* shut down 2026-10-23 / 2026-12-01. |
212+| Audio in/out | **no** in Responses | probe: `400 invalid_request_error param=input "Audio input is not available."`. Audio chat = Chat Completions with `gpt-audio-1.5` (`input_audio` parts, `modalities:["text","audio"]`) or Realtime (`gpt-realtime-2.1`). TTS: `gpt-4o-mini-tts`; STT: `gpt-transcribe`, `gpt-live-transcribe` (whisper-1/gpt-4o-transcribe shut down 2027-02-26). |
213+| Video | no | Sora 2 / Videos API shut down 2026-09-24. |
214+
215+Sources: https://developers.openai.com/api/docs/guides/images-vision , https://developers.openai.com/api/docs/guides/pdf-files , https://developers.openai.com/api/docs/guides/audio
216+
217+## 11. Context windows, max output, pricing (per 1M tokens, USD, standard tier)
218+
219+| Model | Context | Max output | Input | Cached | Output | Notes |
220+|---|---|---|---|---|---|---|
221+| gpt-6-astra | 1,050,000 | 128,000 | 10 | 1 | 50 | cache write 12.50; >272K input: 2x in / 1.5x out |
222+| gpt-5.6-sol (`gpt-5.6`) | 1,050,000 | 128,000 | 4 | 0.40 | 20 | |
223+| gpt-5.6-terra | 1,050,000 (922K input) | 128,000 | 2 | 0.20 | 12 | |
224+| gpt-5.6-luna | 1,050,000 | 128,000 | 0.20 | 0.02 | 1.20 | |
225+| gpt-5.5 | 1,050,000 | 128,000 | 5 | 0.50 | 30 | >272K: 2x/1.5x |
226+| gpt-5.5-pro | 1,050,000 | 128,000 | 30 | - | 180 | Responses only |
227+| gpt-5.4 | 1,050,000 | 128,000 | 2.50 | 0.25 | 15 | |
228+| gpt-5.4-mini | 400,000 | 128,000 | 0.75 | 0.075 | 4.50 | |
229+| gpt-5.4-nano | 400,000 | 128,000 | 0.20 | 0.02 | 1.25 | |
230+| gpt-5.4-pro | 1,050,000 | 128,000 | 30 | - | 180 | Responses only |
231+| gpt-5.3-codex | 400,000 | 128,000 | 1.75 | 0.175 | 14 | Responses only, coding |
232+| gpt-5.2 | 400,000 | 128,000 | 1.75 | 0.175 | 14 | |
233+| gpt-5.2-pro | 400,000 | 128,000 | 21 | - | 168 | Responses only |
234+| gpt-5.1 | 400,000 | 128,000 | 1.25 | 0.125 | 10 | |
235+| gpt-5 | 400,000 | 128,000 | 1.25 | 0.125 | 10 | snapshot shuts down 2026-12-11 |
236+| gpt-5-mini | 400,000 | 128,000 | 0.25 | 0.025 | 2 | snapshot shuts down 2026-12-11 |
237+| gpt-5-nano | 400,000 | 128,000 | 0.05 | 0.005 | 0.40 | snapshot shuts down 2026-12-11 |
238+| gpt-5-pro | 400,000 | 272,000 | 15 | - | 120 | Responses only |
239+| chat-latest | 400,000 (272K input) | 128,000 | 5 | 0.50 | 30 | ChatGPT Instant, non-reasoning |
240+| gpt-4.1 | 1,047,576 | 32,768 | 2 | 0.50 | 8 | |
241+| gpt-4.1-mini | 1,047,576 | 32,768 | 0.40 | 0.10 | 1.60 | |
242+| gpt-4.1-nano | 1,047,576 | 32,768 | 0.10 | 0.025 | 0.40 | shuts down 2026-10-23 |
243+| gpt-4o | 128,000 | 16,384 | 2.50 | 1.25 | 10 | alias -> 2024-08-06 |
244+| gpt-4o-mini | 128,000 | 16,384 | 0.15 | 0.075 | 0.60 | |
245+| o3 | 200,000 | 100,000 | 2 | 0.50 | 8 | snapshot shuts down 2026-12-11 |
246+| o3-pro | 200,000 | 100,000 | 20 | - | 80 | Responses only |
247+| o4-mini | 200,000 | 100,000 | 1.10 | 0.275 | 4.40 | shuts down 2026-10-23 |
248+| o3-mini | 200,000 | 100,000 | 1.10 | 0.55 | 4.40 | text only; shuts down 2026-10-23 |
249+| o1 | 200,000 | 100,000 | 15 | 7.50 | 60 | shuts down 2026-10-23 |
250+| o1-pro | 200,000 | 100,000 | 150 | - | 600 | shuts down 2026-10-23 |
251+| gpt-4-turbo | 128,000 | 4,096 | 10 | - | 30 | shuts down 2026-10-23 |
252+| gpt-4 | 8,192 | 8,192 | 30 | - | 60 | shuts down 2026-10-23 |
253+| gpt-3.5-turbo | 16,385 | 4,096 | 0.50 | - | 1.50 | shuts down 2026-10-23 |
254+
255+Tiers: Batch and Flex = ~50% of standard; Priority higher; Fast = 2x (not for gpt-6-astra with EU residency). Regional data residency +10% for models released after 2026-03-05. Tools: web search $10 / 1k calls (+ tokens), file search $2.50 / 1k calls + $0.10/GB/day storage (1 GB free), code interpreter $0.03-$1.92 per 20-min session by memory tier, MCP = tokens only. Unknown for this key: `gpt-5-search-api`, `gpt-4o-mini-search-preview`, the dead codex snapshots (set to `null` in the JSON).
256+
257+Sources: per-model pages under https://developers.openai.com/api/docs/models/<id> , https://developers.openai.com/api/docs/pricing
258+
259+## 12. Prompt caching
260+
261+Automatic prefix caching; minimum cacheable prefix 1,024 tokens (GPT-5.6+) / 2,048 (earlier). Reads at the "cached" price (0.1x on 5.6+, 0.5x on gpt-4o/o3-mini/o1); GPT-5.6+ also bill **cache writes at 1.25x** (reported in `usage.input_tokens_details.cache_write_tokens`, present in every usage object we saw). `prompt_cache_key` (routing hint, accepted on every model) ; `prompt_cache_retention: "in_memory" | "24h"` for pre-5.6 models (accepted on gpt-5.5 and even gpt-6-astra, but docs say it is deprecated for 6 -> use `prompt_cache_options: { ttl: "30m" }`, verified accepted on gpt-5.6-sol, echoed `{mode:"implicit", ttl:"30m"}`). `cached_tokens` is exact on 5.6+, rounded to 128 earlier. Cache lifetime 5-10 min (up to 1 h) or 24 h; not shared across orgs.
262+
263+Source: https://developers.openai.com/api/docs/guides/prompt-caching
264+
265+## 13. Rate limits, headers, retries, timeouts
266+
267+- Dimensions: RPM, TPM, RPD, TPD, IPM (+ audio minutes). Tiers Free..Tier 5 by cumulative spend; this key is Tier 5 (headers show 15,000 RPM / 40M TPM on gpt-5.5, 30,000 RPM / 150M TPM on gpt-4.1-mini).
268+- Headers (verified on every 200): `x-ratelimit-limit-requests`, `x-ratelimit-remaining-requests`, `x-ratelimit-reset-requests` (e.g. `4ms`, `6m0s`), `x-ratelimit-limit-tokens`, `x-ratelimit-remaining-tokens`, `x-ratelimit-reset-tokens`; docs also list `x-ratelimit-limit-project-tokens` / `x-ratelimit-remaining-project-tokens` and `Retry-After` (seconds) on 429/503. Also `x-request-id` and `openai-processing-ms`.
269+- 429 codes: `rate_limit_exceeded`, `slow_down` (traffic ramped too fast), `insufficient_quota` / `credit_balance_exhausted`, `organization_spend_limit_exceeded`, `project_spend_limit_exceeded`, `organization_usage_limit_exceeded`. 503 `server_is_overloaded`. Billing/quota 429s must **not** be retried.
270+- Retry guidance: honour `Retry-After` when present, else exponential backoff with jitter; ramp traffic <= +50% per 15 min above 1M TPM. SDK default: `maxRetries: 2`, retries 408/409/429/>=500 and any response with `x-should-retry: true`, honours `retry-after-ms` / `retry-after`, backoff 0.5 s x 2^n capped at 8 s with up to 25% jitter. For a BYOK chat UI use `maxRetries: 1-2` for non-streaming, and do not retry once streaming has begun.
271+- Timeouts: SDK default 10 minutes (`OpenAI.DEFAULT_TIMEOUT = 600000`). Recommend: 60 s connect/first-byte for chat, overall 5-10 min for high/xhigh/max effort, and `background: true` (+ polling / resumable stream) for pro models and anything expected to run > 1-2 min. Docs: streaming is "the single most effective approach" to perceived latency; `service_tier: "priority" | "fast"` buys lower latency at higher price (`flex` accepted on gpt-5.4-mini: slower, cheaper).
272+
273+Sources: https://developers.openai.com/api/docs/guides/rate-limits , https://developers.openai.com/api/docs/guides/error-codes , https://developers.openai.com/api/docs/guides/latency-optimization , SDK `client.js`
274+
275+## 14. Error schema
276+
277+HTTP body: `{ "error": { "message", "type", "param", "code" } }` (raw fetch with a bad key also returned a top-level `"status": 401`). SDK maps to `BadRequestError` (400), `AuthenticationError` (401), `PermissionDeniedError` (403), `NotFoundError` (404), `RateLimitError` (429), `InternalServerError` (>=500), `APIConnectionError`, `APITimeoutError`; each exposes `.status`, `.code`, `.type`, `.param`, `.requestID`, `.headers`, `.error` (raw body).
278+
279+Verified examples:
280+
281+| Case | Status | `type` | `code` | `param` | `message` |
282+|---|---|---|---|---|---|
283+| invalid key | 401 | invalid_request_error | `invalid_api_key` | null | `Incorrect API key provided: sk-inva*****key. You can find your API key at https://platform.openai.com/account/api-keys.` |
284+| unknown model | 404 | invalid_request_error | `model_not_found` | null | ``The model `gpt-does-not-exist` does not exist or you do not have access to it.`` |
285+| CC-only model on Responses | 400 | invalid_request_error | `model_not_found` | model | `The requested model 'gpt-5-search-api' is not supported with the Responses API.` |
286+| wrong type | 400 | invalid_request_error | `invalid_type` | max_output_tokens | `Invalid type for 'max_output_tokens': expected an integer, but got a string instead.` |
287+| below min | 400 | invalid_request_error | `integer_below_min_value` | max_output_tokens | `Invalid 'max_output_tokens': integer below minimum value. Expected a value >= 16, but got 5 instead.` |
288+| unsupported param | 400 | invalid_request_error | **null** | temperature | `Unsupported parameter: 'temperature' is not supported with this model.` |
289+| unsupported param | 400 | invalid_request_error | `unsupported_parameter` | reasoning.effort | `Unsupported parameter: 'reasoning.effort' is not supported with this model.` |
290+| unsupported value | 400 | invalid_request_error | `unsupported_value` | reasoning.effort | `Unsupported value: 'minimal' is not supported with the 'gpt-5.5' model. Supported values are: 'none', 'low', 'medium', 'high', and 'xhigh'.` |
291+| unknown param | 400 | invalid_request_error | `unknown_parameter` | stop | `Unknown parameter: 'stop'. Did you mean 'store'?` |
292+| logprobs on reasoning | 400 | invalid_request_error | `unsupported_parameter` | - | `logprobs are not supported with reasoning models.` |
293+| prev response gone | 400 | invalid_request_error | `previous_response_not_found` | previous_response_id | `Previous response with id 'resp_...' not found.` |
294+| audio in Responses | 400 | invalid_request_error | null | input | `Audio input is not available.` |
295+
296+Note `code` is sometimes null for "Unsupported parameter" errors; match on `param` + message prefix as well. Other documented codes: `context_length_exceeded`, `invalid_service_tier`, `insufficient_quota`, `rate_limit_exceeded`, `slow_down`, `server_is_overloaded`.
297+
298+## 15. Usage reporting and token counting
299+
300+- Every response (and `response.completed`) has `usage: { input_tokens, input_tokens_details: { cached_tokens, cache_write_tokens }, output_tokens, output_tokens_details: { reasoning_tokens }, total_tokens }`. Web search inflates `input_tokens` heavily (4.7k-8.8k for a one-line question) because search results are injected as context and billed as input.
301+- Chat Completions usage: `prompt_tokens`, `completion_tokens`, `total_tokens`, `prompt_tokens_details {cached_tokens, audio_tokens}`, `completion_tokens_details {reasoning_tokens, audio_tokens, accepted_prediction_tokens, rejected_prediction_tokens}`; streaming needs `stream_options: {include_usage: true}` (usage arrives in a final chunk with empty `choices`).
302+- Pre-flight counting: `POST /v1/responses/input_tokens` (`{model, input, instructions?, tools?, conversation?, previous_response_id?}` -> `{object:"response.input_tokens", input_tokens}`); SDK: `client.responses.inputTokens.count(...)`. Client-side: `tiktoken` / `js-tiktoken` with `o200k_base` for gpt-4o and newer (approximation only for images/PDF). Rule of thumb 1 token ~ 4 chars English.
303+- SDK 7.8 added `compute_units` tracking on usage for some tiers (not observed in our responses).
304+
305+Source: https://developers.openai.com/api/docs/api-reference/responses/input-tokens
306+
307+## 16. Model listing
308+
309+`GET /v1/models` (SDK `client.models.list()` auto-paginates) returns `{id, object:"model", created, owned_by, shutdown_date}`. **`shutdown_date` is the only lifecycle signal** (ISO date or null; documented as "The date when the model will shut down, or null if not announced"). No capability, context or pricing metadata is exposed, so a static registry is mandatory (`openai.models.json`). 131 ids were returned for this key on 2026-09-08; 55 carried a `shutdown_date`, several already in the past (see 18). Filtering heuristics for chat models: exclude ids matching `babbage|davinci|instruct|transcribe|tts|whisper|audio|realtime|image|sora|embedding|moderation|search-preview|search-api|deep-research|codex` and anything whose `shutdown_date < today`; keep the rest and look it up in the registry (unknown ids -> show as "unverified").
310+
311+Source: https://developers.openai.com/api/docs/api-reference/models
312+
313+## 17. Aliases
314+
315+- `gpt-5.6` -> `gpt-5.6-sol` (documented; verified `response.model === "gpt-5.6-sol"`; **not** itself listed by `/v1/models`).
316+- `gpt-5.5` -> `gpt-5.5-2026-04-23`; `gpt-5.4` -> `-2026-03-05`; `gpt-5.4-mini`/`-nano` -> `-2026-03-17`; `gpt-5.2` -> `-2025-12-11`; `gpt-5.1` -> `-2025-11-13`; `gpt-5*` -> `-2025-08-07`; `gpt-4.1*` -> `-2025-04-14`; `gpt-4o` -> `-2024-08-06` (not the newest 11-20 snapshot); `gpt-4o-mini` -> `-2024-07-18`; `o3` -> `-2025-04-16`; `o4-mini` -> `-2025-04-16`; `o3-mini` -> `-2025-01-31`; `gpt-4-turbo` -> `-2024-04-09`; `gpt-3.5-turbo` -> `-0125`. `gpt-6-astra`, `gpt-5.6-*`, `gpt-5.3-codex`, `chat-latest` have no dated snapshot (echoed as-is).
317+- `*-chat-latest` aliases (gpt-5 / 5.1 / 5.2 / 5.3) are **dead** (404) although still listed; `chat-latest` is the live ChatGPT-Instant alias.
318+
319+## 18. Lifecycle / deprecations relevant to a chat app
320+
321+| Shutdown | Models | Replacement |
322+|---|---|---|
323+| 2026-07-23 (passed; 404 today) | gpt-5-chat-latest, gpt-5.1-chat-latest, gpt-5-codex, gpt-5.1-codex(-max/-mini), gpt-5.2-codex, o3-deep-research, o4-mini-deep-research, *-search-preview-2025-03-11 snapshots | gpt-6-astra / gpt-5.3-codex |
324+| 2026-08-10 (passed; 404) | gpt-5.2-chat-latest, gpt-5.3-chat-latest | chat-latest / gpt-6-astra |
325+| 2026-08-26 | Assistants API | Responses + Conversations |
326+| 2026-09-24 | sora-2, sora-2-pro, Videos API | - |
327+| 2026-09-28 | gpt-3.5-turbo-1106, gpt-3.5-turbo-instruct, babbage-002, davinci-002 | gpt-5.6-terra |
328+| 2026-10-23 | gpt-3.5-turbo(-0125), gpt-4(-0613), gpt-4-turbo, gpt-4.1-nano, gpt-4o-2024-05-13, gpt-image-1, o1, o1-pro, o3-mini, o4-mini | gpt-5.6-sol / terra / luna (o1-pro -> 5.6-sol `reasoning.mode: pro`) |
329+| 2026-11-30 | v1/prompts, Evals, Agent Builder | - |
330+| 2026-12-01 | gpt-image-1-mini, gpt-image-1.5, chatgpt-image-latest | gpt-image-2 |
331+| 2026-12-11 | gpt-5-2025-08-07, gpt-5-mini-2025-08-07, gpt-5-nano-2025-08-07, gpt-5-pro-2025-10-06, o3-2025-04-16, o3-pro-2025-06-10 (the bare aliases `gpt-5`, `o3` currently have `shutdown_date: null`) | gpt-5.6-sol / terra / luna |
332+| 2027-01-20 / 2027-02-26 | legacy audio/realtime/transcribe models | gpt-audio-1.5, gpt-realtime-2.1, gpt-transcribe |
333+
334+Fine-tuning: closed to new orgs since 2026-05-07; no new jobs at all after 2027-01-06.
335+
336+Source: https://developers.openai.com/api/docs/deprecations + `shutdown_date` from `/v1/models`
337+
338+## 19. Built-in tools, state, safety
339+
340+- **Conversation state**: `store` defaults to **true** (30-day retention, visible in dashboard logs) - set `store:false` for privacy-minded BYOK usage and manage history client-side; then use `include:["reasoning.encrypted_content"]` and replay all output items. `previous_response_id` (verified) and `conversation` (Conversations API, `conv_...`, not subject to 30-day TTL) require `store:true`. Server-side compaction: `context_management:[{type:"compaction", compact_threshold}]`.
341+- **Web search**: `{type:"web_search", search_context_size?:"low"|"medium"|"high", user_location?:{type:"approximate", country, city, region, timezone}, filters?:{allowed_domains[] | blocked_domains[]} (<=100), external_web_access?, search_content_types?:["text","image"], return_token_budget?}` (legacy `web_search_preview` still accepted). Output: `web_search_call` items (`action: {type:"search", queries[], query} | {type:"open_page", url} | {type:"find_in_page"}`) then a `message` whose `output_text` part has `annotations: [{type:"url_citation", start_index, end_index, url, title}]` and inline markdown links with `?utm_source=openai`. Events: `response.web_search_call.{in_progress,searching,completed}`, `response.output_text.annotation.added`. Verified on gpt-4.1-mini and gpt-5.5 (effort low); the gpt-5.5 default-effort attempt at 200 tokens ended with three searches and no message - budget again. Search context capped at 128k. Supported per docs on gpt-6, 5.6, 5.5, 5.4 family, 5.2, 5.1, 5(-mini/-nano), 4.1(-mini), 4o(-mini), o3, o4-mini, chat-latest; not on gpt-4.1-nano, o3-mini, o1, gpt-4, gpt-3.5.
342+- **Code execution**: `{type:"code_interpreter", container: {type:"auto", memory_limit?:"1g"|"4g"|"16g"|"64g", file_ids?} | "cntr_..."}` -> `code_interpreter_call {code, outputs, container_id}`; generated files as `container_file_citation` annotations; 100 RPM/org; events `response.code_interpreter_call*`. Also `shell` (hosted shell), `local_shell`, `apply_patch`, skills.
343+- **File search**: `{type:"file_search", vector_store_ids[], max_num_results?, filters?, ranking_options?}` -> `file_search_call` + `file_citation {file_id, filename, index}` annotations; `include:["file_search_call.results"]`.
344+- **Computer use**: `{type:"computer"}` (new) or `computer_use_preview {display_width, display_height, environment}`; `computer_call` -> reply with `computer_call_output {call_id, output:{type:"computer_screenshot", image_url}}`; docs recommend GPT-6 Astra with code execution instead. Not relevant for PolyLLM v1.
345+- **MCP**: `{type:"mcp", server_label, server_url | connector_id, server_description?, authorization?, headers?, allowed_tools?, require_approval:"never"|"always"|{...}, defer_loading?}` -> `mcp_list_tools`, `mcp_call`, `mcp_approval_request` (answer with `mcp_approval_response {approval_request_id, approve}`); events `response.mcp_call*`, `response.mcp_list_tools*`. Billing = tokens only. 8 first-party connectors (Gmail, Drive, Calendar, Dropbox, Teams, Outlook x2, SharePoint).
346+- **Citations/annotations**: `url_citation`, `file_citation`, `container_file_citation`, `file_path` types on `output_text.annotations[]`; streamed through `response.output_text.annotation.added`.
347+- **Safety**: send `safety_identifier` (hashed user id) on every request; `incomplete_details.reason:"content_filter"` and `refusal` parts must be surfaced; free Moderation API (`omni-moderation-latest`) available; revoke leaked keys immediately. `moderation` request param exists in the SDK types.
348+
349+Sources: https://developers.openai.com/api/docs/guides/conversation-state , https://developers.openai.com/api/docs/guides/tools-web-search , https://developers.openai.com/api/docs/guides/tools-code-interpreter , https://developers.openai.com/api/docs/guides/tools-file-search , https://developers.openai.com/api/docs/guides/tools-computer-use , https://developers.openai.com/api/docs/guides/tools-remote-mcp , https://developers.openai.com/api/docs/guides/safety-best-practices
350+
351+## 20. Probe results (2026-09-08, key = Tier 5 project key)
352+
353+Legend: OK = completed with expected output; INC = accepted but `status:"incomplete"` (reasoning consumed the <= 200-token cap); 4xx = rejected with the quoted message.
354+
355+| Probe | gpt-5.5 | gpt-5.4-mini | gpt-5.6-sol | gpt-6-astra | gpt-4.1-mini | o4-mini |
356+|---|---|---|---|---|---|---|
357+| (a) basic Responses, 200 tok | OK (`gpt-5.5-2026-04-23`, 12 reasoning tok) | OK (0 reasoning) | OK (0 reasoning) | OK (0 reasoning) | OK | OK (64 reasoning) |
358+| (b) streaming events | OK, reasoning item but no summary events | OK | OK, `reasoning_summary_*` events seen | OK, no summary events | OK | INC: summary events, then `response.incomplete` |
359+| (c) temperature / top_p | 400 `Unsupported parameter: 'temperature' is not supported with this model.` (OK with `effort:"none"`) | OK (echo 0.5) | 400 same (OK with `effort:"none"`) | 400 same; `effort:"none"` itself rejected | OK | 400 same |
360+| (c) frequency/presence_penalty | 400 `Unsupported parameter: 'frequency_penalty' is not supported with this model.` | OK | 400 | 400 | OK | 400 |
361+| (c) seed | 400 `unknown_parameter` `Unknown parameter: 'seed'.` (all models) | | | | | |
362+| (c) stop | 400 `unknown_parameter` `Unknown parameter: 'stop'. Did you mean 'store'?` (all models) | | | | | |
363+| (c) logprobs | 400 `logprobs are not supported with reasoning models.` | OK | 400 | 400 | OK | 400 |
364+| (c) effort none | OK | OK | OK | 400 `Unsupported value: 'none' is not supported with the 'gpt-6-astra' model. Supported values are: 'low', 'medium', 'high', 'xhigh', and 'max'.` | 400 `Unsupported parameter: 'reasoning.effort' is not supported with this model.` | 400 `Supported values are: 'low', 'medium', and 'high'.` |
365+| (c) effort minimal | 400 `... Supported values are: 'none', 'low', 'medium', 'high', and 'xhigh'.` | 400 same | 400 `... 'none', 'low', 'medium', 'high', 'xhigh', and 'max'.` | 400 | 400 | 400 |
366+| (c) effort low/medium/high | OK | OK | OK | OK | 400 | OK |
367+| (c) effort xhigh | OK | OK | OK | OK | 400 | 400 |
368+| (c) effort max | 400 | 400 | OK | OK | 400 | 400 |
369+| (c) reasoning.summary auto | OK (echo `detailed`) | OK | OK | OK | OK (ignored) | OK |
370+| (c) text.verbosity low | OK | OK | OK | OK | 400 `Unsupported value: 'low' is not supported with the 'gpt-4.1-mini' model. Supported values are: 'medium'.` | 400 same wording |
371+| (c) max_output_tokens 5 | 400 `integer_below_min_value` `Expected a value >= 16, but got 5 instead.` (all) | | | | | |
372+| (c) truncation auto, prompt_cache_key, store:false+encrypted | OK on all six | | | | | |
373+| (d) function call, streaming | OK: `function_call` item, args `{"city":"Paris","unit":"c"}`, round trip -> "18°C and cloudy" | OK (+ `previous_response_id` variant OK) | OK | OK | OK | INC (192 reasoning tokens, no call) |
374+| (e) json_schema strict | OK parsed | OK | OK | OK | OK | INC |
375+| (f) vision 2x2 PNG | INC at default effort; OK with `effort:"none"` | OK | INC default; OK with `effort:"none"` | OK (`effort:"low"`, detail high) | OK | INC (even at `effort:"low"`) |
376+| (h) web_search tool | OK with `effort:"low"`: `web_search_call` + `url_citation` annotation; default effort at 200 tok: 3 searches, no message | OK (3 searches + message, no citation) | not probed | not probed | OK with citation | not probed |
377+| (i) Chat Completions | `temperature:0.3` -> 400 `Only the default (1) value is supported`; `reasoning_effort`+`verbosity` OK | - | - | `max_tokens` -> 400 `Use 'max_completion_tokens' instead.` | OK streaming, usage in last chunk | OK streaming |
378+| (g) invalid key | 401 `invalid_api_key` (`AuthenticationError`) - see section 14 | | | | | |
379+
380+Other probes: `gpt-5.6` alias OK; 26-model sweep OK except `gpt-5.3-chat-latest` (404); `gpt-5-nano` INC at default effort; `o1` INC at 32 tokens; `gpt-5.5-pro` OK (7.3 s, "pong"); `gpt-4.1-nano`, `gpt-4-turbo`, `gpt-3.5-turbo`, `o3-mini` still answer despite announced shutdowns; `gpt-5-search-api` works only via `chat.completions`; PDF input OK on gpt-5.4-mini; `previous_response_id` OK (remembered "7"); `service_tier:"flex"` OK; `input_audio` -> 400 `Audio input is not available.`; `prompt_cache_options.ttl:"30m"` OK on gpt-5.6-sol.
381+
382+## 21. Adapter recommendations (summary)
383+
384+1. Responses API only; Chat Completions merely as an optional legacy toggle (needed for `gpt-audio-*`, `*-search-*`).
385+2. Registry-driven parameter gating: sampling params allowed iff model is non-reasoning or `effort === "none"`; never send `seed`/`stop`; `max_output_tokens >= 16` and default it high (>= 4k) for reasoning models; effort dropdown filtered per model (`reasoningEfforts` in the JSON).
386+3. Stream handler keyed on `event.type`; treat `response.incomplete` as a normal terminal event (show partial text + "reasoning exhausted budget" hint when `reason === "max_output_tokens"` and no text).
387+4. Default `store:false` + `include:["reasoning.encrypted_content"]`, replay full `output` items each turn; offer `previous_response_id` mode only when the user opts into server-side storage.
388+5. Persist `usage` (incl. `cached_tokens`, `cache_write_tokens`, `reasoning_tokens`) per message and price with the registry table; web-search turns cost 5-9k input tokens.
389+6. Model list = `GET /v1/models` filtered by regex + `shutdown_date`, then joined with `openai.models.json`; show shutdown badges for dates < 90 days away.
390+7. Errors: map on `status` + `code` + `param`; `code` can be null for "Unsupported parameter" - fall back to message prefix; never retry 401/400/quota-429.
added docs/provider-research/openai.models.json +4472 −0
@@ -0,0 +1,4472 @@
1+[
2+ {
3+ "id": "chat-latest",
4+ "displayName": "ChatGPT Instant (chat-latest)",
5+ "family": "chat-latest",
6+ "contextTokens": 400000,
7+ "maxOutputTokens": 128000,
8+ "capabilities": {
9+ "text": true,
10+ "vision": true,
11+ "audioInput": false,
12+ "audioOutput": false,
13+ "imageGeneration": true,
14+ "video": false,
15+ "reasoning": false,
16+ "tools": true,
17+ "structuredOutput": true,
18+ "streaming": true,
19+ "files": true,
20+ "webSearch": true
21+ },
22+ "parameters": {
23+ "temperature": null,
24+ "topP": null,
25+ "topK": "unsupported",
26+ "maxTokens": "supported",
27+ "reasoningEffort": "unsupported",
28+ "thinkingBudget": "unsupported",
29+ "stop": "conditional",
30+ "seed": "conditional",
31+ "frequencyPenalty": null,
32+ "presencePenalty": null,
33+ "verbosity": "supported"
34+ },
35+ "pricing": {
36+ "inputPerMillion": 5,
37+ "cachedInputPerMillion": 0.5,
38+ "outputPerMillion": 30
39+ },
40+ "status": "active",
41+ "notes": "Latest ChatGPT Instant model; non-reasoning (probe echoed reasoning.effort medium but 0 reasoning tokens). Max input 272,000. No Batch. Docs recommend GPT-6 Astra for production. Sampling params not probed. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
42+ "reasoningEfforts": null,
43+ "defaultReasoningEffort": null,
44+ "apis": [
45+ "responses",
46+ "chat"
47+ ],
48+ "knowledgeCutoff": "2025-08-31",
49+ "shutdownDate": null,
50+ "snapshotOf": null
51+ },
52+ {
53+ "id": "gpt-3.5-turbo",
54+ "displayName": "GPT-3.5 Turbo",
55+ "family": "gpt-3.5",
56+ "contextTokens": 16385,
57+ "maxOutputTokens": 4096,
58+ "capabilities": {
59+ "text": true,
60+ "vision": false,
61+ "audioInput": false,
62+ "audioOutput": false,
63+ "imageGeneration": false,
64+ "video": false,
65+ "reasoning": false,
66+ "tools": true,
67+ "structuredOutput": false,
68+ "streaming": true,
69+ "files": false,
70+ "webSearch": false
71+ },
72+ "parameters": {
73+ "temperature": "supported",
74+ "topP": "supported",
75+ "topK": "unsupported",
76+ "maxTokens": "supported",
77+ "reasoningEffort": "unsupported",
78+ "thinkingBudget": "unsupported",
79+ "stop": "conditional",
80+ "seed": "conditional",
81+ "frequencyPenalty": "supported",
82+ "presencePenalty": "supported",
83+ "verbosity": "unsupported"
84+ },
85+ "pricing": {
86+ "inputPerMillion": 0.5,
87+ "cachedInputPerMillion": null,
88+ "outputPerMillion": 1.5
89+ },
90+ "status": "deprecated",
91+ "notes": "Alias; currently resolves to gpt-3.5-turbo-0125. shutdown_date (from GET /v1/models): 2026-10-23. Alias -> gpt-3.5-turbo-0125 (verified). shutdown_date 2026-10-23 (-1106 and -instruct: 2026-09-28) -> gpt-5.6-terra. Text only, JSON mode only. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
92+ "reasoningEfforts": null,
93+ "defaultReasoningEffort": null,
94+ "apis": [
95+ "responses",
96+ "chat",
97+ "batch",
98+ "fine-tuning"
99+ ],
100+ "knowledgeCutoff": null,
101+ "shutdownDate": "2026-10-23",
102+ "snapshotOf": null
103+ },
104+ {
105+ "id": "gpt-3.5-turbo-0125",
106+ "displayName": "GPT-3.5 Turbo (0125)",
107+ "family": "gpt-3.5",
108+ "contextTokens": 16385,
109+ "maxOutputTokens": 4096,
110+ "capabilities": {
111+ "text": true,
112+ "vision": false,
113+ "audioInput": false,
114+ "audioOutput": false,
115+ "imageGeneration": false,
116+ "video": false,
117+ "reasoning": false,
118+ "tools": true,
119+ "structuredOutput": false,
120+ "streaming": true,
121+ "files": false,
122+ "webSearch": false
123+ },
124+ "parameters": {
125+ "temperature": "supported",
126+ "topP": "supported",
127+ "topK": "unsupported",
128+ "maxTokens": "supported",
129+ "reasoningEffort": "unsupported",
130+ "thinkingBudget": "unsupported",
131+ "stop": "conditional",
132+ "seed": "conditional",
133+ "frequencyPenalty": "supported",
134+ "presencePenalty": "supported",
135+ "verbosity": "unsupported"
136+ },
137+ "pricing": {
138+ "inputPerMillion": 0.5,
139+ "cachedInputPerMillion": null,
140+ "outputPerMillion": 1.5
141+ },
142+ "status": "deprecated",
143+ "notes": "Dated snapshot of gpt-3.5-turbo. shutdown_date (from GET /v1/models): 2026-10-23. Alias -> gpt-3.5-turbo-0125 (verified). shutdown_date 2026-10-23 (-1106 and -instruct: 2026-09-28) -> gpt-5.6-terra. Text only, JSON mode only. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
144+ "reasoningEfforts": null,
145+ "defaultReasoningEffort": null,
146+ "apis": [
147+ "responses",
148+ "chat",
149+ "batch",
150+ "fine-tuning"
151+ ],
152+ "knowledgeCutoff": null,
153+ "shutdownDate": "2026-10-23",
154+ "snapshotOf": "gpt-3.5-turbo"
155+ },
156+ {
157+ "id": "gpt-3.5-turbo-1106",
158+ "displayName": "GPT-3.5 Turbo (1106)",
159+ "family": "gpt-3.5",
160+ "contextTokens": 16385,
161+ "maxOutputTokens": 4096,
162+ "capabilities": {
163+ "text": true,
164+ "vision": false,
165+ "audioInput": false,
166+ "audioOutput": false,
167+ "imageGeneration": false,
168+ "video": false,
169+ "reasoning": false,
170+ "tools": true,
171+ "structuredOutput": false,
172+ "streaming": true,
173+ "files": false,
174+ "webSearch": false
175+ },
176+ "parameters": {
177+ "temperature": "supported",
178+ "topP": "supported",
179+ "topK": "unsupported",
180+ "maxTokens": "supported",
181+ "reasoningEffort": "unsupported",
182+ "thinkingBudget": "unsupported",
183+ "stop": "conditional",
184+ "seed": "conditional",
185+ "frequencyPenalty": "supported",
186+ "presencePenalty": "supported",
187+ "verbosity": "unsupported"
188+ },
189+ "pricing": {
190+ "inputPerMillion": 0.5,
191+ "cachedInputPerMillion": null,
192+ "outputPerMillion": 1.5
193+ },
194+ "status": "deprecated",
195+ "notes": "Dated snapshot of gpt-3.5-turbo. shutdown_date (from GET /v1/models): 2026-09-28. Alias -> gpt-3.5-turbo-0125 (verified). shutdown_date 2026-10-23 (-1106 and -instruct: 2026-09-28) -> gpt-5.6-terra. Text only, JSON mode only. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
196+ "reasoningEfforts": null,
197+ "defaultReasoningEffort": null,
198+ "apis": [
199+ "responses",
200+ "chat",
201+ "batch",
202+ "fine-tuning"
203+ ],
204+ "knowledgeCutoff": null,
205+ "shutdownDate": "2026-09-28",
206+ "snapshotOf": "gpt-3.5-turbo"
207+ },
208+ {
209+ "id": "gpt-3.5-turbo-16k",
210+ "displayName": "GPT-3.5 Turbo (16k)",
211+ "family": "gpt-3.5",
212+ "contextTokens": 16385,
213+ "maxOutputTokens": 4096,
214+ "capabilities": {
215+ "text": true,
216+ "vision": false,
217+ "audioInput": false,
218+ "audioOutput": false,
219+ "imageGeneration": false,
220+ "video": false,
221+ "reasoning": false,
222+ "tools": true,
223+ "structuredOutput": false,
224+ "streaming": true,
225+ "files": false,
226+ "webSearch": false
227+ },
228+ "parameters": {
229+ "temperature": "supported",
230+ "topP": "supported",
231+ "topK": "unsupported",
232+ "maxTokens": "supported",
233+ "reasoningEffort": "unsupported",
234+ "thinkingBudget": "unsupported",
235+ "stop": "conditional",
236+ "seed": "conditional",
237+ "frequencyPenalty": "supported",
238+ "presencePenalty": "supported",
239+ "verbosity": "unsupported"
240+ },
241+ "pricing": {
242+ "inputPerMillion": 0.5,
243+ "cachedInputPerMillion": null,
244+ "outputPerMillion": 1.5
245+ },
246+ "status": "deprecated",
247+ "notes": "Dated snapshot of gpt-3.5-turbo. Alias -> gpt-3.5-turbo-0125 (verified). shutdown_date 2026-10-23 (-1106 and -instruct: 2026-09-28) -> gpt-5.6-terra. Text only, JSON mode only. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
248+ "reasoningEfforts": null,
249+ "defaultReasoningEffort": null,
250+ "apis": [
251+ "responses",
252+ "chat",
253+ "batch",
254+ "fine-tuning"
255+ ],
256+ "knowledgeCutoff": null,
257+ "shutdownDate": null,
258+ "snapshotOf": "gpt-3.5-turbo"
259+ },
260+ {
261+ "id": "gpt-4",
262+ "displayName": "GPT-4",
263+ "family": "gpt-4",
264+ "contextTokens": 8192,
265+ "maxOutputTokens": 8192,
266+ "capabilities": {
267+ "text": true,
268+ "vision": false,
269+ "audioInput": false,
270+ "audioOutput": false,
271+ "imageGeneration": false,
272+ "video": false,
273+ "reasoning": false,
274+ "tools": true,
275+ "structuredOutput": false,
276+ "streaming": true,
277+ "files": false,
278+ "webSearch": false
279+ },
280+ "parameters": {
281+ "temperature": "supported",
282+ "topP": "supported",
283+ "topK": "unsupported",
284+ "maxTokens": "supported",
285+ "reasoningEffort": "unsupported",
286+ "thinkingBudget": "unsupported",
287+ "stop": "conditional",
288+ "seed": "conditional",
289+ "frequencyPenalty": "supported",
290+ "presencePenalty": "supported",
291+ "verbosity": "unsupported"
292+ },
293+ "pricing": {
294+ "inputPerMillion": 30,
295+ "cachedInputPerMillion": null,
296+ "outputPerMillion": 60
297+ },
298+ "status": "deprecated",
299+ "notes": "shutdown_date (from GET /v1/models): 2026-10-23. shutdown_date 2026-10-23 -> gpt-5.6-sol. Text only, no structured outputs (JSON mode only). Not probed. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
300+ "reasoningEfforts": null,
301+ "defaultReasoningEffort": null,
302+ "apis": [
303+ "responses",
304+ "chat",
305+ "batch",
306+ "assistants",
307+ "fine-tuning"
308+ ],
309+ "knowledgeCutoff": "2023-12-01",
310+ "shutdownDate": "2026-10-23",
311+ "snapshotOf": null
312+ },
313+ {
314+ "id": "gpt-4-0613",
315+ "displayName": "GPT-4 (0613)",
316+ "family": "gpt-4",
317+ "contextTokens": 8192,
318+ "maxOutputTokens": 8192,
319+ "capabilities": {
320+ "text": true,
321+ "vision": false,
322+ "audioInput": false,
323+ "audioOutput": false,
324+ "imageGeneration": false,
325+ "video": false,
326+ "reasoning": false,
327+ "tools": true,
328+ "structuredOutput": false,
329+ "streaming": true,
330+ "files": false,
331+ "webSearch": false
332+ },
333+ "parameters": {
334+ "temperature": "supported",
335+ "topP": "supported",
336+ "topK": "unsupported",
337+ "maxTokens": "supported",
338+ "reasoningEffort": "unsupported",
339+ "thinkingBudget": "unsupported",
340+ "stop": "conditional",
341+ "seed": "conditional",
342+ "frequencyPenalty": "supported",
343+ "presencePenalty": "supported",
344+ "verbosity": "unsupported"
345+ },
346+ "pricing": {
347+ "inputPerMillion": 30,
348+ "cachedInputPerMillion": null,
349+ "outputPerMillion": 60
350+ },
351+ "status": "deprecated",
352+ "notes": "Dated snapshot of gpt-4. shutdown_date (from GET /v1/models): 2026-10-23. shutdown_date 2026-10-23 -> gpt-5.6-sol. Text only, no structured outputs (JSON mode only). Not probed. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
353+ "reasoningEfforts": null,
354+ "defaultReasoningEffort": null,
355+ "apis": [
356+ "responses",
357+ "chat",
358+ "batch",
359+ "assistants",
360+ "fine-tuning"
361+ ],
362+ "knowledgeCutoff": "2023-12-01",
363+ "shutdownDate": "2026-10-23",
364+ "snapshotOf": "gpt-4"
365+ },
366+ {
367+ "id": "gpt-4-turbo",
368+ "displayName": "GPT-4 Turbo",
369+ "family": "gpt-4",
370+ "contextTokens": 128000,
371+ "maxOutputTokens": 4096,
372+ "capabilities": {
373+ "text": true,
374+ "vision": true,
375+ "audioInput": false,
376+ "audioOutput": false,
377+ "imageGeneration": false,
378+ "video": false,
379+ "reasoning": false,
380+ "tools": true,
381+ "structuredOutput": true,
382+ "streaming": true,
383+ "files": null,
384+ "webSearch": false
385+ },
386+ "parameters": {
387+ "temperature": "supported",
388+ "topP": "supported",
389+ "topK": "unsupported",
390+ "maxTokens": "supported",
391+ "reasoningEffort": "unsupported",
392+ "thinkingBudget": "unsupported",
393+ "stop": "conditional",
394+ "seed": "conditional",
395+ "frequencyPenalty": "supported",
396+ "presencePenalty": "supported",
397+ "verbosity": "unsupported"
398+ },
399+ "pricing": {
400+ "inputPerMillion": 10,
401+ "cachedInputPerMillion": null,
402+ "outputPerMillion": 30
403+ },
404+ "status": "deprecated",
405+ "notes": "shutdown_date (from GET /v1/models): 2026-10-23. shutdown_date 2026-10-23 -> gpt-5.6-sol. Still answers (verified). No prompt caching. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
406+ "reasoningEfforts": null,
407+ "defaultReasoningEffort": null,
408+ "apis": [
409+ "responses",
410+ "chat",
411+ "batch",
412+ "assistants"
413+ ],
414+ "knowledgeCutoff": "2023-12-01",
415+ "shutdownDate": "2026-10-23",
416+ "snapshotOf": null
417+ },
418+ {
419+ "id": "gpt-4-turbo-2024-04-09",
420+ "displayName": "GPT-4 Turbo (2024-04-09)",
421+ "family": "gpt-4",
422+ "contextTokens": 128000,
423+ "maxOutputTokens": 4096,
424+ "capabilities": {
425+ "text": true,
426+ "vision": true,
427+ "audioInput": false,
428+ "audioOutput": false,
429+ "imageGeneration": false,
430+ "video": false,
431+ "reasoning": false,
432+ "tools": true,
433+ "structuredOutput": true,
434+ "streaming": true,
435+ "files": null,
436+ "webSearch": false
437+ },
438+ "parameters": {
439+ "temperature": "supported",
440+ "topP": "supported",
441+ "topK": "unsupported",
442+ "maxTokens": "supported",
443+ "reasoningEffort": "unsupported",
444+ "thinkingBudget": "unsupported",
445+ "stop": "conditional",
446+ "seed": "conditional",
447+ "frequencyPenalty": "supported",
448+ "presencePenalty": "supported",
449+ "verbosity": "unsupported"
450+ },
451+ "pricing": {
452+ "inputPerMillion": 10,
453+ "cachedInputPerMillion": null,
454+ "outputPerMillion": 30
455+ },
456+ "status": "deprecated",
457+ "notes": "Dated snapshot of gpt-4-turbo. shutdown_date (from GET /v1/models): 2026-10-23. shutdown_date 2026-10-23 -> gpt-5.6-sol. Still answers (verified). No prompt caching. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
458+ "reasoningEfforts": null,
459+ "defaultReasoningEffort": null,
460+ "apis": [
461+ "responses",
462+ "chat",
463+ "batch",
464+ "assistants"
465+ ],
466+ "knowledgeCutoff": "2023-12-01",
467+ "shutdownDate": "2026-10-23",
468+ "snapshotOf": "gpt-4-turbo"
469+ },
470+ {
471+ "id": "gpt-4.1",
472+ "displayName": "GPT-4.1",
473+ "family": "gpt-4.1",
474+ "contextTokens": 1047576,
475+ "maxOutputTokens": 32768,
476+ "capabilities": {
477+ "text": true,
478+ "vision": true,
479+ "audioInput": false,
480+ "audioOutput": false,
481+ "imageGeneration": true,
482+ "video": false,
483+ "reasoning": false,
484+ "tools": true,
485+ "structuredOutput": true,
486+ "streaming": true,
487+ "files": true,
488+ "webSearch": true
489+ },
490+ "parameters": {
491+ "temperature": "supported",
492+ "topP": "supported",
493+ "topK": "unsupported",
494+ "maxTokens": "supported",
495+ "reasoningEffort": "unsupported",
496+ "thinkingBudget": "unsupported",
497+ "stop": "conditional",
498+ "seed": "conditional",
499+ "frequencyPenalty": "supported",
500+ "presencePenalty": "supported",
501+ "verbosity": "unsupported"
502+ },
503+ "pricing": {
504+ "inputPerMillion": 2,
505+ "cachedInputPerMillion": 0.5,
506+ "outputPerMillion": 8
507+ },
508+ "status": "active",
509+ "notes": "Snapshot gpt-4.1-2025-04-14. Non-reasoning; classic sampling params; text.verbosity only 'medium'. Web search supported. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
510+ "reasoningEfforts": null,
511+ "defaultReasoningEffort": null,
512+ "apis": [
513+ "responses",
514+ "chat",
515+ "batch",
516+ "assistants",
517+ "fine-tuning"
518+ ],
519+ "knowledgeCutoff": "2024-06-01",
520+ "shutdownDate": null,
521+ "snapshotOf": null
522+ },
523+ {
524+ "id": "gpt-4.1-2025-04-14",
525+ "displayName": "GPT-4.1 (2025-04-14)",
526+ "family": "gpt-4.1",
527+ "contextTokens": 1047576,
528+ "maxOutputTokens": 32768,
529+ "capabilities": {
530+ "text": true,
531+ "vision": true,
532+ "audioInput": false,
533+ "audioOutput": false,
534+ "imageGeneration": true,
535+ "video": false,
536+ "reasoning": false,
537+ "tools": true,
538+ "structuredOutput": true,
539+ "streaming": true,
540+ "files": true,
541+ "webSearch": true
542+ },
543+ "parameters": {
544+ "temperature": "supported",
545+ "topP": "supported",
546+ "topK": "unsupported",
547+ "maxTokens": "supported",
548+ "reasoningEffort": "unsupported",
549+ "thinkingBudget": "unsupported",
550+ "stop": "conditional",
551+ "seed": "conditional",
552+ "frequencyPenalty": "supported",
553+ "presencePenalty": "supported",
554+ "verbosity": "unsupported"
555+ },
556+ "pricing": {
557+ "inputPerMillion": 2,
558+ "cachedInputPerMillion": 0.5,
559+ "outputPerMillion": 8
560+ },
561+ "status": "active",
562+ "notes": "Dated snapshot of gpt-4.1. Snapshot gpt-4.1-2025-04-14. Non-reasoning; classic sampling params; text.verbosity only 'medium'. Web search supported. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
563+ "reasoningEfforts": null,
564+ "defaultReasoningEffort": null,
565+ "apis": [
566+ "responses",
567+ "chat",
568+ "batch",
569+ "assistants",
570+ "fine-tuning"
571+ ],
572+ "knowledgeCutoff": "2024-06-01",
573+ "shutdownDate": null,
574+ "snapshotOf": "gpt-4.1"
575+ },
576+ {
577+ "id": "gpt-4.1-mini",
578+ "displayName": "GPT-4.1 mini",
579+ "family": "gpt-4.1",
580+ "contextTokens": 1047576,
581+ "maxOutputTokens": 32768,
582+ "capabilities": {
583+ "text": true,
584+ "vision": true,
585+ "audioInput": false,
586+ "audioOutput": false,
587+ "imageGeneration": true,
588+ "video": false,
589+ "reasoning": false,
590+ "tools": true,
591+ "structuredOutput": true,
592+ "streaming": true,
593+ "files": true,
594+ "webSearch": true
595+ },
596+ "parameters": {
597+ "temperature": "supported",
598+ "topP": "supported",
599+ "topK": "unsupported",
600+ "maxTokens": "supported",
601+ "reasoningEffort": "unsupported",
602+ "thinkingBudget": "unsupported",
603+ "stop": "conditional",
604+ "seed": "conditional",
605+ "frequencyPenalty": "supported",
606+ "presencePenalty": "supported",
607+ "verbosity": "unsupported"
608+ },
609+ "pricing": {
610+ "inputPerMillion": 0.4,
611+ "cachedInputPerMillion": 0.1,
612+ "outputPerMillion": 1.6
613+ },
614+ "status": "active",
615+ "notes": "temperature/top_p/frequency_penalty/presence_penalty/logprobs accepted; reasoning.effort rejected ('Unsupported parameter'); text.verbosity 'low' rejected ('Supported values are: medium'); seed/stop unknown_parameter in Responses (available in Chat Completions). web_search verified with url_citation annotations. Verified by probe: basic, stream, params, tools, structured, vision, web_search, chat completions. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
616+ "reasoningEfforts": null,
617+ "defaultReasoningEffort": null,
618+ "apis": [
619+ "responses",
620+ "chat",
621+ "batch",
622+ "assistants",
623+ "fine-tuning"
624+ ],
625+ "knowledgeCutoff": "2024-06-01",
626+ "shutdownDate": null,
627+ "snapshotOf": null
628+ },
629+ {
630+ "id": "gpt-4.1-mini-2025-04-14",
631+ "displayName": "GPT-4.1 mini (2025-04-14)",
632+ "family": "gpt-4.1",
633+ "contextTokens": 1047576,
634+ "maxOutputTokens": 32768,
635+ "capabilities": {
636+ "text": true,
637+ "vision": true,
638+ "audioInput": false,
639+ "audioOutput": false,
640+ "imageGeneration": true,
641+ "video": false,
642+ "reasoning": false,
643+ "tools": true,
644+ "structuredOutput": true,
645+ "streaming": true,
646+ "files": true,
647+ "webSearch": true
648+ },
649+ "parameters": {
650+ "temperature": "supported",
651+ "topP": "supported",
652+ "topK": "unsupported",
653+ "maxTokens": "supported",
654+ "reasoningEffort": "unsupported",
655+ "thinkingBudget": "unsupported",
656+ "stop": "conditional",
657+ "seed": "conditional",
658+ "frequencyPenalty": "supported",
659+ "presencePenalty": "supported",
660+ "verbosity": "unsupported"
661+ },
662+ "pricing": {
663+ "inputPerMillion": 0.4,
664+ "cachedInputPerMillion": 0.1,
665+ "outputPerMillion": 1.6
666+ },
667+ "status": "active",
668+ "notes": "Dated snapshot of gpt-4.1-mini. temperature/top_p/frequency_penalty/presence_penalty/logprobs accepted; reasoning.effort rejected ('Unsupported parameter'); text.verbosity 'low' rejected ('Supported values are: medium'); seed/stop unknown_parameter in Responses (available in Chat Completions). web_search verified with url_citation annotations. Verified by probe: basic, stream, params, tools, structured, vision, web_search, chat completions. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
669+ "reasoningEfforts": null,
670+ "defaultReasoningEffort": null,
671+ "apis": [
672+ "responses",
673+ "chat",
674+ "batch",
675+ "assistants",
676+ "fine-tuning"
677+ ],
678+ "knowledgeCutoff": "2024-06-01",
679+ "shutdownDate": null,
680+ "snapshotOf": "gpt-4.1-mini"
681+ },
682+ {
683+ "id": "gpt-4.1-nano",
684+ "displayName": "GPT-4.1 nano",
685+ "family": "gpt-4.1",
686+ "contextTokens": 1047576,
687+ "maxOutputTokens": 32768,
688+ "capabilities": {
689+ "text": true,
690+ "vision": true,
691+ "audioInput": false,
692+ "audioOutput": false,
693+ "imageGeneration": true,
694+ "video": false,
695+ "reasoning": false,
696+ "tools": true,
697+ "structuredOutput": true,
698+ "streaming": true,
699+ "files": true,
700+ "webSearch": false
701+ },
702+ "parameters": {
703+ "temperature": "supported",
704+ "topP": "supported",
705+ "topK": "unsupported",
706+ "maxTokens": "supported",
707+ "reasoningEffort": "unsupported",
708+ "thinkingBudget": "unsupported",
709+ "stop": "conditional",
710+ "seed": "conditional",
711+ "frequencyPenalty": "supported",
712+ "presencePenalty": "supported",
713+ "verbosity": "unsupported"
714+ },
715+ "pricing": {
716+ "inputPerMillion": 0.1,
717+ "cachedInputPerMillion": 0.025,
718+ "outputPerMillion": 0.4
719+ },
720+ "status": "deprecated",
721+ "notes": "shutdown_date (from GET /v1/models): 2026-10-23. shutdown_date 2026-10-23 (still answers, verified) -> replacement gpt-5.6-luna. No web_search tool. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
722+ "reasoningEfforts": null,
723+ "defaultReasoningEffort": null,
724+ "apis": [
725+ "responses",
726+ "chat",
727+ "batch",
728+ "assistants",
729+ "fine-tuning"
730+ ],
731+ "knowledgeCutoff": "2024-06-01",
732+ "shutdownDate": "2026-10-23",
733+ "snapshotOf": null
734+ },
735+ {
736+ "id": "gpt-4.1-nano-2025-04-14",
737+ "displayName": "GPT-4.1 nano (2025-04-14)",
738+ "family": "gpt-4.1",
739+ "contextTokens": 1047576,
740+ "maxOutputTokens": 32768,
741+ "capabilities": {
742+ "text": true,
743+ "vision": true,
744+ "audioInput": false,
745+ "audioOutput": false,
746+ "imageGeneration": true,
747+ "video": false,
748+ "reasoning": false,
749+ "tools": true,
750+ "structuredOutput": true,
751+ "streaming": true,
752+ "files": true,
753+ "webSearch": false
754+ },
755+ "parameters": {
756+ "temperature": "supported",
757+ "topP": "supported",
758+ "topK": "unsupported",
759+ "maxTokens": "supported",
760+ "reasoningEffort": "unsupported",
761+ "thinkingBudget": "unsupported",
762+ "stop": "conditional",
763+ "seed": "conditional",
764+ "frequencyPenalty": "supported",
765+ "presencePenalty": "supported",
766+ "verbosity": "unsupported"
767+ },
768+ "pricing": {
769+ "inputPerMillion": 0.1,
770+ "cachedInputPerMillion": 0.025,
771+ "outputPerMillion": 0.4
772+ },
773+ "status": "deprecated",
774+ "notes": "Dated snapshot of gpt-4.1-nano. shutdown_date (from GET /v1/models): 2026-10-23. shutdown_date 2026-10-23 (still answers, verified) -> replacement gpt-5.6-luna. No web_search tool. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
775+ "reasoningEfforts": null,
776+ "defaultReasoningEffort": null,
777+ "apis": [
778+ "responses",
779+ "chat",
780+ "batch",
781+ "assistants",
782+ "fine-tuning"
783+ ],
784+ "knowledgeCutoff": "2024-06-01",
785+ "shutdownDate": "2026-10-23",
786+ "snapshotOf": "gpt-4.1-nano"
787+ },
788+ {
789+ "id": "gpt-4o",
790+ "displayName": "GPT-4o",
791+ "family": "gpt-4o",
792+ "contextTokens": 128000,
793+ "maxOutputTokens": 16384,
794+ "capabilities": {
795+ "text": true,
796+ "vision": true,
797+ "audioInput": false,
798+ "audioOutput": false,
799+ "imageGeneration": true,
800+ "video": false,
801+ "reasoning": false,
802+ "tools": true,
803+ "structuredOutput": true,
804+ "streaming": true,
805+ "files": true,
806+ "webSearch": true
807+ },
808+ "parameters": {
809+ "temperature": "supported",
810+ "topP": "supported",
811+ "topK": "unsupported",
812+ "maxTokens": "supported",
813+ "reasoningEffort": "unsupported",
814+ "thinkingBudget": "unsupported",
815+ "stop": "conditional",
816+ "seed": "conditional",
817+ "frequencyPenalty": "supported",
818+ "presencePenalty": "supported",
819+ "verbosity": "unsupported"
820+ },
821+ "pricing": {
822+ "inputPerMillion": 2.5,
823+ "cachedInputPerMillion": 1.25,
824+ "outputPerMillion": 10
825+ },
826+ "status": "active",
827+ "notes": "Alias; currently resolves to gpt-4o-2024-08-06. Alias resolves to gpt-4o-2024-08-06 (verified). Snapshot 2024-05-13 shuts down 2026-10-23 -> gpt-5.6-sol. Cached input is only 50% (older cache pricing). Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
828+ "reasoningEfforts": null,
829+ "defaultReasoningEffort": null,
830+ "apis": [
831+ "responses",
832+ "chat",
833+ "batch",
834+ "assistants",
835+ "fine-tuning"
836+ ],
837+ "knowledgeCutoff": "2023-10-01",
838+ "shutdownDate": null,
839+ "snapshotOf": null
840+ },
841+ {
842+ "id": "gpt-4o-2024-05-13",
843+ "displayName": "GPT-4o (2024-05-13)",
844+ "family": "gpt-4o",
845+ "contextTokens": 128000,
846+ "maxOutputTokens": 16384,
847+ "capabilities": {
848+ "text": true,
849+ "vision": true,
850+ "audioInput": false,
851+ "audioOutput": false,
852+ "imageGeneration": true,
853+ "video": false,
854+ "reasoning": false,
855+ "tools": true,
856+ "structuredOutput": true,
857+ "streaming": true,
858+ "files": true,
859+ "webSearch": true
860+ },
861+ "parameters": {
862+ "temperature": "supported",
863+ "topP": "supported",
864+ "topK": "unsupported",
865+ "maxTokens": "supported",
866+ "reasoningEffort": "unsupported",
867+ "thinkingBudget": "unsupported",
868+ "stop": "conditional",
869+ "seed": "conditional",
870+ "frequencyPenalty": "supported",
871+ "presencePenalty": "supported",
872+ "verbosity": "unsupported"
873+ },
874+ "pricing": {
875+ "inputPerMillion": 2.5,
876+ "cachedInputPerMillion": 1.25,
877+ "outputPerMillion": 10
878+ },
879+ "status": "deprecated",
880+ "notes": "Dated snapshot of gpt-4o. shutdown_date (from GET /v1/models): 2026-10-23. Alias resolves to gpt-4o-2024-08-06 (verified). Snapshot 2024-05-13 shuts down 2026-10-23 -> gpt-5.6-sol. Cached input is only 50% (older cache pricing). Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
881+ "reasoningEfforts": null,
882+ "defaultReasoningEffort": null,
883+ "apis": [
884+ "responses",
885+ "chat",
886+ "batch",
887+ "assistants",
888+ "fine-tuning"
889+ ],
890+ "knowledgeCutoff": "2023-10-01",
891+ "shutdownDate": "2026-10-23",
892+ "snapshotOf": "gpt-4o"
893+ },
894+ {
895+ "id": "gpt-4o-2024-08-06",
896+ "displayName": "GPT-4o (2024-08-06)",
897+ "family": "gpt-4o",
898+ "contextTokens": 128000,
899+ "maxOutputTokens": 16384,
900+ "capabilities": {
901+ "text": true,
902+ "vision": true,
903+ "audioInput": false,
904+ "audioOutput": false,
905+ "imageGeneration": true,
906+ "video": false,
907+ "reasoning": false,
908+ "tools": true,
909+ "structuredOutput": true,
910+ "streaming": true,
911+ "files": true,
912+ "webSearch": true
913+ },
914+ "parameters": {
915+ "temperature": "supported",
916+ "topP": "supported",
917+ "topK": "unsupported",
918+ "maxTokens": "supported",
919+ "reasoningEffort": "unsupported",
920+ "thinkingBudget": "unsupported",
921+ "stop": "conditional",
922+ "seed": "conditional",
923+ "frequencyPenalty": "supported",
924+ "presencePenalty": "supported",
925+ "verbosity": "unsupported"
926+ },
927+ "pricing": {
928+ "inputPerMillion": 2.5,
929+ "cachedInputPerMillion": 1.25,
930+ "outputPerMillion": 10
931+ },
932+ "status": "active",
933+ "notes": "Dated snapshot of gpt-4o. Alias resolves to gpt-4o-2024-08-06 (verified). Snapshot 2024-05-13 shuts down 2026-10-23 -> gpt-5.6-sol. Cached input is only 50% (older cache pricing). Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
934+ "reasoningEfforts": null,
935+ "defaultReasoningEffort": null,
936+ "apis": [
937+ "responses",
938+ "chat",
939+ "batch",
940+ "assistants",
941+ "fine-tuning"
942+ ],
943+ "knowledgeCutoff": "2023-10-01",
944+ "shutdownDate": null,
945+ "snapshotOf": "gpt-4o"
946+ },
947+ {
948+ "id": "gpt-4o-2024-11-20",
949+ "displayName": "GPT-4o (2024-11-20)",
950+ "family": "gpt-4o",
951+ "contextTokens": 128000,
952+ "maxOutputTokens": 16384,
953+ "capabilities": {
954+ "text": true,
955+ "vision": true,
956+ "audioInput": false,
957+ "audioOutput": false,
958+ "imageGeneration": true,
959+ "video": false,
960+ "reasoning": false,
961+ "tools": true,
962+ "structuredOutput": true,
963+ "streaming": true,
964+ "files": true,
965+ "webSearch": true
966+ },
967+ "parameters": {
968+ "temperature": "supported",
969+ "topP": "supported",
970+ "topK": "unsupported",
971+ "maxTokens": "supported",
972+ "reasoningEffort": "unsupported",
973+ "thinkingBudget": "unsupported",
974+ "stop": "conditional",
975+ "seed": "conditional",
976+ "frequencyPenalty": "supported",
977+ "presencePenalty": "supported",
978+ "verbosity": "unsupported"
979+ },
980+ "pricing": {
981+ "inputPerMillion": 2.5,
982+ "cachedInputPerMillion": 1.25,
983+ "outputPerMillion": 10
984+ },
985+ "status": "active",
986+ "notes": "Dated snapshot of gpt-4o. Alias resolves to gpt-4o-2024-08-06 (verified). Snapshot 2024-05-13 shuts down 2026-10-23 -> gpt-5.6-sol. Cached input is only 50% (older cache pricing). Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
987+ "reasoningEfforts": null,
988+ "defaultReasoningEffort": null,
989+ "apis": [
990+ "responses",
991+ "chat",
992+ "batch",
993+ "assistants",
994+ "fine-tuning"
995+ ],
996+ "knowledgeCutoff": "2023-10-01",
997+ "shutdownDate": null,
998+ "snapshotOf": "gpt-4o"
999+ },
1000+ {
1001+ "id": "gpt-4o-mini",
1002+ "displayName": "GPT-4o mini",
1003+ "family": "gpt-4o",
1004+ "contextTokens": 128000,
1005+ "maxOutputTokens": 16384,
1006+ "capabilities": {
1007+ "text": true,
1008+ "vision": true,
1009+ "audioInput": false,
1010+ "audioOutput": false,
1011+ "imageGeneration": true,
1012+ "video": false,
1013+ "reasoning": false,
1014+ "tools": true,
1015+ "structuredOutput": true,
1016+ "streaming": true,
1017+ "files": true,
1018+ "webSearch": true
1019+ },
1020+ "parameters": {
1021+ "temperature": "supported",
1022+ "topP": "supported",
1023+ "topK": "unsupported",
1024+ "maxTokens": "supported",
1025+ "reasoningEffort": "unsupported",
1026+ "thinkingBudget": "unsupported",
1027+ "stop": "conditional",
1028+ "seed": "conditional",
1029+ "frequencyPenalty": "supported",
1030+ "presencePenalty": "supported",
1031+ "verbosity": "unsupported"
1032+ },
1033+ "pricing": {
1034+ "inputPerMillion": 0.15,
1035+ "cachedInputPerMillion": 0.075,
1036+ "outputPerMillion": 0.6
1037+ },
1038+ "status": "active",
1039+ "notes": "Snapshot gpt-4o-mini-2024-07-18. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1040+ "reasoningEfforts": null,
1041+ "defaultReasoningEffort": null,
1042+ "apis": [
1043+ "responses",
1044+ "chat",
1045+ "batch",
1046+ "assistants",
1047+ "fine-tuning"
1048+ ],
1049+ "knowledgeCutoff": "2023-10-01",
1050+ "shutdownDate": null,
1051+ "snapshotOf": null
1052+ },
1053+ {
1054+ "id": "gpt-4o-mini-2024-07-18",
1055+ "displayName": "GPT-4o mini (2024-07-18)",
1056+ "family": "gpt-4o",
1057+ "contextTokens": 128000,
1058+ "maxOutputTokens": 16384,
1059+ "capabilities": {
1060+ "text": true,
1061+ "vision": true,
1062+ "audioInput": false,
1063+ "audioOutput": false,
1064+ "imageGeneration": true,
1065+ "video": false,
1066+ "reasoning": false,
1067+ "tools": true,
1068+ "structuredOutput": true,
1069+ "streaming": true,
1070+ "files": true,
1071+ "webSearch": true
1072+ },
1073+ "parameters": {
1074+ "temperature": "supported",
1075+ "topP": "supported",
1076+ "topK": "unsupported",
1077+ "maxTokens": "supported",
1078+ "reasoningEffort": "unsupported",
1079+ "thinkingBudget": "unsupported",
1080+ "stop": "conditional",
1081+ "seed": "conditional",
1082+ "frequencyPenalty": "supported",
1083+ "presencePenalty": "supported",
1084+ "verbosity": "unsupported"
1085+ },
1086+ "pricing": {
1087+ "inputPerMillion": 0.15,
1088+ "cachedInputPerMillion": 0.075,
1089+ "outputPerMillion": 0.6
1090+ },
1091+ "status": "active",
1092+ "notes": "Dated snapshot of gpt-4o-mini. Snapshot gpt-4o-mini-2024-07-18. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1093+ "reasoningEfforts": null,
1094+ "defaultReasoningEffort": null,
1095+ "apis": [
1096+ "responses",
1097+ "chat",
1098+ "batch",
1099+ "assistants",
1100+ "fine-tuning"
1101+ ],
1102+ "knowledgeCutoff": "2023-10-01",
1103+ "shutdownDate": null,
1104+ "snapshotOf": "gpt-4o-mini"
1105+ },
1106+ {
1107+ "id": "gpt-4o-mini-search-preview",
1108+ "displayName": "GPT-4o mini Search Preview",
1109+ "family": "gpt-4o",
1110+ "contextTokens": 128000,
1111+ "maxOutputTokens": 16384,
1112+ "capabilities": {
1113+ "text": true,
1114+ "vision": true,
1115+ "audioInput": false,
1116+ "audioOutput": false,
1117+ "imageGeneration": false,
1118+ "video": false,
1119+ "reasoning": false,
1120+ "tools": true,
1121+ "structuredOutput": true,
1122+ "streaming": true,
1123+ "files": true,
1124+ "webSearch": true
1125+ },
1126+ "parameters": {
1127+ "temperature": "supported",
1128+ "topP": "supported",
1129+ "topK": "unsupported",
1130+ "maxTokens": "supported",
1131+ "reasoningEffort": "unsupported",
1132+ "thinkingBudget": "unsupported",
1133+ "stop": "conditional",
1134+ "seed": "conditional",
1135+ "frequencyPenalty": "supported",
1136+ "presencePenalty": "supported",
1137+ "verbosity": "unsupported"
1138+ },
1139+ "pricing": {
1140+ "inputPerMillion": null,
1141+ "cachedInputPerMillion": null,
1142+ "outputPerMillion": null
1143+ },
1144+ "status": "preview",
1145+ "notes": "Chat Completions only (by analogy with gpt-4o-search-preview; not probed). Snapshot shutdown_date 2026-07-23. Pricing page not fetched -> null. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1146+ "reasoningEfforts": null,
1147+ "defaultReasoningEffort": null,
1148+ "apis": [
1149+ "chat"
1150+ ],
1151+ "knowledgeCutoff": null,
1152+ "shutdownDate": null,
1153+ "snapshotOf": null
1154+ },
1155+ {
1156+ "id": "gpt-4o-mini-search-preview-2025-03-11",
1157+ "displayName": "GPT-4o mini Search Preview (2025-03-11)",
1158+ "family": "gpt-4o",
1159+ "contextTokens": 128000,
1160+ "maxOutputTokens": 16384,
1161+ "capabilities": {
1162+ "text": true,
1163+ "vision": true,
1164+ "audioInput": false,
1165+ "audioOutput": false,
1166+ "imageGeneration": false,
1167+ "video": false,
1168+ "reasoning": false,
1169+ "tools": true,
1170+ "structuredOutput": true,
1171+ "streaming": true,
1172+ "files": true,
1173+ "webSearch": true
1174+ },
1175+ "parameters": {
1176+ "temperature": "supported",
1177+ "topP": "supported",
1178+ "topK": "unsupported",
1179+ "maxTokens": "supported",
1180+ "reasoningEffort": "unsupported",
1181+ "thinkingBudget": "unsupported",
1182+ "stop": "conditional",
1183+ "seed": "conditional",
1184+ "frequencyPenalty": "supported",
1185+ "presencePenalty": "supported",
1186+ "verbosity": "unsupported"
1187+ },
1188+ "pricing": {
1189+ "inputPerMillion": null,
1190+ "cachedInputPerMillion": null,
1191+ "outputPerMillion": null
1192+ },
1193+ "status": "deprecated",
1194+ "notes": "Dated snapshot of gpt-4o-mini-search-preview. shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. Chat Completions only (by analogy with gpt-4o-search-preview; not probed). Snapshot shutdown_date 2026-07-23. Pricing page not fetched -> null. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1195+ "reasoningEfforts": null,
1196+ "defaultReasoningEffort": null,
1197+ "apis": [
1198+ "chat"
1199+ ],
1200+ "knowledgeCutoff": null,
1201+ "shutdownDate": "2026-07-23",
1202+ "snapshotOf": "gpt-4o-mini-search-preview"
1203+ },
1204+ {
1205+ "id": "gpt-4o-search-preview",
1206+ "displayName": "GPT-4o Search Preview",
1207+ "family": "gpt-4o",
1208+ "contextTokens": 128000,
1209+ "maxOutputTokens": 16384,
1210+ "capabilities": {
1211+ "text": true,
1212+ "vision": true,
1213+ "audioInput": false,
1214+ "audioOutput": false,
1215+ "imageGeneration": false,
1216+ "video": false,
1217+ "reasoning": false,
1218+ "tools": true,
1219+ "structuredOutput": true,
1220+ "streaming": true,
1221+ "files": true,
1222+ "webSearch": true
1223+ },
1224+ "parameters": {
1225+ "temperature": "supported",
1226+ "topP": "supported",
1227+ "topK": "unsupported",
1228+ "maxTokens": "supported",
1229+ "reasoningEffort": "unsupported",
1230+ "thinkingBudget": "unsupported",
1231+ "stop": "conditional",
1232+ "seed": "conditional",
1233+ "frequencyPenalty": "supported",
1234+ "presencePenalty": "supported",
1235+ "verbosity": "unsupported"
1236+ },
1237+ "pricing": {
1238+ "inputPerMillion": 2.5,
1239+ "cachedInputPerMillion": null,
1240+ "outputPerMillion": 10
1241+ },
1242+ "status": "preview",
1243+ "notes": "Chat Completions only (Responses -> 400 'not supported with the Responses API', verified). Snapshot 2025-03-11 has shutdown_date 2026-07-23. Legacy; use web_search tool instead. Verified by probe: responses -> 400. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1244+ "reasoningEfforts": null,
1245+ "defaultReasoningEffort": null,
1246+ "apis": [
1247+ "chat"
1248+ ],
1249+ "knowledgeCutoff": null,
1250+ "shutdownDate": null,
1251+ "snapshotOf": null
1252+ },
1253+ {
1254+ "id": "gpt-4o-search-preview-2025-03-11",
1255+ "displayName": "GPT-4o Search Preview (2025-03-11)",
1256+ "family": "gpt-4o",
1257+ "contextTokens": 128000,
1258+ "maxOutputTokens": 16384,
1259+ "capabilities": {
1260+ "text": true,
1261+ "vision": true,
1262+ "audioInput": false,
1263+ "audioOutput": false,
1264+ "imageGeneration": false,
1265+ "video": false,
1266+ "reasoning": false,
1267+ "tools": true,
1268+ "structuredOutput": true,
1269+ "streaming": true,
1270+ "files": true,
1271+ "webSearch": true
1272+ },
1273+ "parameters": {
1274+ "temperature": "supported",
1275+ "topP": "supported",
1276+ "topK": "unsupported",
1277+ "maxTokens": "supported",
1278+ "reasoningEffort": "unsupported",
1279+ "thinkingBudget": "unsupported",
1280+ "stop": "conditional",
1281+ "seed": "conditional",
1282+ "frequencyPenalty": "supported",
1283+ "presencePenalty": "supported",
1284+ "verbosity": "unsupported"
1285+ },
1286+ "pricing": {
1287+ "inputPerMillion": 2.5,
1288+ "cachedInputPerMillion": null,
1289+ "outputPerMillion": 10
1290+ },
1291+ "status": "deprecated",
1292+ "notes": "Dated snapshot of gpt-4o-search-preview. shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. Chat Completions only (Responses -> 400 'not supported with the Responses API', verified). Snapshot 2025-03-11 has shutdown_date 2026-07-23. Legacy; use web_search tool instead. Verified by probe: responses -> 400. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1293+ "reasoningEfforts": null,
1294+ "defaultReasoningEffort": null,
1295+ "apis": [
1296+ "chat"
1297+ ],
1298+ "knowledgeCutoff": null,
1299+ "shutdownDate": "2026-07-23",
1300+ "snapshotOf": "gpt-4o-search-preview"
1301+ },
1302+ {
1303+ "id": "gpt-5",
1304+ "displayName": "GPT-5",
1305+ "family": "gpt-5",
1306+ "contextTokens": 400000,
1307+ "maxOutputTokens": 128000,
1308+ "capabilities": {
1309+ "text": true,
1310+ "vision": true,
1311+ "audioInput": false,
1312+ "audioOutput": false,
1313+ "imageGeneration": true,
1314+ "video": false,
1315+ "reasoning": true,
1316+ "tools": true,
1317+ "structuredOutput": true,
1318+ "streaming": true,
1319+ "files": true,
1320+ "webSearch": true
1321+ },
1322+ "parameters": {
1323+ "temperature": "unsupported",
1324+ "topP": "unsupported",
1325+ "topK": "unsupported",
1326+ "maxTokens": "supported",
1327+ "reasoningEffort": "supported",
1328+ "thinkingBudget": "unsupported",
1329+ "stop": "unsupported",
1330+ "seed": "unsupported",
1331+ "frequencyPenalty": "unsupported",
1332+ "presencePenalty": "unsupported",
1333+ "verbosity": "supported"
1334+ },
1335+ "pricing": {
1336+ "inputPerMillion": 1.25,
1337+ "cachedInputPerMillion": 0.125,
1338+ "outputPerMillion": 10
1339+ },
1340+ "status": "active",
1341+ "notes": "Alias still active but snapshot gpt-5-2025-08-07 has shutdown_date 2026-12-11 -> replacement gpt-5.6-sol. Uses 'minimal' (not 'none'); temperature not supported at any effort (docs). Reasoning items appear in output by default. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1342+ "reasoningEfforts": [
1343+ "minimal",
1344+ "low",
1345+ "medium",
1346+ "high"
1347+ ],
1348+ "defaultReasoningEffort": "medium",
1349+ "apis": [
1350+ "responses",
1351+ "chat",
1352+ "batch"
1353+ ],
1354+ "knowledgeCutoff": "2024-09-30",
1355+ "shutdownDate": null,
1356+ "snapshotOf": null
1357+ },
1358+ {
1359+ "id": "gpt-5-2025-08-07",
1360+ "displayName": "GPT-5 (2025-08-07)",
1361+ "family": "gpt-5",
1362+ "contextTokens": 400000,
1363+ "maxOutputTokens": 128000,
1364+ "capabilities": {
1365+ "text": true,
1366+ "vision": true,
1367+ "audioInput": false,
1368+ "audioOutput": false,
1369+ "imageGeneration": true,
1370+ "video": false,
1371+ "reasoning": true,
1372+ "tools": true,
1373+ "structuredOutput": true,
1374+ "streaming": true,
1375+ "files": true,
1376+ "webSearch": true
1377+ },
1378+ "parameters": {
1379+ "temperature": "unsupported",
1380+ "topP": "unsupported",
1381+ "topK": "unsupported",
1382+ "maxTokens": "supported",
1383+ "reasoningEffort": "supported",
1384+ "thinkingBudget": "unsupported",
1385+ "stop": "unsupported",
1386+ "seed": "unsupported",
1387+ "frequencyPenalty": "unsupported",
1388+ "presencePenalty": "unsupported",
1389+ "verbosity": "supported"
1390+ },
1391+ "pricing": {
1392+ "inputPerMillion": 1.25,
1393+ "cachedInputPerMillion": 0.125,
1394+ "outputPerMillion": 10
1395+ },
1396+ "status": "deprecated",
1397+ "notes": "Dated snapshot of gpt-5. shutdown_date (from GET /v1/models): 2026-12-11. Alias still active but snapshot gpt-5-2025-08-07 has shutdown_date 2026-12-11 -> replacement gpt-5.6-sol. Uses 'minimal' (not 'none'); temperature not supported at any effort (docs). Reasoning items appear in output by default. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1398+ "reasoningEfforts": [
1399+ "minimal",
1400+ "low",
1401+ "medium",
1402+ "high"
1403+ ],
1404+ "defaultReasoningEffort": "medium",
1405+ "apis": [
1406+ "responses",
1407+ "chat",
1408+ "batch"
1409+ ],
1410+ "knowledgeCutoff": "2024-09-30",
1411+ "shutdownDate": "2026-12-11",
1412+ "snapshotOf": "gpt-5"
1413+ },
1414+ {
1415+ "id": "gpt-5-chat-latest",
1416+ "displayName": "GPT-5 Chat",
1417+ "family": "gpt-5",
1418+ "contextTokens": 128000,
1419+ "maxOutputTokens": 16384,
1420+ "capabilities": {
1421+ "text": true,
1422+ "vision": true,
1423+ "audioInput": false,
1424+ "audioOutput": false,
1425+ "imageGeneration": true,
1426+ "video": false,
1427+ "reasoning": false,
1428+ "tools": true,
1429+ "structuredOutput": true,
1430+ "streaming": true,
1431+ "files": true,
1432+ "webSearch": true
1433+ },
1434+ "parameters": {
1435+ "temperature": "supported",
1436+ "topP": "supported",
1437+ "topK": "unsupported",
1438+ "maxTokens": "supported",
1439+ "reasoningEffort": "unsupported",
1440+ "thinkingBudget": "unsupported",
1441+ "stop": "conditional",
1442+ "seed": "conditional",
1443+ "frequencyPenalty": "supported",
1444+ "presencePenalty": "supported",
1445+ "verbosity": "unsupported"
1446+ },
1447+ "pricing": {
1448+ "inputPerMillion": 1.25,
1449+ "cachedInputPerMillion": 0.125,
1450+ "outputPerMillion": 10
1451+ },
1452+ "status": "deprecated",
1453+ "notes": "shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. shutdown_date 2026-07-23; 404 model_not_found (verified). Verified by probe: basic -> 404. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1454+ "reasoningEfforts": null,
1455+ "defaultReasoningEffort": null,
1456+ "apis": [
1457+ "responses",
1458+ "chat"
1459+ ],
1460+ "knowledgeCutoff": null,
1461+ "shutdownDate": "2026-07-23",
1462+ "snapshotOf": null
1463+ },
1464+ {
1465+ "id": "gpt-5-codex",
1466+ "displayName": "GPT-5 Codex",
1467+ "family": "gpt-5",
1468+ "contextTokens": 400000,
1469+ "maxOutputTokens": 128000,
1470+ "capabilities": {
1471+ "text": true,
1472+ "vision": true,
1473+ "audioInput": false,
1474+ "audioOutput": false,
1475+ "imageGeneration": true,
1476+ "video": false,
1477+ "reasoning": true,
1478+ "tools": true,
1479+ "structuredOutput": true,
1480+ "streaming": true,
1481+ "files": true,
1482+ "webSearch": true
1483+ },
1484+ "parameters": {
1485+ "temperature": "unsupported",
1486+ "topP": "unsupported",
1487+ "topK": "unsupported",
1488+ "maxTokens": "supported",
1489+ "reasoningEffort": "supported",
1490+ "thinkingBudget": "unsupported",
1491+ "stop": "unsupported",
1492+ "seed": "unsupported",
1493+ "frequencyPenalty": "unsupported",
1494+ "presencePenalty": "unsupported",
1495+ "verbosity": "supported"
1496+ },
1497+ "pricing": {
1498+ "inputPerMillion": null,
1499+ "cachedInputPerMillion": null,
1500+ "outputPerMillion": null
1501+ },
1502+ "status": "deprecated",
1503+ "notes": "shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. shutdown_date 2026-07-23; 404 model_not_found (verified). Verified by probe: basic -> 404. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1504+ "reasoningEfforts": null,
1505+ "defaultReasoningEffort": null,
1506+ "apis": [
1507+ "responses"
1508+ ],
1509+ "knowledgeCutoff": null,
1510+ "shutdownDate": "2026-07-23",
1511+ "snapshotOf": null
1512+ },
1513+ {
1514+ "id": "gpt-5-mini",
1515+ "displayName": "GPT-5 mini",
1516+ "family": "gpt-5",
1517+ "contextTokens": 400000,
1518+ "maxOutputTokens": 128000,
1519+ "capabilities": {
1520+ "text": true,
1521+ "vision": true,
1522+ "audioInput": false,
1523+ "audioOutput": false,
1524+ "imageGeneration": true,
1525+ "video": false,
1526+ "reasoning": true,
1527+ "tools": true,
1528+ "structuredOutput": true,
1529+ "streaming": true,
1530+ "files": true,
1531+ "webSearch": true
1532+ },
1533+ "parameters": {
1534+ "temperature": "unsupported",
1535+ "topP": "unsupported",
1536+ "topK": "unsupported",
1537+ "maxTokens": "supported",
1538+ "reasoningEffort": "supported",
1539+ "thinkingBudget": "unsupported",
1540+ "stop": "unsupported",
1541+ "seed": "unsupported",
1542+ "frequencyPenalty": "unsupported",
1543+ "presencePenalty": "unsupported",
1544+ "verbosity": "supported"
1545+ },
1546+ "pricing": {
1547+ "inputPerMillion": 0.25,
1548+ "cachedInputPerMillion": 0.025,
1549+ "outputPerMillion": 2
1550+ },
1551+ "status": "active",
1552+ "notes": "Snapshot gpt-5-mini-2025-08-07 shuts down 2026-12-11 -> gpt-5.6-terra. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1553+ "reasoningEfforts": [
1554+ "minimal",
1555+ "low",
1556+ "medium",
1557+ "high"
1558+ ],
1559+ "defaultReasoningEffort": "medium",
1560+ "apis": [
1561+ "responses",
1562+ "chat",
1563+ "batch"
1564+ ],
1565+ "knowledgeCutoff": "2024-05-31",
1566+ "shutdownDate": null,
1567+ "snapshotOf": null
1568+ },
1569+ {
1570+ "id": "gpt-5-mini-2025-08-07",
1571+ "displayName": "GPT-5 mini (2025-08-07)",
1572+ "family": "gpt-5",
1573+ "contextTokens": 400000,
1574+ "maxOutputTokens": 128000,
1575+ "capabilities": {
1576+ "text": true,
1577+ "vision": true,
1578+ "audioInput": false,
1579+ "audioOutput": false,
1580+ "imageGeneration": true,
1581+ "video": false,
1582+ "reasoning": true,
1583+ "tools": true,
1584+ "structuredOutput": true,
1585+ "streaming": true,
1586+ "files": true,
1587+ "webSearch": true
1588+ },
1589+ "parameters": {
1590+ "temperature": "unsupported",
1591+ "topP": "unsupported",
1592+ "topK": "unsupported",
1593+ "maxTokens": "supported",
1594+ "reasoningEffort": "supported",
1595+ "thinkingBudget": "unsupported",
1596+ "stop": "unsupported",
1597+ "seed": "unsupported",
1598+ "frequencyPenalty": "unsupported",
1599+ "presencePenalty": "unsupported",
1600+ "verbosity": "supported"
1601+ },
1602+ "pricing": {
1603+ "inputPerMillion": 0.25,
1604+ "cachedInputPerMillion": 0.025,
1605+ "outputPerMillion": 2
1606+ },
1607+ "status": "deprecated",
1608+ "notes": "Dated snapshot of gpt-5-mini. shutdown_date (from GET /v1/models): 2026-12-11. Snapshot gpt-5-mini-2025-08-07 shuts down 2026-12-11 -> gpt-5.6-terra. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1609+ "reasoningEfforts": [
1610+ "minimal",
1611+ "low",
1612+ "medium",
1613+ "high"
1614+ ],
1615+ "defaultReasoningEffort": "medium",
1616+ "apis": [
1617+ "responses",
1618+ "chat",
1619+ "batch"
1620+ ],
1621+ "knowledgeCutoff": "2024-05-31",
1622+ "shutdownDate": "2026-12-11",
1623+ "snapshotOf": "gpt-5-mini"
1624+ },
1625+ {
1626+ "id": "gpt-5-nano",
1627+ "displayName": "GPT-5 nano",
1628+ "family": "gpt-5",
1629+ "contextTokens": 400000,
1630+ "maxOutputTokens": 128000,
1631+ "capabilities": {
1632+ "text": true,
1633+ "vision": true,
1634+ "audioInput": false,
1635+ "audioOutput": false,
1636+ "imageGeneration": true,
1637+ "video": false,
1638+ "reasoning": true,
1639+ "tools": true,
1640+ "structuredOutput": true,
1641+ "streaming": true,
1642+ "files": true,
1643+ "webSearch": true
1644+ },
1645+ "parameters": {
1646+ "temperature": "unsupported",
1647+ "topP": "unsupported",
1648+ "topK": "unsupported",
1649+ "maxTokens": "supported",
1650+ "reasoningEffort": "supported",
1651+ "thinkingBudget": "unsupported",
1652+ "stop": "unsupported",
1653+ "seed": "unsupported",
1654+ "frequencyPenalty": "unsupported",
1655+ "presencePenalty": "unsupported",
1656+ "verbosity": "supported"
1657+ },
1658+ "pricing": {
1659+ "inputPerMillion": 0.05,
1660+ "cachedInputPerMillion": 0.005,
1661+ "outputPerMillion": 0.4
1662+ },
1663+ "status": "active",
1664+ "notes": "Snapshot gpt-5-nano-2025-08-07 shuts down 2026-12-11 -> gpt-5.6-luna. Probe at default effort burned all 200 output tokens on reasoning (status incomplete) -> set effort minimal/low for short answers. Verified by probe: basic (incomplete at 200 tokens). Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1665+ "reasoningEfforts": [
1666+ "minimal",
1667+ "low",
1668+ "medium",
1669+ "high"
1670+ ],
1671+ "defaultReasoningEffort": "medium",
1672+ "apis": [
1673+ "responses",
1674+ "chat",
1675+ "batch"
1676+ ],
1677+ "knowledgeCutoff": "2024-05-31",
1678+ "shutdownDate": null,
1679+ "snapshotOf": null
1680+ },
1681+ {
1682+ "id": "gpt-5-nano-2025-08-07",
1683+ "displayName": "GPT-5 nano (2025-08-07)",
1684+ "family": "gpt-5",
1685+ "contextTokens": 400000,
1686+ "maxOutputTokens": 128000,
1687+ "capabilities": {
1688+ "text": true,
1689+ "vision": true,
1690+ "audioInput": false,
1691+ "audioOutput": false,
1692+ "imageGeneration": true,
1693+ "video": false,
1694+ "reasoning": true,
1695+ "tools": true,
1696+ "structuredOutput": true,
1697+ "streaming": true,
1698+ "files": true,
1699+ "webSearch": true
1700+ },
1701+ "parameters": {
1702+ "temperature": "unsupported",
1703+ "topP": "unsupported",
1704+ "topK": "unsupported",
1705+ "maxTokens": "supported",
1706+ "reasoningEffort": "supported",
1707+ "thinkingBudget": "unsupported",
1708+ "stop": "unsupported",
1709+ "seed": "unsupported",
1710+ "frequencyPenalty": "unsupported",
1711+ "presencePenalty": "unsupported",
1712+ "verbosity": "supported"
1713+ },
1714+ "pricing": {
1715+ "inputPerMillion": 0.05,
1716+ "cachedInputPerMillion": 0.005,
1717+ "outputPerMillion": 0.4
1718+ },
1719+ "status": "deprecated",
1720+ "notes": "Dated snapshot of gpt-5-nano. shutdown_date (from GET /v1/models): 2026-12-11. Snapshot gpt-5-nano-2025-08-07 shuts down 2026-12-11 -> gpt-5.6-luna. Probe at default effort burned all 200 output tokens on reasoning (status incomplete) -> set effort minimal/low for short answers. Verified by probe: basic (incomplete at 200 tokens). Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1721+ "reasoningEfforts": [
1722+ "minimal",
1723+ "low",
1724+ "medium",
1725+ "high"
1726+ ],
1727+ "defaultReasoningEffort": "medium",
1728+ "apis": [
1729+ "responses",
1730+ "chat",
1731+ "batch"
1732+ ],
1733+ "knowledgeCutoff": "2024-05-31",
1734+ "shutdownDate": "2026-12-11",
1735+ "snapshotOf": "gpt-5-nano"
1736+ },
1737+ {
1738+ "id": "gpt-5-pro",
1739+ "displayName": "GPT-5 Pro",
1740+ "family": "gpt-5",
1741+ "contextTokens": 400000,
1742+ "maxOutputTokens": 272000,
1743+ "capabilities": {
1744+ "text": true,
1745+ "vision": true,
1746+ "audioInput": false,
1747+ "audioOutput": false,
1748+ "imageGeneration": true,
1749+ "video": false,
1750+ "reasoning": true,
1751+ "tools": true,
1752+ "structuredOutput": true,
1753+ "streaming": true,
1754+ "files": true,
1755+ "webSearch": true
1756+ },
1757+ "parameters": {
1758+ "temperature": "unsupported",
1759+ "topP": "unsupported",
1760+ "topK": "unsupported",
1761+ "maxTokens": "supported",
1762+ "reasoningEffort": "supported",
1763+ "thinkingBudget": "unsupported",
1764+ "stop": "unsupported",
1765+ "seed": "unsupported",
1766+ "frequencyPenalty": "unsupported",
1767+ "presencePenalty": "unsupported",
1768+ "verbosity": null
1769+ },
1770+ "pricing": {
1771+ "inputPerMillion": 15,
1772+ "cachedInputPerMillion": null,
1773+ "outputPerMillion": 120
1774+ },
1775+ "status": "active",
1776+ "notes": "Only reasoning.effort high. Snapshot gpt-5-pro-2025-10-06 shuts down 2026-12-11 -> gpt-5.6-sol with reasoning.mode pro. Not probed. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1777+ "reasoningEfforts": [
1778+ "high"
1779+ ],
1780+ "defaultReasoningEffort": "high",
1781+ "apis": [
1782+ "responses",
1783+ "batch"
1784+ ],
1785+ "knowledgeCutoff": "2024-09-30",
1786+ "shutdownDate": null,
1787+ "snapshotOf": null
1788+ },
1789+ {
1790+ "id": "gpt-5-pro-2025-10-06",
1791+ "displayName": "GPT-5 Pro (2025-10-06)",
1792+ "family": "gpt-5",
1793+ "contextTokens": 400000,
1794+ "maxOutputTokens": 272000,
1795+ "capabilities": {
1796+ "text": true,
1797+ "vision": true,
1798+ "audioInput": false,
1799+ "audioOutput": false,
1800+ "imageGeneration": true,
1801+ "video": false,
1802+ "reasoning": true,
1803+ "tools": true,
1804+ "structuredOutput": true,
1805+ "streaming": true,
1806+ "files": true,
1807+ "webSearch": true
1808+ },
1809+ "parameters": {
1810+ "temperature": "unsupported",
1811+ "topP": "unsupported",
1812+ "topK": "unsupported",
1813+ "maxTokens": "supported",
1814+ "reasoningEffort": "supported",
1815+ "thinkingBudget": "unsupported",
1816+ "stop": "unsupported",
1817+ "seed": "unsupported",
1818+ "frequencyPenalty": "unsupported",
1819+ "presencePenalty": "unsupported",
1820+ "verbosity": null
1821+ },
1822+ "pricing": {
1823+ "inputPerMillion": 15,
1824+ "cachedInputPerMillion": null,
1825+ "outputPerMillion": 120
1826+ },
1827+ "status": "deprecated",
1828+ "notes": "Dated snapshot of gpt-5-pro. shutdown_date (from GET /v1/models): 2026-12-11. Only reasoning.effort high. Snapshot gpt-5-pro-2025-10-06 shuts down 2026-12-11 -> gpt-5.6-sol with reasoning.mode pro. Not probed. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1829+ "reasoningEfforts": [
1830+ "high"
1831+ ],
1832+ "defaultReasoningEffort": "high",
1833+ "apis": [
1834+ "responses",
1835+ "batch"
1836+ ],
1837+ "knowledgeCutoff": "2024-09-30",
1838+ "shutdownDate": "2026-12-11",
1839+ "snapshotOf": "gpt-5-pro"
1840+ },
1841+ {
1842+ "id": "gpt-5-search-api",
1843+ "displayName": "GPT-5 Search API (Chat Completions web search)",
1844+ "family": "gpt-5",
1845+ "contextTokens": null,
1846+ "maxOutputTokens": null,
1847+ "capabilities": {
1848+ "text": true,
1849+ "vision": true,
1850+ "audioInput": false,
1851+ "audioOutput": false,
1852+ "imageGeneration": false,
1853+ "video": false,
1854+ "reasoning": false,
1855+ "tools": true,
1856+ "structuredOutput": true,
1857+ "streaming": true,
1858+ "files": true,
1859+ "webSearch": true
1860+ },
1861+ "parameters": {
1862+ "temperature": "supported",
1863+ "topP": "supported",
1864+ "topK": "unsupported",
1865+ "maxTokens": "supported",
1866+ "reasoningEffort": "unsupported",
1867+ "thinkingBudget": "unsupported",
1868+ "stop": "conditional",
1869+ "seed": "conditional",
1870+ "frequencyPenalty": "supported",
1871+ "presencePenalty": "supported",
1872+ "verbosity": "unsupported"
1873+ },
1874+ "pricing": {
1875+ "inputPerMillion": null,
1876+ "cachedInputPerMillion": null,
1877+ "outputPerMillion": null
1878+ },
1879+ "status": "preview",
1880+ "notes": "Chat Completions ONLY: Responses returns 400 model_not_found 'not supported with the Responses API' (verified); chat.completions works (verified, resolves gpt-5-search-api-2025-10-14). Model page 404 -> context/pricing unknown. Prefer web_search tool on a normal model. Verified by probe: chat only. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1881+ "reasoningEfforts": null,
1882+ "defaultReasoningEffort": null,
1883+ "apis": [
1884+ "chat"
1885+ ],
1886+ "knowledgeCutoff": null,
1887+ "shutdownDate": null,
1888+ "snapshotOf": null
1889+ },
1890+ {
1891+ "id": "gpt-5-search-api-2025-10-14",
1892+ "displayName": "GPT-5 Search API (Chat Completions web search) (2025-10-14)",
1893+ "family": "gpt-5",
1894+ "contextTokens": null,
1895+ "maxOutputTokens": null,
1896+ "capabilities": {
1897+ "text": true,
1898+ "vision": true,
1899+ "audioInput": false,
1900+ "audioOutput": false,
1901+ "imageGeneration": false,
1902+ "video": false,
1903+ "reasoning": false,
1904+ "tools": true,
1905+ "structuredOutput": true,
1906+ "streaming": true,
1907+ "files": true,
1908+ "webSearch": true
1909+ },
1910+ "parameters": {
1911+ "temperature": "supported",
1912+ "topP": "supported",
1913+ "topK": "unsupported",
1914+ "maxTokens": "supported",
1915+ "reasoningEffort": "unsupported",
1916+ "thinkingBudget": "unsupported",
1917+ "stop": "conditional",
1918+ "seed": "conditional",
1919+ "frequencyPenalty": "supported",
1920+ "presencePenalty": "supported",
1921+ "verbosity": "unsupported"
1922+ },
1923+ "pricing": {
1924+ "inputPerMillion": null,
1925+ "cachedInputPerMillion": null,
1926+ "outputPerMillion": null
1927+ },
1928+ "status": "preview",
1929+ "notes": "Dated snapshot of gpt-5-search-api. Chat Completions ONLY: Responses returns 400 model_not_found 'not supported with the Responses API' (verified); chat.completions works (verified, resolves gpt-5-search-api-2025-10-14). Model page 404 -> context/pricing unknown. Prefer web_search tool on a normal model. Verified by probe: chat only. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1930+ "reasoningEfforts": null,
1931+ "defaultReasoningEffort": null,
1932+ "apis": [
1933+ "chat"
1934+ ],
1935+ "knowledgeCutoff": null,
1936+ "shutdownDate": null,
1937+ "snapshotOf": "gpt-5-search-api"
1938+ },
1939+ {
1940+ "id": "gpt-5.1",
1941+ "displayName": "GPT-5.1",
1942+ "family": "gpt-5.1",
1943+ "contextTokens": 400000,
1944+ "maxOutputTokens": 128000,
1945+ "capabilities": {
1946+ "text": true,
1947+ "vision": true,
1948+ "audioInput": false,
1949+ "audioOutput": false,
1950+ "imageGeneration": true,
1951+ "video": false,
1952+ "reasoning": true,
1953+ "tools": true,
1954+ "structuredOutput": true,
1955+ "streaming": true,
1956+ "files": true,
1957+ "webSearch": true
1958+ },
1959+ "parameters": {
1960+ "temperature": "conditional",
1961+ "topP": "conditional",
1962+ "topK": "unsupported",
1963+ "maxTokens": "supported",
1964+ "reasoningEffort": "supported",
1965+ "thinkingBudget": "unsupported",
1966+ "stop": "unsupported",
1967+ "seed": "unsupported",
1968+ "frequencyPenalty": "conditional",
1969+ "presencePenalty": "conditional",
1970+ "verbosity": "supported"
1971+ },
1972+ "pricing": {
1973+ "inputPerMillion": 1.25,
1974+ "cachedInputPerMillion": 0.125,
1975+ "outputPerMillion": 10
1976+ },
1977+ "status": "active",
1978+ "notes": "Snapshot gpt-5.1-2025-11-13. No xhigh. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
1979+ "reasoningEfforts": [
1980+ "none",
1981+ "low",
1982+ "medium",
1983+ "high"
1984+ ],
1985+ "defaultReasoningEffort": "none",
1986+ "apis": [
1987+ "responses",
1988+ "chat",
1989+ "batch"
1990+ ],
1991+ "knowledgeCutoff": "2024-09-30",
1992+ "shutdownDate": null,
1993+ "snapshotOf": null
1994+ },
1995+ {
1996+ "id": "gpt-5.1-2025-11-13",
1997+ "displayName": "GPT-5.1 (2025-11-13)",
1998+ "family": "gpt-5.1",
1999+ "contextTokens": 400000,
2000+ "maxOutputTokens": 128000,
2001+ "capabilities": {
2002+ "text": true,
2003+ "vision": true,
2004+ "audioInput": false,
2005+ "audioOutput": false,
2006+ "imageGeneration": true,
2007+ "video": false,
2008+ "reasoning": true,
2009+ "tools": true,
2010+ "structuredOutput": true,
2011+ "streaming": true,
2012+ "files": true,
2013+ "webSearch": true
2014+ },
2015+ "parameters": {
2016+ "temperature": "conditional",
2017+ "topP": "conditional",
2018+ "topK": "unsupported",
2019+ "maxTokens": "supported",
2020+ "reasoningEffort": "supported",
2021+ "thinkingBudget": "unsupported",
2022+ "stop": "unsupported",
2023+ "seed": "unsupported",
2024+ "frequencyPenalty": "conditional",
2025+ "presencePenalty": "conditional",
2026+ "verbosity": "supported"
2027+ },
2028+ "pricing": {
2029+ "inputPerMillion": 1.25,
2030+ "cachedInputPerMillion": 0.125,
2031+ "outputPerMillion": 10
2032+ },
2033+ "status": "active",
2034+ "notes": "Dated snapshot of gpt-5.1. Snapshot gpt-5.1-2025-11-13. No xhigh. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2035+ "reasoningEfforts": [
2036+ "none",
2037+ "low",
2038+ "medium",
2039+ "high"
2040+ ],
2041+ "defaultReasoningEffort": "none",
2042+ "apis": [
2043+ "responses",
2044+ "chat",
2045+ "batch"
2046+ ],
2047+ "knowledgeCutoff": "2024-09-30",
2048+ "shutdownDate": null,
2049+ "snapshotOf": "gpt-5.1"
2050+ },
2051+ {
2052+ "id": "gpt-5.1-chat-latest",
2053+ "displayName": "GPT-5.1 Chat",
2054+ "family": "gpt-5.1",
2055+ "contextTokens": 128000,
2056+ "maxOutputTokens": 16384,
2057+ "capabilities": {
2058+ "text": true,
2059+ "vision": true,
2060+ "audioInput": false,
2061+ "audioOutput": false,
2062+ "imageGeneration": true,
2063+ "video": false,
2064+ "reasoning": false,
2065+ "tools": true,
2066+ "structuredOutput": true,
2067+ "streaming": true,
2068+ "files": true,
2069+ "webSearch": true
2070+ },
2071+ "parameters": {
2072+ "temperature": "supported",
2073+ "topP": "supported",
2074+ "topK": "unsupported",
2075+ "maxTokens": "supported",
2076+ "reasoningEffort": "unsupported",
2077+ "thinkingBudget": "unsupported",
2078+ "stop": "conditional",
2079+ "seed": "conditional",
2080+ "frequencyPenalty": "supported",
2081+ "presencePenalty": "supported",
2082+ "verbosity": "unsupported"
2083+ },
2084+ "pricing": {
2085+ "inputPerMillion": 1.25,
2086+ "cachedInputPerMillion": 0.125,
2087+ "outputPerMillion": 10
2088+ },
2089+ "status": "deprecated",
2090+ "notes": "shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. shutdown_date 2026-07-23; requests return 404 model_not_found (verified). Verified by probe: basic -> 404. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2091+ "reasoningEfforts": null,
2092+ "defaultReasoningEffort": null,
2093+ "apis": [
2094+ "responses",
2095+ "chat"
2096+ ],
2097+ "knowledgeCutoff": null,
2098+ "shutdownDate": "2026-07-23",
2099+ "snapshotOf": null
2100+ },
2101+ {
2102+ "id": "gpt-5.1-codex",
2103+ "displayName": "GPT-5.1 Codex",
2104+ "family": "gpt-5.1",
2105+ "contextTokens": 400000,
2106+ "maxOutputTokens": 128000,
2107+ "capabilities": {
2108+ "text": true,
2109+ "vision": true,
2110+ "audioInput": false,
2111+ "audioOutput": false,
2112+ "imageGeneration": true,
2113+ "video": false,
2114+ "reasoning": true,
2115+ "tools": true,
2116+ "structuredOutput": true,
2117+ "streaming": true,
2118+ "files": true,
2119+ "webSearch": true
2120+ },
2121+ "parameters": {
2122+ "temperature": "unsupported",
2123+ "topP": "unsupported",
2124+ "topK": "unsupported",
2125+ "maxTokens": "supported",
2126+ "reasoningEffort": "supported",
2127+ "thinkingBudget": "unsupported",
2128+ "stop": "unsupported",
2129+ "seed": "unsupported",
2130+ "frequencyPenalty": "unsupported",
2131+ "presencePenalty": "unsupported",
2132+ "verbosity": "supported"
2133+ },
2134+ "pricing": {
2135+ "inputPerMillion": null,
2136+ "cachedInputPerMillion": null,
2137+ "outputPerMillion": null
2138+ },
2139+ "status": "deprecated",
2140+ "notes": "shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. shutdown_date 2026-07-23; 404 model_not_found (verified). Pricing unknown. Verified by probe: basic -> 404. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2141+ "reasoningEfforts": null,
2142+ "defaultReasoningEffort": null,
2143+ "apis": [
2144+ "responses"
2145+ ],
2146+ "knowledgeCutoff": null,
2147+ "shutdownDate": "2026-07-23",
2148+ "snapshotOf": null
2149+ },
2150+ {
2151+ "id": "gpt-5.1-codex-max",
2152+ "displayName": "GPT-5.1 Codex Max",
2153+ "family": "gpt-5.1",
2154+ "contextTokens": null,
2155+ "maxOutputTokens": null,
2156+ "capabilities": {
2157+ "text": true,
2158+ "vision": true,
2159+ "audioInput": false,
2160+ "audioOutput": false,
2161+ "imageGeneration": true,
2162+ "video": false,
2163+ "reasoning": true,
2164+ "tools": true,
2165+ "structuredOutput": true,
2166+ "streaming": true,
2167+ "files": true,
2168+ "webSearch": true
2169+ },
2170+ "parameters": {
2171+ "temperature": "unsupported",
2172+ "topP": "unsupported",
2173+ "topK": "unsupported",
2174+ "maxTokens": "supported",
2175+ "reasoningEffort": "supported",
2176+ "thinkingBudget": "unsupported",
2177+ "stop": "unsupported",
2178+ "seed": "unsupported",
2179+ "frequencyPenalty": "unsupported",
2180+ "presencePenalty": "unsupported",
2181+ "verbosity": "supported"
2182+ },
2183+ "pricing": {
2184+ "inputPerMillion": null,
2185+ "cachedInputPerMillion": null,
2186+ "outputPerMillion": null
2187+ },
2188+ "status": "deprecated",
2189+ "notes": "shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. shutdown_date 2026-07-23 (passed). Not probed; context/pricing unknown. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2190+ "reasoningEfforts": null,
2191+ "defaultReasoningEffort": null,
2192+ "apis": [
2193+ "responses"
2194+ ],
2195+ "knowledgeCutoff": null,
2196+ "shutdownDate": "2026-07-23",
2197+ "snapshotOf": null
2198+ },
2199+ {
2200+ "id": "gpt-5.1-codex-mini",
2201+ "displayName": "GPT-5.1 Codex Mini",
2202+ "family": "gpt-5.1",
2203+ "contextTokens": null,
2204+ "maxOutputTokens": null,
2205+ "capabilities": {
2206+ "text": true,
2207+ "vision": true,
2208+ "audioInput": false,
2209+ "audioOutput": false,
2210+ "imageGeneration": true,
2211+ "video": false,
2212+ "reasoning": true,
2213+ "tools": true,
2214+ "structuredOutput": true,
2215+ "streaming": true,
2216+ "files": true,
2217+ "webSearch": true
2218+ },
2219+ "parameters": {
2220+ "temperature": "unsupported",
2221+ "topP": "unsupported",
2222+ "topK": "unsupported",
2223+ "maxTokens": "supported",
2224+ "reasoningEffort": "supported",
2225+ "thinkingBudget": "unsupported",
2226+ "stop": "unsupported",
2227+ "seed": "unsupported",
2228+ "frequencyPenalty": "unsupported",
2229+ "presencePenalty": "unsupported",
2230+ "verbosity": "supported"
2231+ },
2232+ "pricing": {
2233+ "inputPerMillion": null,
2234+ "cachedInputPerMillion": null,
2235+ "outputPerMillion": null
2236+ },
2237+ "status": "deprecated",
2238+ "notes": "shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. shutdown_date 2026-07-23 (passed). Not probed; context/pricing unknown. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2239+ "reasoningEfforts": null,
2240+ "defaultReasoningEffort": null,
2241+ "apis": [
2242+ "responses"
2243+ ],
2244+ "knowledgeCutoff": null,
2245+ "shutdownDate": "2026-07-23",
2246+ "snapshotOf": null
2247+ },
2248+ {
2249+ "id": "gpt-5.2",
2250+ "displayName": "GPT-5.2",
2251+ "family": "gpt-5.2",
2252+ "contextTokens": 400000,
2253+ "maxOutputTokens": 128000,
2254+ "capabilities": {
2255+ "text": true,
2256+ "vision": true,
2257+ "audioInput": false,
2258+ "audioOutput": false,
2259+ "imageGeneration": true,
2260+ "video": false,
2261+ "reasoning": true,
2262+ "tools": true,
2263+ "structuredOutput": true,
2264+ "streaming": true,
2265+ "files": true,
2266+ "webSearch": true
2267+ },
2268+ "parameters": {
2269+ "temperature": "conditional",
2270+ "topP": "conditional",
2271+ "topK": "unsupported",
2272+ "maxTokens": "supported",
2273+ "reasoningEffort": "supported",
2274+ "thinkingBudget": "unsupported",
2275+ "stop": "unsupported",
2276+ "seed": "unsupported",
2277+ "frequencyPenalty": "conditional",
2278+ "presencePenalty": "conditional",
2279+ "verbosity": "supported"
2280+ },
2281+ "pricing": {
2282+ "inputPerMillion": 1.75,
2283+ "cachedInputPerMillion": 0.175,
2284+ "outputPerMillion": 14
2285+ },
2286+ "status": "active",
2287+ "notes": "Snapshot gpt-5.2-2025-12-11. Docs recommend GPT-6 Astra instead. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2288+ "reasoningEfforts": [
2289+ "none",
2290+ "low",
2291+ "medium",
2292+ "high",
2293+ "xhigh"
2294+ ],
2295+ "defaultReasoningEffort": "none",
2296+ "apis": [
2297+ "responses",
2298+ "chat",
2299+ "batch"
2300+ ],
2301+ "knowledgeCutoff": "2025-08-31",
2302+ "shutdownDate": null,
2303+ "snapshotOf": null
2304+ },
2305+ {
2306+ "id": "gpt-5.2-2025-12-11",
2307+ "displayName": "GPT-5.2 (2025-12-11)",
2308+ "family": "gpt-5.2",
2309+ "contextTokens": 400000,
2310+ "maxOutputTokens": 128000,
2311+ "capabilities": {
2312+ "text": true,
2313+ "vision": true,
2314+ "audioInput": false,
2315+ "audioOutput": false,
2316+ "imageGeneration": true,
2317+ "video": false,
2318+ "reasoning": true,
2319+ "tools": true,
2320+ "structuredOutput": true,
2321+ "streaming": true,
2322+ "files": true,
2323+ "webSearch": true
2324+ },
2325+ "parameters": {
2326+ "temperature": "conditional",
2327+ "topP": "conditional",
2328+ "topK": "unsupported",
2329+ "maxTokens": "supported",
2330+ "reasoningEffort": "supported",
2331+ "thinkingBudget": "unsupported",
2332+ "stop": "unsupported",
2333+ "seed": "unsupported",
2334+ "frequencyPenalty": "conditional",
2335+ "presencePenalty": "conditional",
2336+ "verbosity": "supported"
2337+ },
2338+ "pricing": {
2339+ "inputPerMillion": 1.75,
2340+ "cachedInputPerMillion": 0.175,
2341+ "outputPerMillion": 14
2342+ },
2343+ "status": "active",
2344+ "notes": "Dated snapshot of gpt-5.2. Snapshot gpt-5.2-2025-12-11. Docs recommend GPT-6 Astra instead. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2345+ "reasoningEfforts": [
2346+ "none",
2347+ "low",
2348+ "medium",
2349+ "high",
2350+ "xhigh"
2351+ ],
2352+ "defaultReasoningEffort": "none",
2353+ "apis": [
2354+ "responses",
2355+ "chat",
2356+ "batch"
2357+ ],
2358+ "knowledgeCutoff": "2025-08-31",
2359+ "shutdownDate": null,
2360+ "snapshotOf": "gpt-5.2"
2361+ },
2362+ {
2363+ "id": "gpt-5.2-chat-latest",
2364+ "displayName": "GPT-5.2 Chat",
2365+ "family": "gpt-5.2",
2366+ "contextTokens": 128000,
2367+ "maxOutputTokens": 16384,
2368+ "capabilities": {
2369+ "text": true,
2370+ "vision": true,
2371+ "audioInput": false,
2372+ "audioOutput": false,
2373+ "imageGeneration": true,
2374+ "video": false,
2375+ "reasoning": false,
2376+ "tools": true,
2377+ "structuredOutput": true,
2378+ "streaming": true,
2379+ "files": true,
2380+ "webSearch": true
2381+ },
2382+ "parameters": {
2383+ "temperature": "supported",
2384+ "topP": "supported",
2385+ "topK": "unsupported",
2386+ "maxTokens": "supported",
2387+ "reasoningEffort": "unsupported",
2388+ "thinkingBudget": "unsupported",
2389+ "stop": "conditional",
2390+ "seed": "conditional",
2391+ "frequencyPenalty": "supported",
2392+ "presencePenalty": "supported",
2393+ "verbosity": "unsupported"
2394+ },
2395+ "pricing": {
2396+ "inputPerMillion": 1.75,
2397+ "cachedInputPerMillion": 0.175,
2398+ "outputPerMillion": 14
2399+ },
2400+ "status": "deprecated",
2401+ "notes": "shutdown_date (from GET /v1/models): 2026-08-10 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. shutdown_date 2026-08-10; requests return 404 model_not_found (verified). Verified by probe: basic -> 404. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2402+ "reasoningEfforts": null,
2403+ "defaultReasoningEffort": null,
2404+ "apis": [
2405+ "responses",
2406+ "chat"
2407+ ],
2408+ "knowledgeCutoff": "2025-08-31",
2409+ "shutdownDate": "2026-08-10",
2410+ "snapshotOf": null
2411+ },
2412+ {
2413+ "id": "gpt-5.2-codex",
2414+ "displayName": "GPT-5.2 Codex",
2415+ "family": "gpt-5.2",
2416+ "contextTokens": 400000,
2417+ "maxOutputTokens": 128000,
2418+ "capabilities": {
2419+ "text": true,
2420+ "vision": true,
2421+ "audioInput": false,
2422+ "audioOutput": false,
2423+ "imageGeneration": true,
2424+ "video": false,
2425+ "reasoning": true,
2426+ "tools": true,
2427+ "structuredOutput": true,
2428+ "streaming": true,
2429+ "files": true,
2430+ "webSearch": true
2431+ },
2432+ "parameters": {
2433+ "temperature": "unsupported",
2434+ "topP": "unsupported",
2435+ "topK": "unsupported",
2436+ "maxTokens": "supported",
2437+ "reasoningEffort": "supported",
2438+ "thinkingBudget": "unsupported",
2439+ "stop": "unsupported",
2440+ "seed": "unsupported",
2441+ "frequencyPenalty": "unsupported",
2442+ "presencePenalty": "unsupported",
2443+ "verbosity": "supported"
2444+ },
2445+ "pricing": {
2446+ "inputPerMillion": null,
2447+ "cachedInputPerMillion": null,
2448+ "outputPerMillion": null
2449+ },
2450+ "status": "deprecated",
2451+ "notes": "shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. shutdown_date 2026-07-23 (passed). Not probed; siblings gpt-5-codex/gpt-5.1-codex return 404. Pricing unknown (page not fetched). Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2452+ "reasoningEfforts": null,
2453+ "defaultReasoningEffort": null,
2454+ "apis": [
2455+ "responses"
2456+ ],
2457+ "knowledgeCutoff": null,
2458+ "shutdownDate": "2026-07-23",
2459+ "snapshotOf": null
2460+ },
2461+ {
2462+ "id": "gpt-5.2-pro",
2463+ "displayName": "GPT-5.2 Pro",
2464+ "family": "gpt-5.2",
2465+ "contextTokens": 400000,
2466+ "maxOutputTokens": 128000,
2467+ "capabilities": {
2468+ "text": true,
2469+ "vision": true,
2470+ "audioInput": false,
2471+ "audioOutput": false,
2472+ "imageGeneration": true,
2473+ "video": false,
2474+ "reasoning": true,
2475+ "tools": true,
2476+ "structuredOutput": null,
2477+ "streaming": true,
2478+ "files": true,
2479+ "webSearch": true
2480+ },
2481+ "parameters": {
2482+ "temperature": "unsupported",
2483+ "topP": "unsupported",
2484+ "topK": "unsupported",
2485+ "maxTokens": "supported",
2486+ "reasoningEffort": "supported",
2487+ "thinkingBudget": "unsupported",
2488+ "stop": "unsupported",
2489+ "seed": "unsupported",
2490+ "frequencyPenalty": "unsupported",
2491+ "presencePenalty": "unsupported",
2492+ "verbosity": "supported"
2493+ },
2494+ "pricing": {
2495+ "inputPerMillion": 21,
2496+ "cachedInputPerMillion": null,
2497+ "outputPerMillion": 168
2498+ },
2499+ "status": "active",
2500+ "notes": "Responses API only; docs recommend GPT-5.5 Pro. Not probed. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2501+ "reasoningEfforts": [
2502+ "medium",
2503+ "high",
2504+ "xhigh"
2505+ ],
2506+ "defaultReasoningEffort": "medium",
2507+ "apis": [
2508+ "responses"
2509+ ],
2510+ "knowledgeCutoff": "2025-08-31",
2511+ "shutdownDate": null,
2512+ "snapshotOf": null
2513+ },
2514+ {
2515+ "id": "gpt-5.2-pro-2025-12-11",
2516+ "displayName": "GPT-5.2 Pro (2025-12-11)",
2517+ "family": "gpt-5.2",
2518+ "contextTokens": 400000,
2519+ "maxOutputTokens": 128000,
2520+ "capabilities": {
2521+ "text": true,
2522+ "vision": true,
2523+ "audioInput": false,
2524+ "audioOutput": false,
2525+ "imageGeneration": true,
2526+ "video": false,
2527+ "reasoning": true,
2528+ "tools": true,
2529+ "structuredOutput": null,
2530+ "streaming": true,
2531+ "files": true,
2532+ "webSearch": true
2533+ },
2534+ "parameters": {
2535+ "temperature": "unsupported",
2536+ "topP": "unsupported",
2537+ "topK": "unsupported",
2538+ "maxTokens": "supported",
2539+ "reasoningEffort": "supported",
2540+ "thinkingBudget": "unsupported",
2541+ "stop": "unsupported",
2542+ "seed": "unsupported",
2543+ "frequencyPenalty": "unsupported",
2544+ "presencePenalty": "unsupported",
2545+ "verbosity": "supported"
2546+ },
2547+ "pricing": {
2548+ "inputPerMillion": 21,
2549+ "cachedInputPerMillion": null,
2550+ "outputPerMillion": 168
2551+ },
2552+ "status": "active",
2553+ "notes": "Dated snapshot of gpt-5.2-pro. Responses API only; docs recommend GPT-5.5 Pro. Not probed. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2554+ "reasoningEfforts": [
2555+ "medium",
2556+ "high",
2557+ "xhigh"
2558+ ],
2559+ "defaultReasoningEffort": "medium",
2560+ "apis": [
2561+ "responses"
2562+ ],
2563+ "knowledgeCutoff": "2025-08-31",
2564+ "shutdownDate": null,
2565+ "snapshotOf": "gpt-5.2-pro"
2566+ },
2567+ {
2568+ "id": "gpt-5.3-chat-latest",
2569+ "displayName": "GPT-5.3 Chat (ChatGPT Instant)",
2570+ "family": "gpt-5.3",
2571+ "contextTokens": 128000,
2572+ "maxOutputTokens": 16384,
2573+ "capabilities": {
2574+ "text": true,
2575+ "vision": true,
2576+ "audioInput": false,
2577+ "audioOutput": false,
2578+ "imageGeneration": true,
2579+ "video": false,
2580+ "reasoning": false,
2581+ "tools": true,
2582+ "structuredOutput": true,
2583+ "streaming": true,
2584+ "files": true,
2585+ "webSearch": true
2586+ },
2587+ "parameters": {
2588+ "temperature": null,
2589+ "topP": null,
2590+ "topK": "unsupported",
2591+ "maxTokens": "supported",
2592+ "reasoningEffort": "unsupported",
2593+ "thinkingBudget": "unsupported",
2594+ "stop": "conditional",
2595+ "seed": "conditional",
2596+ "frequencyPenalty": null,
2597+ "presencePenalty": null,
2598+ "verbosity": null
2599+ },
2600+ "pricing": {
2601+ "inputPerMillion": 1.75,
2602+ "cachedInputPerMillion": 0.175,
2603+ "outputPerMillion": 14
2604+ },
2605+ "status": "deprecated",
2606+ "notes": "shutdown_date (from GET /v1/models): 2026-08-10 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. Listed by GET /v1/models with shutdown_date 2026-08-10 but requests return 404 model_not_found (verified). Docs: 'This model has been deprecated. We recommend GPT-6 Astra'. Use chat-latest instead. Verified by probe: basic -> 404. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2607+ "reasoningEfforts": null,
2608+ "defaultReasoningEffort": null,
2609+ "apis": [
2610+ "responses",
2611+ "chat"
2612+ ],
2613+ "knowledgeCutoff": "2025-08-31",
2614+ "shutdownDate": "2026-08-10",
2615+ "snapshotOf": null
2616+ },
2617+ {
2618+ "id": "gpt-5.3-codex",
2619+ "displayName": "GPT-5.3 Codex",
2620+ "family": "gpt-5.3",
2621+ "contextTokens": 400000,
2622+ "maxOutputTokens": 128000,
2623+ "capabilities": {
2624+ "text": true,
2625+ "vision": true,
2626+ "audioInput": false,
2627+ "audioOutput": false,
2628+ "imageGeneration": true,
2629+ "video": false,
2630+ "reasoning": true,
2631+ "tools": true,
2632+ "structuredOutput": true,
2633+ "streaming": true,
2634+ "files": true,
2635+ "webSearch": true
2636+ },
2637+ "parameters": {
2638+ "temperature": null,
2639+ "topP": null,
2640+ "topK": "unsupported",
2641+ "maxTokens": "supported",
2642+ "reasoningEffort": "supported",
2643+ "thinkingBudget": "unsupported",
2644+ "stop": "unsupported",
2645+ "seed": "unsupported",
2646+ "frequencyPenalty": null,
2647+ "presencePenalty": null,
2648+ "verbosity": "supported"
2649+ },
2650+ "pricing": {
2651+ "inputPerMillion": 1.75,
2652+ "cachedInputPerMillion": 0.175,
2653+ "outputPerMillion": 14
2654+ },
2655+ "status": "active",
2656+ "notes": "Agentic-coding model, Responses API only. Probe echoed reasoning.effort 'none' as default although docs list low..xhigh. Not a general chat model. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2657+ "reasoningEfforts": [
2658+ "low",
2659+ "medium",
2660+ "high",
2661+ "xhigh"
2662+ ],
2663+ "defaultReasoningEffort": "none",
2664+ "apis": [
2665+ "responses"
2666+ ],
2667+ "knowledgeCutoff": "2025-08-31",
2668+ "shutdownDate": null,
2669+ "snapshotOf": null
2670+ },
2671+ {
2672+ "id": "gpt-5.4",
2673+ "displayName": "GPT-5.4",
2674+ "family": "gpt-5.4",
2675+ "contextTokens": 1050000,
2676+ "maxOutputTokens": 128000,
2677+ "capabilities": {
2678+ "text": true,
2679+ "vision": true,
2680+ "audioInput": false,
2681+ "audioOutput": false,
2682+ "imageGeneration": true,
2683+ "video": false,
2684+ "reasoning": true,
2685+ "tools": true,
2686+ "structuredOutput": true,
2687+ "streaming": true,
2688+ "files": true,
2689+ "webSearch": true
2690+ },
2691+ "parameters": {
2692+ "temperature": "conditional",
2693+ "topP": "conditional",
2694+ "topK": "unsupported",
2695+ "maxTokens": "supported",
2696+ "reasoningEffort": "supported",
2697+ "thinkingBudget": "unsupported",
2698+ "stop": "unsupported",
2699+ "seed": "unsupported",
2700+ "frequencyPenalty": "conditional",
2701+ "presencePenalty": "conditional",
2702+ "verbosity": "supported"
2703+ },
2704+ "pricing": {
2705+ "inputPerMillion": 2.5,
2706+ "cachedInputPerMillion": 0.25,
2707+ "outputPerMillion": 15
2708+ },
2709+ "status": "active",
2710+ "notes": "Snapshot gpt-5.4-2026-03-05. Default effort 'none' (verified echo) so sampling params work by default; assumed rejected once effort >= low (pattern verified on gpt-5.5/5.6). Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2711+ "reasoningEfforts": [
2712+ "none",
2713+ "low",
2714+ "medium",
2715+ "high",
2716+ "xhigh"
2717+ ],
2718+ "defaultReasoningEffort": "none",
2719+ "apis": [
2720+ "responses",
2721+ "chat",
2722+ "batch"
2723+ ],
2724+ "knowledgeCutoff": "2025-08-31",
2725+ "shutdownDate": null,
2726+ "snapshotOf": null
2727+ },
2728+ {
2729+ "id": "gpt-5.4-2026-03-05",
2730+ "displayName": "GPT-5.4 (2026-03-05)",
2731+ "family": "gpt-5.4",
2732+ "contextTokens": 1050000,
2733+ "maxOutputTokens": 128000,
2734+ "capabilities": {
2735+ "text": true,
2736+ "vision": true,
2737+ "audioInput": false,
2738+ "audioOutput": false,
2739+ "imageGeneration": true,
2740+ "video": false,
2741+ "reasoning": true,
2742+ "tools": true,
2743+ "structuredOutput": true,
2744+ "streaming": true,
2745+ "files": true,
2746+ "webSearch": true
2747+ },
2748+ "parameters": {
2749+ "temperature": "conditional",
2750+ "topP": "conditional",
2751+ "topK": "unsupported",
2752+ "maxTokens": "supported",
2753+ "reasoningEffort": "supported",
2754+ "thinkingBudget": "unsupported",
2755+ "stop": "unsupported",
2756+ "seed": "unsupported",
2757+ "frequencyPenalty": "conditional",
2758+ "presencePenalty": "conditional",
2759+ "verbosity": "supported"
2760+ },
2761+ "pricing": {
2762+ "inputPerMillion": 2.5,
2763+ "cachedInputPerMillion": 0.25,
2764+ "outputPerMillion": 15
2765+ },
2766+ "status": "active",
2767+ "notes": "Dated snapshot of gpt-5.4. Snapshot gpt-5.4-2026-03-05. Default effort 'none' (verified echo) so sampling params work by default; assumed rejected once effort >= low (pattern verified on gpt-5.5/5.6). Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2768+ "reasoningEfforts": [
2769+ "none",
2770+ "low",
2771+ "medium",
2772+ "high",
2773+ "xhigh"
2774+ ],
2775+ "defaultReasoningEffort": "none",
2776+ "apis": [
2777+ "responses",
2778+ "chat",
2779+ "batch"
2780+ ],
2781+ "knowledgeCutoff": "2025-08-31",
2782+ "shutdownDate": null,
2783+ "snapshotOf": "gpt-5.4"
2784+ },
2785+ {
2786+ "id": "gpt-5.4-mini",
2787+ "displayName": "GPT-5.4 mini",
2788+ "family": "gpt-5.4",
2789+ "contextTokens": 400000,
2790+ "maxOutputTokens": 128000,
2791+ "capabilities": {
2792+ "text": true,
2793+ "vision": true,
2794+ "audioInput": false,
2795+ "audioOutput": false,
2796+ "imageGeneration": true,
2797+ "video": false,
2798+ "reasoning": true,
2799+ "tools": true,
2800+ "structuredOutput": true,
2801+ "streaming": true,
2802+ "files": true,
2803+ "webSearch": true
2804+ },
2805+ "parameters": {
2806+ "temperature": "conditional",
2807+ "topP": "conditional",
2808+ "topK": "unsupported",
2809+ "maxTokens": "supported",
2810+ "reasoningEffort": "supported",
2811+ "thinkingBudget": "unsupported",
2812+ "stop": "unsupported",
2813+ "seed": "unsupported",
2814+ "frequencyPenalty": "conditional",
2815+ "presencePenalty": "conditional",
2816+ "verbosity": "supported"
2817+ },
2818+ "pricing": {
2819+ "inputPerMillion": 0.75,
2820+ "cachedInputPerMillion": 0.075,
2821+ "outputPerMillion": 4.5
2822+ },
2823+ "status": "active",
2824+ "notes": "Snapshot gpt-5.4-mini-2026-03-17. Default effort 'none': temperature, top_p, frequency_penalty, presence_penalty, logprobs all ACCEPTED at default (verified). 'minimal'/'max' rejected. PDF input (input_file file_data) verified. previous_response_id verified. service_tier 'flex' accepted. Verified by probe: basic, stream, params, tools(+previous_response_id), structured, vision, web_search, pdf, flex. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2825+ "reasoningEfforts": [
2826+ "none",
2827+ "low",
2828+ "medium",
2829+ "high",
2830+ "xhigh"
2831+ ],
2832+ "defaultReasoningEffort": "none",
2833+ "apis": [
2834+ "responses",
2835+ "chat",
2836+ "batch"
2837+ ],
2838+ "knowledgeCutoff": "2025-08-31",
2839+ "shutdownDate": null,
2840+ "snapshotOf": null
2841+ },
2842+ {
2843+ "id": "gpt-5.4-mini-2026-03-17",
2844+ "displayName": "GPT-5.4 mini (2026-03-17)",
2845+ "family": "gpt-5.4",
2846+ "contextTokens": 400000,
2847+ "maxOutputTokens": 128000,
2848+ "capabilities": {
2849+ "text": true,
2850+ "vision": true,
2851+ "audioInput": false,
2852+ "audioOutput": false,
2853+ "imageGeneration": true,
2854+ "video": false,
2855+ "reasoning": true,
2856+ "tools": true,
2857+ "structuredOutput": true,
2858+ "streaming": true,
2859+ "files": true,
2860+ "webSearch": true
2861+ },
2862+ "parameters": {
2863+ "temperature": "conditional",
2864+ "topP": "conditional",
2865+ "topK": "unsupported",
2866+ "maxTokens": "supported",
2867+ "reasoningEffort": "supported",
2868+ "thinkingBudget": "unsupported",
2869+ "stop": "unsupported",
2870+ "seed": "unsupported",
2871+ "frequencyPenalty": "conditional",
2872+ "presencePenalty": "conditional",
2873+ "verbosity": "supported"
2874+ },
2875+ "pricing": {
2876+ "inputPerMillion": 0.75,
2877+ "cachedInputPerMillion": 0.075,
2878+ "outputPerMillion": 4.5
2879+ },
2880+ "status": "active",
2881+ "notes": "Dated snapshot of gpt-5.4-mini. Snapshot gpt-5.4-mini-2026-03-17. Default effort 'none': temperature, top_p, frequency_penalty, presence_penalty, logprobs all ACCEPTED at default (verified). 'minimal'/'max' rejected. PDF input (input_file file_data) verified. previous_response_id verified. service_tier 'flex' accepted. Verified by probe: basic, stream, params, tools(+previous_response_id), structured, vision, web_search, pdf, flex. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2882+ "reasoningEfforts": [
2883+ "none",
2884+ "low",
2885+ "medium",
2886+ "high",
2887+ "xhigh"
2888+ ],
2889+ "defaultReasoningEffort": "none",
2890+ "apis": [
2891+ "responses",
2892+ "chat",
2893+ "batch"
2894+ ],
2895+ "knowledgeCutoff": "2025-08-31",
2896+ "shutdownDate": null,
2897+ "snapshotOf": "gpt-5.4-mini"
2898+ },
2899+ {
2900+ "id": "gpt-5.4-nano",
2901+ "displayName": "GPT-5.4 nano",
2902+ "family": "gpt-5.4",
2903+ "contextTokens": 400000,
2904+ "maxOutputTokens": 128000,
2905+ "capabilities": {
2906+ "text": true,
2907+ "vision": true,
2908+ "audioInput": false,
2909+ "audioOutput": false,
2910+ "imageGeneration": true,
2911+ "video": false,
2912+ "reasoning": true,
2913+ "tools": true,
2914+ "structuredOutput": true,
2915+ "streaming": true,
2916+ "files": true,
2917+ "webSearch": true
2918+ },
2919+ "parameters": {
2920+ "temperature": "conditional",
2921+ "topP": "conditional",
2922+ "topK": "unsupported",
2923+ "maxTokens": "supported",
2924+ "reasoningEffort": "supported",
2925+ "thinkingBudget": "unsupported",
2926+ "stop": "unsupported",
2927+ "seed": "unsupported",
2928+ "frequencyPenalty": "conditional",
2929+ "presencePenalty": "conditional",
2930+ "verbosity": "supported"
2931+ },
2932+ "pricing": {
2933+ "inputPerMillion": 0.2,
2934+ "cachedInputPerMillion": 0.02,
2935+ "outputPerMillion": 1.25
2936+ },
2937+ "status": "active",
2938+ "notes": "Snapshot gpt-5.4-nano-2026-03-17. Model page lists web_search among tools but computer use/tool_search absent. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2939+ "reasoningEfforts": [
2940+ "none",
2941+ "low",
2942+ "medium",
2943+ "high",
2944+ "xhigh"
2945+ ],
2946+ "defaultReasoningEffort": "none",
2947+ "apis": [
2948+ "responses",
2949+ "chat",
2950+ "batch"
2951+ ],
2952+ "knowledgeCutoff": "2025-08-31",
2953+ "shutdownDate": null,
2954+ "snapshotOf": null
2955+ },
2956+ {
2957+ "id": "gpt-5.4-nano-2026-03-17",
2958+ "displayName": "GPT-5.4 nano (2026-03-17)",
2959+ "family": "gpt-5.4",
2960+ "contextTokens": 400000,
2961+ "maxOutputTokens": 128000,
2962+ "capabilities": {
2963+ "text": true,
2964+ "vision": true,
2965+ "audioInput": false,
2966+ "audioOutput": false,
2967+ "imageGeneration": true,
2968+ "video": false,
2969+ "reasoning": true,
2970+ "tools": true,
2971+ "structuredOutput": true,
2972+ "streaming": true,
2973+ "files": true,
2974+ "webSearch": true
2975+ },
2976+ "parameters": {
2977+ "temperature": "conditional",
2978+ "topP": "conditional",
2979+ "topK": "unsupported",
2980+ "maxTokens": "supported",
2981+ "reasoningEffort": "supported",
2982+ "thinkingBudget": "unsupported",
2983+ "stop": "unsupported",
2984+ "seed": "unsupported",
2985+ "frequencyPenalty": "conditional",
2986+ "presencePenalty": "conditional",
2987+ "verbosity": "supported"
2988+ },
2989+ "pricing": {
2990+ "inputPerMillion": 0.2,
2991+ "cachedInputPerMillion": 0.02,
2992+ "outputPerMillion": 1.25
2993+ },
2994+ "status": "active",
2995+ "notes": "Dated snapshot of gpt-5.4-nano. Snapshot gpt-5.4-nano-2026-03-17. Model page lists web_search among tools but computer use/tool_search absent. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
2996+ "reasoningEfforts": [
2997+ "none",
2998+ "low",
2999+ "medium",
3000+ "high",
3001+ "xhigh"
3002+ ],
3003+ "defaultReasoningEffort": "none",
3004+ "apis": [
3005+ "responses",
3006+ "chat",
3007+ "batch"
3008+ ],
3009+ "knowledgeCutoff": "2025-08-31",
3010+ "shutdownDate": null,
3011+ "snapshotOf": "gpt-5.4-nano"
3012+ },
3013+ {
3014+ "id": "gpt-5.4-pro",
3015+ "displayName": "GPT-5.4 Pro",
3016+ "family": "gpt-5.4",
3017+ "contextTokens": 1050000,
3018+ "maxOutputTokens": 128000,
3019+ "capabilities": {
3020+ "text": true,
3021+ "vision": true,
3022+ "audioInput": false,
3023+ "audioOutput": false,
3024+ "imageGeneration": true,
3025+ "video": false,
3026+ "reasoning": true,
3027+ "tools": true,
3028+ "structuredOutput": null,
3029+ "streaming": true,
3030+ "files": true,
3031+ "webSearch": true
3032+ },
3033+ "parameters": {
3034+ "temperature": "unsupported",
3035+ "topP": "unsupported",
3036+ "topK": "unsupported",
3037+ "maxTokens": "supported",
3038+ "reasoningEffort": "supported",
3039+ "thinkingBudget": "unsupported",
3040+ "stop": "unsupported",
3041+ "seed": "unsupported",
3042+ "frequencyPenalty": "unsupported",
3043+ "presencePenalty": "unsupported",
3044+ "verbosity": "supported"
3045+ },
3046+ "pricing": {
3047+ "inputPerMillion": 30,
3048+ "cachedInputPerMillion": null,
3049+ "outputPerMillion": 180
3050+ },
3051+ "status": "active",
3052+ "notes": "Responses API only. Not probed (cost). Docs: no structured outputs listed for pro variants of 5.4? (page lists function calling, web search, MCP; structured outputs not listed) -> structuredOutput null. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3053+ "reasoningEfforts": [
3054+ "medium",
3055+ "high",
3056+ "xhigh"
3057+ ],
3058+ "defaultReasoningEffort": "medium",
3059+ "apis": [
3060+ "responses"
3061+ ],
3062+ "knowledgeCutoff": "2025-08-31",
3063+ "shutdownDate": null,
3064+ "snapshotOf": null
3065+ },
3066+ {
3067+ "id": "gpt-5.4-pro-2026-03-05",
3068+ "displayName": "GPT-5.4 Pro (2026-03-05)",
3069+ "family": "gpt-5.4",
3070+ "contextTokens": 1050000,
3071+ "maxOutputTokens": 128000,
3072+ "capabilities": {
3073+ "text": true,
3074+ "vision": true,
3075+ "audioInput": false,
3076+ "audioOutput": false,
3077+ "imageGeneration": true,
3078+ "video": false,
3079+ "reasoning": true,
3080+ "tools": true,
3081+ "structuredOutput": null,
3082+ "streaming": true,
3083+ "files": true,
3084+ "webSearch": true
3085+ },
3086+ "parameters": {
3087+ "temperature": "unsupported",
3088+ "topP": "unsupported",
3089+ "topK": "unsupported",
3090+ "maxTokens": "supported",
3091+ "reasoningEffort": "supported",
3092+ "thinkingBudget": "unsupported",
3093+ "stop": "unsupported",
3094+ "seed": "unsupported",
3095+ "frequencyPenalty": "unsupported",
3096+ "presencePenalty": "unsupported",
3097+ "verbosity": "supported"
3098+ },
3099+ "pricing": {
3100+ "inputPerMillion": 30,
3101+ "cachedInputPerMillion": null,
3102+ "outputPerMillion": 180
3103+ },
3104+ "status": "active",
3105+ "notes": "Dated snapshot of gpt-5.4-pro. Responses API only. Not probed (cost). Docs: no structured outputs listed for pro variants of 5.4? (page lists function calling, web search, MCP; structured outputs not listed) -> structuredOutput null. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3106+ "reasoningEfforts": [
3107+ "medium",
3108+ "high",
3109+ "xhigh"
3110+ ],
3111+ "defaultReasoningEffort": "medium",
3112+ "apis": [
3113+ "responses"
3114+ ],
3115+ "knowledgeCutoff": "2025-08-31",
3116+ "shutdownDate": null,
3117+ "snapshotOf": "gpt-5.4-pro"
3118+ },
3119+ {
3120+ "id": "gpt-5.5",
3121+ "displayName": "GPT-5.5",
3122+ "family": "gpt-5.5",
3123+ "contextTokens": 1050000,
3124+ "maxOutputTokens": 128000,
3125+ "capabilities": {
3126+ "text": true,
3127+ "vision": true,
3128+ "audioInput": false,
3129+ "audioOutput": false,
3130+ "imageGeneration": true,
3131+ "video": false,
3132+ "reasoning": true,
3133+ "tools": true,
3134+ "structuredOutput": true,
3135+ "streaming": true,
3136+ "files": true,
3137+ "webSearch": true
3138+ },
3139+ "parameters": {
3140+ "temperature": "conditional",
3141+ "topP": "conditional",
3142+ "topK": "unsupported",
3143+ "maxTokens": "supported",
3144+ "reasoningEffort": "supported",
3145+ "thinkingBudget": "unsupported",
3146+ "stop": "unsupported",
3147+ "seed": "unsupported",
3148+ "frequencyPenalty": "conditional",
3149+ "presencePenalty": "conditional",
3150+ "verbosity": "supported"
3151+ },
3152+ "pricing": {
3153+ "inputPerMillion": 5,
3154+ "cachedInputPerMillion": 0.5,
3155+ "outputPerMillion": 30
3156+ },
3157+ "status": "active",
3158+ "notes": "Snapshot gpt-5.5-2026-04-23. 'minimal' and 'max' efforts rejected (400 unsupported_value). temperature/top_p/penalties rejected unless reasoning.effort='none' (verified both ways). >272K input tokens billed 2x/1.5x. Default top_p echoed as 0.98. Chat Completions: temperature other than 1 rejected ('Only the default (1) value is supported'). Verified by probe: basic, stream, params, tools(+round trip), structured, vision(effort none), web_search (url_citation annotations), encrypted reasoning round trip, chat completions. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3159+ "reasoningEfforts": [
3160+ "none",
3161+ "low",
3162+ "medium",
3163+ "high",
3164+ "xhigh"
3165+ ],
3166+ "defaultReasoningEffort": "medium",
3167+ "apis": [
3168+ "responses",
3169+ "chat",
3170+ "batch"
3171+ ],
3172+ "knowledgeCutoff": "2025-12-01",
3173+ "shutdownDate": null,
3174+ "snapshotOf": null
3175+ },
3176+ {
3177+ "id": "gpt-5.5-2026-04-23",
3178+ "displayName": "GPT-5.5 (2026-04-23)",
3179+ "family": "gpt-5.5",
3180+ "contextTokens": 1050000,
3181+ "maxOutputTokens": 128000,
3182+ "capabilities": {
3183+ "text": true,
3184+ "vision": true,
3185+ "audioInput": false,
3186+ "audioOutput": false,
3187+ "imageGeneration": true,
3188+ "video": false,
3189+ "reasoning": true,
3190+ "tools": true,
3191+ "structuredOutput": true,
3192+ "streaming": true,
3193+ "files": true,
3194+ "webSearch": true
3195+ },
3196+ "parameters": {
3197+ "temperature": "conditional",
3198+ "topP": "conditional",
3199+ "topK": "unsupported",
3200+ "maxTokens": "supported",
3201+ "reasoningEffort": "supported",
3202+ "thinkingBudget": "unsupported",
3203+ "stop": "unsupported",
3204+ "seed": "unsupported",
3205+ "frequencyPenalty": "conditional",
3206+ "presencePenalty": "conditional",
3207+ "verbosity": "supported"
3208+ },
3209+ "pricing": {
3210+ "inputPerMillion": 5,
3211+ "cachedInputPerMillion": 0.5,
3212+ "outputPerMillion": 30
3213+ },
3214+ "status": "active",
3215+ "notes": "Dated snapshot of gpt-5.5. Snapshot gpt-5.5-2026-04-23. 'minimal' and 'max' efforts rejected (400 unsupported_value). temperature/top_p/penalties rejected unless reasoning.effort='none' (verified both ways). >272K input tokens billed 2x/1.5x. Default top_p echoed as 0.98. Chat Completions: temperature other than 1 rejected ('Only the default (1) value is supported'). Verified by probe: basic, stream, params, tools(+round trip), structured, vision(effort none), web_search (url_citation annotations), encrypted reasoning round trip, chat completions. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3216+ "reasoningEfforts": [
3217+ "none",
3218+ "low",
3219+ "medium",
3220+ "high",
3221+ "xhigh"
3222+ ],
3223+ "defaultReasoningEffort": "medium",
3224+ "apis": [
3225+ "responses",
3226+ "chat",
3227+ "batch"
3228+ ],
3229+ "knowledgeCutoff": "2025-12-01",
3230+ "shutdownDate": null,
3231+ "snapshotOf": "gpt-5.5"
3232+ },
3233+ {
3234+ "id": "gpt-5.5-pro",
3235+ "displayName": "GPT-5.5 Pro",
3236+ "family": "gpt-5.5",
3237+ "contextTokens": 1050000,
3238+ "maxOutputTokens": 128000,
3239+ "capabilities": {
3240+ "text": true,
3241+ "vision": true,
3242+ "audioInput": false,
3243+ "audioOutput": false,
3244+ "imageGeneration": true,
3245+ "video": false,
3246+ "reasoning": true,
3247+ "tools": true,
3248+ "structuredOutput": true,
3249+ "streaming": true,
3250+ "files": true,
3251+ "webSearch": true
3252+ },
3253+ "parameters": {
3254+ "temperature": "unsupported",
3255+ "topP": "unsupported",
3256+ "topK": "unsupported",
3257+ "maxTokens": "supported",
3258+ "reasoningEffort": "supported",
3259+ "thinkingBudget": "unsupported",
3260+ "stop": "unsupported",
3261+ "seed": "unsupported",
3262+ "frequencyPenalty": "unsupported",
3263+ "presencePenalty": "unsupported",
3264+ "verbosity": "supported"
3265+ },
3266+ "pricing": {
3267+ "inputPerMillion": 30,
3268+ "cachedInputPerMillion": null,
3269+ "outputPerMillion": 180
3270+ },
3271+ "status": "active",
3272+ "notes": "Responses API only (no Chat Completions). No cached-input price. Slow: docs recommend background:true. One tiny probe answered in 7.3 s. Docs: streaming listed but not verified. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3273+ "reasoningEfforts": [
3274+ "medium",
3275+ "high",
3276+ "xhigh"
3277+ ],
3278+ "defaultReasoningEffort": "high",
3279+ "apis": [
3280+ "responses",
3281+ "batch"
3282+ ],
3283+ "knowledgeCutoff": "2025-12-01",
3284+ "shutdownDate": null,
3285+ "snapshotOf": null
3286+ },
3287+ {
3288+ "id": "gpt-5.5-pro-2026-04-23",
3289+ "displayName": "GPT-5.5 Pro (2026-04-23)",
3290+ "family": "gpt-5.5",
3291+ "contextTokens": 1050000,
3292+ "maxOutputTokens": 128000,
3293+ "capabilities": {
3294+ "text": true,
3295+ "vision": true,
3296+ "audioInput": false,
3297+ "audioOutput": false,
3298+ "imageGeneration": true,
3299+ "video": false,
3300+ "reasoning": true,
3301+ "tools": true,
3302+ "structuredOutput": true,
3303+ "streaming": true,
3304+ "files": true,
3305+ "webSearch": true
3306+ },
3307+ "parameters": {
3308+ "temperature": "unsupported",
3309+ "topP": "unsupported",
3310+ "topK": "unsupported",
3311+ "maxTokens": "supported",
3312+ "reasoningEffort": "supported",
3313+ "thinkingBudget": "unsupported",
3314+ "stop": "unsupported",
3315+ "seed": "unsupported",
3316+ "frequencyPenalty": "unsupported",
3317+ "presencePenalty": "unsupported",
3318+ "verbosity": "supported"
3319+ },
3320+ "pricing": {
3321+ "inputPerMillion": 30,
3322+ "cachedInputPerMillion": null,
3323+ "outputPerMillion": 180
3324+ },
3325+ "status": "active",
3326+ "notes": "Dated snapshot of gpt-5.5-pro. Responses API only (no Chat Completions). No cached-input price. Slow: docs recommend background:true. One tiny probe answered in 7.3 s. Docs: streaming listed but not verified. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3327+ "reasoningEfforts": [
3328+ "medium",
3329+ "high",
3330+ "xhigh"
3331+ ],
3332+ "defaultReasoningEffort": "high",
3333+ "apis": [
3334+ "responses",
3335+ "batch"
3336+ ],
3337+ "knowledgeCutoff": "2025-12-01",
3338+ "shutdownDate": null,
3339+ "snapshotOf": "gpt-5.5-pro"
3340+ },
3341+ {
3342+ "id": "gpt-5.6-luna",
3343+ "displayName": "GPT-5.6 Luna",
3344+ "family": "gpt-5.6",
3345+ "contextTokens": 1050000,
3346+ "maxOutputTokens": 128000,
3347+ "capabilities": {
3348+ "text": true,
3349+ "vision": true,
3350+ "audioInput": false,
3351+ "audioOutput": false,
3352+ "imageGeneration": true,
3353+ "video": false,
3354+ "reasoning": true,
3355+ "tools": true,
3356+ "structuredOutput": true,
3357+ "streaming": true,
3358+ "files": true,
3359+ "webSearch": true
3360+ },
3361+ "parameters": {
3362+ "temperature": "conditional",
3363+ "topP": "conditional",
3364+ "topK": "unsupported",
3365+ "maxTokens": "supported",
3366+ "reasoningEffort": "supported",
3367+ "thinkingBudget": "unsupported",
3368+ "stop": "unsupported",
3369+ "seed": "unsupported",
3370+ "frequencyPenalty": "conditional",
3371+ "presencePenalty": "conditional",
3372+ "verbosity": "supported"
3373+ },
3374+ "pricing": {
3375+ "inputPerMillion": 0.2,
3376+ "cachedInputPerMillion": 0.02,
3377+ "outputPerMillion": 1.2
3378+ },
3379+ "status": "active",
3380+ "notes": "Cheapest 5.6. Recommended replacement for gpt-5-nano and gpt-4.1-nano. Param matrix assumed identical to gpt-5.6-sol (not individually probed). Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3381+ "reasoningEfforts": [
3382+ "none",
3383+ "low",
3384+ "medium",
3385+ "high",
3386+ "xhigh",
3387+ "max"
3388+ ],
3389+ "defaultReasoningEffort": "medium",
3390+ "apis": [
3391+ "responses",
3392+ "chat",
3393+ "batch"
3394+ ],
3395+ "knowledgeCutoff": "2026-02-16",
3396+ "shutdownDate": null,
3397+ "snapshotOf": null
3398+ },
3399+ {
3400+ "id": "gpt-5.6-sol",
3401+ "displayName": "GPT-5.6 Sol",
3402+ "family": "gpt-5.6",
3403+ "contextTokens": 1050000,
3404+ "maxOutputTokens": 128000,
3405+ "capabilities": {
3406+ "text": true,
3407+ "vision": true,
3408+ "audioInput": false,
3409+ "audioOutput": false,
3410+ "imageGeneration": true,
3411+ "video": false,
3412+ "reasoning": true,
3413+ "tools": true,
3414+ "structuredOutput": true,
3415+ "streaming": true,
3416+ "files": true,
3417+ "webSearch": true
3418+ },
3419+ "parameters": {
3420+ "temperature": "conditional",
3421+ "topP": "conditional",
3422+ "topK": "unsupported",
3423+ "maxTokens": "supported",
3424+ "reasoningEffort": "supported",
3425+ "thinkingBudget": "unsupported",
3426+ "stop": "unsupported",
3427+ "seed": "unsupported",
3428+ "frequencyPenalty": "conditional",
3429+ "presencePenalty": "conditional",
3430+ "verbosity": "supported"
3431+ },
3432+ "pricing": {
3433+ "inputPerMillion": 4,
3434+ "cachedInputPerMillion": 0.4,
3435+ "outputPerMillion": 20
3436+ },
3437+ "status": "active",
3438+ "notes": "Alias 'gpt-5.6' resolves here (verified: response.model = gpt-5.6-sol). temperature/top_p/penalties rejected unless reasoning.effort='none' (verified). Supports reasoning.mode 'standard'|'pro' (pro = replacement for *-pro models, not probed), reasoning.context all_turns (default), prompt_cache_options.ttl '30m', explicit cache breakpoints. Recommended replacement for gpt-5, o3, gpt-4o, o1, gpt-4-turbo. Verified by probe: basic, stream (reasoning_summary events seen), params, tools, structured, vision(effort none). Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3439+ "reasoningEfforts": [
3440+ "none",
3441+ "low",
3442+ "medium",
3443+ "high",
3444+ "xhigh",
3445+ "max"
3446+ ],
3447+ "defaultReasoningEffort": "medium",
3448+ "apis": [
3449+ "responses",
3450+ "chat",
3451+ "batch"
3452+ ],
3453+ "knowledgeCutoff": "2026-02-16",
3454+ "shutdownDate": null,
3455+ "snapshotOf": null
3456+ },
3457+ {
3458+ "id": "gpt-5.6-terra",
3459+ "displayName": "GPT-5.6 Terra",
3460+ "family": "gpt-5.6",
3461+ "contextTokens": 1050000,
3462+ "maxOutputTokens": 128000,
3463+ "capabilities": {
3464+ "text": true,
3465+ "vision": true,
3466+ "audioInput": false,
3467+ "audioOutput": false,
3468+ "imageGeneration": true,
3469+ "video": false,
3470+ "reasoning": true,
3471+ "tools": true,
3472+ "structuredOutput": true,
3473+ "streaming": true,
3474+ "files": true,
3475+ "webSearch": true
3476+ },
3477+ "parameters": {
3478+ "temperature": "conditional",
3479+ "topP": "conditional",
3480+ "topK": "unsupported",
3481+ "maxTokens": "supported",
3482+ "reasoningEffort": "supported",
3483+ "thinkingBudget": "unsupported",
3484+ "stop": "unsupported",
3485+ "seed": "unsupported",
3486+ "frequencyPenalty": "conditional",
3487+ "presencePenalty": "conditional",
3488+ "verbosity": "supported"
3489+ },
3490+ "pricing": {
3491+ "inputPerMillion": 2,
3492+ "cachedInputPerMillion": 0.2,
3493+ "outputPerMillion": 12
3494+ },
3495+ "status": "active",
3496+ "notes": "Max input 922,000 tokens. Recommended replacement for gpt-5-mini, o4-mini, gpt-3.5-turbo. Param matrix assumed identical to gpt-5.6-sol (not individually probed). Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3497+ "reasoningEfforts": [
3498+ "none",
3499+ "low",
3500+ "medium",
3501+ "high",
3502+ "xhigh",
3503+ "max"
3504+ ],
3505+ "defaultReasoningEffort": "medium",
3506+ "apis": [
3507+ "responses",
3508+ "chat",
3509+ "batch"
3510+ ],
3511+ "knowledgeCutoff": "2026-02-16",
3512+ "shutdownDate": null,
3513+ "snapshotOf": null
3514+ },
3515+ {
3516+ "id": "gpt-6-astra",
3517+ "displayName": "GPT-6 Astra",
3518+ "family": "gpt-6",
3519+ "contextTokens": 1050000,
3520+ "maxOutputTokens": 128000,
3521+ "capabilities": {
3522+ "text": true,
3523+ "vision": true,
3524+ "audioInput": false,
3525+ "audioOutput": false,
3526+ "imageGeneration": true,
3527+ "video": false,
3528+ "reasoning": true,
3529+ "tools": true,
3530+ "structuredOutput": true,
3531+ "streaming": true,
3532+ "files": true,
3533+ "webSearch": true
3534+ },
3535+ "parameters": {
3536+ "temperature": "unsupported",
3537+ "topP": "unsupported",
3538+ "topK": "unsupported",
3539+ "maxTokens": "supported",
3540+ "reasoningEffort": "supported",
3541+ "thinkingBudget": "unsupported",
3542+ "stop": "unsupported",
3543+ "seed": "unsupported",
3544+ "frequencyPenalty": "unsupported",
3545+ "presencePenalty": "unsupported",
3546+ "verbosity": "supported"
3547+ },
3548+ "pricing": {
3549+ "inputPerMillion": 10,
3550+ "cachedInputPerMillion": 1,
3551+ "outputPerMillion": 50
3552+ },
3553+ "status": "active",
3554+ "notes": "Flagship. reasoning.effort 'none'/'minimal' rejected (400 unsupported_value). temperature/top_p/frequency_penalty/presence_penalty rejected ('Unsupported parameter ... is not supported with this model'); logprobs rejected. Cache write $12.50/M; >272K input tokens billed 2x input / 1.5x output. reasoning.context defaults to all_turns. prompt_cache_retention accepted but docs say use prompt_cache_options.ttl='30m'. Verified by probe: basic, stream, params, tools, structured, vision(detail high, effort low), chat completions. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3555+ "reasoningEfforts": [
3556+ "low",
3557+ "medium",
3558+ "high",
3559+ "xhigh",
3560+ "max"
3561+ ],
3562+ "defaultReasoningEffort": "medium",
3563+ "apis": [
3564+ "responses",
3565+ "chat",
3566+ "batch"
3567+ ],
3568+ "knowledgeCutoff": "2026-04-30",
3569+ "shutdownDate": null,
3570+ "snapshotOf": null
3571+ },
3572+ {
3573+ "id": "o1",
3574+ "displayName": "o1",
3575+ "family": "o-series",
3576+ "contextTokens": 200000,
3577+ "maxOutputTokens": 100000,
3578+ "capabilities": {
3579+ "text": true,
3580+ "vision": true,
3581+ "audioInput": false,
3582+ "audioOutput": false,
3583+ "imageGeneration": false,
3584+ "video": false,
3585+ "reasoning": true,
3586+ "tools": true,
3587+ "structuredOutput": true,
3588+ "streaming": true,
3589+ "files": true,
3590+ "webSearch": false
3591+ },
3592+ "parameters": {
3593+ "temperature": "unsupported",
3594+ "topP": "unsupported",
3595+ "topK": "unsupported",
3596+ "maxTokens": "supported",
3597+ "reasoningEffort": "supported",
3598+ "thinkingBudget": "unsupported",
3599+ "stop": "unsupported",
3600+ "seed": "unsupported",
3601+ "frequencyPenalty": "unsupported",
3602+ "presencePenalty": "unsupported",
3603+ "verbosity": "unsupported"
3604+ },
3605+ "pricing": {
3606+ "inputPerMillion": 15,
3607+ "cachedInputPerMillion": 7.5,
3608+ "outputPerMillion": 60
3609+ },
3610+ "status": "deprecated",
3611+ "notes": "shutdown_date (from GET /v1/models): 2026-10-23. shutdown_date 2026-10-23 -> gpt-5.6-sol. Still answers (verified; 32-token probe came back incomplete because of reasoning). Verified by probe: basic (incomplete). Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3612+ "reasoningEfforts": [
3613+ "low",
3614+ "medium",
3615+ "high"
3616+ ],
3617+ "defaultReasoningEffort": "medium",
3618+ "apis": [
3619+ "responses",
3620+ "chat",
3621+ "batch",
3622+ "assistants"
3623+ ],
3624+ "knowledgeCutoff": "2023-10-01",
3625+ "shutdownDate": "2026-10-23",
3626+ "snapshotOf": null
3627+ },
3628+ {
3629+ "id": "o1-2024-12-17",
3630+ "displayName": "o1 (2024-12-17)",
3631+ "family": "o-series",
3632+ "contextTokens": 200000,
3633+ "maxOutputTokens": 100000,
3634+ "capabilities": {
3635+ "text": true,
3636+ "vision": true,
3637+ "audioInput": false,
3638+ "audioOutput": false,
3639+ "imageGeneration": false,
3640+ "video": false,
3641+ "reasoning": true,
3642+ "tools": true,
3643+ "structuredOutput": true,
3644+ "streaming": true,
3645+ "files": true,
3646+ "webSearch": false
3647+ },
3648+ "parameters": {
3649+ "temperature": "unsupported",
3650+ "topP": "unsupported",
3651+ "topK": "unsupported",
3652+ "maxTokens": "supported",
3653+ "reasoningEffort": "supported",
3654+ "thinkingBudget": "unsupported",
3655+ "stop": "unsupported",
3656+ "seed": "unsupported",
3657+ "frequencyPenalty": "unsupported",
3658+ "presencePenalty": "unsupported",
3659+ "verbosity": "unsupported"
3660+ },
3661+ "pricing": {
3662+ "inputPerMillion": 15,
3663+ "cachedInputPerMillion": 7.5,
3664+ "outputPerMillion": 60
3665+ },
3666+ "status": "deprecated",
3667+ "notes": "Dated snapshot of o1. shutdown_date (from GET /v1/models): 2026-10-23. shutdown_date 2026-10-23 -> gpt-5.6-sol. Still answers (verified; 32-token probe came back incomplete because of reasoning). Verified by probe: basic (incomplete). Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3668+ "reasoningEfforts": [
3669+ "low",
3670+ "medium",
3671+ "high"
3672+ ],
3673+ "defaultReasoningEffort": "medium",
3674+ "apis": [
3675+ "responses",
3676+ "chat",
3677+ "batch",
3678+ "assistants"
3679+ ],
3680+ "knowledgeCutoff": "2023-10-01",
3681+ "shutdownDate": "2026-10-23",
3682+ "snapshotOf": "o1"
3683+ },
3684+ {
3685+ "id": "o1-pro",
3686+ "displayName": "o1-pro",
3687+ "family": "o-series",
3688+ "contextTokens": 200000,
3689+ "maxOutputTokens": 100000,
3690+ "capabilities": {
3691+ "text": true,
3692+ "vision": true,
3693+ "audioInput": false,
3694+ "audioOutput": false,
3695+ "imageGeneration": false,
3696+ "video": false,
3697+ "reasoning": true,
3698+ "tools": true,
3699+ "structuredOutput": true,
3700+ "streaming": true,
3701+ "files": true,
3702+ "webSearch": false
3703+ },
3704+ "parameters": {
3705+ "temperature": "unsupported",
3706+ "topP": "unsupported",
3707+ "topK": "unsupported",
3708+ "maxTokens": "supported",
3709+ "reasoningEffort": "supported",
3710+ "thinkingBudget": "unsupported",
3711+ "stop": "unsupported",
3712+ "seed": "unsupported",
3713+ "frequencyPenalty": "unsupported",
3714+ "presencePenalty": "unsupported",
3715+ "verbosity": "unsupported"
3716+ },
3717+ "pricing": {
3718+ "inputPerMillion": 150,
3719+ "cachedInputPerMillion": null,
3720+ "outputPerMillion": 600
3721+ },
3722+ "status": "deprecated",
3723+ "notes": "shutdown_date (from GET /v1/models): 2026-10-23. shutdown_date 2026-10-23 -> gpt-5.6-sol with reasoning.mode pro. Responses only. Not probed (cost). Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3724+ "reasoningEfforts": null,
3725+ "defaultReasoningEffort": null,
3726+ "apis": [
3727+ "responses",
3728+ "batch"
3729+ ],
3730+ "knowledgeCutoff": null,
3731+ "shutdownDate": "2026-10-23",
3732+ "snapshotOf": null
3733+ },
3734+ {
3735+ "id": "o1-pro-2025-03-19",
3736+ "displayName": "o1-pro (2025-03-19)",
3737+ "family": "o-series",
3738+ "contextTokens": 200000,
3739+ "maxOutputTokens": 100000,
3740+ "capabilities": {
3741+ "text": true,
3742+ "vision": true,
3743+ "audioInput": false,
3744+ "audioOutput": false,
3745+ "imageGeneration": false,
3746+ "video": false,
3747+ "reasoning": true,
3748+ "tools": true,
3749+ "structuredOutput": true,
3750+ "streaming": true,
3751+ "files": true,
3752+ "webSearch": false
3753+ },
3754+ "parameters": {
3755+ "temperature": "unsupported",
3756+ "topP": "unsupported",
3757+ "topK": "unsupported",
3758+ "maxTokens": "supported",
3759+ "reasoningEffort": "supported",
3760+ "thinkingBudget": "unsupported",
3761+ "stop": "unsupported",
3762+ "seed": "unsupported",
3763+ "frequencyPenalty": "unsupported",
3764+ "presencePenalty": "unsupported",
3765+ "verbosity": "unsupported"
3766+ },
3767+ "pricing": {
3768+ "inputPerMillion": 150,
3769+ "cachedInputPerMillion": null,
3770+ "outputPerMillion": 600
3771+ },
3772+ "status": "deprecated",
3773+ "notes": "Dated snapshot of o1-pro. shutdown_date (from GET /v1/models): 2026-10-23. shutdown_date 2026-10-23 -> gpt-5.6-sol with reasoning.mode pro. Responses only. Not probed (cost). Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3774+ "reasoningEfforts": null,
3775+ "defaultReasoningEffort": null,
3776+ "apis": [
3777+ "responses",
3778+ "batch"
3779+ ],
3780+ "knowledgeCutoff": null,
3781+ "shutdownDate": "2026-10-23",
3782+ "snapshotOf": "o1-pro"
3783+ },
3784+ {
3785+ "id": "o3",
3786+ "displayName": "o3",
3787+ "family": "o-series",
3788+ "contextTokens": 200000,
3789+ "maxOutputTokens": 100000,
3790+ "capabilities": {
3791+ "text": true,
3792+ "vision": true,
3793+ "audioInput": false,
3794+ "audioOutput": false,
3795+ "imageGeneration": true,
3796+ "video": false,
3797+ "reasoning": true,
3798+ "tools": true,
3799+ "structuredOutput": true,
3800+ "streaming": true,
3801+ "files": true,
3802+ "webSearch": true
3803+ },
3804+ "parameters": {
3805+ "temperature": "unsupported",
3806+ "topP": "unsupported",
3807+ "topK": "unsupported",
3808+ "maxTokens": "supported",
3809+ "reasoningEffort": "supported",
3810+ "thinkingBudget": "unsupported",
3811+ "stop": "unsupported",
3812+ "seed": "unsupported",
3813+ "frequencyPenalty": "unsupported",
3814+ "presencePenalty": "unsupported",
3815+ "verbosity": "unsupported"
3816+ },
3817+ "pricing": {
3818+ "inputPerMillion": 2,
3819+ "cachedInputPerMillion": 0.5,
3820+ "outputPerMillion": 8
3821+ },
3822+ "status": "active",
3823+ "notes": "Alias active; snapshot o3-2025-04-16 shuts down 2026-12-11 -> gpt-5.6-sol. Docs: 'o3 is succeeded by GPT-5'. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3824+ "reasoningEfforts": [
3825+ "low",
3826+ "medium",
3827+ "high"
3828+ ],
3829+ "defaultReasoningEffort": "medium",
3830+ "apis": [
3831+ "responses",
3832+ "chat",
3833+ "batch"
3834+ ],
3835+ "knowledgeCutoff": "2024-06-01",
3836+ "shutdownDate": null,
3837+ "snapshotOf": null
3838+ },
3839+ {
3840+ "id": "o3-2025-04-16",
3841+ "displayName": "o3 (2025-04-16)",
3842+ "family": "o-series",
3843+ "contextTokens": 200000,
3844+ "maxOutputTokens": 100000,
3845+ "capabilities": {
3846+ "text": true,
3847+ "vision": true,
3848+ "audioInput": false,
3849+ "audioOutput": false,
3850+ "imageGeneration": true,
3851+ "video": false,
3852+ "reasoning": true,
3853+ "tools": true,
3854+ "structuredOutput": true,
3855+ "streaming": true,
3856+ "files": true,
3857+ "webSearch": true
3858+ },
3859+ "parameters": {
3860+ "temperature": "unsupported",
3861+ "topP": "unsupported",
3862+ "topK": "unsupported",
3863+ "maxTokens": "supported",
3864+ "reasoningEffort": "supported",
3865+ "thinkingBudget": "unsupported",
3866+ "stop": "unsupported",
3867+ "seed": "unsupported",
3868+ "frequencyPenalty": "unsupported",
3869+ "presencePenalty": "unsupported",
3870+ "verbosity": "unsupported"
3871+ },
3872+ "pricing": {
3873+ "inputPerMillion": 2,
3874+ "cachedInputPerMillion": 0.5,
3875+ "outputPerMillion": 8
3876+ },
3877+ "status": "deprecated",
3878+ "notes": "Dated snapshot of o3. shutdown_date (from GET /v1/models): 2026-12-11. Alias active; snapshot o3-2025-04-16 shuts down 2026-12-11 -> gpt-5.6-sol. Docs: 'o3 is succeeded by GPT-5'. Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3879+ "reasoningEfforts": [
3880+ "low",
3881+ "medium",
3882+ "high"
3883+ ],
3884+ "defaultReasoningEffort": "medium",
3885+ "apis": [
3886+ "responses",
3887+ "chat",
3888+ "batch"
3889+ ],
3890+ "knowledgeCutoff": "2024-06-01",
3891+ "shutdownDate": "2026-12-11",
3892+ "snapshotOf": "o3"
3893+ },
3894+ {
3895+ "id": "o3-deep-research",
3896+ "displayName": "o3 Deep Research",
3897+ "family": "o-series",
3898+ "contextTokens": 200000,
3899+ "maxOutputTokens": 100000,
3900+ "capabilities": {
3901+ "text": true,
3902+ "vision": true,
3903+ "audioInput": false,
3904+ "audioOutput": false,
3905+ "imageGeneration": false,
3906+ "video": false,
3907+ "reasoning": true,
3908+ "tools": true,
3909+ "structuredOutput": true,
3910+ "streaming": true,
3911+ "files": true,
3912+ "webSearch": true
3913+ },
3914+ "parameters": {
3915+ "temperature": "unsupported",
3916+ "topP": "unsupported",
3917+ "topK": "unsupported",
3918+ "maxTokens": "supported",
3919+ "reasoningEffort": "supported",
3920+ "thinkingBudget": "unsupported",
3921+ "stop": "unsupported",
3922+ "seed": "unsupported",
3923+ "frequencyPenalty": "unsupported",
3924+ "presencePenalty": "unsupported",
3925+ "verbosity": "supported"
3926+ },
3927+ "pricing": {
3928+ "inputPerMillion": null,
3929+ "cachedInputPerMillion": null,
3930+ "outputPerMillion": null
3931+ },
3932+ "status": "deprecated",
3933+ "notes": "shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. shutdown_date 2026-07-23; 404 model_not_found (verified). Agentic research model, not a chat model. Verified by probe: basic -> 404. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3934+ "reasoningEfforts": null,
3935+ "defaultReasoningEffort": null,
3936+ "apis": [
3937+ "responses"
3938+ ],
3939+ "knowledgeCutoff": null,
3940+ "shutdownDate": "2026-07-23",
3941+ "snapshotOf": null
3942+ },
3943+ {
3944+ "id": "o3-deep-research-2025-06-26",
3945+ "displayName": "o3 Deep Research (2025-06-26)",
3946+ "family": "o-series",
3947+ "contextTokens": 200000,
3948+ "maxOutputTokens": 100000,
3949+ "capabilities": {
3950+ "text": true,
3951+ "vision": true,
3952+ "audioInput": false,
3953+ "audioOutput": false,
3954+ "imageGeneration": false,
3955+ "video": false,
3956+ "reasoning": true,
3957+ "tools": true,
3958+ "structuredOutput": true,
3959+ "streaming": true,
3960+ "files": true,
3961+ "webSearch": true
3962+ },
3963+ "parameters": {
3964+ "temperature": "unsupported",
3965+ "topP": "unsupported",
3966+ "topK": "unsupported",
3967+ "maxTokens": "supported",
3968+ "reasoningEffort": "supported",
3969+ "thinkingBudget": "unsupported",
3970+ "stop": "unsupported",
3971+ "seed": "unsupported",
3972+ "frequencyPenalty": "unsupported",
3973+ "presencePenalty": "unsupported",
3974+ "verbosity": "supported"
3975+ },
3976+ "pricing": {
3977+ "inputPerMillion": null,
3978+ "cachedInputPerMillion": null,
3979+ "outputPerMillion": null
3980+ },
3981+ "status": "deprecated",
3982+ "notes": "Dated snapshot of o3-deep-research. shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. shutdown_date 2026-07-23; 404 model_not_found (verified). Agentic research model, not a chat model. Verified by probe: basic -> 404. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
3983+ "reasoningEfforts": null,
3984+ "defaultReasoningEffort": null,
3985+ "apis": [
3986+ "responses"
3987+ ],
3988+ "knowledgeCutoff": null,
3989+ "shutdownDate": "2026-07-23",
3990+ "snapshotOf": "o3-deep-research"
3991+ },
3992+ {
3993+ "id": "o3-mini",
3994+ "displayName": "o3-mini",
3995+ "family": "o-series",
3996+ "contextTokens": 200000,
3997+ "maxOutputTokens": 100000,
3998+ "capabilities": {
3999+ "text": true,
4000+ "vision": false,
4001+ "audioInput": false,
4002+ "audioOutput": false,
4003+ "imageGeneration": false,
4004+ "video": false,
4005+ "reasoning": true,
4006+ "tools": true,
4007+ "structuredOutput": true,
4008+ "streaming": true,
4009+ "files": false,
4010+ "webSearch": false
4011+ },
4012+ "parameters": {
4013+ "temperature": "unsupported",
4014+ "topP": "unsupported",
4015+ "topK": "unsupported",
4016+ "maxTokens": "supported",
4017+ "reasoningEffort": "supported",
4018+ "thinkingBudget": "unsupported",
4019+ "stop": "unsupported",
4020+ "seed": "unsupported",
4021+ "frequencyPenalty": "unsupported",
4022+ "presencePenalty": "unsupported",
4023+ "verbosity": "unsupported"
4024+ },
4025+ "pricing": {
4026+ "inputPerMillion": 1.1,
4027+ "cachedInputPerMillion": 0.55,
4028+ "outputPerMillion": 4.4
4029+ },
4030+ "status": "deprecated",
4031+ "notes": "shutdown_date (from GET /v1/models): 2026-10-23. TEXT ONLY (no image input). shutdown_date 2026-10-23 -> gpt-5.6-sol. Still answers (verified). Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
4032+ "reasoningEfforts": [
4033+ "low",
4034+ "medium",
4035+ "high"
4036+ ],
4037+ "defaultReasoningEffort": "medium",
4038+ "apis": [
4039+ "responses",
4040+ "chat",
4041+ "batch",
4042+ "assistants"
4043+ ],
4044+ "knowledgeCutoff": "2023-10-01",
4045+ "shutdownDate": "2026-10-23",
4046+ "snapshotOf": null
4047+ },
4048+ {
4049+ "id": "o3-mini-2025-01-31",
4050+ "displayName": "o3-mini (2025-01-31)",
4051+ "family": "o-series",
4052+ "contextTokens": 200000,
4053+ "maxOutputTokens": 100000,
4054+ "capabilities": {
4055+ "text": true,
4056+ "vision": false,
4057+ "audioInput": false,
4058+ "audioOutput": false,
4059+ "imageGeneration": false,
4060+ "video": false,
4061+ "reasoning": true,
4062+ "tools": true,
4063+ "structuredOutput": true,
4064+ "streaming": true,
4065+ "files": false,
4066+ "webSearch": false
4067+ },
4068+ "parameters": {
4069+ "temperature": "unsupported",
4070+ "topP": "unsupported",
4071+ "topK": "unsupported",
4072+ "maxTokens": "supported",
4073+ "reasoningEffort": "supported",
4074+ "thinkingBudget": "unsupported",
4075+ "stop": "unsupported",
4076+ "seed": "unsupported",
4077+ "frequencyPenalty": "unsupported",
4078+ "presencePenalty": "unsupported",
4079+ "verbosity": "unsupported"
4080+ },
4081+ "pricing": {
4082+ "inputPerMillion": 1.1,
4083+ "cachedInputPerMillion": 0.55,
4084+ "outputPerMillion": 4.4
4085+ },
4086+ "status": "deprecated",
4087+ "notes": "Dated snapshot of o3-mini. shutdown_date (from GET /v1/models): 2026-10-23. TEXT ONLY (no image input). shutdown_date 2026-10-23 -> gpt-5.6-sol. Still answers (verified). Verified by probe: basic. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
4088+ "reasoningEfforts": [
4089+ "low",
4090+ "medium",
4091+ "high"
4092+ ],
4093+ "defaultReasoningEffort": "medium",
4094+ "apis": [
4095+ "responses",
4096+ "chat",
4097+ "batch",
4098+ "assistants"
4099+ ],
4100+ "knowledgeCutoff": "2023-10-01",
4101+ "shutdownDate": "2026-10-23",
4102+ "snapshotOf": "o3-mini"
4103+ },
4104+ {
4105+ "id": "o3-pro",
4106+ "displayName": "o3-pro",
4107+ "family": "o-series",
4108+ "contextTokens": 200000,
4109+ "maxOutputTokens": 100000,
4110+ "capabilities": {
4111+ "text": true,
4112+ "vision": true,
4113+ "audioInput": false,
4114+ "audioOutput": false,
4115+ "imageGeneration": true,
4116+ "video": false,
4117+ "reasoning": true,
4118+ "tools": true,
4119+ "structuredOutput": true,
4120+ "streaming": true,
4121+ "files": true,
4122+ "webSearch": true
4123+ },
4124+ "parameters": {
4125+ "temperature": "unsupported",
4126+ "topP": "unsupported",
4127+ "topK": "unsupported",
4128+ "maxTokens": "supported",
4129+ "reasoningEffort": "supported",
4130+ "thinkingBudget": "unsupported",
4131+ "stop": "unsupported",
4132+ "seed": "unsupported",
4133+ "frequencyPenalty": "unsupported",
4134+ "presencePenalty": "unsupported",
4135+ "verbosity": "unsupported"
4136+ },
4137+ "pricing": {
4138+ "inputPerMillion": 20,
4139+ "cachedInputPerMillion": null,
4140+ "outputPerMillion": 80
4141+ },
4142+ "status": "active",
4143+ "notes": "Responses only, background mode recommended; streaming not indicated in docs. Snapshot o3-pro-2025-06-10 shuts down 2026-12-11. Not probed. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
4144+ "reasoningEfforts": null,
4145+ "defaultReasoningEffort": null,
4146+ "apis": [
4147+ "responses",
4148+ "batch"
4149+ ],
4150+ "knowledgeCutoff": null,
4151+ "shutdownDate": null,
4152+ "snapshotOf": null
4153+ },
4154+ {
4155+ "id": "o3-pro-2025-06-10",
4156+ "displayName": "o3-pro (2025-06-10)",
4157+ "family": "o-series",
4158+ "contextTokens": 200000,
4159+ "maxOutputTokens": 100000,
4160+ "capabilities": {
4161+ "text": true,
4162+ "vision": true,
4163+ "audioInput": false,
4164+ "audioOutput": false,
4165+ "imageGeneration": true,
4166+ "video": false,
4167+ "reasoning": true,
4168+ "tools": true,
4169+ "structuredOutput": true,
4170+ "streaming": true,
4171+ "files": true,
4172+ "webSearch": true
4173+ },
4174+ "parameters": {
4175+ "temperature": "unsupported",
4176+ "topP": "unsupported",
4177+ "topK": "unsupported",
4178+ "maxTokens": "supported",
4179+ "reasoningEffort": "supported",
4180+ "thinkingBudget": "unsupported",
4181+ "stop": "unsupported",
4182+ "seed": "unsupported",
4183+ "frequencyPenalty": "unsupported",
4184+ "presencePenalty": "unsupported",
4185+ "verbosity": "unsupported"
4186+ },
4187+ "pricing": {
4188+ "inputPerMillion": 20,
4189+ "cachedInputPerMillion": null,
4190+ "outputPerMillion": 80
4191+ },
4192+ "status": "deprecated",
4193+ "notes": "Dated snapshot of o3-pro. shutdown_date (from GET /v1/models): 2026-12-11. Responses only, background mode recommended; streaming not indicated in docs. Snapshot o3-pro-2025-06-10 shuts down 2026-12-11. Not probed. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
4194+ "reasoningEfforts": null,
4195+ "defaultReasoningEffort": null,
4196+ "apis": [
4197+ "responses",
4198+ "batch"
4199+ ],
4200+ "knowledgeCutoff": null,
4201+ "shutdownDate": "2026-12-11",
4202+ "snapshotOf": "o3-pro"
4203+ },
4204+ {
4205+ "id": "o4-mini",
4206+ "displayName": "o4-mini",
4207+ "family": "o-series",
4208+ "contextTokens": 200000,
4209+ "maxOutputTokens": 100000,
4210+ "capabilities": {
4211+ "text": true,
4212+ "vision": true,
4213+ "audioInput": false,
4214+ "audioOutput": false,
4215+ "imageGeneration": true,
4216+ "video": false,
4217+ "reasoning": true,
4218+ "tools": true,
4219+ "structuredOutput": true,
4220+ "streaming": true,
4221+ "files": true,
4222+ "webSearch": true
4223+ },
4224+ "parameters": {
4225+ "temperature": "unsupported",
4226+ "topP": "unsupported",
4227+ "topK": "unsupported",
4228+ "maxTokens": "supported",
4229+ "reasoningEffort": "supported",
4230+ "thinkingBudget": "unsupported",
4231+ "stop": "unsupported",
4232+ "seed": "unsupported",
4233+ "frequencyPenalty": "unsupported",
4234+ "presencePenalty": "unsupported",
4235+ "verbosity": "unsupported"
4236+ },
4237+ "pricing": {
4238+ "inputPerMillion": 1.1,
4239+ "cachedInputPerMillion": 0.275,
4240+ "outputPerMillion": 4.4
4241+ },
4242+ "status": "deprecated",
4243+ "notes": "shutdown_date (from GET /v1/models): 2026-10-23. shutdown_date 2026-10-23 -> gpt-5.6-terra. Verified: effort none/minimal/xhigh/max rejected ('Supported values are: low, medium, and high'); temperature/top_p/penalties/logprobs rejected; text.verbosity only 'medium'. Heavy reasoner: at max_output_tokens 200 the tool-call, structured and vision probes all came back incomplete (all tokens spent on reasoning) -> give it >= 1-2k output tokens. Reasoning summaries stream (response.reasoning_summary_*). Verified by probe: basic, stream, params, structured/vision/tools (incomplete at 200 tokens), chat completions. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
4244+ "reasoningEfforts": [
4245+ "low",
4246+ "medium",
4247+ "high"
4248+ ],
4249+ "defaultReasoningEffort": "medium",
4250+ "apis": [
4251+ "responses",
4252+ "chat",
4253+ "batch",
4254+ "fine-tuning"
4255+ ],
4256+ "knowledgeCutoff": "2024-06-01",
4257+ "shutdownDate": "2026-10-23",
4258+ "snapshotOf": null
4259+ },
4260+ {
4261+ "id": "o4-mini-2025-04-16",
4262+ "displayName": "o4-mini (2025-04-16)",
4263+ "family": "o-series",
4264+ "contextTokens": 200000,
4265+ "maxOutputTokens": 100000,
4266+ "capabilities": {
4267+ "text": true,
4268+ "vision": true,
4269+ "audioInput": false,
4270+ "audioOutput": false,
4271+ "imageGeneration": true,
4272+ "video": false,
4273+ "reasoning": true,
4274+ "tools": true,
4275+ "structuredOutput": true,
4276+ "streaming": true,
4277+ "files": true,
4278+ "webSearch": true
4279+ },
4280+ "parameters": {
4281+ "temperature": "unsupported",
4282+ "topP": "unsupported",
4283+ "topK": "unsupported",
4284+ "maxTokens": "supported",
4285+ "reasoningEffort": "supported",
4286+ "thinkingBudget": "unsupported",
4287+ "stop": "unsupported",
4288+ "seed": "unsupported",
4289+ "frequencyPenalty": "unsupported",
4290+ "presencePenalty": "unsupported",
4291+ "verbosity": "unsupported"
4292+ },
4293+ "pricing": {
4294+ "inputPerMillion": 1.1,
4295+ "cachedInputPerMillion": 0.275,
4296+ "outputPerMillion": 4.4
4297+ },
4298+ "status": "deprecated",
4299+ "notes": "Dated snapshot of o4-mini. shutdown_date (from GET /v1/models): 2026-10-23. shutdown_date 2026-10-23 -> gpt-5.6-terra. Verified: effort none/minimal/xhigh/max rejected ('Supported values are: low, medium, and high'); temperature/top_p/penalties/logprobs rejected; text.verbosity only 'medium'. Heavy reasoner: at max_output_tokens 200 the tool-call, structured and vision probes all came back incomplete (all tokens spent on reasoning) -> give it >= 1-2k output tokens. Reasoning summaries stream (response.reasoning_summary_*). Verified by probe: basic, stream, params, structured/vision/tools (incomplete at 200 tokens), chat completions. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
4300+ "reasoningEfforts": [
4301+ "low",
4302+ "medium",
4303+ "high"
4304+ ],
4305+ "defaultReasoningEffort": "medium",
4306+ "apis": [
4307+ "responses",
4308+ "chat",
4309+ "batch",
4310+ "fine-tuning"
4311+ ],
4312+ "knowledgeCutoff": "2024-06-01",
4313+ "shutdownDate": "2026-10-23",
4314+ "snapshotOf": "o4-mini"
4315+ },
4316+ {
4317+ "id": "o4-mini-deep-research",
4318+ "displayName": "o4-mini Deep Research",
4319+ "family": "o-series",
4320+ "contextTokens": 200000,
4321+ "maxOutputTokens": 100000,
4322+ "capabilities": {
4323+ "text": true,
4324+ "vision": true,
4325+ "audioInput": false,
4326+ "audioOutput": false,
4327+ "imageGeneration": false,
4328+ "video": false,
4329+ "reasoning": true,
4330+ "tools": true,
4331+ "structuredOutput": true,
4332+ "streaming": true,
4333+ "files": true,
4334+ "webSearch": true
4335+ },
4336+ "parameters": {
4337+ "temperature": "unsupported",
4338+ "topP": "unsupported",
4339+ "topK": "unsupported",
4340+ "maxTokens": "supported",
4341+ "reasoningEffort": "supported",
4342+ "thinkingBudget": "unsupported",
4343+ "stop": "unsupported",
4344+ "seed": "unsupported",
4345+ "frequencyPenalty": "unsupported",
4346+ "presencePenalty": "unsupported",
4347+ "verbosity": "supported"
4348+ },
4349+ "pricing": {
4350+ "inputPerMillion": null,
4351+ "cachedInputPerMillion": null,
4352+ "outputPerMillion": null
4353+ },
4354+ "status": "deprecated",
4355+ "notes": "shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. shutdown_date 2026-07-23 (passed). Not probed; sibling o3-deep-research returns 404. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
4356+ "reasoningEfforts": null,
4357+ "defaultReasoningEffort": null,
4358+ "apis": [
4359+ "responses"
4360+ ],
4361+ "knowledgeCutoff": null,
4362+ "shutdownDate": "2026-07-23",
4363+ "snapshotOf": null
4364+ },
4365+ {
4366+ "id": "o4-mini-deep-research-2025-06-26",
4367+ "displayName": "o4-mini Deep Research (2025-06-26)",
4368+ "family": "o-series",
4369+ "contextTokens": 200000,
4370+ "maxOutputTokens": 100000,
4371+ "capabilities": {
4372+ "text": true,
4373+ "vision": true,
4374+ "audioInput": false,
4375+ "audioOutput": false,
4376+ "imageGeneration": false,
4377+ "video": false,
4378+ "reasoning": true,
4379+ "tools": true,
4380+ "structuredOutput": true,
4381+ "streaming": true,
4382+ "files": true,
4383+ "webSearch": true
4384+ },
4385+ "parameters": {
4386+ "temperature": "unsupported",
4387+ "topP": "unsupported",
4388+ "topK": "unsupported",
4389+ "maxTokens": "supported",
4390+ "reasoningEffort": "supported",
4391+ "thinkingBudget": "unsupported",
4392+ "stop": "unsupported",
4393+ "seed": "unsupported",
4394+ "frequencyPenalty": "unsupported",
4395+ "presencePenalty": "unsupported",
4396+ "verbosity": "supported"
4397+ },
4398+ "pricing": {
4399+ "inputPerMillion": null,
4400+ "cachedInputPerMillion": null,
4401+ "outputPerMillion": null
4402+ },
4403+ "status": "deprecated",
4404+ "notes": "Dated snapshot of o4-mini-deep-research. shutdown_date (from GET /v1/models): 2026-07-23 (already passed). Listed by /v1/models but no longer serves requests (404 model_not_found) or past shutdown. shutdown_date 2026-07-23 (passed). Not probed; sibling o3-deep-research returns 404. Verified by probe: none. Param legend: supported | unsupported | conditional (sampling params only accepted when reasoning.effort='none'; stop/seed only via Chat Completions) | null = unknown. files = PDF via input_file (docs: any vision model); verified only on gpt-5.4-mini. audioInput/audioOutput false: Responses API rejects input_audio ('Audio input is not available', verified); audio requires gpt-audio-*/gpt-realtime-* via Chat Completions/Realtime. imageGeneration = via the built-in image_generation tool (gpt-image-2), not native output. video false everywhere (Sora/Videos API deprecated, shutdown 2026-09-24).",
4405+ "reasoningEfforts": null,
4406+ "defaultReasoningEffort": null,
4407+ "apis": [
4408+ "responses"
4409+ ],
4410+ "knowledgeCutoff": null,
4411+ "shutdownDate": "2026-07-23",
4412+ "snapshotOf": "o4-mini-deep-research"
4413+ },
4414+ {
4415+ "id": "gpt-5.6",
4416+ "displayName": "GPT-5.6 (alias -> gpt-5.6-sol)",
4417+ "family": "gpt-5.6",
4418+ "contextTokens": 1050000,
4419+ "maxOutputTokens": 128000,
4420+ "capabilities": {
4421+ "text": true,
4422+ "vision": true,
4423+ "audioInput": false,
4424+ "audioOutput": false,
4425+ "imageGeneration": true,
4426+ "video": false,
4427+ "reasoning": true,
4428+ "tools": true,
4429+ "structuredOutput": true,
4430+ "streaming": true,
4431+ "files": true,
4432+ "webSearch": true
4433+ },
4434+ "parameters": {
4435+ "temperature": "conditional",
4436+ "topP": "conditional",
4437+ "topK": "unsupported",
4438+ "maxTokens": "supported",
4439+ "reasoningEffort": "supported",
4440+ "thinkingBudget": "unsupported",
4441+ "stop": "unsupported",
4442+ "seed": "unsupported",
4443+ "frequencyPenalty": "conditional",
4444+ "presencePenalty": "conditional",
4445+ "verbosity": "supported"
4446+ },
4447+ "pricing": {
4448+ "inputPerMillion": 4,
4449+ "cachedInputPerMillion": 0.4,
4450+ "outputPerMillion": 20
4451+ },
4452+ "status": "active",
4453+ "notes": "NOT returned by GET /v1/models for this key, but documented and verified: a request for 'gpt-5.6' returns response.model = 'gpt-5.6-sol'. Included so the registry can resolve it.",
4454+ "reasoningEfforts": [
4455+ "none",
4456+ "low",
4457+ "medium",
4458+ "high",
4459+ "xhigh",
4460+ "max"
4461+ ],
4462+ "defaultReasoningEffort": "medium",
4463+ "apis": [
4464+ "responses",
4465+ "chat",
4466+ "batch"
4467+ ],
4468+ "knowledgeCutoff": "2026-02-16",
4469+ "shutdownDate": null,
4470+ "snapshotOf": "gpt-5.6-sol"
4471+ }
4472+]
added docs/provider-research/xai.md +280 −0
@@ -0,0 +1,280 @@
1+# xAI (Grok API) — provider research for PolyLLM
2+
3+Last documentation audit: **2026-09-08**
4+Probes executed 2026-09-08 with a real key against `https://api.x.ai/v1` (scripts in `research/xai/`, raw outputs in `research/xai/out/`). Everything marked **(probed)** was observed live; everything marked **(docs)** comes from the pages listed at the end.
5+
6+> Heads-up: `docs.x.ai/docs/...` URLs given in the brief are all **404** now. The documentation moved to `https://docs.x.ai/developers/...` (see "Documentation pages used"). The API error for Live Search still points to the old `/docs/guides/tools/overview` URL, which is dead.
7+
8+---
9+
10+## 1. Base URL, auth, headers
11+
12+| Item | Value |
13+|---|---|
14+| REST base URL | `https://api.x.ai/v1` (also a gRPC API at `api.x.ai:443`, not relevant for a web app) |
15+| Auth | `Authorization: Bearer <XAI_API_KEY>` |
16+| Content type | `application/json` (malformed JSON → **422 text/plain** Rust/serde message, e.g. `Failed to deserialize the JSON body into the target type: messages: invalid type: string "nope", expected a sequence at line 1 column 37`) **(probed)** |
17+| Useful request headers | `x-grok-conv-id: <stable id>` — routes a conversation to the same server to maximise prompt-cache hits (docs); accepted **(probed)**. Body field `prompt_cache_key` is the equivalent for Responses API. |
18+| Response headers **(probed)** | `x-request-id`, `x-ratelimit-limit-requests`, `x-ratelimit-remaining-requests`, `x-ratelimit-limit-tokens`, `x-ratelimit-remaining-tokens` (present on inference calls; not on `/models`). Behind Cloudflare (`cf-ray`). Observed limits: grok-4.6 `7200` req / `50 000 000` tokens per window; grok-4.3 `1800` req / `10 000 000` tokens (window is per minute per the TPM docs; the RPS numbers below suggest the header window is 1 minute). |
19+| Key introspection | `GET /v1/api-key` (redacted key, name, ACLs, team/user ids) and `GET /v1/me` (adds `zdr_status`, `team_blocked`) **(probed, 200)**. Handy for a "validate key" button: cheap, no tokens. **But** an invalid key returns **400**, not 401 (see §14). |
20+
21+## 2. SDK recommendation (TypeScript / Node)
22+
23+- **There is no official xAI JavaScript/TypeScript SDK.** `xai-sdk` is Python-only (gRPC). npm `xai-sdk` / `@xai/sdk` do not exist (checked 2026-09-08).
24+- xAI's own docs give JS examples with **`openai` (OpenAI SDK) pointed at `baseURL: "https://api.x.ai/v1"`** and with **Vercel AI SDK `@ai-sdk/xai`** (latest **4.0.54**; `xai(model)` = Responses API since AI SDK 7, `xai.chat(model)` = legacy chat completions; exposes `xai.tools.webSearch/xSearch/codeExecution/mcpServer/…`).
25+- **Anthropic SDK compatibility (`/v1/messages`, `/v1/complete`) is "fully deprecated"** (docs, Legacy section). Do not build on it.
26+- **Recommendation for PolyLLM:** use the OpenAI SDK **`openai@7.10.0`** (what we probed) with `baseURL: https://api.x.ai/v1`, `maxRetries` handled by us, and a long `timeout` (docs recommend 3600 s for reasoning models; we used 120 s fine for small prompts). Both `client.chat.completions.create` and `client.responses.create` work unchanged. A raw `fetch` SSE parser also works (see §16) and is what we used to capture exact chunk shapes.
27+
28+## 3. Endpoints (inference + management)
29+
30+| Endpoint | Status | Notes |
31+|---|---|---|
32+| `POST /v1/responses` | **preferred** (docs: "The Responses API is the preferred way… New features come to the Responses API first") | Stateful by default (`store: true`, 30-day retention), `previous_response_id`, server-side tools, encrypted reasoning, structured outputs via `text.format`. **(probed)** |
33+| `GET /v1/responses/{id}`, `GET /v1/responses/{id}/input_items`, `DELETE /v1/responses/{id}` | active | Delete returns `{"id","object":"response","deleted":true}` **(probed)** |
34+| `POST /v1/responses/compact` | active | Context compaction → opaque blob to feed back verbatim (docs) |
35+| `POST /v1/chat/completions` | **legacy but fully working** | OpenAI-compatible; `reasoning_content` returned; no deprecation date. Multi-agent model rejected here. **(probed)** |
36+| `GET /v1/chat/deferred-completion/{request_id}` | active | For `deferred: true` requests (202 while pending, 24 h retention, single read) (docs) |
37+| `POST /v1/completions`, `POST /v1/messages`, `POST /v1/complete` | **deprecated/legacy** | Not supported by reasoning models; Anthropic compat fully deprecated (docs) |
38+| `GET /v1/models`, `GET /v1/models/{id}` | active | Minimal (id, aliases). **(probed)** |
39+| `GET /v1/language-models`, `GET /v1/language-models/{id}` | active | Rich metadata + pricing (§12). **Does NOT include `context_length`** despite docs example. **(probed)** |
40+| `GET /v1/image-generation-models`, `GET /v1/video-generation-models` (+`/{id}`) | active | Image: `image_price`, `pricing[]`, `max_prompt_length`. **(probed)** |
41+| `POST /v1/tokenize-text` | active | `{text, model}` → `{token_ids:[{token_id,string_token,token_bytes}]}` **(probed)** — usable for client-side token counting (one network call). |
42+| `GET /v1/api-key`, `GET /v1/me` | active | See §1 |
43+| `POST /v1/images/generations`, `/v1/images/edits`, videos, voice (STT/TTS/speech-to-speech), `/v1/files`, collections, batches, embeddings (section exists, no text-embedding model listed) | active | Out of scope for the chat adapter except image generation (grok-imagine-*). |
44+
45+## 4. Chat Completions request/response (probed shapes)
46+
47+Request body fields (docs API ref + probes): `model`, `messages`, `max_completion_tokens` (default **128 000**; `max_tokens` is *deprecated but still accepted* **(probed)**), `temperature` 0–2, `top_p` 0–1, `n`, `seed`, `stop` (≤4; rejected by reasoning models), `frequency_penalty`/`presence_penalty` (rejected by every current model), `logit_bias`, `logprobs`/`top_logprobs` (0–8; "ignored by grok-4.20+", accepted **(probed)**), `reasoning_effort` (`none|low|medium|high|xhigh`, model-dependent), `response_format`, `tools` (≤128 docs API ref; ≤200 docs function-calling page), `tool_choice`, `parallel_tool_calls`, `stream`, `stream_options.include_usage`, `prompt_cache_key`, `service_tier` (`default|priority`), `user`, `deferred`, `web_search_options` (OpenAI compat), `search_parameters` (**dead → 410**).
48+
49+Roles: `system`, `user`, `assistant`, `tool`. `developer` role is **accepted** **(probed, all 6 models)**. Unknown top-level params (`foo_bar`) are **silently ignored** **(probed)**; `top_k` is accepted on chat completions although only documented for Responses **(probed)**.
50+
51+Non-streaming response **(probed)**:
52+
53+```json
54+{
55+ "id": "…", "object": "chat.completion", "created": 1788842609, "model": "grok-4.6",
56+ "choices": [{ "index": 0, "finish_reason": "stop",
57+ "message": { "role": "assistant", "content": "2 + 2 equals 4.",
58+ "reasoning_content": "The user asked: …", "refusal": null } }],
59+ "usage": {
60+ "prompt_tokens": 652, "completion_tokens": 8, "total_tokens": 770,
61+ "prompt_tokens_details": { "text_tokens": 652, "audio_tokens": 0, "image_tokens": 0, "cached_tokens": 512 },
62+ "completion_tokens_details": { "reasoning_tokens": 110, "audio_tokens": 0,
63+ "accepted_prediction_tokens": 0, "rejected_prediction_tokens": 0 },
64+ "num_sources_used": 0, "cost_in_usd_ticks": 12440000 },
65+ "system_fingerprint": "fp_e41c6060b2628547", "service_tier": "default"
66+}
67+```
68+
69+- `total_tokens` = prompt + completion + **reasoning** (reasoning tokens are *not* inside `completion_tokens`; 652+8+110=770).
70+- `cost_in_usd_ticks`: 10 000 000 000 ticks = $1 (docs) → 12 440 000 ticks = $0.001244. Responses API also returns `cost_in_usd_ticks` (and docs mention `cost_in_nano_usd`). **Use this for exact per-request cost display.**
71+- `finish_reason`: `stop`, `length` (**probed**: `max_completion_tokens: 10` → `"length"` on both reasoning and non-reasoning models; on reasoning models the cap applies to *visible* tokens, reasoning still ran ~680 tokens), `tool_calls` **(probed)**. Docs also list `end_turn` (streaming).
72+- Hidden system prompt: even a one-line prompt costs ~190–200 prompt tokens on grok-4.3/4.20/build, ~500 on grok-4.5 and ~650 on grok-4.6 **(probed)** — budget for it.
73+
74+## 5. Streaming protocol (chat completions) **(probed)**
75+
76+SSE, `Content-Type: text/event-stream`, no `event:` field, `data: {json}` lines, terminated by `data: [DONE]`.
77+
78+Chunk sequence for a reasoning model (grok-4.6):
79+
80+```json
81+data: {"id":"1039…","object":"chat.completion.chunk","created":1788842609,"model":"grok-4.6",
82+ "choices":[{"index":0,"delta":{"reasoning_content":"The","role":"assistant"}}],
83+ "system_fingerprint":"fp_e41c6060b2628547","service_tier":"default"}
84+data: {"…","choices":[{"index":0,"delta":{"reasoning_content":" user"}}],…}
85+…
86+data: {"…","choices":[{"index":0,"delta":{"content":"Bonjour"}}],…}
87+data: {"…","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],…}
88+data: {"…","choices":[],"usage":{"prompt_tokens":646,"completion_tokens":3,"total_tokens":1189,
89+ "prompt_tokens_details":{…,"cached_tokens":512},
90+ "completion_tokens_details":{"reasoning_tokens":540,…},"num_sources_used":0,"cost_in_usd_ticks":37820000},…}
91+data: [DONE]
92+```
93+
94+- Delta keys observed: `role`, `reasoning_content`, `content`, `tool_calls`. Non-reasoning model (grok-4.20-non-reasoning): only `role`/`content`.
95+- **Reasoning is streamed as `delta.reasoning_content` (plain text)** for grok-4.6, 4.5, 4.3, 4.20-reasoning, grok-build → PolyLLM can render a live "thinking" pane on chat completions without any extra flag.
96+- Usage arrives in a **final extra chunk with `choices: []`** only when `stream_options: {include_usage: true}`; the `finish_reason` chunk is separate. No `x-ratelimit` differences for streams.
97+- Chunks carry no per-chunk `usage` (docs' example showing usage on every chunk is outdated).
98+
99+## 6. Tool / function calling **(probed on all 6 models)**
100+
101+- Chat completions: OpenAI nested format `{type:"function", function:{name, description, parameters}}`; `tool_choice`: `auto|required|none|{type:"function",function:{name}}`; `parallel_tool_calls` (default true). Parameter root must be an object (or anyOf/oneOf of objects).
102+- Round trip works with `assistant.tool_calls` + `{role:"tool", tool_call_id, content}` on every model.
103+- **Streaming: the whole tool call arrives in ONE chunk** (docs + probed), with full `arguments`:
104+
105+```json
106+{"delta":{"tool_calls":[{"id":"call-cbf4aac4-…-0","function":{"name":"get_weather","arguments":"{\"city\":\"Montreal\"}"},"index":0,"type":"function"}]}}
107+```
108+ then `finish_reason: "tool_calls"`. The non-reasoning model also includes `"role":"assistant"` in that delta. Standard OpenAI accumulation code works, but you can also treat each tool_calls delta as complete. Tool-call ids look like `call-<uuid>-<n>`.
109+- Responses API: flat tool `{type:"function", name, description, parameters}`; events `response.output_item.added` (item `type:"function_call"`, `call_id`, `name`, `arguments:""`), **one** `response.function_call_arguments.delta` with the full JSON, `response.function_call_arguments.done`, `response.output_item.done`. Return results as `{type:"function_call_output", call_id, output}` items **(probed)**.
110+- Tool arguments are implicitly `strict` (docs: "Tool calling… implicit strict: true").
111+
112+## 7. Structured output **(probed on all 6 models)**
113+
114+- Chat completions: `response_format: {type:"json_schema", json_schema:{name, schema, strict:true}}` → valid JSON on all 6 models; `{type:"json_object"}` also works on all 6 (docs say it is accepted).
115+- Responses API: `text: {format: {type:"json_schema", name, schema, strict:true}}` **(probed OK)**.
116+- OpenAI SDK helpers work: `client.chat.completions.parse(... response_format: zodResponseFormat(...))` (docs).
117+- JSON Schema support (docs): string/number/integer/boolean/null/enum/const/array/object/anyOf/oneOf/allOf(single)/$ref+$defs (non-circular); enforced formats date, time, date-time, email, uuid, ipv4, ipv6, uri; minLength/maxLength ≤2048, minItems/maxItems ≤256, min/maxProperties ≤64; `additionalProperties` defaults to **false**; rejected: empty enum/anyOf, boolean-valued properties, min/maxContains, tuple `items`. Regex: no backrefs/lookaround/\b/Unicode properties; `.` matches newline; `^`/`$` implicit. "Structured Outputs are available on Grok 4 family models."
118+
119+## 8. Reasoning controls **(probed matrix)**
120+
121+| Model | Reasoning | `reasoning_effort` accepted | `reasoning_content` returned |
122+|---|---|---|---|
123+| grok-4.6 | always on | `low`, `medium`, `high` (default), `xhigh`; `minimal` accepted (undocumented, likely mapped); **`none` → 400** `This model does not support \`reasoning_effort\` value \`none\`.` | yes (chat completions, plain text; Responses: `reasoning.summary[]` + optional `encrypted_content`) |
124+| grok-4.5 | always on | `low`, `medium`, `high` (default); `xhigh`/`minimal` accepted (docs: xhigh treated as high); `none` → 400 same message | yes |
125+| grok-4.3 | configurable | **`none` accepted → reasoning_tokens 0**, `low`, `medium`, `high`; `xhigh`/`minimal` accepted (mapped) | yes (empty when `none`) |
126+| grok-4.20-0309-reasoning | always on, fixed | **any value → 400** `Model grok-4.20-0309-reasoning does not support parameter reasoningEffort.` | yes |
127+| grok-4.20-0309-non-reasoning | none | any value → 400 same pattern | no (`reasoning_tokens: 0`) |
128+| grok-build-0.1 | always on, fixed | any value → 400 same pattern | yes |
129+| grok-4.20-multi-agent-0309 | always on | `low|medium` = 4 agents, `high|xhigh` = 16 agents (docs) | Responses only; sub-agents hidden |
130+
131+- Same behaviour via Responses API `reasoning: {effort}` **(probed)**: 4.20-*/build reject `low`; 4.3 accepts `none` (`reasoning.summary` becomes `"none"`, no reasoning item).
132+- Responses API returns reasoning as an output item `{type:"reasoning", summary:[{type:"summary_text", text}], encrypted_content?}`; streamed as `response.reasoning_summary_part.added` / `response.reasoning_summary_text.delta` / `…done` / `response.reasoning_summary_part.done`. With `include: ["reasoning.encrypted_content"]` you get an opaque `encrypted_content` you can pass back in the `input` for stateless multi-turn with reasoning continuity (docs). `reasoning.summary` (`auto|concise|detailed`) is "compatibility only"; the API echoed `"summary":"detailed"` when we sent `auto`.
133+- No thinking-budget parameter exists. Reasoning tokens are billed at the output price.
134+
135+## 9. Sampling & other parameters — support matrix **(probed, chat completions)**
136+
137+| Param | 4.6 | 4.5 | 4.3 | 4.20-reasoning | 4.20-non-reasoning | build-0.1 |
138+|---|---|---|---|---|---|---|
139+| `temperature` (0–2) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
140+| `top_p` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
141+| `top_k` (undocumented on chat) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
142+| `seed` (+ `system_fingerprint`) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
143+| `max_completion_tokens` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
144+| `max_tokens` (deprecated) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
145+| `n: 2` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
146+| `logprobs`/`top_logprobs` | ✓ (accepted; docs: ignored on 4.20+) | ✓ | ✓ | ✓ | ✓ | ✓ |
147+| `response_format` json_object / json_schema | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
148+| `stop` | **400** | **400** | **400** | **400** | ✓ | **400** |
149+| `frequency_penalty` | **400** | **400** | **400** | **400** | **400** | **400** |
150+| `presence_penalty` | **400** | **400** | **400** | **400** | **400** | **400** |
151+| `reasoning_effort` | see §8 | | | 400 | 400 | 400 |
152+| `developer` role | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
153+
154+Exact rejection text: `{"code":"invalid-argument","error":"Model grok-4.6 does not support parameter presencePenalty."}` (camelCase param names: `presencePenalty`, `frequencyPenalty`, `stop`, `reasoningEffort`). **Adapter rule: never send `frequency_penalty`/`presence_penalty` to xAI; send `stop` only to grok-4.20-0309-non-reasoning; send `reasoning_effort` only to 4.6/4.5/4.3 (and multi-agent).** On `/v1/responses`, `presence_penalty` was silently accepted and echoed as `0` **(probed)** — the Responses endpoint is more lenient; Responses defaults echoed: `temperature 0.7`, `top_p 0.95`, `truncation "disabled"`.
155+
156+## 10. Modalities, context, output limits
157+
158+- **Input**: text + image on **all 7 language models** (`input_modalities: ["text","image"]` from `/v1/language-models`; vision **probed OK on all 6 chat models**). No audio input on text models (separate voice models/endpoints). **Output**: text only. Image generation = separate models `grok-imagine-image`, `-2.0`, `-quality` via `/v1/images/generations` (also an `image_generation` server-side tool on Responses); video = `grok-imagine-video`, `-1.5`.
159+- **Images**: JPG/PNG, ≤20 MiB, data URL `data:image/png;base64,…` or public URL, `detail: "high"` accepted, unlimited count (docs). **Hard minimums (probed, undocumented)**: width and height ≥ 8 px *and* total ≥ 512 pixels — errors `{"code":"invalid_image","error":"Image dimensions 2x2 are too small. Both width and height must be at least 8 pixels."}` / `"Image has 64 total pixels (8x8), which is below the minimum of 512 pixels."` / `"Invalid PNG image."`. A 32×32 PNG cost 1–3 `image_tokens`. Image tokens billed at the text input price (`prompt_image_token_price` == `prompt_text_token_price`).
160+- Chat completions image format: `{type:"image_url", image_url:{url, detail}}`; Responses: `{type:"input_image", image_url:"<url or data url>", detail}` (string, not object) + `{type:"input_text", text}`.
161+- **Context windows (docs, not in API)**: grok-4.6 **500k**, grok-4.5 **500k**, grok-4.3 / 4.20-* / multi-agent **1M**, grok-build-0.1 **256k**. `long_context_threshold` = **200 000** tokens for every model: when the prompt exceeds it, input/cached/output are all billed at **2×**.
162+- **Max output**: docs — grok-4.6 "no text output limit"; API default `max_completion_tokens` / `max_output_tokens` = **128 000**. `max_output_tokens` on Responses *includes* reasoning tokens; `max_completion_tokens` on chat completions covers *visible* tokens only (docs + probed).
163+- Files: `POST /v1/files` (48 MB, text/PDF/code), `input_file` with `file_id`/`file_url` on Responses, auto `attachment_search` tool ($10/1k calls), agentic models only (4.20, 4.5, 4.6). Collections (RAG) $2.50/1k searches.
164+
165+## 11. Server-side (agentic) tools, search, citations **(probed on grok-4.3 via /v1/responses)**
166+
167+- **Live Search (`search_parameters`) is dead**: chat completions → **410** `{"error":"Live search is deprecated. Please switch to the Agent Tools API: https://docs.x.ai/docs/guides/tools/overview"}`; `tools:[{type:"live_search",sources:[…]}]` → 410 too; `tools:[{type:"web_search"}]` on chat completions → **422** `tools[0].type: unknown variant \`web_search\`, expected \`function\` or \`live_search\``. **Server-side tools are Responses-API-only.**
168+- Responses tools: `{type:"web_search", allowed_domains?(≤5), excluded_domains?(≤5), enable_image_understanding?, enable_image_search?}`, `{type:"x_search", allowed_x_handles?/excluded_x_handles? (≤20), from_date?, to_date?, enable_image_understanding?, enable_video_understanding?}`, `{type:"code_interpreter"}` (sandboxed Python), `{type:"mcp", server_url, server_label, server_description?, allowed_tools?, authorization?, headers?}` (Streamable HTTP/SSE), `{type:"file_search"}` / `collections_search`, `{type:"image_generation"}`. `max_turns` caps agentic loops. Tool-call output is *not* returned by default; docs' `include` values (`web_search_call_output`, …) are **rejected** (`400 Argument not supported: "web_search_call_output" in "include" field`) — what *is* accepted: `include: ["web_search_call.action.sources"]` and `["no_inline_citations"]` **(probed)**.
169+- Streaming event names observed with web_search: `response.created`, `response.in_progress`, `response.output_item.added`, `response.reasoning_summary_part.added`, `response.reasoning_summary_text.delta`, `response.reasoning_summary_text.done`, `response.reasoning_summary_part.done`, `response.output_item.done`, `response.web_search_call.in_progress`, `response.web_search_call.searching`, `response.web_search_call.completed`, `response.content_part.added`, `response.output_text.delta`, **`response.output_text.annotation.added`**, `response.output_text.done`, `response.content_part.done`, `response.completed`. Each event has `sequence_number`, `item_id`, `output_index`.
170+- **Citations**: (1) inline Markdown `[[N]](url)` in the text (default on; disable with `include:["no_inline_citations"]`), (2) `annotations: [{type:"url_citation", url, start_index, end_index, title:"1"}]` on the `output_text` part, (3) `output[]` items `{type:"web_search_call", status, action:{type:"search", query, sources:[{type:"url", url}]}}` (one per search, 3 searches for our question). A top-level `response.citations` field was **not** present in the REST response (the docs' `response.citations` is the Python SDK). Usage adds `num_server_side_tools_used`, `server_side_tool_usage_details:{web_search_calls, x_search_calls, code_interpreter_calls, file_search_calls, mcp_calls, document_search_calls, image_generation_calls}` and `context_details`. Our single question consumed **20 919 input tokens** (11 072 cached) + 856 output → ≈ $0.032 + 3 × $0.005 tool calls. Budget accordingly.
171+- Tool pricing (docs): web/X search $5 per 1 000 calls, code execution $5/1k, file attachments $10/1k, collections $2.50/1k; image/video understanding token-based.
172+- No computer-use tool. Image generation available as a tool and as `/v1/images/generations`.
173+
174+## 12. Model listing & pricing units **(probed)**
175+
176+`GET /v1/language-models` fields: `id, fingerprint, created, object, owned_by, version, input_modalities, output_modalities, prompt_text_token_price, cached_prompt_text_token_price, prompt_image_token_price, completion_text_token_price, search_price, prompt_text_token_price_long_context, cached_prompt_text_token_price_long_context, completion_text_token_price_long_context, long_context_threshold, aliases`. **No `context_length`, no max output.**
177+
178+**Unit (verified against the pricing page): USD cents per 100 000 000 tokens → `$ per 1M tokens = value / 10 000`.** grok-4.6 `prompt_text_token_price: 20000` → $2.00/M ✓; `cached 5000` → $0.50 ✓; `completion 60000` → $6.00 ✓; grok-4.3 `12500` → $1.25 ✓. Image models: `image_price` in 1/100 000 000 cent → `grok-imagine-image 200000000` = $0.02 ✓.
179+
180+| Model | ctx (docs) | in / cached / out ($/M, <200k) | ≥200k tokens | aliases |
181+|---|---|---|---|---|
182+| grok-4.6 | 500k | 2.00 / 0.50 / 6.00 | 4.00 / 1.00 / 12.00 | — |
183+| grok-4.5 | 500k | 2.00 / 0.30 / 6.00 | 4.00 / 0.60 / 12.00 | grok-4.5-latest, **grok-build-latest** |
184+| grok-4.3 | 1M | 1.25 / 0.20 / 2.50 | 2.50 / 0.40 / 5.00 | grok-4.3-latest |
185+| grok-4.20-0309-reasoning | 1M | 1.25 / 0.20 / 2.50 | 2.50 / 0.40 / 5.00 | grok-4.20, grok-4.20-reasoning, … (15) |
186+| grok-4.20-0309-non-reasoning | 1M | 1.25 / 0.20 / 2.50 | 2.50 / 0.40 / 5.00 | grok-4.20-non-reasoning, … (8) |
187+| grok-4.20-multi-agent-0309 | 1M | 1.25 / 0.20 / 2.50 (all agents billed) | 2.50 / 0.40 / 5.00 | grok-4.20-multi-agent, … (6) |
188+| grok-build-0.1 | 256k | 1.00 / 0.20 / 2.00 | 2.00 / 0.40 / 4.00 | grok-code-fast-1, grok-code-fast, grok-code-fast-1-0825 |
189+
190+Image gen: grok-imagine-image $0.02, -2.0 $0.04 (pricing[] by quality/resolution 0.04–0.08), -quality $0.05 (retiring **2026-11-02** → redirected to -2.0 low). Video $0.05/s, -1.5 $0.08/s. Batch API −20 % on grok-4.3 and grok-4.20 variants only. `service_tier: "priority"` = 2× tokens. Knowledge cutoff grok-4.6: 2026-02-01.
191+
192+## 13. Prompt caching & provider-side state
193+
194+- **Automatic** on all grok language models, prefix-based on the messages array; no minimum documented; no fixed TTL ("can be evicted at any time"). Reported as `usage.prompt_tokens_details.cached_tokens` (chat) / `usage.input_tokens_details.cached_tokens` (Responses). **(probed: 128–512 cached tokens on the very first request — the hidden system prompt is cached.)** Cached price = 10–25 % of input price (see table). Maximise hits with `x-grok-conv-id` header (chat) or `prompt_cache_key` (Responses) = stable session id; never edit earlier messages.
195+- **Server-side state**: Responses API stores everything for 30 days by default (`store: true` echoed **(probed)**), `previous_response_id` continuation works **(probed: recalled "pamplemousse")**, `instructions` incompatible with `previous_response_id` (docs). For a BYOK privacy-conscious app **send `store: false`** and manage history client-side (docs image page even recommends not storing). `zdr_status` on `/v1/me` tells whether the team has zero-data-retention.
196+
197+## 14. Errors, rate limits, retries
198+
199+Error body: `{"code": "<string>", "error": "<message>"}` (not OpenAI's `{error:{message,type,code}}` — the OpenAI SDK will surface `e.error` = that object, `e.message` derived).
200+
201+| Case **(probed)** | HTTP | body |
202+|---|---|---|
203+| Invalid key | **400** | `{"code":"invalid-argument","error":"Incorrect API key provided. You can obtain an API key from https://console.x.ai."}` |
204+| No Authorization header | 401 | `{"code":"unauthenticated:no-credentials","error":"No credentials presented."}` |
205+| Unknown model | 400 | `{"code":"invalid-argument","error":"Model not found: grok-99"}` |
206+| Unsupported param | 400 | `{"code":"invalid-argument","error":"Model X does not support parameter presencePenalty."}` |
207+| Malformed body | 422 (text/plain) | serde message |
208+| Bad image | 400 | `{"code":"invalid_image","error":"…"}` |
209+| Bad `include` | 400 | `{"code":"400","error":"Argument not supported: …"}` |
210+| Live search | 410 | `{"error":"Live search is deprecated. …"}` (no `code`) |
211+| Multi-agent on chat completions | 400 (text/plain) | `Multi Agent requests are not allowed on chat completions` |
212+| Rate limit | 429 (docs) | exponential backoff recommended |
213+
214+Docs also list 403 (permissions/ACL), 404, 405, 415, 202 (deferred). Rate limits (docs, tiers by cumulative spend since 2026-01-01, never downgrade): T0 $0 → T4 $5 000; grok-4.6/4.5: 150 RPS / 50M TPM (T0) → 500 RPS / 100M TPM (T4); grok-4.3, 4.20-*, build: 37 RPS / 10M TPM → 208 RPS / 85M; multi-agent 9 RPS / 2.5M → 56 / 21M. TPM counts prompt + completion + reasoning + cached tokens. Headers in §1. Status page https://status.x.ai.
215+
216+**Retry/timeout recommendation for the adapter:** retry 429/5xx with jittered exponential backoff (respect `retry-after` if present — none observed), never retry 400/422; do not retry mid-stream; use a long read timeout (≥ 5 min; xAI suggests 3600 s) because `xhigh` reasoning can run minutes before the first `content` delta (but `reasoning_content` deltas arrive quickly, which is a good liveness signal). Map xAI 400 "Incorrect API key" to the app's *invalid credentials* state (do not rely on 401).
217+
218+## 15. Lifecycle / aliases
219+
220+- May 15 2026 retirement: `grok-3`, `grok-4-0709`, `grok-4-fast-*`, `grok-4-1-fast-*`, `grok-code-fast-1`, `grok-imagine-image-pro`. Slugs still resolve **(probed: `grok-3` and `grok-4-fast-reasoning` answered with `model: "grok-4.3"` and were billed at 4.3 rates)**; reasoning slugs → grok-4.3 `low`, non-reasoning → grok-4.3 `none`, grok-code-fast-1 → grok-build-0.1. Do **not** list retired slugs in the UI; if a user types one, show the redirect.
221+- `-latest` aliases exist for 4.5, 4.3, 4.20-*; grok-4.6 has none yet. `grok-build-latest` → grok-4.5 (surprising). Use canonical ids from `/v1/language-models` and display aliases as secondary.
222+- grok-4.20-multi-agent is **beta** ("potential breaking changes"), Responses-only, no client tools.
223+- Docs pages under `/docs/*` are gone; only `/developers/*` is maintained.
224+
225+## 16. Exact streaming code that worked
226+
227+OpenAI SDK (`openai@7.10.0`) — chat completions with reasoning + usage:
228+
229+```ts
230+import OpenAI from "openai";
231+const client = new OpenAI({ apiKey: process.env.XAI_API_KEY, baseURL: "https://api.x.ai/v1", timeout: 3_600_000, maxRetries: 0 });
232+
233+const stream = await client.chat.completions.create({
234+ model: "grok-4.6",
235+ messages: [{ role: "user", content: "Say hello in French, 5 words max." }],
236+ stream: true,
237+ stream_options: { include_usage: true },
238+ max_completion_tokens: 200,
239+ reasoning_effort: "low", // only 4.6 / 4.5 / 4.3
240+}, { headers: { "x-grok-conv-id": sessionId } });
241+
242+for await (const chunk of stream) {
243+ const d = (chunk.choices[0]?.delta ?? {}) as any;
244+ if (d.reasoning_content) onThinking(d.reasoning_content);
245+ if (d.content) onText(d.content);
246+ if (d.tool_calls) onToolCalls(d.tool_calls); // arrives complete in one chunk
247+ if (chunk.choices[0]?.finish_reason) onFinish(chunk.choices[0].finish_reason);
248+ if (chunk.usage) onUsage(chunk.usage); // last chunk, choices: []
249+}
250+```
251+
252+Raw fetch SSE for `/v1/responses` (used in `research/xai/lib.ts` → `rawSSE`): POST JSON, read `res.body` with `TextDecoder`, split on `\n\n`, take `data:` lines, `JSON.parse`, stop at `[DONE]`; each event's `type` field is the event name (`response.output_text.delta` → `delta`, `response.completed` → `response.usage`, `response.function_call_arguments.done` → `arguments`, `response.output_text.annotation.added` → citation).
253+
254+## 17. Probe results table
255+
256+| # | Probe | Model(s) | Result |
257+|---|---|---|---|
258+| 00 | `GET /models`, `/language-models`, `/image-generation-models`, `/video-generation-models`, `/api-key`, `/me`, `POST /tokenize-text` | — | all 200; 7 language, 3 image, 2 video models; prices in cents/100M tokens; no context_length; tokenizer returns token ids + bytes |
259+| 01a | tiny chat completion `max_completion_tokens: 200` | 6 models | all 200, `finish_reason: stop`; `reasoning_content` present on 5/6; reasoning 46–333 tokens for "2+2"; ~2.6 s for grok-4.6 |
260+| 01b | streaming + `include_usage` | 6 models | SSE `data:` only; `delta.reasoning_content` then `delta.content`; final `choices: []` usage chunk with `cached_tokens`, `reasoning_tokens`, `cost_in_usd_ticks`; `[DONE]` |
261+| 02 | param matrix (21 variants) | 6 models | see §9; penalties rejected everywhere; `stop` only on non-reasoning; `reasoning_effort` per §8; unknown params ignored |
262+| 03 | function call round trip, streaming | 6 models | tool call in a single chunk with complete `arguments`; `finish_reason: tool_calls`; round 2 with `role: tool` OK on all |
263+| 04 | `response_format: json_schema` strict | 6 models | valid JSON matching schema on all |
264+| 05 | vision, base64 PNG data URL | 6 models | 2×2 → 400 (min 8 px sides); 8×8 → 400 (min 512 px total); 32×32 → 200 on all, `image_tokens` 1–3 |
265+| 06 | invalid key / no auth / unknown model / bad body / retired slugs | — | 400 invalid-argument / 401 / 400 / 422 text / 200 served by grok-4.3 |
266+| 07 | `/v1/responses`: basic + `reasoning.summary` + `encrypted_content`, streaming events, function call (flat tool) + `function_call_output`, `text.format` json_schema, `input_image`, multi-agent on chat | grok-4.3 (+multi-agent) | all 200; 13 event types; encrypted reasoning returned; multi-agent on chat completions → 400 |
267+| 08 | web_search tool streaming; legacy `search_parameters`; `web_search` on chat; `include` variants | grok-4.3 | Responses OK (3 searches, `url_citation` annotations + inline `[[N]](url)`, 20.9k input tokens); chat: 410 / 422; `include` accepts `web_search_call.action.sources`, `no_inline_citations` only |
268+| 09 | `finish_reason` on truncation; Responses `reasoning.effort` on 4.20/build/4.3; `x-grok-conv-id` + `prompt_cache_key` + `service_tier`; `store` default + `previous_response_id` + DELETE | mixed | `length`; 4.20/build reject effort, 4.3 `none` OK; header/params accepted, `service_tier: default`; store default `true`, follow-up recalled word, delete → `deleted: true` |
269+| 10 | `tools:[{type:"live_search", sources:[{type:"web"}]}]` on chat | grok-4.3 | 410 Live search deprecated |
270+
271+## Documentation pages used (all fetched 2026-09-08)
272+
273+- https://docs.x.ai/docs/overview (redirect hub) · https://docs.x.ai/developers/quickstart · https://docs.x.ai/developers/community · https://docs.x.ai/developers/release-notes
274+- https://docs.x.ai/developers/models · https://docs.x.ai/developers/grok-4-6 · https://docs.x.ai/developers/pricing · https://docs.x.ai/developers/rate-limits · https://docs.x.ai/developers/migration/may-15-retirement
275+- https://docs.x.ai/developers/rest-api-reference/inference/chat-completions · https://docs.x.ai/developers/rest-api-reference/inference/responses · https://docs.x.ai/developers/rest-api-reference/inference/models · https://docs.x.ai/developers/rest-api-reference/inference/legacy · https://docs.x.ai/developers/rest-api-reference/inference/other
276+- https://docs.x.ai/developers/model-capabilities/text/generate-text · …/text/streaming · …/text/reasoning · …/text/structured-outputs · …/text/multi-agent · …/text/comparison (Responses vs Chat Completions migration) · https://docs.x.ai/developers/model-capabilities/legacy/chat-completions · https://docs.x.ai/developers/model-capabilities/images/understanding
277+- https://docs.x.ai/developers/tools/overview · …/tools/function-calling · …/tools/web-search · …/tools/x-search · …/tools/code-execution · …/tools/remote-mcp · …/tools/citations · …/tools/streaming-and-sync · …/tools/tool-usage-details
278+- https://docs.x.ai/developers/advanced-api-usage/prompt-caching (+ /how-it-works, /usage-and-pricing, /best-practices) · …/batch-api · …/priority-processing · …/deferred-chat-completions · …/context-compaction · https://docs.x.ai/developers/files · https://docs.x.ai/developers/debugging
279+- https://docs.x.ai/sitemap.xml (to discover the new paths) · https://ai-sdk.dev/providers/ai-sdk-providers/xai (Vercel provider)
280+- 404 at audit time: `/docs/guides/responses`, `/docs/api-reference`, `/docs/guides/migration`, `/docs/key-information/rate-limits`, `/docs/guides/prompt-caching`, `/developers/rest-api-reference/inference/legacy-deprecated`, `/developers/rest-api-reference/inference/account`, `/developers/advanced-api-usage/rate-limits`, `/developers/advanced-api-usage/migration`, `/developers/advanced-api-usage/error-handling`, `/developers/model-capabilities/text/chat-completions`.
added docs/provider-research/xai.models.json +356 −0
@@ -0,0 +1,356 @@
1+[
2+ {
3+ "id": "grok-4.6",
4+ "displayName": "Grok 4.6",
5+ "family": "grok-4.6",
6+ "contextTokens": 500000,
7+ "maxOutputTokens": 128000,
8+ "capabilities": {
9+ "text": true,
10+ "vision": true,
11+ "audioInput": false,
12+ "audioOutput": false,
13+ "imageGeneration": false,
14+ "video": false,
15+ "reasoning": true,
16+ "tools": true,
17+ "structuredOutput": true,
18+ "streaming": true,
19+ "files": true,
20+ "webSearch": true
21+ },
22+ "parameters": {
23+ "temperature": true,
24+ "topP": true,
25+ "topK": "accepted-on-chat-completions-undocumented",
26+ "maxTokens": true,
27+ "reasoningEffort": ["low", "medium", "high", "xhigh"],
28+ "thinkingBudget": false,
29+ "stop": false,
30+ "seed": true,
31+ "frequencyPenalty": false,
32+ "presencePenalty": false
33+ },
34+ "pricing": {
35+ "inputPerMillion": 2.0,
36+ "cachedInputPerMillion": 0.5,
37+ "outputPerMillion": 6.0,
38+ "longContextThresholdTokens": 200000,
39+ "longContextInputPerMillion": 4.0,
40+ "longContextCachedInputPerMillion": 1.0,
41+ "longContextOutputPerMillion": 12.0,
42+ "imageInputPerMillionTokens": 2.0
43+ },
44+ "status": "active",
45+ "aliases": [],
46+ "notes": "Flagship (Aug 2026). Always-reasoning; reasoning_effort default high, 'none' rejected ('This model does not support `reasoning_effort` value `none`'). reasoning_content returned in chat completions (plain text, also streamed as delta.reasoning_content). Knowledge cutoff 2026-02-01. Docs: 'no text output limit'; API default cap max_completion_tokens=128000. Large hidden system prompt (~640 prompt tokens on an empty request). Supports web_search/x_search/code_interpreter/mcp/file tools on /v1/responses. Rate-limit headers observed: 7200 req / 50M tokens per window."
47+ },
48+ {
49+ "id": "grok-4.5",
50+ "displayName": "Grok 4.5",
51+ "family": "grok-4.5",
52+ "contextTokens": 500000,
53+ "maxOutputTokens": 128000,
54+ "capabilities": {
55+ "text": true,
56+ "vision": true,
57+ "audioInput": false,
58+ "audioOutput": false,
59+ "imageGeneration": false,
60+ "video": false,
61+ "reasoning": true,
62+ "tools": true,
63+ "structuredOutput": true,
64+ "streaming": true,
65+ "files": true,
66+ "webSearch": true
67+ },
68+ "parameters": {
69+ "temperature": true,
70+ "topP": true,
71+ "topK": "accepted-on-chat-completions-undocumented",
72+ "maxTokens": true,
73+ "reasoningEffort": ["low", "medium", "high"],
74+ "thinkingBudget": false,
75+ "stop": false,
76+ "seed": true,
77+ "frequencyPenalty": false,
78+ "presencePenalty": false
79+ },
80+ "pricing": {
81+ "inputPerMillion": 2.0,
82+ "cachedInputPerMillion": 0.3,
83+ "outputPerMillion": 6.0,
84+ "longContextThresholdTokens": 200000,
85+ "longContextInputPerMillion": 4.0,
86+ "longContextCachedInputPerMillion": 0.6,
87+ "longContextOutputPerMillion": 12.0,
88+ "imageInputPerMillionTokens": 2.0
89+ },
90+ "status": "active",
91+ "aliases": ["grok-4.5-latest", "grok-build-latest"],
92+ "notes": "Coding/agentic model (Jul 2026). Always-reasoning; 'none' rejected; 'xhigh' accepted by the API but docs say it is treated as 'high' on models that do not support it. Very few reasoning tokens on trivial prompts (~13-50). reasoning_content returned. Note the alias 'grok-build-latest' points here, not to grok-build-0.1."
93+ },
94+ {
95+ "id": "grok-4.3",
96+ "displayName": "Grok 4.3",
97+ "family": "grok-4.3",
98+ "contextTokens": 1000000,
99+ "maxOutputTokens": 128000,
100+ "capabilities": {
101+ "text": true,
102+ "vision": true,
103+ "audioInput": false,
104+ "audioOutput": false,
105+ "imageGeneration": false,
106+ "video": false,
107+ "reasoning": true,
108+ "tools": true,
109+ "structuredOutput": true,
110+ "streaming": true,
111+ "files": true,
112+ "webSearch": true
113+ },
114+ "parameters": {
115+ "temperature": true,
116+ "topP": true,
117+ "topK": "accepted-on-chat-completions-undocumented",
118+ "maxTokens": true,
119+ "reasoningEffort": ["none", "low", "medium", "high"],
120+ "thinkingBudget": false,
121+ "stop": false,
122+ "seed": true,
123+ "frequencyPenalty": false,
124+ "presencePenalty": false
125+ },
126+ "pricing": {
127+ "inputPerMillion": 1.25,
128+ "cachedInputPerMillion": 0.2,
129+ "outputPerMillion": 2.5,
130+ "longContextThresholdTokens": 200000,
131+ "longContextInputPerMillion": 2.5,
132+ "longContextCachedInputPerMillion": 0.4,
133+ "longContextOutputPerMillion": 5.0,
134+ "imageInputPerMillionTokens": 1.25
135+ },
136+ "status": "active",
137+ "aliases": ["grok-4.3-latest"],
138+ "notes": "Best value general model; 1M context. The ONLY probed model that accepts reasoning_effort 'none' (reasoning_tokens=0 -> effectively a non-reasoning mode). 'xhigh' accepted (docs/AI SDK say not supported -> treated as high). Retired May-15-2026 slugs (grok-3, grok-4-0709, grok-4-fast-*, grok-4-1-fast-*) are transparently served by grok-4.3 (response.model = 'grok-4.3'). Retired non-reasoning slugs map to effort 'none', reasoning slugs to 'low'. reasoning_content returned. Batch API 20% discount."
139+ },
140+ {
141+ "id": "grok-4.20-0309-reasoning",
142+ "displayName": "Grok 4.20 Reasoning (0309)",
143+ "family": "grok-4.20",
144+ "contextTokens": 1000000,
145+ "maxOutputTokens": 128000,
146+ "capabilities": {
147+ "text": true,
148+ "vision": true,
149+ "audioInput": false,
150+ "audioOutput": false,
151+ "imageGeneration": false,
152+ "video": false,
153+ "reasoning": true,
154+ "tools": true,
155+ "structuredOutput": true,
156+ "streaming": true,
157+ "files": true,
158+ "webSearch": true
159+ },
160+ "parameters": {
161+ "temperature": true,
162+ "topP": true,
163+ "topK": "accepted-on-chat-completions-undocumented",
164+ "maxTokens": true,
165+ "reasoningEffort": false,
166+ "thinkingBudget": false,
167+ "stop": false,
168+ "seed": true,
169+ "frequencyPenalty": false,
170+ "presencePenalty": false
171+ },
172+ "pricing": {
173+ "inputPerMillion": 1.25,
174+ "cachedInputPerMillion": 0.2,
175+ "outputPerMillion": 2.5,
176+ "longContextThresholdTokens": 200000,
177+ "longContextInputPerMillion": 2.5,
178+ "longContextCachedInputPerMillion": 0.4,
179+ "longContextOutputPerMillion": 5.0,
180+ "imageInputPerMillionTokens": 1.25
181+ },
182+ "status": "active",
183+ "aliases": [
184+ "grok-4.20-reasoning-latest",
185+ "grok-4.20",
186+ "grok-4.20-reasoning",
187+ "grok-4.20-0309",
188+ "grok-4.20-beta-0309-reasoning",
189+ "grok-4.20-beta",
190+ "grok-4.20-beta-0309",
191+ "grok-4.20-beta-latest",
192+ "grok-4.20-beta-latest-reasoning",
193+ "grok-4.20-beta-reasoning",
194+ "grok-4.20-experimental-beta-0304-reasoning",
195+ "grok-4.20-experimental-beta-0304",
196+ "grok-4.20-experimental-beta-reasoning-latest",
197+ "grok-4.20-experimental-beta-latest",
198+ "grok-4.20-reasoning-gv2"
199+ ],
200+ "notes": "Always-reasoning, fixed depth: ANY reasoning_effort value (incl. 'none') is rejected with 400 'Model grok-4.20-0309-reasoning does not support parameter reasoningEffort.' (both chat completions and /v1/responses reasoning.effort). reasoning_content returned. Occasionally emits stray '\\\\confidence{NN}' tokens after the answer on trivial prompts (observed with top_k/logprobs). Batch API 20% discount."
201+ },
202+ {
203+ "id": "grok-4.20-0309-non-reasoning",
204+ "displayName": "Grok 4.20 Non-Reasoning (0309)",
205+ "family": "grok-4.20",
206+ "contextTokens": 1000000,
207+ "maxOutputTokens": 128000,
208+ "capabilities": {
209+ "text": true,
210+ "vision": true,
211+ "audioInput": false,
212+ "audioOutput": false,
213+ "imageGeneration": false,
214+ "video": false,
215+ "reasoning": false,
216+ "tools": true,
217+ "structuredOutput": true,
218+ "streaming": true,
219+ "files": true,
220+ "webSearch": true
221+ },
222+ "parameters": {
223+ "temperature": true,
224+ "topP": true,
225+ "topK": "accepted-on-chat-completions-undocumented",
226+ "maxTokens": true,
227+ "reasoningEffort": false,
228+ "thinkingBudget": false,
229+ "stop": true,
230+ "seed": true,
231+ "frequencyPenalty": false,
232+ "presencePenalty": false
233+ },
234+ "pricing": {
235+ "inputPerMillion": 1.25,
236+ "cachedInputPerMillion": 0.2,
237+ "outputPerMillion": 2.5,
238+ "longContextThresholdTokens": 200000,
239+ "longContextInputPerMillion": 2.5,
240+ "longContextCachedInputPerMillion": 0.4,
241+ "longContextOutputPerMillion": 5.0,
242+ "imageInputPerMillionTokens": 1.25
243+ },
244+ "status": "active",
245+ "aliases": [
246+ "grok-4.20-non-reasoning",
247+ "grok-4.20-non-reasoning-latest",
248+ "grok-4.20-beta-non-reasoning",
249+ "grok-4.20-beta-latest-non-reasoning",
250+ "grok-4.20-experimental-beta-0304-non-reasoning",
251+ "grok-4.20-experimental-beta-non-reasoning-latest",
252+ "grok-4.20-beta-0309-non-reasoning",
253+ "grok-4.20-non-reasoning-gv2"
254+ ],
255+ "notes": "The only true non-reasoning model in the lineup (fastest TTFT, reasoning_tokens always 0, no reasoning_content). The ONLY model that accepts `stop`. reasoning_effort rejected. frequency/presence_penalty still rejected (400). Good default for cheap/fast chat. Batch API 20% discount."
256+ },
257+ {
258+ "id": "grok-4.20-multi-agent-0309",
259+ "displayName": "Grok 4.20 Multi-Agent (0309, beta)",
260+ "family": "grok-4.20",
261+ "contextTokens": 1000000,
262+ "maxOutputTokens": null,
263+ "capabilities": {
264+ "text": true,
265+ "vision": true,
266+ "audioInput": false,
267+ "audioOutput": false,
268+ "imageGeneration": false,
269+ "video": false,
270+ "reasoning": true,
271+ "tools": "server-side-only",
272+ "structuredOutput": null,
273+ "streaming": true,
274+ "files": true,
275+ "webSearch": true
276+ },
277+ "parameters": {
278+ "temperature": null,
279+ "topP": null,
280+ "topK": null,
281+ "maxTokens": false,
282+ "reasoningEffort": ["low", "medium", "high", "xhigh"],
283+ "thinkingBudget": false,
284+ "stop": false,
285+ "seed": null,
286+ "frequencyPenalty": false,
287+ "presencePenalty": false
288+ },
289+ "pricing": {
290+ "inputPerMillion": 1.25,
291+ "cachedInputPerMillion": 0.2,
292+ "outputPerMillion": 2.5,
293+ "longContextThresholdTokens": 200000,
294+ "longContextInputPerMillion": 2.5,
295+ "longContextCachedInputPerMillion": 0.4,
296+ "longContextOutputPerMillion": 5.0,
297+ "imageInputPerMillionTokens": 1.25
298+ },
299+ "status": "beta",
300+ "aliases": [
301+ "grok-4.20-multi-agent",
302+ "grok-4.20-multi-agent-latest",
303+ "grok-4.20-multi-agent-beta-latest",
304+ "grok-4.20-multi-agent-experimental-beta-0304",
305+ "grok-4.20-multi-agent-experimental-beta-latest",
306+ "grok-4.20-multi-agent-beta-0309"
307+ ],
308+ "notes": "/v1/responses ONLY: chat completions returns 400 'Multi Agent requests are not allowed on chat completions' (probed). reasoning.effort selects agent count (low/medium = 4 agents, high/xhigh = 16), not depth. No client-side function tools, no max_tokens. All leader + sub-agent tokens billed -> expensive; lower rate limits (T0 9 RPS / 2.5M TPM). Not probed for generation (cost). Deliberately NOT recommended as a default chat model in PolyLLM."
309+ },
310+ {
311+ "id": "grok-build-0.1",
312+ "displayName": "Grok Build 0.1",
313+ "family": "grok-build",
314+ "contextTokens": 256000,
315+ "maxOutputTokens": 128000,
316+ "capabilities": {
317+ "text": true,
318+ "vision": true,
319+ "audioInput": false,
320+ "audioOutput": false,
321+ "imageGeneration": false,
322+ "video": false,
323+ "reasoning": true,
324+ "tools": true,
325+ "structuredOutput": true,
326+ "streaming": true,
327+ "files": null,
328+ "webSearch": null
329+ },
330+ "parameters": {
331+ "temperature": true,
332+ "topP": true,
333+ "topK": "accepted-on-chat-completions-undocumented",
334+ "maxTokens": true,
335+ "reasoningEffort": false,
336+ "thinkingBudget": false,
337+ "stop": false,
338+ "seed": true,
339+ "frequencyPenalty": false,
340+ "presencePenalty": false
341+ },
342+ "pricing": {
343+ "inputPerMillion": 1.0,
344+ "cachedInputPerMillion": 0.2,
345+ "outputPerMillion": 2.0,
346+ "longContextThresholdTokens": 200000,
347+ "longContextInputPerMillion": 2.0,
348+ "longContextCachedInputPerMillion": 0.4,
349+ "longContextOutputPerMillion": 4.0,
350+ "imageInputPerMillionTokens": 1.0
351+ },
352+ "status": "active",
353+ "aliases": ["grok-code-fast-1", "grok-code-fast", "grok-code-fast-1-0825"],
354+ "notes": "Cheapest text model; successor of grok-code-fast-1 (those slugs alias here). Always-reasoning with fixed depth: every reasoning_effort value rejected (400 'does not support parameter reasoningEffort'). Tends to spend many reasoning tokens even on trivial prompts (300-650). reasoning_content returned. Coding-oriented; image input accepted (image_tokens billed)."
355+ }
356+]
added docs/provider-test-matrix.md +34 −0
@@ -0,0 +1,34 @@
1+# Provider test matrix
2+
3+Generated by `pnpm providers:matrix` against the REAL provider APIs on 2026-09-08. A cell is ✅ only when the live request succeeded and the assertion passed. “—” = not run (no key).
4+
5+Test models: openai: gpt-5.4-mini / reasoning gpt-5.4-mini; anthropic: claude-haiku-4-5 / reasoning claude-sonnet-5; gemini: gemini-3.5-flash-lite / reasoning gemini-3.5-flash-lite; xai: grok-4.20-0309-non-reasoning / reasoning grok-4.3.
6+
7+| Capability | OpenAI | Anthropic | Gemini | xAI |
8+| --- | :-: | :-: | :-: | :-: |
9+| Auth | ✅ | ✅ | ✅ | ✅ |
10+| Model list | ✅ | ✅ | ✅ | ✅ |
11+| Text | ✅ | ✅ | ✅ | ✅ |
12+| Streaming | ✅ | ✅ | ✅ | ✅ |
13+| System | ✅ | ✅ | ✅ | ✅ |
14+| Vision | ✅ | ✅ | ✅ | ✅ |
15+| Tools | ✅ | ✅ | ✅ | ✅ |
16+| Structured output | ✅ | ✅ | ✅ | ✅ |
17+| Reasoning | ✅ | ✅ | ✅ | ✅ |
18+| Token usage | ✅ | ✅ | ✅ | ✅ |
19+| Invalid key | ✅ | ✅ | ✅ | ✅ |
20+| Error normalization | ✅ | ✅ | ✅ | ✅ |
21+| Long response | ✅ | ✅ | ✅ | ✅ |
22+
23+## Notes
24+
25+- gemini: models: 18 (gemini-2.5-flash, gemini-2.5-pro, gemma-4-26b-a4b-it, gemma-4-31b-it, gemini-flash-latest…)
26+- gemini: text(gemini-3.5-flash-lite): "OK" deltas=1 usage={"inputTokens":6,"outputTokens":1,"totalTokens":7} finish=stop
27+- gemini: system: "Arr, hello there, me hearty!"
28+- gemini: vision: "Red"
29+- gemini: tools: [{"n":"calculator","a":{"expression":"1234 * 5678"}}] finish=tool-calls
30+- gemini: structured: { "city": "Ottawa", "country": "Canada" }
31+- gemini: reasoning(gemini-3.5-flash-lite): text="16" reasoningChars=2115 reasoningTokens=3907
32+- gemini: invalid key → INVALID_API_KEY (400)
33+- gemini: unknown model → MODEL_NOT_FOUND: { "error": { "code": 404, "message": "models/definitely-not-a-model-xyz is not f
34+- gemini: long: 471 words, 25 deltas
added drizzle.config.ts +10 −0
@@ -0,0 +1,10 @@
1+import { defineConfig } from "drizzle-kit";
2+
3+export default defineConfig({
4+ dialect: "postgresql",
5+ schema: "./src/db/schema.ts",
6+ out: "./drizzle",
7+ dbCredentials: { url: process.env.DATABASE_URL ?? "postgres://localhost:5432/polyllm" },
8+ strict: true,
9+ verbose: false,
10+});
added drizzle/0000_foamy_loners.sql +370 −0
@@ -0,0 +1,370 @@
1+CREATE TABLE "accounts" (
2+ "id" text PRIMARY KEY NOT NULL,
3+ "account_id" text NOT NULL,
4+ "provider_id" text NOT NULL,
5+ "user_id" text NOT NULL,
6+ "access_token" text,
7+ "refresh_token" text,
8+ "id_token" text,
9+ "access_token_expires_at" timestamp with time zone,
10+ "refresh_token_expires_at" timestamp with time zone,
11+ "scope" text,
12+ "password" text,
13+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
14+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
15+);
16+--> statement-breakpoint
17+CREATE TABLE "arena_responses" (
18+ "id" text PRIMARY KEY NOT NULL,
19+ "session_id" text NOT NULL,
20+ "model_key" text NOT NULL,
21+ "provider" text NOT NULL,
22+ "content" text DEFAULT '' NOT NULL,
23+ "reasoning" text,
24+ "status" text DEFAULT 'complete' NOT NULL,
25+ "error" jsonb,
26+ "usage" jsonb,
27+ "latency_ms" integer,
28+ "ttft_ms" integer,
29+ "cost_usd" double precision,
30+ "ratings" jsonb DEFAULT '{}'::jsonb NOT NULL,
31+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
32+);
33+--> statement-breakpoint
34+CREATE TABLE "arena_sessions" (
35+ "id" text PRIMARY KEY NOT NULL,
36+ "user_id" text NOT NULL,
37+ "prompt" text NOT NULL,
38+ "system_prompt" text,
39+ "model_keys" jsonb NOT NULL,
40+ "settings" jsonb DEFAULT '{}'::jsonb NOT NULL,
41+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
42+);
43+--> statement-breakpoint
44+CREATE TABLE "audit_events" (
45+ "id" text PRIMARY KEY NOT NULL,
46+ "user_id" text,
47+ "action" text NOT NULL,
48+ "ip_address" text,
49+ "user_agent" text,
50+ "meta" jsonb DEFAULT '{}'::jsonb NOT NULL,
51+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
52+);
53+--> statement-breakpoint
54+CREATE TABLE "conversation_tags" (
55+ "conversation_id" text NOT NULL,
56+ "tag_id" text NOT NULL,
57+ CONSTRAINT "conversation_tags_conversation_id_tag_id_pk" PRIMARY KEY("conversation_id","tag_id")
58+);
59+--> statement-breakpoint
60+CREATE TABLE "conversations" (
61+ "id" text PRIMARY KEY NOT NULL,
62+ "user_id" text NOT NULL,
63+ "title" text DEFAULT 'New chat' NOT NULL,
64+ "title_source" text DEFAULT 'auto' NOT NULL,
65+ "folder_id" text,
66+ "pinned" boolean DEFAULT false NOT NULL,
67+ "archived" boolean DEFAULT false NOT NULL,
68+ "model_key" text,
69+ "provider" text,
70+ "system_prompt" text,
71+ "settings" jsonb DEFAULT '{}'::jsonb NOT NULL,
72+ "parent_conversation_id" text,
73+ "branched_from_message_id" text,
74+ "message_count" integer DEFAULT 0 NOT NULL,
75+ "total_cost_usd" double precision DEFAULT 0 NOT NULL,
76+ "total_input_tokens" integer DEFAULT 0 NOT NULL,
77+ "total_output_tokens" integer DEFAULT 0 NOT NULL,
78+ "last_message_at" timestamp with time zone,
79+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
80+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
81+);
82+--> statement-breakpoint
83+CREATE TABLE "folders" (
84+ "id" text PRIMARY KEY NOT NULL,
85+ "user_id" text NOT NULL,
86+ "name" text NOT NULL,
87+ "color" text,
88+ "sort_order" integer DEFAULT 0 NOT NULL,
89+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
90+);
91+--> statement-breakpoint
92+CREATE TABLE "message_attachments" (
93+ "id" text PRIMARY KEY NOT NULL,
94+ "user_id" text NOT NULL,
95+ "message_id" text,
96+ "conversation_id" text,
97+ "kind" text NOT NULL,
98+ "name" text NOT NULL,
99+ "mime_type" text NOT NULL,
100+ "size_bytes" integer NOT NULL,
101+ "data_base64" text NOT NULL,
102+ "width" integer,
103+ "height" integer,
104+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
105+);
106+--> statement-breakpoint
107+CREATE TABLE "messages" (
108+ "id" text PRIMARY KEY NOT NULL,
109+ "conversation_id" text NOT NULL,
110+ "user_id" text NOT NULL,
111+ "role" text NOT NULL,
112+ "content" text DEFAULT '' NOT NULL,
113+ "parts" jsonb DEFAULT '[]'::jsonb NOT NULL,
114+ "model_key" text,
115+ "provider" text,
116+ "status" text DEFAULT 'complete' NOT NULL,
117+ "finish_reason" text,
118+ "error" jsonb,
119+ "usage" jsonb,
120+ "settings" jsonb,
121+ "latency_ms" integer,
122+ "ttft_ms" integer,
123+ "cost_usd" double precision,
124+ "parent_message_id" text,
125+ "version" integer DEFAULT 1 NOT NULL,
126+ "active" boolean DEFAULT true NOT NULL,
127+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
128+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
129+);
130+--> statement-breakpoint
131+CREATE TABLE "model_presets" (
132+ "id" text PRIMARY KEY NOT NULL,
133+ "user_id" text NOT NULL,
134+ "name" text NOT NULL,
135+ "description" text,
136+ "icon" text,
137+ "model_key" text NOT NULL,
138+ "system_prompt" text,
139+ "parameters" jsonb DEFAULT '{}'::jsonb NOT NULL,
140+ "tools" jsonb DEFAULT '{}'::jsonb NOT NULL,
141+ "file_settings" jsonb DEFAULT '{}'::jsonb NOT NULL,
142+ "sort_order" integer DEFAULT 0 NOT NULL,
143+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
144+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
145+);
146+--> statement-breakpoint
147+CREATE TABLE "model_sync_runs" (
148+ "id" text PRIMARY KEY NOT NULL,
149+ "provider" text NOT NULL,
150+ "triggered_by" text DEFAULT 'schedule' NOT NULL,
151+ "started_at" timestamp with time zone DEFAULT now() NOT NULL,
152+ "finished_at" timestamp with time zone,
153+ "ok" boolean,
154+ "models_found" integer,
155+ "models_added" integer,
156+ "models_removed" integer,
157+ "latency_ms" integer,
158+ "error_code" text,
159+ "error_message" text
160+);
161+--> statement-breakpoint
162+CREATE TABLE "models" (
163+ "key" text PRIMARY KEY NOT NULL,
164+ "provider" text NOT NULL,
165+ "model_id" text NOT NULL,
166+ "display_name" text NOT NULL,
167+ "family" text,
168+ "capabilities" jsonb NOT NULL,
169+ "limits" jsonb DEFAULT '{}'::jsonb NOT NULL,
170+ "parameters" jsonb DEFAULT '{}'::jsonb NOT NULL,
171+ "pricing" jsonb,
172+ "status" text DEFAULT 'unknown' NOT NULL,
173+ "source" text DEFAULT 'catalog' NOT NULL,
174+ "hidden" boolean DEFAULT false NOT NULL,
175+ "sort_weight" integer DEFAULT 0 NOT NULL,
176+ "metadata" jsonb DEFAULT '{}'::jsonb NOT NULL,
177+ "first_seen_at" timestamp with time zone DEFAULT now() NOT NULL,
178+ "last_seen_at" timestamp with time zone DEFAULT now() NOT NULL,
179+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
180+);
181+--> statement-breakpoint
182+CREATE TABLE "prompt_presets" (
183+ "id" text PRIMARY KEY NOT NULL,
184+ "user_id" text NOT NULL,
185+ "name" text NOT NULL,
186+ "description" text,
187+ "icon" text,
188+ "system_prompt" text NOT NULL,
189+ "default_model_key" text,
190+ "parameters" jsonb DEFAULT '{}'::jsonb NOT NULL,
191+ "tools" jsonb DEFAULT '{}'::jsonb NOT NULL,
192+ "sort_order" integer DEFAULT 0 NOT NULL,
193+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
194+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
195+);
196+--> statement-breakpoint
197+CREATE TABLE "provider_connections" (
198+ "id" text PRIMARY KEY NOT NULL,
199+ "user_id" text NOT NULL,
200+ "provider" text NOT NULL,
201+ "encrypted_key" text NOT NULL,
202+ "key_hint" text NOT NULL,
203+ "key_fingerprint" text NOT NULL,
204+ "status" text DEFAULT 'unverified' NOT NULL,
205+ "last_validated_at" timestamp with time zone,
206+ "last_validation_error" text,
207+ "last_success_at" timestamp with time zone,
208+ "last_error_at" timestamp with time zone,
209+ "last_error_code" text,
210+ "models_available" integer,
211+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
212+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
213+);
214+--> statement-breakpoint
215+CREATE TABLE "sessions" (
216+ "id" text PRIMARY KEY NOT NULL,
217+ "expires_at" timestamp with time zone NOT NULL,
218+ "token" text NOT NULL,
219+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
220+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
221+ "ip_address" text,
222+ "user_agent" text,
223+ "user_id" text NOT NULL
224+);
225+--> statement-breakpoint
226+CREATE TABLE "shared_conversations" (
227+ "id" text PRIMARY KEY NOT NULL,
228+ "conversation_id" text NOT NULL,
229+ "user_id" text NOT NULL,
230+ "title" text NOT NULL,
231+ "snapshot" jsonb NOT NULL,
232+ "is_public" boolean DEFAULT true NOT NULL,
233+ "view_count" integer DEFAULT 0 NOT NULL,
234+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
235+ "revoked_at" timestamp with time zone
236+);
237+--> statement-breakpoint
238+CREATE TABLE "tags" (
239+ "id" text PRIMARY KEY NOT NULL,
240+ "user_id" text NOT NULL,
241+ "name" text NOT NULL,
242+ "color" text,
243+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
244+);
245+--> statement-breakpoint
246+CREATE TABLE "usage_records" (
247+ "id" text PRIMARY KEY NOT NULL,
248+ "user_id" text NOT NULL,
249+ "conversation_id" text,
250+ "message_id" text,
251+ "arena_session_id" text,
252+ "provider" text NOT NULL,
253+ "model_key" text NOT NULL,
254+ "kind" text DEFAULT 'chat' NOT NULL,
255+ "status" text DEFAULT 'ok' NOT NULL,
256+ "error_code" text,
257+ "input_tokens" integer DEFAULT 0 NOT NULL,
258+ "output_tokens" integer DEFAULT 0 NOT NULL,
259+ "cached_tokens" integer DEFAULT 0 NOT NULL,
260+ "reasoning_tokens" integer DEFAULT 0 NOT NULL,
261+ "cost_usd" double precision,
262+ "latency_ms" integer,
263+ "ttft_ms" integer,
264+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
265+);
266+--> statement-breakpoint
267+CREATE TABLE "user_model_favorites" (
268+ "user_id" text NOT NULL,
269+ "model_key" text NOT NULL,
270+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
271+ CONSTRAINT "user_model_favorites_user_id_model_key_pk" PRIMARY KEY("user_id","model_key")
272+);
273+--> statement-breakpoint
274+CREATE TABLE "user_model_recents" (
275+ "user_id" text NOT NULL,
276+ "model_key" text NOT NULL,
277+ "used_at" timestamp with time zone DEFAULT now() NOT NULL,
278+ "uses" integer DEFAULT 1 NOT NULL,
279+ CONSTRAINT "user_model_recents_user_id_model_key_pk" PRIMARY KEY("user_id","model_key")
280+);
281+--> statement-breakpoint
282+CREATE TABLE "user_preferences" (
283+ "user_id" text PRIMARY KEY NOT NULL,
284+ "theme" text DEFAULT 'system' NOT NULL,
285+ "language" text DEFAULT 'en' NOT NULL,
286+ "default_model_key" text,
287+ "default_system_prompt" text,
288+ "enter_to_send" boolean DEFAULT true NOT NULL,
289+ "streaming" boolean DEFAULT true NOT NULL,
290+ "code_wrap" boolean DEFAULT false NOT NULL,
291+ "show_reasoning" boolean DEFAULT true NOT NULL,
292+ "show_costs" boolean DEFAULT true NOT NULL,
293+ "auto_title" boolean DEFAULT true NOT NULL,
294+ "extra" jsonb DEFAULT '{}'::jsonb NOT NULL,
295+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
296+);
297+--> statement-breakpoint
298+CREATE TABLE "users" (
299+ "id" text PRIMARY KEY NOT NULL,
300+ "name" text DEFAULT '' NOT NULL,
301+ "email" text NOT NULL,
302+ "email_verified" boolean DEFAULT false NOT NULL,
303+ "image" text,
304+ "role" text DEFAULT 'user' NOT NULL,
305+ "onboarding_completed_at" timestamp with time zone,
306+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
307+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
308+);
309+--> statement-breakpoint
310+CREATE TABLE "verifications" (
311+ "id" text PRIMARY KEY NOT NULL,
312+ "identifier" text NOT NULL,
313+ "value" text NOT NULL,
314+ "expires_at" timestamp with time zone NOT NULL,
315+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
316+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
317+);
318+--> statement-breakpoint
319+ALTER TABLE "accounts" ADD CONSTRAINT "accounts_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
320+ALTER TABLE "arena_responses" ADD CONSTRAINT "arena_responses_session_id_arena_sessions_id_fk" FOREIGN KEY ("session_id") REFERENCES "public"."arena_sessions"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
321+ALTER TABLE "arena_sessions" ADD CONSTRAINT "arena_sessions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
322+ALTER TABLE "audit_events" ADD CONSTRAINT "audit_events_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
323+ALTER TABLE "conversation_tags" ADD CONSTRAINT "conversation_tags_conversation_id_conversations_id_fk" FOREIGN KEY ("conversation_id") REFERENCES "public"."conversations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
324+ALTER TABLE "conversation_tags" ADD CONSTRAINT "conversation_tags_tag_id_tags_id_fk" FOREIGN KEY ("tag_id") REFERENCES "public"."tags"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
325+ALTER TABLE "conversations" ADD CONSTRAINT "conversations_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
326+ALTER TABLE "conversations" ADD CONSTRAINT "conversations_folder_id_folders_id_fk" FOREIGN KEY ("folder_id") REFERENCES "public"."folders"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
327+ALTER TABLE "folders" ADD CONSTRAINT "folders_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
328+ALTER TABLE "message_attachments" ADD CONSTRAINT "message_attachments_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
329+ALTER TABLE "message_attachments" ADD CONSTRAINT "message_attachments_message_id_messages_id_fk" FOREIGN KEY ("message_id") REFERENCES "public"."messages"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
330+ALTER TABLE "message_attachments" ADD CONSTRAINT "message_attachments_conversation_id_conversations_id_fk" FOREIGN KEY ("conversation_id") REFERENCES "public"."conversations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
331+ALTER TABLE "messages" ADD CONSTRAINT "messages_conversation_id_conversations_id_fk" FOREIGN KEY ("conversation_id") REFERENCES "public"."conversations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
332+ALTER TABLE "messages" ADD CONSTRAINT "messages_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
333+ALTER TABLE "model_presets" ADD CONSTRAINT "model_presets_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
334+ALTER TABLE "prompt_presets" ADD CONSTRAINT "prompt_presets_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
335+ALTER TABLE "provider_connections" ADD CONSTRAINT "provider_connections_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
336+ALTER TABLE "sessions" ADD CONSTRAINT "sessions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
337+ALTER TABLE "shared_conversations" ADD CONSTRAINT "shared_conversations_conversation_id_conversations_id_fk" FOREIGN KEY ("conversation_id") REFERENCES "public"."conversations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
338+ALTER TABLE "shared_conversations" ADD CONSTRAINT "shared_conversations_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
339+ALTER TABLE "tags" ADD CONSTRAINT "tags_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
340+ALTER TABLE "usage_records" ADD CONSTRAINT "usage_records_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
341+ALTER TABLE "user_model_favorites" ADD CONSTRAINT "user_model_favorites_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
342+ALTER TABLE "user_model_recents" ADD CONSTRAINT "user_model_recents_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
343+ALTER TABLE "user_preferences" ADD CONSTRAINT "user_preferences_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
344+CREATE INDEX "accounts_user_idx" ON "accounts" USING btree ("user_id");--> statement-breakpoint
345+CREATE INDEX "arena_responses_session_idx" ON "arena_responses" USING btree ("session_id");--> statement-breakpoint
346+CREATE INDEX "arena_sessions_user_idx" ON "arena_sessions" USING btree ("user_id","created_at");--> statement-breakpoint
347+CREATE INDEX "audit_user_created_idx" ON "audit_events" USING btree ("user_id","created_at");--> statement-breakpoint
348+CREATE INDEX "conversations_user_updated_idx" ON "conversations" USING btree ("user_id","updated_at");--> statement-breakpoint
349+CREATE INDEX "conversations_user_folder_idx" ON "conversations" USING btree ("user_id","folder_id");--> statement-breakpoint
350+CREATE INDEX "conversations_user_model_idx" ON "conversations" USING btree ("user_id","model_key");--> statement-breakpoint
351+CREATE INDEX "folders_user_idx" ON "folders" USING btree ("user_id");--> statement-breakpoint
352+CREATE INDEX "attachments_message_idx" ON "message_attachments" USING btree ("message_id");--> statement-breakpoint
353+CREATE INDEX "attachments_user_idx" ON "message_attachments" USING btree ("user_id");--> statement-breakpoint
354+CREATE INDEX "messages_conversation_created_idx" ON "messages" USING btree ("conversation_id","created_at");--> statement-breakpoint
355+CREATE INDEX "messages_user_idx" ON "messages" USING btree ("user_id");--> statement-breakpoint
356+CREATE INDEX "model_presets_user_idx" ON "model_presets" USING btree ("user_id");--> statement-breakpoint
357+CREATE INDEX "model_sync_runs_provider_started_idx" ON "model_sync_runs" USING btree ("provider","started_at");--> statement-breakpoint
358+CREATE INDEX "models_provider_idx" ON "models" USING btree ("provider");--> statement-breakpoint
359+CREATE INDEX "models_status_idx" ON "models" USING btree ("status");--> statement-breakpoint
360+CREATE INDEX "prompt_presets_user_idx" ON "prompt_presets" USING btree ("user_id");--> statement-breakpoint
361+CREATE UNIQUE INDEX "provider_connections_user_provider_uq" ON "provider_connections" USING btree ("user_id","provider");--> statement-breakpoint
362+CREATE UNIQUE INDEX "sessions_token_uq" ON "sessions" USING btree ("token");--> statement-breakpoint
363+CREATE INDEX "sessions_user_idx" ON "sessions" USING btree ("user_id");--> statement-breakpoint
364+CREATE INDEX "shared_conversation_idx" ON "shared_conversations" USING btree ("conversation_id");--> statement-breakpoint
365+CREATE UNIQUE INDEX "tags_user_name_uq" ON "tags" USING btree ("user_id","name");--> statement-breakpoint
366+CREATE INDEX "usage_user_created_idx" ON "usage_records" USING btree ("user_id","created_at");--> statement-breakpoint
367+CREATE INDEX "usage_user_provider_idx" ON "usage_records" USING btree ("user_id","provider");--> statement-breakpoint
368+CREATE INDEX "usage_user_model_idx" ON "usage_records" USING btree ("user_id","model_key");--> statement-breakpoint
369+CREATE UNIQUE INDEX "users_email_uq" ON "users" USING btree ("email");--> statement-breakpoint
370+CREATE INDEX "verifications_identifier_idx" ON "verifications" USING btree ("identifier");
\ No newline at end of file
added drizzle/meta/0000_snapshot.json +2748 −0
@@ -0,0 +1,2748 @@
1+{
2+ "id": "6f7e7f5c-d043-4e85-b3e5-b92b0ee9d52b",
3+ "prevId": "00000000-0000-0000-0000-000000000000",
4+ "version": "7",
5+ "dialect": "postgresql",
6+ "tables": {
7+ "public.accounts": {
8+ "name": "accounts",
9+ "schema": "",
10+ "columns": {
11+ "id": {
12+ "name": "id",
13+ "type": "text",
14+ "primaryKey": true,
15+ "notNull": true
16+ },
17+ "account_id": {
18+ "name": "account_id",
19+ "type": "text",
20+ "primaryKey": false,
21+ "notNull": true
22+ },
23+ "provider_id": {
24+ "name": "provider_id",
25+ "type": "text",
26+ "primaryKey": false,
27+ "notNull": true
28+ },
29+ "user_id": {
30+ "name": "user_id",
31+ "type": "text",
32+ "primaryKey": false,
33+ "notNull": true
34+ },
35+ "access_token": {
36+ "name": "access_token",
37+ "type": "text",
38+ "primaryKey": false,
39+ "notNull": false
40+ },
41+ "refresh_token": {
42+ "name": "refresh_token",
43+ "type": "text",
44+ "primaryKey": false,
45+ "notNull": false
46+ },
47+ "id_token": {
48+ "name": "id_token",
49+ "type": "text",
50+ "primaryKey": false,
51+ "notNull": false
52+ },
53+ "access_token_expires_at": {
54+ "name": "access_token_expires_at",
55+ "type": "timestamp with time zone",
56+ "primaryKey": false,
57+ "notNull": false
58+ },
59+ "refresh_token_expires_at": {
60+ "name": "refresh_token_expires_at",
61+ "type": "timestamp with time zone",
62+ "primaryKey": false,
63+ "notNull": false
64+ },
65+ "scope": {
66+ "name": "scope",
67+ "type": "text",
68+ "primaryKey": false,
69+ "notNull": false
70+ },
71+ "password": {
72+ "name": "password",
73+ "type": "text",
74+ "primaryKey": false,
75+ "notNull": false
76+ },
77+ "created_at": {
78+ "name": "created_at",
79+ "type": "timestamp with time zone",
80+ "primaryKey": false,
81+ "notNull": true,
82+ "default": "now()"
83+ },
84+ "updated_at": {
85+ "name": "updated_at",
86+ "type": "timestamp with time zone",
87+ "primaryKey": false,
88+ "notNull": true,
89+ "default": "now()"
90+ }
91+ },
92+ "indexes": {
93+ "accounts_user_idx": {
94+ "name": "accounts_user_idx",
95+ "columns": [
96+ {
97+ "expression": "user_id",
98+ "isExpression": false,
99+ "asc": true,
100+ "nulls": "last"
101+ }
102+ ],
103+ "isUnique": false,
104+ "concurrently": false,
105+ "method": "btree",
106+ "with": {}
107+ }
108+ },
109+ "foreignKeys": {
110+ "accounts_user_id_users_id_fk": {
111+ "name": "accounts_user_id_users_id_fk",
112+ "tableFrom": "accounts",
113+ "tableTo": "users",
114+ "columnsFrom": [
115+ "user_id"
116+ ],
117+ "columnsTo": [
118+ "id"
119+ ],
120+ "onDelete": "cascade",
121+ "onUpdate": "no action"
122+ }
123+ },
124+ "compositePrimaryKeys": {},
125+ "uniqueConstraints": {},
126+ "policies": {},
127+ "checkConstraints": {},
128+ "isRLSEnabled": false
129+ },
130+ "public.arena_responses": {
131+ "name": "arena_responses",
132+ "schema": "",
133+ "columns": {
134+ "id": {
135+ "name": "id",
136+ "type": "text",
137+ "primaryKey": true,
138+ "notNull": true
139+ },
140+ "session_id": {
141+ "name": "session_id",
142+ "type": "text",
143+ "primaryKey": false,
144+ "notNull": true
145+ },
146+ "model_key": {
147+ "name": "model_key",
148+ "type": "text",
149+ "primaryKey": false,
150+ "notNull": true
151+ },
152+ "provider": {
153+ "name": "provider",
154+ "type": "text",
155+ "primaryKey": false,
156+ "notNull": true
157+ },
158+ "content": {
159+ "name": "content",
160+ "type": "text",
161+ "primaryKey": false,
162+ "notNull": true,
163+ "default": "''"
164+ },
165+ "reasoning": {
166+ "name": "reasoning",
167+ "type": "text",
168+ "primaryKey": false,
169+ "notNull": false
170+ },
171+ "status": {
172+ "name": "status",
173+ "type": "text",
174+ "primaryKey": false,
175+ "notNull": true,
176+ "default": "'complete'"
177+ },
178+ "error": {
179+ "name": "error",
180+ "type": "jsonb",
181+ "primaryKey": false,
182+ "notNull": false
183+ },
184+ "usage": {
185+ "name": "usage",
186+ "type": "jsonb",
187+ "primaryKey": false,
188+ "notNull": false
189+ },
190+ "latency_ms": {
191+ "name": "latency_ms",
192+ "type": "integer",
193+ "primaryKey": false,
194+ "notNull": false
195+ },
196+ "ttft_ms": {
197+ "name": "ttft_ms",
198+ "type": "integer",
199+ "primaryKey": false,
200+ "notNull": false
201+ },
202+ "cost_usd": {
203+ "name": "cost_usd",
204+ "type": "double precision",
205+ "primaryKey": false,
206+ "notNull": false
207+ },
208+ "ratings": {
209+ "name": "ratings",
210+ "type": "jsonb",
211+ "primaryKey": false,
212+ "notNull": true,
213+ "default": "'{}'::jsonb"
214+ },
215+ "created_at": {
216+ "name": "created_at",
217+ "type": "timestamp with time zone",
218+ "primaryKey": false,
219+ "notNull": true,
220+ "default": "now()"
221+ }
222+ },
223+ "indexes": {
224+ "arena_responses_session_idx": {
225+ "name": "arena_responses_session_idx",
226+ "columns": [
227+ {
228+ "expression": "session_id",
229+ "isExpression": false,
230+ "asc": true,
231+ "nulls": "last"
232+ }
233+ ],
234+ "isUnique": false,
235+ "concurrently": false,
236+ "method": "btree",
237+ "with": {}
238+ }
239+ },
240+ "foreignKeys": {
241+ "arena_responses_session_id_arena_sessions_id_fk": {
242+ "name": "arena_responses_session_id_arena_sessions_id_fk",
243+ "tableFrom": "arena_responses",
244+ "tableTo": "arena_sessions",
245+ "columnsFrom": [
246+ "session_id"
247+ ],
248+ "columnsTo": [
249+ "id"
250+ ],
251+ "onDelete": "cascade",
252+ "onUpdate": "no action"
253+ }
254+ },
255+ "compositePrimaryKeys": {},
256+ "uniqueConstraints": {},
257+ "policies": {},
258+ "checkConstraints": {},
259+ "isRLSEnabled": false
260+ },
261+ "public.arena_sessions": {
262+ "name": "arena_sessions",
263+ "schema": "",
264+ "columns": {
265+ "id": {
266+ "name": "id",
267+ "type": "text",
268+ "primaryKey": true,
269+ "notNull": true
270+ },
271+ "user_id": {
272+ "name": "user_id",
273+ "type": "text",
274+ "primaryKey": false,
275+ "notNull": true
276+ },
277+ "prompt": {
278+ "name": "prompt",
279+ "type": "text",
280+ "primaryKey": false,
281+ "notNull": true
282+ },
283+ "system_prompt": {
284+ "name": "system_prompt",
285+ "type": "text",
286+ "primaryKey": false,
287+ "notNull": false
288+ },
289+ "model_keys": {
290+ "name": "model_keys",
291+ "type": "jsonb",
292+ "primaryKey": false,
293+ "notNull": true
294+ },
295+ "settings": {
296+ "name": "settings",
297+ "type": "jsonb",
298+ "primaryKey": false,
299+ "notNull": true,
300+ "default": "'{}'::jsonb"
301+ },
302+ "created_at": {
303+ "name": "created_at",
304+ "type": "timestamp with time zone",
305+ "primaryKey": false,
306+ "notNull": true,
307+ "default": "now()"
308+ }
309+ },
310+ "indexes": {
311+ "arena_sessions_user_idx": {
312+ "name": "arena_sessions_user_idx",
313+ "columns": [
314+ {
315+ "expression": "user_id",
316+ "isExpression": false,
317+ "asc": true,
318+ "nulls": "last"
319+ },
320+ {
321+ "expression": "created_at",
322+ "isExpression": false,
323+ "asc": true,
324+ "nulls": "last"
325+ }
326+ ],
327+ "isUnique": false,
328+ "concurrently": false,
329+ "method": "btree",
330+ "with": {}
331+ }
332+ },
333+ "foreignKeys": {
334+ "arena_sessions_user_id_users_id_fk": {
335+ "name": "arena_sessions_user_id_users_id_fk",
336+ "tableFrom": "arena_sessions",
337+ "tableTo": "users",
338+ "columnsFrom": [
339+ "user_id"
340+ ],
341+ "columnsTo": [
342+ "id"
343+ ],
344+ "onDelete": "cascade",
345+ "onUpdate": "no action"
346+ }
347+ },
348+ "compositePrimaryKeys": {},
349+ "uniqueConstraints": {},
350+ "policies": {},
351+ "checkConstraints": {},
352+ "isRLSEnabled": false
353+ },
354+ "public.audit_events": {
355+ "name": "audit_events",
356+ "schema": "",
357+ "columns": {
358+ "id": {
359+ "name": "id",
360+ "type": "text",
361+ "primaryKey": true,
362+ "notNull": true
363+ },
364+ "user_id": {
365+ "name": "user_id",
366+ "type": "text",
367+ "primaryKey": false,
368+ "notNull": false
369+ },
370+ "action": {
371+ "name": "action",
372+ "type": "text",
373+ "primaryKey": false,
374+ "notNull": true
375+ },
376+ "ip_address": {
377+ "name": "ip_address",
378+ "type": "text",
379+ "primaryKey": false,
380+ "notNull": false
381+ },
382+ "user_agent": {
383+ "name": "user_agent",
384+ "type": "text",
385+ "primaryKey": false,
386+ "notNull": false
387+ },
388+ "meta": {
389+ "name": "meta",
390+ "type": "jsonb",
391+ "primaryKey": false,
392+ "notNull": true,
393+ "default": "'{}'::jsonb"
394+ },
395+ "created_at": {
396+ "name": "created_at",
397+ "type": "timestamp with time zone",
398+ "primaryKey": false,
399+ "notNull": true,
400+ "default": "now()"
401+ }
402+ },
403+ "indexes": {
404+ "audit_user_created_idx": {
405+ "name": "audit_user_created_idx",
406+ "columns": [
407+ {
408+ "expression": "user_id",
409+ "isExpression": false,
410+ "asc": true,
411+ "nulls": "last"
412+ },
413+ {
414+ "expression": "created_at",
415+ "isExpression": false,
416+ "asc": true,
417+ "nulls": "last"
418+ }
419+ ],
420+ "isUnique": false,
421+ "concurrently": false,
422+ "method": "btree",
423+ "with": {}
424+ }
425+ },
426+ "foreignKeys": {
427+ "audit_events_user_id_users_id_fk": {
428+ "name": "audit_events_user_id_users_id_fk",
429+ "tableFrom": "audit_events",
430+ "tableTo": "users",
431+ "columnsFrom": [
432+ "user_id"
433+ ],
434+ "columnsTo": [
435+ "id"
436+ ],
437+ "onDelete": "set null",
438+ "onUpdate": "no action"
439+ }
440+ },
441+ "compositePrimaryKeys": {},
442+ "uniqueConstraints": {},
443+ "policies": {},
444+ "checkConstraints": {},
445+ "isRLSEnabled": false
446+ },
447+ "public.conversation_tags": {
448+ "name": "conversation_tags",
449+ "schema": "",
450+ "columns": {
451+ "conversation_id": {
452+ "name": "conversation_id",
453+ "type": "text",
454+ "primaryKey": false,
455+ "notNull": true
456+ },
457+ "tag_id": {
458+ "name": "tag_id",
459+ "type": "text",
460+ "primaryKey": false,
461+ "notNull": true
462+ }
463+ },
464+ "indexes": {},
465+ "foreignKeys": {
466+ "conversation_tags_conversation_id_conversations_id_fk": {
467+ "name": "conversation_tags_conversation_id_conversations_id_fk",
468+ "tableFrom": "conversation_tags",
469+ "tableTo": "conversations",
470+ "columnsFrom": [
471+ "conversation_id"
472+ ],
473+ "columnsTo": [
474+ "id"
475+ ],
476+ "onDelete": "cascade",
477+ "onUpdate": "no action"
478+ },
479+ "conversation_tags_tag_id_tags_id_fk": {
480+ "name": "conversation_tags_tag_id_tags_id_fk",
481+ "tableFrom": "conversation_tags",
482+ "tableTo": "tags",
483+ "columnsFrom": [
484+ "tag_id"
485+ ],
486+ "columnsTo": [
487+ "id"
488+ ],
489+ "onDelete": "cascade",
490+ "onUpdate": "no action"
491+ }
492+ },
493+ "compositePrimaryKeys": {
494+ "conversation_tags_conversation_id_tag_id_pk": {
495+ "name": "conversation_tags_conversation_id_tag_id_pk",
496+ "columns": [
497+ "conversation_id",
498+ "tag_id"
499+ ]
500+ }
501+ },
502+ "uniqueConstraints": {},
503+ "policies": {},
504+ "checkConstraints": {},
505+ "isRLSEnabled": false
506+ },
507+ "public.conversations": {
508+ "name": "conversations",
509+ "schema": "",
510+ "columns": {
511+ "id": {
512+ "name": "id",
513+ "type": "text",
514+ "primaryKey": true,
515+ "notNull": true
516+ },
517+ "user_id": {
518+ "name": "user_id",
519+ "type": "text",
520+ "primaryKey": false,
521+ "notNull": true
522+ },
523+ "title": {
524+ "name": "title",
525+ "type": "text",
526+ "primaryKey": false,
527+ "notNull": true,
528+ "default": "'New chat'"
529+ },
530+ "title_source": {
531+ "name": "title_source",
532+ "type": "text",
533+ "primaryKey": false,
534+ "notNull": true,
535+ "default": "'auto'"
536+ },
537+ "folder_id": {
538+ "name": "folder_id",
539+ "type": "text",
540+ "primaryKey": false,
541+ "notNull": false
542+ },
543+ "pinned": {
544+ "name": "pinned",
545+ "type": "boolean",
546+ "primaryKey": false,
547+ "notNull": true,
548+ "default": false
549+ },
550+ "archived": {
551+ "name": "archived",
552+ "type": "boolean",
553+ "primaryKey": false,
554+ "notNull": true,
555+ "default": false
556+ },
557+ "model_key": {
558+ "name": "model_key",
559+ "type": "text",
560+ "primaryKey": false,
561+ "notNull": false
562+ },
563+ "provider": {
564+ "name": "provider",
565+ "type": "text",
566+ "primaryKey": false,
567+ "notNull": false
568+ },
569+ "system_prompt": {
570+ "name": "system_prompt",
571+ "type": "text",
572+ "primaryKey": false,
573+ "notNull": false
574+ },
575+ "settings": {
576+ "name": "settings",
577+ "type": "jsonb",
578+ "primaryKey": false,
579+ "notNull": true,
580+ "default": "'{}'::jsonb"
581+ },
582+ "parent_conversation_id": {
583+ "name": "parent_conversation_id",
584+ "type": "text",
585+ "primaryKey": false,
586+ "notNull": false
587+ },
588+ "branched_from_message_id": {
589+ "name": "branched_from_message_id",
590+ "type": "text",
591+ "primaryKey": false,
592+ "notNull": false
593+ },
594+ "message_count": {
595+ "name": "message_count",
596+ "type": "integer",
597+ "primaryKey": false,
598+ "notNull": true,
599+ "default": 0
600+ },
601+ "total_cost_usd": {
602+ "name": "total_cost_usd",
603+ "type": "double precision",
604+ "primaryKey": false,
605+ "notNull": true,
606+ "default": 0
607+ },
608+ "total_input_tokens": {
609+ "name": "total_input_tokens",
610+ "type": "integer",
611+ "primaryKey": false,
612+ "notNull": true,
613+ "default": 0
614+ },
615+ "total_output_tokens": {
616+ "name": "total_output_tokens",
617+ "type": "integer",
618+ "primaryKey": false,
619+ "notNull": true,
620+ "default": 0
621+ },
622+ "last_message_at": {
623+ "name": "last_message_at",
624+ "type": "timestamp with time zone",
625+ "primaryKey": false,
626+ "notNull": false
627+ },
628+ "created_at": {
629+ "name": "created_at",
630+ "type": "timestamp with time zone",
631+ "primaryKey": false,
632+ "notNull": true,
633+ "default": "now()"
634+ },
635+ "updated_at": {
636+ "name": "updated_at",
637+ "type": "timestamp with time zone",
638+ "primaryKey": false,
639+ "notNull": true,
640+ "default": "now()"
641+ }
642+ },
643+ "indexes": {
644+ "conversations_user_updated_idx": {
645+ "name": "conversations_user_updated_idx",
646+ "columns": [
647+ {
648+ "expression": "user_id",
649+ "isExpression": false,
650+ "asc": true,
651+ "nulls": "last"
652+ },
653+ {
654+ "expression": "updated_at",
655+ "isExpression": false,
656+ "asc": true,
657+ "nulls": "last"
658+ }
659+ ],
660+ "isUnique": false,
661+ "concurrently": false,
662+ "method": "btree",
663+ "with": {}
664+ },
665+ "conversations_user_folder_idx": {
666+ "name": "conversations_user_folder_idx",
667+ "columns": [
668+ {
669+ "expression": "user_id",
670+ "isExpression": false,
671+ "asc": true,
672+ "nulls": "last"
673+ },
674+ {
675+ "expression": "folder_id",
676+ "isExpression": false,
677+ "asc": true,
678+ "nulls": "last"
679+ }
680+ ],
681+ "isUnique": false,
682+ "concurrently": false,
683+ "method": "btree",
684+ "with": {}
685+ },
686+ "conversations_user_model_idx": {
687+ "name": "conversations_user_model_idx",
688+ "columns": [
689+ {
690+ "expression": "user_id",
691+ "isExpression": false,
692+ "asc": true,
693+ "nulls": "last"
694+ },
695+ {
696+ "expression": "model_key",
697+ "isExpression": false,
698+ "asc": true,
699+ "nulls": "last"
700+ }
701+ ],
702+ "isUnique": false,
703+ "concurrently": false,
704+ "method": "btree",
705+ "with": {}
706+ }
707+ },
708+ "foreignKeys": {
709+ "conversations_user_id_users_id_fk": {
710+ "name": "conversations_user_id_users_id_fk",
711+ "tableFrom": "conversations",
712+ "tableTo": "users",
713+ "columnsFrom": [
714+ "user_id"
715+ ],
716+ "columnsTo": [
717+ "id"
718+ ],
719+ "onDelete": "cascade",
720+ "onUpdate": "no action"
721+ },
722+ "conversations_folder_id_folders_id_fk": {
723+ "name": "conversations_folder_id_folders_id_fk",
724+ "tableFrom": "conversations",
725+ "tableTo": "folders",
726+ "columnsFrom": [
727+ "folder_id"
728+ ],
729+ "columnsTo": [
730+ "id"
731+ ],
732+ "onDelete": "set null",
733+ "onUpdate": "no action"
734+ }
735+ },
736+ "compositePrimaryKeys": {},
737+ "uniqueConstraints": {},
738+ "policies": {},
739+ "checkConstraints": {},
740+ "isRLSEnabled": false
741+ },
742+ "public.folders": {
743+ "name": "folders",
744+ "schema": "",
745+ "columns": {
746+ "id": {
747+ "name": "id",
748+ "type": "text",
749+ "primaryKey": true,
750+ "notNull": true
751+ },
752+ "user_id": {
753+ "name": "user_id",
754+ "type": "text",
755+ "primaryKey": false,
756+ "notNull": true
757+ },
758+ "name": {
759+ "name": "name",
760+ "type": "text",
761+ "primaryKey": false,
762+ "notNull": true
763+ },
764+ "color": {
765+ "name": "color",
766+ "type": "text",
767+ "primaryKey": false,
768+ "notNull": false
769+ },
770+ "sort_order": {
771+ "name": "sort_order",
772+ "type": "integer",
773+ "primaryKey": false,
774+ "notNull": true,
775+ "default": 0
776+ },
777+ "created_at": {
778+ "name": "created_at",
779+ "type": "timestamp with time zone",
780+ "primaryKey": false,
781+ "notNull": true,
782+ "default": "now()"
783+ }
784+ },
785+ "indexes": {
786+ "folders_user_idx": {
787+ "name": "folders_user_idx",
788+ "columns": [
789+ {
790+ "expression": "user_id",
791+ "isExpression": false,
792+ "asc": true,
793+ "nulls": "last"
794+ }
795+ ],
796+ "isUnique": false,
797+ "concurrently": false,
798+ "method": "btree",
799+ "with": {}
800+ }
801+ },
802+ "foreignKeys": {
803+ "folders_user_id_users_id_fk": {
804+ "name": "folders_user_id_users_id_fk",
805+ "tableFrom": "folders",
806+ "tableTo": "users",
807+ "columnsFrom": [
808+ "user_id"
809+ ],
810+ "columnsTo": [
811+ "id"
812+ ],
813+ "onDelete": "cascade",
814+ "onUpdate": "no action"
815+ }
816+ },
817+ "compositePrimaryKeys": {},
818+ "uniqueConstraints": {},
819+ "policies": {},
820+ "checkConstraints": {},
821+ "isRLSEnabled": false
822+ },
823+ "public.message_attachments": {
824+ "name": "message_attachments",
825+ "schema": "",
826+ "columns": {
827+ "id": {
828+ "name": "id",
829+ "type": "text",
830+ "primaryKey": true,
831+ "notNull": true
832+ },
833+ "user_id": {
834+ "name": "user_id",
835+ "type": "text",
836+ "primaryKey": false,
837+ "notNull": true
838+ },
839+ "message_id": {
840+ "name": "message_id",
841+ "type": "text",
842+ "primaryKey": false,
843+ "notNull": false
844+ },
845+ "conversation_id": {
846+ "name": "conversation_id",
847+ "type": "text",
848+ "primaryKey": false,
849+ "notNull": false
850+ },
851+ "kind": {
852+ "name": "kind",
853+ "type": "text",
854+ "primaryKey": false,
855+ "notNull": true
856+ },
857+ "name": {
858+ "name": "name",
859+ "type": "text",
860+ "primaryKey": false,
861+ "notNull": true
862+ },
863+ "mime_type": {
864+ "name": "mime_type",
865+ "type": "text",
866+ "primaryKey": false,
867+ "notNull": true
868+ },
869+ "size_bytes": {
870+ "name": "size_bytes",
871+ "type": "integer",
872+ "primaryKey": false,
873+ "notNull": true
874+ },
875+ "data_base64": {
876+ "name": "data_base64",
877+ "type": "text",
878+ "primaryKey": false,
879+ "notNull": true
880+ },
881+ "width": {
882+ "name": "width",
883+ "type": "integer",
884+ "primaryKey": false,
885+ "notNull": false
886+ },
887+ "height": {
888+ "name": "height",
889+ "type": "integer",
890+ "primaryKey": false,
891+ "notNull": false
892+ },
893+ "created_at": {
894+ "name": "created_at",
895+ "type": "timestamp with time zone",
896+ "primaryKey": false,
897+ "notNull": true,
898+ "default": "now()"
899+ }
900+ },
901+ "indexes": {
902+ "attachments_message_idx": {
903+ "name": "attachments_message_idx",
904+ "columns": [
905+ {
906+ "expression": "message_id",
907+ "isExpression": false,
908+ "asc": true,
909+ "nulls": "last"
910+ }
911+ ],
912+ "isUnique": false,
913+ "concurrently": false,
914+ "method": "btree",
915+ "with": {}
916+ },
917+ "attachments_user_idx": {
918+ "name": "attachments_user_idx",
919+ "columns": [
920+ {
921+ "expression": "user_id",
922+ "isExpression": false,
923+ "asc": true,
924+ "nulls": "last"
925+ }
926+ ],
927+ "isUnique": false,
928+ "concurrently": false,
929+ "method": "btree",
930+ "with": {}
931+ }
932+ },
933+ "foreignKeys": {
934+ "message_attachments_user_id_users_id_fk": {
935+ "name": "message_attachments_user_id_users_id_fk",
936+ "tableFrom": "message_attachments",
937+ "tableTo": "users",
938+ "columnsFrom": [
939+ "user_id"
940+ ],
941+ "columnsTo": [
942+ "id"
943+ ],
944+ "onDelete": "cascade",
945+ "onUpdate": "no action"
946+ },
947+ "message_attachments_message_id_messages_id_fk": {
948+ "name": "message_attachments_message_id_messages_id_fk",
949+ "tableFrom": "message_attachments",
950+ "tableTo": "messages",
951+ "columnsFrom": [
952+ "message_id"
953+ ],
954+ "columnsTo": [
955+ "id"
956+ ],
957+ "onDelete": "cascade",
958+ "onUpdate": "no action"
959+ },
960+ "message_attachments_conversation_id_conversations_id_fk": {
961+ "name": "message_attachments_conversation_id_conversations_id_fk",
962+ "tableFrom": "message_attachments",
963+ "tableTo": "conversations",
964+ "columnsFrom": [
965+ "conversation_id"
966+ ],
967+ "columnsTo": [
968+ "id"
969+ ],
970+ "onDelete": "cascade",
971+ "onUpdate": "no action"
972+ }
973+ },
974+ "compositePrimaryKeys": {},
975+ "uniqueConstraints": {},
976+ "policies": {},
977+ "checkConstraints": {},
978+ "isRLSEnabled": false
979+ },
980+ "public.messages": {
981+ "name": "messages",
982+ "schema": "",
983+ "columns": {
984+ "id": {
985+ "name": "id",
986+ "type": "text",
987+ "primaryKey": true,
988+ "notNull": true
989+ },
990+ "conversation_id": {
991+ "name": "conversation_id",
992+ "type": "text",
993+ "primaryKey": false,
994+ "notNull": true
995+ },
996+ "user_id": {
997+ "name": "user_id",
998+ "type": "text",
999+ "primaryKey": false,
1000+ "notNull": true
1001+ },
1002+ "role": {
1003+ "name": "role",
1004+ "type": "text",
1005+ "primaryKey": false,
1006+ "notNull": true
1007+ },
1008+ "content": {
1009+ "name": "content",
1010+ "type": "text",
1011+ "primaryKey": false,
1012+ "notNull": true,
1013+ "default": "''"
1014+ },
1015+ "parts": {
1016+ "name": "parts",
1017+ "type": "jsonb",
1018+ "primaryKey": false,
1019+ "notNull": true,
1020+ "default": "'[]'::jsonb"
1021+ },
1022+ "model_key": {
1023+ "name": "model_key",
1024+ "type": "text",
1025+ "primaryKey": false,
1026+ "notNull": false
1027+ },
1028+ "provider": {
1029+ "name": "provider",
1030+ "type": "text",
1031+ "primaryKey": false,
1032+ "notNull": false
1033+ },
1034+ "status": {
1035+ "name": "status",
1036+ "type": "text",
1037+ "primaryKey": false,
1038+ "notNull": true,
1039+ "default": "'complete'"
1040+ },
1041+ "finish_reason": {
1042+ "name": "finish_reason",
1043+ "type": "text",
1044+ "primaryKey": false,
1045+ "notNull": false
1046+ },
1047+ "error": {
1048+ "name": "error",
1049+ "type": "jsonb",
1050+ "primaryKey": false,
1051+ "notNull": false
1052+ },
1053+ "usage": {
1054+ "name": "usage",
1055+ "type": "jsonb",
1056+ "primaryKey": false,
1057+ "notNull": false
1058+ },
1059+ "settings": {
1060+ "name": "settings",
1061+ "type": "jsonb",
1062+ "primaryKey": false,
1063+ "notNull": false
1064+ },
1065+ "latency_ms": {
1066+ "name": "latency_ms",
1067+ "type": "integer",
1068+ "primaryKey": false,
1069+ "notNull": false
1070+ },
1071+ "ttft_ms": {
1072+ "name": "ttft_ms",
1073+ "type": "integer",
1074+ "primaryKey": false,
1075+ "notNull": false
1076+ },
1077+ "cost_usd": {
1078+ "name": "cost_usd",
1079+ "type": "double precision",
1080+ "primaryKey": false,
1081+ "notNull": false
1082+ },
1083+ "parent_message_id": {
1084+ "name": "parent_message_id",
1085+ "type": "text",
1086+ "primaryKey": false,
1087+ "notNull": false
1088+ },
1089+ "version": {
1090+ "name": "version",
1091+ "type": "integer",
1092+ "primaryKey": false,
1093+ "notNull": true,
1094+ "default": 1
1095+ },
1096+ "active": {
1097+ "name": "active",
1098+ "type": "boolean",
1099+ "primaryKey": false,
1100+ "notNull": true,
1101+ "default": true
1102+ },
1103+ "created_at": {
1104+ "name": "created_at",
1105+ "type": "timestamp with time zone",
1106+ "primaryKey": false,
1107+ "notNull": true,
1108+ "default": "now()"
1109+ },
1110+ "updated_at": {
1111+ "name": "updated_at",
1112+ "type": "timestamp with time zone",
1113+ "primaryKey": false,
1114+ "notNull": true,
1115+ "default": "now()"
1116+ }
1117+ },
1118+ "indexes": {
1119+ "messages_conversation_created_idx": {
1120+ "name": "messages_conversation_created_idx",
1121+ "columns": [
1122+ {
1123+ "expression": "conversation_id",
1124+ "isExpression": false,
1125+ "asc": true,
1126+ "nulls": "last"
1127+ },
1128+ {
1129+ "expression": "created_at",
1130+ "isExpression": false,
1131+ "asc": true,
1132+ "nulls": "last"
1133+ }
1134+ ],
1135+ "isUnique": false,
1136+ "concurrently": false,
1137+ "method": "btree",
1138+ "with": {}
1139+ },
1140+ "messages_user_idx": {
1141+ "name": "messages_user_idx",
1142+ "columns": [
1143+ {
1144+ "expression": "user_id",
1145+ "isExpression": false,
1146+ "asc": true,
1147+ "nulls": "last"
1148+ }
1149+ ],
1150+ "isUnique": false,
1151+ "concurrently": false,
1152+ "method": "btree",
1153+ "with": {}
1154+ }
1155+ },
1156+ "foreignKeys": {
1157+ "messages_conversation_id_conversations_id_fk": {
1158+ "name": "messages_conversation_id_conversations_id_fk",
1159+ "tableFrom": "messages",
1160+ "tableTo": "conversations",
1161+ "columnsFrom": [
1162+ "conversation_id"
1163+ ],
1164+ "columnsTo": [
1165+ "id"
1166+ ],
1167+ "onDelete": "cascade",
1168+ "onUpdate": "no action"
1169+ },
1170+ "messages_user_id_users_id_fk": {
1171+ "name": "messages_user_id_users_id_fk",
1172+ "tableFrom": "messages",
1173+ "tableTo": "users",
1174+ "columnsFrom": [
1175+ "user_id"
1176+ ],
1177+ "columnsTo": [
1178+ "id"
1179+ ],
1180+ "onDelete": "cascade",
1181+ "onUpdate": "no action"
1182+ }
1183+ },
1184+ "compositePrimaryKeys": {},
1185+ "uniqueConstraints": {},
1186+ "policies": {},
1187+ "checkConstraints": {},
1188+ "isRLSEnabled": false
1189+ },
1190+ "public.model_presets": {
1191+ "name": "model_presets",
1192+ "schema": "",
1193+ "columns": {
1194+ "id": {
1195+ "name": "id",
1196+ "type": "text",
1197+ "primaryKey": true,
1198+ "notNull": true
1199+ },
1200+ "user_id": {
1201+ "name": "user_id",
1202+ "type": "text",
1203+ "primaryKey": false,
1204+ "notNull": true
1205+ },
1206+ "name": {
1207+ "name": "name",
1208+ "type": "text",
1209+ "primaryKey": false,
1210+ "notNull": true
1211+ },
1212+ "description": {
1213+ "name": "description",
1214+ "type": "text",
1215+ "primaryKey": false,
1216+ "notNull": false
1217+ },
1218+ "icon": {
1219+ "name": "icon",
1220+ "type": "text",
1221+ "primaryKey": false,
1222+ "notNull": false
1223+ },
1224+ "model_key": {
1225+ "name": "model_key",
1226+ "type": "text",
1227+ "primaryKey": false,
1228+ "notNull": true
1229+ },
1230+ "system_prompt": {
1231+ "name": "system_prompt",
1232+ "type": "text",
1233+ "primaryKey": false,
1234+ "notNull": false
1235+ },
1236+ "parameters": {
1237+ "name": "parameters",
1238+ "type": "jsonb",
1239+ "primaryKey": false,
1240+ "notNull": true,
1241+ "default": "'{}'::jsonb"
1242+ },
1243+ "tools": {
1244+ "name": "tools",
1245+ "type": "jsonb",
1246+ "primaryKey": false,
1247+ "notNull": true,
1248+ "default": "'{}'::jsonb"
1249+ },
1250+ "file_settings": {
1251+ "name": "file_settings",
1252+ "type": "jsonb",
1253+ "primaryKey": false,
1254+ "notNull": true,
1255+ "default": "'{}'::jsonb"
1256+ },
1257+ "sort_order": {
1258+ "name": "sort_order",
1259+ "type": "integer",
1260+ "primaryKey": false,
1261+ "notNull": true,
1262+ "default": 0
1263+ },
1264+ "created_at": {
1265+ "name": "created_at",
1266+ "type": "timestamp with time zone",
1267+ "primaryKey": false,
1268+ "notNull": true,
1269+ "default": "now()"
1270+ },
1271+ "updated_at": {
1272+ "name": "updated_at",
1273+ "type": "timestamp with time zone",
1274+ "primaryKey": false,
1275+ "notNull": true,
1276+ "default": "now()"
1277+ }
1278+ },
1279+ "indexes": {
1280+ "model_presets_user_idx": {
1281+ "name": "model_presets_user_idx",
1282+ "columns": [
1283+ {
1284+ "expression": "user_id",
1285+ "isExpression": false,
1286+ "asc": true,
1287+ "nulls": "last"
1288+ }
1289+ ],
1290+ "isUnique": false,
1291+ "concurrently": false,
1292+ "method": "btree",
1293+ "with": {}
1294+ }
1295+ },
1296+ "foreignKeys": {
1297+ "model_presets_user_id_users_id_fk": {
1298+ "name": "model_presets_user_id_users_id_fk",
1299+ "tableFrom": "model_presets",
1300+ "tableTo": "users",
1301+ "columnsFrom": [
1302+ "user_id"
1303+ ],
1304+ "columnsTo": [
1305+ "id"
1306+ ],
1307+ "onDelete": "cascade",
1308+ "onUpdate": "no action"
1309+ }
1310+ },
1311+ "compositePrimaryKeys": {},
1312+ "uniqueConstraints": {},
1313+ "policies": {},
1314+ "checkConstraints": {},
1315+ "isRLSEnabled": false
1316+ },
1317+ "public.model_sync_runs": {
1318+ "name": "model_sync_runs",
1319+ "schema": "",
1320+ "columns": {
1321+ "id": {
1322+ "name": "id",
1323+ "type": "text",
1324+ "primaryKey": true,
1325+ "notNull": true
1326+ },
1327+ "provider": {
1328+ "name": "provider",
1329+ "type": "text",
1330+ "primaryKey": false,
1331+ "notNull": true
1332+ },
1333+ "triggered_by": {
1334+ "name": "triggered_by",
1335+ "type": "text",
1336+ "primaryKey": false,
1337+ "notNull": true,
1338+ "default": "'schedule'"
1339+ },
1340+ "started_at": {
1341+ "name": "started_at",
1342+ "type": "timestamp with time zone",
1343+ "primaryKey": false,
1344+ "notNull": true,
1345+ "default": "now()"
1346+ },
1347+ "finished_at": {
1348+ "name": "finished_at",
1349+ "type": "timestamp with time zone",
1350+ "primaryKey": false,
1351+ "notNull": false
1352+ },
1353+ "ok": {
1354+ "name": "ok",
1355+ "type": "boolean",
1356+ "primaryKey": false,
1357+ "notNull": false
1358+ },
1359+ "models_found": {
1360+ "name": "models_found",
1361+ "type": "integer",
1362+ "primaryKey": false,
1363+ "notNull": false
1364+ },
1365+ "models_added": {
1366+ "name": "models_added",
1367+ "type": "integer",
1368+ "primaryKey": false,
1369+ "notNull": false
1370+ },
1371+ "models_removed": {
1372+ "name": "models_removed",
1373+ "type": "integer",
1374+ "primaryKey": false,
1375+ "notNull": false
1376+ },
1377+ "latency_ms": {
1378+ "name": "latency_ms",
1379+ "type": "integer",
1380+ "primaryKey": false,
1381+ "notNull": false
1382+ },
1383+ "error_code": {
1384+ "name": "error_code",
1385+ "type": "text",
1386+ "primaryKey": false,
1387+ "notNull": false
1388+ },
1389+ "error_message": {
1390+ "name": "error_message",
1391+ "type": "text",
1392+ "primaryKey": false,
1393+ "notNull": false
1394+ }
1395+ },
1396+ "indexes": {
1397+ "model_sync_runs_provider_started_idx": {
1398+ "name": "model_sync_runs_provider_started_idx",
1399+ "columns": [
1400+ {
1401+ "expression": "provider",
1402+ "isExpression": false,
1403+ "asc": true,
1404+ "nulls": "last"
1405+ },
1406+ {
1407+ "expression": "started_at",
1408+ "isExpression": false,
1409+ "asc": true,
1410+ "nulls": "last"
1411+ }
1412+ ],
1413+ "isUnique": false,
1414+ "concurrently": false,
1415+ "method": "btree",
1416+ "with": {}
1417+ }
1418+ },
1419+ "foreignKeys": {},
1420+ "compositePrimaryKeys": {},
1421+ "uniqueConstraints": {},
1422+ "policies": {},
1423+ "checkConstraints": {},
1424+ "isRLSEnabled": false
1425+ },
1426+ "public.models": {
1427+ "name": "models",
1428+ "schema": "",
1429+ "columns": {
1430+ "key": {
1431+ "name": "key",
1432+ "type": "text",
1433+ "primaryKey": true,
1434+ "notNull": true
1435+ },
1436+ "provider": {
1437+ "name": "provider",
1438+ "type": "text",
1439+ "primaryKey": false,
1440+ "notNull": true
1441+ },
1442+ "model_id": {
1443+ "name": "model_id",
1444+ "type": "text",
1445+ "primaryKey": false,
1446+ "notNull": true
1447+ },
1448+ "display_name": {
1449+ "name": "display_name",
1450+ "type": "text",
1451+ "primaryKey": false,
1452+ "notNull": true
1453+ },
1454+ "family": {
1455+ "name": "family",
1456+ "type": "text",
1457+ "primaryKey": false,
1458+ "notNull": false
1459+ },
1460+ "capabilities": {
1461+ "name": "capabilities",
1462+ "type": "jsonb",
1463+ "primaryKey": false,
1464+ "notNull": true
1465+ },
1466+ "limits": {
1467+ "name": "limits",
1468+ "type": "jsonb",
1469+ "primaryKey": false,
1470+ "notNull": true,
1471+ "default": "'{}'::jsonb"
1472+ },
1473+ "parameters": {
1474+ "name": "parameters",
1475+ "type": "jsonb",
1476+ "primaryKey": false,
1477+ "notNull": true,
1478+ "default": "'{}'::jsonb"
1479+ },
1480+ "pricing": {
1481+ "name": "pricing",
1482+ "type": "jsonb",
1483+ "primaryKey": false,
1484+ "notNull": false
1485+ },
1486+ "status": {
1487+ "name": "status",
1488+ "type": "text",
1489+ "primaryKey": false,
1490+ "notNull": true,
1491+ "default": "'unknown'"
1492+ },
1493+ "source": {
1494+ "name": "source",
1495+ "type": "text",
1496+ "primaryKey": false,
1497+ "notNull": true,
1498+ "default": "'catalog'"
1499+ },
1500+ "hidden": {
1501+ "name": "hidden",
1502+ "type": "boolean",
1503+ "primaryKey": false,
1504+ "notNull": true,
1505+ "default": false
1506+ },
1507+ "sort_weight": {
1508+ "name": "sort_weight",
1509+ "type": "integer",
1510+ "primaryKey": false,
1511+ "notNull": true,
1512+ "default": 0
1513+ },
1514+ "metadata": {
1515+ "name": "metadata",
1516+ "type": "jsonb",
1517+ "primaryKey": false,
1518+ "notNull": true,
1519+ "default": "'{}'::jsonb"
1520+ },
1521+ "first_seen_at": {
1522+ "name": "first_seen_at",
1523+ "type": "timestamp with time zone",
1524+ "primaryKey": false,
1525+ "notNull": true,
1526+ "default": "now()"
1527+ },
1528+ "last_seen_at": {
1529+ "name": "last_seen_at",
1530+ "type": "timestamp with time zone",
1531+ "primaryKey": false,
1532+ "notNull": true,
1533+ "default": "now()"
1534+ },
1535+ "updated_at": {
1536+ "name": "updated_at",
1537+ "type": "timestamp with time zone",
1538+ "primaryKey": false,
1539+ "notNull": true,
1540+ "default": "now()"
1541+ }
1542+ },
1543+ "indexes": {
1544+ "models_provider_idx": {
1545+ "name": "models_provider_idx",
1546+ "columns": [
1547+ {
1548+ "expression": "provider",
1549+ "isExpression": false,
1550+ "asc": true,
1551+ "nulls": "last"
1552+ }
1553+ ],
1554+ "isUnique": false,
1555+ "concurrently": false,
1556+ "method": "btree",
1557+ "with": {}
1558+ },
1559+ "models_status_idx": {
1560+ "name": "models_status_idx",
1561+ "columns": [
1562+ {
1563+ "expression": "status",
1564+ "isExpression": false,
1565+ "asc": true,
1566+ "nulls": "last"
1567+ }
1568+ ],
1569+ "isUnique": false,
1570+ "concurrently": false,
1571+ "method": "btree",
1572+ "with": {}
1573+ }
1574+ },
1575+ "foreignKeys": {},
1576+ "compositePrimaryKeys": {},
1577+ "uniqueConstraints": {},
1578+ "policies": {},
1579+ "checkConstraints": {},
1580+ "isRLSEnabled": false
1581+ },
1582+ "public.prompt_presets": {
1583+ "name": "prompt_presets",
1584+ "schema": "",
1585+ "columns": {
1586+ "id": {
1587+ "name": "id",
1588+ "type": "text",
1589+ "primaryKey": true,
1590+ "notNull": true
1591+ },
1592+ "user_id": {
1593+ "name": "user_id",
1594+ "type": "text",
1595+ "primaryKey": false,
1596+ "notNull": true
1597+ },
1598+ "name": {
1599+ "name": "name",
1600+ "type": "text",
1601+ "primaryKey": false,
1602+ "notNull": true
1603+ },
1604+ "description": {
1605+ "name": "description",
1606+ "type": "text",
1607+ "primaryKey": false,
1608+ "notNull": false
1609+ },
1610+ "icon": {
1611+ "name": "icon",
1612+ "type": "text",
1613+ "primaryKey": false,
1614+ "notNull": false
1615+ },
1616+ "system_prompt": {
1617+ "name": "system_prompt",
1618+ "type": "text",
1619+ "primaryKey": false,
1620+ "notNull": true
1621+ },
1622+ "default_model_key": {
1623+ "name": "default_model_key",
1624+ "type": "text",
1625+ "primaryKey": false,
1626+ "notNull": false
1627+ },
1628+ "parameters": {
1629+ "name": "parameters",
1630+ "type": "jsonb",
1631+ "primaryKey": false,
1632+ "notNull": true,
1633+ "default": "'{}'::jsonb"
1634+ },
1635+ "tools": {
1636+ "name": "tools",
1637+ "type": "jsonb",
1638+ "primaryKey": false,
1639+ "notNull": true,
1640+ "default": "'{}'::jsonb"
1641+ },
1642+ "sort_order": {
1643+ "name": "sort_order",
1644+ "type": "integer",
1645+ "primaryKey": false,
1646+ "notNull": true,
1647+ "default": 0
1648+ },
1649+ "created_at": {
1650+ "name": "created_at",
1651+ "type": "timestamp with time zone",
1652+ "primaryKey": false,
1653+ "notNull": true,
1654+ "default": "now()"
1655+ },
1656+ "updated_at": {
1657+ "name": "updated_at",
1658+ "type": "timestamp with time zone",
1659+ "primaryKey": false,
1660+ "notNull": true,
1661+ "default": "now()"
1662+ }
1663+ },
1664+ "indexes": {
1665+ "prompt_presets_user_idx": {
1666+ "name": "prompt_presets_user_idx",
1667+ "columns": [
1668+ {
1669+ "expression": "user_id",
1670+ "isExpression": false,
1671+ "asc": true,
1672+ "nulls": "last"
1673+ }
1674+ ],
1675+ "isUnique": false,
1676+ "concurrently": false,
1677+ "method": "btree",
1678+ "with": {}
1679+ }
1680+ },
1681+ "foreignKeys": {
1682+ "prompt_presets_user_id_users_id_fk": {
1683+ "name": "prompt_presets_user_id_users_id_fk",
1684+ "tableFrom": "prompt_presets",
1685+ "tableTo": "users",
1686+ "columnsFrom": [
1687+ "user_id"
1688+ ],
1689+ "columnsTo": [
1690+ "id"
1691+ ],
1692+ "onDelete": "cascade",
1693+ "onUpdate": "no action"
1694+ }
1695+ },
1696+ "compositePrimaryKeys": {},
1697+ "uniqueConstraints": {},
1698+ "policies": {},
1699+ "checkConstraints": {},
1700+ "isRLSEnabled": false
1701+ },
1702+ "public.provider_connections": {
1703+ "name": "provider_connections",
1704+ "schema": "",
1705+ "columns": {
1706+ "id": {
1707+ "name": "id",
1708+ "type": "text",
1709+ "primaryKey": true,
1710+ "notNull": true
1711+ },
1712+ "user_id": {
1713+ "name": "user_id",
1714+ "type": "text",
1715+ "primaryKey": false,
1716+ "notNull": true
1717+ },
1718+ "provider": {
1719+ "name": "provider",
1720+ "type": "text",
1721+ "primaryKey": false,
1722+ "notNull": true
1723+ },
1724+ "encrypted_key": {
1725+ "name": "encrypted_key",
1726+ "type": "text",
1727+ "primaryKey": false,
1728+ "notNull": true
1729+ },
1730+ "key_hint": {
1731+ "name": "key_hint",
1732+ "type": "text",
1733+ "primaryKey": false,
1734+ "notNull": true
1735+ },
1736+ "key_fingerprint": {
1737+ "name": "key_fingerprint",
1738+ "type": "text",
1739+ "primaryKey": false,
1740+ "notNull": true
1741+ },
1742+ "status": {
1743+ "name": "status",
1744+ "type": "text",
1745+ "primaryKey": false,
1746+ "notNull": true,
1747+ "default": "'unverified'"
1748+ },
1749+ "last_validated_at": {
1750+ "name": "last_validated_at",
1751+ "type": "timestamp with time zone",
1752+ "primaryKey": false,
1753+ "notNull": false
1754+ },
1755+ "last_validation_error": {
1756+ "name": "last_validation_error",
1757+ "type": "text",
1758+ "primaryKey": false,
1759+ "notNull": false
1760+ },
1761+ "last_success_at": {
1762+ "name": "last_success_at",
1763+ "type": "timestamp with time zone",
1764+ "primaryKey": false,
1765+ "notNull": false
1766+ },
1767+ "last_error_at": {
1768+ "name": "last_error_at",
1769+ "type": "timestamp with time zone",
1770+ "primaryKey": false,
1771+ "notNull": false
1772+ },
1773+ "last_error_code": {
1774+ "name": "last_error_code",
1775+ "type": "text",
1776+ "primaryKey": false,
1777+ "notNull": false
1778+ },
1779+ "models_available": {
1780+ "name": "models_available",
1781+ "type": "integer",
1782+ "primaryKey": false,
1783+ "notNull": false
1784+ },
1785+ "created_at": {
1786+ "name": "created_at",
1787+ "type": "timestamp with time zone",
1788+ "primaryKey": false,
1789+ "notNull": true,
1790+ "default": "now()"
1791+ },
1792+ "updated_at": {
1793+ "name": "updated_at",
1794+ "type": "timestamp with time zone",
1795+ "primaryKey": false,
1796+ "notNull": true,
1797+ "default": "now()"
1798+ }
1799+ },
1800+ "indexes": {
1801+ "provider_connections_user_provider_uq": {
1802+ "name": "provider_connections_user_provider_uq",
1803+ "columns": [
1804+ {
1805+ "expression": "user_id",
1806+ "isExpression": false,
1807+ "asc": true,
1808+ "nulls": "last"
1809+ },
1810+ {
1811+ "expression": "provider",
1812+ "isExpression": false,
1813+ "asc": true,
1814+ "nulls": "last"
1815+ }
1816+ ],
1817+ "isUnique": true,
1818+ "concurrently": false,
1819+ "method": "btree",
1820+ "with": {}
1821+ }
1822+ },
1823+ "foreignKeys": {
1824+ "provider_connections_user_id_users_id_fk": {
1825+ "name": "provider_connections_user_id_users_id_fk",
1826+ "tableFrom": "provider_connections",
1827+ "tableTo": "users",
1828+ "columnsFrom": [
1829+ "user_id"
1830+ ],
1831+ "columnsTo": [
1832+ "id"
1833+ ],
1834+ "onDelete": "cascade",
1835+ "onUpdate": "no action"
1836+ }
1837+ },
1838+ "compositePrimaryKeys": {},
1839+ "uniqueConstraints": {},
1840+ "policies": {},
1841+ "checkConstraints": {},
1842+ "isRLSEnabled": false
1843+ },
1844+ "public.sessions": {
1845+ "name": "sessions",
1846+ "schema": "",
1847+ "columns": {
1848+ "id": {
1849+ "name": "id",
1850+ "type": "text",
1851+ "primaryKey": true,
1852+ "notNull": true
1853+ },
1854+ "expires_at": {
1855+ "name": "expires_at",
1856+ "type": "timestamp with time zone",
1857+ "primaryKey": false,
1858+ "notNull": true
1859+ },
1860+ "token": {
1861+ "name": "token",
1862+ "type": "text",
1863+ "primaryKey": false,
1864+ "notNull": true
1865+ },
1866+ "created_at": {
1867+ "name": "created_at",
1868+ "type": "timestamp with time zone",
1869+ "primaryKey": false,
1870+ "notNull": true,
1871+ "default": "now()"
1872+ },
1873+ "updated_at": {
1874+ "name": "updated_at",
1875+ "type": "timestamp with time zone",
1876+ "primaryKey": false,
1877+ "notNull": true,
1878+ "default": "now()"
1879+ },
1880+ "ip_address": {
1881+ "name": "ip_address",
1882+ "type": "text",
1883+ "primaryKey": false,
1884+ "notNull": false
1885+ },
1886+ "user_agent": {
1887+ "name": "user_agent",
1888+ "type": "text",
1889+ "primaryKey": false,
1890+ "notNull": false
1891+ },
1892+ "user_id": {
1893+ "name": "user_id",
1894+ "type": "text",
1895+ "primaryKey": false,
1896+ "notNull": true
1897+ }
1898+ },
1899+ "indexes": {
1900+ "sessions_token_uq": {
1901+ "name": "sessions_token_uq",
1902+ "columns": [
1903+ {
1904+ "expression": "token",
1905+ "isExpression": false,
1906+ "asc": true,
1907+ "nulls": "last"
1908+ }
1909+ ],
1910+ "isUnique": true,
1911+ "concurrently": false,
1912+ "method": "btree",
1913+ "with": {}
1914+ },
1915+ "sessions_user_idx": {
1916+ "name": "sessions_user_idx",
1917+ "columns": [
1918+ {
1919+ "expression": "user_id",
1920+ "isExpression": false,
1921+ "asc": true,
1922+ "nulls": "last"
1923+ }
1924+ ],
1925+ "isUnique": false,
1926+ "concurrently": false,
1927+ "method": "btree",
1928+ "with": {}
1929+ }
1930+ },
1931+ "foreignKeys": {
1932+ "sessions_user_id_users_id_fk": {
1933+ "name": "sessions_user_id_users_id_fk",
1934+ "tableFrom": "sessions",
1935+ "tableTo": "users",
1936+ "columnsFrom": [
1937+ "user_id"
1938+ ],
1939+ "columnsTo": [
1940+ "id"
1941+ ],
1942+ "onDelete": "cascade",
1943+ "onUpdate": "no action"
1944+ }
1945+ },
1946+ "compositePrimaryKeys": {},
1947+ "uniqueConstraints": {},
1948+ "policies": {},
1949+ "checkConstraints": {},
1950+ "isRLSEnabled": false
1951+ },
1952+ "public.shared_conversations": {
1953+ "name": "shared_conversations",
1954+ "schema": "",
1955+ "columns": {
1956+ "id": {
1957+ "name": "id",
1958+ "type": "text",
1959+ "primaryKey": true,
1960+ "notNull": true
1961+ },
1962+ "conversation_id": {
1963+ "name": "conversation_id",
1964+ "type": "text",
1965+ "primaryKey": false,
1966+ "notNull": true
1967+ },
1968+ "user_id": {
1969+ "name": "user_id",
1970+ "type": "text",
1971+ "primaryKey": false,
1972+ "notNull": true
1973+ },
1974+ "title": {
1975+ "name": "title",
1976+ "type": "text",
1977+ "primaryKey": false,
1978+ "notNull": true
1979+ },
1980+ "snapshot": {
1981+ "name": "snapshot",
1982+ "type": "jsonb",
1983+ "primaryKey": false,
1984+ "notNull": true
1985+ },
1986+ "is_public": {
1987+ "name": "is_public",
1988+ "type": "boolean",
1989+ "primaryKey": false,
1990+ "notNull": true,
1991+ "default": true
1992+ },
1993+ "view_count": {
1994+ "name": "view_count",
1995+ "type": "integer",
1996+ "primaryKey": false,
1997+ "notNull": true,
1998+ "default": 0
1999+ },
2000+ "created_at": {
2001+ "name": "created_at",
2002+ "type": "timestamp with time zone",
2003+ "primaryKey": false,
2004+ "notNull": true,
2005+ "default": "now()"
2006+ },
2007+ "revoked_at": {
2008+ "name": "revoked_at",
2009+ "type": "timestamp with time zone",
2010+ "primaryKey": false,
2011+ "notNull": false
2012+ }
2013+ },
2014+ "indexes": {
2015+ "shared_conversation_idx": {
2016+ "name": "shared_conversation_idx",
2017+ "columns": [
2018+ {
2019+ "expression": "conversation_id",
2020+ "isExpression": false,
2021+ "asc": true,
2022+ "nulls": "last"
2023+ }
2024+ ],
2025+ "isUnique": false,
2026+ "concurrently": false,
2027+ "method": "btree",
2028+ "with": {}
2029+ }
2030+ },
2031+ "foreignKeys": {
2032+ "shared_conversations_conversation_id_conversations_id_fk": {
2033+ "name": "shared_conversations_conversation_id_conversations_id_fk",
2034+ "tableFrom": "shared_conversations",
2035+ "tableTo": "conversations",
2036+ "columnsFrom": [
2037+ "conversation_id"
2038+ ],
2039+ "columnsTo": [
2040+ "id"
2041+ ],
2042+ "onDelete": "cascade",
2043+ "onUpdate": "no action"
2044+ },
2045+ "shared_conversations_user_id_users_id_fk": {
2046+ "name": "shared_conversations_user_id_users_id_fk",
2047+ "tableFrom": "shared_conversations",
2048+ "tableTo": "users",
2049+ "columnsFrom": [
2050+ "user_id"
2051+ ],
2052+ "columnsTo": [
2053+ "id"
2054+ ],
2055+ "onDelete": "cascade",
2056+ "onUpdate": "no action"
2057+ }
2058+ },
2059+ "compositePrimaryKeys": {},
2060+ "uniqueConstraints": {},
2061+ "policies": {},
2062+ "checkConstraints": {},
2063+ "isRLSEnabled": false
2064+ },
2065+ "public.tags": {
2066+ "name": "tags",
2067+ "schema": "",
2068+ "columns": {
2069+ "id": {
2070+ "name": "id",
2071+ "type": "text",
2072+ "primaryKey": true,
2073+ "notNull": true
2074+ },
2075+ "user_id": {
2076+ "name": "user_id",
2077+ "type": "text",
2078+ "primaryKey": false,
2079+ "notNull": true
2080+ },
2081+ "name": {
2082+ "name": "name",
2083+ "type": "text",
2084+ "primaryKey": false,
2085+ "notNull": true
2086+ },
2087+ "color": {
2088+ "name": "color",
2089+ "type": "text",
2090+ "primaryKey": false,
2091+ "notNull": false
2092+ },
2093+ "created_at": {
2094+ "name": "created_at",
2095+ "type": "timestamp with time zone",
2096+ "primaryKey": false,
2097+ "notNull": true,
2098+ "default": "now()"
2099+ }
2100+ },
2101+ "indexes": {
2102+ "tags_user_name_uq": {
2103+ "name": "tags_user_name_uq",
2104+ "columns": [
2105+ {
2106+ "expression": "user_id",
2107+ "isExpression": false,
2108+ "asc": true,
2109+ "nulls": "last"
2110+ },
2111+ {
2112+ "expression": "name",
2113+ "isExpression": false,
2114+ "asc": true,
2115+ "nulls": "last"
2116+ }
2117+ ],
2118+ "isUnique": true,
2119+ "concurrently": false,
2120+ "method": "btree",
2121+ "with": {}
2122+ }
2123+ },
2124+ "foreignKeys": {
2125+ "tags_user_id_users_id_fk": {
2126+ "name": "tags_user_id_users_id_fk",
2127+ "tableFrom": "tags",
2128+ "tableTo": "users",
2129+ "columnsFrom": [
2130+ "user_id"
2131+ ],
2132+ "columnsTo": [
2133+ "id"
2134+ ],
2135+ "onDelete": "cascade",
2136+ "onUpdate": "no action"
2137+ }
2138+ },
2139+ "compositePrimaryKeys": {},
2140+ "uniqueConstraints": {},
2141+ "policies": {},
2142+ "checkConstraints": {},
2143+ "isRLSEnabled": false
2144+ },
2145+ "public.usage_records": {
2146+ "name": "usage_records",
2147+ "schema": "",
2148+ "columns": {
2149+ "id": {
2150+ "name": "id",
2151+ "type": "text",
2152+ "primaryKey": true,
2153+ "notNull": true
2154+ },
2155+ "user_id": {
2156+ "name": "user_id",
2157+ "type": "text",
2158+ "primaryKey": false,
2159+ "notNull": true
2160+ },
2161+ "conversation_id": {
2162+ "name": "conversation_id",
2163+ "type": "text",
2164+ "primaryKey": false,
2165+ "notNull": false
2166+ },
2167+ "message_id": {
2168+ "name": "message_id",
2169+ "type": "text",
2170+ "primaryKey": false,
2171+ "notNull": false
2172+ },
2173+ "arena_session_id": {
2174+ "name": "arena_session_id",
2175+ "type": "text",
2176+ "primaryKey": false,
2177+ "notNull": false
2178+ },
2179+ "provider": {
2180+ "name": "provider",
2181+ "type": "text",
2182+ "primaryKey": false,
2183+ "notNull": true
2184+ },
2185+ "model_key": {
2186+ "name": "model_key",
2187+ "type": "text",
2188+ "primaryKey": false,
2189+ "notNull": true
2190+ },
2191+ "kind": {
2192+ "name": "kind",
2193+ "type": "text",
2194+ "primaryKey": false,
2195+ "notNull": true,
2196+ "default": "'chat'"
2197+ },
2198+ "status": {
2199+ "name": "status",
2200+ "type": "text",
2201+ "primaryKey": false,
2202+ "notNull": true,
2203+ "default": "'ok'"
2204+ },
2205+ "error_code": {
2206+ "name": "error_code",
2207+ "type": "text",
2208+ "primaryKey": false,
2209+ "notNull": false
2210+ },
2211+ "input_tokens": {
2212+ "name": "input_tokens",
2213+ "type": "integer",
2214+ "primaryKey": false,
2215+ "notNull": true,
2216+ "default": 0
2217+ },
2218+ "output_tokens": {
2219+ "name": "output_tokens",
2220+ "type": "integer",
2221+ "primaryKey": false,
2222+ "notNull": true,
2223+ "default": 0
2224+ },
2225+ "cached_tokens": {
2226+ "name": "cached_tokens",
2227+ "type": "integer",
2228+ "primaryKey": false,
2229+ "notNull": true,
2230+ "default": 0
2231+ },
2232+ "reasoning_tokens": {
2233+ "name": "reasoning_tokens",
2234+ "type": "integer",
2235+ "primaryKey": false,
2236+ "notNull": true,
2237+ "default": 0
2238+ },
2239+ "cost_usd": {
2240+ "name": "cost_usd",
2241+ "type": "double precision",
2242+ "primaryKey": false,
2243+ "notNull": false
2244+ },
2245+ "latency_ms": {
2246+ "name": "latency_ms",
2247+ "type": "integer",
2248+ "primaryKey": false,
2249+ "notNull": false
2250+ },
2251+ "ttft_ms": {
2252+ "name": "ttft_ms",
2253+ "type": "integer",
2254+ "primaryKey": false,
2255+ "notNull": false
2256+ },
2257+ "created_at": {
2258+ "name": "created_at",
2259+ "type": "timestamp with time zone",
2260+ "primaryKey": false,
2261+ "notNull": true,
2262+ "default": "now()"
2263+ }
2264+ },
2265+ "indexes": {
2266+ "usage_user_created_idx": {
2267+ "name": "usage_user_created_idx",
2268+ "columns": [
2269+ {
2270+ "expression": "user_id",
2271+ "isExpression": false,
2272+ "asc": true,
2273+ "nulls": "last"
2274+ },
2275+ {
2276+ "expression": "created_at",
2277+ "isExpression": false,
2278+ "asc": true,
2279+ "nulls": "last"
2280+ }
2281+ ],
2282+ "isUnique": false,
2283+ "concurrently": false,
2284+ "method": "btree",
2285+ "with": {}
2286+ },
2287+ "usage_user_provider_idx": {
2288+ "name": "usage_user_provider_idx",
2289+ "columns": [
2290+ {
2291+ "expression": "user_id",
2292+ "isExpression": false,
2293+ "asc": true,
2294+ "nulls": "last"
2295+ },
2296+ {
2297+ "expression": "provider",
2298+ "isExpression": false,
2299+ "asc": true,
2300+ "nulls": "last"
2301+ }
2302+ ],
2303+ "isUnique": false,
2304+ "concurrently": false,
2305+ "method": "btree",
2306+ "with": {}
2307+ },
2308+ "usage_user_model_idx": {
2309+ "name": "usage_user_model_idx",
2310+ "columns": [
2311+ {
2312+ "expression": "user_id",
2313+ "isExpression": false,
2314+ "asc": true,
2315+ "nulls": "last"
2316+ },
2317+ {
2318+ "expression": "model_key",
2319+ "isExpression": false,
2320+ "asc": true,
2321+ "nulls": "last"
2322+ }
2323+ ],
2324+ "isUnique": false,
2325+ "concurrently": false,
2326+ "method": "btree",
2327+ "with": {}
2328+ }
2329+ },
2330+ "foreignKeys": {
2331+ "usage_records_user_id_users_id_fk": {
2332+ "name": "usage_records_user_id_users_id_fk",
2333+ "tableFrom": "usage_records",
2334+ "tableTo": "users",
2335+ "columnsFrom": [
2336+ "user_id"
2337+ ],
2338+ "columnsTo": [
2339+ "id"
2340+ ],
2341+ "onDelete": "cascade",
2342+ "onUpdate": "no action"
2343+ }
2344+ },
2345+ "compositePrimaryKeys": {},
2346+ "uniqueConstraints": {},
2347+ "policies": {},
2348+ "checkConstraints": {},
2349+ "isRLSEnabled": false
2350+ },
2351+ "public.user_model_favorites": {
2352+ "name": "user_model_favorites",
2353+ "schema": "",
2354+ "columns": {
2355+ "user_id": {
2356+ "name": "user_id",
2357+ "type": "text",
2358+ "primaryKey": false,
2359+ "notNull": true
2360+ },
2361+ "model_key": {
2362+ "name": "model_key",
2363+ "type": "text",
2364+ "primaryKey": false,
2365+ "notNull": true
2366+ },
2367+ "created_at": {
2368+ "name": "created_at",
2369+ "type": "timestamp with time zone",
2370+ "primaryKey": false,
2371+ "notNull": true,
2372+ "default": "now()"
2373+ }
2374+ },
2375+ "indexes": {},
2376+ "foreignKeys": {
2377+ "user_model_favorites_user_id_users_id_fk": {
2378+ "name": "user_model_favorites_user_id_users_id_fk",
2379+ "tableFrom": "user_model_favorites",
2380+ "tableTo": "users",
2381+ "columnsFrom": [
2382+ "user_id"
2383+ ],
2384+ "columnsTo": [
2385+ "id"
2386+ ],
2387+ "onDelete": "cascade",
2388+ "onUpdate": "no action"
2389+ }
2390+ },
2391+ "compositePrimaryKeys": {
2392+ "user_model_favorites_user_id_model_key_pk": {
2393+ "name": "user_model_favorites_user_id_model_key_pk",
2394+ "columns": [
2395+ "user_id",
2396+ "model_key"
2397+ ]
2398+ }
2399+ },
2400+ "uniqueConstraints": {},
2401+ "policies": {},
2402+ "checkConstraints": {},
2403+ "isRLSEnabled": false
2404+ },
2405+ "public.user_model_recents": {
2406+ "name": "user_model_recents",
2407+ "schema": "",
2408+ "columns": {
2409+ "user_id": {
2410+ "name": "user_id",
2411+ "type": "text",
2412+ "primaryKey": false,
2413+ "notNull": true
2414+ },
2415+ "model_key": {
2416+ "name": "model_key",
2417+ "type": "text",
2418+ "primaryKey": false,
2419+ "notNull": true
2420+ },
2421+ "used_at": {
2422+ "name": "used_at",
2423+ "type": "timestamp with time zone",
2424+ "primaryKey": false,
2425+ "notNull": true,
2426+ "default": "now()"
2427+ },
2428+ "uses": {
2429+ "name": "uses",
2430+ "type": "integer",
2431+ "primaryKey": false,
2432+ "notNull": true,
2433+ "default": 1
2434+ }
2435+ },
2436+ "indexes": {},
2437+ "foreignKeys": {
2438+ "user_model_recents_user_id_users_id_fk": {
2439+ "name": "user_model_recents_user_id_users_id_fk",
2440+ "tableFrom": "user_model_recents",
2441+ "tableTo": "users",
2442+ "columnsFrom": [
2443+ "user_id"
2444+ ],
2445+ "columnsTo": [
2446+ "id"
2447+ ],
2448+ "onDelete": "cascade",
2449+ "onUpdate": "no action"
2450+ }
2451+ },
2452+ "compositePrimaryKeys": {
2453+ "user_model_recents_user_id_model_key_pk": {
2454+ "name": "user_model_recents_user_id_model_key_pk",
2455+ "columns": [
2456+ "user_id",
2457+ "model_key"
2458+ ]
2459+ }
2460+ },
2461+ "uniqueConstraints": {},
2462+ "policies": {},
2463+ "checkConstraints": {},
2464+ "isRLSEnabled": false
2465+ },
2466+ "public.user_preferences": {
2467+ "name": "user_preferences",
2468+ "schema": "",
2469+ "columns": {
2470+ "user_id": {
2471+ "name": "user_id",
2472+ "type": "text",
2473+ "primaryKey": true,
2474+ "notNull": true
2475+ },
2476+ "theme": {
2477+ "name": "theme",
2478+ "type": "text",
2479+ "primaryKey": false,
2480+ "notNull": true,
2481+ "default": "'system'"
2482+ },
2483+ "language": {
2484+ "name": "language",
2485+ "type": "text",
2486+ "primaryKey": false,
2487+ "notNull": true,
2488+ "default": "'en'"
2489+ },
2490+ "default_model_key": {
2491+ "name": "default_model_key",
2492+ "type": "text",
2493+ "primaryKey": false,
2494+ "notNull": false
2495+ },
2496+ "default_system_prompt": {
2497+ "name": "default_system_prompt",
2498+ "type": "text",
2499+ "primaryKey": false,
2500+ "notNull": false
2501+ },
2502+ "enter_to_send": {
2503+ "name": "enter_to_send",
2504+ "type": "boolean",
2505+ "primaryKey": false,
2506+ "notNull": true,
2507+ "default": true
2508+ },
2509+ "streaming": {
2510+ "name": "streaming",
2511+ "type": "boolean",
2512+ "primaryKey": false,
2513+ "notNull": true,
2514+ "default": true
2515+ },
2516+ "code_wrap": {
2517+ "name": "code_wrap",
2518+ "type": "boolean",
2519+ "primaryKey": false,
2520+ "notNull": true,
2521+ "default": false
2522+ },
2523+ "show_reasoning": {
2524+ "name": "show_reasoning",
2525+ "type": "boolean",
2526+ "primaryKey": false,
2527+ "notNull": true,
2528+ "default": true
2529+ },
2530+ "show_costs": {
2531+ "name": "show_costs",
2532+ "type": "boolean",
2533+ "primaryKey": false,
2534+ "notNull": true,
2535+ "default": true
2536+ },
2537+ "auto_title": {
2538+ "name": "auto_title",
2539+ "type": "boolean",
2540+ "primaryKey": false,
2541+ "notNull": true,
2542+ "default": true
2543+ },
2544+ "extra": {
2545+ "name": "extra",
2546+ "type": "jsonb",
2547+ "primaryKey": false,
2548+ "notNull": true,
2549+ "default": "'{}'::jsonb"
2550+ },
2551+ "updated_at": {
2552+ "name": "updated_at",
2553+ "type": "timestamp with time zone",
2554+ "primaryKey": false,
2555+ "notNull": true,
2556+ "default": "now()"
2557+ }
2558+ },
2559+ "indexes": {},
2560+ "foreignKeys": {
2561+ "user_preferences_user_id_users_id_fk": {
2562+ "name": "user_preferences_user_id_users_id_fk",
2563+ "tableFrom": "user_preferences",
2564+ "tableTo": "users",
2565+ "columnsFrom": [
2566+ "user_id"
2567+ ],
2568+ "columnsTo": [
2569+ "id"
2570+ ],
2571+ "onDelete": "cascade",
2572+ "onUpdate": "no action"
2573+ }
2574+ },
2575+ "compositePrimaryKeys": {},
2576+ "uniqueConstraints": {},
2577+ "policies": {},
2578+ "checkConstraints": {},
2579+ "isRLSEnabled": false
2580+ },
2581+ "public.users": {
2582+ "name": "users",
2583+ "schema": "",
2584+ "columns": {
2585+ "id": {
2586+ "name": "id",
2587+ "type": "text",
2588+ "primaryKey": true,
2589+ "notNull": true
2590+ },
2591+ "name": {
2592+ "name": "name",
2593+ "type": "text",
2594+ "primaryKey": false,
2595+ "notNull": true,
2596+ "default": "''"
2597+ },
2598+ "email": {
2599+ "name": "email",
2600+ "type": "text",
2601+ "primaryKey": false,
2602+ "notNull": true
2603+ },
2604+ "email_verified": {
2605+ "name": "email_verified",
2606+ "type": "boolean",
2607+ "primaryKey": false,
2608+ "notNull": true,
2609+ "default": false
2610+ },
2611+ "image": {
2612+ "name": "image",
2613+ "type": "text",
2614+ "primaryKey": false,
2615+ "notNull": false
2616+ },
2617+ "role": {
2618+ "name": "role",
2619+ "type": "text",
2620+ "primaryKey": false,
2621+ "notNull": true,
2622+ "default": "'user'"
2623+ },
2624+ "onboarding_completed_at": {
2625+ "name": "onboarding_completed_at",
2626+ "type": "timestamp with time zone",
2627+ "primaryKey": false,
2628+ "notNull": false
2629+ },
2630+ "created_at": {
2631+ "name": "created_at",
2632+ "type": "timestamp with time zone",
2633+ "primaryKey": false,
2634+ "notNull": true,
2635+ "default": "now()"
2636+ },
2637+ "updated_at": {
2638+ "name": "updated_at",
2639+ "type": "timestamp with time zone",
2640+ "primaryKey": false,
2641+ "notNull": true,
2642+ "default": "now()"
2643+ }
2644+ },
2645+ "indexes": {
2646+ "users_email_uq": {
2647+ "name": "users_email_uq",
2648+ "columns": [
2649+ {
2650+ "expression": "email",
2651+ "isExpression": false,
2652+ "asc": true,
2653+ "nulls": "last"
2654+ }
2655+ ],
2656+ "isUnique": true,
2657+ "concurrently": false,
2658+ "method": "btree",
2659+ "with": {}
2660+ }
2661+ },
2662+ "foreignKeys": {},
2663+ "compositePrimaryKeys": {},
2664+ "uniqueConstraints": {},
2665+ "policies": {},
2666+ "checkConstraints": {},
2667+ "isRLSEnabled": false
2668+ },
2669+ "public.verifications": {
2670+ "name": "verifications",
2671+ "schema": "",
2672+ "columns": {
2673+ "id": {
2674+ "name": "id",
2675+ "type": "text",
2676+ "primaryKey": true,
2677+ "notNull": true
2678+ },
2679+ "identifier": {
2680+ "name": "identifier",
2681+ "type": "text",
2682+ "primaryKey": false,
2683+ "notNull": true
2684+ },
2685+ "value": {
2686+ "name": "value",
2687+ "type": "text",
2688+ "primaryKey": false,
2689+ "notNull": true
2690+ },
2691+ "expires_at": {
2692+ "name": "expires_at",
2693+ "type": "timestamp with time zone",
2694+ "primaryKey": false,
2695+ "notNull": true
2696+ },
2697+ "created_at": {
2698+ "name": "created_at",
2699+ "type": "timestamp with time zone",
2700+ "primaryKey": false,
2701+ "notNull": true,
2702+ "default": "now()"
2703+ },
2704+ "updated_at": {
2705+ "name": "updated_at",
2706+ "type": "timestamp with time zone",
2707+ "primaryKey": false,
2708+ "notNull": true,
2709+ "default": "now()"
2710+ }
2711+ },
2712+ "indexes": {
2713+ "verifications_identifier_idx": {
2714+ "name": "verifications_identifier_idx",
2715+ "columns": [
2716+ {
2717+ "expression": "identifier",
2718+ "isExpression": false,
2719+ "asc": true,
2720+ "nulls": "last"
2721+ }
2722+ ],
2723+ "isUnique": false,
2724+ "concurrently": false,
2725+ "method": "btree",
2726+ "with": {}
2727+ }
2728+ },
2729+ "foreignKeys": {},
2730+ "compositePrimaryKeys": {},
2731+ "uniqueConstraints": {},
2732+ "policies": {},
2733+ "checkConstraints": {},
2734+ "isRLSEnabled": false
2735+ }
2736+ },
2737+ "enums": {},
2738+ "schemas": {},
2739+ "sequences": {},
2740+ "roles": {},
2741+ "policies": {},
2742+ "views": {},
2743+ "_meta": {
2744+ "columns": {},
2745+ "schemas": {},
2746+ "tables": {}
2747+ }
2748+}
\ No newline at end of file
added drizzle/meta/_journal.json +13 −0
@@ -0,0 +1,13 @@
1+{
2+ "version": "7",
3+ "dialect": "postgresql",
4+ "entries": [
5+ {
6+ "idx": 0,
7+ "version": "7",
8+ "when": 1788844960714,
9+ "tag": "0000_foamy_loners",
10+ "breakpoints": true
11+ }
12+ ]
13+}
\ No newline at end of file
added e2e/full-flow.spec.ts +156 −0
@@ -0,0 +1,156 @@
1+import { test, expect } from "@playwright/test";
2+import { TEST_EMAIL, TEST_PASSWORD, lastLinkFromLog, login, noConsoleErrors, readEnv, sql } from "./helpers";
3+
4+/**
5+ * Full workflow against the dev server (EMAIL_DRY_RUN=1 EMAIL_DRY_RUN_PRINT=1 so links land in the log):
6+ * sign up → verify email → login → add provider key → validate → select model → send → stream → new chat →
7+ * reload → persistence → change password → logout → login again.
8+ */
9+test.describe.serial("PolyLLM full flow", () => {
10+ const email = TEST_EMAIL;
11+ const password = TEST_PASSWORD;
12+ let conversationUrl = "";
13+
14+ test("landing renders without console errors", async ({ page }) => {
15+ const errors = await noConsoleErrors(page);
16+ await page.goto("/");
17+ await expect(page.getByRole("heading", { level: 1 })).toContainText(/every model/i);
18+ await expect(page.getByRole("link", { name: /start using polyllm/i }).first()).toBeVisible();
19+ expect(errors).toEqual([]);
20+ });
21+
22+ test("sign up sends a verification email", async ({ page }) => {
23+ await page.goto("/signup");
24+ await page.getByLabel(/name/i).fill("E2E Tester");
25+ await page.getByLabel(/email/i).fill(email);
26+ await page.getByLabel(/^password$/i).fill(password);
27+ const confirm = page.getByLabel(/confirm/i);
28+ if (await confirm.count()) await confirm.fill(password);
29+ await page.getByRole("button", { name: /create account|sign up/i }).click();
30+ await expect(page.getByText(/check your inbox|verify/i).first()).toBeVisible({ timeout: 30_000 });
31+ // the account exists but is unverified
32+ await expect.poll(() => sql(`select email_verified from users where email='${email}'`)).toBe("f");
33+ });
34+
35+ test("login before verification is refused", async ({ page }) => {
36+ await page.goto("/login");
37+ await page.getByLabel(/email/i).fill(email);
38+ await page.getByLabel(/^password$/i).fill(password);
39+ await page.getByRole("button", { name: /sign in/i }).click();
40+ await expect(page.getByText(/verify|not verified|check your inbox/i).first()).toBeVisible({ timeout: 20_000 });
41+ });
42+
43+ test("verification link activates the account and signs in", async ({ page }) => {
44+ const link = lastLinkFromLog(/http:\/\/localhost:3000\/api\/auth\/verify-email\?token=[^\s"'<>]+/g);
45+ expect(link, "verification link should be printed in the dev log").toBeTruthy();
46+ await page.goto(link!);
47+ await page.waitForURL(/\/app|\/verify-email/, { timeout: 30_000 });
48+ await expect.poll(() => sql(`select email_verified from users where email='${email}'`)).toBe("t");
49+ if (!/\/app/.test(page.url())) await login(page, email, password);
50+ await expect(page).toHaveURL(/\/app\/chat/);
51+ });
52+
53+ test("add + validate provider keys (real providers)", async ({ page }) => {
54+ await login(page, email, password);
55+ await page.goto("/app/settings/providers");
56+ const names: Record<string, RegExp> = { anthropic: /^Anthropic$/, openai: /^OpenAI$/, xai: /^xAI$/, gemini: /^Google Gemini$/ };
57+ for (const [provider, envName] of [
58+ ["anthropic", "ANTHROPIC_API_KEY"],
59+ ["openai", "OPENAI_API_KEY"],
60+ ["xai", "XAI_API_KEY"],
61+ ["gemini", "GOOGLE_GEMINI_API_KEY"],
62+ ] as const) {
63+ const key = readEnv(envName);
64+ test.skip(!key, `${envName} missing`);
65+ const item = page.locator("li", { has: page.getByRole("heading", { level: 3, name: names[provider] }) }).first();
66+ await item.getByRole("button", { name: /add key|replace key/i }).click();
67+ await page.locator("#provider-api-key").fill(key!);
68+ await page.getByRole("button", { name: /^connect$|^replace key$/i }).last().click();
69+ await expect(item).toContainText(/connected/i, { timeout: 60_000 });
70+ await expect(page.locator("#provider-api-key")).toHaveCount(0);
71+ }
72+ // never in the DOM
73+ const html = await page.content();
74+ expect(html).not.toContain(readEnv("ANTHROPIC_API_KEY")!.slice(10, 30));
75+ await expect.poll(() => sql(`select count(*) from provider_connections pc join users u on u.id=pc.user_id where u.email='${email}' and pc.status='valid'`)).toBe("4");
76+ // keys are encrypted at rest
77+ const stored = sql(`select encrypted_key from provider_connections pc join users u on u.id=pc.user_id where u.email='${email}' and provider='anthropic'`);
78+ expect(stored.startsWith("v1.")).toBe(true);
79+ expect(stored).not.toContain("sk-ant");
80+ });
81+
82+ test("select a model, send a message and receive a real stream", async ({ page }) => {
83+ await login(page, email, password);
84+ await page.goto("/app/chat");
85+ await page.getByRole("button", { name: /select model/i }).click();
86+ await page.getByLabel(/search models/i).fill("haiku 4.5");
87+ await page.getByRole("option").first().click();
88+ await expect(page.getByRole("button", { name: /select model/i })).toContainText(/haiku/i);
89+ await page.getByLabel(/^message$/i).fill("Reply with exactly the word PONG and nothing else.");
90+ await page.getByRole("button", { name: /^send$/i }).click();
91+ await expect(page.getByText(/PONG/).first()).toBeVisible({ timeout: 60_000 });
92+ await page.waitForURL(/\/app\/chat\/cnv_/, { timeout: 30_000 });
93+ conversationUrl = page.url();
94+ // footer meta appears (tokens + latency)
95+ await expect(page.getByText(/tok\/s|\bin ·/).first()).toBeVisible({ timeout: 30_000 });
96+ // sidebar shows the conversation with an auto title
97+ await expect(page.locator("aside").getByText(/reply with exactly/i).first()).toBeVisible();
98+ });
99+
100+ test("conversation persists after reload and a second model works", async ({ page }) => {
101+ await login(page, email, password);
102+ await page.goto(conversationUrl);
103+ await expect(page.getByText(/PONG/).first()).toBeVisible();
104+ // switch to an OpenAI model in the same conversation and continue
105+ await page.getByRole("button", { name: /select model/i }).click();
106+ await page.getByLabel(/search models/i).fill("gpt-5.4-nano");
107+ await page.getByRole("option").first().click();
108+ await page.getByLabel(/^message$/i).fill("Now reply with exactly the word PING.");
109+ await page.getByRole("button", { name: /^send$/i }).click();
110+ await expect(page.getByText(/PING/).first()).toBeVisible({ timeout: 60_000 });
111+ await page.reload();
112+ await expect(page.getByText(/PONG/).first()).toBeVisible();
113+ await expect(page.getByText(/PING/).first()).toBeVisible();
114+ });
115+
116+ test("model configuration is capability-driven", async ({ page }) => {
117+ await login(page, email, password);
118+ await page.goto("/app/chat");
119+ await page.getByRole("button", { name: /select model/i }).click();
120+ await page.getByLabel(/search models/i).fill("gpt-5.5");
121+ await page.getByRole("option").first().click();
122+ await page.getByRole("button", { name: /model configuration/i }).click();
123+ await expect(page.getByText(/reasoning/i).first()).toBeVisible();
124+ await expect(page.getByText(/^Effort$/)).toBeVisible();
125+ // seed/stop are not supported by the Responses API → never shown
126+ await expect(page.getByText(/^Seed$/)).toHaveCount(0);
127+ await expect(page.getByText(/stop sequences/i)).toHaveCount(0);
128+ await page.keyboard.press("Escape");
129+ });
130+
131+ test("usage dashboard shows the requests", async ({ page }) => {
132+ await login(page, email, password);
133+ await page.goto("/app/usage");
134+ await expect(page.getByText(/requests/i).first()).toBeVisible();
135+ await expect.poll(() => Number(sql(`select count(*) from usage_records ur join users u on u.id=ur.user_id where u.email='${email}'`))).toBeGreaterThanOrEqual(2);
136+ });
137+
138+ test("change password, logout, login again", async ({ page }) => {
139+ await login(page, email, password);
140+ await page.goto("/app/settings/security");
141+ const newPassword = `${password}-2`;
142+ await page.getByLabel(/current password/i).fill(password);
143+ await page.getByLabel(/^new password$/i).fill(newPassword);
144+ const confirm = page.getByLabel(/confirm/i);
145+ if (await confirm.count()) await confirm.fill(newPassword);
146+ await page.getByRole("button", { name: /change password|update password/i }).click();
147+ await expect(page.getByText(/password (changed|updated)/i).first()).toBeVisible({ timeout: 20_000 });
148+ // sign out via the sidebar menu
149+ await page.goto("/app/chat");
150+ await page.getByText(email).first().click();
151+ await page.getByRole("menuitem", { name: /sign out/i }).click();
152+ await page.waitForURL(/\/login/);
153+ await login(page, email, newPassword);
154+ await expect(page).toHaveURL(/\/app/);
155+ });
156+});
added e2e/helpers.ts +44 −0
@@ -0,0 +1,44 @@
1+import { execSync } from "node:child_process";
2+import fs from "node:fs";
3+import type { Page } from "@playwright/test";
4+
5+export const DB = process.env.E2E_DATABASE_URL ?? "postgres://localhost:5432/polyllm";
6+export const DEV_LOG = process.env.E2E_DEV_LOG ?? "/tmp/polyllm-dev.log";
7+
8+export function sql(q: string): string {
9+ return execSync(`psql "${DB}" -Atc ${JSON.stringify(q)}`, { encoding: "utf8" }).trim();
10+}
11+
12+/** Finds the latest verification / reset URL for an email in the dev log (EMAIL_DRY_RUN_PRINT=1). */
13+export function lastLinkFromLog(pattern: RegExp): string | null {
14+ const log = fs.readFileSync(DEV_LOG, "utf8");
15+ const matches = [...log.matchAll(pattern)];
16+ return matches.length ? matches[matches.length - 1][0] : null;
17+}
18+
19+export function readEnv(name: string): string | undefined {
20+ if (process.env[name]) return process.env[name];
21+ const env = fs.existsSync(".env") ? fs.readFileSync(".env", "utf8") : "";
22+ const m = env.match(new RegExp(`^${name}=(.*)$`, "m"));
23+ return m ? m[1].replace(/^"|"$/g, "") : undefined;
24+}
25+
26+export const TEST_EMAIL = process.env.E2E_EMAIL ?? `e2e+${Date.now()}@polyllm.test`;
27+export const TEST_PASSWORD = "Str0ng-Passw0rd-e2e!";
28+
29+export async function login(page: Page, email: string, password: string) {
30+ await page.goto("/login");
31+ await page.getByLabel(/email/i).fill(email);
32+ await page.getByLabel(/^password$/i).fill(password);
33+ await page.getByRole("button", { name: /sign in/i }).click();
34+ await page.waitForURL(/\/app/);
35+}
36+
37+export async function noConsoleErrors(page: Page) {
38+ const errors: string[] = [];
39+ page.on("console", (msg) => {
40+ if (msg.type() === "error" && !/favicon|hydration|Download the React DevTools/i.test(msg.text())) errors.push(msg.text());
41+ });
42+ page.on("pageerror", (e) => errors.push(e.message));
43+ return errors;
44+}
added e2e/mobile.spec.ts +12 −0
@@ -0,0 +1,12 @@
1+import { test, expect } from "@playwright/test";
2+import { noConsoleErrors } from "./helpers";
3+
4+test("landing and auth pages have no horizontal overflow on mobile", async ({ page }) => {
5+ const errors = await noConsoleErrors(page);
6+ for (const path of ["/", "/login", "/signup", "/forgot-password"]) {
7+ await page.goto(path);
8+ const overflow = await page.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth);
9+ expect(overflow, `${path} overflows horizontally by ${overflow}px`).toBeLessThanOrEqual(1);
10+ }
11+ expect(errors).toEqual([]);
12+});
added eslint.config.mjs +10 −0
@@ -0,0 +1,10 @@
1+import nextVitals from "eslint-config-next/core-web-vitals";
2+import nextTs from "eslint-config-next/typescript";
3+
4+const eslintConfig = [
5+ ...nextVitals,
6+ ...nextTs,
7+ { ignores: [".next/**", "node_modules/**", "research/**", "drizzle/**", "playwright-report/**", "test-results/**"] },
8+];
9+
10+export default eslintConfig;
added next.config.ts +51 −0
@@ -0,0 +1,51 @@
1+import type { NextConfig } from "next";
2+
3+const isProd = process.env.NODE_ENV === "production";
4+
5+/**
6+ * Content-Security-Policy. Inline styles are required by Tailwind's runtime-free
7+ * output only for a few third-party components (Radix measures via style attrs),
8+ * and Next.js injects inline scripts for hydration; nonces are not used because the
9+ * app is fully static-shell + client-fetch and `next start` runs behind ngrok.
10+ */
11+const csp = [
12+ "default-src 'self'",
13+ "base-uri 'self'",
14+ "frame-ancestors 'none'",
15+ "form-action 'self'",
16+ "object-src 'none'",
17+ "img-src 'self' data: blob: https:",
18+ "font-src 'self' data:",
19+ "style-src 'self' 'unsafe-inline'",
20+ isProd ? "script-src 'self' 'unsafe-inline'" : "script-src 'self' 'unsafe-inline' 'unsafe-eval'",
21+ "connect-src 'self'",
22+ "worker-src 'self' blob:",
23+ "upgrade-insecure-requests",
24+].join("; ");
25+
26+const nextConfig: NextConfig = {
27+ reactStrictMode: true,
28+ poweredByHeader: false,
29+ agentRules: false,
30+ serverExternalPackages: ["pg", "argon2", "resend", "@anthropic-ai/sdk", "openai", "@google/genai", "shiki"],
31+ experimental: {
32+ serverActions: { bodySizeLimit: "2mb" },
33+ },
34+ async headers() {
35+ return [
36+ {
37+ source: "/(.*)",
38+ headers: [
39+ { key: "X-Content-Type-Options", value: "nosniff" },
40+ { key: "X-Frame-Options", value: "DENY" },
41+ { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
42+ { key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=(), payment=()" },
43+ { key: "Content-Security-Policy", value: csp },
44+ ...(isProd ? [{ key: "Strict-Transport-Security", value: "max-age=31536000; includeSubDomains" }] : []),
45+ ],
46+ },
47+ ];
48+ },
49+};
50+
51+export default nextConfig;
added package.json +80 −0
@@ -0,0 +1,80 @@
1+{
2+ "name": "polyllm",
3+ "version": "0.1.0",
4+ "private": true,
5+ "description": "PolyLLM — One interface. Every model. Bring your own keys.",
6+ "type": "module",
7+ "packageManager": "pnpm@11.1.2",
8+ "engines": {
9+ "node": ">=22"
10+ },
11+ "scripts": {
12+ "dev": "next dev -p ${PORT:-3000}",
13+ "build": "next build",
14+ "start": "next start -p ${PORT:-3000} -H 0.0.0.0",
15+ "lint": "eslint",
16+ "typecheck": "tsc -p tsconfig.json --noEmit",
17+ "test": "vitest run",
18+ "test:e2e": "playwright test",
19+ "db:generate": "drizzle-kit generate",
20+ "db:migrate": "tsx src/db/migrate.ts",
21+ "db:studio": "drizzle-kit studio",
22+ "models:sync": "tsx --tsconfig tsconfig.json --import ./scripts/hooks.mjs scripts/sync-models.ts",
23+ "providers:matrix": "tsx --tsconfig tsconfig.json --import ./scripts/hooks.mjs scripts/provider-matrix.ts"
24+ },
25+ "dependencies": {
26+ "@anthropic-ai/sdk": "^0.124.0",
27+ "@google/genai": "^2.21.0",
28+ "@radix-ui/react-dialog": "^1.1.14",
29+ "@radix-ui/react-dropdown-menu": "^2.1.15",
30+ "@radix-ui/react-popover": "^1.1.14",
31+ "@radix-ui/react-scroll-area": "^1.2.9",
32+ "@radix-ui/react-select": "^2.2.5",
33+ "@radix-ui/react-slider": "^1.3.5",
34+ "@radix-ui/react-slot": "^1.2.3",
35+ "@radix-ui/react-switch": "^1.2.5",
36+ "@radix-ui/react-tabs": "^1.1.12",
37+ "@radix-ui/react-tooltip": "^1.2.7",
38+ "@tanstack/react-virtual": "^3.13.0",
39+ "argon2": "^0.45.0",
40+ "better-auth": "^1.7.3",
41+ "class-variance-authority": "^0.7.1",
42+ "clsx": "^2.1.1",
43+ "cmdk": "^1.1.1",
44+ "drizzle-orm": "^0.45.2",
45+ "geist": "^1.5.0",
46+ "lucide-react": "^1.42.0",
47+ "motion": "^12.23.0",
48+ "next": "16.3.4",
49+ "next-themes": "^0.4.6",
50+ "openai": "^7.10.0",
51+ "pg": "^8.23.0",
52+ "react": "19.2.8",
53+ "react-dom": "19.2.8",
54+ "react-markdown": "^10.1.0",
55+ "recharts": "^3.0.0",
56+ "rehype-raw": "^7.0.0",
57+ "remark-gfm": "^4.0.1",
58+ "resend": "^6.26.0",
59+ "server-only": "^0.0.1",
60+ "shiki": "^4.4.3",
61+ "swr": "^2.5.1",
62+ "tailwind-merge": "^3.3.1",
63+ "zod": "^4.5.4"
64+ },
65+ "devDependencies": {
66+ "@playwright/test": "^1.63.0",
67+ "@tailwindcss/postcss": "^4.3.3",
68+ "@types/node": "^24.0.0",
69+ "@types/pg": "^8.15.0",
70+ "@types/react": "^19",
71+ "@types/react-dom": "^19",
72+ "drizzle-kit": "^0.31.10",
73+ "eslint": "^9",
74+ "eslint-config-next": "16.3.4",
75+ "tailwindcss": "^4.3.3",
76+ "tsx": "^4.20.0",
77+ "typescript": "^5.9.3",
78+ "vitest": "^3.2.0"
79+ }
80+}
added playwright.config.ts +18 −0
@@ -0,0 +1,18 @@
1+import { defineConfig, devices } from "@playwright/test";
2+
3+const baseURL = process.env.E2E_BASE_URL ?? "http://localhost:3000";
4+
5+export default defineConfig({
6+ testDir: "./e2e",
7+ timeout: 180_000,
8+ expect: { timeout: 20_000 },
9+ fullyParallel: false,
10+ workers: 1,
11+ retries: 0,
12+ reporter: [["list"], ["html", { open: "never", outputFolder: "playwright-report" }]],
13+ use: { baseURL, trace: "retain-on-failure", screenshot: "only-on-failure", video: "off" },
14+ projects: [
15+ { name: "desktop", use: { ...devices["Desktop Chrome"], viewport: { width: 1360, height: 860 } } },
16+ { name: "mobile", use: { ...devices["iPhone 14"], browserName: "chromium" }, testMatch: /mobile\.spec\.ts/ },
17+ ],
18+});
added pnpm-lock.yaml +9267 −0
@@ -0,0 +1,9267 @@
1+lockfileVersion: '9.0'
2+
3+settings:
4+ autoInstallPeers: true
5+ excludeLinksFromLockfile: false
6+
7+importers:
8+
9+ .:
10+ dependencies:
11+ '@anthropic-ai/sdk':
12+ specifier: ^0.124.0
13+ version: 0.124.0(zod@4.5.4)
14+ '@google/genai':
15+ specifier: ^2.21.0
16+ version: 2.21.0
17+ '@radix-ui/react-dialog':
18+ specifier: ^1.1.14
19+ version: 1.1.23(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
20+ '@radix-ui/react-dropdown-menu':
21+ specifier: ^2.1.15
22+ version: 2.1.24(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
23+ '@radix-ui/react-popover':
24+ specifier: ^1.1.14
25+ version: 1.1.23(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
26+ '@radix-ui/react-scroll-area':
27+ specifier: ^1.2.9
28+ version: 1.2.18(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
29+ '@radix-ui/react-select':
30+ specifier: ^2.2.5
31+ version: 2.3.7(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
32+ '@radix-ui/react-slider':
33+ specifier: ^1.3.5
34+ version: 1.4.7(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
35+ '@radix-ui/react-slot':
36+ specifier: ^1.2.3
37+ version: 1.3.3(@types/react@19.2.18)(react@19.2.8)
38+ '@radix-ui/react-switch':
39+ specifier: ^1.2.5
40+ version: 1.3.7(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
41+ '@radix-ui/react-tabs':
42+ specifier: ^1.1.12
43+ version: 1.1.21(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
44+ '@radix-ui/react-tooltip':
45+ specifier: ^1.2.7
46+ version: 1.2.16(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
47+ '@tanstack/react-virtual':
48+ specifier: ^3.13.0
49+ version: 3.14.10(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
50+ argon2:
51+ specifier: ^0.45.0
52+ version: 0.45.1
53+ better-auth:
54+ specifier: ^1.7.3
55+ version: 1.7.3(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@types/pg@8.23.1)(kysely@0.29.5)(pg@8.23.0))(next@16.3.4(@babel/core@7.29.7)(@playwright/test@1.63.0)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@3.2.7(@types/debug@4.1.13)(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13))
56+ class-variance-authority:
57+ specifier: ^0.7.1
58+ version: 0.7.1
59+ clsx:
60+ specifier: ^2.1.1
61+ version: 2.1.1
62+ cmdk:
63+ specifier: ^1.1.1
64+ version: 1.1.1(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
65+ drizzle-orm:
66+ specifier: ^0.45.2
67+ version: 0.45.2(@types/pg@8.23.1)(kysely@0.29.5)(pg@8.23.0)
68+ geist:
69+ specifier: ^1.5.0
70+ version: 1.7.2(next@16.3.4(@babel/core@7.29.7)(@playwright/test@1.63.0)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))
71+ lucide-react:
72+ specifier: ^1.42.0
73+ version: 1.42.0(react@19.2.8)
74+ motion:
75+ specifier: ^12.23.0
76+ version: 12.43.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
77+ next:
78+ specifier: 16.3.4
79+ version: 16.3.4(@babel/core@7.29.7)(@playwright/test@1.63.0)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
80+ next-themes:
81+ specifier: ^0.4.6
82+ version: 0.4.6(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
83+ openai:
84+ specifier: ^7.10.0
85+ version: 7.10.0(ws@8.21.3)(zod@4.5.4)
86+ pg:
87+ specifier: ^8.23.0
88+ version: 8.23.0
89+ react:
90+ specifier: 19.2.8
91+ version: 19.2.8
92+ react-dom:
93+ specifier: 19.2.8
94+ version: 19.2.8(react@19.2.8)
95+ react-markdown:
96+ specifier: ^10.1.0
97+ version: 10.1.0(@types/react@19.2.18)(react@19.2.8)
98+ recharts:
99+ specifier: ^3.0.0
100+ version: 3.10.1(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react-is@16.13.1)(react@19.2.8)(redux@5.0.1)
101+ rehype-raw:
102+ specifier: ^7.0.0
103+ version: 7.0.0
104+ remark-gfm:
105+ specifier: ^4.0.1
106+ version: 4.0.1
107+ resend:
108+ specifier: ^6.26.0
109+ version: 6.26.0
110+ server-only:
111+ specifier: ^0.0.1
112+ version: 0.0.1
113+ shiki:
114+ specifier: ^4.4.3
115+ version: 4.4.3
116+ swr:
117+ specifier: ^2.5.1
118+ version: 2.5.1(react@19.2.8)
119+ tailwind-merge:
120+ specifier: ^3.3.1
121+ version: 3.6.0
122+ zod:
123+ specifier: ^4.5.4
124+ version: 4.5.4
125+ devDependencies:
126+ '@playwright/test':
127+ specifier: ^1.63.0
128+ version: 1.63.0
129+ '@tailwindcss/postcss':
130+ specifier: ^4.3.3
131+ version: 4.3.3
132+ '@types/node':
133+ specifier: ^24.0.0
134+ version: 24.13.3
135+ '@types/pg':
136+ specifier: ^8.15.0
137+ version: 8.23.1
138+ '@types/react':
139+ specifier: ^19
140+ version: 19.2.18
141+ '@types/react-dom':
142+ specifier: ^19
143+ version: 19.2.7(@types/react@19.2.18)
144+ drizzle-kit:
145+ specifier: ^0.31.10
146+ version: 0.31.10
147+ eslint:
148+ specifier: ^9
149+ version: 9.39.5(jiti@2.7.0)
150+ eslint-config-next:
151+ specifier: 16.3.4
152+ version: 16.3.4(@typescript-eslint/parser@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
153+ tailwindcss:
154+ specifier: ^4.3.3
155+ version: 4.3.3
156+ tsx:
157+ specifier: ^4.20.0
158+ version: 4.23.13
159+ typescript:
160+ specifier: ^5.9.3
161+ version: 5.9.3
162+ vitest:
163+ specifier: ^3.2.0
164+ version: 3.2.7(@types/debug@4.1.13)(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13)
165+
166+packages:
167+
168+ '@alloc/quick-lru@5.3.0':
169+ resolution: {integrity: sha512-U4+70Pc5ZS9osnCBCE5Jha/ciHM+Yp+CNMNC/7HvYbNRk1Ldd+f7qO65W5qfhu/TCv+/ozljlXXe9Nj8419DMA==}
170+ engines: {node: '>=10'}
171+
172+ '@anthropic-ai/sdk@0.124.0':
173+ resolution: {integrity: sha512-cN5O8i9UVxHeOQAzj/XjshWXG8KiibJDw9OGpH2Z/eR3n/RBxdoLxDJOcfqAJWvjaMDFfHTBADU04hWRJVkDyA==}
174+ hasBin: true
175+ peerDependencies:
176+ zod: ^3.25.0 || ^4.0.0
177+ peerDependenciesMeta:
178+ zod:
179+ optional: true
180+
181+ '@babel/code-frame@7.29.7':
182+ resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
183+ engines: {node: '>=6.9.0'}
184+
185+ '@babel/compat-data@7.29.7':
186+ resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==}
187+ engines: {node: '>=6.9.0'}
188+
189+ '@babel/core@7.29.7':
190+ resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==}
191+ engines: {node: '>=6.9.0'}
192+
193+ '@babel/generator@7.29.8':
194+ resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==}
195+ engines: {node: '>=6.9.0'}
196+
197+ '@babel/helper-compilation-targets@7.29.7':
198+ resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==}
199+ engines: {node: '>=6.9.0'}
200+
201+ '@babel/helper-globals@7.29.7':
202+ resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==}
203+ engines: {node: '>=6.9.0'}
204+
205+ '@babel/helper-module-imports@7.29.7':
206+ resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==}
207+ engines: {node: '>=6.9.0'}
208+
209+ '@babel/helper-module-transforms@7.29.7':
210+ resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==}
211+ engines: {node: '>=6.9.0'}
212+ peerDependencies:
213+ '@babel/core': ^7.0.0
214+
215+ '@babel/helper-string-parser@7.29.7':
216+ resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==}
217+ engines: {node: '>=6.9.0'}
218+
219+ '@babel/helper-validator-identifier@7.29.7':
220+ resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
221+ engines: {node: '>=6.9.0'}
222+
223+ '@babel/helper-validator-option@7.29.7':
224+ resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==}
225+ engines: {node: '>=6.9.0'}
226+
227+ '@babel/helpers@7.29.7':
228+ resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==}
229+ engines: {node: '>=6.9.0'}
230+
231+ '@babel/parser@7.29.8':
232+ resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==}
233+ engines: {node: '>=6.0.0'}
234+ hasBin: true
235+
236+ '@babel/runtime@7.29.7':
237+ resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==}
238+ engines: {node: '>=6.9.0'}
239+
240+ '@babel/template@7.29.7':
241+ resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
242+ engines: {node: '>=6.9.0'}
243+
244+ '@babel/traverse@7.29.8':
245+ resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==}
246+ engines: {node: '>=6.9.0'}
247+
248+ '@babel/types@7.29.8':
249+ resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==}
250+ engines: {node: '>=6.9.0'}
251+
252+ '@better-auth/core@1.7.3':
253+ resolution: {integrity: sha512-JdP7lOkyE83jgjn7RilJj1XvZ7n2JjRsErKJuaXchjyuNo6cf1iVd3GtbhAtiUyJJkWdk8yL+LaUBKT80H0zLA==}
254+ peerDependencies:
255+ '@better-auth/utils': 0.4.2
256+ '@better-fetch/fetch': 1.3.1
257+ '@cloudflare/workers-types': '>=4'
258+ '@opentelemetry/api': ^1.9.0
259+ better-call: 1.4.0
260+ jose: ^6.1.0
261+ kysely: ^0.28.5 || ^0.29.0
262+ nanostores: ^1.0.1
263+ peerDependenciesMeta:
264+ '@cloudflare/workers-types':
265+ optional: true
266+ '@opentelemetry/api':
267+ optional: true
268+
269+ '@better-auth/drizzle-adapter@1.7.3':
270+ resolution: {integrity: sha512-S+nQRlxbUhkR43LrSv8c98ZvOvmv3nrtOnHkiZXkdDkr60PWp7maC2cqgzZ2C9exCC1a+4TugJlx2jRL+r+/9A==}
271+ peerDependencies:
272+ '@better-auth/core': ^1.7.3
273+ '@better-auth/utils': 0.4.2
274+ drizzle-orm: ^0.45.2 || >=1.0.0-rc.1 <2.0.0
275+ peerDependenciesMeta:
276+ drizzle-orm:
277+ optional: true
278+
279+ '@better-auth/kysely-adapter@1.7.3':
280+ resolution: {integrity: sha512-UIsyJMIrjUnT+yTaS6dkCxYYmtPwxFHxwSJ8+CLty2II5w9BewlDxDA0/QzhoL/InYCPxQ5Y6xIgLHZG1dhwRA==}
281+ peerDependencies:
282+ '@better-auth/core': ^1.7.3
283+ '@better-auth/utils': 0.4.2
284+ kysely: ^0.28.17 || ^0.29.0
285+ peerDependenciesMeta:
286+ kysely:
287+ optional: true
288+
289+ '@better-auth/memory-adapter@1.7.3':
290+ resolution: {integrity: sha512-WdLANFY/QWC3G351RCzxU+Y9YlW+BQ1oG9NwBTSOUWQw5rZ87ws+weU8tvAMO7sQ4C9gKIlkOKBKUKXrSt91Tw==}
291+ peerDependencies:
292+ '@better-auth/core': ^1.7.3
293+ '@better-auth/utils': 0.4.2
294+
295+ '@better-auth/mongo-adapter@1.7.3':
296+ resolution: {integrity: sha512-YL9m01tNogmFmRvOWJ46M9WwE6HirCXHDell29mtsQB/Qs1TPNLrgj7ybGMMGhQuyj6S218+8Wbls8m9s+i8RQ==}
297+ peerDependencies:
298+ '@better-auth/core': ^1.7.3
299+ '@better-auth/utils': 0.4.2
300+ mongodb: ^6.0.0 || ^7.0.0
301+ peerDependenciesMeta:
302+ mongodb:
303+ optional: true
304+
305+ '@better-auth/prisma-adapter@1.7.3':
306+ resolution: {integrity: sha512-TJ/DhlU7oLzrC626/1wfYA1Pl+lVsXa/zXBZ8d7Rlc2YO5fGd5fsAYJdRrYMyA51iZEo+rWLXMhZ0cez1BamsQ==}
307+ peerDependencies:
308+ '@better-auth/core': ^1.7.3
309+ '@better-auth/utils': 0.4.2
310+ '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0
311+ prisma: ^5.0.0 || ^6.0.0 || ^7.0.0
312+ peerDependenciesMeta:
313+ '@prisma/client':
314+ optional: true
315+ prisma:
316+ optional: true
317+
318+ '@better-auth/telemetry@1.7.3':
319+ resolution: {integrity: sha512-aixgHbJhGvS8PRczX/LR3murYyBnIvOGmJw37ZZBMg6ZtLR/UBJAkufbDi1HYn5THSuTJ3D5DtY85Ahh/ABQtw==}
320+ peerDependencies:
321+ '@better-auth/core': ^1.7.3
322+ '@better-auth/utils': 0.4.2
323+ '@better-fetch/fetch': 1.3.1
324+
325+ '@better-auth/utils@0.4.2':
326+ resolution: {integrity: sha512-AUxrvu+HaaODsUyzDxFgwd/8RZ1yZaYo42LXKSrU2oGgR38pS1ij8nqQKNgtTWoYGpNevNXtCfgTy6loHveW9A==}
327+
328+ '@better-auth/utils@0.5.0':
329+ resolution: {integrity: sha512-BL8W4EfIZFwlu0r54m3v1ztjDhu6dDe/amLTm0xybmbZaNgYUqhD3SjpAsnq0q8YD6/ki4iwIgxJNLP/N3TxiA==}
330+
331+ '@better-fetch/fetch@1.3.1':
332+ resolution: {integrity: sha512-ABkD1WhyfPZprKRQI3bhATjeiFuNWC9PXhfGWqL+sg/gKrM977oFrYkdb4msM3hgUGonr7KlOsOFT5TU2rht9g==}
333+
334+ '@drizzle-team/brocli@0.10.2':
335+ resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
336+
337+ '@emnapi/core@1.10.0':
338+ resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==}
339+
340+ '@emnapi/runtime@1.10.0':
341+ resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==}
342+
343+ '@emnapi/runtime@1.11.3':
344+ resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==}
345+
346+ '@emnapi/wasi-threads@1.2.1':
347+ resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
348+
349+ '@epic-web/invariant@1.0.0':
350+ resolution: {integrity: sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==}
351+
352+ '@esbuild-kit/core-utils@3.3.2':
353+ resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==}
354+ deprecated: 'Merged into tsx: https://tsx.hirok.io'
355+
356+ '@esbuild-kit/esm-loader@2.6.5':
357+ resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==}
358+ deprecated: 'Merged into tsx: https://tsx.hirok.io'
359+
360+ '@esbuild/aix-ppc64@0.25.12':
361+ resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==}
362+ engines: {node: '>=18'}
363+ cpu: [ppc64]
364+ os: [aix]
365+
366+ '@esbuild/aix-ppc64@0.28.2':
367+ resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==}
368+ engines: {node: '>=18'}
369+ cpu: [ppc64]
370+ os: [aix]
371+
372+ '@esbuild/android-arm64@0.18.20':
373+ resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
374+ engines: {node: '>=12'}
375+ cpu: [arm64]
376+ os: [android]
377+
378+ '@esbuild/android-arm64@0.25.12':
379+ resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==}
380+ engines: {node: '>=18'}
381+ cpu: [arm64]
382+ os: [android]
383+
384+ '@esbuild/android-arm64@0.28.2':
385+ resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==}
386+ engines: {node: '>=18'}
387+ cpu: [arm64]
388+ os: [android]
389+
390+ '@esbuild/android-arm@0.18.20':
391+ resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==}
392+ engines: {node: '>=12'}
393+ cpu: [arm]
394+ os: [android]
395+
396+ '@esbuild/android-arm@0.25.12':
397+ resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
398+ engines: {node: '>=18'}
399+ cpu: [arm]
400+ os: [android]
401+
402+ '@esbuild/android-arm@0.28.2':
403+ resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==}
404+ engines: {node: '>=18'}
405+ cpu: [arm]
406+ os: [android]
407+
408+ '@esbuild/android-x64@0.18.20':
409+ resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==}
410+ engines: {node: '>=12'}
411+ cpu: [x64]
412+ os: [android]
413+
414+ '@esbuild/android-x64@0.25.12':
415+ resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==}
416+ engines: {node: '>=18'}
417+ cpu: [x64]
418+ os: [android]
419+
420+ '@esbuild/android-x64@0.28.2':
421+ resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==}
422+ engines: {node: '>=18'}
423+ cpu: [x64]
424+ os: [android]
425+
426+ '@esbuild/darwin-arm64@0.18.20':
427+ resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==}
428+ engines: {node: '>=12'}
429+ cpu: [arm64]
430+ os: [darwin]
431+
432+ '@esbuild/darwin-arm64@0.25.12':
433+ resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
434+ engines: {node: '>=18'}
435+ cpu: [arm64]
436+ os: [darwin]
437+
438+ '@esbuild/darwin-arm64@0.28.2':
439+ resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==}
440+ engines: {node: '>=18'}
441+ cpu: [arm64]
442+ os: [darwin]
443+
444+ '@esbuild/darwin-x64@0.18.20':
445+ resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==}
446+ engines: {node: '>=12'}
447+ cpu: [x64]
448+ os: [darwin]
449+
450+ '@esbuild/darwin-x64@0.25.12':
451+ resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==}
452+ engines: {node: '>=18'}
453+ cpu: [x64]
454+ os: [darwin]
455+
456+ '@esbuild/darwin-x64@0.28.2':
457+ resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==}
458+ engines: {node: '>=18'}
459+ cpu: [x64]
460+ os: [darwin]
461+
462+ '@esbuild/freebsd-arm64@0.18.20':
463+ resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==}
464+ engines: {node: '>=12'}
465+ cpu: [arm64]
466+ os: [freebsd]
467+
468+ '@esbuild/freebsd-arm64@0.25.12':
469+ resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
470+ engines: {node: '>=18'}
471+ cpu: [arm64]
472+ os: [freebsd]
473+
474+ '@esbuild/freebsd-arm64@0.28.2':
475+ resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==}
476+ engines: {node: '>=18'}
477+ cpu: [arm64]
478+ os: [freebsd]
479+
480+ '@esbuild/freebsd-x64@0.18.20':
481+ resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==}
482+ engines: {node: '>=12'}
483+ cpu: [x64]
484+ os: [freebsd]
485+
486+ '@esbuild/freebsd-x64@0.25.12':
487+ resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==}
488+ engines: {node: '>=18'}
489+ cpu: [x64]
490+ os: [freebsd]
491+
492+ '@esbuild/freebsd-x64@0.28.2':
493+ resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==}
494+ engines: {node: '>=18'}
495+ cpu: [x64]
496+ os: [freebsd]
497+
498+ '@esbuild/linux-arm64@0.18.20':
499+ resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==}
500+ engines: {node: '>=12'}
501+ cpu: [arm64]
502+ os: [linux]
503+
504+ '@esbuild/linux-arm64@0.25.12':
505+ resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
506+ engines: {node: '>=18'}
507+ cpu: [arm64]
508+ os: [linux]
509+
510+ '@esbuild/linux-arm64@0.28.2':
511+ resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==}
512+ engines: {node: '>=18'}
513+ cpu: [arm64]
514+ os: [linux]
515+
516+ '@esbuild/linux-arm@0.18.20':
517+ resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==}
518+ engines: {node: '>=12'}
519+ cpu: [arm]
520+ os: [linux]
521+
522+ '@esbuild/linux-arm@0.25.12':
523+ resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==}
524+ engines: {node: '>=18'}
525+ cpu: [arm]
526+ os: [linux]
527+
528+ '@esbuild/linux-arm@0.28.2':
529+ resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==}
530+ engines: {node: '>=18'}
531+ cpu: [arm]
532+ os: [linux]
533+
534+ '@esbuild/linux-ia32@0.18.20':
535+ resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==}
536+ engines: {node: '>=12'}
537+ cpu: [ia32]
538+ os: [linux]
539+
540+ '@esbuild/linux-ia32@0.25.12':
541+ resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
542+ engines: {node: '>=18'}
543+ cpu: [ia32]
544+ os: [linux]
545+
546+ '@esbuild/linux-ia32@0.28.2':
547+ resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==}
548+ engines: {node: '>=18'}
549+ cpu: [ia32]
550+ os: [linux]
551+
552+ '@esbuild/linux-loong64@0.18.20':
553+ resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==}
554+ engines: {node: '>=12'}
555+ cpu: [loong64]
556+ os: [linux]
557+
558+ '@esbuild/linux-loong64@0.25.12':
559+ resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==}
560+ engines: {node: '>=18'}
561+ cpu: [loong64]
562+ os: [linux]
563+
564+ '@esbuild/linux-loong64@0.28.2':
565+ resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==}
566+ engines: {node: '>=18'}
567+ cpu: [loong64]
568+ os: [linux]
569+
570+ '@esbuild/linux-mips64el@0.18.20':
571+ resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==}
572+ engines: {node: '>=12'}
573+ cpu: [mips64el]
574+ os: [linux]
575+
576+ '@esbuild/linux-mips64el@0.25.12':
577+ resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
578+ engines: {node: '>=18'}
579+ cpu: [mips64el]
580+ os: [linux]
581+
582+ '@esbuild/linux-mips64el@0.28.2':
583+ resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==}
584+ engines: {node: '>=18'}
585+ cpu: [mips64el]
586+ os: [linux]
587+
588+ '@esbuild/linux-ppc64@0.18.20':
589+ resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==}
590+ engines: {node: '>=12'}
591+ cpu: [ppc64]
592+ os: [linux]
593+
594+ '@esbuild/linux-ppc64@0.25.12':
595+ resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==}
596+ engines: {node: '>=18'}
597+ cpu: [ppc64]
598+ os: [linux]
599+
600+ '@esbuild/linux-ppc64@0.28.2':
601+ resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==}
602+ engines: {node: '>=18'}
603+ cpu: [ppc64]
604+ os: [linux]
605+
606+ '@esbuild/linux-riscv64@0.18.20':
607+ resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==}
608+ engines: {node: '>=12'}
609+ cpu: [riscv64]
610+ os: [linux]
611+
612+ '@esbuild/linux-riscv64@0.25.12':
613+ resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
614+ engines: {node: '>=18'}
615+ cpu: [riscv64]
616+ os: [linux]
617+
618+ '@esbuild/linux-riscv64@0.28.2':
619+ resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==}
620+ engines: {node: '>=18'}
621+ cpu: [riscv64]
622+ os: [linux]
623+
624+ '@esbuild/linux-s390x@0.18.20':
625+ resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==}
626+ engines: {node: '>=12'}
627+ cpu: [s390x]
628+ os: [linux]
629+
630+ '@esbuild/linux-s390x@0.25.12':
631+ resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==}
632+ engines: {node: '>=18'}
633+ cpu: [s390x]
634+ os: [linux]
635+
636+ '@esbuild/linux-s390x@0.28.2':
637+ resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==}
638+ engines: {node: '>=18'}
639+ cpu: [s390x]
640+ os: [linux]
641+
642+ '@esbuild/linux-x64@0.18.20':
643+ resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==}
644+ engines: {node: '>=12'}
645+ cpu: [x64]
646+ os: [linux]
647+
648+ '@esbuild/linux-x64@0.25.12':
649+ resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
650+ engines: {node: '>=18'}
651+ cpu: [x64]
652+ os: [linux]
653+
654+ '@esbuild/linux-x64@0.28.2':
655+ resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==}
656+ engines: {node: '>=18'}
657+ cpu: [x64]
658+ os: [linux]
659+
660+ '@esbuild/netbsd-arm64@0.25.12':
661+ resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==}
662+ engines: {node: '>=18'}
663+ cpu: [arm64]
664+ os: [netbsd]
665+
666+ '@esbuild/netbsd-arm64@0.28.2':
667+ resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==}
668+ engines: {node: '>=18'}
669+ cpu: [arm64]
670+ os: [netbsd]
671+
672+ '@esbuild/netbsd-x64@0.18.20':
673+ resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==}
674+ engines: {node: '>=12'}
675+ cpu: [x64]
676+ os: [netbsd]
677+
678+ '@esbuild/netbsd-x64@0.25.12':
679+ resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
680+ engines: {node: '>=18'}
681+ cpu: [x64]
682+ os: [netbsd]
683+
684+ '@esbuild/netbsd-x64@0.28.2':
685+ resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==}
686+ engines: {node: '>=18'}
687+ cpu: [x64]
688+ os: [netbsd]
689+
690+ '@esbuild/openbsd-arm64@0.25.12':
691+ resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==}
692+ engines: {node: '>=18'}
693+ cpu: [arm64]
694+ os: [openbsd]
695+
696+ '@esbuild/openbsd-arm64@0.28.2':
697+ resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==}
698+ engines: {node: '>=18'}
699+ cpu: [arm64]
700+ os: [openbsd]
701+
702+ '@esbuild/openbsd-x64@0.18.20':
703+ resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==}
704+ engines: {node: '>=12'}
705+ cpu: [x64]
706+ os: [openbsd]
707+
708+ '@esbuild/openbsd-x64@0.25.12':
709+ resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
710+ engines: {node: '>=18'}
711+ cpu: [x64]
712+ os: [openbsd]
713+
714+ '@esbuild/openbsd-x64@0.28.2':
715+ resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==}
716+ engines: {node: '>=18'}
717+ cpu: [x64]
718+ os: [openbsd]
719+
720+ '@esbuild/openharmony-arm64@0.25.12':
721+ resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==}
722+ engines: {node: '>=18'}
723+ cpu: [arm64]
724+ os: [openharmony]
725+
726+ '@esbuild/openharmony-arm64@0.28.2':
727+ resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==}
728+ engines: {node: '>=18'}
729+ cpu: [arm64]
730+ os: [openharmony]
731+
732+ '@esbuild/sunos-x64@0.18.20':
733+ resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==}
734+ engines: {node: '>=12'}
735+ cpu: [x64]
736+ os: [sunos]
737+
738+ '@esbuild/sunos-x64@0.25.12':
739+ resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
740+ engines: {node: '>=18'}
741+ cpu: [x64]
742+ os: [sunos]
743+
744+ '@esbuild/sunos-x64@0.28.2':
745+ resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==}
746+ engines: {node: '>=18'}
747+ cpu: [x64]
748+ os: [sunos]
749+
750+ '@esbuild/win32-arm64@0.18.20':
751+ resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==}
752+ engines: {node: '>=12'}
753+ cpu: [arm64]
754+ os: [win32]
755+
756+ '@esbuild/win32-arm64@0.25.12':
757+ resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==}
758+ engines: {node: '>=18'}
759+ cpu: [arm64]
760+ os: [win32]
761+
762+ '@esbuild/win32-arm64@0.28.2':
763+ resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==}
764+ engines: {node: '>=18'}
765+ cpu: [arm64]
766+ os: [win32]
767+
768+ '@esbuild/win32-ia32@0.18.20':
769+ resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==}
770+ engines: {node: '>=12'}
771+ cpu: [ia32]
772+ os: [win32]
773+
774+ '@esbuild/win32-ia32@0.25.12':
775+ resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
776+ engines: {node: '>=18'}
777+ cpu: [ia32]
778+ os: [win32]
779+
780+ '@esbuild/win32-ia32@0.28.2':
781+ resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==}
782+ engines: {node: '>=18'}
783+ cpu: [ia32]
784+ os: [win32]
785+
786+ '@esbuild/win32-x64@0.18.20':
787+ resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==}
788+ engines: {node: '>=12'}
789+ cpu: [x64]
790+ os: [win32]
791+
792+ '@esbuild/win32-x64@0.25.12':
793+ resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==}
794+ engines: {node: '>=18'}
795+ cpu: [x64]
796+ os: [win32]
797+
798+ '@esbuild/win32-x64@0.28.2':
799+ resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==}
800+ engines: {node: '>=18'}
801+ cpu: [x64]
802+ os: [win32]
803+
804+ '@eslint-community/eslint-utils@4.10.1':
805+ resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==}
806+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
807+ peerDependencies:
808+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
809+
810+ '@eslint-community/eslint-utils@4.9.1':
811+ resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
812+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
813+ peerDependencies:
814+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
815+
816+ '@eslint-community/regexpp@4.12.2':
817+ resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
818+ engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
819+
820+ '@eslint/config-array@0.21.2':
821+ resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==}
822+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
823+
824+ '@eslint/config-helpers@0.4.2':
825+ resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==}
826+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
827+
828+ '@eslint/core@0.17.0':
829+ resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==}
830+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
831+
832+ '@eslint/eslintrc@3.3.7':
833+ resolution: {integrity: sha512-F42g89Qd5oAWtp0k0nnSrjziAKza7w8SVT4mStc18LZMaRb4J1HQAHLCalEtDCxrTuksx7NU9qsmeLwpOfPqWw==}
834+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
835+
836+ '@eslint/js@9.39.5':
837+ resolution: {integrity: sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==}
838+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
839+
840+ '@eslint/object-schema@2.1.7':
841+ resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
842+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
843+
844+ '@eslint/plugin-kit@0.4.1':
845+ resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
846+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
847+
848+ '@floating-ui/core@1.8.0':
849+ resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==}
850+
851+ '@floating-ui/dom@1.8.0':
852+ resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==}
853+
854+ '@floating-ui/react-dom@2.1.9':
855+ resolution: {integrity: sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==}
856+ peerDependencies:
857+ react: '>=16.8.0'
858+ react-dom: '>=16.8.0'
859+
860+ '@floating-ui/utils@0.2.12':
861+ resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==}
862+
863+ '@google/genai@2.21.0':
864+ resolution: {integrity: sha512-+PDtco2/Z0ONdzCGekCoCT+O1VJS9xJQNN4XzQpXG/t3El/SWWMkCWlFRO1KmivOHPa4Q0VjUYu1HBKCZ/v33Q==}
865+ engines: {node: '>=20.0.0'}
866+ peerDependencies:
867+ '@modelcontextprotocol/sdk': ^1.25.2
868+ peerDependenciesMeta:
869+ '@modelcontextprotocol/sdk':
870+ optional: true
871+
872+ '@humanfs/core@0.19.2':
873+ resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==}
874+ engines: {node: '>=18.18.0'}
875+
876+ '@humanfs/node@0.16.8':
877+ resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==}
878+ engines: {node: '>=18.18.0'}
879+
880+ '@humanfs/types@0.15.0':
881+ resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==}
882+ engines: {node: '>=18.18.0'}
883+
884+ '@humanwhocodes/module-importer@1.0.1':
885+ resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
886+ engines: {node: '>=12.22'}
887+
888+ '@humanwhocodes/retry@0.4.3':
889+ resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
890+ engines: {node: '>=18.18'}
891+
892+ '@img/colour@1.1.0':
893+ resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
894+ engines: {node: '>=18'}
895+
896+ '@img/sharp-darwin-arm64@0.35.4':
897+ resolution: {integrity: sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==}
898+ engines: {node: '>=20.9.0'}
899+ cpu: [arm64]
900+ os: [darwin]
901+
902+ '@img/sharp-darwin-x64@0.35.4':
903+ resolution: {integrity: sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==}
904+ engines: {node: '>=20.9.0'}
905+ cpu: [x64]
906+ os: [darwin]
907+
908+ '@img/sharp-freebsd-wasm32@0.35.4':
909+ resolution: {integrity: sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==}
910+ engines: {node: '>=20.9.0'}
911+ os: [freebsd]
912+
913+ '@img/sharp-libvips-darwin-arm64@1.3.3':
914+ resolution: {integrity: sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==}
915+ cpu: [arm64]
916+ os: [darwin]
917+
918+ '@img/sharp-libvips-darwin-x64@1.3.3':
919+ resolution: {integrity: sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==}
920+ cpu: [x64]
921+ os: [darwin]
922+
923+ '@img/sharp-libvips-linux-arm64@1.3.3':
924+ resolution: {integrity: sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==}
925+ cpu: [arm64]
926+ os: [linux]
927+ libc: [glibc]
928+
929+ '@img/sharp-libvips-linux-arm@1.3.3':
930+ resolution: {integrity: sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==}
931+ cpu: [arm]
932+ os: [linux]
933+ libc: [glibc]
934+
935+ '@img/sharp-libvips-linux-ppc64@1.3.3':
936+ resolution: {integrity: sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==}
937+ cpu: [ppc64]
938+ os: [linux]
939+ libc: [glibc]
940+
941+ '@img/sharp-libvips-linux-riscv64@1.3.3':
942+ resolution: {integrity: sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==}
943+ cpu: [riscv64]
944+ os: [linux]
945+ libc: [glibc]
946+
947+ '@img/sharp-libvips-linux-s390x@1.3.3':
948+ resolution: {integrity: sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==}
949+ cpu: [s390x]
950+ os: [linux]
951+ libc: [glibc]
952+
953+ '@img/sharp-libvips-linux-x64@1.3.3':
954+ resolution: {integrity: sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==}
955+ cpu: [x64]
956+ os: [linux]
957+ libc: [glibc]
958+
959+ '@img/sharp-libvips-linuxmusl-arm64@1.3.3':
960+ resolution: {integrity: sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==}
961+ cpu: [arm64]
962+ os: [linux]
963+ libc: [musl]
964+
965+ '@img/sharp-libvips-linuxmusl-x64@1.3.3':
966+ resolution: {integrity: sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==}
967+ cpu: [x64]
968+ os: [linux]
969+ libc: [musl]
970+
971+ '@img/sharp-linux-arm64@0.35.4':
972+ resolution: {integrity: sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==}
973+ engines: {node: '>=20.9.0'}
974+ cpu: [arm64]
975+ os: [linux]
976+ libc: [glibc]
977+
978+ '@img/sharp-linux-arm@0.35.4':
979+ resolution: {integrity: sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==}
980+ engines: {node: '>=20.9.0'}
981+ cpu: [arm]
982+ os: [linux]
983+ libc: [glibc]
984+
985+ '@img/sharp-linux-ppc64@0.35.4':
986+ resolution: {integrity: sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==}
987+ engines: {node: '>=20.9.0'}
988+ cpu: [ppc64]
989+ os: [linux]
990+ libc: [glibc]
991+
992+ '@img/sharp-linux-riscv64@0.35.4':
993+ resolution: {integrity: sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==}
994+ engines: {node: '>=20.9.0'}
995+ cpu: [riscv64]
996+ os: [linux]
997+ libc: [glibc]
998+
999+ '@img/sharp-linux-s390x@0.35.4':
1000+ resolution: {integrity: sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==}
1001+ engines: {node: '>=20.9.0'}
1002+ cpu: [s390x]
1003+ os: [linux]
1004+ libc: [glibc]
1005+
1006+ '@img/sharp-linux-x64@0.35.4':
1007+ resolution: {integrity: sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==}
1008+ engines: {node: '>=20.9.0'}
1009+ cpu: [x64]
1010+ os: [linux]
1011+ libc: [glibc]
1012+
1013+ '@img/sharp-linuxmusl-arm64@0.35.4':
1014+ resolution: {integrity: sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==}
1015+ engines: {node: '>=20.9.0'}
1016+ cpu: [arm64]
1017+ os: [linux]
1018+ libc: [musl]
1019+
1020+ '@img/sharp-linuxmusl-x64@0.35.4':
1021+ resolution: {integrity: sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==}
1022+ engines: {node: '>=20.9.0'}
1023+ cpu: [x64]
1024+ os: [linux]
1025+ libc: [musl]
1026+
1027+ '@img/sharp-wasm32@0.35.4':
1028+ resolution: {integrity: sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==}
1029+ engines: {node: '>=20.9.0'}
1030+
1031+ '@img/sharp-webcontainers-wasm32@0.35.4':
1032+ resolution: {integrity: sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==}
1033+ engines: {node: '>=20.9.0'}
1034+ cpu: [wasm32]
1035+
1036+ '@img/sharp-win32-arm64@0.35.4':
1037+ resolution: {integrity: sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==}
1038+ engines: {node: '>=20.9.0'}
1039+ cpu: [arm64]
1040+ os: [win32]
1041+
1042+ '@img/sharp-win32-ia32@0.35.4':
1043+ resolution: {integrity: sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==}
1044+ engines: {node: ^20.9.0}
1045+ cpu: [ia32]
1046+ os: [win32]
1047+
1048+ '@img/sharp-win32-x64@0.35.4':
1049+ resolution: {integrity: sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==}
1050+ engines: {node: '>=20.9.0'}
1051+ cpu: [x64]
1052+ os: [win32]
1053+
1054+ '@jridgewell/gen-mapping@0.3.13':
1055+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
1056+
1057+ '@jridgewell/remapping@2.3.5':
1058+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
1059+
1060+ '@jridgewell/resolve-uri@3.1.2':
1061+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
1062+ engines: {node: '>=6.0.0'}
1063+
1064+ '@jridgewell/sourcemap-codec@1.6.0':
1065+ resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==}
1066+
1067+ '@jridgewell/trace-mapping@0.3.31':
1068+ resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
1069+
1070+ '@napi-rs/lzma-linux-x64-gnu@1.5.1':
1071+ resolution: {integrity: sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==}
1072+ engines: {node: ^22.20 || ^24.12 || >=25}
1073+ cpu: [x64]
1074+ os: [linux]
1075+ libc: [glibc]
1076+
1077+ '@napi-rs/wasm-runtime@1.2.3':
1078+ resolution: {integrity: sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==}
1079+ engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0}
1080+ peerDependencies:
1081+ '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4
1082+ '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4
1083+
1084+ '@next/env@16.3.4':
1085+ resolution: {integrity: sha512-cjWZnUUa6jZq2kFaNe/ZyJdZonOZ/QoN0Zka2nz/FLOrfx14pQuM9c5RaSVkWMqgdt4ksgPAMWPyHSs/CyV48Q==}
1086+
1087+ '@next/eslint-plugin-next@16.3.4':
1088+ resolution: {integrity: sha512-szW9y2Aumu4z88YXfTzcFsgUAg2k64uzbtcO5L9f1AKS4w/GUKJcbFllRflROVyNPgJtGOnvNxiyp3v6b+prIA==}
1089+
1090+ '@next/swc-darwin-arm64@16.3.4':
1091+ resolution: {integrity: sha512-iBr3I5LZNk5/bgl5//iTgD2tcym14MX0Xo7fD//u9dYAEgGzza1y9oywluPtf74YnOswVdH1908aK9xVz7zQTw==}
1092+ engines: {node: '>= 10'}
1093+ cpu: [arm64]
1094+ os: [darwin]
1095+
1096+ '@next/swc-darwin-x64@16.3.4':
1097+ resolution: {integrity: sha512-2dpiSyl2Jw/NrBPaU2MAKGSa+2MR82pJIn4Sm5Rjr+gxAeuh0z158Su3Z2O8zn7UNNq+ej4bToed6RcRN/Lydg==}
1098+ engines: {node: '>= 10'}
1099+ cpu: [x64]
1100+ os: [darwin]
1101+
1102+ '@next/swc-linux-arm64-gnu@16.3.4':
1103+ resolution: {integrity: sha512-+t+U8HZT+fApePCS5h89CSH3datz29MkzyfCn+6fpsZBG/oiEOhINcb9rtkv6sdpToLGFn2e6146NzaKCXkqrA==}
1104+ engines: {node: '>= 10'}
1105+ cpu: [arm64]
1106+ os: [linux]
1107+ libc: [glibc]
1108+
1109+ '@next/swc-linux-arm64-musl@16.3.4':
1110+ resolution: {integrity: sha512-mx03GNs1ocQA5JQ4FxDMmIsNkdrZh8cuezKCrId28e5/gIPU/l7Kcy2+vmCCzdjnnmXJy+iOAu+7K0QppO6Urg==}
1111+ engines: {node: '>= 10'}
1112+ cpu: [arm64]
1113+ os: [linux]
1114+ libc: [musl]
1115+
1116+ '@next/swc-linux-x64-gnu@16.3.4':
1117+ resolution: {integrity: sha512-YIhGY6fSMfha52bnVxnzc9zaVBzJg+cqQTOD8tXIBSx4fuv0pVMxQTE0PaS59YhnMOiYiG09IMwxJAf/CFm/Dw==}
1118+ engines: {node: '>= 10'}
1119+ cpu: [x64]
1120+ os: [linux]
1121+ libc: [glibc]
1122+
1123+ '@next/swc-linux-x64-musl@16.3.4':
1124+ resolution: {integrity: sha512-+eaaX6axpDb0yF1GCpiERe6njplvdC+nks/fKfcHu3XPGRrald8P3/X7yv7QLdjA51knnxwl9pxdIJsg+w1L+Q==}
1125+ engines: {node: '>= 10'}
1126+ cpu: [x64]
1127+ os: [linux]
1128+ libc: [musl]
1129+
1130+ '@next/swc-win32-arm64-msvc@16.3.4':
1131+ resolution: {integrity: sha512-0jcXW7Xs/uzICrmgV3MhDYDeRy++1CqnpDIerlPIqYO4bhzB4WNbX/aRnQclustsAyTkFKB0z6rbcjmNg5tR8A==}
1132+ engines: {node: '>= 10'}
1133+ cpu: [arm64]
1134+ os: [win32]
1135+
1136+ '@next/swc-win32-x64-msvc@16.3.4':
1137+ resolution: {integrity: sha512-vvBzwu1pYQCp92maZCFCIw/XgOTMR5tur9GjakwIo2cmwRTMKajRZZDS9+e4KsUZWKu1E007WUeAFXRRjZeuzw==}
1138+ engines: {node: '>= 10'}
1139+ cpu: [x64]
1140+ os: [win32]
1141+
1142+ '@noble/ciphers@2.4.0':
1143+ resolution: {integrity: sha512-AnjFn0Jv92laAkvMrghlFZq4qQCIN/4DxFV/eooqtC2YTjB7kBeLMS2T9KJX4Dn+ZVXLOwK0lSgqDtx9gvxtiw==}
1144+ engines: {node: '>= 20.19.0'}
1145+
1146+ '@noble/hashes@2.4.0':
1147+ resolution: {integrity: sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==}
1148+ engines: {node: '>= 20.19.0'}
1149+
1150+ '@nodelib/fs.scandir@2.1.5':
1151+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
1152+ engines: {node: '>= 8'}
1153+
1154+ '@nodelib/fs.stat@2.0.5':
1155+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
1156+ engines: {node: '>= 8'}
1157+
1158+ '@nodelib/fs.walk@1.2.8':
1159+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
1160+ engines: {node: '>= 8'}
1161+
1162+ '@nolyfill/is-core-module@1.0.39':
1163+ resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
1164+ engines: {node: '>=12.4.0'}
1165+
1166+ '@opentelemetry/semantic-conventions@1.43.0':
1167+ resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==}
1168+ engines: {node: '>=14'}
1169+
1170+ '@phc/format@1.0.0':
1171+ resolution: {integrity: sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==}
1172+ engines: {node: '>=10'}
1173+
1174+ '@playwright/test@1.63.0':
1175+ resolution: {integrity: sha512-oxMK4vllB9RK5NQ2l1pq1IfOf2AvnEuj/vYGDj0H2nMtmtZpKtCwt/l00GEO6xjGfpBNAvjovvYdCm50dRQkpQ==}
1176+ engines: {node: '>=20'}
1177+ hasBin: true
1178+
1179+ '@protobufjs/aspromise@1.1.2':
1180+ resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
1181+
1182+ '@protobufjs/base64@1.1.2':
1183+ resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
1184+
1185+ '@protobufjs/codegen@2.0.5':
1186+ resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==}
1187+
1188+ '@protobufjs/eventemitter@1.1.1':
1189+ resolution: {integrity: sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==}
1190+
1191+ '@protobufjs/fetch@1.1.1':
1192+ resolution: {integrity: sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==}
1193+
1194+ '@protobufjs/float@1.0.2':
1195+ resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
1196+
1197+ '@protobufjs/path@1.1.2':
1198+ resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
1199+
1200+ '@protobufjs/pool@1.1.0':
1201+ resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
1202+
1203+ '@protobufjs/utf8@1.1.2':
1204+ resolution: {integrity: sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==}
1205+
1206+ '@radix-ui/number@1.1.3':
1207+ resolution: {integrity: sha512-Road2bidD0uu/1BGDOWNdPI06g0lIRy6IF9GZcIrDK2KGItfor8IQwQa+yM2ERgHM1MmHxaxpTzk0/Jp42lNfA==}
1208+
1209+ '@radix-ui/primitive@1.1.7':
1210+ resolution: {integrity: sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q==}
1211+
1212+ '@radix-ui/react-arrow@1.1.15':
1213+ resolution: {integrity: sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA==}
1214+ peerDependencies:
1215+ '@types/react': '*'
1216+ '@types/react-dom': '*'
1217+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1218+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1219+ peerDependenciesMeta:
1220+ '@types/react':
1221+ optional: true
1222+ '@types/react-dom':
1223+ optional: true
1224+
1225+ '@radix-ui/react-collection@1.1.15':
1226+ resolution: {integrity: sha512-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA==}
1227+ peerDependencies:
1228+ '@types/react': '*'
1229+ '@types/react-dom': '*'
1230+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1231+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1232+ peerDependenciesMeta:
1233+ '@types/react':
1234+ optional: true
1235+ '@types/react-dom':
1236+ optional: true
1237+
1238+ '@radix-ui/react-compose-refs@1.1.5':
1239+ resolution: {integrity: sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==}
1240+ peerDependencies:
1241+ '@types/react': '*'
1242+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1243+ peerDependenciesMeta:
1244+ '@types/react':
1245+ optional: true
1246+
1247+ '@radix-ui/react-context@1.2.2':
1248+ resolution: {integrity: sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA==}
1249+ peerDependencies:
1250+ '@types/react': '*'
1251+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1252+ peerDependenciesMeta:
1253+ '@types/react':
1254+ optional: true
1255+
1256+ '@radix-ui/react-dialog@1.1.23':
1257+ resolution: {integrity: sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA==}
1258+ peerDependencies:
1259+ '@types/react': '*'
1260+ '@types/react-dom': '*'
1261+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1262+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1263+ peerDependenciesMeta:
1264+ '@types/react':
1265+ optional: true
1266+ '@types/react-dom':
1267+ optional: true
1268+
1269+ '@radix-ui/react-direction@1.1.4':
1270+ resolution: {integrity: sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg==}
1271+ peerDependencies:
1272+ '@types/react': '*'
1273+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1274+ peerDependenciesMeta:
1275+ '@types/react':
1276+ optional: true
1277+
1278+ '@radix-ui/react-dismissable-layer@1.1.19':
1279+ resolution: {integrity: sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w==}
1280+ peerDependencies:
1281+ '@types/react': '*'
1282+ '@types/react-dom': '*'
1283+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1284+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1285+ peerDependenciesMeta:
1286+ '@types/react':
1287+ optional: true
1288+ '@types/react-dom':
1289+ optional: true
1290+
1291+ '@radix-ui/react-dropdown-menu@2.1.24':
1292+ resolution: {integrity: sha512-geq8l2rJkxvkXsT9RMgtUE3P8pITFpTsvYpbySi1IH4fZEABD/Gp85myayFgxk0ktljGMJnCbeFkyTusvSvv7g==}
1293+ peerDependencies:
1294+ '@types/react': '*'
1295+ '@types/react-dom': '*'
1296+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1297+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1298+ peerDependenciesMeta:
1299+ '@types/react':
1300+ optional: true
1301+ '@types/react-dom':
1302+ optional: true
1303+
1304+ '@radix-ui/react-focus-guards@1.1.6':
1305+ resolution: {integrity: sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ==}
1306+ peerDependencies:
1307+ '@types/react': '*'
1308+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1309+ peerDependenciesMeta:
1310+ '@types/react':
1311+ optional: true
1312+
1313+ '@radix-ui/react-focus-scope@1.1.16':
1314+ resolution: {integrity: sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ==}
1315+ peerDependencies:
1316+ '@types/react': '*'
1317+ '@types/react-dom': '*'
1318+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1319+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1320+ peerDependenciesMeta:
1321+ '@types/react':
1322+ optional: true
1323+ '@types/react-dom':
1324+ optional: true
1325+
1326+ '@radix-ui/react-id@1.1.4':
1327+ resolution: {integrity: sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==}
1328+ peerDependencies:
1329+ '@types/react': '*'
1330+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1331+ peerDependenciesMeta:
1332+ '@types/react':
1333+ optional: true
1334+
1335+ '@radix-ui/react-menu@2.1.24':
1336+ resolution: {integrity: sha512-uW7RVuU6Lp/ZtfeY4b3kL32zccgEWvPv1+cf17ubYzHa9cL8AHokmk36cG/XEiH/smbQvumnieXX9j/e9RqJWA==}
1337+ peerDependencies:
1338+ '@types/react': '*'
1339+ '@types/react-dom': '*'
1340+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1341+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1342+ peerDependenciesMeta:
1343+ '@types/react':
1344+ optional: true
1345+ '@types/react-dom':
1346+ optional: true
1347+
1348+ '@radix-ui/react-popover@1.1.23':
1349+ resolution: {integrity: sha512-mw58MrBlyHWFisTOYignD0vf/3gdcgAR+9of1s9G/38CbFiUwH1nCDkc0AUM9IrXFgN5Ue8n45j9WCgyM1sbiQ==}
1350+ peerDependencies:
1351+ '@types/react': '*'
1352+ '@types/react-dom': '*'
1353+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1354+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1355+ peerDependenciesMeta:
1356+ '@types/react':
1357+ optional: true
1358+ '@types/react-dom':
1359+ optional: true
1360+
1361+ '@radix-ui/react-popper@1.3.7':
1362+ resolution: {integrity: sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg==}
1363+ peerDependencies:
1364+ '@types/react': '*'
1365+ '@types/react-dom': '*'
1366+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1367+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1368+ peerDependenciesMeta:
1369+ '@types/react':
1370+ optional: true
1371+ '@types/react-dom':
1372+ optional: true
1373+
1374+ '@radix-ui/react-portal@1.1.17':
1375+ resolution: {integrity: sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ==}
1376+ peerDependencies:
1377+ '@types/react': '*'
1378+ '@types/react-dom': '*'
1379+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1380+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1381+ peerDependenciesMeta:
1382+ '@types/react':
1383+ optional: true
1384+ '@types/react-dom':
1385+ optional: true
1386+
1387+ '@radix-ui/react-presence@1.1.10':
1388+ resolution: {integrity: sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw==}
1389+ peerDependencies:
1390+ '@types/react': '*'
1391+ '@types/react-dom': '*'
1392+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1393+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1394+ peerDependenciesMeta:
1395+ '@types/react':
1396+ optional: true
1397+ '@types/react-dom':
1398+ optional: true
1399+
1400+ '@radix-ui/react-primitive@2.1.10':
1401+ resolution: {integrity: sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg==}
1402+ peerDependencies:
1403+ '@types/react': '*'
1404+ '@types/react-dom': '*'
1405+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1406+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1407+ peerDependenciesMeta:
1408+ '@types/react':
1409+ optional: true
1410+ '@types/react-dom':
1411+ optional: true
1412+
1413+ '@radix-ui/react-roving-focus@1.1.19':
1414+ resolution: {integrity: sha512-V9jI6hDjT7l3jsCQD9bLNvDLM3tH/gdbOTp7Tefp3hbbgCGQoK7tUvrWiRlcoBHIZ809ElXwNQwVo0B98LuTXQ==}
1415+ peerDependencies:
1416+ '@types/react': '*'
1417+ '@types/react-dom': '*'
1418+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1419+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1420+ peerDependenciesMeta:
1421+ '@types/react':
1422+ optional: true
1423+ '@types/react-dom':
1424+ optional: true
1425+
1426+ '@radix-ui/react-scroll-area@1.2.18':
1427+ resolution: {integrity: sha512-Zn5Cd171wxsO3Dfg8HaW6RifTb9CYTKQJHs/G4+LN1GfmJpaQMZQyQxMprVPHpaz7QY4l9BxK2JwQuzHsXC8nA==}
1428+ peerDependencies:
1429+ '@types/react': '*'
1430+ '@types/react-dom': '*'
1431+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1432+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1433+ peerDependenciesMeta:
1434+ '@types/react':
1435+ optional: true
1436+ '@types/react-dom':
1437+ optional: true
1438+
1439+ '@radix-ui/react-select@2.3.7':
1440+ resolution: {integrity: sha512-WFGImkmbzcfxeIwq/+4HvRN0pizBwbwQUED4I13ezQsDdfl38ZntN6TmR8XaSzPBqoCToe8rF75j6NPNDSzhbg==}
1441+ peerDependencies:
1442+ '@types/react': '*'
1443+ '@types/react-dom': '*'
1444+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1445+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1446+ peerDependenciesMeta:
1447+ '@types/react':
1448+ optional: true
1449+ '@types/react-dom':
1450+ optional: true
1451+
1452+ '@radix-ui/react-slider@1.4.7':
1453+ resolution: {integrity: sha512-mTSLf1GC/C0moWjTbvCM6Qn/gBjvlFt1azuWF2v7MN5C3Zq2U2J2lN3ZEYkpujuOU5Ro7A28wkviSxaKnG0BYg==}
1454+ peerDependencies:
1455+ '@types/react': '*'
1456+ '@types/react-dom': '*'
1457+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1458+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1459+ peerDependenciesMeta:
1460+ '@types/react':
1461+ optional: true
1462+ '@types/react-dom':
1463+ optional: true
1464+
1465+ '@radix-ui/react-slot@1.3.3':
1466+ resolution: {integrity: sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q==}
1467+ peerDependencies:
1468+ '@types/react': '*'
1469+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1470+ peerDependenciesMeta:
1471+ '@types/react':
1472+ optional: true
1473+
1474+ '@radix-ui/react-switch@1.3.7':
1475+ resolution: {integrity: sha512-48tB/4dn2UVLBCYhTu9AuR63IHl73l/qLbLgxd86noTUor4/K4LFDAcYjK+isP5313qxaFpjPVogE7+Y0/V3Kw==}
1476+ peerDependencies:
1477+ '@types/react': '*'
1478+ '@types/react-dom': '*'
1479+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1480+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1481+ peerDependenciesMeta:
1482+ '@types/react':
1483+ optional: true
1484+ '@types/react-dom':
1485+ optional: true
1486+
1487+ '@radix-ui/react-tabs@1.1.21':
1488+ resolution: {integrity: sha512-UKxJlZid7FVtsk/WTxj4i4uSEgj2Au+KBbS7SQyTlzMhhn+86Cz3tISZdTa87bfEfcuvZezf2ZsxD4xuEKtkog==}
1489+ peerDependencies:
1490+ '@types/react': '*'
1491+ '@types/react-dom': '*'
1492+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1493+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1494+ peerDependenciesMeta:
1495+ '@types/react':
1496+ optional: true
1497+ '@types/react-dom':
1498+ optional: true
1499+
1500+ '@radix-ui/react-tooltip@1.2.16':
1501+ resolution: {integrity: sha512-6EamKFRRnlpdadndbZ6LMwycfwkwPte1B42hs6QA0gYhjaOKqW4PZ4pjaW9UrlDX5eVt/OjncE7BFTPL5nmZhg==}
1502+ peerDependencies:
1503+ '@types/react': '*'
1504+ '@types/react-dom': '*'
1505+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1506+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1507+ peerDependenciesMeta:
1508+ '@types/react':
1509+ optional: true
1510+ '@types/react-dom':
1511+ optional: true
1512+
1513+ '@radix-ui/react-use-callback-ref@1.1.4':
1514+ resolution: {integrity: sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ==}
1515+ peerDependencies:
1516+ '@types/react': '*'
1517+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1518+ peerDependenciesMeta:
1519+ '@types/react':
1520+ optional: true
1521+
1522+ '@radix-ui/react-use-controllable-state@1.2.6':
1523+ resolution: {integrity: sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ==}
1524+ peerDependencies:
1525+ '@types/react': '*'
1526+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1527+ peerDependenciesMeta:
1528+ '@types/react':
1529+ optional: true
1530+
1531+ '@radix-ui/react-use-effect-event@0.0.5':
1532+ resolution: {integrity: sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==}
1533+ peerDependencies:
1534+ '@types/react': '*'
1535+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1536+ peerDependenciesMeta:
1537+ '@types/react':
1538+ optional: true
1539+
1540+ '@radix-ui/react-use-is-hydrated@0.1.3':
1541+ resolution: {integrity: sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw==}
1542+ peerDependencies:
1543+ '@types/react': '*'
1544+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1545+ peerDependenciesMeta:
1546+ '@types/react':
1547+ optional: true
1548+
1549+ '@radix-ui/react-use-layout-effect@1.1.4':
1550+ resolution: {integrity: sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==}
1551+ peerDependencies:
1552+ '@types/react': '*'
1553+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1554+ peerDependenciesMeta:
1555+ '@types/react':
1556+ optional: true
1557+
1558+ '@radix-ui/react-use-previous@1.1.4':
1559+ resolution: {integrity: sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg==}
1560+ peerDependencies:
1561+ '@types/react': '*'
1562+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1563+ peerDependenciesMeta:
1564+ '@types/react':
1565+ optional: true
1566+
1567+ '@radix-ui/react-use-rect@1.1.4':
1568+ resolution: {integrity: sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ==}
1569+ peerDependencies:
1570+ '@types/react': '*'
1571+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1572+ peerDependenciesMeta:
1573+ '@types/react':
1574+ optional: true
1575+
1576+ '@radix-ui/react-use-size@1.1.4':
1577+ resolution: {integrity: sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw==}
1578+ peerDependencies:
1579+ '@types/react': '*'
1580+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1581+ peerDependenciesMeta:
1582+ '@types/react':
1583+ optional: true
1584+
1585+ '@radix-ui/react-visually-hidden@1.2.11':
1586+ resolution: {integrity: sha512-NFS86RYYZb4/exihaESBGOpMJFz8MGLAfu3mOBSGByVnVPC9JPASfYubxd/8KbkQK0sYAv8lVQDEQukDX/qXvQ==}
1587+ peerDependencies:
1588+ '@types/react': '*'
1589+ '@types/react-dom': '*'
1590+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1591+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1592+ peerDependenciesMeta:
1593+ '@types/react':
1594+ optional: true
1595+ '@types/react-dom':
1596+ optional: true
1597+
1598+ '@radix-ui/rect@1.1.3':
1599+ resolution: {integrity: sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw==}
1600+
1601+ '@reduxjs/toolkit@2.12.0':
1602+ resolution: {integrity: sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==}
1603+ peerDependencies:
1604+ react: ^16.9.0 || ^17.0.0 || ^18 || ^19
1605+ react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0
1606+ peerDependenciesMeta:
1607+ react:
1608+ optional: true
1609+ react-redux:
1610+ optional: true
1611+
1612+ '@rollup/rollup-android-arm-eabi@4.63.1':
1613+ resolution: {integrity: sha512-UZ8sUxPTiHWYX9QNdJedb1kDZSpS1t/VPWBWGSgqHNi9w3Cu6IXvu2mzbhiTiPvtrqgTQJ+zqiAq2iPIPilpaQ==}
1614+ cpu: [arm]
1615+ os: [android]
1616+
1617+ '@rollup/rollup-android-arm64@4.63.1':
1618+ resolution: {integrity: sha512-cQ4nFQABN5cDvDpbvJ7bMStCpnaVxynZrRMfUJYgxcIk9Sh54FIO1vtfkg0B69REjER77ioZ/ov+eAApx/KmLQ==}
1619+ cpu: [arm64]
1620+ os: [android]
1621+
1622+ '@rollup/rollup-darwin-arm64@4.63.1':
1623+ resolution: {integrity: sha512-FQNqd1lRy/0QhDk3xeRIkSBiCpXCiDnZO3YLVdcDKN1UBiKToNftCzcXYNLshmPDUMlu2TdeS8tGcsU6f3YF1Q==}
1624+ cpu: [arm64]
1625+ os: [darwin]
1626+
1627+ '@rollup/rollup-darwin-x64@4.63.1':
1628+ resolution: {integrity: sha512-pvD16V939D3CloK0+qikpGaxiPrDUXTe7Y5cWOMkMSy7m1cawa8EGy/kXYi/G/cKAC4HDAbSnzCIk1WmsoOKXg==}
1629+ cpu: [x64]
1630+ os: [darwin]
1631+
1632+ '@rollup/rollup-freebsd-arm64@4.63.1':
1633+ resolution: {integrity: sha512-pcFGeL2345VwdTnJhA6zLbew+YgWB0qBG2+dMtXjCicf6+rm6kO6cOoh5VnTe0ZMrMRgRyuHmCJxZWrIdzYuOw==}
1634+ cpu: [arm64]
1635+ os: [freebsd]
1636+
1637+ '@rollup/rollup-freebsd-x64@4.63.1':
1638+ resolution: {integrity: sha512-mRJlqSRulVzcKq/LKA6ICSIc3K/l4fzlVn/gePn2nXIHy8seRi5z/eeRE0d/XMBxcMldiXtQTSpRj0tkkC3g8Q==}
1639+ cpu: [x64]
1640+ os: [freebsd]
1641+
1642+ '@rollup/rollup-linux-arm-gnueabihf@4.63.1':
1643+ resolution: {integrity: sha512-YDUNvVM85TI3g/1OpnqKP1h4NeW/j64DfWMf+G3M809xNk1bJSnpFp4sh83NpmVE5DXnkh8ULor4LTVZKoYLHw==}
1644+ cpu: [arm]
1645+ os: [linux]
1646+ libc: [glibc]
1647+
1648+ '@rollup/rollup-linux-arm-musleabihf@4.63.1':
1649+ resolution: {integrity: sha512-7Mcn71p9ZuQFAj+h+dhQXy/yeLePRS2yKRnmW1DijA9thKO5qap0GNOIQK4yQ6iP3SU0Mrb/yWo8h8vgRba8lw==}
1650+ cpu: [arm]
1651+ os: [linux]
1652+ libc: [musl]
1653+
1654+ '@rollup/rollup-linux-arm64-gnu@4.63.1':
1655+ resolution: {integrity: sha512-4YiLQTX6U4CSl0L9cluep9A9W6UmTfqBDc2/CH6wlu54pl4E7Jn3cOD8oxzvBDEGk/JMKgJ47C8g+radF7mwvg==}
1656+ cpu: [arm64]
1657+ os: [linux]
1658+ libc: [glibc]
1659+
1660+ '@rollup/rollup-linux-arm64-musl@4.63.1':
1661+ resolution: {integrity: sha512-2ra8F7w8OquwZN9z2/fKFnli69wa8PLwaVzRMIPGb13ByMJwC28Fbp8YcVGoUhlYMTt7j5j9bNgpysrN2UM+vw==}
1662+ cpu: [arm64]
1663+ os: [linux]
1664+ libc: [musl]
1665+
1666+ '@rollup/rollup-linux-loong64-gnu@4.63.1':
1667+ resolution: {integrity: sha512-Sy20ncyhjmBP0Ml+UvQbimjlk6VFgjW5uNP+qqwHB00mTE8Bl2C1TuHTlRwK2YoXeZbee5lP2XevBWVkAQAtSQ==}
1668+ cpu: [loong64]
1669+ os: [linux]
1670+ libc: [glibc]
1671+
1672+ '@rollup/rollup-linux-loong64-musl@4.63.1':
1673+ resolution: {integrity: sha512-noITLp8oNjYliPnGWmLyelIHwULGqbHloQHGw1rtxbWhTuWooRpnZarZQJ1y9EUC4szuCusCc+HEpUtxpIwYvA==}
1674+ cpu: [loong64]
1675+ os: [linux]
1676+ libc: [musl]
1677+
1678+ '@rollup/rollup-linux-ppc64-gnu@4.63.1':
1679+ resolution: {integrity: sha512-hlxxXd+F1mWiAcaFR7Sv9ZQT6m6UfI8+Vy/kFJzztq2pDMU/0wZ9sish0iszNZvsQDo8Gc0i5yuFEOz5dDf6fA==}
1680+ cpu: [ppc64]
1681+ os: [linux]
1682+ libc: [glibc]
1683+
1684+ '@rollup/rollup-linux-ppc64-musl@4.63.1':
1685+ resolution: {integrity: sha512-EF7OpqQTQ/BvGqLzUi4rEHuagCV9MugAUXSHemwPW5vxZ75RR+jxO/2j95Ph2dalMpFHSVECjRoioHZgA9zOYA==}
1686+ cpu: [ppc64]
1687+ os: [linux]
1688+ libc: [musl]
1689+
1690+ '@rollup/rollup-linux-riscv64-gnu@4.63.1':
1691+ resolution: {integrity: sha512-wQO3JesW9PRkwlabQ27y7sPfVOOTLRG73I4F2UYHG5PXun3J9U3y+b7ezVKSYbsvSKGQ1k1cq8Qlun4C9kLt3w==}
1692+ cpu: [riscv64]
1693+ os: [linux]
1694+ libc: [glibc]
1695+
1696+ '@rollup/rollup-linux-riscv64-musl@4.63.1':
1697+ resolution: {integrity: sha512-ouAGwhO6wHRXdnOVCOsB0tRFkA7nhNB2Nwax6oECXN0YiN8EYUTBAOudADOB1PI+yDL61TeNx/u7MVCzksNbkQ==}
1698+ cpu: [riscv64]
1699+ os: [linux]
1700+ libc: [musl]
1701+
1702+ '@rollup/rollup-linux-s390x-gnu@4.63.1':
1703+ resolution: {integrity: sha512-q2R38Sn+1J8RxhfJ+T54wSWmyKXWec+9jgDfqO2AtArEqHO5R2aeayp5H5OYLr5UYDVGsVaZPEFUooMhYCdz5A==}
1704+ cpu: [s390x]
1705+ os: [linux]
1706+ libc: [glibc]
1707+
1708+ '@rollup/rollup-linux-x64-gnu@4.63.1':
1709+ resolution: {integrity: sha512-gfI5T24WLLuFfSKw7Go/zDXjAAV0fny0swTaDv+WjK7vqcw4cRhFfdsyKL1n+ukI+ooBxn3bVQnyrn06WpI50w==}
1710+ cpu: [x64]
1711+ os: [linux]
1712+ libc: [glibc]
1713+
1714+ '@rollup/rollup-linux-x64-musl@4.63.1':
1715+ resolution: {integrity: sha512-4h6XqthmB4Hspji84wvgk+ElodTsGj+dbZqHJHHtKxj4mYq0ANSEEPX9ys3moJueqsRjwpaJYH7874Itwnj2ow==}
1716+ cpu: [x64]
1717+ os: [linux]
1718+ libc: [musl]
1719+
1720+ '@rollup/rollup-openbsd-x64@4.63.1':
1721+ resolution: {integrity: sha512-dlfCOa87o1VAYegLQ9EKilx2JCeRofiyPGhTCmqnuXZ6bMPiycO1rq1+sKoulAp7pGLIsTIw+1x5R+zgh5LhhA==}
1722+ cpu: [x64]
1723+ os: [openbsd]
1724+
1725+ '@rollup/rollup-openharmony-arm64@4.63.1':
1726+ resolution: {integrity: sha512-cjkLbOlfcm3QGhMM1J5zaZjsw1GggbN6rw9UTSSRrPrR1KkcXnN7Uq9rPw34xImQ9VOY9GN+6u2Zj80B9ptkcw==}
1727+ cpu: [arm64]
1728+ os: [openharmony]
1729+
1730+ '@rollup/rollup-win32-arm64-msvc@4.63.1':
1731+ resolution: {integrity: sha512-Li1KdUnWGE4N3e1F/B4RTB1ms+nG4WBgjByO46pkeBVX/2UBsY53xf5vK9WygVmnH3RwncIST7lkSdLSY6P9lg==}
1732+ cpu: [arm64]
1733+ os: [win32]
1734+
1735+ '@rollup/rollup-win32-ia32-msvc@4.63.1':
1736+ resolution: {integrity: sha512-t4ZYOSoLTgwhuFMrmTMLx/+i1DQVK7HYqMc6kY46EApwi8X0nIVphzdNoThU3xt6n+N5urG1/gxBdCaKDLavfg==}
1737+ cpu: [ia32]
1738+ os: [win32]
1739+
1740+ '@rollup/rollup-win32-x64-gnu@4.63.1':
1741+ resolution: {integrity: sha512-RgroPfMmKlD1RzSDxvwgcPiy2HNQKoYV7OmwIXDsk73uKW5t6B/V8KIy27SMv/FNXFo/oSBtWc9J0X7t91ezZg==}
1742+ cpu: [x64]
1743+ os: [win32]
1744+
1745+ '@rollup/rollup-win32-x64-msvc@4.63.1':
1746+ resolution: {integrity: sha512-at8QVep6S3h5Y6gSbdGU06bRY5WJkf6WUduM9YtvYMbYhB1MOFfUgc6kehitQXzOtMSaT70q7f9ydPhpqu821w==}
1747+ cpu: [x64]
1748+ os: [win32]
1749+
1750+ '@rtsao/scc@1.1.0':
1751+ resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
1752+
1753+ '@shikijs/core@4.4.3':
1754+ resolution: {integrity: sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==}
1755+ engines: {node: '>=20'}
1756+
1757+ '@shikijs/engine-javascript@4.4.3':
1758+ resolution: {integrity: sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==}
1759+ engines: {node: '>=20'}
1760+
1761+ '@shikijs/engine-oniguruma@4.4.3':
1762+ resolution: {integrity: sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==}
1763+ engines: {node: '>=20'}
1764+
1765+ '@shikijs/langs@4.4.3':
1766+ resolution: {integrity: sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==}
1767+ engines: {node: '>=20'}
1768+
1769+ '@shikijs/primitive@4.4.3':
1770+ resolution: {integrity: sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==}
1771+ engines: {node: '>=20'}
1772+
1773+ '@shikijs/themes@4.4.3':
1774+ resolution: {integrity: sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==}
1775+ engines: {node: '>=20'}
1776+
1777+ '@shikijs/types@4.4.3':
1778+ resolution: {integrity: sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==}
1779+ engines: {node: '>=20'}
1780+
1781+ '@shikijs/vscode-textmate@10.0.2':
1782+ resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
1783+
1784+ '@stablelib/base64@1.0.1':
1785+ resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==}
1786+
1787+ '@standard-schema/spec@1.1.0':
1788+ resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
1789+
1790+ '@standard-schema/utils@0.3.0':
1791+ resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==}
1792+
1793+ '@swc/helpers@0.5.23':
1794+ resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==}
1795+
1796+ '@tailwindcss/node@4.3.3':
1797+ resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==}
1798+
1799+ '@tailwindcss/oxide-android-arm64@4.3.3':
1800+ resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==}
1801+ engines: {node: '>= 20'}
1802+ cpu: [arm64]
1803+ os: [android]
1804+
1805+ '@tailwindcss/oxide-darwin-arm64@4.3.3':
1806+ resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==}
1807+ engines: {node: '>= 20'}
1808+ cpu: [arm64]
1809+ os: [darwin]
1810+
1811+ '@tailwindcss/oxide-darwin-x64@4.3.3':
1812+ resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==}
1813+ engines: {node: '>= 20'}
1814+ cpu: [x64]
1815+ os: [darwin]
1816+
1817+ '@tailwindcss/oxide-freebsd-x64@4.3.3':
1818+ resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==}
1819+ engines: {node: '>= 20'}
1820+ cpu: [x64]
1821+ os: [freebsd]
1822+
1823+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
1824+ resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==}
1825+ engines: {node: '>= 20'}
1826+ cpu: [arm]
1827+ os: [linux]
1828+
1829+ '@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
1830+ resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==}
1831+ engines: {node: '>= 20'}
1832+ cpu: [arm64]
1833+ os: [linux]
1834+ libc: [glibc]
1835+
1836+ '@tailwindcss/oxide-linux-arm64-musl@4.3.3':
1837+ resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==}
1838+ engines: {node: '>= 20'}
1839+ cpu: [arm64]
1840+ os: [linux]
1841+ libc: [musl]
1842+
1843+ '@tailwindcss/oxide-linux-x64-gnu@4.3.3':
1844+ resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==}
1845+ engines: {node: '>= 20'}
1846+ cpu: [x64]
1847+ os: [linux]
1848+ libc: [glibc]
1849+
1850+ '@tailwindcss/oxide-linux-x64-musl@4.3.3':
1851+ resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==}
1852+ engines: {node: '>= 20'}
1853+ cpu: [x64]
1854+ os: [linux]
1855+ libc: [musl]
1856+
1857+ '@tailwindcss/oxide-wasm32-wasi@4.3.3':
1858+ resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==}
1859+ engines: {node: '>=14.0.0'}
1860+ cpu: [wasm32]
1861+ bundledDependencies:
1862+ - '@napi-rs/wasm-runtime'
1863+ - '@emnapi/core'
1864+ - '@emnapi/runtime'
1865+ - '@tybys/wasm-util'
1866+ - '@emnapi/wasi-threads'
1867+ - tslib
1868+
1869+ '@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
1870+ resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==}
1871+ engines: {node: '>= 20'}
1872+ cpu: [arm64]
1873+ os: [win32]
1874+
1875+ '@tailwindcss/oxide-win32-x64-msvc@4.3.3':
1876+ resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==}
1877+ engines: {node: '>= 20'}
1878+ cpu: [x64]
1879+ os: [win32]
1880+
1881+ '@tailwindcss/oxide@4.3.3':
1882+ resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==}
1883+ engines: {node: '>= 20'}
1884+
1885+ '@tailwindcss/postcss@4.3.3':
1886+ resolution: {integrity: sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==}
1887+
1888+ '@tanstack/react-virtual@3.14.10':
1889+ resolution: {integrity: sha512-SRyoUbdFMRHuYXMijV5H4ZarQWpXkj3iANq8OFre+pybeVap8ZJjZ3Nz9bVjx4d8PfobVUQUdKyyyHYk3E+djw==}
1890+ peerDependencies:
1891+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
1892+ react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
1893+
1894+ '@tanstack/virtual-core@3.17.8':
1895+ resolution: {integrity: sha512-BfEvehNpOT75r5Ksc5xW6NZuXujTfb7nlSEyVu4XHG3gdxNg1KqXruWbDewXOUaUYIo4oRbSfkjIajz4MAT8tA==}
1896+
1897+ '@tybys/wasm-util@0.10.3':
1898+ resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==}
1899+
1900+ '@types/chai@5.2.3':
1901+ resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
1902+
1903+ '@types/d3-array@3.2.2':
1904+ resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==}
1905+
1906+ '@types/d3-color@3.1.3':
1907+ resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==}
1908+
1909+ '@types/d3-ease@3.0.2':
1910+ resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==}
1911+
1912+ '@types/d3-interpolate@3.0.4':
1913+ resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==}
1914+
1915+ '@types/d3-path@3.1.1':
1916+ resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==}
1917+
1918+ '@types/d3-scale@4.0.9':
1919+ resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==}
1920+
1921+ '@types/d3-shape@3.2.0':
1922+ resolution: {integrity: sha512-kVd74ta9eof3eJOvbNd1vGKS/XERRyQbT26Og63hIsvDO84cjD5gEOhsXf26w3FSoNlPVz84DOFcKv/oou+fMw==}
1923+
1924+ '@types/d3-time@3.0.4':
1925+ resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==}
1926+
1927+ '@types/d3-timer@3.0.2':
1928+ resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==}
1929+
1930+ '@types/debug@4.1.13':
1931+ resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==}
1932+
1933+ '@types/deep-eql@4.0.2':
1934+ resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
1935+
1936+ '@types/estree-jsx@1.0.5':
1937+ resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
1938+
1939+ '@types/estree@1.0.9':
1940+ resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
1941+
1942+ '@types/hast@3.0.5':
1943+ resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==}
1944+
1945+ '@types/json-schema@7.0.15':
1946+ resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
1947+
1948+ '@types/json5@0.0.29':
1949+ resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
1950+
1951+ '@types/mdast@4.0.4':
1952+ resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
1953+
1954+ '@types/ms@2.1.0':
1955+ resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
1956+
1957+ '@types/node@24.13.3':
1958+ resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==}
1959+
1960+ '@types/pg@8.23.1':
1961+ resolution: {integrity: sha512-fKVHpikPdg4GKks3JuLEhvwSyvwzF23hnabPy6DD8ljVbC7+6J5dQzdv4arV6jqq57djnMgs1HKBxX4P8aBI3A==}
1962+
1963+ '@types/react-dom@19.2.7':
1964+ resolution: {integrity: sha512-I8bPpDLcHBv1qiIiXDCy71Rt8eQDKJP0sMSWJphDdAcdqiJ1sGpZamavoEIRZmYzjia9LuEb2HlYdDpmoENpvQ==}
1965+ peerDependencies:
1966+ '@types/react': ^19.2.0
1967+
1968+ '@types/react@19.2.18':
1969+ resolution: {integrity: sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==}
1970+
1971+ '@types/retry@0.12.0':
1972+ resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==}
1973+
1974+ '@types/unist@2.0.11':
1975+ resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
1976+
1977+ '@types/unist@3.0.3':
1978+ resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
1979+
1980+ '@types/use-sync-external-store@0.0.6':
1981+ resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==}
1982+
1983+ '@typescript-eslint/eslint-plugin@8.69.0':
1984+ resolution: {integrity: sha512-t5jQTKPIgVW1PE6dR6H6Qz5gm8zjMlX5/2gRaOGd9eO6V7J+tQc6iWKukEe7dY8u9HyYasQ0yfF0/FSSTEO2gA==}
1985+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1986+ peerDependencies:
1987+ '@typescript-eslint/parser': ^8.69.0
1988+ eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
1989+ typescript: '>=4.8.4 <6.1.0'
1990+
1991+ '@typescript-eslint/parser@8.69.0':
1992+ resolution: {integrity: sha512-l4b0DhWioGg6Gt2ebGlvfkFMOjRsauxtsnDRwUSRX1qHq3HdTfQHV8wW9zEXeciai6HfeaKOedQn2Zoofx3WBw==}
1993+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1994+ peerDependencies:
1995+ eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
1996+ typescript: '>=4.8.4 <6.1.0'
1997+
1998+ '@typescript-eslint/project-service@8.69.0':
1999+ resolution: {integrity: sha512-yi4obFrHMmnsesWehHbkg9zMA7Jt8cXT+mKM08G999pH1yT6nqgsHx7MYm0uY1wAj8CqiBXYRJ7WAT0QdQHQXg==}
2000+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2001+ peerDependencies:
2002+ typescript: '>=4.8.4 <6.1.0'
2003+
2004+ '@typescript-eslint/scope-manager@8.69.0':
2005+ resolution: {integrity: sha512-ewfspqWvSxKSOaplqAUNbaSFO0eB6w1EtQ+esfYFRm3614Ty4uNtExkcbgd6nWsXphbqKyf9ZYdbZdv2xEoWEQ==}
2006+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2007+
2008+ '@typescript-eslint/tsconfig-utils@8.69.0':
2009+ resolution: {integrity: sha512-xNqK7YTDZsLniQMV/4rpFR8Z5JlqeRvVjuG1YgF/mdPVH84HSD19L8CczMA0qg2RfwEV231GHH3VnToJDo4MfQ==}
2010+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2011+ peerDependencies:
2012+ typescript: '>=4.8.4 <6.1.0'
2013+
2014+ '@typescript-eslint/type-utils@8.69.0':
2015+ resolution: {integrity: sha512-ZfoJAVg3JZndQEpEl9petVlxau3lRuElc4HRMuAlLCf8to04/iHz692RUSNmXKDjEuJmIL+KZ2/BsOcBc16dsA==}
2016+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2017+ peerDependencies:
2018+ eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
2019+ typescript: '>=4.8.4 <6.1.0'
2020+
2021+ '@typescript-eslint/types@8.69.0':
2022+ resolution: {integrity: sha512-K3VrubUPhlo9VDBS6QdI8YB5j7ClpqLRdefcz6PFrhnwicehBweqQ9Evhl4l+FYz0HdDmMqIiSX0aldGRYtDCA==}
2023+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2024+
2025+ '@typescript-eslint/typescript-estree@8.69.0':
2026+ resolution: {integrity: sha512-AdFkgqck3Vudb/kWnxlyafU/4aBhHrbQ9locP2N4psXTy5mOBg0SHJumnLvx7r6g1gV4DKvUFwV2nJZBoqOD8w==}
2027+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2028+ peerDependencies:
2029+ typescript: '>=4.8.4 <6.1.0'
2030+
2031+ '@typescript-eslint/utils@8.69.0':
2032+ resolution: {integrity: sha512-tUbx60BBqQa31kXF5MCsOOLL5E/WzUuxIn7YpAvq+eaUlqvk8/NXnXMBNAdLCr0icjkzem7iUA5QqWHe/hJ1aw==}
2033+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2034+ peerDependencies:
2035+ eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
2036+ typescript: '>=4.8.4 <6.1.0'
2037+
2038+ '@typescript-eslint/visitor-keys@8.69.0':
2039+ resolution: {integrity: sha512-+rmdgPA+EXkNgKYvHvFfhrs35utXbwaC5PGpDquSXcoXQDKUA5UjV0LmTucG/4JXkM31BTu4TilHtrN8IVBe8w==}
2040+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2041+
2042+ '@ungap/structured-clone@1.4.0':
2043+ resolution: {integrity: sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==}
2044+
2045+ '@unrs/resolver-binding-android-arm-eabi@1.12.2':
2046+ resolution: {integrity: sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==}
2047+ cpu: [arm]
2048+ os: [android]
2049+
2050+ '@unrs/resolver-binding-android-arm64@1.12.2':
2051+ resolution: {integrity: sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==}
2052+ cpu: [arm64]
2053+ os: [android]
2054+
2055+ '@unrs/resolver-binding-darwin-arm64@1.12.2':
2056+ resolution: {integrity: sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==}
2057+ cpu: [arm64]
2058+ os: [darwin]
2059+
2060+ '@unrs/resolver-binding-darwin-x64@1.12.2':
2061+ resolution: {integrity: sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==}
2062+ cpu: [x64]
2063+ os: [darwin]
2064+
2065+ '@unrs/resolver-binding-freebsd-x64@1.12.2':
2066+ resolution: {integrity: sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==}
2067+ cpu: [x64]
2068+ os: [freebsd]
2069+
2070+ '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2':
2071+ resolution: {integrity: sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==}
2072+ cpu: [arm]
2073+ os: [linux]
2074+
2075+ '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2':
2076+ resolution: {integrity: sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==}
2077+ cpu: [arm]
2078+ os: [linux]
2079+
2080+ '@unrs/resolver-binding-linux-arm64-gnu@1.12.2':
2081+ resolution: {integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==}
2082+ cpu: [arm64]
2083+ os: [linux]
2084+ libc: [glibc]
2085+
2086+ '@unrs/resolver-binding-linux-arm64-musl@1.12.2':
2087+ resolution: {integrity: sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==}
2088+ cpu: [arm64]
2089+ os: [linux]
2090+ libc: [musl]
2091+
2092+ '@unrs/resolver-binding-linux-loong64-gnu@1.12.2':
2093+ resolution: {integrity: sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==}
2094+ cpu: [loong64]
2095+ os: [linux]
2096+ libc: [glibc]
2097+
2098+ '@unrs/resolver-binding-linux-loong64-musl@1.12.2':
2099+ resolution: {integrity: sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==}
2100+ cpu: [loong64]
2101+ os: [linux]
2102+ libc: [musl]
2103+
2104+ '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2':
2105+ resolution: {integrity: sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==}
2106+ cpu: [ppc64]
2107+ os: [linux]
2108+ libc: [glibc]
2109+
2110+ '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2':
2111+ resolution: {integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==}
2112+ cpu: [riscv64]
2113+ os: [linux]
2114+ libc: [glibc]
2115+
2116+ '@unrs/resolver-binding-linux-riscv64-musl@1.12.2':
2117+ resolution: {integrity: sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==}
2118+ cpu: [riscv64]
2119+ os: [linux]
2120+ libc: [musl]
2121+
2122+ '@unrs/resolver-binding-linux-s390x-gnu@1.12.2':
2123+ resolution: {integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==}
2124+ cpu: [s390x]
2125+ os: [linux]
2126+ libc: [glibc]
2127+
2128+ '@unrs/resolver-binding-linux-x64-gnu@1.12.2':
2129+ resolution: {integrity: sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==}
2130+ cpu: [x64]
2131+ os: [linux]
2132+ libc: [glibc]
2133+
2134+ '@unrs/resolver-binding-linux-x64-musl@1.12.2':
2135+ resolution: {integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==}
2136+ cpu: [x64]
2137+ os: [linux]
2138+ libc: [musl]
2139+
2140+ '@unrs/resolver-binding-openharmony-arm64@1.12.2':
2141+ resolution: {integrity: sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==}
2142+ cpu: [arm64]
2143+ os: [openharmony]
2144+
2145+ '@unrs/resolver-binding-wasm32-wasi@1.12.2':
2146+ resolution: {integrity: sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==}
2147+ engines: {node: '>=14.0.0'}
2148+ cpu: [wasm32]
2149+
2150+ '@unrs/resolver-binding-win32-arm64-msvc@1.12.2':
2151+ resolution: {integrity: sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==}
2152+ cpu: [arm64]
2153+ os: [win32]
2154+
2155+ '@unrs/resolver-binding-win32-ia32-msvc@1.12.2':
2156+ resolution: {integrity: sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==}
2157+ cpu: [ia32]
2158+ os: [win32]
2159+
2160+ '@unrs/resolver-binding-win32-x64-msvc@1.12.2':
2161+ resolution: {integrity: sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==}
2162+ cpu: [x64]
2163+ os: [win32]
2164+
2165+ '@vitest/expect@3.2.7':
2166+ resolution: {integrity: sha512-E8eBXaKibuvH2pSZErOjdVb5vF4PbKYcrnluBTYxEk1l/VhhwZg1kZQsdtjq+CsF5CFydf2Rdkz7jDHKSisi3w==}
2167+
2168+ '@vitest/mocker@3.2.7':
2169+ resolution: {integrity: sha512-Trr0hYO9CM3Wj6ksWHRhK9IZpIY6wTMO5u/MqXurMxT57sWBaOPEtP3Oq60ihZuh5JsiagKfz95OcxdEP6dBrA==}
2170+ peerDependencies:
2171+ msw: ^2.4.9
2172+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0
2173+ peerDependenciesMeta:
2174+ msw:
2175+ optional: true
2176+ vite:
2177+ optional: true
2178+
2179+ '@vitest/pretty-format@3.2.7':
2180+ resolution: {integrity: sha512-KUHlwqVu0sRlhCdyPdQ/wBoTfRahjUky1MubOmYw9fWfIZy1gNoHpuaaQBPAaMaVYdQYHJLurzj8ECCj5OwTqA==}
2181+
2182+ '@vitest/runner@3.2.7':
2183+ resolution: {integrity: sha512-sB9y4ovltoQP+WaUPwmSxO9WIg9Ig694Di5PalVPsYHklAdE027mehpWF2SQSVq+k6sFgaivbTjTJwZLSHbedA==}
2184+
2185+ '@vitest/snapshot@3.2.7':
2186+ resolution: {integrity: sha512-7C+MwShwtBSI5Buwoyg3s/iY1eHL9PKAf+O1wVh/TdnjXUtkoL/9YQtre90i4MtNXM6edP1wJ2zOBpfCyhIS7g==}
2187+
2188+ '@vitest/spy@3.2.7':
2189+ resolution: {integrity: sha512-Q2eQGI6d2L/hBtZ0qNuKcAGid68XK6cv1xsoaIma6PaJhHPoqcEJhYpXZ/5myCMqkNgtP6UKuBhbc0nHKnrkuQ==}
2190+
2191+ '@vitest/utils@3.2.7':
2192+ resolution: {integrity: sha512-x6BDOd7dyo3PFLY3I9/HJ25X/6OurhGXk2/B9gOZNPF7XDVjeBK4k01lQE5uvDpbuheErh91qYuE1E2OEjK3Rw==}
2193+
2194+ acorn-jsx@5.3.2:
2195+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
2196+ peerDependencies:
2197+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
2198+
2199+ acorn@8.18.0:
2200+ resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==}
2201+ engines: {node: '>=0.4.0'}
2202+ hasBin: true
2203+
2204+ agent-base@7.1.4:
2205+ resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
2206+ engines: {node: '>= 14'}
2207+
2208+ ajv@6.15.0:
2209+ resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==}
2210+
2211+ ansi-styles@4.3.0:
2212+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
2213+ engines: {node: '>=8'}
2214+
2215+ argon2@0.45.1:
2216+ resolution: {integrity: sha512-skm+/WCjkGqCQxF7FG1LuZXM5yvbFjgbfiCGsud2oLgaDhh6b6dbH0b1EkghbM+xx4Bj8Ape+KKgixoIlWZicQ==}
2217+ engines: {node: '>=16.17.0'}
2218+
2219+ argparse@2.0.1:
2220+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
2221+
2222+ aria-hidden@1.2.6:
2223+ resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
2224+ engines: {node: '>=10'}
2225+
2226+ aria-query@5.3.2:
2227+ resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
2228+ engines: {node: '>= 0.4'}
2229+
2230+ array-buffer-byte-length@1.0.2:
2231+ resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
2232+ engines: {node: '>= 0.4'}
2233+
2234+ array-includes@3.1.9:
2235+ resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
2236+ engines: {node: '>= 0.4'}
2237+
2238+ array.prototype.findlast@1.2.5:
2239+ resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==}
2240+ engines: {node: '>= 0.4'}
2241+
2242+ array.prototype.findlastindex@1.2.6:
2243+ resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==}
2244+ engines: {node: '>= 0.4'}
2245+
2246+ array.prototype.flat@1.3.3:
2247+ resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==}
2248+ engines: {node: '>= 0.4'}
2249+
2250+ array.prototype.flatmap@1.3.3:
2251+ resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==}
2252+ engines: {node: '>= 0.4'}
2253+
2254+ array.prototype.tosorted@1.1.4:
2255+ resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==}
2256+ engines: {node: '>= 0.4'}
2257+
2258+ arraybuffer.prototype.slice@1.0.4:
2259+ resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
2260+ engines: {node: '>= 0.4'}
2261+
2262+ assertion-error@2.0.1:
2263+ resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
2264+ engines: {node: '>=12'}
2265+
2266+ ast-types-flow@0.0.8:
2267+ resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
2268+
2269+ async-function@1.0.0:
2270+ resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
2271+ engines: {node: '>= 0.4'}
2272+
2273+ available-typed-arrays@1.0.7:
2274+ resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
2275+ engines: {node: '>= 0.4'}
2276+
2277+ axe-core@4.13.0:
2278+ resolution: {integrity: sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==}
2279+ engines: {node: '>=4'}
2280+
2281+ axobject-query@4.1.0:
2282+ resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
2283+ engines: {node: '>= 0.4'}
2284+
2285+ bail@2.0.2:
2286+ resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
2287+
2288+ balanced-match@1.0.2:
2289+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
2290+
2291+ balanced-match@4.0.4:
2292+ resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
2293+ engines: {node: 18 || 20 || >=22}
2294+
2295+ base64-js@1.5.1:
2296+ resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
2297+
2298+ baseline-browser-mapping@2.11.21:
2299+ resolution: {integrity: sha512-uh8vpY/1/YyFkunIDFH/12p7/7VdPKA1hejMVEbdkEaWnUz0Hesvx5EbiU6XxjyHZIOju+ZMbQJkRh+es3/spQ==}
2300+ engines: {node: '>=6.0.0'}
2301+ hasBin: true
2302+
2303+ better-auth@1.7.3:
2304+ resolution: {integrity: sha512-8xGp68JQ+l36kniDEgP8bP99TLi1GdEv0NTEUBkyqnYnus/cgFUZseUfqUHKzr2BAsg2O6aD88I9f0U68shanQ==}
2305+ peerDependencies:
2306+ '@lynx-js/react': '*'
2307+ '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0
2308+ '@sveltejs/kit': ^2.0.0
2309+ '@tanstack/react-start': ^1.0.0
2310+ '@tanstack/solid-start': ^1.0.0
2311+ better-sqlite3: ^12.0.0
2312+ drizzle-kit: '>=0.31.4 || >=1.0.0-beta.1'
2313+ drizzle-orm: ^0.45.2 || >=1.0.0-rc.1 <2.0.0
2314+ mongodb: ^6.0.0 || ^7.0.0
2315+ mysql2: ^3.0.0
2316+ next: ^14.0.0 || ^15.0.0 || ^16.0.0
2317+ pg: ^8.0.0
2318+ prisma: ^5.0.0 || ^6.0.0 || ^7.0.0
2319+ react: ^18.0.0 || ^19.0.0
2320+ react-dom: ^18.0.0 || ^19.0.0
2321+ solid-js: ^1.0.0
2322+ svelte: ^4.0.0 || ^5.0.0
2323+ vitest: ^2.0.0 || ^3.0.0 || ^4.0.0
2324+ vue: ^3.0.0
2325+ peerDependenciesMeta:
2326+ '@lynx-js/react':
2327+ optional: true
2328+ '@prisma/client':
2329+ optional: true
2330+ '@sveltejs/kit':
2331+ optional: true
2332+ '@tanstack/react-start':
2333+ optional: true
2334+ '@tanstack/solid-start':
2335+ optional: true
2336+ better-sqlite3:
2337+ optional: true
2338+ drizzle-kit:
2339+ optional: true
2340+ drizzle-orm:
2341+ optional: true
2342+ mongodb:
2343+ optional: true
2344+ mysql2:
2345+ optional: true
2346+ next:
2347+ optional: true
2348+ pg:
2349+ optional: true
2350+ prisma:
2351+ optional: true
2352+ react:
2353+ optional: true
2354+ react-dom:
2355+ optional: true
2356+ solid-js:
2357+ optional: true
2358+ svelte:
2359+ optional: true
2360+ vitest:
2361+ optional: true
2362+ vue:
2363+ optional: true
2364+
2365+ better-call@1.4.0:
2366+ resolution: {integrity: sha512-bBKOT4vv1kZLDgxVePdilk/Jwkn+dtRRsmi3DzHcDP+WnswyVl6dR59l2HEeP/0cB+bDoopASAesWDPIdd/zZA==}
2367+ peerDependencies:
2368+ zod: ^4.0.0
2369+ peerDependenciesMeta:
2370+ zod:
2371+ optional: true
2372+
2373+ bignumber.js@9.3.1:
2374+ resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==}
2375+
2376+ brace-expansion@1.1.18:
2377+ resolution: {integrity: sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==}
2378+
2379+ brace-expansion@5.0.9:
2380+ resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==}
2381+ engines: {node: 20 || >=22}
2382+
2383+ braces@3.0.3:
2384+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
2385+ engines: {node: '>=8'}
2386+
2387+ browserslist@4.28.9:
2388+ resolution: {integrity: sha512-EWazOblFYUvlGZcfGhPUPmYh3nikUxBVb+y9MJun5f3hBi812X+8MSQTujLBtgK3cf51fJWbWfOjyeO954d+Eg==}
2389+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
2390+ hasBin: true
2391+
2392+ buffer-equal-constant-time@1.0.1:
2393+ resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
2394+
2395+ buffer-from@1.1.2:
2396+ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
2397+
2398+ cac@6.7.14:
2399+ resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
2400+ engines: {node: '>=8'}
2401+
2402+ call-bind-apply-helpers@1.0.2:
2403+ resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
2404+ engines: {node: '>= 0.4'}
2405+
2406+ call-bind@1.0.9:
2407+ resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==}
2408+ engines: {node: '>= 0.4'}
2409+
2410+ call-bound@1.0.4:
2411+ resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
2412+ engines: {node: '>= 0.4'}
2413+
2414+ callsites@3.1.0:
2415+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
2416+ engines: {node: '>=6'}
2417+
2418+ caniuse-lite@1.0.30001810:
2419+ resolution: {integrity: sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==}
2420+
2421+ ccount@2.0.1:
2422+ resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
2423+
2424+ chai@5.3.3:
2425+ resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
2426+ engines: {node: '>=18'}
2427+
2428+ chalk@4.1.2:
2429+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
2430+ engines: {node: '>=10'}
2431+
2432+ character-entities-html4@2.1.0:
2433+ resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
2434+
2435+ character-entities-legacy@3.0.0:
2436+ resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
2437+
2438+ character-entities@2.0.2:
2439+ resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
2440+
2441+ character-reference-invalid@2.0.1:
2442+ resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
2443+
2444+ check-error@2.1.3:
2445+ resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==}
2446+ engines: {node: '>= 16'}
2447+
2448+ class-variance-authority@0.7.1:
2449+ resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
2450+
2451+ client-only@0.0.1:
2452+ resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
2453+
2454+ clsx@2.1.1:
2455+ resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
2456+ engines: {node: '>=6'}
2457+
2458+ cmdk@1.1.1:
2459+ resolution: {integrity: sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==}
2460+ peerDependencies:
2461+ react: ^18 || ^19 || ^19.0.0-rc
2462+ react-dom: ^18 || ^19 || ^19.0.0-rc
2463+
2464+ color-convert@2.0.1:
2465+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
2466+ engines: {node: '>=7.0.0'}
2467+
2468+ color-name@1.1.4:
2469+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
2470+
2471+ comma-separated-tokens@2.0.3:
2472+ resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
2473+
2474+ concat-map@0.0.1:
2475+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
2476+
2477+ convert-source-map@2.0.0:
2478+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
2479+
2480+ cross-env@10.1.0:
2481+ resolution: {integrity: sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==}
2482+ engines: {node: '>=20'}
2483+ hasBin: true
2484+
2485+ cross-spawn@7.0.6:
2486+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
2487+ engines: {node: '>= 8'}
2488+
2489+ csstype@3.2.3:
2490+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
2491+
2492+ d3-array@3.2.4:
2493+ resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
2494+ engines: {node: '>=12'}
2495+
2496+ d3-color@3.1.0:
2497+ resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
2498+ engines: {node: '>=12'}
2499+
2500+ d3-ease@3.0.1:
2501+ resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
2502+ engines: {node: '>=12'}
2503+
2504+ d3-format@3.1.2:
2505+ resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==}
2506+ engines: {node: '>=12'}
2507+
2508+ d3-interpolate@3.0.1:
2509+ resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
2510+ engines: {node: '>=12'}
2511+
2512+ d3-path@3.1.0:
2513+ resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==}
2514+ engines: {node: '>=12'}
2515+
2516+ d3-scale@4.0.2:
2517+ resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==}
2518+ engines: {node: '>=12'}
2519+
2520+ d3-shape@3.2.0:
2521+ resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
2522+ engines: {node: '>=12'}
2523+
2524+ d3-time-format@4.1.0:
2525+ resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
2526+ engines: {node: '>=12'}
2527+
2528+ d3-time@3.1.0:
2529+ resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
2530+ engines: {node: '>=12'}
2531+
2532+ d3-timer@3.0.1:
2533+ resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
2534+ engines: {node: '>=12'}
2535+
2536+ damerau-levenshtein@1.0.8:
2537+ resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
2538+
2539+ data-uri-to-buffer@4.0.1:
2540+ resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
2541+ engines: {node: '>= 12'}
2542+
2543+ data-view-buffer@1.0.2:
2544+ resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
2545+ engines: {node: '>= 0.4'}
2546+
2547+ data-view-byte-length@1.0.2:
2548+ resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==}
2549+ engines: {node: '>= 0.4'}
2550+
2551+ data-view-byte-offset@1.0.1:
2552+ resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
2553+ engines: {node: '>= 0.4'}
2554+
2555+ debug@3.2.7:
2556+ resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
2557+ peerDependencies:
2558+ supports-color: '*'
2559+ peerDependenciesMeta:
2560+ supports-color:
2561+ optional: true
2562+
2563+ debug@4.4.3:
2564+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
2565+ engines: {node: '>=6.0'}
2566+ peerDependencies:
2567+ supports-color: '*'
2568+ peerDependenciesMeta:
2569+ supports-color:
2570+ optional: true
2571+
2572+ decimal.js-light@2.5.1:
2573+ resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==}
2574+
2575+ decode-named-character-reference@1.3.0:
2576+ resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==}
2577+
2578+ deep-eql@5.0.2:
2579+ resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
2580+ engines: {node: '>=6'}
2581+
2582+ deep-is@0.1.4:
2583+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
2584+
2585+ define-data-property@1.1.4:
2586+ resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
2587+ engines: {node: '>= 0.4'}
2588+
2589+ define-properties@1.2.1:
2590+ resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
2591+ engines: {node: '>= 0.4'}
2592+
2593+ defu@6.1.7:
2594+ resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==}
2595+
2596+ dequal@2.0.3:
2597+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
2598+ engines: {node: '>=6'}
2599+
2600+ detect-libc@2.1.2:
2601+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
2602+ engines: {node: '>=8'}
2603+
2604+ detect-node-es@1.1.0:
2605+ resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
2606+
2607+ devlop@1.1.0:
2608+ resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
2609+
2610+ doctrine@2.1.0:
2611+ resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
2612+ engines: {node: '>=0.10.0'}
2613+
2614+ drizzle-kit@0.31.10:
2615+ resolution: {integrity: sha512-7OZcmQUrdGI+DUNNsKBn1aW8qSoKuTH7d0mYgSP8bAzdFzKoovxEFnoGQp2dVs82EOJeYycqRtciopszwUf8bw==}
2616+ hasBin: true
2617+
2618+ drizzle-orm@0.45.2:
2619+ resolution: {integrity: sha512-kY0BSaTNYWnoDMVoyY8uxmyHjpJW1geOmBMdSSicKo9CIIWkSxMIj2rkeSR51b8KAPB7m+qysjuHme5nKP+E5Q==}
2620+ peerDependencies:
2621+ '@aws-sdk/client-rds-data': '>=3'
2622+ '@cloudflare/workers-types': '>=4'
2623+ '@electric-sql/pglite': '>=0.2.0'
2624+ '@libsql/client': '>=0.10.0'
2625+ '@libsql/client-wasm': '>=0.10.0'
2626+ '@neondatabase/serverless': '>=0.10.0'
2627+ '@op-engineering/op-sqlite': '>=2'
2628+ '@opentelemetry/api': ^1.4.1
2629+ '@planetscale/database': '>=1.13'
2630+ '@prisma/client': '*'
2631+ '@tidbcloud/serverless': '*'
2632+ '@types/better-sqlite3': '*'
2633+ '@types/pg': '*'
2634+ '@types/sql.js': '*'
2635+ '@upstash/redis': '>=1.34.7'
2636+ '@vercel/postgres': '>=0.8.0'
2637+ '@xata.io/client': '*'
2638+ better-sqlite3: '>=7'
2639+ bun-types: '*'
2640+ expo-sqlite: '>=14.0.0'
2641+ gel: '>=2'
2642+ knex: '*'
2643+ kysely: '*'
2644+ mysql2: '>=2'
2645+ pg: '>=8'
2646+ postgres: '>=3'
2647+ prisma: '*'
2648+ sql.js: '>=1'
2649+ sqlite3: '>=5'
2650+ peerDependenciesMeta:
2651+ '@aws-sdk/client-rds-data':
2652+ optional: true
2653+ '@cloudflare/workers-types':
2654+ optional: true
2655+ '@electric-sql/pglite':
2656+ optional: true
2657+ '@libsql/client':
2658+ optional: true
2659+ '@libsql/client-wasm':
2660+ optional: true
2661+ '@neondatabase/serverless':
2662+ optional: true
2663+ '@op-engineering/op-sqlite':
2664+ optional: true
2665+ '@opentelemetry/api':
2666+ optional: true
2667+ '@planetscale/database':
2668+ optional: true
2669+ '@prisma/client':
2670+ optional: true
2671+ '@tidbcloud/serverless':
2672+ optional: true
2673+ '@types/better-sqlite3':
2674+ optional: true
2675+ '@types/pg':
2676+ optional: true
2677+ '@types/sql.js':
2678+ optional: true
2679+ '@upstash/redis':
2680+ optional: true
2681+ '@vercel/postgres':
2682+ optional: true
2683+ '@xata.io/client':
2684+ optional: true
2685+ better-sqlite3:
2686+ optional: true
2687+ bun-types:
2688+ optional: true
2689+ expo-sqlite:
2690+ optional: true
2691+ gel:
2692+ optional: true
2693+ knex:
2694+ optional: true
2695+ kysely:
2696+ optional: true
2697+ mysql2:
2698+ optional: true
2699+ pg:
2700+ optional: true
2701+ postgres:
2702+ optional: true
2703+ prisma:
2704+ optional: true
2705+ sql.js:
2706+ optional: true
2707+ sqlite3:
2708+ optional: true
2709+
2710+ dunder-proto@1.0.1:
2711+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
2712+ engines: {node: '>= 0.4'}
2713+
2714+ ecdsa-sig-formatter@1.0.11:
2715+ resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
2716+
2717+ electron-to-chromium@1.5.422:
2718+ resolution: {integrity: sha512-UvA/32XqrLDdZSn7Jllo1AYNcWji/G0d5M0GTViE7KoGBiMunw3a34Sb2KO4ZZyrSEhqsxFoVhWWJshdyfKqJA==}
2719+
2720+ emoji-regex@9.2.2:
2721+ resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
2722+
2723+ enhanced-resolve@5.24.5:
2724+ resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==}
2725+ engines: {node: '>=10.13.0'}
2726+
2727+ entities@6.0.1:
2728+ resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
2729+ engines: {node: '>=0.12'}
2730+
2731+ es-abstract-get@1.0.0:
2732+ resolution: {integrity: sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==}
2733+ engines: {node: '>= 0.4'}
2734+
2735+ es-abstract@1.24.2:
2736+ resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==}
2737+ engines: {node: '>= 0.4'}
2738+
2739+ es-define-property@1.0.1:
2740+ resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
2741+ engines: {node: '>= 0.4'}
2742+
2743+ es-errors@1.3.0:
2744+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
2745+ engines: {node: '>= 0.4'}
2746+
2747+ es-iterator-helpers@1.4.0:
2748+ resolution: {integrity: sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==}
2749+ engines: {node: '>= 0.4'}
2750+
2751+ es-module-lexer@1.7.0:
2752+ resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
2753+
2754+ es-object-atoms@1.1.2:
2755+ resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==}
2756+ engines: {node: '>= 0.4'}
2757+
2758+ es-set-tostringtag@2.1.0:
2759+ resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
2760+ engines: {node: '>= 0.4'}
2761+
2762+ es-shim-unscopables@1.1.0:
2763+ resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==}
2764+ engines: {node: '>= 0.4'}
2765+
2766+ es-to-primitive@1.3.4:
2767+ resolution: {integrity: sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==}
2768+ engines: {node: '>= 0.4'}
2769+
2770+ es-toolkit@1.52.0:
2771+ resolution: {integrity: sha512-XTNEJQh1tY1ZJVcf6ayP/2n4ZPyaHlW2FWs7xvw5ddPuhUVjLD3olQVQS7kf58JbAB48iL0uL/jerTrjtV3lDA==}
2772+
2773+ esbuild@0.18.20:
2774+ resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==}
2775+ engines: {node: '>=12'}
2776+ hasBin: true
2777+
2778+ esbuild@0.25.12:
2779+ resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
2780+ engines: {node: '>=18'}
2781+ hasBin: true
2782+
2783+ esbuild@0.28.2:
2784+ resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==}
2785+ engines: {node: '>=18'}
2786+ hasBin: true
2787+
2788+ escalade@3.2.0:
2789+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
2790+ engines: {node: '>=6'}
2791+
2792+ escape-string-regexp@4.0.0:
2793+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
2794+ engines: {node: '>=10'}
2795+
2796+ escape-string-regexp@5.0.0:
2797+ resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
2798+ engines: {node: '>=12'}
2799+
2800+ eslint-config-next@16.3.4:
2801+ resolution: {integrity: sha512-35/8RM10huEL9vlr8hUZMERMENHBrnyHN3ZZkF9efSgzGaqK34jIqry44A956//zriUhUAUW0XSkcolhrryqAA==}
2802+ peerDependencies:
2803+ eslint: '>=9.0.0'
2804+ typescript: '>=3.3.1'
2805+ peerDependenciesMeta:
2806+ typescript:
2807+ optional: true
2808+
2809+ eslint-import-resolver-node@0.3.10:
2810+ resolution: {integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==}
2811+
2812+ eslint-import-resolver-typescript@3.10.1:
2813+ resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==}
2814+ engines: {node: ^14.18.0 || >=16.0.0}
2815+ peerDependencies:
2816+ eslint: '*'
2817+ eslint-plugin-import: '*'
2818+ eslint-plugin-import-x: '*'
2819+ peerDependenciesMeta:
2820+ eslint-plugin-import:
2821+ optional: true
2822+ eslint-plugin-import-x:
2823+ optional: true
2824+
2825+ eslint-module-utils@2.14.0:
2826+ resolution: {integrity: sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig==}
2827+ engines: {node: '>=4'}
2828+ peerDependencies:
2829+ '@typescript-eslint/parser': '*'
2830+ eslint: '*'
2831+ eslint-import-resolver-node: '*'
2832+ eslint-import-resolver-typescript: '*'
2833+ eslint-import-resolver-webpack: '*'
2834+ peerDependenciesMeta:
2835+ '@typescript-eslint/parser':
2836+ optional: true
2837+ eslint:
2838+ optional: true
2839+ eslint-import-resolver-node:
2840+ optional: true
2841+ eslint-import-resolver-typescript:
2842+ optional: true
2843+ eslint-import-resolver-webpack:
2844+ optional: true
2845+
2846+ eslint-plugin-import@2.32.0:
2847+ resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==}
2848+ engines: {node: '>=4'}
2849+ peerDependencies:
2850+ '@typescript-eslint/parser': '*'
2851+ eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9
2852+ peerDependenciesMeta:
2853+ '@typescript-eslint/parser':
2854+ optional: true
2855+
2856+ eslint-plugin-jsx-a11y@6.10.2:
2857+ resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==}
2858+ engines: {node: '>=4.0'}
2859+ peerDependencies:
2860+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9
2861+
2862+ eslint-plugin-react-hooks@7.1.1:
2863+ resolution: {integrity: sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==}
2864+ engines: {node: '>=18'}
2865+ peerDependencies:
2866+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0
2867+
2868+ eslint-plugin-react@7.37.5:
2869+ resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==}
2870+ engines: {node: '>=4'}
2871+ peerDependencies:
2872+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
2873+
2874+ eslint-scope@8.4.0:
2875+ resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
2876+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2877+
2878+ eslint-visitor-keys@3.4.3:
2879+ resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
2880+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
2881+
2882+ eslint-visitor-keys@4.2.1:
2883+ resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
2884+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2885+
2886+ eslint-visitor-keys@5.0.1:
2887+ resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==}
2888+ engines: {node: ^20.19.0 || ^22.13.0 || >=24}
2889+
2890+ eslint@9.39.5:
2891+ resolution: {integrity: sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==}
2892+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2893+ deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
2894+ hasBin: true
2895+ peerDependencies:
2896+ jiti: '*'
2897+ peerDependenciesMeta:
2898+ jiti:
2899+ optional: true
2900+
2901+ espree@10.4.0:
2902+ resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
2903+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2904+
2905+ esquery@1.7.0:
2906+ resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==}
2907+ engines: {node: '>=0.10'}
2908+
2909+ esrecurse@4.3.0:
2910+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
2911+ engines: {node: '>=4.0'}
2912+
2913+ estraverse@5.3.0:
2914+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
2915+ engines: {node: '>=4.0'}
2916+
2917+ estree-util-is-identifier-name@3.0.0:
2918+ resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
2919+
2920+ estree-walker@3.0.3:
2921+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
2922+
2923+ esutils@2.0.3:
2924+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
2925+ engines: {node: '>=0.10.0'}
2926+
2927+ eventemitter3@5.0.4:
2928+ resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==}
2929+
2930+ expect-type@1.4.0:
2931+ resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==}
2932+ engines: {node: '>=12.0.0'}
2933+
2934+ extend@3.0.2:
2935+ resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
2936+
2937+ fast-deep-equal@3.1.3:
2938+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
2939+
2940+ fast-glob@3.3.1:
2941+ resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
2942+ engines: {node: '>=8.6.0'}
2943+
2944+ fast-json-stable-stringify@2.1.0:
2945+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
2946+
2947+ fast-levenshtein@2.0.6:
2948+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
2949+
2950+ fast-sha256@1.3.0:
2951+ resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==}
2952+
2953+ fastq@1.20.3:
2954+ resolution: {integrity: sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==}
2955+
2956+ fdir@6.5.0:
2957+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
2958+ engines: {node: '>=12.0.0'}
2959+ peerDependencies:
2960+ picomatch: ^3 || ^4
2961+ peerDependenciesMeta:
2962+ picomatch:
2963+ optional: true
2964+
2965+ fetch-blob@3.2.0:
2966+ resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
2967+ engines: {node: ^12.20 || >= 14.13}
2968+
2969+ file-entry-cache@8.0.0:
2970+ resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
2971+ engines: {node: '>=16.0.0'}
2972+
2973+ fill-range@7.1.1:
2974+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
2975+ engines: {node: '>=8'}
2976+
2977+ find-up@5.0.0:
2978+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
2979+ engines: {node: '>=10'}
2980+
2981+ flat-cache@4.0.1:
2982+ resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
2983+ engines: {node: '>=16'}
2984+
2985+ flatted@3.4.4:
2986+ resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==}
2987+
2988+ for-each@0.3.5:
2989+ resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
2990+ engines: {node: '>= 0.4'}
2991+
2992+ formdata-polyfill@4.0.10:
2993+ resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
2994+ engines: {node: '>=12.20.0'}
2995+
2996+ framer-motion@12.43.0:
2997+ resolution: {integrity: sha512-1eaL3RvR/kAlbG7UYcpMptEyzPoENO0c6w7ZnB3/hh2vSAz/6uGAFn6fdoqTBguNstf3MsFhJHsD/0DHiclG+g==}
2998+ peerDependencies:
2999+ '@emotion/is-prop-valid': '*'
3000+ react: ^18.0.0 || ^19.0.0
3001+ react-dom: ^18.0.0 || ^19.0.0
3002+ peerDependenciesMeta:
3003+ '@emotion/is-prop-valid':
3004+ optional: true
3005+ react:
3006+ optional: true
3007+ react-dom:
3008+ optional: true
3009+
3010+ fsevents@2.3.3:
3011+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
3012+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
3013+ os: [darwin]
3014+
3015+ function-bind@1.1.2:
3016+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
3017+
3018+ function.prototype.name@1.2.0:
3019+ resolution: {integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==}
3020+ engines: {node: '>= 0.4'}
3021+
3022+ functions-have-names@1.2.3:
3023+ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
3024+
3025+ gaxios@7.3.1:
3026+ resolution: {integrity: sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==}
3027+ engines: {node: '>=18'}
3028+
3029+ gcp-metadata@8.1.2:
3030+ resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==}
3031+ engines: {node: '>=18'}
3032+
3033+ geist@1.7.2:
3034+ resolution: {integrity: sha512-Gu5lDFa3pLRyoBlBPf0QIFHVdWAnpco7fS1bJm41jyLPFoguBgiubseUN2oLXMgqZ7uxAxDoXcHMhCY/fOTTgg==}
3035+ peerDependencies:
3036+ next: '>=13.2.0'
3037+
3038+ generator-function@2.0.1:
3039+ resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
3040+ engines: {node: '>= 0.4'}
3041+
3042+ gensync@1.0.0-beta.2:
3043+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
3044+ engines: {node: '>=6.9.0'}
3045+
3046+ get-intrinsic@1.3.0:
3047+ resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
3048+ engines: {node: '>= 0.4'}
3049+
3050+ get-nonce@1.0.1:
3051+ resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
3052+ engines: {node: '>=6'}
3053+
3054+ get-proto@1.0.1:
3055+ resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
3056+ engines: {node: '>= 0.4'}
3057+
3058+ get-symbol-description@1.1.0:
3059+ resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
3060+ engines: {node: '>= 0.4'}
3061+
3062+ get-tsconfig@4.14.3:
3063+ resolution: {integrity: sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==}
3064+
3065+ glob-parent@5.1.2:
3066+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
3067+ engines: {node: '>= 6'}
3068+
3069+ glob-parent@6.0.2:
3070+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
3071+ engines: {node: '>=10.13.0'}
3072+
3073+ globals@14.0.0:
3074+ resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
3075+ engines: {node: '>=18'}
3076+
3077+ globals@16.4.0:
3078+ resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==}
3079+ engines: {node: '>=18'}
3080+
3081+ globalthis@1.0.4:
3082+ resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
3083+ engines: {node: '>= 0.4'}
3084+
3085+ google-auth-library@10.9.1:
3086+ resolution: {integrity: sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==}
3087+ engines: {node: '>=18'}
3088+
3089+ google-logging-utils@1.1.3:
3090+ resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==}
3091+ engines: {node: '>=14'}
3092+
3093+ gopd@1.2.0:
3094+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
3095+ engines: {node: '>= 0.4'}
3096+
3097+ graceful-fs@4.2.11:
3098+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
3099+
3100+ has-bigints@1.1.0:
3101+ resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
3102+ engines: {node: '>= 0.4'}
3103+
3104+ has-flag@4.0.0:
3105+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
3106+ engines: {node: '>=8'}
3107+
3108+ has-property-descriptors@1.0.2:
3109+ resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
3110+
3111+ has-proto@1.2.0:
3112+ resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==}
3113+ engines: {node: '>= 0.4'}
3114+
3115+ has-symbols@1.1.0:
3116+ resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
3117+ engines: {node: '>= 0.4'}
3118+
3119+ has-tostringtag@1.0.2:
3120+ resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
3121+ engines: {node: '>= 0.4'}
3122+
3123+ hasown@2.0.4:
3124+ resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==}
3125+ engines: {node: '>= 0.4'}
3126+
3127+ hast-util-from-parse5@8.0.3:
3128+ resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==}
3129+
3130+ hast-util-parse-selector@4.0.0:
3131+ resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
3132+
3133+ hast-util-raw@9.1.0:
3134+ resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==}
3135+
3136+ hast-util-to-html@9.0.5:
3137+ resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
3138+
3139+ hast-util-to-jsx-runtime@2.3.6:
3140+ resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
3141+
3142+ hast-util-to-parse5@8.0.1:
3143+ resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==}
3144+
3145+ hast-util-whitespace@3.0.0:
3146+ resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
3147+
3148+ hastscript@9.0.1:
3149+ resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}
3150+
3151+ hermes-estree@0.25.1:
3152+ resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==}
3153+
3154+ hermes-parser@0.25.1:
3155+ resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
3156+
3157+ html-url-attributes@3.0.1:
3158+ resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
3159+
3160+ html-void-elements@3.0.0:
3161+ resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
3162+
3163+ https-proxy-agent@7.0.6:
3164+ resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
3165+ engines: {node: '>= 14'}
3166+
3167+ ignore@5.3.2:
3168+ resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
3169+ engines: {node: '>= 4'}
3170+
3171+ ignore@7.0.8:
3172+ resolution: {integrity: sha512-YYNsSlXBjMk92SKnkwvB5LOVSa6OznlFUGcsvrFgNJbJCd0M1XKeFVRc8ZByeCqz32FivYNHJVooLmdqrmvp/Q==}
3173+ engines: {node: '>= 4'}
3174+
3175+ immer@11.1.18:
3176+ resolution: {integrity: sha512-EQyQtLiYW029lyoczMl/Hh4Xu7cDecSc58JRYpHyL4tIAu3eqd1yJzQX04d2BZHDkzFFvm6qJEJWOtfDSWAXbQ==}
3177+
3178+ import-fresh@3.3.1:
3179+ resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
3180+ engines: {node: '>=6'}
3181+
3182+ imurmurhash@0.1.4:
3183+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
3184+ engines: {node: '>=0.8.19'}
3185+
3186+ inline-style-parser@0.2.7:
3187+ resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
3188+
3189+ internal-slot@1.1.0:
3190+ resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
3191+ engines: {node: '>= 0.4'}
3192+
3193+ internmap@2.0.3:
3194+ resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
3195+ engines: {node: '>=12'}
3196+
3197+ is-alphabetical@2.0.1:
3198+ resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
3199+
3200+ is-alphanumerical@2.0.1:
3201+ resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
3202+
3203+ is-array-buffer@3.0.5:
3204+ resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
3205+ engines: {node: '>= 0.4'}
3206+
3207+ is-async-function@2.1.1:
3208+ resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==}
3209+ engines: {node: '>= 0.4'}
3210+
3211+ is-bigint@1.1.0:
3212+ resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
3213+ engines: {node: '>= 0.4'}
3214+
3215+ is-boolean-object@1.2.2:
3216+ resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
3217+ engines: {node: '>= 0.4'}
3218+
3219+ is-bun-module@2.0.0:
3220+ resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==}
3221+
3222+ is-callable@1.2.7:
3223+ resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
3224+ engines: {node: '>= 0.4'}
3225+
3226+ is-core-module@2.16.2:
3227+ resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==}
3228+ engines: {node: '>= 0.4'}
3229+
3230+ is-data-view@1.0.2:
3231+ resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==}
3232+ engines: {node: '>= 0.4'}
3233+
3234+ is-date-object@1.1.0:
3235+ resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
3236+ engines: {node: '>= 0.4'}
3237+
3238+ is-decimal@2.0.1:
3239+ resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
3240+
3241+ is-document.all@1.0.0:
3242+ resolution: {integrity: sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==}
3243+ engines: {node: '>= 0.4'}
3244+
3245+ is-extglob@2.1.1:
3246+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
3247+ engines: {node: '>=0.10.0'}
3248+
3249+ is-finalizationregistry@1.1.1:
3250+ resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
3251+ engines: {node: '>= 0.4'}
3252+
3253+ is-generator-function@1.1.2:
3254+ resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
3255+ engines: {node: '>= 0.4'}
3256+
3257+ is-glob@4.0.3:
3258+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
3259+ engines: {node: '>=0.10.0'}
3260+
3261+ is-hexadecimal@2.0.1:
3262+ resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
3263+
3264+ is-map@2.0.3:
3265+ resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
3266+ engines: {node: '>= 0.4'}
3267+
3268+ is-negative-zero@2.0.3:
3269+ resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
3270+ engines: {node: '>= 0.4'}
3271+
3272+ is-number-object@1.1.1:
3273+ resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
3274+ engines: {node: '>= 0.4'}
3275+
3276+ is-number@7.0.0:
3277+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
3278+ engines: {node: '>=0.12.0'}
3279+
3280+ is-plain-obj@4.1.0:
3281+ resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
3282+ engines: {node: '>=12'}
3283+
3284+ is-regex@1.2.1:
3285+ resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
3286+ engines: {node: '>= 0.4'}
3287+
3288+ is-set@2.0.3:
3289+ resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==}
3290+ engines: {node: '>= 0.4'}
3291+
3292+ is-shared-array-buffer@1.0.4:
3293+ resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
3294+ engines: {node: '>= 0.4'}
3295+
3296+ is-string@1.1.1:
3297+ resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
3298+ engines: {node: '>= 0.4'}
3299+
3300+ is-symbol@1.1.1:
3301+ resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==}
3302+ engines: {node: '>= 0.4'}
3303+
3304+ is-typed-array@1.1.15:
3305+ resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
3306+ engines: {node: '>= 0.4'}
3307+
3308+ is-weakmap@2.0.2:
3309+ resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
3310+ engines: {node: '>= 0.4'}
3311+
3312+ is-weakref@1.1.1:
3313+ resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==}
3314+ engines: {node: '>= 0.4'}
3315+
3316+ is-weakset@2.0.4:
3317+ resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
3318+ engines: {node: '>= 0.4'}
3319+
3320+ isarray@2.0.5:
3321+ resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
3322+
3323+ isexe@2.0.0:
3324+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
3325+
3326+ iterator.prototype@1.1.5:
3327+ resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
3328+ engines: {node: '>= 0.4'}
3329+
3330+ jiti@2.7.0:
3331+ resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
3332+ hasBin: true
3333+
3334+ jose@6.2.12:
3335+ resolution: {integrity: sha512-9NiFmJEex0sy2Dk58j2UGBSHgUs2ypF9eZSu4L6vjOX3Dp96Sw1F3uL+H+D1sx02jZZdzUT0HgvCy59CuvXcWw==}
3336+
3337+ js-tokens@4.0.0:
3338+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
3339+
3340+ js-tokens@9.0.1:
3341+ resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
3342+
3343+ js-yaml@4.3.2:
3344+ resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==}
3345+ hasBin: true
3346+
3347+ jsesc@3.1.0:
3348+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
3349+ engines: {node: '>=6'}
3350+ hasBin: true
3351+
3352+ json-bigint@1.0.0:
3353+ resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==}
3354+
3355+ json-buffer@3.0.1:
3356+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
3357+
3358+ json-schema-to-ts@3.1.1:
3359+ resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==}
3360+ engines: {node: '>=16'}
3361+
3362+ json-schema-traverse@0.4.1:
3363+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
3364+
3365+ json-stable-stringify-without-jsonify@1.0.1:
3366+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
3367+
3368+ json5@1.0.2:
3369+ resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
3370+ hasBin: true
3371+
3372+ json5@2.2.3:
3373+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
3374+ engines: {node: '>=6'}
3375+ hasBin: true
3376+
3377+ jsx-ast-utils@3.3.5:
3378+ resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
3379+ engines: {node: '>=4.0'}
3380+
3381+ jwa@2.0.1:
3382+ resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
3383+
3384+ jws@4.0.1:
3385+ resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==}
3386+
3387+ keyv@4.5.4:
3388+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
3389+
3390+ kysely@0.29.5:
3391+ resolution: {integrity: sha512-ooa+eSbBNPTo3MycPEuW5jdrxQdQwdtB3LC3h43FiXQbIry5tR0C5lDG7eealK0E4D7XjrnOP5DIUg/LyjRMYQ==}
3392+ engines: {node: '>=22.0.0'}
3393+
3394+ language-subtag-registry@0.3.23:
3395+ resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==}
3396+
3397+ language-tags@1.0.9:
3398+ resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==}
3399+ engines: {node: '>=0.10'}
3400+
3401+ levn@0.4.1:
3402+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
3403+ engines: {node: '>= 0.8.0'}
3404+
3405+ lightningcss-android-arm64@1.32.0:
3406+ resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
3407+ engines: {node: '>= 12.0.0'}
3408+ cpu: [arm64]
3409+ os: [android]
3410+
3411+ lightningcss-darwin-arm64@1.32.0:
3412+ resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
3413+ engines: {node: '>= 12.0.0'}
3414+ cpu: [arm64]
3415+ os: [darwin]
3416+
3417+ lightningcss-darwin-x64@1.32.0:
3418+ resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
3419+ engines: {node: '>= 12.0.0'}
3420+ cpu: [x64]
3421+ os: [darwin]
3422+
3423+ lightningcss-freebsd-x64@1.32.0:
3424+ resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
3425+ engines: {node: '>= 12.0.0'}
3426+ cpu: [x64]
3427+ os: [freebsd]
3428+
3429+ lightningcss-linux-arm-gnueabihf@1.32.0:
3430+ resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
3431+ engines: {node: '>= 12.0.0'}
3432+ cpu: [arm]
3433+ os: [linux]
3434+
3435+ lightningcss-linux-arm64-gnu@1.32.0:
3436+ resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
3437+ engines: {node: '>= 12.0.0'}
3438+ cpu: [arm64]
3439+ os: [linux]
3440+ libc: [glibc]
3441+
3442+ lightningcss-linux-arm64-musl@1.32.0:
3443+ resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
3444+ engines: {node: '>= 12.0.0'}
3445+ cpu: [arm64]
3446+ os: [linux]
3447+ libc: [musl]
3448+
3449+ lightningcss-linux-x64-gnu@1.32.0:
3450+ resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
3451+ engines: {node: '>= 12.0.0'}
3452+ cpu: [x64]
3453+ os: [linux]
3454+ libc: [glibc]
3455+
3456+ lightningcss-linux-x64-musl@1.32.0:
3457+ resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
3458+ engines: {node: '>= 12.0.0'}
3459+ cpu: [x64]
3460+ os: [linux]
3461+ libc: [musl]
3462+
3463+ lightningcss-win32-arm64-msvc@1.32.0:
3464+ resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
3465+ engines: {node: '>= 12.0.0'}
3466+ cpu: [arm64]
3467+ os: [win32]
3468+
3469+ lightningcss-win32-x64-msvc@1.32.0:
3470+ resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
3471+ engines: {node: '>= 12.0.0'}
3472+ cpu: [x64]
3473+ os: [win32]
3474+
3475+ lightningcss@1.32.0:
3476+ resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
3477+ engines: {node: '>= 12.0.0'}
3478+
3479+ locate-path@6.0.0:
3480+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
3481+ engines: {node: '>=10'}
3482+
3483+ lodash.merge@4.6.2:
3484+ resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
3485+
3486+ long@5.3.2:
3487+ resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
3488+
3489+ longest-streak@3.1.0:
3490+ resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
3491+
3492+ loose-envify@1.4.0:
3493+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
3494+ hasBin: true
3495+
3496+ loupe@3.2.1:
3497+ resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
3498+
3499+ lru-cache@5.1.1:
3500+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
3501+
3502+ lucide-react@1.42.0:
3503+ resolution: {integrity: sha512-b3jprplnoLS8n5etw1z8xODe3hF/yjKATrTitsrKrnjUhCef5BdDct6Ppv3zVvzFwmtfWgLO6XNM3C9fAD93ug==}
3504+ peerDependencies:
3505+ react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
3506+
3507+ magic-string@0.30.21:
3508+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
3509+
3510+ markdown-table@3.0.4:
3511+ resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
3512+
3513+ math-intrinsics@1.1.0:
3514+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
3515+ engines: {node: '>= 0.4'}
3516+
3517+ mdast-util-find-and-replace@3.0.2:
3518+ resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
3519+
3520+ mdast-util-from-markdown@2.0.3:
3521+ resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==}
3522+
3523+ mdast-util-gfm-autolink-literal@2.0.1:
3524+ resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}
3525+
3526+ mdast-util-gfm-footnote@2.1.0:
3527+ resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==}
3528+
3529+ mdast-util-gfm-strikethrough@2.0.0:
3530+ resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
3531+
3532+ mdast-util-gfm-table@2.0.0:
3533+ resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
3534+
3535+ mdast-util-gfm-task-list-item@2.0.0:
3536+ resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
3537+
3538+ mdast-util-gfm@3.1.0:
3539+ resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==}
3540+
3541+ mdast-util-mdx-expression@2.0.1:
3542+ resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
3543+
3544+ mdast-util-mdx-jsx@3.2.0:
3545+ resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
3546+
3547+ mdast-util-mdxjs-esm@2.0.1:
3548+ resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
3549+
3550+ mdast-util-phrasing@4.1.0:
3551+ resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
3552+
3553+ mdast-util-to-hast@13.2.1:
3554+ resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}
3555+
3556+ mdast-util-to-markdown@2.1.2:
3557+ resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
3558+
3559+ mdast-util-to-string@4.0.0:
3560+ resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
3561+
3562+ merge2@1.4.1:
3563+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
3564+ engines: {node: '>= 8'}
3565+
3566+ micromark-core-commonmark@2.0.3:
3567+ resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
3568+
3569+ micromark-extension-gfm-autolink-literal@2.1.0:
3570+ resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==}
3571+
3572+ micromark-extension-gfm-footnote@2.1.0:
3573+ resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==}
3574+
3575+ micromark-extension-gfm-strikethrough@2.1.0:
3576+ resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==}
3577+
3578+ micromark-extension-gfm-table@2.1.1:
3579+ resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==}
3580+
3581+ micromark-extension-gfm-tagfilter@2.0.0:
3582+ resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
3583+
3584+ micromark-extension-gfm-task-list-item@2.1.0:
3585+ resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==}
3586+
3587+ micromark-extension-gfm@3.0.0:
3588+ resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
3589+
3590+ micromark-factory-destination@2.0.1:
3591+ resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
3592+
3593+ micromark-factory-label@2.0.1:
3594+ resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
3595+
3596+ micromark-factory-space@2.0.1:
3597+ resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
3598+
3599+ micromark-factory-title@2.0.1:
3600+ resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==}
3601+
3602+ micromark-factory-whitespace@2.0.1:
3603+ resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==}
3604+
3605+ micromark-util-character@2.1.1:
3606+ resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
3607+
3608+ micromark-util-chunked@2.0.1:
3609+ resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==}
3610+
3611+ micromark-util-classify-character@2.0.1:
3612+ resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==}
3613+
3614+ micromark-util-combine-extensions@2.0.1:
3615+ resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==}
3616+
3617+ micromark-util-decode-numeric-character-reference@2.0.2:
3618+ resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==}
3619+
3620+ micromark-util-decode-string@2.0.1:
3621+ resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==}
3622+
3623+ micromark-util-encode@2.0.1:
3624+ resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
3625+
3626+ micromark-util-html-tag-name@2.0.1:
3627+ resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
3628+
3629+ micromark-util-normalize-identifier@2.0.1:
3630+ resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==}
3631+
3632+ micromark-util-resolve-all@2.0.1:
3633+ resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==}
3634+
3635+ micromark-util-sanitize-uri@2.0.1:
3636+ resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
3637+
3638+ micromark-util-subtokenize@2.1.0:
3639+ resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==}
3640+
3641+ micromark-util-symbol@2.0.1:
3642+ resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
3643+
3644+ micromark-util-types@2.0.2:
3645+ resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
3646+
3647+ micromark@4.0.2:
3648+ resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
3649+
3650+ micromatch@4.0.8:
3651+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
3652+ engines: {node: '>=8.6'}
3653+
3654+ minimatch@10.2.6:
3655+ resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==}
3656+ engines: {node: 18 || 20 || >=22}
3657+
3658+ minimatch@3.1.5:
3659+ resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==}
3660+
3661+ minimist@1.2.8:
3662+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
3663+
3664+ motion-dom@12.43.0:
3665+ resolution: {integrity: sha512-azKON4d9S65PEoFUiQTMTgPheEmzf2QngdRc50AKfJp9Q9mmcBVw22c8eMq9k8kxOFHdL7+WZY7N/5F/lwiDag==}
3666+
3667+ motion-utils@12.39.0:
3668+ resolution: {integrity: sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==}
3669+
3670+ motion@12.43.0:
3671+ resolution: {integrity: sha512-BQgQbSa9Hn3/mtbib0MK53y6JSANa+YKUKlaYnWzAVDH424RYQ5LVpV3pNiWH00BA2z4ojsSdMzqT7g2FQwjuQ==}
3672+ peerDependencies:
3673+ '@emotion/is-prop-valid': '*'
3674+ react: ^18.0.0 || ^19.0.0
3675+ react-dom: ^18.0.0 || ^19.0.0
3676+ peerDependenciesMeta:
3677+ '@emotion/is-prop-valid':
3678+ optional: true
3679+ react:
3680+ optional: true
3681+ react-dom:
3682+ optional: true
3683+
3684+ ms@2.1.3:
3685+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
3686+
3687+ nanoid@3.3.18:
3688+ resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==}
3689+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
3690+ hasBin: true
3691+
3692+ nanostores@1.5.3:
3693+ resolution: {integrity: sha512-rQLB6eV4f2AW/n3L0JmwCROpaisYy9EDEADvEFSd1C/qG8hB6O5TPlh9A791JRbJr4CnMQBzptDcvD9OR1+6WA==}
3694+ engines: {node: ^20.0.0 || >=22.0.0}
3695+
3696+ napi-postinstall@0.3.4:
3697+ resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==}
3698+ engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
3699+ hasBin: true
3700+
3701+ natural-compare@1.4.0:
3702+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
3703+
3704+ next-themes@0.4.6:
3705+ resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==}
3706+ peerDependencies:
3707+ react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
3708+ react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
3709+
3710+ next@16.3.4:
3711+ resolution: {integrity: sha512-/Ztf6CeRH+ejEXUrYtqI4gkS66eFIHuSwqi60RgcpWKodxFZx2/dqVCMKBwILfAHXQ+F1b1vAudgj3mnxqtoIA==}
3712+ engines: {node: '>=20.9.0'}
3713+ hasBin: true
3714+ peerDependencies:
3715+ '@opentelemetry/api': ^1.1.0
3716+ '@playwright/test': ^1.51.1
3717+ babel-plugin-react-compiler: '*'
3718+ react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
3719+ react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
3720+ sass: ^1.3.0
3721+ peerDependenciesMeta:
3722+ '@opentelemetry/api':
3723+ optional: true
3724+ '@playwright/test':
3725+ optional: true
3726+ babel-plugin-react-compiler:
3727+ optional: true
3728+ sass:
3729+ optional: true
3730+
3731+ node-addon-api@8.9.2:
3732+ resolution: {integrity: sha512-VijLXbi3UACN69I0JVXJsX4tjACjNoQDgv2gTF6sx2wWEi8tkSg2eX8p5gSIFi8z2+DL3oHmY6OyKce38SDolg==}
3733+ engines: {node: ^18 || ^20 || >= 21}
3734+
3735+ node-domexception@1.0.0:
3736+ resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
3737+ engines: {node: '>=10.5.0'}
3738+ deprecated: Use your platform's native DOMException instead
3739+
3740+ node-exports-info@1.6.2:
3741+ resolution: {integrity: sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==}
3742+ engines: {node: '>= 0.4'}
3743+
3744+ node-fetch@3.3.2:
3745+ resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
3746+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
3747+
3748+ node-gyp-build@4.8.4:
3749+ resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==}
3750+ hasBin: true
3751+
3752+ node-releases@2.0.54:
3753+ resolution: {integrity: sha512-YHs7BmmcsdAI5Ozuf8JZo6PT0mv2GIWC9vMfvUC3dp65M8hn7Ux8CPL+2oBI7juNuj9d0ndhTcznq2ODBps9cQ==}
3754+ engines: {node: '>=18'}
3755+
3756+ object-assign@4.1.1:
3757+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
3758+ engines: {node: '>=0.10.0'}
3759+
3760+ object-inspect@1.13.4:
3761+ resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
3762+ engines: {node: '>= 0.4'}
3763+
3764+ object-keys@1.1.1:
3765+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
3766+ engines: {node: '>= 0.4'}
3767+
3768+ object.assign@4.1.7:
3769+ resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==}
3770+ engines: {node: '>= 0.4'}
3771+
3772+ object.entries@1.1.9:
3773+ resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==}
3774+ engines: {node: '>= 0.4'}
3775+
3776+ object.fromentries@2.0.8:
3777+ resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==}
3778+ engines: {node: '>= 0.4'}
3779+
3780+ object.groupby@1.0.3:
3781+ resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==}
3782+ engines: {node: '>= 0.4'}
3783+
3784+ object.values@1.2.1:
3785+ resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
3786+ engines: {node: '>= 0.4'}
3787+
3788+ oniguruma-parser@0.12.2:
3789+ resolution: {integrity: sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==}
3790+
3791+ oniguruma-to-es@4.3.6:
3792+ resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==}
3793+
3794+ openai@7.10.0:
3795+ resolution: {integrity: sha512-sn9t2Kls7O52PwuF9BUTYNu4Gk/r0lXJyrgaNht4TNRlZFb3dJIGO0RciSgjARGCBRtWjySubAQFJttlzUvGQQ==}
3796+ engines: {node: '>=22.0.0'}
3797+ peerDependencies:
3798+ '@aws-sdk/credential-provider-node': '>=3.972.0 <4'
3799+ '@smithy/hash-node': '>=4.3.0 <5'
3800+ '@smithy/signature-v4': '>=5.4.0 <6'
3801+ undici: '>=5 <9'
3802+ ws: ^8.21.0
3803+ zod: ^3.25 || ^4.0
3804+ peerDependenciesMeta:
3805+ '@aws-sdk/credential-provider-node':
3806+ optional: true
3807+ '@smithy/hash-node':
3808+ optional: true
3809+ '@smithy/signature-v4':
3810+ optional: true
3811+ undici:
3812+ optional: true
3813+ ws:
3814+ optional: true
3815+ zod:
3816+ optional: true
3817+
3818+ optionator@0.9.4:
3819+ resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
3820+ engines: {node: '>= 0.8.0'}
3821+
3822+ own-keys@1.0.2:
3823+ resolution: {integrity: sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==}
3824+ engines: {node: '>= 0.4'}
3825+
3826+ p-limit@3.1.0:
3827+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
3828+ engines: {node: '>=10'}
3829+
3830+ p-locate@5.0.0:
3831+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
3832+ engines: {node: '>=10'}
3833+
3834+ p-retry@4.6.2:
3835+ resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==}
3836+ engines: {node: '>=8'}
3837+
3838+ parent-module@1.0.1:
3839+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
3840+ engines: {node: '>=6'}
3841+
3842+ parse-entities@4.0.2:
3843+ resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
3844+
3845+ parse5@7.3.0:
3846+ resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
3847+
3848+ path-exists@4.0.0:
3849+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
3850+ engines: {node: '>=8'}
3851+
3852+ path-key@3.1.1:
3853+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
3854+ engines: {node: '>=8'}
3855+
3856+ path-parse@1.0.7:
3857+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
3858+
3859+ pathe@2.0.3:
3860+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
3861+
3862+ pathval@2.0.1:
3863+ resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==}
3864+ engines: {node: '>= 14.16'}
3865+
3866+ pg-cloudflare@1.4.0:
3867+ resolution: {integrity: sha512-Vo7z/6rrQYxpNRylp4Tlob2elzbh+N/MOQbxFVWCxS7oEx6jF53GTJFxK2WWpKuBRkmiin4Mt+xofFDjx09R0A==}
3868+
3869+ pg-connection-string@2.14.0:
3870+ resolution: {integrity: sha512-XwWDGcLRGCXAR8F/AM5bG7Q+A3Wm2s6QeEjlOKZLlH3UYcguiqCWKyWXVag5TLTIjR7oOJUY8kcADaZgWPyLeg==}
3871+
3872+ pg-int8@1.0.1:
3873+ resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
3874+ engines: {node: '>=4.0.0'}
3875+
3876+ pg-pool@3.14.0:
3877+ resolution: {integrity: sha512-gKtPkFdQPU3DksooVLi9LsjZxrsBUZIpa+7aVx+LV5pNh0KzP4Zleud2po+ConrxbuXGBJ6Hfer6hdgpIBpBaw==}
3878+ peerDependencies:
3879+ pg: '>=8.0'
3880+
3881+ pg-protocol@1.16.0:
3882+ resolution: {integrity: sha512-sILXutLVjCLjcDuOmvhX5e2Z4cS5qG/6Bu3VkpFwdf/633ElGLpEh9bgmuI5I4sqKqkifQiGyiCcx1HdtrK7tg==}
3883+
3884+ pg-types@2.2.0:
3885+ resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
3886+ engines: {node: '>=4'}
3887+
3888+ pg@8.23.0:
3889+ resolution: {integrity: sha512-Ip2EQCngowJLGOfCwkFhPXU7/ljlhn6Rxlmy4XYfL2Y+vyRM59+8uR2xqRWKdYmbXmxCFOAmKxBuSUCdF34qLg==}
3890+ engines: {node: '>= 16.0.0'}
3891+ peerDependencies:
3892+ pg-native: '>=3.0.1'
3893+ peerDependenciesMeta:
3894+ pg-native:
3895+ optional: true
3896+
3897+ pgpass@1.0.5:
3898+ resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
3899+
3900+ picocolors@1.1.1:
3901+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
3902+
3903+ picomatch@2.3.2:
3904+ resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==}
3905+ engines: {node: '>=8.6'}
3906+
3907+ picomatch@4.0.7:
3908+ resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==}
3909+ engines: {node: '>=12'}
3910+
3911+ playwright-core@1.63.0:
3912+ resolution: {integrity: sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg==}
3913+ engines: {node: '>=20'}
3914+ hasBin: true
3915+
3916+ playwright@1.63.0:
3917+ resolution: {integrity: sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg==}
3918+ engines: {node: '>=20'}
3919+ hasBin: true
3920+
3921+ possible-typed-array-names@1.1.0:
3922+ resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
3923+ engines: {node: '>= 0.4'}
3924+
3925+ postal-mime@2.7.5:
3926+ resolution: {integrity: sha512-GNEXKvWFQnbgO5NlrGzVa0FmWzBZ24PersAWErttSg1Hjpf0ATxTwS5DOMGaOpTG6bUh5cTr7xi0jAD942wCJA==}
3927+
3928+ postcss@8.5.23:
3929+ resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==}
3930+ engines: {node: ^10 || ^12 || >=14}
3931+
3932+ postcss@8.5.28:
3933+ resolution: {integrity: sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==}
3934+ engines: {node: ^10 || ^12 || >=14}
3935+
3936+ postgres-array@2.0.0:
3937+ resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
3938+ engines: {node: '>=4'}
3939+
3940+ postgres-bytea@1.0.1:
3941+ resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==}
3942+ engines: {node: '>=0.10.0'}
3943+
3944+ postgres-date@1.0.7:
3945+ resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
3946+ engines: {node: '>=0.10.0'}
3947+
3948+ postgres-interval@1.2.0:
3949+ resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
3950+ engines: {node: '>=0.10.0'}
3951+
3952+ prelude-ls@1.2.1:
3953+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
3954+ engines: {node: '>= 0.8.0'}
3955+
3956+ prop-types@15.8.1:
3957+ resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
3958+
3959+ property-information@7.2.0:
3960+ resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==}
3961+
3962+ protobufjs@7.6.6:
3963+ resolution: {integrity: sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==}
3964+ engines: {node: '>=12.0.0'}
3965+
3966+ punycode@2.3.1:
3967+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
3968+ engines: {node: '>=6'}
3969+
3970+ queue-microtask@1.2.3:
3971+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
3972+
3973+ react-dom@19.2.8:
3974+ resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==}
3975+ peerDependencies:
3976+ react: ^19.2.8
3977+
3978+ react-is@16.13.1:
3979+ resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
3980+
3981+ react-markdown@10.1.0:
3982+ resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==}
3983+ peerDependencies:
3984+ '@types/react': '>=18'
3985+ react: '>=18'
3986+
3987+ react-redux@9.3.0:
3988+ resolution: {integrity: sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==}
3989+ peerDependencies:
3990+ '@types/react': ^18.2.25 || ^19
3991+ react: ^18.0 || ^19
3992+ redux: ^5.0.0
3993+ peerDependenciesMeta:
3994+ '@types/react':
3995+ optional: true
3996+ redux:
3997+ optional: true
3998+
3999+ react-remove-scroll-bar@2.3.8:
4000+ resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==}
4001+ engines: {node: '>=10'}
4002+ peerDependencies:
4003+ '@types/react': '*'
4004+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
4005+ peerDependenciesMeta:
4006+ '@types/react':
4007+ optional: true
4008+
4009+ react-remove-scroll@2.7.2:
4010+ resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==}
4011+ engines: {node: '>=10'}
4012+ peerDependencies:
4013+ '@types/react': '*'
4014+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
4015+ peerDependenciesMeta:
4016+ '@types/react':
4017+ optional: true
4018+
4019+ react-style-singleton@2.2.3:
4020+ resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
4021+ engines: {node: '>=10'}
4022+ peerDependencies:
4023+ '@types/react': '*'
4024+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
4025+ peerDependenciesMeta:
4026+ '@types/react':
4027+ optional: true
4028+
4029+ react@19.2.8:
4030+ resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==}
4031+ engines: {node: '>=0.10.0'}
4032+
4033+ recharts@3.10.1:
4034+ resolution: {integrity: sha512-QXFrvt6IVcw7eeZCoyXTwkIJAX3Dv1nyVhMicXJ47GsGDDpcN8z6o644DibE9XjpBTThtsomLKnTV6lc+cVFUA==}
4035+ engines: {node: '>=18'}
4036+ peerDependencies:
4037+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
4038+ react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
4039+ react-is: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
4040+
4041+ redux-thunk@3.1.0:
4042+ resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==}
4043+ peerDependencies:
4044+ redux: ^5.0.0
4045+
4046+ redux@5.0.1:
4047+ resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==}
4048+
4049+ reflect.getprototypeof@1.0.10:
4050+ resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
4051+ engines: {node: '>= 0.4'}
4052+
4053+ regex-recursion@6.0.2:
4054+ resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
4055+
4056+ regex-utilities@2.3.0:
4057+ resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==}
4058+
4059+ regex@6.1.0:
4060+ resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==}
4061+
4062+ regexp.prototype.flags@1.5.4:
4063+ resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
4064+ engines: {node: '>= 0.4'}
4065+
4066+ rehype-raw@7.0.0:
4067+ resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==}
4068+
4069+ remark-gfm@4.0.1:
4070+ resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
4071+
4072+ remark-parse@11.0.0:
4073+ resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
4074+
4075+ remark-rehype@11.1.2:
4076+ resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
4077+
4078+ remark-stringify@11.0.0:
4079+ resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
4080+
4081+ reselect@5.2.0:
4082+ resolution: {integrity: sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==}
4083+
4084+ resend@6.26.0:
4085+ resolution: {integrity: sha512-vkrULozV5nGF8o7tyun/t0+qFgtPpn+cyRhVqeorhOsPUNDiSc/9p/pn8AprdHqJpYaTvftpnQgWurW++FkCdw==}
4086+ engines: {node: '>=20'}
4087+ peerDependencies:
4088+ '@react-email/render': '*'
4089+ peerDependenciesMeta:
4090+ '@react-email/render':
4091+ optional: true
4092+
4093+ resolve-from@4.0.0:
4094+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
4095+ engines: {node: '>=4'}
4096+
4097+ resolve-pkg-maps@1.0.0:
4098+ resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
4099+
4100+ resolve@2.0.0-next.7:
4101+ resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==}
4102+ engines: {node: '>= 0.4'}
4103+ hasBin: true
4104+
4105+ retry@0.13.1:
4106+ resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
4107+ engines: {node: '>= 4'}
4108+
4109+ reusify@1.1.0:
4110+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
4111+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
4112+
4113+ rollup@4.63.1:
4114+ resolution: {integrity: sha512-3Df9jsstwhccuEfmAMi9l8XUh/GOkVObmFTU7CCVBysEbcOZLl84jCtaAZMcPiMz2EGKsATzQcU+Xr3n/wU6cg==}
4115+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
4116+ hasBin: true
4117+
4118+ rou3@0.9.2:
4119+ resolution: {integrity: sha512-3SOzvaAg8rkHrXtRjpCvCvbyO5to9oOO27Z/XqHEYXfMRVSw/qMIVdmaOk9W2lcRLtR6dlqTjo9hDeJk70QBYQ==}
4120+
4121+ run-parallel@1.2.0:
4122+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
4123+
4124+ safe-array-concat@1.1.4:
4125+ resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==}
4126+ engines: {node: '>=0.4'}
4127+
4128+ safe-buffer@5.2.1:
4129+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
4130+
4131+ safe-push-apply@1.0.0:
4132+ resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
4133+ engines: {node: '>= 0.4'}
4134+
4135+ safe-regex-test@1.1.0:
4136+ resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
4137+ engines: {node: '>= 0.4'}
4138+
4139+ scheduler@0.27.0:
4140+ resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
4141+
4142+ semver@6.3.1:
4143+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
4144+ hasBin: true
4145+
4146+ semver@7.8.5:
4147+ resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==}
4148+ engines: {node: '>=10'}
4149+ hasBin: true
4150+
4151+ server-only@0.0.1:
4152+ resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
4153+
4154+ set-cookie-parser@3.1.2:
4155+ resolution: {integrity: sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw==}
4156+
4157+ set-function-length@1.2.2:
4158+ resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
4159+ engines: {node: '>= 0.4'}
4160+
4161+ set-function-name@2.0.2:
4162+ resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
4163+ engines: {node: '>= 0.4'}
4164+
4165+ set-proto@1.0.0:
4166+ resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
4167+ engines: {node: '>= 0.4'}
4168+
4169+ sharp@0.35.4:
4170+ resolution: {integrity: sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==}
4171+ engines: {node: '>=20.9.0'}
4172+ peerDependencies:
4173+ '@types/node': '*'
4174+ peerDependenciesMeta:
4175+ '@types/node':
4176+ optional: true
4177+
4178+ shebang-command@2.0.0:
4179+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
4180+ engines: {node: '>=8'}
4181+
4182+ shebang-regex@3.0.0:
4183+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
4184+ engines: {node: '>=8'}
4185+
4186+ shiki@4.4.3:
4187+ resolution: {integrity: sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==}
4188+ engines: {node: '>=20'}
4189+
4190+ side-channel-list@1.0.1:
4191+ resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==}
4192+ engines: {node: '>= 0.4'}
4193+
4194+ side-channel-map@1.0.1:
4195+ resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
4196+ engines: {node: '>= 0.4'}
4197+
4198+ side-channel-weakmap@1.0.2:
4199+ resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
4200+ engines: {node: '>= 0.4'}
4201+
4202+ side-channel@1.1.1:
4203+ resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==}
4204+ engines: {node: '>= 0.4'}
4205+
4206+ siginfo@2.0.0:
4207+ resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
4208+
4209+ source-map-js@1.2.1:
4210+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
4211+ engines: {node: '>=0.10.0'}
4212+
4213+ source-map-support@0.5.21:
4214+ resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
4215+
4216+ source-map@0.6.1:
4217+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
4218+ engines: {node: '>=0.10.0'}
4219+
4220+ space-separated-tokens@2.0.2:
4221+ resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
4222+
4223+ split2@4.2.0:
4224+ resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
4225+ engines: {node: '>= 10.x'}
4226+
4227+ stable-hash@0.0.5:
4228+ resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
4229+
4230+ stackback@0.0.2:
4231+ resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
4232+
4233+ standardwebhooks@1.0.0:
4234+ resolution: {integrity: sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==}
4235+
4236+ standardwebhooks@1.1.1:
4237+ resolution: {integrity: sha512-bCbX9ZEyFkWPsRz7Bl3NuQUJohmwGSev/yhr7vhaGPlc4AfIrspIRa6cPTBuI1ItmrTDJ4d/S2hCsfe4+vQGnQ==}
4238+
4239+ std-env@3.10.0:
4240+ resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
4241+
4242+ stop-iteration-iterator@1.1.0:
4243+ resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
4244+ engines: {node: '>= 0.4'}
4245+
4246+ string.prototype.includes@2.0.1:
4247+ resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==}
4248+ engines: {node: '>= 0.4'}
4249+
4250+ string.prototype.matchall@4.1.0:
4251+ resolution: {integrity: sha512-tHNHTxInrYLCga9O9YGxWA3G9/nnzQw8UGAyqGx3Ar1pSTTzIuM4woFSq4SowkXCjJIwq5sIiQvEfRI9tCH1qQ==}
4252+ engines: {node: '>= 0.4'}
4253+
4254+ string.prototype.repeat@1.0.0:
4255+ resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==}
4256+
4257+ string.prototype.trim@1.2.11:
4258+ resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==}
4259+ engines: {node: '>= 0.4'}
4260+
4261+ string.prototype.trimend@1.0.10:
4262+ resolution: {integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==}
4263+ engines: {node: '>= 0.4'}
4264+
4265+ string.prototype.trimstart@1.0.8:
4266+ resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
4267+ engines: {node: '>= 0.4'}
4268+
4269+ stringify-entities@4.0.4:
4270+ resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
4271+
4272+ strip-bom@3.0.0:
4273+ resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
4274+ engines: {node: '>=4'}
4275+
4276+ strip-json-comments@3.1.1:
4277+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
4278+ engines: {node: '>=8'}
4279+
4280+ strip-literal@3.1.0:
4281+ resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
4282+
4283+ style-to-js@1.1.21:
4284+ resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==}
4285+
4286+ style-to-object@1.0.14:
4287+ resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
4288+
4289+ styled-jsx@5.1.6:
4290+ resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
4291+ engines: {node: '>= 12.0.0'}
4292+ peerDependencies:
4293+ '@babel/core': '*'
4294+ babel-plugin-macros: '*'
4295+ react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0'
4296+ peerDependenciesMeta:
4297+ '@babel/core':
4298+ optional: true
4299+ babel-plugin-macros:
4300+ optional: true
4301+
4302+ supports-color@7.2.0:
4303+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
4304+ engines: {node: '>=8'}
4305+
4306+ supports-preserve-symlinks-flag@1.0.0:
4307+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
4308+ engines: {node: '>= 0.4'}
4309+
4310+ swr@2.5.1:
4311+ resolution: {integrity: sha512-BRw55e8r0B7SpDN20CAzoQAHl7y1yP7/Zt7oqUjMv0vSt2u2Xnkm88Ws+VypbV9BXHQVuSuyVq7zMjO16wSExw==}
4312+ peerDependencies:
4313+ react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
4314+
4315+ tailwind-merge@3.6.0:
4316+ resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==}
4317+
4318+ tailwindcss@4.3.3:
4319+ resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==}
4320+
4321+ tapable@2.3.3:
4322+ resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==}
4323+ engines: {node: '>=6'}
4324+
4325+ tiny-invariant@1.3.3:
4326+ resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
4327+
4328+ tinybench@2.9.0:
4329+ resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
4330+
4331+ tinyexec@0.3.2:
4332+ resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
4333+
4334+ tinyglobby@0.2.17:
4335+ resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
4336+ engines: {node: '>=12.0.0'}
4337+
4338+ tinypool@1.1.1:
4339+ resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
4340+ engines: {node: ^18.0.0 || >=20.0.0}
4341+
4342+ tinyrainbow@2.0.0:
4343+ resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
4344+ engines: {node: '>=14.0.0'}
4345+
4346+ tinyspy@4.0.6:
4347+ resolution: {integrity: sha512-u8KszXvGfU68hVcZpRHKG28T0krMuv2G5nDhiHaMLen/gIuFEgIJhaJuO69qjnXg5paSrbPMFfx3brNuN8eVSg==}
4348+ engines: {node: '>=14.0.0'}
4349+
4350+ to-regex-range@5.0.1:
4351+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
4352+ engines: {node: '>=8.0'}
4353+
4354+ trim-lines@3.0.1:
4355+ resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
4356+
4357+ trough@2.2.0:
4358+ resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
4359+
4360+ ts-algebra@2.0.0:
4361+ resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==}
4362+
4363+ ts-api-utils@2.5.0:
4364+ resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==}
4365+ engines: {node: '>=18.12'}
4366+ peerDependencies:
4367+ typescript: '>=4.8.4'
4368+
4369+ tsconfig-paths@3.15.0:
4370+ resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
4371+
4372+ tslib@2.8.1:
4373+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
4374+
4375+ tsx@4.23.13:
4376+ resolution: {integrity: sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==}
4377+ engines: {node: '>=18.0.0'}
4378+ hasBin: true
4379+
4380+ type-check@0.4.0:
4381+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
4382+ engines: {node: '>= 0.8.0'}
4383+
4384+ typed-array-buffer@1.0.3:
4385+ resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
4386+ engines: {node: '>= 0.4'}
4387+
4388+ typed-array-byte-length@1.0.3:
4389+ resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==}
4390+ engines: {node: '>= 0.4'}
4391+
4392+ typed-array-byte-offset@1.0.4:
4393+ resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==}
4394+ engines: {node: '>= 0.4'}
4395+
4396+ typed-array-length@1.0.8:
4397+ resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==}
4398+ engines: {node: '>= 0.4'}
4399+
4400+ typescript-eslint@8.69.0:
4401+ resolution: {integrity: sha512-B3MltX0VqjUBNEe3b3sSuiRbfa6XrfHFtBiPamjT5AsW/dfq+y+bc0wyuS9DxAS1LyzCxRp2+rxzpLUvqM2BvA==}
4402+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
4403+ peerDependencies:
4404+ eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
4405+ typescript: '>=4.8.4 <6.1.0'
4406+
4407+ typescript@5.9.3:
4408+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
4409+ engines: {node: '>=14.17'}
4410+ hasBin: true
4411+
4412+ unbox-primitive@1.1.0:
4413+ resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
4414+ engines: {node: '>= 0.4'}
4415+
4416+ undici-types@7.18.2:
4417+ resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
4418+
4419+ unified@11.0.5:
4420+ resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
4421+
4422+ unist-util-is@6.0.1:
4423+ resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
4424+
4425+ unist-util-position@5.0.0:
4426+ resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
4427+
4428+ unist-util-stringify-position@4.0.0:
4429+ resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
4430+
4431+ unist-util-visit-parents@6.0.2:
4432+ resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
4433+
4434+ unist-util-visit@5.1.0:
4435+ resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==}
4436+
4437+ unrs-resolver@1.12.2:
4438+ resolution: {integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==}
4439+
4440+ update-browserslist-db@1.3.2:
4441+ resolution: {integrity: sha512-UQ+MSxlhRm1bzjhU+DcuXfjFO1FzNtqhK5+9Yvlp90ItDLk5vT932A0rFu619nf7RVS+Y/VeaUW1jaRDqZ8VJw==}
4442+ hasBin: true
4443+ peerDependencies:
4444+ browserslist: '>= 4.21.0'
4445+
4446+ uri-js@4.4.1:
4447+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
4448+
4449+ use-callback-ref@1.3.3:
4450+ resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
4451+ engines: {node: '>=10'}
4452+ peerDependencies:
4453+ '@types/react': '*'
4454+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
4455+ peerDependenciesMeta:
4456+ '@types/react':
4457+ optional: true
4458+
4459+ use-sidecar@1.1.3:
4460+ resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
4461+ engines: {node: '>=10'}
4462+ peerDependencies:
4463+ '@types/react': '*'
4464+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
4465+ peerDependenciesMeta:
4466+ '@types/react':
4467+ optional: true
4468+
4469+ use-sync-external-store@1.6.0:
4470+ resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==}
4471+ peerDependencies:
4472+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
4473+
4474+ vfile-location@5.0.3:
4475+ resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==}
4476+
4477+ vfile-message@4.0.3:
4478+ resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
4479+
4480+ vfile@6.0.3:
4481+ resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
4482+
4483+ victory-vendor@37.3.6:
4484+ resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==}
4485+
4486+ vite-node@3.2.4:
4487+ resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
4488+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
4489+ hasBin: true
4490+
4491+ vite@7.3.6:
4492+ resolution: {integrity: sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==}
4493+ engines: {node: ^20.19.0 || >=22.12.0}
4494+ hasBin: true
4495+ peerDependencies:
4496+ '@types/node': ^20.19.0 || >=22.12.0
4497+ jiti: '>=1.21.0'
4498+ less: ^4.0.0
4499+ lightningcss: ^1.21.0
4500+ sass: ^1.70.0
4501+ sass-embedded: ^1.70.0
4502+ stylus: '>=0.54.8'
4503+ sugarss: ^5.0.0
4504+ terser: ^5.16.0
4505+ tsx: ^4.8.1
4506+ yaml: ^2.4.2
4507+ peerDependenciesMeta:
4508+ '@types/node':
4509+ optional: true
4510+ jiti:
4511+ optional: true
4512+ less:
4513+ optional: true
4514+ lightningcss:
4515+ optional: true
4516+ sass:
4517+ optional: true
4518+ sass-embedded:
4519+ optional: true
4520+ stylus:
4521+ optional: true
4522+ sugarss:
4523+ optional: true
4524+ terser:
4525+ optional: true
4526+ tsx:
4527+ optional: true
4528+ yaml:
4529+ optional: true
4530+
4531+ vitest@3.2.7:
4532+ resolution: {integrity: sha512-KrxIJ62Fd89gfysR4WotlgZABiz2dqFPgqGzX7s+CwsqLFomRH7777ZcrOD6+WVAh7khPQP41A+BKbpcJFrdEg==}
4533+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
4534+ hasBin: true
4535+ peerDependencies:
4536+ '@edge-runtime/vm': '*'
4537+ '@types/debug': ^4.1.12
4538+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
4539+ '@vitest/browser': 3.2.7
4540+ '@vitest/ui': 3.2.7
4541+ happy-dom: '*'
4542+ jsdom: '*'
4543+ peerDependenciesMeta:
4544+ '@edge-runtime/vm':
4545+ optional: true
4546+ '@types/debug':
4547+ optional: true
4548+ '@types/node':
4549+ optional: true
4550+ '@vitest/browser':
4551+ optional: true
4552+ '@vitest/ui':
4553+ optional: true
4554+ happy-dom:
4555+ optional: true
4556+ jsdom:
4557+ optional: true
4558+
4559+ web-namespaces@2.0.1:
4560+ resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
4561+
4562+ web-streams-polyfill@3.3.3:
4563+ resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
4564+ engines: {node: '>= 8'}
4565+
4566+ which-boxed-primitive@1.1.1:
4567+ resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
4568+ engines: {node: '>= 0.4'}
4569+
4570+ which-builtin-type@1.2.1:
4571+ resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
4572+ engines: {node: '>= 0.4'}
4573+
4574+ which-collection@1.0.2:
4575+ resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==}
4576+ engines: {node: '>= 0.4'}
4577+
4578+ which-typed-array@1.1.22:
4579+ resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==}
4580+ engines: {node: '>= 0.4'}
4581+
4582+ which@2.0.2:
4583+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
4584+ engines: {node: '>= 8'}
4585+ hasBin: true
4586+
4587+ why-is-node-running@2.3.0:
4588+ resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
4589+ engines: {node: '>=8'}
4590+ hasBin: true
4591+
4592+ word-wrap@1.2.5:
4593+ resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
4594+ engines: {node: '>=0.10.0'}
4595+
4596+ ws@8.21.3:
4597+ resolution: {integrity: sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==}
4598+ engines: {node: '>=10.0.0'}
4599+ peerDependencies:
4600+ bufferutil: ^4.0.1
4601+ utf-8-validate: '>=5.0.2'
4602+ peerDependenciesMeta:
4603+ bufferutil:
4604+ optional: true
4605+ utf-8-validate:
4606+ optional: true
4607+
4608+ xtend@4.0.2:
4609+ resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
4610+ engines: {node: '>=0.4'}
4611+
4612+ yallist@3.1.1:
4613+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
4614+
4615+ yocto-queue@0.1.0:
4616+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
4617+ engines: {node: '>=10'}
4618+
4619+ zod-validation-error@4.0.2:
4620+ resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==}
4621+ engines: {node: '>=18.0.0'}
4622+ peerDependencies:
4623+ zod: ^3.25.0 || ^4.0.0
4624+
4625+ zod@4.5.4:
4626+ resolution: {integrity: sha512-sC95tT5iHHH9gtpj6A81kh+NEaRAUFN+qlUPDUbRfOMvNf5QCBqsb3WgvnpVtK5Y+4UfA6KqufotuTvMGiTlsA==}
4627+
4628+ zwitch@2.0.4:
4629+ resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
4630+
4631+snapshots:
4632+
4633+ '@alloc/quick-lru@5.3.0': {}
4634+
4635+ '@anthropic-ai/sdk@0.124.0(zod@4.5.4)':
4636+ dependencies:
4637+ json-schema-to-ts: 3.1.1
4638+ standardwebhooks: 1.1.1
4639+ optionalDependencies:
4640+ zod: 4.5.4
4641+
4642+ '@babel/code-frame@7.29.7':
4643+ dependencies:
4644+ '@babel/helper-validator-identifier': 7.29.7
4645+ js-tokens: 4.0.0
4646+ picocolors: 1.1.1
4647+
4648+ '@babel/compat-data@7.29.7': {}
4649+
4650+ '@babel/core@7.29.7':
4651+ dependencies:
4652+ '@babel/code-frame': 7.29.7
4653+ '@babel/generator': 7.29.8
4654+ '@babel/helper-compilation-targets': 7.29.7
4655+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
4656+ '@babel/helpers': 7.29.7
4657+ '@babel/parser': 7.29.8
4658+ '@babel/template': 7.29.7
4659+ '@babel/traverse': 7.29.8
4660+ '@babel/types': 7.29.8
4661+ '@jridgewell/remapping': 2.3.5
4662+ convert-source-map: 2.0.0
4663+ debug: 4.4.3
4664+ gensync: 1.0.0-beta.2
4665+ json5: 2.2.3
4666+ semver: 6.3.1
4667+ transitivePeerDependencies:
4668+ - supports-color
4669+
4670+ '@babel/generator@7.29.8':
4671+ dependencies:
4672+ '@babel/parser': 7.29.8
4673+ '@babel/types': 7.29.8
4674+ '@jridgewell/gen-mapping': 0.3.13
4675+ '@jridgewell/trace-mapping': 0.3.31
4676+ jsesc: 3.1.0
4677+
4678+ '@babel/helper-compilation-targets@7.29.7':
4679+ dependencies:
4680+ '@babel/compat-data': 7.29.7
4681+ '@babel/helper-validator-option': 7.29.7
4682+ browserslist: 4.28.9
4683+ lru-cache: 5.1.1
4684+ semver: 6.3.1
4685+
4686+ '@babel/helper-globals@7.29.7': {}
4687+
4688+ '@babel/helper-module-imports@7.29.7':
4689+ dependencies:
4690+ '@babel/traverse': 7.29.8
4691+ '@babel/types': 7.29.8
4692+ transitivePeerDependencies:
4693+ - supports-color
4694+
4695+ '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)':
4696+ dependencies:
4697+ '@babel/core': 7.29.7
4698+ '@babel/helper-module-imports': 7.29.7
4699+ '@babel/helper-validator-identifier': 7.29.7
4700+ '@babel/traverse': 7.29.8
4701+ transitivePeerDependencies:
4702+ - supports-color
4703+
4704+ '@babel/helper-string-parser@7.29.7': {}
4705+
4706+ '@babel/helper-validator-identifier@7.29.7': {}
4707+
4708+ '@babel/helper-validator-option@7.29.7': {}
4709+
4710+ '@babel/helpers@7.29.7':
4711+ dependencies:
4712+ '@babel/template': 7.29.7
4713+ '@babel/types': 7.29.8
4714+
4715+ '@babel/parser@7.29.8':
4716+ dependencies:
4717+ '@babel/types': 7.29.8
4718+
4719+ '@babel/runtime@7.29.7': {}
4720+
4721+ '@babel/template@7.29.7':
4722+ dependencies:
4723+ '@babel/code-frame': 7.29.7
4724+ '@babel/parser': 7.29.8
4725+ '@babel/types': 7.29.8
4726+
4727+ '@babel/traverse@7.29.8':
4728+ dependencies:
4729+ '@babel/code-frame': 7.29.7
4730+ '@babel/generator': 7.29.8
4731+ '@babel/helper-globals': 7.29.7
4732+ '@babel/parser': 7.29.8
4733+ '@babel/template': 7.29.7
4734+ '@babel/types': 7.29.8
4735+ debug: 4.4.3
4736+ transitivePeerDependencies:
4737+ - supports-color
4738+
4739+ '@babel/types@7.29.8':
4740+ dependencies:
4741+ '@babel/helper-string-parser': 7.29.7
4742+ '@babel/helper-validator-identifier': 7.29.7
4743+
4744+ '@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3)':
4745+ dependencies:
4746+ '@better-auth/utils': 0.4.2
4747+ '@better-fetch/fetch': 1.3.1
4748+ '@opentelemetry/semantic-conventions': 1.43.0
4749+ '@standard-schema/spec': 1.1.0
4750+ better-call: 1.4.0(zod@4.5.4)
4751+ jose: 6.2.12
4752+ kysely: 0.29.5
4753+ nanostores: 1.5.3
4754+ zod: 4.5.4
4755+
4756+ '@better-auth/drizzle-adapter@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)(drizzle-orm@0.45.2(@types/pg@8.23.1)(kysely@0.29.5)(pg@8.23.0))':
4757+ dependencies:
4758+ '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3)
4759+ '@better-auth/utils': 0.4.2
4760+ optionalDependencies:
4761+ drizzle-orm: 0.45.2(@types/pg@8.23.1)(kysely@0.29.5)(pg@8.23.0)
4762+
4763+ '@better-auth/kysely-adapter@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)(kysely@0.29.5)':
4764+ dependencies:
4765+ '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3)
4766+ '@better-auth/utils': 0.4.2
4767+ optionalDependencies:
4768+ kysely: 0.29.5
4769+
4770+ '@better-auth/memory-adapter@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)':
4771+ dependencies:
4772+ '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3)
4773+ '@better-auth/utils': 0.4.2
4774+
4775+ '@better-auth/mongo-adapter@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)':
4776+ dependencies:
4777+ '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3)
4778+ '@better-auth/utils': 0.4.2
4779+
4780+ '@better-auth/prisma-adapter@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)':
4781+ dependencies:
4782+ '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3)
4783+ '@better-auth/utils': 0.4.2
4784+
4785+ '@better-auth/telemetry@1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)':
4786+ dependencies:
4787+ '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3)
4788+ '@better-auth/utils': 0.4.2
4789+ '@better-fetch/fetch': 1.3.1
4790+
4791+ '@better-auth/utils@0.4.2':
4792+ dependencies:
4793+ '@noble/hashes': 2.4.0
4794+
4795+ '@better-auth/utils@0.5.0':
4796+ dependencies:
4797+ '@noble/hashes': 2.4.0
4798+
4799+ '@better-fetch/fetch@1.3.1': {}
4800+
4801+ '@drizzle-team/brocli@0.10.2': {}
4802+
4803+ '@emnapi/core@1.10.0':
4804+ dependencies:
4805+ '@emnapi/wasi-threads': 1.2.1
4806+ tslib: 2.8.1
4807+ optional: true
4808+
4809+ '@emnapi/runtime@1.10.0':
4810+ dependencies:
4811+ tslib: 2.8.1
4812+ optional: true
4813+
4814+ '@emnapi/runtime@1.11.3':
4815+ dependencies:
4816+ tslib: 2.8.1
4817+ optional: true
4818+
4819+ '@emnapi/wasi-threads@1.2.1':
4820+ dependencies:
4821+ tslib: 2.8.1
4822+ optional: true
4823+
4824+ '@epic-web/invariant@1.0.0': {}
4825+
4826+ '@esbuild-kit/core-utils@3.3.2':
4827+ dependencies:
4828+ esbuild: 0.18.20
4829+ source-map-support: 0.5.21
4830+
4831+ '@esbuild-kit/esm-loader@2.6.5':
4832+ dependencies:
4833+ '@esbuild-kit/core-utils': 3.3.2
4834+ get-tsconfig: 4.14.3
4835+
4836+ '@esbuild/aix-ppc64@0.25.12':
4837+ optional: true
4838+
4839+ '@esbuild/aix-ppc64@0.28.2':
4840+ optional: true
4841+
4842+ '@esbuild/android-arm64@0.18.20':
4843+ optional: true
4844+
4845+ '@esbuild/android-arm64@0.25.12':
4846+ optional: true
4847+
4848+ '@esbuild/android-arm64@0.28.2':
4849+ optional: true
4850+
4851+ '@esbuild/android-arm@0.18.20':
4852+ optional: true
4853+
4854+ '@esbuild/android-arm@0.25.12':
4855+ optional: true
4856+
4857+ '@esbuild/android-arm@0.28.2':
4858+ optional: true
4859+
4860+ '@esbuild/android-x64@0.18.20':
4861+ optional: true
4862+
4863+ '@esbuild/android-x64@0.25.12':
4864+ optional: true
4865+
4866+ '@esbuild/android-x64@0.28.2':
4867+ optional: true
4868+
4869+ '@esbuild/darwin-arm64@0.18.20':
4870+ optional: true
4871+
4872+ '@esbuild/darwin-arm64@0.25.12':
4873+ optional: true
4874+
4875+ '@esbuild/darwin-arm64@0.28.2':
4876+ optional: true
4877+
4878+ '@esbuild/darwin-x64@0.18.20':
4879+ optional: true
4880+
4881+ '@esbuild/darwin-x64@0.25.12':
4882+ optional: true
4883+
4884+ '@esbuild/darwin-x64@0.28.2':
4885+ optional: true
4886+
4887+ '@esbuild/freebsd-arm64@0.18.20':
4888+ optional: true
4889+
4890+ '@esbuild/freebsd-arm64@0.25.12':
4891+ optional: true
4892+
4893+ '@esbuild/freebsd-arm64@0.28.2':
4894+ optional: true
4895+
4896+ '@esbuild/freebsd-x64@0.18.20':
4897+ optional: true
4898+
4899+ '@esbuild/freebsd-x64@0.25.12':
4900+ optional: true
4901+
4902+ '@esbuild/freebsd-x64@0.28.2':
4903+ optional: true
4904+
4905+ '@esbuild/linux-arm64@0.18.20':
4906+ optional: true
4907+
4908+ '@esbuild/linux-arm64@0.25.12':
4909+ optional: true
4910+
4911+ '@esbuild/linux-arm64@0.28.2':
4912+ optional: true
4913+
4914+ '@esbuild/linux-arm@0.18.20':
4915+ optional: true
4916+
4917+ '@esbuild/linux-arm@0.25.12':
4918+ optional: true
4919+
4920+ '@esbuild/linux-arm@0.28.2':
4921+ optional: true
4922+
4923+ '@esbuild/linux-ia32@0.18.20':
4924+ optional: true
4925+
4926+ '@esbuild/linux-ia32@0.25.12':
4927+ optional: true
4928+
4929+ '@esbuild/linux-ia32@0.28.2':
4930+ optional: true
4931+
4932+ '@esbuild/linux-loong64@0.18.20':
4933+ optional: true
4934+
4935+ '@esbuild/linux-loong64@0.25.12':
4936+ optional: true
4937+
4938+ '@esbuild/linux-loong64@0.28.2':
4939+ optional: true
4940+
4941+ '@esbuild/linux-mips64el@0.18.20':
4942+ optional: true
4943+
4944+ '@esbuild/linux-mips64el@0.25.12':
4945+ optional: true
4946+
4947+ '@esbuild/linux-mips64el@0.28.2':
4948+ optional: true
4949+
4950+ '@esbuild/linux-ppc64@0.18.20':
4951+ optional: true
4952+
4953+ '@esbuild/linux-ppc64@0.25.12':
4954+ optional: true
4955+
4956+ '@esbuild/linux-ppc64@0.28.2':
4957+ optional: true
4958+
4959+ '@esbuild/linux-riscv64@0.18.20':
4960+ optional: true
4961+
4962+ '@esbuild/linux-riscv64@0.25.12':
4963+ optional: true
4964+
4965+ '@esbuild/linux-riscv64@0.28.2':
4966+ optional: true
4967+
4968+ '@esbuild/linux-s390x@0.18.20':
4969+ optional: true
4970+
4971+ '@esbuild/linux-s390x@0.25.12':
4972+ optional: true
4973+
4974+ '@esbuild/linux-s390x@0.28.2':
4975+ optional: true
4976+
4977+ '@esbuild/linux-x64@0.18.20':
4978+ optional: true
4979+
4980+ '@esbuild/linux-x64@0.25.12':
4981+ optional: true
4982+
4983+ '@esbuild/linux-x64@0.28.2':
4984+ optional: true
4985+
4986+ '@esbuild/netbsd-arm64@0.25.12':
4987+ optional: true
4988+
4989+ '@esbuild/netbsd-arm64@0.28.2':
4990+ optional: true
4991+
4992+ '@esbuild/netbsd-x64@0.18.20':
4993+ optional: true
4994+
4995+ '@esbuild/netbsd-x64@0.25.12':
4996+ optional: true
4997+
4998+ '@esbuild/netbsd-x64@0.28.2':
4999+ optional: true
5000+
5001+ '@esbuild/openbsd-arm64@0.25.12':
5002+ optional: true
5003+
5004+ '@esbuild/openbsd-arm64@0.28.2':
5005+ optional: true
5006+
5007+ '@esbuild/openbsd-x64@0.18.20':
5008+ optional: true
5009+
5010+ '@esbuild/openbsd-x64@0.25.12':
5011+ optional: true
5012+
5013+ '@esbuild/openbsd-x64@0.28.2':
5014+ optional: true
5015+
5016+ '@esbuild/openharmony-arm64@0.25.12':
5017+ optional: true
5018+
5019+ '@esbuild/openharmony-arm64@0.28.2':
5020+ optional: true
5021+
5022+ '@esbuild/sunos-x64@0.18.20':
5023+ optional: true
5024+
5025+ '@esbuild/sunos-x64@0.25.12':
5026+ optional: true
5027+
5028+ '@esbuild/sunos-x64@0.28.2':
5029+ optional: true
5030+
5031+ '@esbuild/win32-arm64@0.18.20':
5032+ optional: true
5033+
5034+ '@esbuild/win32-arm64@0.25.12':
5035+ optional: true
5036+
5037+ '@esbuild/win32-arm64@0.28.2':
5038+ optional: true
5039+
5040+ '@esbuild/win32-ia32@0.18.20':
5041+ optional: true
5042+
5043+ '@esbuild/win32-ia32@0.25.12':
5044+ optional: true
5045+
5046+ '@esbuild/win32-ia32@0.28.2':
5047+ optional: true
5048+
5049+ '@esbuild/win32-x64@0.18.20':
5050+ optional: true
5051+
5052+ '@esbuild/win32-x64@0.25.12':
5053+ optional: true
5054+
5055+ '@esbuild/win32-x64@0.28.2':
5056+ optional: true
5057+
5058+ '@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(jiti@2.7.0))':
5059+ dependencies:
5060+ eslint: 9.39.5(jiti@2.7.0)
5061+ eslint-visitor-keys: 3.4.3
5062+
5063+ '@eslint-community/eslint-utils@4.9.1(eslint@9.39.5(jiti@2.7.0))':
5064+ dependencies:
5065+ eslint: 9.39.5(jiti@2.7.0)
5066+ eslint-visitor-keys: 3.4.3
5067+
5068+ '@eslint-community/regexpp@4.12.2': {}
5069+
5070+ '@eslint/config-array@0.21.2':
5071+ dependencies:
5072+ '@eslint/object-schema': 2.1.7
5073+ debug: 4.4.3
5074+ minimatch: 3.1.5
5075+ transitivePeerDependencies:
5076+ - supports-color
5077+
5078+ '@eslint/config-helpers@0.4.2':
5079+ dependencies:
5080+ '@eslint/core': 0.17.0
5081+
5082+ '@eslint/core@0.17.0':
5083+ dependencies:
5084+ '@types/json-schema': 7.0.15
5085+
5086+ '@eslint/eslintrc@3.3.7':
5087+ dependencies:
5088+ ajv: 6.15.0
5089+ debug: 4.4.3
5090+ espree: 10.4.0
5091+ globals: 14.0.0
5092+ ignore: 5.3.2
5093+ import-fresh: 3.3.1
5094+ js-yaml: 4.3.2
5095+ minimatch: 3.1.5
5096+ strip-json-comments: 3.1.1
5097+ transitivePeerDependencies:
5098+ - supports-color
5099+
5100+ '@eslint/js@9.39.5': {}
5101+
5102+ '@eslint/object-schema@2.1.7': {}
5103+
5104+ '@eslint/plugin-kit@0.4.1':
5105+ dependencies:
5106+ '@eslint/core': 0.17.0
5107+ levn: 0.4.1
5108+
5109+ '@floating-ui/core@1.8.0':
5110+ dependencies:
5111+ '@floating-ui/utils': 0.2.12
5112+
5113+ '@floating-ui/dom@1.8.0':
5114+ dependencies:
5115+ '@floating-ui/core': 1.8.0
5116+ '@floating-ui/utils': 0.2.12
5117+
5118+ '@floating-ui/react-dom@2.1.9(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5119+ dependencies:
5120+ '@floating-ui/dom': 1.8.0
5121+ react: 19.2.8
5122+ react-dom: 19.2.8(react@19.2.8)
5123+
5124+ '@floating-ui/utils@0.2.12': {}
5125+
5126+ '@google/genai@2.21.0':
5127+ dependencies:
5128+ google-auth-library: 10.9.1
5129+ p-retry: 4.6.2
5130+ protobufjs: 7.6.6
5131+ ws: 8.21.3
5132+ transitivePeerDependencies:
5133+ - bufferutil
5134+ - supports-color
5135+ - utf-8-validate
5136+
5137+ '@humanfs/core@0.19.2':
5138+ dependencies:
5139+ '@humanfs/types': 0.15.0
5140+
5141+ '@humanfs/node@0.16.8':
5142+ dependencies:
5143+ '@humanfs/core': 0.19.2
5144+ '@humanfs/types': 0.15.0
5145+ '@humanwhocodes/retry': 0.4.3
5146+
5147+ '@humanfs/types@0.15.0': {}
5148+
5149+ '@humanwhocodes/module-importer@1.0.1': {}
5150+
5151+ '@humanwhocodes/retry@0.4.3': {}
5152+
5153+ '@img/colour@1.1.0':
5154+ optional: true
5155+
5156+ '@img/sharp-darwin-arm64@0.35.4':
5157+ optionalDependencies:
5158+ '@img/sharp-libvips-darwin-arm64': 1.3.3
5159+ optional: true
5160+
5161+ '@img/sharp-darwin-x64@0.35.4':
5162+ optionalDependencies:
5163+ '@img/sharp-libvips-darwin-x64': 1.3.3
5164+ optional: true
5165+
5166+ '@img/sharp-freebsd-wasm32@0.35.4':
5167+ dependencies:
5168+ '@img/sharp-wasm32': 0.35.4
5169+ optional: true
5170+
5171+ '@img/sharp-libvips-darwin-arm64@1.3.3':
5172+ optional: true
5173+
5174+ '@img/sharp-libvips-darwin-x64@1.3.3':
5175+ optional: true
5176+
5177+ '@img/sharp-libvips-linux-arm64@1.3.3':
5178+ optional: true
5179+
5180+ '@img/sharp-libvips-linux-arm@1.3.3':
5181+ optional: true
5182+
5183+ '@img/sharp-libvips-linux-ppc64@1.3.3':
5184+ optional: true
5185+
5186+ '@img/sharp-libvips-linux-riscv64@1.3.3':
5187+ optional: true
5188+
5189+ '@img/sharp-libvips-linux-s390x@1.3.3':
5190+ optional: true
5191+
5192+ '@img/sharp-libvips-linux-x64@1.3.3':
5193+ optional: true
5194+
5195+ '@img/sharp-libvips-linuxmusl-arm64@1.3.3':
5196+ optional: true
5197+
5198+ '@img/sharp-libvips-linuxmusl-x64@1.3.3':
5199+ optional: true
5200+
5201+ '@img/sharp-linux-arm64@0.35.4':
5202+ optionalDependencies:
5203+ '@img/sharp-libvips-linux-arm64': 1.3.3
5204+ optional: true
5205+
5206+ '@img/sharp-linux-arm@0.35.4':
5207+ optionalDependencies:
5208+ '@img/sharp-libvips-linux-arm': 1.3.3
5209+ optional: true
5210+
5211+ '@img/sharp-linux-ppc64@0.35.4':
5212+ optionalDependencies:
5213+ '@img/sharp-libvips-linux-ppc64': 1.3.3
5214+ optional: true
5215+
5216+ '@img/sharp-linux-riscv64@0.35.4':
5217+ optionalDependencies:
5218+ '@img/sharp-libvips-linux-riscv64': 1.3.3
5219+ optional: true
5220+
5221+ '@img/sharp-linux-s390x@0.35.4':
5222+ optionalDependencies:
5223+ '@img/sharp-libvips-linux-s390x': 1.3.3
5224+ optional: true
5225+
5226+ '@img/sharp-linux-x64@0.35.4':
5227+ optionalDependencies:
5228+ '@img/sharp-libvips-linux-x64': 1.3.3
5229+ optional: true
5230+
5231+ '@img/sharp-linuxmusl-arm64@0.35.4':
5232+ optionalDependencies:
5233+ '@img/sharp-libvips-linuxmusl-arm64': 1.3.3
5234+ optional: true
5235+
5236+ '@img/sharp-linuxmusl-x64@0.35.4':
5237+ optionalDependencies:
5238+ '@img/sharp-libvips-linuxmusl-x64': 1.3.3
5239+ optional: true
5240+
5241+ '@img/sharp-wasm32@0.35.4':
5242+ dependencies:
5243+ '@emnapi/runtime': 1.11.3
5244+ optional: true
5245+
5246+ '@img/sharp-webcontainers-wasm32@0.35.4':
5247+ dependencies:
5248+ '@img/sharp-wasm32': 0.35.4
5249+ optional: true
5250+
5251+ '@img/sharp-win32-arm64@0.35.4':
5252+ optional: true
5253+
5254+ '@img/sharp-win32-ia32@0.35.4':
5255+ optional: true
5256+
5257+ '@img/sharp-win32-x64@0.35.4':
5258+ optional: true
5259+
5260+ '@jridgewell/gen-mapping@0.3.13':
5261+ dependencies:
5262+ '@jridgewell/sourcemap-codec': 1.6.0
5263+ '@jridgewell/trace-mapping': 0.3.31
5264+
5265+ '@jridgewell/remapping@2.3.5':
5266+ dependencies:
5267+ '@jridgewell/gen-mapping': 0.3.13
5268+ '@jridgewell/trace-mapping': 0.3.31
5269+
5270+ '@jridgewell/resolve-uri@3.1.2': {}
5271+
5272+ '@jridgewell/sourcemap-codec@1.6.0': {}
5273+
5274+ '@jridgewell/trace-mapping@0.3.31':
5275+ dependencies:
5276+ '@jridgewell/resolve-uri': 3.1.2
5277+ '@jridgewell/sourcemap-codec': 1.6.0
5278+
5279+ '@napi-rs/lzma-linux-x64-gnu@1.5.1':
5280+ optional: true
5281+
5282+ '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
5283+ dependencies:
5284+ '@emnapi/core': 1.10.0
5285+ '@emnapi/runtime': 1.10.0
5286+ '@tybys/wasm-util': 0.10.3
5287+ optional: true
5288+
5289+ '@next/env@16.3.4': {}
5290+
5291+ '@next/eslint-plugin-next@16.3.4(eslint@9.39.5(jiti@2.7.0))':
5292+ dependencies:
5293+ '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.5(jiti@2.7.0))
5294+ fast-glob: 3.3.1
5295+ transitivePeerDependencies:
5296+ - eslint
5297+
5298+ '@next/swc-darwin-arm64@16.3.4':
5299+ optional: true
5300+
5301+ '@next/swc-darwin-x64@16.3.4':
5302+ optional: true
5303+
5304+ '@next/swc-linux-arm64-gnu@16.3.4':
5305+ optional: true
5306+
5307+ '@next/swc-linux-arm64-musl@16.3.4':
5308+ optional: true
5309+
5310+ '@next/swc-linux-x64-gnu@16.3.4':
5311+ optional: true
5312+
5313+ '@next/swc-linux-x64-musl@16.3.4':
5314+ optional: true
5315+
5316+ '@next/swc-win32-arm64-msvc@16.3.4':
5317+ optional: true
5318+
5319+ '@next/swc-win32-x64-msvc@16.3.4':
5320+ optional: true
5321+
5322+ '@noble/ciphers@2.4.0': {}
5323+
5324+ '@noble/hashes@2.4.0': {}
5325+
5326+ '@nodelib/fs.scandir@2.1.5':
5327+ dependencies:
5328+ '@nodelib/fs.stat': 2.0.5
5329+ run-parallel: 1.2.0
5330+
5331+ '@nodelib/fs.stat@2.0.5': {}
5332+
5333+ '@nodelib/fs.walk@1.2.8':
5334+ dependencies:
5335+ '@nodelib/fs.scandir': 2.1.5
5336+ fastq: 1.20.3
5337+
5338+ '@nolyfill/is-core-module@1.0.39': {}
5339+
5340+ '@opentelemetry/semantic-conventions@1.43.0': {}
5341+
5342+ '@phc/format@1.0.0': {}
5343+
5344+ '@playwright/test@1.63.0':
5345+ dependencies:
5346+ playwright: 1.63.0
5347+
5348+ '@protobufjs/aspromise@1.1.2': {}
5349+
5350+ '@protobufjs/base64@1.1.2': {}
5351+
5352+ '@protobufjs/codegen@2.0.5': {}
5353+
5354+ '@protobufjs/eventemitter@1.1.1': {}
5355+
5356+ '@protobufjs/fetch@1.1.1':
5357+ dependencies:
5358+ '@protobufjs/aspromise': 1.1.2
5359+
5360+ '@protobufjs/float@1.0.2': {}
5361+
5362+ '@protobufjs/path@1.1.2': {}
5363+
5364+ '@protobufjs/pool@1.1.0': {}
5365+
5366+ '@protobufjs/utf8@1.1.2': {}
5367+
5368+ '@radix-ui/number@1.1.3': {}
5369+
5370+ '@radix-ui/primitive@1.1.7': {}
5371+
5372+ '@radix-ui/react-arrow@1.1.15(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5373+ dependencies:
5374+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5375+ react: 19.2.8
5376+ react-dom: 19.2.8(react@19.2.8)
5377+ optionalDependencies:
5378+ '@types/react': 19.2.18
5379+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5380+
5381+ '@radix-ui/react-collection@1.1.15(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5382+ dependencies:
5383+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5384+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5385+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5386+ '@radix-ui/react-slot': 1.3.3(@types/react@19.2.18)(react@19.2.8)
5387+ react: 19.2.8
5388+ react-dom: 19.2.8(react@19.2.8)
5389+ optionalDependencies:
5390+ '@types/react': 19.2.18
5391+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5392+
5393+ '@radix-ui/react-compose-refs@1.1.5(@types/react@19.2.18)(react@19.2.8)':
5394+ dependencies:
5395+ react: 19.2.8
5396+ optionalDependencies:
5397+ '@types/react': 19.2.18
5398+
5399+ '@radix-ui/react-context@1.2.2(@types/react@19.2.18)(react@19.2.8)':
5400+ dependencies:
5401+ react: 19.2.8
5402+ optionalDependencies:
5403+ '@types/react': 19.2.18
5404+
5405+ '@radix-ui/react-dialog@1.1.23(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5406+ dependencies:
5407+ '@radix-ui/primitive': 1.1.7
5408+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5409+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5410+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5411+ '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.18)(react@19.2.8)
5412+ '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5413+ '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5414+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5415+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5416+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5417+ '@radix-ui/react-slot': 1.3.3(@types/react@19.2.18)(react@19.2.8)
5418+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.8)
5419+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5420+ aria-hidden: 1.2.6
5421+ react: 19.2.8
5422+ react-dom: 19.2.8(react@19.2.8)
5423+ react-remove-scroll: 2.7.2(@types/react@19.2.18)(react@19.2.8)
5424+ optionalDependencies:
5425+ '@types/react': 19.2.18
5426+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5427+
5428+ '@radix-ui/react-direction@1.1.4(@types/react@19.2.18)(react@19.2.8)':
5429+ dependencies:
5430+ react: 19.2.8
5431+ optionalDependencies:
5432+ '@types/react': 19.2.18
5433+
5434+ '@radix-ui/react-dismissable-layer@1.1.19(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5435+ dependencies:
5436+ '@radix-ui/primitive': 1.1.7
5437+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5438+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5439+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5440+ '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.18)(react@19.2.8)
5441+ react: 19.2.8
5442+ react-dom: 19.2.8(react@19.2.8)
5443+ optionalDependencies:
5444+ '@types/react': 19.2.18
5445+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5446+
5447+ '@radix-ui/react-dropdown-menu@2.1.24(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5448+ dependencies:
5449+ '@radix-ui/primitive': 1.1.7
5450+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5451+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5452+ '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5453+ '@radix-ui/react-menu': 2.1.24(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5454+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5455+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.8)
5456+ react: 19.2.8
5457+ react-dom: 19.2.8(react@19.2.8)
5458+ optionalDependencies:
5459+ '@types/react': 19.2.18
5460+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5461+
5462+ '@radix-ui/react-focus-guards@1.1.6(@types/react@19.2.18)(react@19.2.8)':
5463+ dependencies:
5464+ react: 19.2.8
5465+ optionalDependencies:
5466+ '@types/react': 19.2.18
5467+
5468+ '@radix-ui/react-focus-scope@1.1.16(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5469+ dependencies:
5470+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5471+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5472+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5473+ react: 19.2.8
5474+ react-dom: 19.2.8(react@19.2.8)
5475+ optionalDependencies:
5476+ '@types/react': 19.2.18
5477+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5478+
5479+ '@radix-ui/react-id@1.1.4(@types/react@19.2.18)(react@19.2.8)':
5480+ dependencies:
5481+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5482+ react: 19.2.8
5483+ optionalDependencies:
5484+ '@types/react': 19.2.18
5485+
5486+ '@radix-ui/react-menu@2.1.24(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5487+ dependencies:
5488+ '@radix-ui/primitive': 1.1.7
5489+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5490+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5491+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5492+ '@radix-ui/react-direction': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5493+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5494+ '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.18)(react@19.2.8)
5495+ '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5496+ '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5497+ '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5498+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5499+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5500+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5501+ '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5502+ '@radix-ui/react-slot': 1.3.3(@types/react@19.2.18)(react@19.2.8)
5503+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5504+ aria-hidden: 1.2.6
5505+ react: 19.2.8
5506+ react-dom: 19.2.8(react@19.2.8)
5507+ react-remove-scroll: 2.7.2(@types/react@19.2.18)(react@19.2.8)
5508+ optionalDependencies:
5509+ '@types/react': 19.2.18
5510+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5511+
5512+ '@radix-ui/react-popover@1.1.23(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5513+ dependencies:
5514+ '@radix-ui/primitive': 1.1.7
5515+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5516+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5517+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5518+ '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.18)(react@19.2.8)
5519+ '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5520+ '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5521+ '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5522+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5523+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5524+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5525+ '@radix-ui/react-slot': 1.3.3(@types/react@19.2.18)(react@19.2.8)
5526+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.8)
5527+ aria-hidden: 1.2.6
5528+ react: 19.2.8
5529+ react-dom: 19.2.8(react@19.2.8)
5530+ react-remove-scroll: 2.7.2(@types/react@19.2.18)(react@19.2.8)
5531+ optionalDependencies:
5532+ '@types/react': 19.2.18
5533+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5534+
5535+ '@radix-ui/react-popper@1.3.7(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5536+ dependencies:
5537+ '@floating-ui/react-dom': 2.1.9(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5538+ '@radix-ui/react-arrow': 1.1.15(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5539+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5540+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5541+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5542+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5543+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5544+ '@radix-ui/react-use-rect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5545+ '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5546+ '@radix-ui/rect': 1.1.3
5547+ react: 19.2.8
5548+ react-dom: 19.2.8(react@19.2.8)
5549+ optionalDependencies:
5550+ '@types/react': 19.2.18
5551+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5552+
5553+ '@radix-ui/react-portal@1.1.17(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5554+ dependencies:
5555+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5556+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5557+ react: 19.2.8
5558+ react-dom: 19.2.8(react@19.2.8)
5559+ optionalDependencies:
5560+ '@types/react': 19.2.18
5561+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5562+
5563+ '@radix-ui/react-presence@1.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5564+ dependencies:
5565+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5566+ react: 19.2.8
5567+ react-dom: 19.2.8(react@19.2.8)
5568+ optionalDependencies:
5569+ '@types/react': 19.2.18
5570+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5571+
5572+ '@radix-ui/react-primitive@2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5573+ dependencies:
5574+ '@radix-ui/react-slot': 1.3.3(@types/react@19.2.18)(react@19.2.8)
5575+ react: 19.2.8
5576+ react-dom: 19.2.8(react@19.2.8)
5577+ optionalDependencies:
5578+ '@types/react': 19.2.18
5579+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5580+
5581+ '@radix-ui/react-roving-focus@1.1.19(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5582+ dependencies:
5583+ '@radix-ui/primitive': 1.1.7
5584+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5585+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5586+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5587+ '@radix-ui/react-direction': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5588+ '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5589+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5590+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5591+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.8)
5592+ '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.2.18)(react@19.2.8)
5593+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5594+ react: 19.2.8
5595+ react-dom: 19.2.8(react@19.2.8)
5596+ optionalDependencies:
5597+ '@types/react': 19.2.18
5598+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5599+
5600+ '@radix-ui/react-scroll-area@1.2.18(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5601+ dependencies:
5602+ '@radix-ui/number': 1.1.3
5603+ '@radix-ui/primitive': 1.1.7
5604+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5605+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5606+ '@radix-ui/react-direction': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5607+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5608+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5609+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5610+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5611+ react: 19.2.8
5612+ react-dom: 19.2.8(react@19.2.8)
5613+ optionalDependencies:
5614+ '@types/react': 19.2.18
5615+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5616+
5617+ '@radix-ui/react-select@2.3.7(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5618+ dependencies:
5619+ '@radix-ui/number': 1.1.3
5620+ '@radix-ui/primitive': 1.1.7
5621+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5622+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5623+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5624+ '@radix-ui/react-direction': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5625+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5626+ '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.18)(react@19.2.8)
5627+ '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5628+ '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5629+ '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5630+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5631+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5632+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5633+ '@radix-ui/react-slot': 1.3.3(@types/react@19.2.18)(react@19.2.8)
5634+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5635+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.8)
5636+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5637+ '@radix-ui/react-use-previous': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5638+ '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5639+ aria-hidden: 1.2.6
5640+ react: 19.2.8
5641+ react-dom: 19.2.8(react@19.2.8)
5642+ react-remove-scroll: 2.7.2(@types/react@19.2.18)(react@19.2.8)
5643+ optionalDependencies:
5644+ '@types/react': 19.2.18
5645+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5646+
5647+ '@radix-ui/react-slider@1.4.7(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5648+ dependencies:
5649+ '@radix-ui/number': 1.1.3
5650+ '@radix-ui/primitive': 1.1.7
5651+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5652+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5653+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5654+ '@radix-ui/react-direction': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5655+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5656+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.8)
5657+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5658+ '@radix-ui/react-use-previous': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5659+ '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5660+ react: 19.2.8
5661+ react-dom: 19.2.8(react@19.2.8)
5662+ optionalDependencies:
5663+ '@types/react': 19.2.18
5664+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5665+
5666+ '@radix-ui/react-slot@1.3.3(@types/react@19.2.18)(react@19.2.8)':
5667+ dependencies:
5668+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5669+ react: 19.2.8
5670+ optionalDependencies:
5671+ '@types/react': 19.2.18
5672+
5673+ '@radix-ui/react-switch@1.3.7(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5674+ dependencies:
5675+ '@radix-ui/primitive': 1.1.7
5676+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5677+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5678+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5679+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.8)
5680+ '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5681+ react: 19.2.8
5682+ react-dom: 19.2.8(react@19.2.8)
5683+ optionalDependencies:
5684+ '@types/react': 19.2.18
5685+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5686+
5687+ '@radix-ui/react-tabs@1.1.21(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5688+ dependencies:
5689+ '@radix-ui/primitive': 1.1.7
5690+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5691+ '@radix-ui/react-direction': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5692+ '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5693+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5694+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5695+ '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5696+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.8)
5697+ react: 19.2.8
5698+ react-dom: 19.2.8(react@19.2.8)
5699+ optionalDependencies:
5700+ '@types/react': 19.2.18
5701+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5702+
5703+ '@radix-ui/react-tooltip@1.2.16(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5704+ dependencies:
5705+ '@radix-ui/primitive': 1.1.7
5706+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
5707+ '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.8)
5708+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5709+ '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5710+ '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5711+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5712+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5713+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5714+ '@radix-ui/react-slot': 1.3.3(@types/react@19.2.18)(react@19.2.8)
5715+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.8)
5716+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5717+ '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5718+ react: 19.2.8
5719+ react-dom: 19.2.8(react@19.2.8)
5720+ optionalDependencies:
5721+ '@types/react': 19.2.18
5722+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5723+
5724+ '@radix-ui/react-use-callback-ref@1.1.4(@types/react@19.2.18)(react@19.2.8)':
5725+ dependencies:
5726+ react: 19.2.8
5727+ optionalDependencies:
5728+ '@types/react': 19.2.18
5729+
5730+ '@radix-ui/react-use-controllable-state@1.2.6(@types/react@19.2.18)(react@19.2.8)':
5731+ dependencies:
5732+ '@radix-ui/primitive': 1.1.7
5733+ '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.18)(react@19.2.8)
5734+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5735+ react: 19.2.8
5736+ optionalDependencies:
5737+ '@types/react': 19.2.18
5738+
5739+ '@radix-ui/react-use-effect-event@0.0.5(@types/react@19.2.18)(react@19.2.8)':
5740+ dependencies:
5741+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5742+ react: 19.2.8
5743+ optionalDependencies:
5744+ '@types/react': 19.2.18
5745+
5746+ '@radix-ui/react-use-is-hydrated@0.1.3(@types/react@19.2.18)(react@19.2.8)':
5747+ dependencies:
5748+ react: 19.2.8
5749+ optionalDependencies:
5750+ '@types/react': 19.2.18
5751+
5752+ '@radix-ui/react-use-layout-effect@1.1.4(@types/react@19.2.18)(react@19.2.8)':
5753+ dependencies:
5754+ react: 19.2.8
5755+ optionalDependencies:
5756+ '@types/react': 19.2.18
5757+
5758+ '@radix-ui/react-use-previous@1.1.4(@types/react@19.2.18)(react@19.2.8)':
5759+ dependencies:
5760+ react: 19.2.8
5761+ optionalDependencies:
5762+ '@types/react': 19.2.18
5763+
5764+ '@radix-ui/react-use-rect@1.1.4(@types/react@19.2.18)(react@19.2.8)':
5765+ dependencies:
5766+ '@radix-ui/rect': 1.1.3
5767+ react: 19.2.8
5768+ optionalDependencies:
5769+ '@types/react': 19.2.18
5770+
5771+ '@radix-ui/react-use-size@1.1.4(@types/react@19.2.18)(react@19.2.8)':
5772+ dependencies:
5773+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.8)
5774+ react: 19.2.8
5775+ optionalDependencies:
5776+ '@types/react': 19.2.18
5777+
5778+ '@radix-ui/react-visually-hidden@1.2.11(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5779+ dependencies:
5780+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
5781+ react: 19.2.8
5782+ react-dom: 19.2.8(react@19.2.8)
5783+ optionalDependencies:
5784+ '@types/react': 19.2.18
5785+ '@types/react-dom': 19.2.7(@types/react@19.2.18)
5786+
5787+ '@radix-ui/rect@1.1.3': {}
5788+
5789+ '@reduxjs/toolkit@2.12.0(react-redux@9.3.0(@types/react@19.2.18)(react@19.2.8)(redux@5.0.1))(react@19.2.8)':
5790+ dependencies:
5791+ '@standard-schema/spec': 1.1.0
5792+ '@standard-schema/utils': 0.3.0
5793+ immer: 11.1.18
5794+ redux: 5.0.1
5795+ redux-thunk: 3.1.0(redux@5.0.1)
5796+ reselect: 5.2.0
5797+ optionalDependencies:
5798+ react: 19.2.8
5799+ react-redux: 9.3.0(@types/react@19.2.18)(react@19.2.8)(redux@5.0.1)
5800+
5801+ '@rollup/rollup-android-arm-eabi@4.63.1':
5802+ optional: true
5803+
5804+ '@rollup/rollup-android-arm64@4.63.1':
5805+ optional: true
5806+
5807+ '@rollup/rollup-darwin-arm64@4.63.1':
5808+ optional: true
5809+
5810+ '@rollup/rollup-darwin-x64@4.63.1':
5811+ optional: true
5812+
5813+ '@rollup/rollup-freebsd-arm64@4.63.1':
5814+ optional: true
5815+
5816+ '@rollup/rollup-freebsd-x64@4.63.1':
5817+ optional: true
5818+
5819+ '@rollup/rollup-linux-arm-gnueabihf@4.63.1':
5820+ optional: true
5821+
5822+ '@rollup/rollup-linux-arm-musleabihf@4.63.1':
5823+ optional: true
5824+
5825+ '@rollup/rollup-linux-arm64-gnu@4.63.1':
5826+ optional: true
5827+
5828+ '@rollup/rollup-linux-arm64-musl@4.63.1':
5829+ optional: true
5830+
5831+ '@rollup/rollup-linux-loong64-gnu@4.63.1':
5832+ optional: true
5833+
5834+ '@rollup/rollup-linux-loong64-musl@4.63.1':
5835+ optional: true
5836+
5837+ '@rollup/rollup-linux-ppc64-gnu@4.63.1':
5838+ optional: true
5839+
5840+ '@rollup/rollup-linux-ppc64-musl@4.63.1':
5841+ optional: true
5842+
5843+ '@rollup/rollup-linux-riscv64-gnu@4.63.1':
5844+ optional: true
5845+
5846+ '@rollup/rollup-linux-riscv64-musl@4.63.1':
5847+ optional: true
5848+
5849+ '@rollup/rollup-linux-s390x-gnu@4.63.1':
5850+ optional: true
5851+
5852+ '@rollup/rollup-linux-x64-gnu@4.63.1':
5853+ optional: true
5854+
5855+ '@rollup/rollup-linux-x64-musl@4.63.1':
5856+ optional: true
5857+
5858+ '@rollup/rollup-openbsd-x64@4.63.1':
5859+ optional: true
5860+
5861+ '@rollup/rollup-openharmony-arm64@4.63.1':
5862+ optional: true
5863+
5864+ '@rollup/rollup-win32-arm64-msvc@4.63.1':
5865+ optional: true
5866+
5867+ '@rollup/rollup-win32-ia32-msvc@4.63.1':
5868+ optional: true
5869+
5870+ '@rollup/rollup-win32-x64-gnu@4.63.1':
5871+ optional: true
5872+
5873+ '@rollup/rollup-win32-x64-msvc@4.63.1':
5874+ optional: true
5875+
5876+ '@rtsao/scc@1.1.0': {}
5877+
5878+ '@shikijs/core@4.4.3':
5879+ dependencies:
5880+ '@shikijs/primitive': 4.4.3
5881+ '@shikijs/types': 4.4.3
5882+ '@shikijs/vscode-textmate': 10.0.2
5883+ '@types/hast': 3.0.5
5884+ hast-util-to-html: 9.0.5
5885+
5886+ '@shikijs/engine-javascript@4.4.3':
5887+ dependencies:
5888+ '@shikijs/types': 4.4.3
5889+ '@shikijs/vscode-textmate': 10.0.2
5890+ oniguruma-to-es: 4.3.6
5891+
5892+ '@shikijs/engine-oniguruma@4.4.3':
5893+ dependencies:
5894+ '@shikijs/types': 4.4.3
5895+ '@shikijs/vscode-textmate': 10.0.2
5896+
5897+ '@shikijs/langs@4.4.3':
5898+ dependencies:
5899+ '@shikijs/types': 4.4.3
5900+
5901+ '@shikijs/primitive@4.4.3':
5902+ dependencies:
5903+ '@shikijs/types': 4.4.3
5904+ '@shikijs/vscode-textmate': 10.0.2
5905+ '@types/hast': 3.0.5
5906+
5907+ '@shikijs/themes@4.4.3':
5908+ dependencies:
5909+ '@shikijs/types': 4.4.3
5910+
5911+ '@shikijs/types@4.4.3':
5912+ dependencies:
5913+ '@shikijs/vscode-textmate': 10.0.2
5914+ '@types/hast': 3.0.5
5915+
5916+ '@shikijs/vscode-textmate@10.0.2': {}
5917+
5918+ '@stablelib/base64@1.0.1': {}
5919+
5920+ '@standard-schema/spec@1.1.0': {}
5921+
5922+ '@standard-schema/utils@0.3.0': {}
5923+
5924+ '@swc/helpers@0.5.23':
5925+ dependencies:
5926+ tslib: 2.8.1
5927+
5928+ '@tailwindcss/node@4.3.3':
5929+ dependencies:
5930+ '@jridgewell/remapping': 2.3.5
5931+ enhanced-resolve: 5.24.5
5932+ jiti: 2.7.0
5933+ lightningcss: 1.32.0
5934+ magic-string: 0.30.21
5935+ source-map-js: 1.2.1
5936+ tailwindcss: 4.3.3
5937+
5938+ '@tailwindcss/oxide-android-arm64@4.3.3':
5939+ optional: true
5940+
5941+ '@tailwindcss/oxide-darwin-arm64@4.3.3':
5942+ optional: true
5943+
5944+ '@tailwindcss/oxide-darwin-x64@4.3.3':
5945+ optional: true
5946+
5947+ '@tailwindcss/oxide-freebsd-x64@4.3.3':
5948+ optional: true
5949+
5950+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
5951+ optional: true
5952+
5953+ '@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
5954+ optional: true
5955+
5956+ '@tailwindcss/oxide-linux-arm64-musl@4.3.3':
5957+ optional: true
5958+
5959+ '@tailwindcss/oxide-linux-x64-gnu@4.3.3':
5960+ optional: true
5961+
5962+ '@tailwindcss/oxide-linux-x64-musl@4.3.3':
5963+ optional: true
5964+
5965+ '@tailwindcss/oxide-wasm32-wasi@4.3.3':
5966+ optional: true
5967+
5968+ '@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
5969+ optional: true
5970+
5971+ '@tailwindcss/oxide-win32-x64-msvc@4.3.3':
5972+ optional: true
5973+
5974+ '@tailwindcss/oxide@4.3.3':
5975+ optionalDependencies:
5976+ '@tailwindcss/oxide-android-arm64': 4.3.3
5977+ '@tailwindcss/oxide-darwin-arm64': 4.3.3
5978+ '@tailwindcss/oxide-darwin-x64': 4.3.3
5979+ '@tailwindcss/oxide-freebsd-x64': 4.3.3
5980+ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3
5981+ '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3
5982+ '@tailwindcss/oxide-linux-arm64-musl': 4.3.3
5983+ '@tailwindcss/oxide-linux-x64-gnu': 4.3.3
5984+ '@tailwindcss/oxide-linux-x64-musl': 4.3.3
5985+ '@tailwindcss/oxide-wasm32-wasi': 4.3.3
5986+ '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3
5987+ '@tailwindcss/oxide-win32-x64-msvc': 4.3.3
5988+
5989+ '@tailwindcss/postcss@4.3.3':
5990+ dependencies:
5991+ '@alloc/quick-lru': 5.3.0
5992+ '@tailwindcss/node': 4.3.3
5993+ '@tailwindcss/oxide': 4.3.3
5994+ postcss: 8.5.28
5995+ tailwindcss: 4.3.3
5996+
5997+ '@tanstack/react-virtual@3.14.10(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
5998+ dependencies:
5999+ '@tanstack/virtual-core': 3.17.8
6000+ react: 19.2.8
6001+ react-dom: 19.2.8(react@19.2.8)
6002+
6003+ '@tanstack/virtual-core@3.17.8': {}
6004+
6005+ '@tybys/wasm-util@0.10.3':
6006+ dependencies:
6007+ tslib: 2.8.1
6008+ optional: true
6009+
6010+ '@types/chai@5.2.3':
6011+ dependencies:
6012+ '@types/deep-eql': 4.0.2
6013+ assertion-error: 2.0.1
6014+
6015+ '@types/d3-array@3.2.2': {}
6016+
6017+ '@types/d3-color@3.1.3': {}
6018+
6019+ '@types/d3-ease@3.0.2': {}
6020+
6021+ '@types/d3-interpolate@3.0.4':
6022+ dependencies:
6023+ '@types/d3-color': 3.1.3
6024+
6025+ '@types/d3-path@3.1.1': {}
6026+
6027+ '@types/d3-scale@4.0.9':
6028+ dependencies:
6029+ '@types/d3-time': 3.0.4
6030+
6031+ '@types/d3-shape@3.2.0':
6032+ dependencies:
6033+ '@types/d3-path': 3.1.1
6034+
6035+ '@types/d3-time@3.0.4': {}
6036+
6037+ '@types/d3-timer@3.0.2': {}
6038+
6039+ '@types/debug@4.1.13':
6040+ dependencies:
6041+ '@types/ms': 2.1.0
6042+
6043+ '@types/deep-eql@4.0.2': {}
6044+
6045+ '@types/estree-jsx@1.0.5':
6046+ dependencies:
6047+ '@types/estree': 1.0.9
6048+
6049+ '@types/estree@1.0.9': {}
6050+
6051+ '@types/hast@3.0.5':
6052+ dependencies:
6053+ '@types/unist': 3.0.3
6054+
6055+ '@types/json-schema@7.0.15': {}
6056+
6057+ '@types/json5@0.0.29': {}
6058+
6059+ '@types/mdast@4.0.4':
6060+ dependencies:
6061+ '@types/unist': 3.0.3
6062+
6063+ '@types/ms@2.1.0': {}
6064+
6065+ '@types/node@24.13.3':
6066+ dependencies:
6067+ undici-types: 7.18.2
6068+
6069+ '@types/pg@8.23.1':
6070+ dependencies:
6071+ '@types/node': 24.13.3
6072+ pg-protocol: 1.16.0
6073+ pg-types: 2.2.0
6074+
6075+ '@types/react-dom@19.2.7(@types/react@19.2.18)':
6076+ dependencies:
6077+ '@types/react': 19.2.18
6078+
6079+ '@types/react@19.2.18':
6080+ dependencies:
6081+ csstype: 3.2.3
6082+
6083+ '@types/retry@0.12.0': {}
6084+
6085+ '@types/unist@2.0.11': {}
6086+
6087+ '@types/unist@3.0.3': {}
6088+
6089+ '@types/use-sync-external-store@0.0.6': {}
6090+
6091+ '@typescript-eslint/eslint-plugin@8.69.0(@typescript-eslint/parser@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)':
6092+ dependencies:
6093+ '@eslint-community/regexpp': 4.12.2
6094+ '@typescript-eslint/parser': 8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
6095+ '@typescript-eslint/scope-manager': 8.69.0
6096+ '@typescript-eslint/type-utils': 8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
6097+ '@typescript-eslint/utils': 8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
6098+ '@typescript-eslint/visitor-keys': 8.69.0
6099+ eslint: 9.39.5(jiti@2.7.0)
6100+ ignore: 7.0.8
6101+ natural-compare: 1.4.0
6102+ ts-api-utils: 2.5.0(typescript@5.9.3)
6103+ typescript: 5.9.3
6104+ transitivePeerDependencies:
6105+ - supports-color
6106+
6107+ '@typescript-eslint/parser@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)':
6108+ dependencies:
6109+ '@typescript-eslint/scope-manager': 8.69.0
6110+ '@typescript-eslint/types': 8.69.0
6111+ '@typescript-eslint/typescript-estree': 8.69.0(typescript@5.9.3)
6112+ '@typescript-eslint/visitor-keys': 8.69.0
6113+ debug: 4.4.3
6114+ eslint: 9.39.5(jiti@2.7.0)
6115+ typescript: 5.9.3
6116+ transitivePeerDependencies:
6117+ - supports-color
6118+
6119+ '@typescript-eslint/project-service@8.69.0(typescript@5.9.3)':
6120+ dependencies:
6121+ '@typescript-eslint/tsconfig-utils': 8.69.0(typescript@5.9.3)
6122+ '@typescript-eslint/types': 8.69.0
6123+ debug: 4.4.3
6124+ typescript: 5.9.3
6125+ transitivePeerDependencies:
6126+ - supports-color
6127+
6128+ '@typescript-eslint/scope-manager@8.69.0':
6129+ dependencies:
6130+ '@typescript-eslint/types': 8.69.0
6131+ '@typescript-eslint/visitor-keys': 8.69.0
6132+
6133+ '@typescript-eslint/tsconfig-utils@8.69.0(typescript@5.9.3)':
6134+ dependencies:
6135+ typescript: 5.9.3
6136+
6137+ '@typescript-eslint/type-utils@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)':
6138+ dependencies:
6139+ '@typescript-eslint/types': 8.69.0
6140+ '@typescript-eslint/typescript-estree': 8.69.0(typescript@5.9.3)
6141+ '@typescript-eslint/utils': 8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
6142+ debug: 4.4.3
6143+ eslint: 9.39.5(jiti@2.7.0)
6144+ ts-api-utils: 2.5.0(typescript@5.9.3)
6145+ typescript: 5.9.3
6146+ transitivePeerDependencies:
6147+ - supports-color
6148+
6149+ '@typescript-eslint/types@8.69.0': {}
6150+
6151+ '@typescript-eslint/typescript-estree@8.69.0(typescript@5.9.3)':
6152+ dependencies:
6153+ '@typescript-eslint/project-service': 8.69.0(typescript@5.9.3)
6154+ '@typescript-eslint/tsconfig-utils': 8.69.0(typescript@5.9.3)
6155+ '@typescript-eslint/types': 8.69.0
6156+ '@typescript-eslint/visitor-keys': 8.69.0
6157+ debug: 4.4.3
6158+ minimatch: 10.2.6
6159+ semver: 7.8.5
6160+ tinyglobby: 0.2.17
6161+ ts-api-utils: 2.5.0(typescript@5.9.3)
6162+ typescript: 5.9.3
6163+ transitivePeerDependencies:
6164+ - supports-color
6165+
6166+ '@typescript-eslint/utils@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)':
6167+ dependencies:
6168+ '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0))
6169+ '@typescript-eslint/scope-manager': 8.69.0
6170+ '@typescript-eslint/types': 8.69.0
6171+ '@typescript-eslint/typescript-estree': 8.69.0(typescript@5.9.3)
6172+ eslint: 9.39.5(jiti@2.7.0)
6173+ typescript: 5.9.3
6174+ transitivePeerDependencies:
6175+ - supports-color
6176+
6177+ '@typescript-eslint/visitor-keys@8.69.0':
6178+ dependencies:
6179+ '@typescript-eslint/types': 8.69.0
6180+ eslint-visitor-keys: 5.0.1
6181+
6182+ '@ungap/structured-clone@1.4.0': {}
6183+
6184+ '@unrs/resolver-binding-android-arm-eabi@1.12.2':
6185+ optional: true
6186+
6187+ '@unrs/resolver-binding-android-arm64@1.12.2':
6188+ optional: true
6189+
6190+ '@unrs/resolver-binding-darwin-arm64@1.12.2':
6191+ optional: true
6192+
6193+ '@unrs/resolver-binding-darwin-x64@1.12.2':
6194+ optional: true
6195+
6196+ '@unrs/resolver-binding-freebsd-x64@1.12.2':
6197+ optional: true
6198+
6199+ '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2':
6200+ optional: true
6201+
6202+ '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2':
6203+ optional: true
6204+
6205+ '@unrs/resolver-binding-linux-arm64-gnu@1.12.2':
6206+ optional: true
6207+
6208+ '@unrs/resolver-binding-linux-arm64-musl@1.12.2':
6209+ optional: true
6210+
6211+ '@unrs/resolver-binding-linux-loong64-gnu@1.12.2':
6212+ optional: true
6213+
6214+ '@unrs/resolver-binding-linux-loong64-musl@1.12.2':
6215+ optional: true
6216+
6217+ '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2':
6218+ optional: true
6219+
6220+ '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2':
6221+ optional: true
6222+
6223+ '@unrs/resolver-binding-linux-riscv64-musl@1.12.2':
6224+ optional: true
6225+
6226+ '@unrs/resolver-binding-linux-s390x-gnu@1.12.2':
6227+ optional: true
6228+
6229+ '@unrs/resolver-binding-linux-x64-gnu@1.12.2':
6230+ optional: true
6231+
6232+ '@unrs/resolver-binding-linux-x64-musl@1.12.2':
6233+ optional: true
6234+
6235+ '@unrs/resolver-binding-openharmony-arm64@1.12.2':
6236+ optional: true
6237+
6238+ '@unrs/resolver-binding-wasm32-wasi@1.12.2':
6239+ dependencies:
6240+ '@emnapi/core': 1.10.0
6241+ '@emnapi/runtime': 1.10.0
6242+ '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)
6243+ optional: true
6244+
6245+ '@unrs/resolver-binding-win32-arm64-msvc@1.12.2':
6246+ optional: true
6247+
6248+ '@unrs/resolver-binding-win32-ia32-msvc@1.12.2':
6249+ optional: true
6250+
6251+ '@unrs/resolver-binding-win32-x64-msvc@1.12.2':
6252+ optional: true
6253+
6254+ '@vitest/expect@3.2.7':
6255+ dependencies:
6256+ '@types/chai': 5.2.3
6257+ '@vitest/spy': 3.2.7
6258+ '@vitest/utils': 3.2.7
6259+ chai: 5.3.3
6260+ tinyrainbow: 2.0.0
6261+
6262+ '@vitest/mocker@3.2.7(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13))':
6263+ dependencies:
6264+ '@vitest/spy': 3.2.7
6265+ estree-walker: 3.0.3
6266+ magic-string: 0.30.21
6267+ optionalDependencies:
6268+ vite: 7.3.6(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13)
6269+
6270+ '@vitest/pretty-format@3.2.7':
6271+ dependencies:
6272+ tinyrainbow: 2.0.0
6273+
6274+ '@vitest/runner@3.2.7':
6275+ dependencies:
6276+ '@vitest/utils': 3.2.7
6277+ pathe: 2.0.3
6278+ strip-literal: 3.1.0
6279+
6280+ '@vitest/snapshot@3.2.7':
6281+ dependencies:
6282+ '@vitest/pretty-format': 3.2.7
6283+ magic-string: 0.30.21
6284+ pathe: 2.0.3
6285+
6286+ '@vitest/spy@3.2.7':
6287+ dependencies:
6288+ tinyspy: 4.0.6
6289+
6290+ '@vitest/utils@3.2.7':
6291+ dependencies:
6292+ '@vitest/pretty-format': 3.2.7
6293+ loupe: 3.2.1
6294+ tinyrainbow: 2.0.0
6295+
6296+ acorn-jsx@5.3.2(acorn@8.18.0):
6297+ dependencies:
6298+ acorn: 8.18.0
6299+
6300+ acorn@8.18.0: {}
6301+
6302+ agent-base@7.1.4: {}
6303+
6304+ ajv@6.15.0:
6305+ dependencies:
6306+ fast-deep-equal: 3.1.3
6307+ fast-json-stable-stringify: 2.1.0
6308+ json-schema-traverse: 0.4.1
6309+ uri-js: 4.4.1
6310+
6311+ ansi-styles@4.3.0:
6312+ dependencies:
6313+ color-convert: 2.0.1
6314+
6315+ argon2@0.45.1:
6316+ dependencies:
6317+ '@phc/format': 1.0.0
6318+ cross-env: 10.1.0
6319+ node-addon-api: 8.9.2
6320+ node-gyp-build: 4.8.4
6321+
6322+ argparse@2.0.1: {}
6323+
6324+ aria-hidden@1.2.6:
6325+ dependencies:
6326+ tslib: 2.8.1
6327+
6328+ aria-query@5.3.2: {}
6329+
6330+ array-buffer-byte-length@1.0.2:
6331+ dependencies:
6332+ call-bound: 1.0.4
6333+ is-array-buffer: 3.0.5
6334+
6335+ array-includes@3.1.9:
6336+ dependencies:
6337+ call-bind: 1.0.9
6338+ call-bound: 1.0.4
6339+ define-properties: 1.2.1
6340+ es-abstract: 1.24.2
6341+ es-object-atoms: 1.1.2
6342+ get-intrinsic: 1.3.0
6343+ is-string: 1.1.1
6344+ math-intrinsics: 1.1.0
6345+
6346+ array.prototype.findlast@1.2.5:
6347+ dependencies:
6348+ call-bind: 1.0.9
6349+ define-properties: 1.2.1
6350+ es-abstract: 1.24.2
6351+ es-errors: 1.3.0
6352+ es-object-atoms: 1.1.2
6353+ es-shim-unscopables: 1.1.0
6354+
6355+ array.prototype.findlastindex@1.2.6:
6356+ dependencies:
6357+ call-bind: 1.0.9
6358+ call-bound: 1.0.4
6359+ define-properties: 1.2.1
6360+ es-abstract: 1.24.2
6361+ es-errors: 1.3.0
6362+ es-object-atoms: 1.1.2
6363+ es-shim-unscopables: 1.1.0
6364+
6365+ array.prototype.flat@1.3.3:
6366+ dependencies:
6367+ call-bind: 1.0.9
6368+ define-properties: 1.2.1
6369+ es-abstract: 1.24.2
6370+ es-shim-unscopables: 1.1.0
6371+
6372+ array.prototype.flatmap@1.3.3:
6373+ dependencies:
6374+ call-bind: 1.0.9
6375+ define-properties: 1.2.1
6376+ es-abstract: 1.24.2
6377+ es-shim-unscopables: 1.1.0
6378+
6379+ array.prototype.tosorted@1.1.4:
6380+ dependencies:
6381+ call-bind: 1.0.9
6382+ define-properties: 1.2.1
6383+ es-abstract: 1.24.2
6384+ es-errors: 1.3.0
6385+ es-shim-unscopables: 1.1.0
6386+
6387+ arraybuffer.prototype.slice@1.0.4:
6388+ dependencies:
6389+ array-buffer-byte-length: 1.0.2
6390+ call-bind: 1.0.9
6391+ define-properties: 1.2.1
6392+ es-abstract: 1.24.2
6393+ es-errors: 1.3.0
6394+ get-intrinsic: 1.3.0
6395+ is-array-buffer: 3.0.5
6396+
6397+ assertion-error@2.0.1: {}
6398+
6399+ ast-types-flow@0.0.8: {}
6400+
6401+ async-function@1.0.0: {}
6402+
6403+ available-typed-arrays@1.0.7:
6404+ dependencies:
6405+ possible-typed-array-names: 1.1.0
6406+
6407+ axe-core@4.13.0: {}
6408+
6409+ axobject-query@4.1.0: {}
6410+
6411+ bail@2.0.2: {}
6412+
6413+ balanced-match@1.0.2: {}
6414+
6415+ balanced-match@4.0.4: {}
6416+
6417+ base64-js@1.5.1: {}
6418+
6419+ baseline-browser-mapping@2.11.21: {}
6420+
6421+ better-auth@1.7.3(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@types/pg@8.23.1)(kysely@0.29.5)(pg@8.23.0))(next@16.3.4(@babel/core@7.29.7)(@playwright/test@1.63.0)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@3.2.7(@types/debug@4.1.13)(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13)):
6422+ dependencies:
6423+ '@better-auth/core': 1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3)
6424+ '@better-auth/drizzle-adapter': 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)(drizzle-orm@0.45.2(@types/pg@8.23.1)(kysely@0.29.5)(pg@8.23.0))
6425+ '@better-auth/kysely-adapter': 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)(kysely@0.29.5)
6426+ '@better-auth/memory-adapter': 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)
6427+ '@better-auth/mongo-adapter': 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)
6428+ '@better-auth/prisma-adapter': 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)
6429+ '@better-auth/telemetry': 1.7.3(@better-auth/core@1.7.3(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.4.0(zod@4.5.4))(jose@6.2.12)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)
6430+ '@better-auth/utils': 0.4.2
6431+ '@better-fetch/fetch': 1.3.1
6432+ '@noble/ciphers': 2.4.0
6433+ '@noble/hashes': 2.4.0
6434+ better-call: 1.4.0(zod@4.5.4)
6435+ defu: 6.1.7
6436+ jose: 6.2.12
6437+ kysely: 0.29.5
6438+ nanostores: 1.5.3
6439+ zod: 4.5.4
6440+ optionalDependencies:
6441+ drizzle-kit: 0.31.10
6442+ drizzle-orm: 0.45.2(@types/pg@8.23.1)(kysely@0.29.5)(pg@8.23.0)
6443+ next: 16.3.4(@babel/core@7.29.7)(@playwright/test@1.63.0)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
6444+ pg: 8.23.0
6445+ react: 19.2.8
6446+ react-dom: 19.2.8(react@19.2.8)
6447+ vitest: 3.2.7(@types/debug@4.1.13)(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13)
6448+ transitivePeerDependencies:
6449+ - '@cloudflare/workers-types'
6450+ - '@opentelemetry/api'
6451+
6452+ better-call@1.4.0(zod@4.5.4):
6453+ dependencies:
6454+ '@better-auth/utils': 0.5.0
6455+ '@better-fetch/fetch': 1.3.1
6456+ rou3: 0.9.2
6457+ set-cookie-parser: 3.1.2
6458+ optionalDependencies:
6459+ zod: 4.5.4
6460+
6461+ bignumber.js@9.3.1: {}
6462+
6463+ brace-expansion@1.1.18:
6464+ dependencies:
6465+ balanced-match: 1.0.2
6466+ concat-map: 0.0.1
6467+
6468+ brace-expansion@5.0.9:
6469+ dependencies:
6470+ balanced-match: 4.0.4
6471+
6472+ braces@3.0.3:
6473+ dependencies:
6474+ fill-range: 7.1.1
6475+
6476+ browserslist@4.28.9:
6477+ dependencies:
6478+ baseline-browser-mapping: 2.11.21
6479+ caniuse-lite: 1.0.30001810
6480+ electron-to-chromium: 1.5.422
6481+ node-releases: 2.0.54
6482+ update-browserslist-db: 1.3.2(browserslist@4.28.9)
6483+
6484+ buffer-equal-constant-time@1.0.1: {}
6485+
6486+ buffer-from@1.1.2: {}
6487+
6488+ cac@6.7.14: {}
6489+
6490+ call-bind-apply-helpers@1.0.2:
6491+ dependencies:
6492+ es-errors: 1.3.0
6493+ function-bind: 1.1.2
6494+
6495+ call-bind@1.0.9:
6496+ dependencies:
6497+ call-bind-apply-helpers: 1.0.2
6498+ es-define-property: 1.0.1
6499+ get-intrinsic: 1.3.0
6500+ set-function-length: 1.2.2
6501+
6502+ call-bound@1.0.4:
6503+ dependencies:
6504+ call-bind-apply-helpers: 1.0.2
6505+ get-intrinsic: 1.3.0
6506+
6507+ callsites@3.1.0: {}
6508+
6509+ caniuse-lite@1.0.30001810: {}
6510+
6511+ ccount@2.0.1: {}
6512+
6513+ chai@5.3.3:
6514+ dependencies:
6515+ assertion-error: 2.0.1
6516+ check-error: 2.1.3
6517+ deep-eql: 5.0.2
6518+ loupe: 3.2.1
6519+ pathval: 2.0.1
6520+
6521+ chalk@4.1.2:
6522+ dependencies:
6523+ ansi-styles: 4.3.0
6524+ supports-color: 7.2.0
6525+
6526+ character-entities-html4@2.1.0: {}
6527+
6528+ character-entities-legacy@3.0.0: {}
6529+
6530+ character-entities@2.0.2: {}
6531+
6532+ character-reference-invalid@2.0.1: {}
6533+
6534+ check-error@2.1.3: {}
6535+
6536+ class-variance-authority@0.7.1:
6537+ dependencies:
6538+ clsx: 2.1.1
6539+
6540+ client-only@0.0.1: {}
6541+
6542+ clsx@2.1.1: {}
6543+
6544+ cmdk@1.1.1(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
6545+ dependencies:
6546+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.8)
6547+ '@radix-ui/react-dialog': 1.1.23(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
6548+ '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.8)
6549+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
6550+ react: 19.2.8
6551+ react-dom: 19.2.8(react@19.2.8)
6552+ transitivePeerDependencies:
6553+ - '@types/react'
6554+ - '@types/react-dom'
6555+
6556+ color-convert@2.0.1:
6557+ dependencies:
6558+ color-name: 1.1.4
6559+
6560+ color-name@1.1.4: {}
6561+
6562+ comma-separated-tokens@2.0.3: {}
6563+
6564+ concat-map@0.0.1: {}
6565+
6566+ convert-source-map@2.0.0: {}
6567+
6568+ cross-env@10.1.0:
6569+ dependencies:
6570+ '@epic-web/invariant': 1.0.0
6571+ cross-spawn: 7.0.6
6572+
6573+ cross-spawn@7.0.6:
6574+ dependencies:
6575+ path-key: 3.1.1
6576+ shebang-command: 2.0.0
6577+ which: 2.0.2
6578+
6579+ csstype@3.2.3: {}
6580+
6581+ d3-array@3.2.4:
6582+ dependencies:
6583+ internmap: 2.0.3
6584+
6585+ d3-color@3.1.0: {}
6586+
6587+ d3-ease@3.0.1: {}
6588+
6589+ d3-format@3.1.2: {}
6590+
6591+ d3-interpolate@3.0.1:
6592+ dependencies:
6593+ d3-color: 3.1.0
6594+
6595+ d3-path@3.1.0: {}
6596+
6597+ d3-scale@4.0.2:
6598+ dependencies:
6599+ d3-array: 3.2.4
6600+ d3-format: 3.1.2
6601+ d3-interpolate: 3.0.1
6602+ d3-time: 3.1.0
6603+ d3-time-format: 4.1.0
6604+
6605+ d3-shape@3.2.0:
6606+ dependencies:
6607+ d3-path: 3.1.0
6608+
6609+ d3-time-format@4.1.0:
6610+ dependencies:
6611+ d3-time: 3.1.0
6612+
6613+ d3-time@3.1.0:
6614+ dependencies:
6615+ d3-array: 3.2.4
6616+
6617+ d3-timer@3.0.1: {}
6618+
6619+ damerau-levenshtein@1.0.8: {}
6620+
6621+ data-uri-to-buffer@4.0.1: {}
6622+
6623+ data-view-buffer@1.0.2:
6624+ dependencies:
6625+ call-bound: 1.0.4
6626+ es-errors: 1.3.0
6627+ is-data-view: 1.0.2
6628+
6629+ data-view-byte-length@1.0.2:
6630+ dependencies:
6631+ call-bound: 1.0.4
6632+ es-errors: 1.3.0
6633+ is-data-view: 1.0.2
6634+
6635+ data-view-byte-offset@1.0.1:
6636+ dependencies:
6637+ call-bound: 1.0.4
6638+ es-errors: 1.3.0
6639+ is-data-view: 1.0.2
6640+
6641+ debug@3.2.7:
6642+ dependencies:
6643+ ms: 2.1.3
6644+
6645+ debug@4.4.3:
6646+ dependencies:
6647+ ms: 2.1.3
6648+
6649+ decimal.js-light@2.5.1: {}
6650+
6651+ decode-named-character-reference@1.3.0:
6652+ dependencies:
6653+ character-entities: 2.0.2
6654+
6655+ deep-eql@5.0.2: {}
6656+
6657+ deep-is@0.1.4: {}
6658+
6659+ define-data-property@1.1.4:
6660+ dependencies:
6661+ es-define-property: 1.0.1
6662+ es-errors: 1.3.0
6663+ gopd: 1.2.0
6664+
6665+ define-properties@1.2.1:
6666+ dependencies:
6667+ define-data-property: 1.1.4
6668+ has-property-descriptors: 1.0.2
6669+ object-keys: 1.1.1
6670+
6671+ defu@6.1.7: {}
6672+
6673+ dequal@2.0.3: {}
6674+
6675+ detect-libc@2.1.2: {}
6676+
6677+ detect-node-es@1.1.0: {}
6678+
6679+ devlop@1.1.0:
6680+ dependencies:
6681+ dequal: 2.0.3
6682+
6683+ doctrine@2.1.0:
6684+ dependencies:
6685+ esutils: 2.0.3
6686+
6687+ drizzle-kit@0.31.10:
6688+ dependencies:
6689+ '@drizzle-team/brocli': 0.10.2
6690+ '@esbuild-kit/esm-loader': 2.6.5
6691+ esbuild: 0.25.12
6692+ tsx: 4.23.13
6693+
6694+ drizzle-orm@0.45.2(@types/pg@8.23.1)(kysely@0.29.5)(pg@8.23.0):
6695+ optionalDependencies:
6696+ '@types/pg': 8.23.1
6697+ kysely: 0.29.5
6698+ pg: 8.23.0
6699+
6700+ dunder-proto@1.0.1:
6701+ dependencies:
6702+ call-bind-apply-helpers: 1.0.2
6703+ es-errors: 1.3.0
6704+ gopd: 1.2.0
6705+
6706+ ecdsa-sig-formatter@1.0.11:
6707+ dependencies:
6708+ safe-buffer: 5.2.1
6709+
6710+ electron-to-chromium@1.5.422: {}
6711+
6712+ emoji-regex@9.2.2: {}
6713+
6714+ enhanced-resolve@5.24.5:
6715+ dependencies:
6716+ graceful-fs: 4.2.11
6717+ tapable: 2.3.3
6718+
6719+ entities@6.0.1: {}
6720+
6721+ es-abstract-get@1.0.0:
6722+ dependencies:
6723+ es-errors: 1.3.0
6724+ es-object-atoms: 1.1.2
6725+ is-callable: 1.2.7
6726+ object-inspect: 1.13.4
6727+
6728+ es-abstract@1.24.2:
6729+ dependencies:
6730+ array-buffer-byte-length: 1.0.2
6731+ arraybuffer.prototype.slice: 1.0.4
6732+ available-typed-arrays: 1.0.7
6733+ call-bind: 1.0.9
6734+ call-bound: 1.0.4
6735+ data-view-buffer: 1.0.2
6736+ data-view-byte-length: 1.0.2
6737+ data-view-byte-offset: 1.0.1
6738+ es-define-property: 1.0.1
6739+ es-errors: 1.3.0
6740+ es-object-atoms: 1.1.2
6741+ es-set-tostringtag: 2.1.0
6742+ es-to-primitive: 1.3.4
6743+ function.prototype.name: 1.2.0
6744+ get-intrinsic: 1.3.0
6745+ get-proto: 1.0.1
6746+ get-symbol-description: 1.1.0
6747+ globalthis: 1.0.4
6748+ gopd: 1.2.0
6749+ has-property-descriptors: 1.0.2
6750+ has-proto: 1.2.0
6751+ has-symbols: 1.1.0
6752+ hasown: 2.0.4
6753+ internal-slot: 1.1.0
6754+ is-array-buffer: 3.0.5
6755+ is-callable: 1.2.7
6756+ is-data-view: 1.0.2
6757+ is-negative-zero: 2.0.3
6758+ is-regex: 1.2.1
6759+ is-set: 2.0.3
6760+ is-shared-array-buffer: 1.0.4
6761+ is-string: 1.1.1
6762+ is-typed-array: 1.1.15
6763+ is-weakref: 1.1.1
6764+ math-intrinsics: 1.1.0
6765+ object-inspect: 1.13.4
6766+ object-keys: 1.1.1
6767+ object.assign: 4.1.7
6768+ own-keys: 1.0.2
6769+ regexp.prototype.flags: 1.5.4
6770+ safe-array-concat: 1.1.4
6771+ safe-push-apply: 1.0.0
6772+ safe-regex-test: 1.1.0
6773+ set-proto: 1.0.0
6774+ stop-iteration-iterator: 1.1.0
6775+ string.prototype.trim: 1.2.11
6776+ string.prototype.trimend: 1.0.10
6777+ string.prototype.trimstart: 1.0.8
6778+ typed-array-buffer: 1.0.3
6779+ typed-array-byte-length: 1.0.3
6780+ typed-array-byte-offset: 1.0.4
6781+ typed-array-length: 1.0.8
6782+ unbox-primitive: 1.1.0
6783+ which-typed-array: 1.1.22
6784+
6785+ es-define-property@1.0.1: {}
6786+
6787+ es-errors@1.3.0: {}
6788+
6789+ es-iterator-helpers@1.4.0:
6790+ dependencies:
6791+ call-bind: 1.0.9
6792+ call-bound: 1.0.4
6793+ define-properties: 1.2.1
6794+ es-abstract: 1.24.2
6795+ es-errors: 1.3.0
6796+ es-set-tostringtag: 2.1.0
6797+ function-bind: 1.1.2
6798+ get-intrinsic: 1.3.0
6799+ globalthis: 1.0.4
6800+ gopd: 1.2.0
6801+ has-property-descriptors: 1.0.2
6802+ has-proto: 1.2.0
6803+ has-symbols: 1.1.0
6804+ internal-slot: 1.1.0
6805+ iterator.prototype: 1.1.5
6806+ math-intrinsics: 1.1.0
6807+
6808+ es-module-lexer@1.7.0: {}
6809+
6810+ es-object-atoms@1.1.2:
6811+ dependencies:
6812+ es-errors: 1.3.0
6813+
6814+ es-set-tostringtag@2.1.0:
6815+ dependencies:
6816+ es-errors: 1.3.0
6817+ get-intrinsic: 1.3.0
6818+ has-tostringtag: 1.0.2
6819+ hasown: 2.0.4
6820+
6821+ es-shim-unscopables@1.1.0:
6822+ dependencies:
6823+ hasown: 2.0.4
6824+
6825+ es-to-primitive@1.3.4:
6826+ dependencies:
6827+ es-abstract-get: 1.0.0
6828+ es-define-property: 1.0.1
6829+ es-errors: 1.3.0
6830+ is-callable: 1.2.7
6831+ is-date-object: 1.1.0
6832+ is-symbol: 1.1.1
6833+
6834+ es-toolkit@1.52.0: {}
6835+
6836+ esbuild@0.18.20:
6837+ optionalDependencies:
6838+ '@esbuild/android-arm': 0.18.20
6839+ '@esbuild/android-arm64': 0.18.20
6840+ '@esbuild/android-x64': 0.18.20
6841+ '@esbuild/darwin-arm64': 0.18.20
6842+ '@esbuild/darwin-x64': 0.18.20
6843+ '@esbuild/freebsd-arm64': 0.18.20
6844+ '@esbuild/freebsd-x64': 0.18.20
6845+ '@esbuild/linux-arm': 0.18.20
6846+ '@esbuild/linux-arm64': 0.18.20
6847+ '@esbuild/linux-ia32': 0.18.20
6848+ '@esbuild/linux-loong64': 0.18.20
6849+ '@esbuild/linux-mips64el': 0.18.20
6850+ '@esbuild/linux-ppc64': 0.18.20
6851+ '@esbuild/linux-riscv64': 0.18.20
6852+ '@esbuild/linux-s390x': 0.18.20
6853+ '@esbuild/linux-x64': 0.18.20
6854+ '@esbuild/netbsd-x64': 0.18.20
6855+ '@esbuild/openbsd-x64': 0.18.20
6856+ '@esbuild/sunos-x64': 0.18.20
6857+ '@esbuild/win32-arm64': 0.18.20
6858+ '@esbuild/win32-ia32': 0.18.20
6859+ '@esbuild/win32-x64': 0.18.20
6860+
6861+ esbuild@0.25.12:
6862+ optionalDependencies:
6863+ '@esbuild/aix-ppc64': 0.25.12
6864+ '@esbuild/android-arm': 0.25.12
6865+ '@esbuild/android-arm64': 0.25.12
6866+ '@esbuild/android-x64': 0.25.12
6867+ '@esbuild/darwin-arm64': 0.25.12
6868+ '@esbuild/darwin-x64': 0.25.12
6869+ '@esbuild/freebsd-arm64': 0.25.12
6870+ '@esbuild/freebsd-x64': 0.25.12
6871+ '@esbuild/linux-arm': 0.25.12
6872+ '@esbuild/linux-arm64': 0.25.12
6873+ '@esbuild/linux-ia32': 0.25.12
6874+ '@esbuild/linux-loong64': 0.25.12
6875+ '@esbuild/linux-mips64el': 0.25.12
6876+ '@esbuild/linux-ppc64': 0.25.12
6877+ '@esbuild/linux-riscv64': 0.25.12
6878+ '@esbuild/linux-s390x': 0.25.12
6879+ '@esbuild/linux-x64': 0.25.12
6880+ '@esbuild/netbsd-arm64': 0.25.12
6881+ '@esbuild/netbsd-x64': 0.25.12
6882+ '@esbuild/openbsd-arm64': 0.25.12
6883+ '@esbuild/openbsd-x64': 0.25.12
6884+ '@esbuild/openharmony-arm64': 0.25.12
6885+ '@esbuild/sunos-x64': 0.25.12
6886+ '@esbuild/win32-arm64': 0.25.12
6887+ '@esbuild/win32-ia32': 0.25.12
6888+ '@esbuild/win32-x64': 0.25.12
6889+
6890+ esbuild@0.28.2:
6891+ optionalDependencies:
6892+ '@esbuild/aix-ppc64': 0.28.2
6893+ '@esbuild/android-arm': 0.28.2
6894+ '@esbuild/android-arm64': 0.28.2
6895+ '@esbuild/android-x64': 0.28.2
6896+ '@esbuild/darwin-arm64': 0.28.2
6897+ '@esbuild/darwin-x64': 0.28.2
6898+ '@esbuild/freebsd-arm64': 0.28.2
6899+ '@esbuild/freebsd-x64': 0.28.2
6900+ '@esbuild/linux-arm': 0.28.2
6901+ '@esbuild/linux-arm64': 0.28.2
6902+ '@esbuild/linux-ia32': 0.28.2
6903+ '@esbuild/linux-loong64': 0.28.2
6904+ '@esbuild/linux-mips64el': 0.28.2
6905+ '@esbuild/linux-ppc64': 0.28.2
6906+ '@esbuild/linux-riscv64': 0.28.2
6907+ '@esbuild/linux-s390x': 0.28.2
6908+ '@esbuild/linux-x64': 0.28.2
6909+ '@esbuild/netbsd-arm64': 0.28.2
6910+ '@esbuild/netbsd-x64': 0.28.2
6911+ '@esbuild/openbsd-arm64': 0.28.2
6912+ '@esbuild/openbsd-x64': 0.28.2
6913+ '@esbuild/openharmony-arm64': 0.28.2
6914+ '@esbuild/sunos-x64': 0.28.2
6915+ '@esbuild/win32-arm64': 0.28.2
6916+ '@esbuild/win32-ia32': 0.28.2
6917+ '@esbuild/win32-x64': 0.28.2
6918+
6919+ escalade@3.2.0: {}
6920+
6921+ escape-string-regexp@4.0.0: {}
6922+
6923+ escape-string-regexp@5.0.0: {}
6924+
6925+ eslint-config-next@16.3.4(@typescript-eslint/parser@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3):
6926+ dependencies:
6927+ '@next/eslint-plugin-next': 16.3.4(eslint@9.39.5(jiti@2.7.0))
6928+ eslint: 9.39.5(jiti@2.7.0)
6929+ eslint-import-resolver-node: 0.3.10
6930+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0))
6931+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0))
6932+ eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.5(jiti@2.7.0))
6933+ eslint-plugin-react: 7.37.5(eslint@9.39.5(jiti@2.7.0))
6934+ eslint-plugin-react-hooks: 7.1.1(eslint@9.39.5(jiti@2.7.0))
6935+ globals: 16.4.0
6936+ typescript-eslint: 8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
6937+ optionalDependencies:
6938+ typescript: 5.9.3
6939+ transitivePeerDependencies:
6940+ - '@typescript-eslint/parser'
6941+ - eslint-import-resolver-webpack
6942+ - eslint-plugin-import-x
6943+ - supports-color
6944+
6945+ eslint-import-resolver-node@0.3.10:
6946+ dependencies:
6947+ debug: 3.2.7
6948+ is-core-module: 2.16.2
6949+ resolve: 2.0.0-next.7
6950+ transitivePeerDependencies:
6951+ - supports-color
6952+
6953+ eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)):
6954+ dependencies:
6955+ '@nolyfill/is-core-module': 1.0.39
6956+ debug: 4.4.3
6957+ eslint: 9.39.5(jiti@2.7.0)
6958+ get-tsconfig: 4.14.3
6959+ is-bun-module: 2.0.0
6960+ stable-hash: 0.0.5
6961+ tinyglobby: 0.2.17
6962+ unrs-resolver: 1.12.2
6963+ optionalDependencies:
6964+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0))
6965+ transitivePeerDependencies:
6966+ - supports-color
6967+
6968+ eslint-module-utils@2.14.0(@typescript-eslint/parser@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)):
6969+ dependencies:
6970+ debug: 3.2.7
6971+ optionalDependencies:
6972+ '@typescript-eslint/parser': 8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
6973+ eslint: 9.39.5(jiti@2.7.0)
6974+ eslint-import-resolver-node: 0.3.10
6975+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0))
6976+ transitivePeerDependencies:
6977+ - supports-color
6978+
6979+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)):
6980+ dependencies:
6981+ '@rtsao/scc': 1.1.0
6982+ array-includes: 3.1.9
6983+ array.prototype.findlastindex: 1.2.6
6984+ array.prototype.flat: 1.3.3
6985+ array.prototype.flatmap: 1.3.3
6986+ debug: 3.2.7
6987+ doctrine: 2.1.0
6988+ eslint: 9.39.5(jiti@2.7.0)
6989+ eslint-import-resolver-node: 0.3.10
6990+ eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0))
6991+ hasown: 2.0.4
6992+ is-core-module: 2.16.2
6993+ is-glob: 4.0.3
6994+ minimatch: 3.1.5
6995+ object.fromentries: 2.0.8
6996+ object.groupby: 1.0.3
6997+ object.values: 1.2.1
6998+ semver: 6.3.1
6999+ string.prototype.trimend: 1.0.10
7000+ tsconfig-paths: 3.15.0
7001+ optionalDependencies:
7002+ '@typescript-eslint/parser': 8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
7003+ transitivePeerDependencies:
7004+ - eslint-import-resolver-typescript
7005+ - eslint-import-resolver-webpack
7006+ - supports-color
7007+
7008+ eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5(jiti@2.7.0)):
7009+ dependencies:
7010+ aria-query: 5.3.2
7011+ array-includes: 3.1.9
7012+ array.prototype.flatmap: 1.3.3
7013+ ast-types-flow: 0.0.8
7014+ axe-core: 4.13.0
7015+ axobject-query: 4.1.0
7016+ damerau-levenshtein: 1.0.8
7017+ emoji-regex: 9.2.2
7018+ eslint: 9.39.5(jiti@2.7.0)
7019+ hasown: 2.0.4
7020+ jsx-ast-utils: 3.3.5
7021+ language-tags: 1.0.9
7022+ minimatch: 3.1.5
7023+ object.fromentries: 2.0.8
7024+ safe-regex-test: 1.1.0
7025+ string.prototype.includes: 2.0.1
7026+
7027+ eslint-plugin-react-hooks@7.1.1(eslint@9.39.5(jiti@2.7.0)):
7028+ dependencies:
7029+ '@babel/core': 7.29.7
7030+ '@babel/parser': 7.29.8
7031+ eslint: 9.39.5(jiti@2.7.0)
7032+ hermes-parser: 0.25.1
7033+ zod: 4.5.4
7034+ zod-validation-error: 4.0.2(zod@4.5.4)
7035+ transitivePeerDependencies:
7036+ - supports-color
7037+
7038+ eslint-plugin-react@7.37.5(eslint@9.39.5(jiti@2.7.0)):
7039+ dependencies:
7040+ array-includes: 3.1.9
7041+ array.prototype.findlast: 1.2.5
7042+ array.prototype.flatmap: 1.3.3
7043+ array.prototype.tosorted: 1.1.4
7044+ doctrine: 2.1.0
7045+ es-iterator-helpers: 1.4.0
7046+ eslint: 9.39.5(jiti@2.7.0)
7047+ estraverse: 5.3.0
7048+ hasown: 2.0.4
7049+ jsx-ast-utils: 3.3.5
7050+ minimatch: 3.1.5
7051+ object.entries: 1.1.9
7052+ object.fromentries: 2.0.8
7053+ object.values: 1.2.1
7054+ prop-types: 15.8.1
7055+ resolve: 2.0.0-next.7
7056+ semver: 6.3.1
7057+ string.prototype.matchall: 4.1.0
7058+ string.prototype.repeat: 1.0.0
7059+
7060+ eslint-scope@8.4.0:
7061+ dependencies:
7062+ esrecurse: 4.3.0
7063+ estraverse: 5.3.0
7064+
7065+ eslint-visitor-keys@3.4.3: {}
7066+
7067+ eslint-visitor-keys@4.2.1: {}
7068+
7069+ eslint-visitor-keys@5.0.1: {}
7070+
7071+ eslint@9.39.5(jiti@2.7.0):
7072+ dependencies:
7073+ '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0))
7074+ '@eslint-community/regexpp': 4.12.2
7075+ '@eslint/config-array': 0.21.2
7076+ '@eslint/config-helpers': 0.4.2
7077+ '@eslint/core': 0.17.0
7078+ '@eslint/eslintrc': 3.3.7
7079+ '@eslint/js': 9.39.5
7080+ '@eslint/plugin-kit': 0.4.1
7081+ '@humanfs/node': 0.16.8
7082+ '@humanwhocodes/module-importer': 1.0.1
7083+ '@humanwhocodes/retry': 0.4.3
7084+ '@types/estree': 1.0.9
7085+ ajv: 6.15.0
7086+ chalk: 4.1.2
7087+ cross-spawn: 7.0.6
7088+ debug: 4.4.3
7089+ escape-string-regexp: 4.0.0
7090+ eslint-scope: 8.4.0
7091+ eslint-visitor-keys: 4.2.1
7092+ espree: 10.4.0
7093+ esquery: 1.7.0
7094+ esutils: 2.0.3
7095+ fast-deep-equal: 3.1.3
7096+ file-entry-cache: 8.0.0
7097+ find-up: 5.0.0
7098+ glob-parent: 6.0.2
7099+ ignore: 5.3.2
7100+ imurmurhash: 0.1.4
7101+ is-glob: 4.0.3
7102+ json-stable-stringify-without-jsonify: 1.0.1
7103+ lodash.merge: 4.6.2
7104+ minimatch: 3.1.5
7105+ natural-compare: 1.4.0
7106+ optionator: 0.9.4
7107+ optionalDependencies:
7108+ jiti: 2.7.0
7109+ transitivePeerDependencies:
7110+ - supports-color
7111+
7112+ espree@10.4.0:
7113+ dependencies:
7114+ acorn: 8.18.0
7115+ acorn-jsx: 5.3.2(acorn@8.18.0)
7116+ eslint-visitor-keys: 4.2.1
7117+
7118+ esquery@1.7.0:
7119+ dependencies:
7120+ estraverse: 5.3.0
7121+
7122+ esrecurse@4.3.0:
7123+ dependencies:
7124+ estraverse: 5.3.0
7125+
7126+ estraverse@5.3.0: {}
7127+
7128+ estree-util-is-identifier-name@3.0.0: {}
7129+
7130+ estree-walker@3.0.3:
7131+ dependencies:
7132+ '@types/estree': 1.0.9
7133+
7134+ esutils@2.0.3: {}
7135+
7136+ eventemitter3@5.0.4: {}
7137+
7138+ expect-type@1.4.0: {}
7139+
7140+ extend@3.0.2: {}
7141+
7142+ fast-deep-equal@3.1.3: {}
7143+
7144+ fast-glob@3.3.1:
7145+ dependencies:
7146+ '@nodelib/fs.stat': 2.0.5
7147+ '@nodelib/fs.walk': 1.2.8
7148+ glob-parent: 5.1.2
7149+ merge2: 1.4.1
7150+ micromatch: 4.0.8
7151+
7152+ fast-json-stable-stringify@2.1.0: {}
7153+
7154+ fast-levenshtein@2.0.6: {}
7155+
7156+ fast-sha256@1.3.0: {}
7157+
7158+ fastq@1.20.3:
7159+ dependencies:
7160+ reusify: 1.1.0
7161+
7162+ fdir@6.5.0(picomatch@4.0.7):
7163+ optionalDependencies:
7164+ picomatch: 4.0.7
7165+
7166+ fetch-blob@3.2.0:
7167+ dependencies:
7168+ node-domexception: 1.0.0
7169+ web-streams-polyfill: 3.3.3
7170+
7171+ file-entry-cache@8.0.0:
7172+ dependencies:
7173+ flat-cache: 4.0.1
7174+
7175+ fill-range@7.1.1:
7176+ dependencies:
7177+ to-regex-range: 5.0.1
7178+
7179+ find-up@5.0.0:
7180+ dependencies:
7181+ locate-path: 6.0.0
7182+ path-exists: 4.0.0
7183+
7184+ flat-cache@4.0.1:
7185+ dependencies:
7186+ flatted: 3.4.4
7187+ keyv: 4.5.4
7188+
7189+ flatted@3.4.4: {}
7190+
7191+ for-each@0.3.5:
7192+ dependencies:
7193+ is-callable: 1.2.7
7194+
7195+ formdata-polyfill@4.0.10:
7196+ dependencies:
7197+ fetch-blob: 3.2.0
7198+
7199+ framer-motion@12.43.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
7200+ dependencies:
7201+ motion-dom: 12.43.0
7202+ motion-utils: 12.39.0
7203+ tslib: 2.8.1
7204+ optionalDependencies:
7205+ react: 19.2.8
7206+ react-dom: 19.2.8(react@19.2.8)
7207+
7208+ fsevents@2.3.3:
7209+ optional: true
7210+
7211+ function-bind@1.1.2: {}
7212+
7213+ function.prototype.name@1.2.0:
7214+ dependencies:
7215+ call-bind: 1.0.9
7216+ call-bound: 1.0.4
7217+ es-define-property: 1.0.1
7218+ es-errors: 1.3.0
7219+ functions-have-names: 1.2.3
7220+ has-property-descriptors: 1.0.2
7221+ hasown: 2.0.4
7222+ is-callable: 1.2.7
7223+ is-document.all: 1.0.0
7224+
7225+ functions-have-names@1.2.3: {}
7226+
7227+ gaxios@7.3.1:
7228+ dependencies:
7229+ extend: 3.0.2
7230+ https-proxy-agent: 7.0.6
7231+ node-fetch: 3.3.2
7232+ transitivePeerDependencies:
7233+ - supports-color
7234+
7235+ gcp-metadata@8.1.2:
7236+ dependencies:
7237+ gaxios: 7.3.1
7238+ google-logging-utils: 1.1.3
7239+ json-bigint: 1.0.0
7240+ transitivePeerDependencies:
7241+ - supports-color
7242+
7243+ geist@1.7.2(next@16.3.4(@babel/core@7.29.7)(@playwright/test@1.63.0)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)):
7244+ dependencies:
7245+ next: 16.3.4(@babel/core@7.29.7)(@playwright/test@1.63.0)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
7246+
7247+ generator-function@2.0.1: {}
7248+
7249+ gensync@1.0.0-beta.2: {}
7250+
7251+ get-intrinsic@1.3.0:
7252+ dependencies:
7253+ call-bind-apply-helpers: 1.0.2
7254+ es-define-property: 1.0.1
7255+ es-errors: 1.3.0
7256+ es-object-atoms: 1.1.2
7257+ function-bind: 1.1.2
7258+ get-proto: 1.0.1
7259+ gopd: 1.2.0
7260+ has-symbols: 1.1.0
7261+ hasown: 2.0.4
7262+ math-intrinsics: 1.1.0
7263+
7264+ get-nonce@1.0.1: {}
7265+
7266+ get-proto@1.0.1:
7267+ dependencies:
7268+ dunder-proto: 1.0.1
7269+ es-object-atoms: 1.1.2
7270+
7271+ get-symbol-description@1.1.0:
7272+ dependencies:
7273+ call-bound: 1.0.4
7274+ es-errors: 1.3.0
7275+ get-intrinsic: 1.3.0
7276+
7277+ get-tsconfig@4.14.3:
7278+ dependencies:
7279+ resolve-pkg-maps: 1.0.0
7280+
7281+ glob-parent@5.1.2:
7282+ dependencies:
7283+ is-glob: 4.0.3
7284+
7285+ glob-parent@6.0.2:
7286+ dependencies:
7287+ is-glob: 4.0.3
7288+
7289+ globals@14.0.0: {}
7290+
7291+ globals@16.4.0: {}
7292+
7293+ globalthis@1.0.4:
7294+ dependencies:
7295+ define-properties: 1.2.1
7296+ gopd: 1.2.0
7297+
7298+ google-auth-library@10.9.1:
7299+ dependencies:
7300+ base64-js: 1.5.1
7301+ ecdsa-sig-formatter: 1.0.11
7302+ gaxios: 7.3.1
7303+ gcp-metadata: 8.1.2
7304+ google-logging-utils: 1.1.3
7305+ jws: 4.0.1
7306+ transitivePeerDependencies:
7307+ - supports-color
7308+
7309+ google-logging-utils@1.1.3: {}
7310+
7311+ gopd@1.2.0: {}
7312+
7313+ graceful-fs@4.2.11: {}
7314+
7315+ has-bigints@1.1.0: {}
7316+
7317+ has-flag@4.0.0: {}
7318+
7319+ has-property-descriptors@1.0.2:
7320+ dependencies:
7321+ es-define-property: 1.0.1
7322+
7323+ has-proto@1.2.0:
7324+ dependencies:
7325+ dunder-proto: 1.0.1
7326+
7327+ has-symbols@1.1.0: {}
7328+
7329+ has-tostringtag@1.0.2:
7330+ dependencies:
7331+ has-symbols: 1.1.0
7332+
7333+ hasown@2.0.4:
7334+ dependencies:
7335+ function-bind: 1.1.2
7336+
7337+ hast-util-from-parse5@8.0.3:
7338+ dependencies:
7339+ '@types/hast': 3.0.5
7340+ '@types/unist': 3.0.3
7341+ devlop: 1.1.0
7342+ hastscript: 9.0.1
7343+ property-information: 7.2.0
7344+ vfile: 6.0.3
7345+ vfile-location: 5.0.3
7346+ web-namespaces: 2.0.1
7347+
7348+ hast-util-parse-selector@4.0.0:
7349+ dependencies:
7350+ '@types/hast': 3.0.5
7351+
7352+ hast-util-raw@9.1.0:
7353+ dependencies:
7354+ '@types/hast': 3.0.5
7355+ '@types/unist': 3.0.3
7356+ '@ungap/structured-clone': 1.4.0
7357+ hast-util-from-parse5: 8.0.3
7358+ hast-util-to-parse5: 8.0.1
7359+ html-void-elements: 3.0.0
7360+ mdast-util-to-hast: 13.2.1
7361+ parse5: 7.3.0
7362+ unist-util-position: 5.0.0
7363+ unist-util-visit: 5.1.0
7364+ vfile: 6.0.3
7365+ web-namespaces: 2.0.1
7366+ zwitch: 2.0.4
7367+
7368+ hast-util-to-html@9.0.5:
7369+ dependencies:
7370+ '@types/hast': 3.0.5
7371+ '@types/unist': 3.0.3
7372+ ccount: 2.0.1
7373+ comma-separated-tokens: 2.0.3
7374+ hast-util-whitespace: 3.0.0
7375+ html-void-elements: 3.0.0
7376+ mdast-util-to-hast: 13.2.1
7377+ property-information: 7.2.0
7378+ space-separated-tokens: 2.0.2
7379+ stringify-entities: 4.0.4
7380+ zwitch: 2.0.4
7381+
7382+ hast-util-to-jsx-runtime@2.3.6:
7383+ dependencies:
7384+ '@types/estree': 1.0.9
7385+ '@types/hast': 3.0.5
7386+ '@types/unist': 3.0.3
7387+ comma-separated-tokens: 2.0.3
7388+ devlop: 1.1.0
7389+ estree-util-is-identifier-name: 3.0.0
7390+ hast-util-whitespace: 3.0.0
7391+ mdast-util-mdx-expression: 2.0.1
7392+ mdast-util-mdx-jsx: 3.2.0
7393+ mdast-util-mdxjs-esm: 2.0.1
7394+ property-information: 7.2.0
7395+ space-separated-tokens: 2.0.2
7396+ style-to-js: 1.1.21
7397+ unist-util-position: 5.0.0
7398+ vfile-message: 4.0.3
7399+ transitivePeerDependencies:
7400+ - supports-color
7401+
7402+ hast-util-to-parse5@8.0.1:
7403+ dependencies:
7404+ '@types/hast': 3.0.5
7405+ comma-separated-tokens: 2.0.3
7406+ devlop: 1.1.0
7407+ property-information: 7.2.0
7408+ space-separated-tokens: 2.0.2
7409+ web-namespaces: 2.0.1
7410+ zwitch: 2.0.4
7411+
7412+ hast-util-whitespace@3.0.0:
7413+ dependencies:
7414+ '@types/hast': 3.0.5
7415+
7416+ hastscript@9.0.1:
7417+ dependencies:
7418+ '@types/hast': 3.0.5
7419+ comma-separated-tokens: 2.0.3
7420+ hast-util-parse-selector: 4.0.0
7421+ property-information: 7.2.0
7422+ space-separated-tokens: 2.0.2
7423+
7424+ hermes-estree@0.25.1: {}
7425+
7426+ hermes-parser@0.25.1:
7427+ dependencies:
7428+ hermes-estree: 0.25.1
7429+
7430+ html-url-attributes@3.0.1: {}
7431+
7432+ html-void-elements@3.0.0: {}
7433+
7434+ https-proxy-agent@7.0.6:
7435+ dependencies:
7436+ agent-base: 7.1.4
7437+ debug: 4.4.3
7438+ transitivePeerDependencies:
7439+ - supports-color
7440+
7441+ ignore@5.3.2: {}
7442+
7443+ ignore@7.0.8: {}
7444+
7445+ immer@11.1.18: {}
7446+
7447+ import-fresh@3.3.1:
7448+ dependencies:
7449+ parent-module: 1.0.1
7450+ resolve-from: 4.0.0
7451+
7452+ imurmurhash@0.1.4: {}
7453+
7454+ inline-style-parser@0.2.7: {}
7455+
7456+ internal-slot@1.1.0:
7457+ dependencies:
7458+ es-errors: 1.3.0
7459+ hasown: 2.0.4
7460+ side-channel: 1.1.1
7461+
7462+ internmap@2.0.3: {}
7463+
7464+ is-alphabetical@2.0.1: {}
7465+
7466+ is-alphanumerical@2.0.1:
7467+ dependencies:
7468+ is-alphabetical: 2.0.1
7469+ is-decimal: 2.0.1
7470+
7471+ is-array-buffer@3.0.5:
7472+ dependencies:
7473+ call-bind: 1.0.9
7474+ call-bound: 1.0.4
7475+ get-intrinsic: 1.3.0
7476+
7477+ is-async-function@2.1.1:
7478+ dependencies:
7479+ async-function: 1.0.0
7480+ call-bound: 1.0.4
7481+ get-proto: 1.0.1
7482+ has-tostringtag: 1.0.2
7483+ safe-regex-test: 1.1.0
7484+
7485+ is-bigint@1.1.0:
7486+ dependencies:
7487+ has-bigints: 1.1.0
7488+
7489+ is-boolean-object@1.2.2:
7490+ dependencies:
7491+ call-bound: 1.0.4
7492+ has-tostringtag: 1.0.2
7493+
7494+ is-bun-module@2.0.0:
7495+ dependencies:
7496+ semver: 7.8.5
7497+
7498+ is-callable@1.2.7: {}
7499+
7500+ is-core-module@2.16.2:
7501+ dependencies:
7502+ hasown: 2.0.4
7503+
7504+ is-data-view@1.0.2:
7505+ dependencies:
7506+ call-bound: 1.0.4
7507+ get-intrinsic: 1.3.0
7508+ is-typed-array: 1.1.15
7509+
7510+ is-date-object@1.1.0:
7511+ dependencies:
7512+ call-bound: 1.0.4
7513+ has-tostringtag: 1.0.2
7514+
7515+ is-decimal@2.0.1: {}
7516+
7517+ is-document.all@1.0.0:
7518+ dependencies:
7519+ call-bound: 1.0.4
7520+
7521+ is-extglob@2.1.1: {}
7522+
7523+ is-finalizationregistry@1.1.1:
7524+ dependencies:
7525+ call-bound: 1.0.4
7526+
7527+ is-generator-function@1.1.2:
7528+ dependencies:
7529+ call-bound: 1.0.4
7530+ generator-function: 2.0.1
7531+ get-proto: 1.0.1
7532+ has-tostringtag: 1.0.2
7533+ safe-regex-test: 1.1.0
7534+
7535+ is-glob@4.0.3:
7536+ dependencies:
7537+ is-extglob: 2.1.1
7538+
7539+ is-hexadecimal@2.0.1: {}
7540+
7541+ is-map@2.0.3: {}
7542+
7543+ is-negative-zero@2.0.3: {}
7544+
7545+ is-number-object@1.1.1:
7546+ dependencies:
7547+ call-bound: 1.0.4
7548+ has-tostringtag: 1.0.2
7549+
7550+ is-number@7.0.0: {}
7551+
7552+ is-plain-obj@4.1.0: {}
7553+
7554+ is-regex@1.2.1:
7555+ dependencies:
7556+ call-bound: 1.0.4
7557+ gopd: 1.2.0
7558+ has-tostringtag: 1.0.2
7559+ hasown: 2.0.4
7560+
7561+ is-set@2.0.3: {}
7562+
7563+ is-shared-array-buffer@1.0.4:
7564+ dependencies:
7565+ call-bound: 1.0.4
7566+
7567+ is-string@1.1.1:
7568+ dependencies:
7569+ call-bound: 1.0.4
7570+ has-tostringtag: 1.0.2
7571+
7572+ is-symbol@1.1.1:
7573+ dependencies:
7574+ call-bound: 1.0.4
7575+ has-symbols: 1.1.0
7576+ safe-regex-test: 1.1.0
7577+
7578+ is-typed-array@1.1.15:
7579+ dependencies:
7580+ which-typed-array: 1.1.22
7581+
7582+ is-weakmap@2.0.2: {}
7583+
7584+ is-weakref@1.1.1:
7585+ dependencies:
7586+ call-bound: 1.0.4
7587+
7588+ is-weakset@2.0.4:
7589+ dependencies:
7590+ call-bound: 1.0.4
7591+ get-intrinsic: 1.3.0
7592+
7593+ isarray@2.0.5: {}
7594+
7595+ isexe@2.0.0: {}
7596+
7597+ iterator.prototype@1.1.5:
7598+ dependencies:
7599+ define-data-property: 1.1.4
7600+ es-object-atoms: 1.1.2
7601+ get-intrinsic: 1.3.0
7602+ get-proto: 1.0.1
7603+ has-symbols: 1.1.0
7604+ set-function-name: 2.0.2
7605+
7606+ jiti@2.7.0: {}
7607+
7608+ jose@6.2.12: {}
7609+
7610+ js-tokens@4.0.0: {}
7611+
7612+ js-tokens@9.0.1: {}
7613+
7614+ js-yaml@4.3.2:
7615+ dependencies:
7616+ argparse: 2.0.1
7617+
7618+ jsesc@3.1.0: {}
7619+
7620+ json-bigint@1.0.0:
7621+ dependencies:
7622+ bignumber.js: 9.3.1
7623+
7624+ json-buffer@3.0.1: {}
7625+
7626+ json-schema-to-ts@3.1.1:
7627+ dependencies:
7628+ '@babel/runtime': 7.29.7
7629+ ts-algebra: 2.0.0
7630+
7631+ json-schema-traverse@0.4.1: {}
7632+
7633+ json-stable-stringify-without-jsonify@1.0.1: {}
7634+
7635+ json5@1.0.2:
7636+ dependencies:
7637+ minimist: 1.2.8
7638+
7639+ json5@2.2.3: {}
7640+
7641+ jsx-ast-utils@3.3.5:
7642+ dependencies:
7643+ array-includes: 3.1.9
7644+ array.prototype.flat: 1.3.3
7645+ object.assign: 4.1.7
7646+ object.values: 1.2.1
7647+
7648+ jwa@2.0.1:
7649+ dependencies:
7650+ buffer-equal-constant-time: 1.0.1
7651+ ecdsa-sig-formatter: 1.0.11
7652+ safe-buffer: 5.2.1
7653+
7654+ jws@4.0.1:
7655+ dependencies:
7656+ jwa: 2.0.1
7657+ safe-buffer: 5.2.1
7658+
7659+ keyv@4.5.4:
7660+ dependencies:
7661+ json-buffer: 3.0.1
7662+
7663+ kysely@0.29.5: {}
7664+
7665+ language-subtag-registry@0.3.23: {}
7666+
7667+ language-tags@1.0.9:
7668+ dependencies:
7669+ language-subtag-registry: 0.3.23
7670+
7671+ levn@0.4.1:
7672+ dependencies:
7673+ prelude-ls: 1.2.1
7674+ type-check: 0.4.0
7675+
7676+ lightningcss-android-arm64@1.32.0:
7677+ optional: true
7678+
7679+ lightningcss-darwin-arm64@1.32.0:
7680+ optional: true
7681+
7682+ lightningcss-darwin-x64@1.32.0:
7683+ optional: true
7684+
7685+ lightningcss-freebsd-x64@1.32.0:
7686+ optional: true
7687+
7688+ lightningcss-linux-arm-gnueabihf@1.32.0:
7689+ optional: true
7690+
7691+ lightningcss-linux-arm64-gnu@1.32.0:
7692+ optional: true
7693+
7694+ lightningcss-linux-arm64-musl@1.32.0:
7695+ optional: true
7696+
7697+ lightningcss-linux-x64-gnu@1.32.0:
7698+ optional: true
7699+
7700+ lightningcss-linux-x64-musl@1.32.0:
7701+ optional: true
7702+
7703+ lightningcss-win32-arm64-msvc@1.32.0:
7704+ optional: true
7705+
7706+ lightningcss-win32-x64-msvc@1.32.0:
7707+ optional: true
7708+
7709+ lightningcss@1.32.0:
7710+ dependencies:
7711+ detect-libc: 2.1.2
7712+ optionalDependencies:
7713+ lightningcss-android-arm64: 1.32.0
7714+ lightningcss-darwin-arm64: 1.32.0
7715+ lightningcss-darwin-x64: 1.32.0
7716+ lightningcss-freebsd-x64: 1.32.0
7717+ lightningcss-linux-arm-gnueabihf: 1.32.0
7718+ lightningcss-linux-arm64-gnu: 1.32.0
7719+ lightningcss-linux-arm64-musl: 1.32.0
7720+ lightningcss-linux-x64-gnu: 1.32.0
7721+ lightningcss-linux-x64-musl: 1.32.0
7722+ lightningcss-win32-arm64-msvc: 1.32.0
7723+ lightningcss-win32-x64-msvc: 1.32.0
7724+
7725+ locate-path@6.0.0:
7726+ dependencies:
7727+ p-locate: 5.0.0
7728+
7729+ lodash.merge@4.6.2: {}
7730+
7731+ long@5.3.2: {}
7732+
7733+ longest-streak@3.1.0: {}
7734+
7735+ loose-envify@1.4.0:
7736+ dependencies:
7737+ js-tokens: 4.0.0
7738+
7739+ loupe@3.2.1: {}
7740+
7741+ lru-cache@5.1.1:
7742+ dependencies:
7743+ yallist: 3.1.1
7744+
7745+ lucide-react@1.42.0(react@19.2.8):
7746+ dependencies:
7747+ react: 19.2.8
7748+
7749+ magic-string@0.30.21:
7750+ dependencies:
7751+ '@jridgewell/sourcemap-codec': 1.6.0
7752+
7753+ markdown-table@3.0.4: {}
7754+
7755+ math-intrinsics@1.1.0: {}
7756+
7757+ mdast-util-find-and-replace@3.0.2:
7758+ dependencies:
7759+ '@types/mdast': 4.0.4
7760+ escape-string-regexp: 5.0.0
7761+ unist-util-is: 6.0.1
7762+ unist-util-visit-parents: 6.0.2
7763+
7764+ mdast-util-from-markdown@2.0.3:
7765+ dependencies:
7766+ '@types/mdast': 4.0.4
7767+ '@types/unist': 3.0.3
7768+ decode-named-character-reference: 1.3.0
7769+ devlop: 1.1.0
7770+ mdast-util-to-string: 4.0.0
7771+ micromark: 4.0.2
7772+ micromark-util-decode-numeric-character-reference: 2.0.2
7773+ micromark-util-decode-string: 2.0.1
7774+ micromark-util-normalize-identifier: 2.0.1
7775+ micromark-util-symbol: 2.0.1
7776+ micromark-util-types: 2.0.2
7777+ unist-util-stringify-position: 4.0.0
7778+ transitivePeerDependencies:
7779+ - supports-color
7780+
7781+ mdast-util-gfm-autolink-literal@2.0.1:
7782+ dependencies:
7783+ '@types/mdast': 4.0.4
7784+ ccount: 2.0.1
7785+ devlop: 1.1.0
7786+ mdast-util-find-and-replace: 3.0.2
7787+ micromark-util-character: 2.1.1
7788+
7789+ mdast-util-gfm-footnote@2.1.0:
7790+ dependencies:
7791+ '@types/mdast': 4.0.4
7792+ devlop: 1.1.0
7793+ mdast-util-from-markdown: 2.0.3
7794+ mdast-util-to-markdown: 2.1.2
7795+ micromark-util-normalize-identifier: 2.0.1
7796+ transitivePeerDependencies:
7797+ - supports-color
7798+
7799+ mdast-util-gfm-strikethrough@2.0.0:
7800+ dependencies:
7801+ '@types/mdast': 4.0.4
7802+ mdast-util-from-markdown: 2.0.3
7803+ mdast-util-to-markdown: 2.1.2
7804+ transitivePeerDependencies:
7805+ - supports-color
7806+
7807+ mdast-util-gfm-table@2.0.0:
7808+ dependencies:
7809+ '@types/mdast': 4.0.4
7810+ devlop: 1.1.0
7811+ markdown-table: 3.0.4
7812+ mdast-util-from-markdown: 2.0.3
7813+ mdast-util-to-markdown: 2.1.2
7814+ transitivePeerDependencies:
7815+ - supports-color
7816+
7817+ mdast-util-gfm-task-list-item@2.0.0:
7818+ dependencies:
7819+ '@types/mdast': 4.0.4
7820+ devlop: 1.1.0
7821+ mdast-util-from-markdown: 2.0.3
7822+ mdast-util-to-markdown: 2.1.2
7823+ transitivePeerDependencies:
7824+ - supports-color
7825+
7826+ mdast-util-gfm@3.1.0:
7827+ dependencies:
7828+ mdast-util-from-markdown: 2.0.3
7829+ mdast-util-gfm-autolink-literal: 2.0.1
7830+ mdast-util-gfm-footnote: 2.1.0
7831+ mdast-util-gfm-strikethrough: 2.0.0
7832+ mdast-util-gfm-table: 2.0.0
7833+ mdast-util-gfm-task-list-item: 2.0.0
7834+ mdast-util-to-markdown: 2.1.2
7835+ transitivePeerDependencies:
7836+ - supports-color
7837+
7838+ mdast-util-mdx-expression@2.0.1:
7839+ dependencies:
7840+ '@types/estree-jsx': 1.0.5
7841+ '@types/hast': 3.0.5
7842+ '@types/mdast': 4.0.4
7843+ devlop: 1.1.0
7844+ mdast-util-from-markdown: 2.0.3
7845+ mdast-util-to-markdown: 2.1.2
7846+ transitivePeerDependencies:
7847+ - supports-color
7848+
7849+ mdast-util-mdx-jsx@3.2.0:
7850+ dependencies:
7851+ '@types/estree-jsx': 1.0.5
7852+ '@types/hast': 3.0.5
7853+ '@types/mdast': 4.0.4
7854+ '@types/unist': 3.0.3
7855+ ccount: 2.0.1
7856+ devlop: 1.1.0
7857+ mdast-util-from-markdown: 2.0.3
7858+ mdast-util-to-markdown: 2.1.2
7859+ parse-entities: 4.0.2
7860+ stringify-entities: 4.0.4
7861+ unist-util-stringify-position: 4.0.0
7862+ vfile-message: 4.0.3
7863+ transitivePeerDependencies:
7864+ - supports-color
7865+
7866+ mdast-util-mdxjs-esm@2.0.1:
7867+ dependencies:
7868+ '@types/estree-jsx': 1.0.5
7869+ '@types/hast': 3.0.5
7870+ '@types/mdast': 4.0.4
7871+ devlop: 1.1.0
7872+ mdast-util-from-markdown: 2.0.3
7873+ mdast-util-to-markdown: 2.1.2
7874+ transitivePeerDependencies:
7875+ - supports-color
7876+
7877+ mdast-util-phrasing@4.1.0:
7878+ dependencies:
7879+ '@types/mdast': 4.0.4
7880+ unist-util-is: 6.0.1
7881+
7882+ mdast-util-to-hast@13.2.1:
7883+ dependencies:
7884+ '@types/hast': 3.0.5
7885+ '@types/mdast': 4.0.4
7886+ '@ungap/structured-clone': 1.4.0
7887+ devlop: 1.1.0
7888+ micromark-util-sanitize-uri: 2.0.1
7889+ trim-lines: 3.0.1
7890+ unist-util-position: 5.0.0
7891+ unist-util-visit: 5.1.0
7892+ vfile: 6.0.3
7893+
7894+ mdast-util-to-markdown@2.1.2:
7895+ dependencies:
7896+ '@types/mdast': 4.0.4
7897+ '@types/unist': 3.0.3
7898+ longest-streak: 3.1.0
7899+ mdast-util-phrasing: 4.1.0
7900+ mdast-util-to-string: 4.0.0
7901+ micromark-util-classify-character: 2.0.1
7902+ micromark-util-decode-string: 2.0.1
7903+ unist-util-visit: 5.1.0
7904+ zwitch: 2.0.4
7905+
7906+ mdast-util-to-string@4.0.0:
7907+ dependencies:
7908+ '@types/mdast': 4.0.4
7909+
7910+ merge2@1.4.1: {}
7911+
7912+ micromark-core-commonmark@2.0.3:
7913+ dependencies:
7914+ decode-named-character-reference: 1.3.0
7915+ devlop: 1.1.0
7916+ micromark-factory-destination: 2.0.1
7917+ micromark-factory-label: 2.0.1
7918+ micromark-factory-space: 2.0.1
7919+ micromark-factory-title: 2.0.1
7920+ micromark-factory-whitespace: 2.0.1
7921+ micromark-util-character: 2.1.1
7922+ micromark-util-chunked: 2.0.1
7923+ micromark-util-classify-character: 2.0.1
7924+ micromark-util-html-tag-name: 2.0.1
7925+ micromark-util-normalize-identifier: 2.0.1
7926+ micromark-util-resolve-all: 2.0.1
7927+ micromark-util-subtokenize: 2.1.0
7928+ micromark-util-symbol: 2.0.1
7929+ micromark-util-types: 2.0.2
7930+
7931+ micromark-extension-gfm-autolink-literal@2.1.0:
7932+ dependencies:
7933+ micromark-util-character: 2.1.1
7934+ micromark-util-sanitize-uri: 2.0.1
7935+ micromark-util-symbol: 2.0.1
7936+ micromark-util-types: 2.0.2
7937+
7938+ micromark-extension-gfm-footnote@2.1.0:
7939+ dependencies:
7940+ devlop: 1.1.0
7941+ micromark-core-commonmark: 2.0.3
7942+ micromark-factory-space: 2.0.1
7943+ micromark-util-character: 2.1.1
7944+ micromark-util-normalize-identifier: 2.0.1
7945+ micromark-util-sanitize-uri: 2.0.1
7946+ micromark-util-symbol: 2.0.1
7947+ micromark-util-types: 2.0.2
7948+
7949+ micromark-extension-gfm-strikethrough@2.1.0:
7950+ dependencies:
7951+ devlop: 1.1.0
7952+ micromark-util-chunked: 2.0.1
7953+ micromark-util-classify-character: 2.0.1
7954+ micromark-util-resolve-all: 2.0.1
7955+ micromark-util-symbol: 2.0.1
7956+ micromark-util-types: 2.0.2
7957+
7958+ micromark-extension-gfm-table@2.1.1:
7959+ dependencies:
7960+ devlop: 1.1.0
7961+ micromark-factory-space: 2.0.1
7962+ micromark-util-character: 2.1.1
7963+ micromark-util-symbol: 2.0.1
7964+ micromark-util-types: 2.0.2
7965+
7966+ micromark-extension-gfm-tagfilter@2.0.0:
7967+ dependencies:
7968+ micromark-util-types: 2.0.2
7969+
7970+ micromark-extension-gfm-task-list-item@2.1.0:
7971+ dependencies:
7972+ devlop: 1.1.0
7973+ micromark-factory-space: 2.0.1
7974+ micromark-util-character: 2.1.1
7975+ micromark-util-symbol: 2.0.1
7976+ micromark-util-types: 2.0.2
7977+
7978+ micromark-extension-gfm@3.0.0:
7979+ dependencies:
7980+ micromark-extension-gfm-autolink-literal: 2.1.0
7981+ micromark-extension-gfm-footnote: 2.1.0
7982+ micromark-extension-gfm-strikethrough: 2.1.0
7983+ micromark-extension-gfm-table: 2.1.1
7984+ micromark-extension-gfm-tagfilter: 2.0.0
7985+ micromark-extension-gfm-task-list-item: 2.1.0
7986+ micromark-util-combine-extensions: 2.0.1
7987+ micromark-util-types: 2.0.2
7988+
7989+ micromark-factory-destination@2.0.1:
7990+ dependencies:
7991+ micromark-util-character: 2.1.1
7992+ micromark-util-symbol: 2.0.1
7993+ micromark-util-types: 2.0.2
7994+
7995+ micromark-factory-label@2.0.1:
7996+ dependencies:
7997+ devlop: 1.1.0
7998+ micromark-util-character: 2.1.1
7999+ micromark-util-symbol: 2.0.1
8000+ micromark-util-types: 2.0.2
8001+
8002+ micromark-factory-space@2.0.1:
8003+ dependencies:
8004+ micromark-util-character: 2.1.1
8005+ micromark-util-types: 2.0.2
8006+
8007+ micromark-factory-title@2.0.1:
8008+ dependencies:
8009+ micromark-factory-space: 2.0.1
8010+ micromark-util-character: 2.1.1
8011+ micromark-util-symbol: 2.0.1
8012+ micromark-util-types: 2.0.2
8013+
8014+ micromark-factory-whitespace@2.0.1:
8015+ dependencies:
8016+ micromark-factory-space: 2.0.1
8017+ micromark-util-character: 2.1.1
8018+ micromark-util-symbol: 2.0.1
8019+ micromark-util-types: 2.0.2
8020+
8021+ micromark-util-character@2.1.1:
8022+ dependencies:
8023+ micromark-util-symbol: 2.0.1
8024+ micromark-util-types: 2.0.2
8025+
8026+ micromark-util-chunked@2.0.1:
8027+ dependencies:
8028+ micromark-util-symbol: 2.0.1
8029+
8030+ micromark-util-classify-character@2.0.1:
8031+ dependencies:
8032+ micromark-util-character: 2.1.1
8033+ micromark-util-symbol: 2.0.1
8034+ micromark-util-types: 2.0.2
8035+
8036+ micromark-util-combine-extensions@2.0.1:
8037+ dependencies:
8038+ micromark-util-chunked: 2.0.1
8039+ micromark-util-types: 2.0.2
8040+
8041+ micromark-util-decode-numeric-character-reference@2.0.2:
8042+ dependencies:
8043+ micromark-util-symbol: 2.0.1
8044+
8045+ micromark-util-decode-string@2.0.1:
8046+ dependencies:
8047+ decode-named-character-reference: 1.3.0
8048+ micromark-util-character: 2.1.1
8049+ micromark-util-decode-numeric-character-reference: 2.0.2
8050+ micromark-util-symbol: 2.0.1
8051+
8052+ micromark-util-encode@2.0.1: {}
8053+
8054+ micromark-util-html-tag-name@2.0.1: {}
8055+
8056+ micromark-util-normalize-identifier@2.0.1:
8057+ dependencies:
8058+ micromark-util-symbol: 2.0.1
8059+
8060+ micromark-util-resolve-all@2.0.1:
8061+ dependencies:
8062+ micromark-util-types: 2.0.2
8063+
8064+ micromark-util-sanitize-uri@2.0.1:
8065+ dependencies:
8066+ micromark-util-character: 2.1.1
8067+ micromark-util-encode: 2.0.1
8068+ micromark-util-symbol: 2.0.1
8069+
8070+ micromark-util-subtokenize@2.1.0:
8071+ dependencies:
8072+ devlop: 1.1.0
8073+ micromark-util-chunked: 2.0.1
8074+ micromark-util-symbol: 2.0.1
8075+ micromark-util-types: 2.0.2
8076+
8077+ micromark-util-symbol@2.0.1: {}
8078+
8079+ micromark-util-types@2.0.2: {}
8080+
8081+ micromark@4.0.2:
8082+ dependencies:
8083+ '@types/debug': 4.1.13
8084+ debug: 4.4.3
8085+ decode-named-character-reference: 1.3.0
8086+ devlop: 1.1.0
8087+ micromark-core-commonmark: 2.0.3
8088+ micromark-factory-space: 2.0.1
8089+ micromark-util-character: 2.1.1
8090+ micromark-util-chunked: 2.0.1
8091+ micromark-util-combine-extensions: 2.0.1
8092+ micromark-util-decode-numeric-character-reference: 2.0.2
8093+ micromark-util-encode: 2.0.1
8094+ micromark-util-normalize-identifier: 2.0.1
8095+ micromark-util-resolve-all: 2.0.1
8096+ micromark-util-sanitize-uri: 2.0.1
8097+ micromark-util-subtokenize: 2.1.0
8098+ micromark-util-symbol: 2.0.1
8099+ micromark-util-types: 2.0.2
8100+ transitivePeerDependencies:
8101+ - supports-color
8102+
8103+ micromatch@4.0.8:
8104+ dependencies:
8105+ braces: 3.0.3
8106+ picomatch: 2.3.2
8107+
8108+ minimatch@10.2.6:
8109+ dependencies:
8110+ brace-expansion: 5.0.9
8111+
8112+ minimatch@3.1.5:
8113+ dependencies:
8114+ brace-expansion: 1.1.18
8115+
8116+ minimist@1.2.8: {}
8117+
8118+ motion-dom@12.43.0:
8119+ dependencies:
8120+ motion-utils: 12.39.0
8121+
8122+ motion-utils@12.39.0: {}
8123+
8124+ motion@12.43.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
8125+ dependencies:
8126+ framer-motion: 12.43.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
8127+ tslib: 2.8.1
8128+ optionalDependencies:
8129+ react: 19.2.8
8130+ react-dom: 19.2.8(react@19.2.8)
8131+
8132+ ms@2.1.3: {}
8133+
8134+ nanoid@3.3.18: {}
8135+
8136+ nanostores@1.5.3: {}
8137+
8138+ napi-postinstall@0.3.4: {}
8139+
8140+ natural-compare@1.4.0: {}
8141+
8142+ next-themes@0.4.6(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
8143+ dependencies:
8144+ react: 19.2.8
8145+ react-dom: 19.2.8(react@19.2.8)
8146+
8147+ next@16.3.4(@babel/core@7.29.7)(@playwright/test@1.63.0)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
8148+ dependencies:
8149+ '@next/env': 16.3.4
8150+ '@swc/helpers': 0.5.23
8151+ baseline-browser-mapping: 2.11.21
8152+ caniuse-lite: 1.0.30001810
8153+ postcss: 8.5.23
8154+ react: 19.2.8
8155+ react-dom: 19.2.8(react@19.2.8)
8156+ styled-jsx: 5.1.6(@babel/core@7.29.7)(react@19.2.8)
8157+ optionalDependencies:
8158+ '@next/swc-darwin-arm64': 16.3.4
8159+ '@next/swc-darwin-x64': 16.3.4
8160+ '@next/swc-linux-arm64-gnu': 16.3.4
8161+ '@next/swc-linux-arm64-musl': 16.3.4
8162+ '@next/swc-linux-x64-gnu': 16.3.4
8163+ '@next/swc-linux-x64-musl': 16.3.4
8164+ '@next/swc-win32-arm64-msvc': 16.3.4
8165+ '@next/swc-win32-x64-msvc': 16.3.4
8166+ '@playwright/test': 1.63.0
8167+ sharp: 0.35.4(@types/node@24.13.3)
8168+ transitivePeerDependencies:
8169+ - '@babel/core'
8170+ - '@types/node'
8171+ - babel-plugin-macros
8172+
8173+ node-addon-api@8.9.2: {}
8174+
8175+ node-domexception@1.0.0: {}
8176+
8177+ node-exports-info@1.6.2:
8178+ dependencies:
8179+ array.prototype.flatmap: 1.3.3
8180+ es-errors: 1.3.0
8181+ object.entries: 1.1.9
8182+ semver: 6.3.1
8183+
8184+ node-fetch@3.3.2:
8185+ dependencies:
8186+ data-uri-to-buffer: 4.0.1
8187+ fetch-blob: 3.2.0
8188+ formdata-polyfill: 4.0.10
8189+
8190+ node-gyp-build@4.8.4: {}
8191+
8192+ node-releases@2.0.54: {}
8193+
8194+ object-assign@4.1.1: {}
8195+
8196+ object-inspect@1.13.4: {}
8197+
8198+ object-keys@1.1.1: {}
8199+
8200+ object.assign@4.1.7:
8201+ dependencies:
8202+ call-bind: 1.0.9
8203+ call-bound: 1.0.4
8204+ define-properties: 1.2.1
8205+ es-object-atoms: 1.1.2
8206+ has-symbols: 1.1.0
8207+ object-keys: 1.1.1
8208+
8209+ object.entries@1.1.9:
8210+ dependencies:
8211+ call-bind: 1.0.9
8212+ call-bound: 1.0.4
8213+ define-properties: 1.2.1
8214+ es-object-atoms: 1.1.2
8215+
8216+ object.fromentries@2.0.8:
8217+ dependencies:
8218+ call-bind: 1.0.9
8219+ define-properties: 1.2.1
8220+ es-abstract: 1.24.2
8221+ es-object-atoms: 1.1.2
8222+
8223+ object.groupby@1.0.3:
8224+ dependencies:
8225+ call-bind: 1.0.9
8226+ define-properties: 1.2.1
8227+ es-abstract: 1.24.2
8228+
8229+ object.values@1.2.1:
8230+ dependencies:
8231+ call-bind: 1.0.9
8232+ call-bound: 1.0.4
8233+ define-properties: 1.2.1
8234+ es-object-atoms: 1.1.2
8235+
8236+ oniguruma-parser@0.12.2: {}
8237+
8238+ oniguruma-to-es@4.3.6:
8239+ dependencies:
8240+ oniguruma-parser: 0.12.2
8241+ regex: 6.1.0
8242+ regex-recursion: 6.0.2
8243+
8244+ openai@7.10.0(ws@8.21.3)(zod@4.5.4):
8245+ optionalDependencies:
8246+ ws: 8.21.3
8247+ zod: 4.5.4
8248+
8249+ optionator@0.9.4:
8250+ dependencies:
8251+ deep-is: 0.1.4
8252+ fast-levenshtein: 2.0.6
8253+ levn: 0.4.1
8254+ prelude-ls: 1.2.1
8255+ type-check: 0.4.0
8256+ word-wrap: 1.2.5
8257+
8258+ own-keys@1.0.2:
8259+ dependencies:
8260+ call-bound: 1.0.4
8261+ get-intrinsic: 1.3.0
8262+ object-keys: 1.1.1
8263+ safe-push-apply: 1.0.0
8264+
8265+ p-limit@3.1.0:
8266+ dependencies:
8267+ yocto-queue: 0.1.0
8268+
8269+ p-locate@5.0.0:
8270+ dependencies:
8271+ p-limit: 3.1.0
8272+
8273+ p-retry@4.6.2:
8274+ dependencies:
8275+ '@types/retry': 0.12.0
8276+ retry: 0.13.1
8277+
8278+ parent-module@1.0.1:
8279+ dependencies:
8280+ callsites: 3.1.0
8281+
8282+ parse-entities@4.0.2:
8283+ dependencies:
8284+ '@types/unist': 2.0.11
8285+ character-entities-legacy: 3.0.0
8286+ character-reference-invalid: 2.0.1
8287+ decode-named-character-reference: 1.3.0
8288+ is-alphanumerical: 2.0.1
8289+ is-decimal: 2.0.1
8290+ is-hexadecimal: 2.0.1
8291+
8292+ parse5@7.3.0:
8293+ dependencies:
8294+ entities: 6.0.1
8295+
8296+ path-exists@4.0.0: {}
8297+
8298+ path-key@3.1.1: {}
8299+
8300+ path-parse@1.0.7: {}
8301+
8302+ pathe@2.0.3: {}
8303+
8304+ pathval@2.0.1: {}
8305+
8306+ pg-cloudflare@1.4.0:
8307+ optional: true
8308+
8309+ pg-connection-string@2.14.0: {}
8310+
8311+ pg-int8@1.0.1: {}
8312+
8313+ pg-pool@3.14.0(pg@8.23.0):
8314+ dependencies:
8315+ pg: 8.23.0
8316+
8317+ pg-protocol@1.16.0: {}
8318+
8319+ pg-types@2.2.0:
8320+ dependencies:
8321+ pg-int8: 1.0.1
8322+ postgres-array: 2.0.0
8323+ postgres-bytea: 1.0.1
8324+ postgres-date: 1.0.7
8325+ postgres-interval: 1.2.0
8326+
8327+ pg@8.23.0:
8328+ dependencies:
8329+ pg-connection-string: 2.14.0
8330+ pg-pool: 3.14.0(pg@8.23.0)
8331+ pg-protocol: 1.16.0
8332+ pg-types: 2.2.0
8333+ pgpass: 1.0.5
8334+ optionalDependencies:
8335+ pg-cloudflare: 1.4.0
8336+
8337+ pgpass@1.0.5:
8338+ dependencies:
8339+ split2: 4.2.0
8340+
8341+ picocolors@1.1.1: {}
8342+
8343+ picomatch@2.3.2: {}
8344+
8345+ picomatch@4.0.7: {}
8346+
8347+ playwright-core@1.63.0: {}
8348+
8349+ playwright@1.63.0:
8350+ dependencies:
8351+ playwright-core: 1.63.0
8352+
8353+ possible-typed-array-names@1.1.0: {}
8354+
8355+ postal-mime@2.7.5: {}
8356+
8357+ postcss@8.5.23:
8358+ dependencies:
8359+ nanoid: 3.3.18
8360+ picocolors: 1.1.1
8361+ source-map-js: 1.2.1
8362+
8363+ postcss@8.5.28:
8364+ dependencies:
8365+ nanoid: 3.3.18
8366+ picocolors: 1.1.1
8367+ source-map-js: 1.2.1
8368+
8369+ postgres-array@2.0.0: {}
8370+
8371+ postgres-bytea@1.0.1: {}
8372+
8373+ postgres-date@1.0.7: {}
8374+
8375+ postgres-interval@1.2.0:
8376+ dependencies:
8377+ xtend: 4.0.2
8378+
8379+ prelude-ls@1.2.1: {}
8380+
8381+ prop-types@15.8.1:
8382+ dependencies:
8383+ loose-envify: 1.4.0
8384+ object-assign: 4.1.1
8385+ react-is: 16.13.1
8386+
8387+ property-information@7.2.0: {}
8388+
8389+ protobufjs@7.6.6:
8390+ dependencies:
8391+ '@protobufjs/aspromise': 1.1.2
8392+ '@protobufjs/base64': 1.1.2
8393+ '@protobufjs/codegen': 2.0.5
8394+ '@protobufjs/eventemitter': 1.1.1
8395+ '@protobufjs/fetch': 1.1.1
8396+ '@protobufjs/float': 1.0.2
8397+ '@protobufjs/path': 1.1.2
8398+ '@protobufjs/pool': 1.1.0
8399+ '@protobufjs/utf8': 1.1.2
8400+ '@types/node': 24.13.3
8401+ long: 5.3.2
8402+
8403+ punycode@2.3.1: {}
8404+
8405+ queue-microtask@1.2.3: {}
8406+
8407+ react-dom@19.2.8(react@19.2.8):
8408+ dependencies:
8409+ react: 19.2.8
8410+ scheduler: 0.27.0
8411+
8412+ react-is@16.13.1: {}
8413+
8414+ react-markdown@10.1.0(@types/react@19.2.18)(react@19.2.8):
8415+ dependencies:
8416+ '@types/hast': 3.0.5
8417+ '@types/mdast': 4.0.4
8418+ '@types/react': 19.2.18
8419+ devlop: 1.1.0
8420+ hast-util-to-jsx-runtime: 2.3.6
8421+ html-url-attributes: 3.0.1
8422+ mdast-util-to-hast: 13.2.1
8423+ react: 19.2.8
8424+ remark-parse: 11.0.0
8425+ remark-rehype: 11.1.2
8426+ unified: 11.0.5
8427+ unist-util-visit: 5.1.0
8428+ vfile: 6.0.3
8429+ transitivePeerDependencies:
8430+ - supports-color
8431+
8432+ react-redux@9.3.0(@types/react@19.2.18)(react@19.2.8)(redux@5.0.1):
8433+ dependencies:
8434+ '@types/use-sync-external-store': 0.0.6
8435+ react: 19.2.8
8436+ use-sync-external-store: 1.6.0(react@19.2.8)
8437+ optionalDependencies:
8438+ '@types/react': 19.2.18
8439+ redux: 5.0.1
8440+
8441+ react-remove-scroll-bar@2.3.8(@types/react@19.2.18)(react@19.2.8):
8442+ dependencies:
8443+ react: 19.2.8
8444+ react-style-singleton: 2.2.3(@types/react@19.2.18)(react@19.2.8)
8445+ tslib: 2.8.1
8446+ optionalDependencies:
8447+ '@types/react': 19.2.18
8448+
8449+ react-remove-scroll@2.7.2(@types/react@19.2.18)(react@19.2.8):
8450+ dependencies:
8451+ react: 19.2.8
8452+ react-remove-scroll-bar: 2.3.8(@types/react@19.2.18)(react@19.2.8)
8453+ react-style-singleton: 2.2.3(@types/react@19.2.18)(react@19.2.8)
8454+ tslib: 2.8.1
8455+ use-callback-ref: 1.3.3(@types/react@19.2.18)(react@19.2.8)
8456+ use-sidecar: 1.1.3(@types/react@19.2.18)(react@19.2.8)
8457+ optionalDependencies:
8458+ '@types/react': 19.2.18
8459+
8460+ react-style-singleton@2.2.3(@types/react@19.2.18)(react@19.2.8):
8461+ dependencies:
8462+ get-nonce: 1.0.1
8463+ react: 19.2.8
8464+ tslib: 2.8.1
8465+ optionalDependencies:
8466+ '@types/react': 19.2.18
8467+
8468+ react@19.2.8: {}
8469+
8470+ recharts@3.10.1(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react-is@16.13.1)(react@19.2.8)(redux@5.0.1):
8471+ dependencies:
8472+ '@reduxjs/toolkit': 2.12.0(react-redux@9.3.0(@types/react@19.2.18)(react@19.2.8)(redux@5.0.1))(react@19.2.8)
8473+ clsx: 2.1.1
8474+ decimal.js-light: 2.5.1
8475+ es-toolkit: 1.52.0
8476+ eventemitter3: 5.0.4
8477+ immer: 11.1.18
8478+ react: 19.2.8
8479+ react-dom: 19.2.8(react@19.2.8)
8480+ react-is: 16.13.1
8481+ react-redux: 9.3.0(@types/react@19.2.18)(react@19.2.8)(redux@5.0.1)
8482+ reselect: 5.2.0
8483+ tiny-invariant: 1.3.3
8484+ use-sync-external-store: 1.6.0(react@19.2.8)
8485+ victory-vendor: 37.3.6
8486+ transitivePeerDependencies:
8487+ - '@types/react'
8488+ - redux
8489+
8490+ redux-thunk@3.1.0(redux@5.0.1):
8491+ dependencies:
8492+ redux: 5.0.1
8493+
8494+ redux@5.0.1: {}
8495+
8496+ reflect.getprototypeof@1.0.10:
8497+ dependencies:
8498+ call-bind: 1.0.9
8499+ define-properties: 1.2.1
8500+ es-abstract: 1.24.2
8501+ es-errors: 1.3.0
8502+ es-object-atoms: 1.1.2
8503+ get-intrinsic: 1.3.0
8504+ get-proto: 1.0.1
8505+ which-builtin-type: 1.2.1
8506+
8507+ regex-recursion@6.0.2:
8508+ dependencies:
8509+ regex-utilities: 2.3.0
8510+
8511+ regex-utilities@2.3.0: {}
8512+
8513+ regex@6.1.0:
8514+ dependencies:
8515+ regex-utilities: 2.3.0
8516+
8517+ regexp.prototype.flags@1.5.4:
8518+ dependencies:
8519+ call-bind: 1.0.9
8520+ define-properties: 1.2.1
8521+ es-errors: 1.3.0
8522+ get-proto: 1.0.1
8523+ gopd: 1.2.0
8524+ set-function-name: 2.0.2
8525+
8526+ rehype-raw@7.0.0:
8527+ dependencies:
8528+ '@types/hast': 3.0.5
8529+ hast-util-raw: 9.1.0
8530+ vfile: 6.0.3
8531+
8532+ remark-gfm@4.0.1:
8533+ dependencies:
8534+ '@types/mdast': 4.0.4
8535+ mdast-util-gfm: 3.1.0
8536+ micromark-extension-gfm: 3.0.0
8537+ remark-parse: 11.0.0
8538+ remark-stringify: 11.0.0
8539+ unified: 11.0.5
8540+ transitivePeerDependencies:
8541+ - supports-color
8542+
8543+ remark-parse@11.0.0:
8544+ dependencies:
8545+ '@types/mdast': 4.0.4
8546+ mdast-util-from-markdown: 2.0.3
8547+ micromark-util-types: 2.0.2
8548+ unified: 11.0.5
8549+ transitivePeerDependencies:
8550+ - supports-color
8551+
8552+ remark-rehype@11.1.2:
8553+ dependencies:
8554+ '@types/hast': 3.0.5
8555+ '@types/mdast': 4.0.4
8556+ mdast-util-to-hast: 13.2.1
8557+ unified: 11.0.5
8558+ vfile: 6.0.3
8559+
8560+ remark-stringify@11.0.0:
8561+ dependencies:
8562+ '@types/mdast': 4.0.4
8563+ mdast-util-to-markdown: 2.1.2
8564+ unified: 11.0.5
8565+
8566+ reselect@5.2.0: {}
8567+
8568+ resend@6.26.0:
8569+ dependencies:
8570+ postal-mime: 2.7.5
8571+ standardwebhooks: 1.0.0
8572+
8573+ resolve-from@4.0.0: {}
8574+
8575+ resolve-pkg-maps@1.0.0: {}
8576+
8577+ resolve@2.0.0-next.7:
8578+ dependencies:
8579+ es-errors: 1.3.0
8580+ is-core-module: 2.16.2
8581+ node-exports-info: 1.6.2
8582+ object-keys: 1.1.1
8583+ path-parse: 1.0.7
8584+ supports-preserve-symlinks-flag: 1.0.0
8585+
8586+ retry@0.13.1: {}
8587+
8588+ reusify@1.1.0: {}
8589+
8590+ rollup@4.63.1:
8591+ dependencies:
8592+ '@types/estree': 1.0.9
8593+ optionalDependencies:
8594+ '@napi-rs/lzma-linux-x64-gnu': 1.5.1
8595+ '@rollup/rollup-android-arm-eabi': 4.63.1
8596+ '@rollup/rollup-android-arm64': 4.63.1
8597+ '@rollup/rollup-darwin-arm64': 4.63.1
8598+ '@rollup/rollup-darwin-x64': 4.63.1
8599+ '@rollup/rollup-freebsd-arm64': 4.63.1
8600+ '@rollup/rollup-freebsd-x64': 4.63.1
8601+ '@rollup/rollup-linux-arm-gnueabihf': 4.63.1
8602+ '@rollup/rollup-linux-arm-musleabihf': 4.63.1
8603+ '@rollup/rollup-linux-arm64-gnu': 4.63.1
8604+ '@rollup/rollup-linux-arm64-musl': 4.63.1
8605+ '@rollup/rollup-linux-loong64-gnu': 4.63.1
8606+ '@rollup/rollup-linux-loong64-musl': 4.63.1
8607+ '@rollup/rollup-linux-ppc64-gnu': 4.63.1
8608+ '@rollup/rollup-linux-ppc64-musl': 4.63.1
8609+ '@rollup/rollup-linux-riscv64-gnu': 4.63.1
8610+ '@rollup/rollup-linux-riscv64-musl': 4.63.1
8611+ '@rollup/rollup-linux-s390x-gnu': 4.63.1
8612+ '@rollup/rollup-linux-x64-gnu': 4.63.1
8613+ '@rollup/rollup-linux-x64-musl': 4.63.1
8614+ '@rollup/rollup-openbsd-x64': 4.63.1
8615+ '@rollup/rollup-openharmony-arm64': 4.63.1
8616+ '@rollup/rollup-win32-arm64-msvc': 4.63.1
8617+ '@rollup/rollup-win32-ia32-msvc': 4.63.1
8618+ '@rollup/rollup-win32-x64-gnu': 4.63.1
8619+ '@rollup/rollup-win32-x64-msvc': 4.63.1
8620+ fsevents: 2.3.3
8621+
8622+ rou3@0.9.2: {}
8623+
8624+ run-parallel@1.2.0:
8625+ dependencies:
8626+ queue-microtask: 1.2.3
8627+
8628+ safe-array-concat@1.1.4:
8629+ dependencies:
8630+ call-bind: 1.0.9
8631+ call-bound: 1.0.4
8632+ get-intrinsic: 1.3.0
8633+ has-symbols: 1.1.0
8634+ isarray: 2.0.5
8635+
8636+ safe-buffer@5.2.1: {}
8637+
8638+ safe-push-apply@1.0.0:
8639+ dependencies:
8640+ es-errors: 1.3.0
8641+ isarray: 2.0.5
8642+
8643+ safe-regex-test@1.1.0:
8644+ dependencies:
8645+ call-bound: 1.0.4
8646+ es-errors: 1.3.0
8647+ is-regex: 1.2.1
8648+
8649+ scheduler@0.27.0: {}
8650+
8651+ semver@6.3.1: {}
8652+
8653+ semver@7.8.5: {}
8654+
8655+ server-only@0.0.1: {}
8656+
8657+ set-cookie-parser@3.1.2: {}
8658+
8659+ set-function-length@1.2.2:
8660+ dependencies:
8661+ define-data-property: 1.1.4
8662+ es-errors: 1.3.0
8663+ function-bind: 1.1.2
8664+ get-intrinsic: 1.3.0
8665+ gopd: 1.2.0
8666+ has-property-descriptors: 1.0.2
8667+
8668+ set-function-name@2.0.2:
8669+ dependencies:
8670+ define-data-property: 1.1.4
8671+ es-errors: 1.3.0
8672+ functions-have-names: 1.2.3
8673+ has-property-descriptors: 1.0.2
8674+
8675+ set-proto@1.0.0:
8676+ dependencies:
8677+ dunder-proto: 1.0.1
8678+ es-errors: 1.3.0
8679+ es-object-atoms: 1.1.2
8680+
8681+ sharp@0.35.4(@types/node@24.13.3):
8682+ dependencies:
8683+ '@img/colour': 1.1.0
8684+ detect-libc: 2.1.2
8685+ semver: 7.8.5
8686+ optionalDependencies:
8687+ '@img/sharp-darwin-arm64': 0.35.4
8688+ '@img/sharp-darwin-x64': 0.35.4
8689+ '@img/sharp-freebsd-wasm32': 0.35.4
8690+ '@img/sharp-libvips-darwin-arm64': 1.3.3
8691+ '@img/sharp-libvips-darwin-x64': 1.3.3
8692+ '@img/sharp-libvips-linux-arm': 1.3.3
8693+ '@img/sharp-libvips-linux-arm64': 1.3.3
8694+ '@img/sharp-libvips-linux-ppc64': 1.3.3
8695+ '@img/sharp-libvips-linux-riscv64': 1.3.3
8696+ '@img/sharp-libvips-linux-s390x': 1.3.3
8697+ '@img/sharp-libvips-linux-x64': 1.3.3
8698+ '@img/sharp-libvips-linuxmusl-arm64': 1.3.3
8699+ '@img/sharp-libvips-linuxmusl-x64': 1.3.3
8700+ '@img/sharp-linux-arm': 0.35.4
8701+ '@img/sharp-linux-arm64': 0.35.4
8702+ '@img/sharp-linux-ppc64': 0.35.4
8703+ '@img/sharp-linux-riscv64': 0.35.4
8704+ '@img/sharp-linux-s390x': 0.35.4
8705+ '@img/sharp-linux-x64': 0.35.4
8706+ '@img/sharp-linuxmusl-arm64': 0.35.4
8707+ '@img/sharp-linuxmusl-x64': 0.35.4
8708+ '@img/sharp-webcontainers-wasm32': 0.35.4
8709+ '@img/sharp-win32-arm64': 0.35.4
8710+ '@img/sharp-win32-ia32': 0.35.4
8711+ '@img/sharp-win32-x64': 0.35.4
8712+ '@types/node': 24.13.3
8713+ optional: true
8714+
8715+ shebang-command@2.0.0:
8716+ dependencies:
8717+ shebang-regex: 3.0.0
8718+
8719+ shebang-regex@3.0.0: {}
8720+
8721+ shiki@4.4.3:
8722+ dependencies:
8723+ '@shikijs/core': 4.4.3
8724+ '@shikijs/engine-javascript': 4.4.3
8725+ '@shikijs/engine-oniguruma': 4.4.3
8726+ '@shikijs/langs': 4.4.3
8727+ '@shikijs/themes': 4.4.3
8728+ '@shikijs/types': 4.4.3
8729+ '@shikijs/vscode-textmate': 10.0.2
8730+ '@types/hast': 3.0.5
8731+
8732+ side-channel-list@1.0.1:
8733+ dependencies:
8734+ es-errors: 1.3.0
8735+ object-inspect: 1.13.4
8736+
8737+ side-channel-map@1.0.1:
8738+ dependencies:
8739+ call-bound: 1.0.4
8740+ es-errors: 1.3.0
8741+ get-intrinsic: 1.3.0
8742+ object-inspect: 1.13.4
8743+
8744+ side-channel-weakmap@1.0.2:
8745+ dependencies:
8746+ call-bound: 1.0.4
8747+ es-errors: 1.3.0
8748+ get-intrinsic: 1.3.0
8749+ object-inspect: 1.13.4
8750+ side-channel-map: 1.0.1
8751+
8752+ side-channel@1.1.1:
8753+ dependencies:
8754+ es-errors: 1.3.0
8755+ object-inspect: 1.13.4
8756+ side-channel-list: 1.0.1
8757+ side-channel-map: 1.0.1
8758+ side-channel-weakmap: 1.0.2
8759+
8760+ siginfo@2.0.0: {}
8761+
8762+ source-map-js@1.2.1: {}
8763+
8764+ source-map-support@0.5.21:
8765+ dependencies:
8766+ buffer-from: 1.1.2
8767+ source-map: 0.6.1
8768+
8769+ source-map@0.6.1: {}
8770+
8771+ space-separated-tokens@2.0.2: {}
8772+
8773+ split2@4.2.0: {}
8774+
8775+ stable-hash@0.0.5: {}
8776+
8777+ stackback@0.0.2: {}
8778+
8779+ standardwebhooks@1.0.0:
8780+ dependencies:
8781+ '@stablelib/base64': 1.0.1
8782+ fast-sha256: 1.3.0
8783+
8784+ standardwebhooks@1.1.1:
8785+ dependencies:
8786+ '@stablelib/base64': 1.0.1
8787+ fast-sha256: 1.3.0
8788+
8789+ std-env@3.10.0: {}
8790+
8791+ stop-iteration-iterator@1.1.0:
8792+ dependencies:
8793+ es-errors: 1.3.0
8794+ internal-slot: 1.1.0
8795+
8796+ string.prototype.includes@2.0.1:
8797+ dependencies:
8798+ call-bind: 1.0.9
8799+ define-properties: 1.2.1
8800+ es-abstract: 1.24.2
8801+
8802+ string.prototype.matchall@4.1.0:
8803+ dependencies:
8804+ call-bind: 1.0.9
8805+ call-bound: 1.0.4
8806+ define-properties: 1.2.1
8807+ es-abstract: 1.24.2
8808+ es-errors: 1.3.0
8809+ es-object-atoms: 1.1.2
8810+ get-intrinsic: 1.3.0
8811+ gopd: 1.2.0
8812+ has-symbols: 1.1.0
8813+ internal-slot: 1.1.0
8814+ regexp.prototype.flags: 1.5.4
8815+ set-function-name: 2.0.2
8816+ side-channel: 1.1.1
8817+
8818+ string.prototype.repeat@1.0.0:
8819+ dependencies:
8820+ define-properties: 1.2.1
8821+ es-abstract: 1.24.2
8822+
8823+ string.prototype.trim@1.2.11:
8824+ dependencies:
8825+ call-bind: 1.0.9
8826+ call-bound: 1.0.4
8827+ define-data-property: 1.1.4
8828+ define-properties: 1.2.1
8829+ es-abstract: 1.24.2
8830+ es-object-atoms: 1.1.2
8831+ has-property-descriptors: 1.0.2
8832+ safe-regex-test: 1.1.0
8833+
8834+ string.prototype.trimend@1.0.10:
8835+ dependencies:
8836+ call-bind: 1.0.9
8837+ call-bound: 1.0.4
8838+ define-properties: 1.2.1
8839+ es-object-atoms: 1.1.2
8840+
8841+ string.prototype.trimstart@1.0.8:
8842+ dependencies:
8843+ call-bind: 1.0.9
8844+ define-properties: 1.2.1
8845+ es-object-atoms: 1.1.2
8846+
8847+ stringify-entities@4.0.4:
8848+ dependencies:
8849+ character-entities-html4: 2.1.0
8850+ character-entities-legacy: 3.0.0
8851+
8852+ strip-bom@3.0.0: {}
8853+
8854+ strip-json-comments@3.1.1: {}
8855+
8856+ strip-literal@3.1.0:
8857+ dependencies:
8858+ js-tokens: 9.0.1
8859+
8860+ style-to-js@1.1.21:
8861+ dependencies:
8862+ style-to-object: 1.0.14
8863+
8864+ style-to-object@1.0.14:
8865+ dependencies:
8866+ inline-style-parser: 0.2.7
8867+
8868+ styled-jsx@5.1.6(@babel/core@7.29.7)(react@19.2.8):
8869+ dependencies:
8870+ client-only: 0.0.1
8871+ react: 19.2.8
8872+ optionalDependencies:
8873+ '@babel/core': 7.29.7
8874+
8875+ supports-color@7.2.0:
8876+ dependencies:
8877+ has-flag: 4.0.0
8878+
8879+ supports-preserve-symlinks-flag@1.0.0: {}
8880+
8881+ swr@2.5.1(react@19.2.8):
8882+ dependencies:
8883+ dequal: 2.0.3
8884+ react: 19.2.8
8885+ use-sync-external-store: 1.6.0(react@19.2.8)
8886+
8887+ tailwind-merge@3.6.0: {}
8888+
8889+ tailwindcss@4.3.3: {}
8890+
8891+ tapable@2.3.3: {}
8892+
8893+ tiny-invariant@1.3.3: {}
8894+
8895+ tinybench@2.9.0: {}
8896+
8897+ tinyexec@0.3.2: {}
8898+
8899+ tinyglobby@0.2.17:
8900+ dependencies:
8901+ fdir: 6.5.0(picomatch@4.0.7)
8902+ picomatch: 4.0.7
8903+
8904+ tinypool@1.1.1: {}
8905+
8906+ tinyrainbow@2.0.0: {}
8907+
8908+ tinyspy@4.0.6: {}
8909+
8910+ to-regex-range@5.0.1:
8911+ dependencies:
8912+ is-number: 7.0.0
8913+
8914+ trim-lines@3.0.1: {}
8915+
8916+ trough@2.2.0: {}
8917+
8918+ ts-algebra@2.0.0: {}
8919+
8920+ ts-api-utils@2.5.0(typescript@5.9.3):
8921+ dependencies:
8922+ typescript: 5.9.3
8923+
8924+ tsconfig-paths@3.15.0:
8925+ dependencies:
8926+ '@types/json5': 0.0.29
8927+ json5: 1.0.2
8928+ minimist: 1.2.8
8929+ strip-bom: 3.0.0
8930+
8931+ tslib@2.8.1: {}
8932+
8933+ tsx@4.23.13:
8934+ dependencies:
8935+ esbuild: 0.28.2
8936+ optionalDependencies:
8937+ fsevents: 2.3.3
8938+
8939+ type-check@0.4.0:
8940+ dependencies:
8941+ prelude-ls: 1.2.1
8942+
8943+ typed-array-buffer@1.0.3:
8944+ dependencies:
8945+ call-bound: 1.0.4
8946+ es-errors: 1.3.0
8947+ is-typed-array: 1.1.15
8948+
8949+ typed-array-byte-length@1.0.3:
8950+ dependencies:
8951+ call-bind: 1.0.9
8952+ for-each: 0.3.5
8953+ gopd: 1.2.0
8954+ has-proto: 1.2.0
8955+ is-typed-array: 1.1.15
8956+
8957+ typed-array-byte-offset@1.0.4:
8958+ dependencies:
8959+ available-typed-arrays: 1.0.7
8960+ call-bind: 1.0.9
8961+ for-each: 0.3.5
8962+ gopd: 1.2.0
8963+ has-proto: 1.2.0
8964+ is-typed-array: 1.1.15
8965+ reflect.getprototypeof: 1.0.10
8966+
8967+ typed-array-length@1.0.8:
8968+ dependencies:
8969+ call-bind: 1.0.9
8970+ for-each: 0.3.5
8971+ gopd: 1.2.0
8972+ is-typed-array: 1.1.15
8973+ possible-typed-array-names: 1.1.0
8974+ reflect.getprototypeof: 1.0.10
8975+
8976+ typescript-eslint@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3):
8977+ dependencies:
8978+ '@typescript-eslint/eslint-plugin': 8.69.0(@typescript-eslint/parser@8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
8979+ '@typescript-eslint/parser': 8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
8980+ '@typescript-eslint/typescript-estree': 8.69.0(typescript@5.9.3)
8981+ '@typescript-eslint/utils': 8.69.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
8982+ eslint: 9.39.5(jiti@2.7.0)
8983+ typescript: 5.9.3
8984+ transitivePeerDependencies:
8985+ - supports-color
8986+
8987+ typescript@5.9.3: {}
8988+
8989+ unbox-primitive@1.1.0:
8990+ dependencies:
8991+ call-bound: 1.0.4
8992+ has-bigints: 1.1.0
8993+ has-symbols: 1.1.0
8994+ which-boxed-primitive: 1.1.1
8995+
8996+ undici-types@7.18.2: {}
8997+
8998+ unified@11.0.5:
8999+ dependencies:
9000+ '@types/unist': 3.0.3
9001+ bail: 2.0.2
9002+ devlop: 1.1.0
9003+ extend: 3.0.2
9004+ is-plain-obj: 4.1.0
9005+ trough: 2.2.0
9006+ vfile: 6.0.3
9007+
9008+ unist-util-is@6.0.1:
9009+ dependencies:
9010+ '@types/unist': 3.0.3
9011+
9012+ unist-util-position@5.0.0:
9013+ dependencies:
9014+ '@types/unist': 3.0.3
9015+
9016+ unist-util-stringify-position@4.0.0:
9017+ dependencies:
9018+ '@types/unist': 3.0.3
9019+
9020+ unist-util-visit-parents@6.0.2:
9021+ dependencies:
9022+ '@types/unist': 3.0.3
9023+ unist-util-is: 6.0.1
9024+
9025+ unist-util-visit@5.1.0:
9026+ dependencies:
9027+ '@types/unist': 3.0.3
9028+ unist-util-is: 6.0.1
9029+ unist-util-visit-parents: 6.0.2
9030+
9031+ unrs-resolver@1.12.2:
9032+ dependencies:
9033+ napi-postinstall: 0.3.4
9034+ optionalDependencies:
9035+ '@unrs/resolver-binding-android-arm-eabi': 1.12.2
9036+ '@unrs/resolver-binding-android-arm64': 1.12.2
9037+ '@unrs/resolver-binding-darwin-arm64': 1.12.2
9038+ '@unrs/resolver-binding-darwin-x64': 1.12.2
9039+ '@unrs/resolver-binding-freebsd-x64': 1.12.2
9040+ '@unrs/resolver-binding-linux-arm-gnueabihf': 1.12.2
9041+ '@unrs/resolver-binding-linux-arm-musleabihf': 1.12.2
9042+ '@unrs/resolver-binding-linux-arm64-gnu': 1.12.2
9043+ '@unrs/resolver-binding-linux-arm64-musl': 1.12.2
9044+ '@unrs/resolver-binding-linux-loong64-gnu': 1.12.2
9045+ '@unrs/resolver-binding-linux-loong64-musl': 1.12.2
9046+ '@unrs/resolver-binding-linux-ppc64-gnu': 1.12.2
9047+ '@unrs/resolver-binding-linux-riscv64-gnu': 1.12.2
9048+ '@unrs/resolver-binding-linux-riscv64-musl': 1.12.2
9049+ '@unrs/resolver-binding-linux-s390x-gnu': 1.12.2
9050+ '@unrs/resolver-binding-linux-x64-gnu': 1.12.2
9051+ '@unrs/resolver-binding-linux-x64-musl': 1.12.2
9052+ '@unrs/resolver-binding-openharmony-arm64': 1.12.2
9053+ '@unrs/resolver-binding-wasm32-wasi': 1.12.2
9054+ '@unrs/resolver-binding-win32-arm64-msvc': 1.12.2
9055+ '@unrs/resolver-binding-win32-ia32-msvc': 1.12.2
9056+ '@unrs/resolver-binding-win32-x64-msvc': 1.12.2
9057+
9058+ update-browserslist-db@1.3.2(browserslist@4.28.9):
9059+ dependencies:
9060+ browserslist: 4.28.9
9061+ escalade: 3.2.0
9062+ picocolors: 1.1.1
9063+
9064+ uri-js@4.4.1:
9065+ dependencies:
9066+ punycode: 2.3.1
9067+
9068+ use-callback-ref@1.3.3(@types/react@19.2.18)(react@19.2.8):
9069+ dependencies:
9070+ react: 19.2.8
9071+ tslib: 2.8.1
9072+ optionalDependencies:
9073+ '@types/react': 19.2.18
9074+
9075+ use-sidecar@1.1.3(@types/react@19.2.18)(react@19.2.8):
9076+ dependencies:
9077+ detect-node-es: 1.1.0
9078+ react: 19.2.8
9079+ tslib: 2.8.1
9080+ optionalDependencies:
9081+ '@types/react': 19.2.18
9082+
9083+ use-sync-external-store@1.6.0(react@19.2.8):
9084+ dependencies:
9085+ react: 19.2.8
9086+
9087+ vfile-location@5.0.3:
9088+ dependencies:
9089+ '@types/unist': 3.0.3
9090+ vfile: 6.0.3
9091+
9092+ vfile-message@4.0.3:
9093+ dependencies:
9094+ '@types/unist': 3.0.3
9095+ unist-util-stringify-position: 4.0.0
9096+
9097+ vfile@6.0.3:
9098+ dependencies:
9099+ '@types/unist': 3.0.3
9100+ vfile-message: 4.0.3
9101+
9102+ victory-vendor@37.3.6:
9103+ dependencies:
9104+ '@types/d3-array': 3.2.2
9105+ '@types/d3-ease': 3.0.2
9106+ '@types/d3-interpolate': 3.0.4
9107+ '@types/d3-scale': 4.0.9
9108+ '@types/d3-shape': 3.2.0
9109+ '@types/d3-time': 3.0.4
9110+ '@types/d3-timer': 3.0.2
9111+ d3-array: 3.2.4
9112+ d3-ease: 3.0.1
9113+ d3-interpolate: 3.0.1
9114+ d3-scale: 4.0.2
9115+ d3-shape: 3.2.0
9116+ d3-time: 3.1.0
9117+ d3-timer: 3.0.1
9118+
9119+ vite-node@3.2.4(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13):
9120+ dependencies:
9121+ cac: 6.7.14
9122+ debug: 4.4.3
9123+ es-module-lexer: 1.7.0
9124+ pathe: 2.0.3
9125+ vite: 7.3.6(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13)
9126+ transitivePeerDependencies:
9127+ - '@types/node'
9128+ - jiti
9129+ - less
9130+ - lightningcss
9131+ - sass
9132+ - sass-embedded
9133+ - stylus
9134+ - sugarss
9135+ - supports-color
9136+ - terser
9137+ - tsx
9138+ - yaml
9139+
9140+ vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13):
9141+ dependencies:
9142+ esbuild: 0.28.2
9143+ fdir: 6.5.0(picomatch@4.0.7)
9144+ picomatch: 4.0.7
9145+ postcss: 8.5.28
9146+ rollup: 4.63.1
9147+ tinyglobby: 0.2.17
9148+ optionalDependencies:
9149+ '@types/node': 24.13.3
9150+ fsevents: 2.3.3
9151+ jiti: 2.7.0
9152+ lightningcss: 1.32.0
9153+ tsx: 4.23.13
9154+
9155+ vitest@3.2.7(@types/debug@4.1.13)(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13):
9156+ dependencies:
9157+ '@types/chai': 5.2.3
9158+ '@vitest/expect': 3.2.7
9159+ '@vitest/mocker': 3.2.7(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13))
9160+ '@vitest/pretty-format': 3.2.7
9161+ '@vitest/runner': 3.2.7
9162+ '@vitest/snapshot': 3.2.7
9163+ '@vitest/spy': 3.2.7
9164+ '@vitest/utils': 3.2.7
9165+ chai: 5.3.3
9166+ debug: 4.4.3
9167+ expect-type: 1.4.0
9168+ magic-string: 0.30.21
9169+ pathe: 2.0.3
9170+ picomatch: 4.0.7
9171+ std-env: 3.10.0
9172+ tinybench: 2.9.0
9173+ tinyexec: 0.3.2
9174+ tinyglobby: 0.2.17
9175+ tinypool: 1.1.1
9176+ tinyrainbow: 2.0.0
9177+ vite: 7.3.6(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13)
9178+ vite-node: 3.2.4(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.13)
9179+ why-is-node-running: 2.3.0
9180+ optionalDependencies:
9181+ '@types/debug': 4.1.13
9182+ '@types/node': 24.13.3
9183+ transitivePeerDependencies:
9184+ - jiti
9185+ - less
9186+ - lightningcss
9187+ - msw
9188+ - sass
9189+ - sass-embedded
9190+ - stylus
9191+ - sugarss
9192+ - supports-color
9193+ - terser
9194+ - tsx
9195+ - yaml
9196+
9197+ web-namespaces@2.0.1: {}
9198+
9199+ web-streams-polyfill@3.3.3: {}
9200+
9201+ which-boxed-primitive@1.1.1:
9202+ dependencies:
9203+ is-bigint: 1.1.0
9204+ is-boolean-object: 1.2.2
9205+ is-number-object: 1.1.1
9206+ is-string: 1.1.1
9207+ is-symbol: 1.1.1
9208+
9209+ which-builtin-type@1.2.1:
9210+ dependencies:
9211+ call-bound: 1.0.4
9212+ function.prototype.name: 1.2.0
9213+ has-tostringtag: 1.0.2
9214+ is-async-function: 2.1.1
9215+ is-date-object: 1.1.0
9216+ is-finalizationregistry: 1.1.1
9217+ is-generator-function: 1.1.2
9218+ is-regex: 1.2.1
9219+ is-weakref: 1.1.1
9220+ isarray: 2.0.5
9221+ which-boxed-primitive: 1.1.1
9222+ which-collection: 1.0.2
9223+ which-typed-array: 1.1.22
9224+
9225+ which-collection@1.0.2:
9226+ dependencies:
9227+ is-map: 2.0.3
9228+ is-set: 2.0.3
9229+ is-weakmap: 2.0.2
9230+ is-weakset: 2.0.4
9231+
9232+ which-typed-array@1.1.22:
9233+ dependencies:
9234+ available-typed-arrays: 1.0.7
9235+ call-bind: 1.0.9
9236+ call-bound: 1.0.4
9237+ for-each: 0.3.5
9238+ get-proto: 1.0.1
9239+ gopd: 1.2.0
9240+ has-tostringtag: 1.0.2
9241+
9242+ which@2.0.2:
9243+ dependencies:
9244+ isexe: 2.0.0
9245+
9246+ why-is-node-running@2.3.0:
9247+ dependencies:
9248+ siginfo: 2.0.0
9249+ stackback: 0.0.2
9250+
9251+ word-wrap@1.2.5: {}
9252+
9253+ ws@8.21.3: {}
9254+
9255+ xtend@4.0.2: {}
9256+
9257+ yallist@3.1.1: {}
9258+
9259+ yocto-queue@0.1.0: {}
9260+
9261+ zod-validation-error@4.0.2(zod@4.5.4):
9262+ dependencies:
9263+ zod: 4.5.4
9264+
9265+ zod@4.5.4: {}
9266+
9267+ zwitch@2.0.4: {}
added postcss.config.mjs +2 −0
@@ -0,0 +1,2 @@
1+const config = { plugins: { "@tailwindcss/postcss": {} } };
2+export default config;
added public/icon.svg +1 −0
@@ -0,0 +1 @@
1+<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none"><defs><linearGradient id="g" x1="4" y1="4" x2="28" y2="28" gradientUnits="userSpaceOnUse"><stop stop-color="#8b8dff"/><stop offset="0.55" stop-color="#b58cff"/><stop offset="1" stop-color="#ff8fab"/></linearGradient></defs><rect x="1" y="1" width="30" height="30" rx="9" fill="url(#g)"/><g stroke="#0b0c10" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 10.5h4.5M9 16h6M9 21.5h4.5"/><path d="M23 10.5h-4.5M23 16h-6M23 21.5h-4.5"/><circle cx="16" cy="16" r="2.4" fill="#0b0c10" stroke="none"/></g></svg>
added public/robots.txt +6 −0
@@ -0,0 +1,6 @@
1+User-agent: *
2+Allow: /
3+Disallow: /app/
4+Disallow: /admin/
5+Disallow: /api/
6+Sitemap: https://www.polyllm.io/sitemap.xml
added research/gemini/00-models-list.ts +44 −0
@@ -0,0 +1,44 @@
1+// Probe 00: list models via REST (x-goog-api-key) and via SDK; dump per-model metadata.
2+// Run: set -a; . ../../.env; set +a; npx tsx 00-models-list.ts
3+import { GoogleGenAI } from "@google/genai";
4+import { writeFileSync } from "node:fs";
5+
6+const key = process.env.GOOGLE_GEMINI_API_KEY!;
7+if (!key) throw new Error("GOOGLE_GEMINI_API_KEY missing");
8+
9+async function main() {
10+ // REST, paginated
11+ const all: any[] = [];
12+ let pageToken: string | undefined;
13+ do {
14+ const url = new URL("https://generativelanguage.googleapis.com/v1beta/models");
15+ url.searchParams.set("pageSize", "1000");
16+ if (pageToken) url.searchParams.set("pageToken", pageToken);
17+ const r = await fetch(url, { headers: { "x-goog-api-key": key } });
18+ console.log("REST status", r.status, "headers:", Object.fromEntries([...r.headers.entries()].filter(([k]) => !/set-cookie/.test(k))));
19+ const j = await r.json();
20+ all.push(...(j.models ?? []));
21+ pageToken = j.nextPageToken;
22+ } while (pageToken);
23+ writeFileSync("out/models.json", JSON.stringify(all, null, 2));
24+ console.log("model count", all.length);
25+ const keys = new Set<string>();
26+ for (const m of all) Object.keys(m).forEach((k) => keys.add(k));
27+ console.log("metadata fields seen:", [...keys].join(", "));
28+ for (const m of all) {
29+ console.log(
30+ m.name.replace("models/", "").padEnd(48),
31+ String(m.inputTokenLimit).padStart(8),
32+ String(m.outputTokenLimit).padStart(7),
33+ (m.thinking ? "think" : " "),
34+ (m.supportedGenerationMethods ?? []).join("|"),
35+ `T=${m.temperature ?? "-"}/${m.maxTemperature ?? "-"} P=${m.topP ?? "-"} K=${m.topK ?? "-"}`,
36+ );
37+ }
38+ // SDK
39+ const ai = new GoogleGenAI({ apiKey: key });
40+ const pager = await ai.models.list({ config: { pageSize: 5 } });
41+ let n = 0;
42+ for await (const m of pager) { n++; if (n === 1) console.log("SDK first model sample:", JSON.stringify(m)); if (n >= 5) break; }
43+}
44+main().catch((e) => { console.error("ERR", e?.message ?? e); process.exit(1); });
added research/gemini/01-basic-stream.ts +83 −0
@@ -0,0 +1,83 @@
1+// Probe 01: per model — (a) tiny generateContent with systemInstruction, (b) generateContentStream chunk shape,
2+// usage arrival pattern, part.thought flag, finishReason, modelVersion. Also raw REST SSE for one model.
3+import { ai, MODELS, KEY, SUFFIX, save, errInfo, shortText, withRetry, sleep, PACE_MS } from "./lib.js";
4+
5+const results: any = {};
6+
7+for (const model of MODELS) {
8+ const r: any = (results[model] = {});
9+ // (a) + (i) non-streaming with systemInstruction
10+ try {
11+ const res = await withRetry(() => ai.models.generateContent({
12+ model,
13+ contents: "Reply with exactly one word: what colour is the sky on a clear day?",
14+ config: { systemInstruction: "You are terse. Always answer in UPPERCASE.", maxOutputTokens: 400 },
15+ }));
16+ r.generate = {
17+ ok: true,
18+ text: shortText(res),
19+ modelVersion: res.modelVersion,
20+ responseId: res.responseId,
21+ finishReason: res.candidates?.[0]?.finishReason,
22+ partKeys: res.candidates?.[0]?.content?.parts?.map((p: any) => Object.keys(p)),
23+ role: res.candidates?.[0]?.content?.role,
24+ usage: res.usageMetadata,
25+ topLevelKeys: Object.keys(res).filter((k) => !k.startsWith("_")),
26+ };
27+ } catch (e) {
28+ r.generate = { ok: false, error: errInfo(e) };
29+ }
30+
31+ // (b) streaming
32+ try {
33+ await sleep(PACE_MS);
34+ const stream = await withRetry(() => ai.models.generateContentStream({
35+ model,
36+ contents: "Count from 1 to 12 separated by spaces, then say DONE.",
37+ config: { maxOutputTokens: 2000, thinkingConfig: { includeThoughts: true } },
38+ }));
39+ const chunks: any[] = [];
40+ for await (const c of stream) {
41+ chunks.push({
42+ parts: c.candidates?.[0]?.content?.parts?.map((p: any) => ({
43+ keys: Object.keys(p), thought: p.thought ?? undefined, textLen: p.text?.length, hasSig: !!p.thoughtSignature,
44+ })),
45+ role: c.candidates?.[0]?.content?.role,
46+ finishReason: c.candidates?.[0]?.finishReason,
47+ usage: c.usageMetadata,
48+ modelVersion: c.modelVersion,
49+ responseId: c.responseId,
50+ keys: Object.keys(c).filter((k) => !k.startsWith("_") && (c as any)[k] !== undefined),
51+ });
52+ }
53+ r.stream = {
54+ ok: true,
55+ chunkCount: chunks.length,
56+ usageOnChunks: chunks.map((c) => (c.usage ? (c.usage.candidatesTokenCount != null ? "full" : "partial") : "none")),
57+ thoughtChunks: chunks.filter((c) => c.parts?.some((p: any) => p.thought)).length,
58+ lastUsage: chunks.at(-1)?.usage,
59+ finishReasons: chunks.map((c) => c.finishReason ?? null),
60+ sampleFirst: chunks[0],
61+ sampleLast: chunks.at(-1),
62+ };
63+ } catch (e) {
64+ r.stream = { ok: false, error: errInfo(e) };
65+ }
66+ await sleep(PACE_MS);
67+ console.log(model, JSON.stringify({ gen: r.generate.ok ? r.generate.text : r.generate.error, stream: r.stream.ok ? { n: r.stream.chunkCount, usage: r.stream.usageOnChunks, thoughts: r.stream.thoughtChunks } : r.stream.error }));
68+}
69+
70+// Raw REST SSE protocol sample (one model)
71+if (!process.argv[2]) {
72+ const model = "gemini-3.5-flash-lite";
73+ const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:streamGenerateContent?alt=sse`, {
74+ method: "POST",
75+ headers: { "x-goog-api-key": KEY, "content-type": "application/json" },
76+ body: JSON.stringify({ contents: [{ role: "user", parts: [{ text: "Say hello in three words." }] }], generationConfig: { maxOutputTokens: 50, thinkingConfig: { thinkingBudget: 0 } } }),
77+ });
78+ const raw = await res.text();
79+ results.restSse = { status: res.status, contentType: res.headers.get("content-type"), rawFirst1200: raw.slice(0, 1200), eventCount: raw.split("\n\n").filter((s) => s.trim()).length };
80+ console.log("REST SSE", res.status, res.headers.get("content-type"), "events:", results.restSse.eventCount);
81+}
82+
83+save(`01-basic-stream${SUFFIX}.json`, results);
added research/gemini/02-params.ts +68 −0
@@ -0,0 +1,68 @@
1+// Probe 02: generationConfig parameter acceptance matrix per model. One request per (model, param).
2+import { ai, MODELS, SUFFIX, save, errInfo, shortText, withRetry, sleep, PACE_MS } from "./lib.js";
3+
4+const schema = { type: "object", properties: { answer: { type: "string" } }, required: ["answer"] };
5+
6+const CASES: Record<string, Record<string, unknown>> = {
7+ temperature_0: { temperature: 0 },
8+ temperature_1_5: { temperature: 1.5 },
9+ temperature_2: { temperature: 2 },
10+ temperature_2_5_out_of_range: { temperature: 2.5 },
11+ topP_0_9: { topP: 0.9 },
12+ topK_40: { topK: 40 },
13+ seed_42: { seed: 42 },
14+ stopSequences: { stopSequences: ["DONE"] },
15+ frequencyPenalty_0_5: { frequencyPenalty: 0.5 },
16+ presencePenalty_0_5: { presencePenalty: 0.5 },
17+ candidateCount_2: { candidateCount: 2 },
18+ responseMimeType_json: { responseMimeType: "application/json" },
19+ responseSchema: { responseMimeType: "application/json", responseSchema: { type: "OBJECT", properties: { answer: { type: "STRING" } }, required: ["answer"] } },
20+ responseJsonSchema: { responseMimeType: "application/json", responseJsonSchema: schema },
21+ responseMimeType_enum: { responseMimeType: "text/x.enum", responseSchema: { type: "STRING", enum: ["red", "blue", "green"] } },
22+ thinkingBudget_0: { thinkingConfig: { thinkingBudget: 0 } },
23+ thinkingBudget_1024: { thinkingConfig: { thinkingBudget: 1024 } },
24+ thinkingBudget_minus1: { thinkingConfig: { thinkingBudget: -1 } },
25+ includeThoughts: { thinkingConfig: { includeThoughts: true } },
26+ thinkingLevel_minimal: { thinkingConfig: { thinkingLevel: "MINIMAL" } },
27+ thinkingLevel_low: { thinkingConfig: { thinkingLevel: "LOW" } },
28+ thinkingLevel_medium: { thinkingConfig: { thinkingLevel: "MEDIUM" } },
29+ thinkingLevel_high: { thinkingConfig: { thinkingLevel: "HIGH" } },
30+ thinkingLevel_and_budget: { thinkingConfig: { thinkingLevel: "LOW", thinkingBudget: 512 } },
31+ responseLogprobs: { responseLogprobs: true, logprobs: 2 },
32+};
33+
34+const only = MODELS;
35+const onlyCases = process.argv[3] ? new Set(process.argv[3].split(",")) : null;
36+const results: any = {};
37+
38+for (const model of only) {
39+ results[model] = {};
40+ for (const [name, cfg] of Object.entries(CASES)) {
41+ if (onlyCases && !onlyCases.has(name)) continue;
42+ const t0 = Date.now();
43+ try {
44+ const res = await withRetry(() => ai.models.generateContent({
45+ model,
46+ contents: name.startsWith("responseMimeType_enum") ? "Which colour is the sky? Answer with one of the enum values." : "Answer in <= 5 words: what is 2+2? Then write DONE.",
47+ config: { maxOutputTokens: 1500, ...cfg } as any,
48+ }));
49+ const usage = res.usageMetadata ?? {};
50+ results[model][name] = {
51+ ok: true,
52+ text: shortText(res),
53+ finishReason: res.candidates?.[0]?.finishReason,
54+ thoughtsTokenCount: usage.thoughtsTokenCount ?? 0,
55+ candidatesTokenCount: usage.candidatesTokenCount,
56+ nCandidates: res.candidates?.length,
57+ hasThoughtParts: res.candidates?.[0]?.content?.parts?.some((p: any) => p.thought) ?? false,
58+ ms: Date.now() - t0,
59+ };
60+ } catch (e) {
61+ results[model][name] = { ok: false, error: errInfo(e), ms: Date.now() - t0 };
62+ }
63+ await sleep(PACE_MS);
64+ const r = results[model][name];
65+ console.log(model.padEnd(24), name.padEnd(30), r.ok ? `OK thoughts=${r.thoughtsTokenCount} fin=${r.finishReason} "${r.text.slice(0, 40).replace(/\n/g, " ")}"` : `FAIL ${r.error.httpStatus} ${r.error.status}: ${r.error.message.slice(0, 160)}`);
66+ }
67+}
68+save(`02-params${SUFFIX}${onlyCases ? "-subset-" + Date.now() : ""}.json`, results);
added research/gemini/03-tools.ts +107 −0
@@ -0,0 +1,107 @@
1+// Probe 03: per model — (d) function-calling round trip with streaming, (e) structured output via responseJsonSchema.
2+// Plus (h) googleSearch grounding and code execution on selected models.
3+import { ai, MODELS, SUFFIX, save, errInfo, shortText, withRetry, sleep, PACE_MS } from "./lib.js";
4+
5+const results: any = {};
6+const weatherTool = {
7+ functionDeclarations: [{
8+ name: "get_weather",
9+ description: "Get the current weather for a city.",
10+ parametersJsonSchema: { type: "object", properties: { city: { type: "string" }, unit: { type: "string", enum: ["C", "F"] } }, required: ["city"] },
11+ }],
12+};
13+
14+for (const model of MODELS) {
15+ const r: any = (results[model] = {});
16+
17+ // (d) function calling, streaming, then send functionResponse
18+ try {
19+ const contents: any[] = [{ role: "user", parts: [{ text: "What is the weather in Montreal right now? Use the tool." }] }];
20+ const stream = await withRetry(() => ai.models.generateContentStream({ model, contents, config: { tools: [weatherTool], maxOutputTokens: 2000 } }));
21+ const chunks: any[] = [];
22+ let modelParts: any[] = [];
23+ for await (const c of stream) {
24+ const parts = c.candidates?.[0]?.content?.parts ?? [];
25+ chunks.push({ parts: parts.map((p: any) => ({ keys: Object.keys(p), fc: p.functionCall, thought: p.thought, sig: p.thoughtSignature ? `${p.thoughtSignature.length} chars` : undefined })), finishReason: c.candidates?.[0]?.finishReason, usage: c.usageMetadata ? Object.keys(c.usageMetadata) : null });
26+ modelParts.push(...parts);
27+ }
28+ const fcParts = modelParts.filter((p) => p.functionCall);
29+ r.functionCall = { ok: true, chunkCount: chunks.length, chunks, functionCalls: fcParts.map((p) => p.functionCall), sigOnFcPart: fcParts.map((p) => !!p.thoughtSignature) };
30+ if (fcParts.length) {
31+ // Round trip: append model content (with thoughtSignature preserved) and functionResponse parts
32+ contents.push({ role: "model", parts: modelParts });
33+ contents.push({
34+ role: "user",
35+ parts: fcParts.map((p) => ({ functionResponse: { name: p.functionCall.name, id: p.functionCall.id, response: { temperatureC: 21, condition: "sunny" } } })),
36+ });
37+ await sleep(PACE_MS);
38+ const res2 = await withRetry(() => ai.models.generateContent({ model, contents, config: { tools: [weatherTool], maxOutputTokens: 2000 } }));
39+ r.functionCall.roundTrip = { text: shortText(res2), finishReason: res2.candidates?.[0]?.finishReason, usage: res2.usageMetadata };
40+ }
41+ } catch (e) {
42+ r.functionCall = { ok: false, error: errInfo(e) };
43+ }
44+
45+ // (e) structured output responseJsonSchema
46+ try {
47+ await sleep(PACE_MS);
48+ const res = await withRetry(() => ai.models.generateContent({
49+ model,
50+ contents: "Extract: 'Alice is 30 and lives in Paris.'",
51+ config: {
52+ maxOutputTokens: 2000,
53+ responseMimeType: "application/json",
54+ responseJsonSchema: { type: "object", properties: { name: { type: "string" }, age: { type: "integer" }, city: { type: "string" } }, required: ["name", "age", "city"], additionalProperties: false },
55+ },
56+ }));
57+ const txt = shortText(res);
58+ let parsed: any = null; try { parsed = JSON.parse(res.candidates?.[0]?.content?.parts?.filter((p: any) => !p.thought).map((p: any) => p.text).join("") ?? ""); } catch {}
59+ r.structured = { ok: true, text: txt, parsedOk: !!parsed, parsed, finishReason: res.candidates?.[0]?.finishReason };
60+ } catch (e) {
61+ r.structured = { ok: false, error: errInfo(e) };
62+ }
63+ await sleep(PACE_MS);
64+ console.log(model, "fc:", r.functionCall.ok ? `${r.functionCall.functionCalls.length} call(s) chunks=${r.functionCall.chunkCount} rt="${r.functionCall.roundTrip?.text?.slice(0, 50)}"` : r.functionCall.error.message.slice(0, 200), "| structured:", r.structured.ok ? r.structured.text.slice(0, 80) : r.structured.error.message.slice(0, 200));
65+}
66+
67+const EXTRAS = process.argv[3] === "extras";
68+// (h) Google Search grounding (3.x models; 2.5 is 404 for this key)
69+for (const model of EXTRAS ? [MODELS[0]] : []) {
70+ await sleep(PACE_MS);
71+ try {
72+ const res = await withRetry(() => ai.models.generateContent({ model, contents: "Who won the most recent FIFA World Cup final and what was the score? One sentence.", config: { tools: [{ googleSearch: {} }], maxOutputTokens: 3000 } }));
73+ const gm: any = res.candidates?.[0]?.groundingMetadata;
74+ results[`search:${model}`] = {
75+ ok: true, text: shortText(res),
76+ groundingMetadataKeys: gm ? Object.keys(gm) : null,
77+ webSearchQueries: gm?.webSearchQueries,
78+ groundingChunksSample: gm?.groundingChunks?.slice(0, 2),
79+ groundingSupportsSample: gm?.groundingSupports?.slice(0, 2),
80+ searchEntryPointKeys: gm?.searchEntryPoint ? Object.keys(gm.searchEntryPoint) : null,
81+ renderedContentLen: gm?.searchEntryPoint?.renderedContent?.length,
82+ usage: res.usageMetadata,
83+ partKeys: res.candidates?.[0]?.content?.parts?.map((p: any) => Object.keys(p)),
84+ };
85+ } catch (e) { results[`search:${model}`] = { ok: false, error: errInfo(e) }; }
86+ console.log("search", model, JSON.stringify(results[`search:${model}`]).slice(0, 300));
87+}
88+
89+// Code execution on one model
90+if (EXTRAS) try {
91+ await sleep(PACE_MS);
92+ const res = await withRetry(() => ai.models.generateContent({ model: MODELS[0], contents: "Compute the 30th Fibonacci number with Python and report it.", config: { tools: [{ codeExecution: {} }], maxOutputTokens: 3000 } }));
93+ results[`codeExecution:${MODELS[0]}`] = { ok: true, parts: res.candidates?.[0]?.content?.parts?.map((p: any) => ({ keys: Object.keys(p), executableCode: p.executableCode, codeExecutionResult: p.codeExecutionResult, text: p.text?.slice(0, 100) })), usage: res.usageMetadata };
94+} catch (e) { results[`codeExecution:${MODELS[0]}`] = { ok: false, error: errInfo(e) }; }
95+if (EXTRAS) console.log("codeExec", JSON.stringify(results[`codeExecution:${MODELS[0]}`]).slice(0, 400));
96+
97+// toolConfig mode ANY (+ streamFunctionCallArguments is Vertex-only: SDK throws before sending) on 3.8
98+if (EXTRAS) try {
99+ await sleep(PACE_MS);
100+ const stream = await withRetry(() => ai.models.generateContentStream({ model: MODELS[0], contents: "Weather in Quebec City?", config: { tools: [weatherTool], toolConfig: { functionCallingConfig: { mode: "ANY" as any, allowedFunctionNames: ["get_weather"] } }, maxOutputTokens: 2000 } }));
101+ const chunks: any[] = [];
102+ for await (const c of stream) chunks.push(c.candidates?.[0]?.content?.parts);
103+ results[`fcModeAny:${MODELS[0]}`] = { ok: true, chunks };
104+} catch (e) { results[`fcModeAny:${MODELS[0]}`] = { ok: false, error: errInfo(e) }; }
105+if (EXTRAS) console.log("fcAny", JSON.stringify(results[`fcModeAny:${MODELS[0]}`]).slice(0, 500));
106+
107+save(`03-tools${SUFFIX}.json`, results);
added research/gemini/04-vision.ts +36 −0
@@ -0,0 +1,36 @@
1+// Probe 04: (f) vision with a tiny inline base64 PNG (2x2, generated in node), per model.
2+import { deflateSync } from "node:zlib";
3+import { ai, MODELS, SUFFIX, save, errInfo, shortText, withRetry, sleep, PACE_MS } from "./lib.js";
4+
5+function crc32(buf: Buffer) {
6+ let c, crc = 0xffffffff;
7+ for (let n = 0; n < buf.length; n++) { c = (crc ^ buf[n]) & 0xff; for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; crc = (crc >>> 8) ^ c; }
8+ return (crc ^ 0xffffffff) >>> 0;
9+}
10+function chunk(type: string, data: Buffer) {
11+ const len = Buffer.alloc(4); len.writeUInt32BE(data.length);
12+ const td = Buffer.concat([Buffer.from(type, "ascii"), data]);
13+ const crc = Buffer.alloc(4); crc.writeUInt32BE(crc32(td));
14+ return Buffer.concat([len, td, crc]);
15+}
16+// 2x2 RGB: red, green / blue, white
17+const ihdr = Buffer.alloc(13); ihdr.writeUInt32BE(2, 0); ihdr.writeUInt32BE(2, 4); ihdr[8] = 8; ihdr[9] = 2; ihdr[10] = 0; ihdr[11] = 0; ihdr[12] = 0;
18+const raw = Buffer.from([0, 255, 0, 0, 0, 255, 0, 0, 0, 0, 255, 255, 255, 255]);
19+const png = Buffer.concat([Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]), chunk("IHDR", ihdr), chunk("IDAT", deflateSync(raw)), chunk("IEND", Buffer.alloc(0))]);
20+const b64 = png.toString("base64");
21+console.log("png bytes", png.length, "b64", b64);
22+
23+const results: any = {};
24+for (const model of MODELS) {
25+ try {
26+ const res = await withRetry(() => ai.models.generateContent({
27+ model,
28+ contents: [{ role: "user", parts: [{ inlineData: { mimeType: "image/png", data: b64 } }, { text: "This is a tiny 2x2 pixel image. List the colours you can identify, comma-separated." }] }],
29+ config: { maxOutputTokens: 1500 },
30+ }));
31+ results[model] = { ok: true, text: shortText(res), usage: res.usageMetadata, finishReason: res.candidates?.[0]?.finishReason };
32+ } catch (e) { results[model] = { ok: false, error: errInfo(e) }; }
33+ await sleep(PACE_MS);
34+ console.log(model.padEnd(24), results[model].ok ? `OK "${results[model].text.slice(0, 60)}" promptTokens=${results[model].usage?.promptTokenCount} details=${JSON.stringify(results[model].usage?.promptTokensDetails)}` : `FAIL ${results[model].error.message.slice(0, 200)}`);
35+}
36+save(`04-vision${SUFFIX}.json`, results);
added research/gemini/05-errors-misc.ts +104 −0
@@ -0,0 +1,104 @@
1+// Probe 05: (g) invalid key (SDK + REST), unknown model 404, bad param 400 raw body, countTokens, chats helper,
2+// Authorization: Bearer test, v1 vs v1beta, models.get, explicit cache creation minimum error, and the Interactions API surface.
3+import { GoogleGenAI } from "@google/genai";
4+import { ai, KEY, save, errInfo } from "./lib.js";
5+
6+const results: any = {};
7+const BASE = "https://generativelanguage.googleapis.com";
8+
9+// (g) invalid key — REST
10+{
11+ const r = await fetch(`${BASE}/v1beta/models/gemini-2.5-flash:generateContent`, { method: "POST", headers: { "x-goog-api-key": "AQ.invalid-key-for-probe", "content-type": "application/json" }, body: JSON.stringify({ contents: [{ parts: [{ text: "hi" }] }] }) });
12+ results.invalidKeyRest = { status: r.status, body: await r.json(), wwwAuthenticate: r.headers.get("www-authenticate") };
13+ console.log("invalid key REST", r.status, JSON.stringify(results.invalidKeyRest.body).slice(0, 400));
14+}
15+// (g) invalid key — SDK
16+try {
17+ const bad = new GoogleGenAI({ apiKey: "AQ.invalid-key-for-probe" });
18+ await bad.models.generateContent({ model: "gemini-2.5-flash", contents: "hi", config: { maxOutputTokens: 5 } });
19+} catch (e: any) { results.invalidKeySdk = { ...errInfo(e), rawMessage: String(e?.message).slice(0, 500), ctor: e?.constructor?.name }; console.log("invalid key SDK", JSON.stringify(results.invalidKeySdk).slice(0, 400)); }
20+
21+// Bearer auth (does Authorization: Bearer <api key> work?)
22+{
23+ const r = await fetch(`${BASE}/v1beta/models?pageSize=1`, { headers: { authorization: `Bearer ${KEY}` } });
24+ results.bearerAuth = { status: r.status, body: r.status !== 200 ? await r.json() : "(ok)" };
25+ console.log("bearer", r.status, JSON.stringify(results.bearerAuth.body).slice(0, 300));
26+}
27+// ?key= query param
28+{
29+ const r = await fetch(`${BASE}/v1beta/models?pageSize=1&key=${encodeURIComponent(KEY)}`);
30+ results.keyQueryParam = { status: r.status };
31+ console.log("?key=", r.status);
32+}
33+// Unknown model
34+try { await ai.models.generateContent({ model: "gemini-9-ultra", contents: "hi" }); } catch (e) { results.unknownModel = errInfo(e); console.log("unknown model", JSON.stringify(results.unknownModel).slice(0, 400)); }
35+// Raw 400 error body
36+{
37+ const r = await fetch(`${BASE}/v1beta/models/gemini-2.5-flash:generateContent`, { method: "POST", headers: { "x-goog-api-key": KEY, "content-type": "application/json" }, body: JSON.stringify({ contents: [{ parts: [{ text: "hi" }] }], generationConfig: { temperature: 5 } }) });
38+ results.raw400 = { status: r.status, body: await r.json() };
39+ console.log("raw 400", JSON.stringify(results.raw400).slice(0, 500));
40+}
41+// Streaming error (bad param) via SSE: does the error come as HTTP status or as an SSE event?
42+{
43+ const r = await fetch(`${BASE}/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse`, { method: "POST", headers: { "x-goog-api-key": KEY, "content-type": "application/json" }, body: JSON.stringify({ contents: [{ parts: [{ text: "hi" }] }], generationConfig: { temperature: 5 } }) });
44+ results.streamError = { status: r.status, contentType: r.headers.get("content-type"), body: (await r.text()).slice(0, 500) };
45+ console.log("stream error", results.streamError.status, results.streamError.contentType);
46+}
47+// countTokens
48+try {
49+ const c = await ai.models.countTokens({ model: "gemini-3.8-flash", contents: "The quick brown fox jumps over the lazy dog." });
50+ results.countTokens = c; console.log("countTokens", JSON.stringify(c));
51+} catch (e) { results.countTokens = errInfo(e); console.log("countTokens ERR", JSON.stringify(results.countTokens)); }
52+// countTokens with systemInstruction + tools via REST generateContentRequest
53+{
54+ const r = await fetch(`${BASE}/v1beta/models/gemini-3.8-flash:countTokens`, { method: "POST", headers: { "x-goog-api-key": KEY, "content-type": "application/json" }, body: JSON.stringify({ generateContentRequest: { model: "models/gemini-3.8-flash", contents: [{ role: "user", parts: [{ text: "The quick brown fox jumps over the lazy dog." }] }], systemInstruction: { parts: [{ text: "You are a helpful assistant that answers briefly." }] }, tools: [{ functionDeclarations: [{ name: "f", description: "A function", parameters: { type: "OBJECT", properties: { a: { type: "STRING" } } } }] }] } }) });
55+ results.countTokensFull = { status: r.status, body: await r.json() };
56+ console.log("countTokens full", JSON.stringify(results.countTokensFull));
57+}
58+// models.get
59+try { const m = await ai.models.get({ model: "gemini-3.8-flash" }); results.modelsGet = m; console.log("models.get", JSON.stringify(m).slice(0, 400)); } catch (e) { results.modelsGet = errInfo(e); }
60+// v1 API version: does gemini-3.8-flash exist on v1? does thinkingConfig work there?
61+try {
62+ const v1 = new GoogleGenAI({ apiKey: KEY, httpOptions: { apiVersion: "v1" } });
63+ const res = await v1.models.generateContent({ model: "gemini-3.8-flash", contents: "Say hi", config: { maxOutputTokens: 50, thinkingConfig: { thinkingLevel: "LOW" as any } } });
64+ results.v1 = { ok: true, text: res.text, modelVersion: res.modelVersion };
65+} catch (e) { results.v1 = { ok: false, error: errInfo(e) }; }
66+console.log("v1", JSON.stringify(results.v1).slice(0, 300));
67+// chats helper (client-side history)
68+try {
69+ const chat = ai.chats.create({ model: "gemini-2.5-flash-lite", config: { maxOutputTokens: 60, thinkingConfig: { thinkingBudget: 0 } } });
70+ await chat.sendMessage({ message: "My name is Simon. Reply OK." });
71+ const r2 = await chat.sendMessage({ message: "What is my name? One word." });
72+ results.chats = { ok: true, text: r2.text, historyLen: chat.getHistory().length, historyRoles: chat.getHistory().map((c) => c.role) };
73+} catch (e) { results.chats = { ok: false, error: errInfo(e) }; }
74+console.log("chats", JSON.stringify(results.chats));
75+// explicit cache: small content should fail with minimum-token error → record exact message
76+try {
77+ const c = await ai.caches.create({ model: "gemini-2.5-flash", config: { contents: [{ role: "user", parts: [{ text: "short" }] }], ttl: "60s" } });
78+ results.cacheCreate = { ok: true, name: c.name }; await ai.caches.delete({ name: c.name! });
79+} catch (e) { results.cacheCreate = { ok: false, error: errInfo(e) }; }
80+console.log("cache", JSON.stringify(results.cacheCreate).slice(0, 400));
81+// Interactions API (new recommended surface) — does the SDK expose it, and does it work with this key?
82+try {
83+ const anyAi: any = ai;
84+ results.interactionsExposed = typeof anyAi.interactions?.create === "function";
85+ if (results.interactionsExposed) {
86+ const it = await anyAi.interactions.create({ model: "gemini-3.8-flash", input: "Say hi in two words.", generation_config: { thinking_level: "low", max_output_tokens: 50 }, store: false });
87+ results.interactions = { ok: true, keys: Object.keys(it), output_text: it.output_text, usage: it.usage, stepsTypes: (it.steps ?? it.outputs ?? []).map((s: any) => s.type) };
88+ }
89+} catch (e) { results.interactions = { ok: false, error: errInfo(e), raw: String((e as any)?.message).slice(0, 300) }; }
90+console.log("interactions", JSON.stringify(results.interactions).slice(0, 500));
91+// Safety settings accepted?
92+try {
93+ const res = await ai.models.generateContent({ model: "gemini-2.5-flash-lite", contents: "Say hi", config: { maxOutputTokens: 20, thinkingConfig: { thinkingBudget: 0 }, safetySettings: [{ category: "HARM_CATEGORY_HARASSMENT" as any, threshold: "BLOCK_NONE" as any }, { category: "HARM_CATEGORY_HATE_SPEECH" as any, threshold: "OFF" as any }] } });
94+ results.safety = { ok: true, text: res.text, safetyRatings: res.candidates?.[0]?.safetyRatings ?? null, promptFeedback: res.promptFeedback ?? null };
95+} catch (e) { results.safety = { ok: false, error: errInfo(e) }; }
96+console.log("safety", JSON.stringify(results.safety).slice(0, 300));
97+// Response headers on a normal request (rate-limit headers?)
98+{
99+ const r = await fetch(`${BASE}/v1beta/models/gemini-2.5-flash-lite:generateContent`, { method: "POST", headers: { "x-goog-api-key": KEY, "content-type": "application/json" }, body: JSON.stringify({ contents: [{ parts: [{ text: "hi" }] }], generationConfig: { maxOutputTokens: 5, thinkingConfig: { thinkingBudget: 0 } } }) });
100+ results.responseHeaders = Object.fromEntries([...r.headers.entries()]);
101+ await r.text();
102+ console.log("headers", JSON.stringify(results.responseHeaders));
103+}
104+save("05-errors-misc.json", results);
added research/gemini/06-availability.ts +26 −0
@@ -0,0 +1,26 @@
1+// Probe 06: which generateContent-capable text models actually answer with this (free-tier) key?
2+// One tiny request per model, serial and paced. Classifies: ok / 404 gone / 429 free-tier-zero / other.
3+import { readFileSync } from "node:fs";
4+import { ai, save, errInfo, quotaKind, sleep, PACE_MS, shortText } from "./lib.js";
5+
6+const models: any[] = JSON.parse(readFileSync("out/models.json", "utf8"));
7+const skip = /embedding|veo|lyria|tts|image|aqa|transcribe|live|native-audio|robotics|computer-use|deep-research|antigravity|nano-banana/;
8+const targets = models.filter((m) => m.supportedGenerationMethods?.includes("generateContent") && !skip.test(m.name)).map((m) => m.name.replace("models/", ""));
9+console.log("targets:", targets.join(", "));
10+
11+const results: any = {};
12+for (const model of targets) {
13+ const t0 = Date.now();
14+ try {
15+ const res = await ai.models.generateContent({ model, contents: "Reply with the single word: pong", config: { maxOutputTokens: 100 } });
16+ results[model] = { status: "ok", text: shortText(res), modelVersion: res.modelVersion, usage: res.usageMetadata, finishReason: res.candidates?.[0]?.finishReason, ms: Date.now() - t0 };
17+ } catch (e) {
18+ const info = errInfo(e);
19+ const kind = quotaKind(e);
20+ results[model] = { status: info.httpStatus === 404 ? "gone-404" : kind === "day" ? "free-tier-zero-429" : `error-${info.httpStatus}`, error: info, ms: Date.now() - t0 };
21+ }
22+ const r = results[model];
23+ console.log(model.padEnd(36), r.status.padEnd(20), r.status === "ok" ? `"${r.text}" v=${r.modelVersion} thoughts=${r.usage?.thoughtsTokenCount ?? 0}` : r.error.message.slice(0, 110).replace(/\n/g, " "));
24+ await sleep(1500);
25+}
26+save("06-availability.json", results);
added research/gemini/07-signature.ts +47 −0
@@ -0,0 +1,47 @@
1+// Probe 07: thought-signature strictness on function calling (Gemini 3.x).
2+// 1) get a functionCall (records whether thoughtSignature is on the functionCall part)
3+// 2) send functionResponse WITHOUT echoing the signature → record exact error (if any)
4+// 3) send with the real signature → OK? 4) send with dummy "skip_thought_signature_validator" → OK?
5+// 5) multi-turn text-only without echoing signature → OK? (signatures on text parts are optional per docs)
6+import { ai, MODELS, SUFFIX, save, errInfo, shortText, withRetry, sleep, PACE_MS } from "./lib.js";
7+
8+const model = MODELS[0];
9+const tool = { functionDeclarations: [{ name: "get_weather", description: "Get weather for a city.", parametersJsonSchema: { type: "object", properties: { city: { type: "string" } }, required: ["city"] } }] };
10+const results: any = { model };
11+
12+const first = await withRetry(() => ai.models.generateContent({ model, contents: [{ role: "user", parts: [{ text: "Weather in Montreal? Use the tool." }] }], config: { tools: [tool], maxOutputTokens: 2000 } }));
13+const parts: any[] = first.candidates?.[0]?.content?.parts ?? [];
14+results.firstTurnParts = parts.map((p) => ({ keys: Object.keys(p), fc: p.functionCall, sigLen: p.thoughtSignature?.length }));
15+console.log("first turn parts", JSON.stringify(results.firstTurnParts));
16+const fc = parts.find((p) => p.functionCall);
17+if (!fc) { console.log("no function call; abort"); save(`07-signature${SUFFIX}.json`, results); process.exit(0); }
18+
19+async function roundTrip(label: string, modelParts: any[]) {
20+ await sleep(PACE_MS);
21+ const contents = [
22+ { role: "user", parts: [{ text: "Weather in Montreal? Use the tool." }] },
23+ { role: "model", parts: modelParts },
24+ { role: "user", parts: [{ functionResponse: { name: fc.functionCall.name, id: fc.functionCall.id, response: { temperatureC: 21, condition: "sunny" } } }] },
25+ ];
26+ try {
27+ const r = await withRetry(() => ai.models.generateContent({ model, contents, config: { tools: [tool], maxOutputTokens: 2000 } }));
28+ results[label] = { ok: true, text: shortText(r), finishReason: r.candidates?.[0]?.finishReason };
29+ } catch (e) { results[label] = { ok: false, error: errInfo(e) }; }
30+ console.log(label, JSON.stringify(results[label]).slice(0, 400));
31+}
32+const stripSig = (p: any) => { const { thoughtSignature, ...rest } = p; return rest; };
33+await roundTrip("withSignature", parts);
34+await roundTrip("withoutSignature", parts.map(stripSig));
35+await roundTrip("dummySignature", parts.map((p) => (p.functionCall ? { ...stripSig(p), thoughtSignature: "skip_thought_signature_validator" } : stripSig(p))));
36+
37+// 5) text-only multi-turn without signatures
38+await sleep(PACE_MS);
39+try {
40+ const t1 = await withRetry(() => ai.models.generateContent({ model, contents: "Pick a random fruit and tell me only its name.", config: { maxOutputTokens: 1500 } }));
41+ const p1: any[] = (t1.candidates?.[0]?.content?.parts ?? []).map(stripSig);
42+ await sleep(PACE_MS);
43+ const t2 = await withRetry(() => ai.models.generateContent({ model, contents: [{ role: "user", parts: [{ text: "Pick a random fruit and tell me only its name." }] }, { role: "model", parts: p1 }, { role: "user", parts: [{ text: "What colour is it? One word." }] }], config: { maxOutputTokens: 1500 } }));
44+ results.textMultiTurnNoSig = { ok: true, fruit: shortText(t1), colour: shortText(t2), firstTurnHadSig: (t1.candidates?.[0]?.content?.parts ?? []).some((p: any) => p.thoughtSignature) };
45+} catch (e) { results.textMultiTurnNoSig = { ok: false, error: errInfo(e) }; }
46+console.log("textMultiTurnNoSig", JSON.stringify(results.textMultiTurnNoSig));
47+save(`07-signature${SUFFIX}.json`, results);
added research/gemini/08-rest-sse.ts +20 −0
@@ -0,0 +1,20 @@
1+// Probe 08: raw REST streaming protocol (alt=sse) and the default (no alt) JSON-array streaming, on one model.
2+import { KEY, MODELS, save } from "./lib.js";
3+const model = MODELS[0];
4+const body = JSON.stringify({ contents: [{ role: "user", parts: [{ text: "Say hello in five words, then think of nothing else." }] }], generationConfig: { maxOutputTokens: 1500, thinkingConfig: { includeThoughts: true, thinkingLevel: "LOW" } } });
5+const results: any = { model };
6+{
7+ const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:streamGenerateContent?alt=sse`, { method: "POST", headers: { "x-goog-api-key": KEY, "content-type": "application/json" }, body });
8+ const raw = await res.text();
9+ const events = raw.split("\n\n").filter((s) => s.trim());
10+ results.sse = { status: res.status, contentType: res.headers.get("content-type"), transferEncoding: res.headers.get("transfer-encoding"), eventCount: events.length, firstEventRaw: events[0]?.slice(0, 1500), lastEventRaw: events.at(-1)?.slice(0, 1500), linePrefixes: [...new Set(events.flatMap((e) => e.split("\n").map((l) => l.split(":")[0])))] };
11+ console.log("SSE", res.status, results.sse.contentType, "events", events.length, "prefixes", results.sse.linePrefixes);
12+ console.log(events[0]?.slice(0, 600));
13+}
14+{
15+ const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:streamGenerateContent`, { method: "POST", headers: { "x-goog-api-key": KEY, "content-type": "application/json" }, body });
16+ const raw = await res.text();
17+ results.noAlt = { status: res.status, contentType: res.headers.get("content-type"), startsWith: raw.slice(0, 120), endsWith: raw.slice(-60) };
18+ console.log("no-alt", res.status, results.noAlt.contentType, JSON.stringify(results.noAlt.startsWith));
19+}
20+save(`08-rest-sse-${model}.json`, results);
added research/gemini/lib.ts +89 −0
@@ -0,0 +1,89 @@
1+// Shared helpers for the Gemini probes. No secrets here: the key comes from env GOOGLE_GEMINI_API_KEY.
2+import { GoogleGenAI } from "@google/genai";
3+import { mkdirSync, writeFileSync } from "node:fs";
4+
5+export const KEY = process.env.GOOGLE_GEMINI_API_KEY ?? "";
6+if (!KEY) throw new Error("GOOGLE_GEMINI_API_KEY missing (set -a; . ../../.env; set +a)");
7+
8+export const ai = new GoogleGenAI({ apiKey: KEY, httpOptions: { timeout: 120_000 } });
9+
10+// Requested set was 3.8-flash, 3.5-flash, 3.1-pro-preview, 2.5-flash, 2.5-pro, omni — but with this free-tier key
11+// 2.5-* return 404 "no longer available to new users" and 3.1-pro / omni have free-tier quota 0 (see out/06-availability.json).
12+// Default probe set = accessible models; override with argv[2] = comma-separated ids.
13+export const DEFAULT_MODELS = [
14+ "gemini-3.8-flash",
15+ "gemini-3.5-flash",
16+ "gemini-3.5-flash-lite",
17+ "gemini-3.1-flash-lite",
18+ "gemini-3-flash-preview",
19+ "gemma-4-31b-it",
20+];
21+export const MODELS = process.argv[2] ? process.argv[2].split(",") : DEFAULT_MODELS;
22+export const SUFFIX = process.argv[2] ? "-" + process.argv[2].replace(/[^a-z0-9.-]/gi, "_") : "";
23+
24+mkdirSync("out", { recursive: true });
25+
26+export function save(name: string, data: unknown) {
27+ writeFileSync(`out/${name}`, JSON.stringify(data, redact, 2));
28+}
29+
30+// Never let a key leak into saved output.
31+function redact(_k: string, v: unknown) {
32+ if (typeof v === "string" && KEY && v.includes(KEY)) return v.replaceAll(KEY, "[REDACTED]");
33+ return v;
34+}
35+
36+export function errInfo(e: any) {
37+ // SDK throws ApiError {name, message, status}. message is usually the JSON error body as string.
38+ let parsed: any = null;
39+ const m: string = e?.message ?? String(e);
40+ try { parsed = JSON.parse(m); } catch { /* not json */ }
41+ const inner = parsed?.error ?? parsed;
42+ return {
43+ name: e?.name,
44+ httpStatus: e?.status ?? inner?.code ?? null,
45+ status: inner?.status ?? null,
46+ message: (inner?.message ?? m).slice(0, 400),
47+ details: inner?.details ?? null,
48+ };
49+}
50+
51+export const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
52+
53+/** Classify a 429: per-minute quota → retryable; per-day / limit 0 → give up for this model. */
54+export function quotaKind(e: any): "minute" | "day" | "other" {
55+ const info = errInfo(e);
56+ if (info.httpStatus !== 429) return "other";
57+ const q = (info.details ?? []).find((d: any) => String(d["@type"]).includes("QuotaFailure"));
58+ const ids: string[] = (q?.violations ?? []).map((v: any) => v.quotaId);
59+ if (ids.some((i) => /PerDay/.test(i))) return "day";
60+ if (ids.some((i) => /PerMinute/.test(i))) return "minute";
61+ return "other";
62+}
63+
64+/** Retry on per-minute 429 (honouring RetryInfo.retryDelay) and on 503 high demand; max `tries`. */
65+export async function withRetry<T>(fn: () => Promise<T>, tries = 4): Promise<T> {
66+ let last: any;
67+ for (let i = 0; i < tries; i++) {
68+ try { return await fn(); } catch (e: any) {
69+ last = e;
70+ const info = errInfo(e);
71+ const kind = quotaKind(e);
72+ if (kind === "minute" || info.httpStatus === 503) {
73+ const ri = (info.details ?? []).find((d: any) => String(d["@type"]).includes("RetryInfo"));
74+ const secs = ri?.retryDelay ? parseInt(String(ri.retryDelay)) + 2 : 20;
75+ console.log(` ..${info.httpStatus} (${kind}); waiting ${secs}s then retry ${i + 1}/${tries - 1}`);
76+ await sleep(secs * 1000);
77+ continue;
78+ }
79+ throw e;
80+ }
81+ }
82+ throw last;
83+}
84+
85+/** Pace requests to stay under the free-tier RPM for a given model. */
86+export const PACE_MS = Number(process.env.PROBE_PACE_MS ?? 7000);
87+
88+export const shortText = (r: any) =>
89+ (r?.candidates?.[0]?.content?.parts ?? []).filter((p: any) => p.text && !p.thought).map((p: any) => p.text).join("").slice(0, 120);
added research/gemini/package.json +24 −0
@@ -0,0 +1,24 @@
1+{
2+ "name": "gemini",
3+ "version": "1.0.0",
4+ "description": "",
5+ "main": "index.js",
6+ "scripts": {
7+ "test": "echo \"Error: no test specified\" && exit 1"
8+ },
9+ "keywords": [],
10+ "author": "",
11+ "license": "ISC",
12+ "devEngines": {
13+ "packageManager": {
14+ "name": "pnpm",
15+ "version": "^11.1.2",
16+ "onFail": "download"
17+ }
18+ },
19+ "type": "module",
20+ "dependencies": {
21+ "@google/genai": "^2.21.0",
22+ "tsx": "^4.23.13"
23+ }
24+}
added research/gemini/pnpm-lock.yaml +91 −0
@@ -0,0 +1,824 @@
1+---
2+lockfileVersion: '9.0'
3+
4+importers:
5+
6+ .:
7+ configDependencies: {}
8+ packageManagerDependencies:
9+ '@pnpm/exe':
10+ specifier: ^11.1.2
11+ version: 11.26.0
12+ pnpm:
13+ specifier: ^11.1.2
14+ version: 11.26.0
15+
16+packages:
17+
18+ '@pnpm/exe@11.26.0':
19+ resolution: {integrity: sha512-eeiNi7WeXulOO1BzDAU9HIk+N3dokG+xwKPUupNQoZT5auL3rh2pFW9DqdIEnCC2xtt/hZd6UGtKyb6OMpqndw==}
20+ hasBin: true
21+
22+ '@pnpm/linux-arm64@11.26.0':
23+ resolution: {integrity: sha512-M0IDuD4hbXxpLBsj1/I9pODcxu/gxTDtbyQmsVGYu1TZwCCpf6YU1x3lzq8aCGjrysmXYQAtCiY8GBjdw4UGFg==}
24+ cpu: [arm64]
25+ os: [linux]
26+
27+ '@pnpm/linux-x64@11.26.0':
28+ resolution: {integrity: sha512-nUuNRsFCGVje3FHtOaWxIQl2EP4NBktKr+PpLN7uhuWnJCCMN/F9RKjNJAM+dUPyvAZs8VDvS0kA8J55kyybyg==}
29+ cpu: [x64]
30+ os: [linux]
31+
32+ '@pnpm/linuxstatic-arm64@11.26.0':
33+ resolution: {integrity: sha512-+dXROkvdWjskrQtjwJAFuJI7Q2uTkghBfLsd0vqRmorX3fPuinhoRjJJ/UPtWXzJqwcByJBmdJRW+q2964m5qQ==}
34+ cpu: [arm64]
35+ os: [linux]
36+ libc: [musl]
37+
38+ '@pnpm/linuxstatic-x64@11.26.0':
39+ resolution: {integrity: sha512-0eXE6spzIBdCbYhJZQ0u/sIOD0v30sqk2PrzoixzsNMc7S/lhd7EkBMVJ6cCPiCL2TXvOsrJC2SpWPBK769A9A==}
40+ cpu: [x64]
41+ os: [linux]
42+ libc: [musl]
43+
44+ '@pnpm/macos-arm64@11.26.0':
45+ resolution: {integrity: sha512-Za3kKV89Zj0SFzQf6zEUTUIy13xH8UiNyb7aILDRjPiTvTaUSCh3q+nvljISfGH1XcopXvo+p3K8Q2nrKYWAug==}
46+ cpu: [arm64]
47+ os: [darwin]
48+
49+ '@pnpm/win-arm64@11.26.0':
50+ resolution: {integrity: sha512-5akeLtbqbFDdJtCV4qgLmDBV3R+XNs6E7h7Xb4ZBzS3rLRp8e/y/ZdgrZaGF5Kjo45g0BLAxdGUREHbU2/lGUw==}
51+ cpu: [arm64]
52+ os: [win32]
53+
54+ '@pnpm/win-x64@11.26.0':
55+ resolution: {integrity: sha512-f15SfIo7nppxBII+STy6jpd1z3LgGTZh6skfuxKA/xHmkzopnQJQXr4hBnl1rJLJAnmuOhN8BssaC4LiXmS78w==}
56+ cpu: [x64]
57+ os: [win32]
58+
59+ '@reflink/reflink-darwin-arm64@0.1.19':
60+ resolution: {integrity: sha512-ruy44Lpepdk1FqDz38vExBY/PVUsjxZA+chd9wozjUH9JjuDT/HEaQYA6wYN9mf041l0yLVar6BCZuWABJvHSA==}
61+ engines: {node: '>= 10'}
62+ cpu: [arm64]
63+ os: [darwin]
64+
65+ '@reflink/reflink-darwin-x64@0.1.19':
66+ resolution: {integrity: sha512-By85MSWrMZa+c26TcnAy8SDk0sTUkYlNnwknSchkhHpGXOtjNDUOxJE9oByBnGbeuIE1PiQsxDG3Ud+IVV9yuA==}
67+ engines: {node: '>= 10'}
68+ cpu: [x64]
69+ os: [darwin]
70+
71+ '@reflink/reflink-linux-arm64-gnu@0.1.19':
72+ resolution: {integrity: sha512-7P+er8+rP9iNeN+bfmccM4hTAaLP6PQJPKWSA4iSk2bNvo6KU6RyPgYeHxXmzNKzPVRcypZQTpFgstHam6maVg==}
73+ engines: {node: '>= 10'}
74+ cpu: [arm64]
75+ os: [linux]
76+ libc: [glibc]
77+
78+ '@reflink/reflink-linux-arm64-musl@0.1.19':
79+ resolution: {integrity: sha512-37iO/Dp6m5DDaC2sf3zPtx/hl9FV3Xze4xoYidrxxS9bgP3S8ALroxRK6xBG/1TtfXKTvolvp+IjrUU6ujIGmA==}
80+ engines: {node: '>= 10'}
81+ cpu: [arm64]
82+ os: [linux]
83+ libc: [musl]
84+
85+ '@reflink/reflink-linux-x64-gnu@0.1.19':
86+ resolution: {integrity: sha512-jbI8jvuYCaA3MVUdu8vLoLAFqC+iNMpiSuLbxlAgg7x3K5bsS8nOpTRnkLF7vISJ+rVR8W+7ThXlXlUQ93ulkw==}
87+ engines: {node: '>= 10'}
88+ cpu: [x64]
89+ os: [linux]
90+ libc: [glibc]
91+

Diff truncated — file too large.

Menu

Theme