diff --git a/.gitignore b/.gitignore
index 6e661a6c..8f35c826 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,3 +76,6 @@ yarn-debug.log*
yarn-error.log*
local-release/
.omx/
+
+# Runtime state (written by app at runtime)
+state/
diff --git a/build/electron-builder.runtime.json b/build/electron-builder.runtime.json
deleted file mode 100644
index db123b28..00000000
--- a/build/electron-builder.runtime.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "extends": "/Users/zacharyzhang/Documents/Github/AgentCompany/electron-builder.yml",
- "directories": {
- "output": "/Users/zacharyzhang/Documents/Github/AgentCompany/build/release"
- },
- "extraMetadata": {
- "version": "0.4.167"
- },
- "publish": [
- {
- "provider": "generic",
- "url": "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC"
- }
- ],
- "mac": {
- "hardenedRuntime": true,
- "sign": "/Users/zacharyzhang/Documents/Github/AgentCompany/scripts/electron-builder-mac-sign.mjs"
- }
-}
diff --git a/logo.svg b/logo.svg
deleted file mode 100644
index bbf75d8f..00000000
--- a/logo.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
diff --git a/pi-mono-reference/.gitattributes b/pi-mono-reference/.gitattributes
deleted file mode 100644
index d8a52c2e..00000000
--- a/pi-mono-reference/.gitattributes
+++ /dev/null
@@ -1,23 +0,0 @@
-# Default to LF for text files across the repo
-* text=auto eol=lf
-
-# Windows scripts should keep CRLF
-*.bat text eol=crlf
-*.cmd text eol=crlf
-*.ps1 text eol=crlf
-
-# Shell scripts should keep LF
-*.sh text eol=lf
-
-# Common binary assets
-*.png binary
-*.jpg binary
-*.jpeg binary
-*.gif binary
-*.webp binary
-*.ico binary
-*.pdf binary
-*.zip binary
-*.gz binary
-*.woff binary
-*.woff2 binary
diff --git a/pi-mono-reference/.github/APPROVED_CONTRIBUTORS b/pi-mono-reference/.github/APPROVED_CONTRIBUTORS
deleted file mode 100644
index 58dd8181..00000000
--- a/pi-mono-reference/.github/APPROVED_CONTRIBUTORS
+++ /dev/null
@@ -1,153 +0,0 @@
-# GitHub handles approved to bypass contribution auto-close
-# Format:
-# capability:
-# issue future issues stay open
-# pr future issues and PRs stay open
-
-barapa pr
-alasano pr
-aadishv pr
-airtonix pr
-aliou pr
-aos pr
-austinm911 pr
-banteg pr
-ben-vargas pr
-butelo pr
-can1357 pr
-CarlosGtrz pr
-cau1k pr
-cmf pr
-crcatala pr
-Cursivez pr
-cv pr
-dannote pr
-default-anton pr
-dnouri pr
-DronNick pr
-enisdenjo pr
-ferologics pr
-fightbulc pr
-ghoulr pr
-gnattu pr
-HACKE-RC pr
-hewliyang pr
-hjanuschka pr
-iamd3vil pr
-jblwilliams pr
-joshp123 pr
-jsinge97 pr
-justram pr
-kaofelix pr
-kiliman pr
-kim0 pr
-lockmeister pr
-LukeFost pr
-lukele pr
-m-box-mr pr
-marckrenn pr
-markusylisiurunen pr
-mcinteerj pr
-melihmucuk pr
-mitsuhiko pr
-mrexodia pr
-nathyong pr
-nickseelert pr
-nicobailon pr
-ninlds pr
-ogulcancelik pr
-patrick-kidger pr
-paulbettner pr
-Perlence pr
-pjtf93 pr
-prateekmedia pr
-prathamdby pr
-ribelo pr
-richardgill pr
-robinwander pr
-ronyrus pr
-roshanasingh4 pr
-scutifer pr
-skuridin pr
-steipete pr
-svkozak pr
-tallshort pr
-theBucky pr
-thomasmhr pr
-tiagoefreitas pr
-timolins pr
-tmustier pr
-tudoroancea pr
-unexge pr
-vaayne pr
-VaclavSynacek pr
-vsabavat pr
-w-winter pr
-Whamp pr
-WismutHansen pr
-XesGaDeus pr
-yevhen pr
-badlogictest pr
-terrorobe pr
-zedrdave pr
-mrud pr
-toorusr pr
-andresaraujo pr
-lightningRalf pr
-williballenthin pr
-masonc15 pr
-4h9fbZ pr
-haoqixu pr
-Graffioh pr
-charles-cooper pr
-emanuelst pr
-juanibiapina pr
-liby pr
-pasky pr
-odysseus0 pr
-giuseppeg pr
-michaelpersonal pr
-academo pr
-PriNova pr
-semtexzv pr
-jasonish pr
-markusn pr
-SamFold pr
-Soleone pr
-virtuald pr
-NateSmyth pr
-7Sageer pr
-MatthieuBizien pr
-sumeet pr
-marchellodev pr
-vedang pr
-lucemia pr
-mcollina pr
-lajarre pr
-smithbm2316 pr
-drewburr pr
-gordonhwc pr
-deybhayden pr
-tintinweb pr
-asoules pr
-zhahaoyu pr
-in0vik pr
-jtac pr
-yzhg1983 pr
-smcllns pr
-dmmulroy pr
-zmberber pr
-andresvi94 pr
-bjesuiter pr
-sudosubin pr
-dyyz1993 pr
-Mic92 pr
-pmateusz pr
-wirjo pr
-jay-aye-see-kay pr
-lucasmeijer pr
-Evizero pr
-
-ofa1 pr
-
-crisog issue
diff --git a/pi-mono-reference/.github/ISSUE_TEMPLATE/bug.yml b/pi-mono-reference/.github/ISSUE_TEMPLATE/bug.yml
deleted file mode 100644
index 147c6400..00000000
--- a/pi-mono-reference/.github/ISSUE_TEMPLATE/bug.yml
+++ /dev/null
@@ -1,43 +0,0 @@
-name: Bug Report
-description: Report something that's broken
-labels: ["bug"]
-body:
- - type: markdown
- attributes:
- value: |
- **Before you start:** Read [CONTRIBUTING.md](https://github.com/badlogic/pi-mono/blob/main/CONTRIBUTING.md).
-
- New issues from new contributors are auto-closed by default. Maintainers review auto-closed issues daily. Issues that do not meet the quality bar in [CONTRIBUTING.md](https://github.com/badlogic/pi-mono/blob/main/CONTRIBUTING.md) will not be reopened or receive a reply.
-
- Keep this short. If it doesn't fit on one screen, it's too long. Write in your own voice.
-
- - type: textarea
- id: description
- attributes:
- label: What happened?
- description: Be specific. Include error messages if any.
- validations:
- required: true
-
- - type: textarea
- id: repro
- attributes:
- label: Steps to reproduce
- description: Minimal steps to trigger the bug.
- validations:
- required: true
-
- - type: textarea
- id: expected
- attributes:
- label: Expected behavior
- validations:
- required: false
-
- - type: input
- id: version
- attributes:
- label: Version
- description: e.g. 0.49.0
- validations:
- required: false
diff --git a/pi-mono-reference/.github/ISSUE_TEMPLATE/config.yml b/pi-mono-reference/.github/ISSUE_TEMPLATE/config.yml
deleted file mode 100644
index 66b6798c..00000000
--- a/pi-mono-reference/.github/ISSUE_TEMPLATE/config.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-blank_issues_enabled: false
-contact_links:
- - name: Questions
- url: https://discord.com/invite/3cU7Bz4UPx
- about: Ask questions on Discord instead of opening an issue
diff --git a/pi-mono-reference/.github/ISSUE_TEMPLATE/contribution.yml b/pi-mono-reference/.github/ISSUE_TEMPLATE/contribution.yml
deleted file mode 100644
index f0d9204c..00000000
--- a/pi-mono-reference/.github/ISSUE_TEMPLATE/contribution.yml
+++ /dev/null
@@ -1,36 +0,0 @@
-name: Contribution Proposal
-description: Propose a change or feature (required for new contributors before submitting a PR)
-labels: []
-body:
- - type: markdown
- attributes:
- value: |
- **Before you start:** Read [CONTRIBUTING.md](https://github.com/badlogic/pi-mono/blob/main/CONTRIBUTING.md).
-
- New issues from new contributors are auto-closed by default. Maintainers review auto-closed issues daily. Issues that do not meet the quality bar in [CONTRIBUTING.md](https://github.com/badlogic/pi-mono/blob/main/CONTRIBUTING.md) will not be reopened or receive a reply.
-
- Keep this short. If it doesn't fit on one screen, it's too long. Write in your own voice.
-
- - type: textarea
- id: what
- attributes:
- label: What do you want to change?
- description: Be specific and concise.
- validations:
- required: true
-
- - type: textarea
- id: why
- attributes:
- label: Why?
- description: What problem does this solve?
- validations:
- required: true
-
- - type: textarea
- id: how
- attributes:
- label: How? (optional)
- description: Brief technical approach if you have one in mind.
- validations:
- required: false
diff --git a/pi-mono-reference/.github/workflows/approve-contributor.yml b/pi-mono-reference/.github/workflows/approve-contributor.yml
deleted file mode 100644
index 794efad6..00000000
--- a/pi-mono-reference/.github/workflows/approve-contributor.yml
+++ /dev/null
@@ -1,179 +0,0 @@
-name: Approve Contributor
-
-on:
- issue_comment:
- types: [created]
-
-jobs:
- approve:
- if: ${{ !github.event.issue.pull_request }}
- runs-on: ubuntu-latest
- permissions:
- contents: write
- issues: write
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- ref: ${{ github.event.repository.default_branch }}
-
- - name: Update contributor approval
- id: update
- uses: actions/github-script@v7
- with:
- script: |
- const fs = require('fs');
-
- const APPROVED_FILE = '.github/APPROVED_CONTRIBUTORS';
- const VALID_CAPABILITIES = new Set(['issue', 'pr']);
- const issueAuthor = context.payload.issue.user.login;
- const commenter = context.payload.comment.user.login;
- const commentBody = (context.payload.comment.body || '').trim();
-
- let targetCapability;
- if (/\blgtmi\b/i.test(commentBody)) {
- targetCapability = 'issue';
- } else if (/\blgtm\b/i.test(commentBody)) {
- targetCapability = 'pr';
- } else {
- console.log('Comment does not match lgtm or lgtmi');
- core.setOutput('status', 'skipped');
- return;
- }
-
- try {
- const { data: permissionLevel } = await github.rest.repos.getCollaboratorPermissionLevel({
- owner: context.repo.owner,
- repo: context.repo.repo,
- username: commenter,
- });
-
- if (!['admin', 'maintain', 'write'].includes(permissionLevel.permission)) {
- console.log(`${commenter} does not have write access`);
- core.setOutput('status', 'skipped');
- return;
- }
- } catch {
- console.log(`${commenter} does not have collaborator access`);
- core.setOutput('status', 'skipped');
- return;
- }
-
- function parseApprovedUsers(content) {
- const lines = content.split('\n');
- const entries = [];
- const users = new Map();
-
- for (const line of lines) {
- const trimmed = line.trim();
- if (!trimmed || trimmed.startsWith('#')) {
- entries.push({ type: 'other', line });
- continue;
- }
-
- const parts = trimmed.split(/\s+/);
- if (parts.length !== 2) {
- console.log(`Skipping malformed line: ${line}`);
- entries.push({ type: 'other', line });
- continue;
- }
-
- const [username, capability] = parts;
- const normalizedCapability = capability.toLowerCase();
- if (!VALID_CAPABILITIES.has(normalizedCapability)) {
- console.log(`Skipping line with invalid capability: ${line}`);
- entries.push({ type: 'other', line });
- continue;
- }
-
- const normalizedUser = username.toLowerCase();
- const entry = { type: 'user', username, normalizedUser, capability: normalizedCapability };
- entries.push(entry);
- users.set(normalizedUser, entry);
- }
-
- return { entries, users };
- }
-
- function stringifyApprovedUsers(entries) {
- const normalizedEntries = [...entries];
-
- while (normalizedEntries.length > 0) {
- const lastEntry = normalizedEntries[normalizedEntries.length - 1];
- if (lastEntry.type !== 'other' || lastEntry.line.trim() !== '') {
- break;
- }
- normalizedEntries.pop();
- }
-
- return `${normalizedEntries
- .map((entry) => (entry.type === 'user' ? `${entry.username} ${entry.capability}` : entry.line))
- .join('\n')}\n`;
- }
-
- const content = fs.readFileSync(APPROVED_FILE, 'utf8');
- const { entries, users } = parseApprovedUsers(content);
- const normalizedAuthor = issueAuthor.toLowerCase();
- const existingEntry = users.get(normalizedAuthor);
- const existingCapability = existingEntry?.capability ?? null;
-
- if (existingCapability === 'pr' || existingCapability === targetCapability) {
- core.setOutput('status', 'already');
- core.setOutput('capability', existingCapability);
- console.log(`${issueAuthor} is already approved for ${existingCapability}`);
- return;
- }
-
- if (existingEntry) {
- existingEntry.capability = targetCapability;
- } else {
- entries.push({ type: 'user', username: issueAuthor, normalizedUser: normalizedAuthor, capability: targetCapability });
- }
-
- fs.writeFileSync(APPROVED_FILE, stringifyApprovedUsers(entries));
- core.setOutput('status', existingCapability ? 'updated' : 'added');
- core.setOutput('capability', targetCapability);
- console.log(`Set ${issueAuthor} capability to ${targetCapability}`);
-
- - name: Commit and push
- if: steps.update.outputs.status == 'added' || steps.update.outputs.status == 'updated'
- run: |
- git config user.name "github-actions[bot]"
- git config user.email "github-actions[bot]@users.noreply.github.com"
- git add .github/APPROVED_CONTRIBUTORS
- git diff --staged --quiet || git commit -m "chore: approve contributor ${{ github.event.issue.user.login }}"
- git push
-
- - name: Comment on issue
- if: steps.update.outputs.status == 'added' || steps.update.outputs.status == 'updated' || steps.update.outputs.status == 'already'
- uses: actions/github-script@v7
- with:
- script: |
- const issueAuthor = context.payload.issue.user.login;
- const capability = '${{ steps.update.outputs.capability }}';
- const defaultBranch = context.payload.repository.default_branch;
- let body;
-
- if ('${{ steps.update.outputs.status }}' === 'already') {
- body = `@${issueAuthor} is already approved.`;
- } else if (capability === 'issue') {
- body = [
- `@${issueAuthor} approved for issues. Your future issues will not be auto-closed. PRs still require \`lgtm\`.`,
- '',
- `See [CONTRIBUTING.md](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/${defaultBranch}/CONTRIBUTING.md).`,
- ].join('\n');
- } else {
- body = [
- `@${issueAuthor} approved for issues and PRs. Your future issues and PRs will not be auto-closed.`,
- '',
- `See [CONTRIBUTING.md](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/${defaultBranch}/CONTRIBUTING.md).`,
- ].join('\n');
- }
-
- await github.rest.issues.createComment({
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: context.issue.number,
- body,
- });
-
diff --git a/pi-mono-reference/.github/workflows/build-binaries.yml b/pi-mono-reference/.github/workflows/build-binaries.yml
deleted file mode 100644
index fcff2104..00000000
--- a/pi-mono-reference/.github/workflows/build-binaries.yml
+++ /dev/null
@@ -1,79 +0,0 @@
-name: Build Binaries
-
-on:
- push:
- tags:
- - 'v*'
- workflow_dispatch:
- inputs:
- tag:
- description: 'Tag to build (e.g., v0.12.0)'
- required: true
- type: string
-
-permissions:
- contents: write
-
-jobs:
- build:
- runs-on: ubuntu-latest
- env:
- RELEASE_TAG: ${{ github.event.inputs.tag || github.ref_name }}
- steps:
- - name: Checkout
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- with:
- ref: ${{ env.RELEASE_TAG }}
-
- - name: Setup Bun
- uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1
- with:
- bun-version: 1.2.20
-
- - name: Setup Node.js
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
- with:
- node-version: '22'
- registry-url: 'https://registry.npmjs.org'
-
- - name: Build binaries
- run: ./scripts/build-binaries.sh
-
- - name: Extract changelog for this version
- id: changelog
- run: |
- VERSION="${RELEASE_TAG}"
- VERSION="${VERSION#v}" # Remove 'v' prefix
-
- # Extract changelog section for this version
- cd packages/coding-agent
- awk "/^## \[${VERSION}\]/{flag=1; next} /^## \[/{flag=0} flag" CHANGELOG.md > /tmp/release-notes.md
-
- # If empty, use a default message
- if [ ! -s /tmp/release-notes.md ]; then
- echo "Release ${VERSION}" > /tmp/release-notes.md
- fi
-
- - name: Create GitHub Release and upload binaries
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- cd packages/coding-agent/binaries
-
- # Create release with changelog notes (or update if exists)
- gh release create "${RELEASE_TAG}" \
- --title "${RELEASE_TAG}" \
- --notes-file /tmp/release-notes.md \
- pi-darwin-arm64.tar.gz \
- pi-darwin-x64.tar.gz \
- pi-linux-x64.tar.gz \
- pi-linux-arm64.tar.gz \
- pi-windows-x64.zip \
- 2>/dev/null || \
- gh release upload "${RELEASE_TAG}" \
- pi-darwin-arm64.tar.gz \
- pi-darwin-x64.tar.gz \
- pi-linux-x64.tar.gz \
- pi-linux-arm64.tar.gz \
- pi-windows-x64.zip \
- --clobber
diff --git a/pi-mono-reference/.github/workflows/ci.yml b/pi-mono-reference/.github/workflows/ci.yml
deleted file mode 100644
index ef5b18da..00000000
--- a/pi-mono-reference/.github/workflows/ci.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-name: CI
-
-on:
- push:
- branches: [main]
- pull_request:
- branches: [main]
-
-concurrency:
- group: ci-${{ github.ref }}
- cancel-in-progress: true
-
-jobs:
- build-check-test:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Setup Node.js
- uses: actions/setup-node@v4
- with:
- node-version: 22
- cache: npm
-
- - name: Install system dependencies
- run: |
- sudo apt-get update
- sudo apt-get install -y libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev fd-find ripgrep
- sudo ln -s $(which fdfind) /usr/local/bin/fd
-
- - name: Install dependencies
- run: npm ci
-
- - name: Build
- run: npm run build
-
- - name: Check
- run: npm run check
-
- - name: Test
- run: npm test
diff --git a/pi-mono-reference/.github/workflows/issue-gate.yml b/pi-mono-reference/.github/workflows/issue-gate.yml
deleted file mode 100644
index 62663940..00000000
--- a/pi-mono-reference/.github/workflows/issue-gate.yml
+++ /dev/null
@@ -1,119 +0,0 @@
-name: Issue Gate
-
-on:
- issues:
- types: [opened]
-
-jobs:
- check-contributor:
- runs-on: ubuntu-latest
- permissions:
- contents: read
- issues: write
- steps:
- - name: Check issue author
- uses: actions/github-script@v7
- with:
- script: |
- const APPROVED_FILE = '.github/APPROVED_CONTRIBUTORS';
- const VALID_CAPABILITIES = new Set(['issue', 'pr']);
- const issueAuthor = context.payload.issue.user.login;
- const defaultBranch = context.payload.repository.default_branch;
-
- if (issueAuthor.endsWith('[bot]') || issueAuthor === 'dependabot[bot]') {
- console.log(`Skipping bot: ${issueAuthor}`);
- return;
- }
-
- async function getPermission(username) {
- try {
- const { data: permissionLevel } = await github.rest.repos.getCollaboratorPermissionLevel({
- owner: context.repo.owner,
- repo: context.repo.repo,
- username,
- });
- return permissionLevel.permission;
- } catch {
- return null;
- }
- }
-
- async function getTextFile(path) {
- const { data: fileContent } = await github.rest.repos.getContent({
- owner: context.repo.owner,
- repo: context.repo.repo,
- path,
- ref: defaultBranch,
- });
-
- if (!('content' in fileContent) || typeof fileContent.content !== 'string') {
- throw new Error(`Expected file content for ${path}`);
- }
-
- return Buffer.from(fileContent.content, 'base64').toString('utf8');
- }
-
- function parseApprovedUsers(content) {
- const users = new Map();
-
- for (const rawLine of content.split('\n')) {
- const line = rawLine.trim();
- if (!line || line.startsWith('#')) continue;
-
- const parts = line.split(/\s+/);
- if (parts.length !== 2) {
- console.log(`Skipping malformed line: ${rawLine}`);
- continue;
- }
-
- const [username, capability] = parts;
- const normalizedCapability = capability.toLowerCase();
- if (!VALID_CAPABILITIES.has(normalizedCapability)) {
- console.log(`Skipping line with invalid capability: ${rawLine}`);
- continue;
- }
-
- users.set(username.toLowerCase(), normalizedCapability);
- }
-
- return users;
- }
-
- const permission = await getPermission(issueAuthor);
- if (['admin', 'maintain', 'write'].includes(permission)) {
- console.log(`${issueAuthor} is a collaborator with ${permission} access`);
- return;
- }
-
- const approvedContent = await getTextFile(APPROVED_FILE);
- const approvedUsers = parseApprovedUsers(approvedContent);
- const capability = approvedUsers.get(issueAuthor.toLowerCase());
-
- if (capability === 'issue' || capability === 'pr') {
- console.log(`${issueAuthor} is approved for ${capability}`);
- return;
- }
-
- const message = [
- 'This issue was auto-closed. All issues from new contributors are auto-closed by default.',
- '',
- `Maintainers review auto-closed issues daily and reopen worthwhile ones. Issues that do not meet the quality bar in [CONTRIBUTING.md](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/${defaultBranch}/CONTRIBUTING.md) will not be reopened or receive a reply.`,
- '',
- 'If a maintainer replies `lgtmi` on one of your issues, your future issues will stay open. If a maintainer replies `lgtm`, your future issues and PRs will stay open.',
- '',
- `See [CONTRIBUTING.md](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/${defaultBranch}/CONTRIBUTING.md).`,
- ].join('\n');
-
- await github.rest.issues.createComment({
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: context.issue.number,
- body: message,
- });
-
- await github.rest.issues.update({
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: context.issue.number,
- state: 'closed',
- });
diff --git a/pi-mono-reference/.github/workflows/openclaw-gate.yml b/pi-mono-reference/.github/workflows/openclaw-gate.yml
deleted file mode 100644
index 126d4ebf..00000000
--- a/pi-mono-reference/.github/workflows/openclaw-gate.yml
+++ /dev/null
@@ -1,122 +0,0 @@
-name: OpenClaw Gate
-
-on:
- issues:
- types: [opened]
- pull_request_target:
- types: [opened]
-
-jobs:
- check-contributor:
- runs-on: ubuntu-latest
- permissions:
- contents: read
- issues: write
- pull-requests: write
- steps:
- - name: Check contributor
- uses: actions/github-script@v7
- with:
- script: |
- const isPR = !!context.payload.pull_request;
- const author = isPR
- ? context.payload.pull_request.user.login
- : context.payload.issue.user.login;
- const number = isPR
- ? context.payload.pull_request.number
- : context.payload.issue.number;
- const defaultBranch = context.payload.repository.default_branch;
-
- if (author.endsWith('[bot]') || author === 'dependabot[bot]') {
- console.log(`Skipping bot: ${author}`);
- return;
- }
-
- const APPROVED_FILE = '.github/APPROVED_CONTRIBUTORS';
- const VALID_CAPABILITIES = new Set(['issue', 'pr']);
-
- // --- Check APPROVED_CONTRIBUTORS ---
- async function getTextFile(path) {
- const { data } = await github.rest.repos.getContent({
- owner: context.repo.owner,
- repo: context.repo.repo,
- path,
- ref: defaultBranch,
- });
- if (!('content' in data) || typeof data.content !== 'string') {
- throw new Error(`Expected file content for ${path}`);
- }
- return Buffer.from(data.content, 'base64').toString('utf8');
- }
-
- try {
- const content = await getTextFile(APPROVED_FILE);
- const approved = new Map();
- for (const rawLine of content.split('\n')) {
- const line = rawLine.trim();
- if (!line || line.startsWith('#')) continue;
-
- const parts = line.split(/\s+/);
- if (parts.length !== 2) continue;
-
- const [username, capability] = parts;
- const normalizedCapability = capability.toLowerCase();
- if (!VALID_CAPABILITIES.has(normalizedCapability)) continue;
-
- approved.set(username.toLowerCase(), normalizedCapability);
- }
-
- if (approved.has(author.toLowerCase())) {
- console.log(`${author} is in APPROVED_CONTRIBUTORS, passing`);
- return;
- }
- } catch (err) {
- console.log(`Could not read APPROVED_CONTRIBUTORS: ${err.message}`);
- }
-
- // --- Also pass collaborators with write+ access ---
- try {
- const { data: perm } = await github.rest.repos.getCollaboratorPermissionLevel({
- owner: context.repo.owner,
- repo: context.repo.repo,
- username: author,
- });
- if (['admin', 'maintain', 'write'].includes(perm.permission)) {
- console.log(`${author} is a collaborator (${perm.permission}), passing`);
- return;
- }
- } catch {
- // not a collaborator
- }
-
- // --- Check if user opened issues/PRs on openclaw/openclaw ---
- async function hasOpenClawActivity(username) {
- try {
- const { data } = await github.rest.search.issuesAndPullRequests({
- q: `repo:openclaw/openclaw author:${username}`,
- per_page: 1,
- });
- if (data.total_count > 0) {
- console.log(`${username} has opened ${data.total_count} issues/PRs on openclaw/openclaw`);
- return true;
- }
- } catch (err) {
- console.log(`Search failed: ${err.message}`);
- }
- return false;
- }
-
- const hasActivity = await hasOpenClawActivity(author);
- if (!hasActivity) {
- console.log(`${author} has no openclaw/openclaw activity, passing`);
- return;
- }
-
- // --- Add openclaw label ---
- console.log(`${author} has openclaw/openclaw activity, adding label`);
- await github.rest.issues.addLabels({
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: number,
- labels: ['possibly-openclaw-clanker'],
- });
diff --git a/pi-mono-reference/.github/workflows/pr-gate.yml b/pi-mono-reference/.github/workflows/pr-gate.yml
deleted file mode 100644
index a62b4afb..00000000
--- a/pi-mono-reference/.github/workflows/pr-gate.yml
+++ /dev/null
@@ -1,126 +0,0 @@
-name: PR Gate
-
-on:
- pull_request_target:
- types: [opened]
-
-jobs:
- check-contributor:
- runs-on: ubuntu-latest
- permissions:
- contents: read
- issues: write
- pull-requests: write
- steps:
- - name: Check if contributor is approved
- uses: actions/github-script@v7
- with:
- script: |
- const APPROVED_FILE = '.github/APPROVED_CONTRIBUTORS';
- const VALID_CAPABILITIES = new Set(['issue', 'pr']);
- const prAuthor = context.payload.pull_request.user.login;
- const defaultBranch = context.payload.repository.default_branch;
-
- if (prAuthor.endsWith('[bot]') || prAuthor === 'dependabot[bot]') {
- console.log(`Skipping bot: ${prAuthor}`);
- return;
- }
-
- async function getPermission(username) {
- try {
- const { data: permissionLevel } = await github.rest.repos.getCollaboratorPermissionLevel({
- owner: context.repo.owner,
- repo: context.repo.repo,
- username,
- });
- return permissionLevel.permission;
- } catch {
- return null;
- }
- }
-
- async function getTextFile(path) {
- const { data: fileContent } = await github.rest.repos.getContent({
- owner: context.repo.owner,
- repo: context.repo.repo,
- path,
- ref: defaultBranch,
- });
-
- if (!('content' in fileContent) || typeof fileContent.content !== 'string') {
- throw new Error(`Expected file content for ${path}`);
- }
-
- return Buffer.from(fileContent.content, 'base64').toString('utf8');
- }
-
- function parseApprovedUsers(content) {
- const users = new Map();
-
- for (const rawLine of content.split('\n')) {
- const line = rawLine.trim();
- if (!line || line.startsWith('#')) continue;
-
- const parts = line.split(/\s+/);
- if (parts.length !== 2) {
- console.log(`Skipping malformed line: ${rawLine}`);
- continue;
- }
-
- const [username, capability] = parts;
- const normalizedCapability = capability.toLowerCase();
- if (!VALID_CAPABILITIES.has(normalizedCapability)) {
- console.log(`Skipping line with invalid capability: ${rawLine}`);
- continue;
- }
-
- users.set(username.toLowerCase(), normalizedCapability);
- }
-
- return users;
- }
-
- async function closePullRequest(message) {
- await github.rest.issues.createComment({
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: context.payload.pull_request.number,
- body: message,
- });
-
- await github.rest.pulls.update({
- owner: context.repo.owner,
- repo: context.repo.repo,
- pull_number: context.payload.pull_request.number,
- state: 'closed',
- });
- }
-
- const permission = await getPermission(prAuthor);
- if (['admin', 'maintain', 'write'].includes(permission)) {
- console.log(`${prAuthor} is a collaborator with ${permission} access`);
- return;
- }
-
- const approvedContent = await getTextFile(APPROVED_FILE);
- const approvedUsers = parseApprovedUsers(approvedContent);
- const capability = approvedUsers.get(prAuthor.toLowerCase());
-
- if (capability === 'pr') {
- console.log(`${prAuthor} is approved for PRs`);
- return;
- }
-
- console.log(`${prAuthor} is not approved, closing PR`);
-
- const message = [
- 'This PR was auto-closed. Only contributors approved with `lgtm` can open PRs. Open an issue first.',
- '',
- `Maintainers review auto-closed issues daily. Issues that do not meet the quality bar in [CONTRIBUTING.md](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/${defaultBranch}/CONTRIBUTING.md) will not be reopened or receive a reply.`,
- '',
- 'If a maintainer replies `lgtmi`, your future issues will stay open. If a maintainer replies `lgtm`, your future issues and PRs will stay open.',
- '',
- `See [CONTRIBUTING.md](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/${defaultBranch}/CONTRIBUTING.md).`,
- ].join('\n');
-
- await closePullRequest(message);
diff --git a/pi-mono-reference/.gitignore b/pi-mono-reference/.gitignore
deleted file mode 100644
index e2e244ec..00000000
--- a/pi-mono-reference/.gitignore
+++ /dev/null
@@ -1,40 +0,0 @@
-node_modules/
-dist/
-*.log
-.DS_Store
-*.tsbuildinfo
-# packages/*/node_modules/
-packages/*/dist/
-packages/*/dist-chrome/
-packages/*/dist-firefox/
-*.cpuprofile
-
-# Environment
-.env
-
-# Editor files
-.vscode/
-.zed/
-.idea/
-*.swp
-*.swo
-*~
-
-# Package specific
-.npm/
-coverage/
-.nyc_output/
-.pi_config/
-tui-debug.log
-compaction-results/
-.opencode/
-syntax.jsonl
-out.jsonl
-pi-*.html
-out.html
-packages/coding-agent/binaries/
-todo.md
-plans/
-.pi/hf-sessions/
-.pi/hf-sessions-backup/
-collect.sh
diff --git a/pi-mono-reference/.husky/pre-commit b/pi-mono-reference/.husky/pre-commit
deleted file mode 100755
index 27d18fbc..00000000
--- a/pi-mono-reference/.husky/pre-commit
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/sh
-
-# Get list of staged files before running check
-STAGED_FILES=$(git diff --cached --name-only)
-
-# Run the check script (formatting, linting, and type checking)
-echo "Running formatting, linting, and type checking..."
-npm run check
-if [ $? -ne 0 ]; then
- echo "❌ Checks failed. Please fix the errors before committing."
- exit 1
-fi
-
-RUN_BROWSER_SMOKE=0
-for file in $STAGED_FILES; do
- case "$file" in
- packages/ai/*|packages/web-ui/*|package.json|package-lock.json)
- RUN_BROWSER_SMOKE=1
- break
- ;;
- esac
-done
-
-if [ $RUN_BROWSER_SMOKE -eq 1 ]; then
- echo "Running browser smoke check..."
- npm run check:browser-smoke
- if [ $? -ne 0 ]; then
- echo "❌ Browser smoke check failed."
- exit 1
- fi
-fi
-
-# Restage files that were previously staged and may have been modified by formatting
-for file in $STAGED_FILES; do
- if [ -f "$file" ]; then
- git add "$file"
- fi
-done
-
-echo "✅ All pre-commit checks passed!"
diff --git a/pi-mono-reference/.pi/extensions/prompt-url-widget.ts b/pi-mono-reference/.pi/extensions/prompt-url-widget.ts
deleted file mode 100644
index 20406e93..00000000
--- a/pi-mono-reference/.pi/extensions/prompt-url-widget.ts
+++ /dev/null
@@ -1,158 +0,0 @@
-import { DynamicBorder, type ExtensionAPI, type ExtensionContext } from "@mariozechner/pi-coding-agent";
-import { Container, Text } from "@mariozechner/pi-tui";
-
-const PR_PROMPT_PATTERN = /^\s*You are given one or more GitHub PR URLs:\s*(\S+)/im;
-const ISSUE_PROMPT_PATTERN = /^\s*Analyze GitHub issue\(s\):\s*(\S+)/im;
-
-type PromptMatch = {
- kind: "pr" | "issue";
- url: string;
-};
-
-type GhMetadata = {
- title?: string;
- author?: {
- login?: string;
- name?: string | null;
- };
-};
-
-function extractPromptMatch(prompt: string): PromptMatch | undefined {
- const prMatch = prompt.match(PR_PROMPT_PATTERN);
- if (prMatch?.[1]) {
- return { kind: "pr", url: prMatch[1].trim() };
- }
-
- const issueMatch = prompt.match(ISSUE_PROMPT_PATTERN);
- if (issueMatch?.[1]) {
- return { kind: "issue", url: issueMatch[1].trim() };
- }
-
- return undefined;
-}
-
-async function fetchGhMetadata(
- pi: ExtensionAPI,
- kind: PromptMatch["kind"],
- url: string,
-): Promise {
- const args =
- kind === "pr" ? ["pr", "view", url, "--json", "title,author"] : ["issue", "view", url, "--json", "title,author"];
-
- try {
- const result = await pi.exec("gh", args);
- if (result.code !== 0 || !result.stdout) return undefined;
- return JSON.parse(result.stdout) as GhMetadata;
- } catch {
- return undefined;
- }
-}
-
-function formatAuthor(author?: GhMetadata["author"]): string | undefined {
- if (!author) return undefined;
- const name = author.name?.trim();
- const login = author.login?.trim();
- if (name && login) return `${name} (@${login})`;
- if (login) return `@${login}`;
- if (name) return name;
- return undefined;
-}
-
-export default function promptUrlWidgetExtension(pi: ExtensionAPI) {
- const setWidget = (ctx: ExtensionContext, match: PromptMatch, title?: string, authorText?: string) => {
- ctx.ui.setWidget("prompt-url", (_tui, thm) => {
- const titleText = title ? thm.fg("accent", title) : thm.fg("accent", match.url);
- const authorLine = authorText ? thm.fg("muted", authorText) : undefined;
- const urlLine = thm.fg("dim", match.url);
-
- const lines = [titleText];
- if (authorLine) lines.push(authorLine);
- lines.push(urlLine);
-
- const container = new Container();
- container.addChild(new DynamicBorder((s: string) => thm.fg("muted", s)));
- container.addChild(new Text(lines.join("\n"), 1, 0));
- return container;
- });
- };
-
- const applySessionName = (ctx: ExtensionContext, match: PromptMatch, title?: string) => {
- const label = match.kind === "pr" ? "PR" : "Issue";
- const trimmedTitle = title?.trim();
- const fallbackName = `${label}: ${match.url}`;
- const desiredName = trimmedTitle ? `${label}: ${trimmedTitle} (${match.url})` : fallbackName;
- const currentName = pi.getSessionName()?.trim();
- if (!currentName) {
- pi.setSessionName(desiredName);
- return;
- }
- if (currentName === match.url || currentName === fallbackName) {
- pi.setSessionName(desiredName);
- }
- };
-
- pi.on("before_agent_start", async (event, ctx) => {
- if (!ctx.hasUI) return;
- const match = extractPromptMatch(event.prompt);
- if (!match) {
- return;
- }
-
- setWidget(ctx, match);
- applySessionName(ctx, match);
- void fetchGhMetadata(pi, match.kind, match.url).then((meta) => {
- const title = meta?.title?.trim();
- const authorText = formatAuthor(meta?.author);
- setWidget(ctx, match, title, authorText);
- applySessionName(ctx, match, title);
- });
- });
-
- pi.on("session_switch", async (_event, ctx) => {
- rebuildFromSession(ctx);
- });
-
- const getUserText = (content: string | { type: string; text?: string }[] | undefined): string => {
- if (!content) return "";
- if (typeof content === "string") return content;
- return (
- content
- .filter((block): block is { type: "text"; text: string } => block.type === "text")
- .map((block) => block.text)
- .join("\n") ?? ""
- );
- };
-
- const rebuildFromSession = (ctx: ExtensionContext) => {
- if (!ctx.hasUI) return;
-
- const entries = ctx.sessionManager.getEntries();
- const lastMatch = [...entries].reverse().find((entry) => {
- if (entry.type !== "message" || entry.message.role !== "user") return false;
- const text = getUserText(entry.message.content);
- return !!extractPromptMatch(text);
- });
-
- const content =
- lastMatch?.type === "message" && lastMatch.message.role === "user" ? lastMatch.message.content : undefined;
- const text = getUserText(content);
- const match = text ? extractPromptMatch(text) : undefined;
- if (!match) {
- ctx.ui.setWidget("prompt-url", undefined);
- return;
- }
-
- setWidget(ctx, match);
- applySessionName(ctx, match);
- void fetchGhMetadata(pi, match.kind, match.url).then((meta) => {
- const title = meta?.title?.trim();
- const authorText = formatAuthor(meta?.author);
- setWidget(ctx, match, title, authorText);
- applySessionName(ctx, match, title);
- });
- };
-
- pi.on("session_start", async (_event, ctx) => {
- rebuildFromSession(ctx);
- });
-}
diff --git a/pi-mono-reference/.pi/extensions/redraws.ts b/pi-mono-reference/.pi/extensions/redraws.ts
deleted file mode 100644
index 2db0867f..00000000
--- a/pi-mono-reference/.pi/extensions/redraws.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Redraws Extension
- *
- * Exposes /tui to show TUI redraw stats.
- */
-
-import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
-import { Text } from "@mariozechner/pi-tui";
-
-export default function (pi: ExtensionAPI) {
- pi.registerCommand("tui", {
- description: "Show TUI stats",
- handler: async (_args, ctx) => {
- if (!ctx.hasUI) return;
- let redraws = 0;
- await ctx.ui.custom((tui, _theme, _keybindings, done) => {
- redraws = tui.fullRedraws;
- done(undefined);
- return new Text("", 0, 0);
- });
- ctx.ui.notify(`TUI full redraws: ${redraws}`, "info");
- },
- });
-}
diff --git a/pi-mono-reference/.pi/extensions/tps.ts b/pi-mono-reference/.pi/extensions/tps.ts
deleted file mode 100644
index 16bea8f6..00000000
--- a/pi-mono-reference/.pi/extensions/tps.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import type { AssistantMessage } from "@mariozechner/pi-ai";
-import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
-
-function isAssistantMessage(message: unknown): message is AssistantMessage {
- if (!message || typeof message !== "object") return false;
- const role = (message as { role?: unknown }).role;
- return role === "assistant";
-}
-
-export default function (pi: ExtensionAPI) {
- let agentStartMs: number | null = null;
-
- pi.on("agent_start", () => {
- agentStartMs = Date.now();
- });
-
- pi.on("agent_end", (event, ctx) => {
- if (!ctx.hasUI) return;
- if (agentStartMs === null) return;
-
- const elapsedMs = Date.now() - agentStartMs;
- agentStartMs = null;
- if (elapsedMs <= 0) return;
-
- let input = 0;
- let output = 0;
- let cacheRead = 0;
- let cacheWrite = 0;
- let totalTokens = 0;
-
- for (const message of event.messages) {
- if (!isAssistantMessage(message)) continue;
- input += message.usage.input || 0;
- output += message.usage.output || 0;
- cacheRead += message.usage.cacheRead || 0;
- cacheWrite += message.usage.cacheWrite || 0;
- totalTokens += message.usage.totalTokens || 0;
- }
-
- if (output <= 0) return;
-
- const elapsedSeconds = elapsedMs / 1000;
- const tokensPerSecond = output / elapsedSeconds;
- const message = `TPS ${tokensPerSecond.toFixed(1)} tok/s. out ${output.toLocaleString()}, in ${input.toLocaleString()}, cache r/w ${cacheRead.toLocaleString()}/${cacheWrite.toLocaleString()}, total ${totalTokens.toLocaleString()}, ${elapsedSeconds.toFixed(1)}s`;
- ctx.ui.notify(message, "info");
- });
-}
diff --git a/pi-mono-reference/.pi/git/.gitignore b/pi-mono-reference/.pi/git/.gitignore
deleted file mode 100644
index d6b7ef32..00000000
--- a/pi-mono-reference/.pi/git/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!.gitignore
diff --git a/pi-mono-reference/.pi/npm/.gitignore b/pi-mono-reference/.pi/npm/.gitignore
deleted file mode 100644
index d6b7ef32..00000000
--- a/pi-mono-reference/.pi/npm/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!.gitignore
diff --git a/pi-mono-reference/LICENSE b/pi-mono-reference/LICENSE
deleted file mode 100644
index b0a8e9b8..00000000
--- a/pi-mono-reference/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2025 Mario Zechner
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
\ No newline at end of file
diff --git a/pi-mono-reference/biome.json b/pi-mono-reference/biome.json
deleted file mode 100644
index 147d081a..00000000
--- a/pi-mono-reference/biome.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- "$schema": "https://biomejs.dev/schemas/2.3.5/schema.json",
- "linter": {
- "enabled": true,
- "rules": {
- "recommended": true,
- "style": {
- "noNonNullAssertion": "off",
- "useConst": "error",
- "useNodejsImportProtocol": "off"
- },
- "suspicious": {
- "noExplicitAny": "off",
- "noControlCharactersInRegex": "off",
- "noEmptyInterface": "off"
- }
- }
- },
- "formatter": {
- "enabled": true,
- "formatWithErrors": false,
- "indentStyle": "tab",
- "indentWidth": 3,
- "lineWidth": 120
- },
- "files": {
- "includes": [
- "packages/*/src/**/*.ts",
- "packages/*/test/**/*.ts",
- "packages/coding-agent/examples/**/*.ts",
- "packages/web-ui/src/**/*.ts",
- "packages/web-ui/example/**/*.ts",
- "!**/node_modules/**/*",
- "!**/test-sessions.ts",
- "!**/models.generated.ts",
- "!packages/web-ui/src/app.css",
- "!packages/mom/data/**/*",
- "!!**/node_modules"
- ]
- }
-}
diff --git a/pi-mono-reference/package-lock.json b/pi-mono-reference/package-lock.json
deleted file mode 100644
index 16022ac2..00000000
--- a/pi-mono-reference/package-lock.json
+++ /dev/null
@@ -1,9009 +0,0 @@
-{
- "name": "pi-monorepo",
- "version": "0.0.3",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "pi-monorepo",
- "version": "0.0.3",
- "workspaces": [
- "packages/*",
- "packages/web-ui/example",
- "packages/coding-agent/examples/extensions/with-deps",
- "packages/coding-agent/examples/extensions/custom-provider-anthropic",
- "packages/coding-agent/examples/extensions/custom-provider-gitlab-duo",
- "packages/coding-agent/examples/extensions/custom-provider-qwen-cli"
- ],
- "dependencies": {
- "@mariozechner/jiti": "^2.6.5",
- "@mariozechner/pi-coding-agent": "^0.30.2",
- "get-east-asian-width": "^1.4.0"
- },
- "devDependencies": {
- "@biomejs/biome": "2.3.5",
- "@types/node": "^22.10.5",
- "@typescript/native-preview": "7.0.0-dev.20260120.1",
- "concurrently": "^9.2.1",
- "husky": "^9.1.7",
- "shx": "^0.4.0",
- "tsx": "^4.20.3",
- "typescript": "^5.9.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@anthropic-ai/sandbox-runtime": {
- "version": "0.0.16",
- "resolved": "https://registry.npmjs.org/@anthropic-ai/sandbox-runtime/-/sandbox-runtime-0.0.16.tgz",
- "integrity": "sha512-I2Us7dRvwCJkqcImrqP7NWrV5kHmKX7AumFDnznCjMd0hB5ZUzg9Is9SlxrMzHiUY2RndEaRLXCOJrUt8JnE4w==",
- "license": "Apache-2.0",
- "dependencies": {
- "@pondwader/socks5-server": "^1.0.10",
- "@types/lodash-es": "^4.17.12",
- "commander": "^12.1.0",
- "lodash-es": "^4.17.21",
- "shell-quote": "^1.8.3",
- "zod": "^3.24.1"
- },
- "bin": {
- "srt": "dist/cli.js"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@anthropic-ai/sandbox-runtime/node_modules/zod": {
- "version": "3.25.76",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
- "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/colinhacks"
- }
- },
- "node_modules/@anthropic-ai/sdk": {
- "version": "0.90.0",
- "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.90.0.tgz",
- "integrity": "sha512-MzZtPabJF1b0FTDl6Z6H5ljphPwACLGP13lu8MTiB8jXaW/YXlpOp+Po2cVou3MPM5+f5toyLnul9whKCy7fBg==",
- "license": "MIT",
- "dependencies": {
- "json-schema-to-ts": "^3.1.1"
- },
- "bin": {
- "anthropic-ai-sdk": "bin/cli"
- },
- "peerDependencies": {
- "zod": "^3.25.0 || ^4.0.0"
- },
- "peerDependenciesMeta": {
- "zod": {
- "optional": true
- }
- }
- },
- "node_modules/@aws-crypto/crc32": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz",
- "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/util": "^5.2.0",
- "@aws-sdk/types": "^3.222.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=16.0.0"
- }
- },
- "node_modules/@aws-crypto/sha256-browser": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
- "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/sha256-js": "^5.2.0",
- "@aws-crypto/supports-web-crypto": "^5.2.0",
- "@aws-crypto/util": "^5.2.0",
- "@aws-sdk/types": "^3.222.0",
- "@aws-sdk/util-locate-window": "^3.0.0",
- "@smithy/util-utf8": "^2.0.0",
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
- "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
- "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
- "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/sha256-js": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz",
- "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/util": "^5.2.0",
- "@aws-sdk/types": "^3.222.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=16.0.0"
- }
- },
- "node_modules/@aws-crypto/supports-web-crypto": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz",
- "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-crypto/util": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
- "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.222.0",
- "@smithy/util-utf8": "^2.0.0",
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
- "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
- "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
- "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-bedrock-runtime": {
- "version": "3.1030.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1030.0.tgz",
- "integrity": "sha512-5Lnyx6mQPsIdld5Xr9FJqu8Hi9RVY6SgE8Rysmn4r3lRY2vNohNEu+gCtdXRDkkv/PgK9OnbA0sUPFU9rBRMYA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/sha256-browser": "5.2.0",
- "@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "^3.973.27",
- "@aws-sdk/credential-provider-node": "^3.972.30",
- "@aws-sdk/eventstream-handler-node": "^3.972.13",
- "@aws-sdk/middleware-eventstream": "^3.972.9",
- "@aws-sdk/middleware-host-header": "^3.972.9",
- "@aws-sdk/middleware-logger": "^3.972.9",
- "@aws-sdk/middleware-recursion-detection": "^3.972.10",
- "@aws-sdk/middleware-user-agent": "^3.972.29",
- "@aws-sdk/middleware-websocket": "^3.972.15",
- "@aws-sdk/region-config-resolver": "^3.972.11",
- "@aws-sdk/token-providers": "3.1030.0",
- "@aws-sdk/types": "^3.973.7",
- "@aws-sdk/util-endpoints": "^3.996.6",
- "@aws-sdk/util-user-agent-browser": "^3.972.9",
- "@aws-sdk/util-user-agent-node": "^3.973.15",
- "@smithy/config-resolver": "^4.4.14",
- "@smithy/core": "^3.23.14",
- "@smithy/eventstream-serde-browser": "^4.2.13",
- "@smithy/eventstream-serde-config-resolver": "^4.3.13",
- "@smithy/eventstream-serde-node": "^4.2.13",
- "@smithy/fetch-http-handler": "^5.3.16",
- "@smithy/hash-node": "^4.2.13",
- "@smithy/invalid-dependency": "^4.2.13",
- "@smithy/middleware-content-length": "^4.2.13",
- "@smithy/middleware-endpoint": "^4.4.29",
- "@smithy/middleware-retry": "^4.5.0",
- "@smithy/middleware-serde": "^4.2.17",
- "@smithy/middleware-stack": "^4.2.13",
- "@smithy/node-config-provider": "^4.3.13",
- "@smithy/node-http-handler": "^4.5.2",
- "@smithy/protocol-http": "^5.3.13",
- "@smithy/smithy-client": "^4.12.9",
- "@smithy/types": "^4.14.0",
- "@smithy/url-parser": "^4.2.13",
- "@smithy/util-base64": "^4.3.2",
- "@smithy/util-body-length-browser": "^4.2.2",
- "@smithy/util-body-length-node": "^4.2.3",
- "@smithy/util-defaults-mode-browser": "^4.3.45",
- "@smithy/util-defaults-mode-node": "^4.2.49",
- "@smithy/util-endpoints": "^3.3.4",
- "@smithy/util-middleware": "^4.2.13",
- "@smithy/util-retry": "^4.3.0",
- "@smithy/util-stream": "^4.5.22",
- "@smithy/util-utf8": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/core": {
- "version": "3.973.27",
- "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.27.tgz",
- "integrity": "sha512-CUZ5m8hwMCH6OYI4Li/WgMfIEx10Q2PLI9Y3XOUTPGZJ53aZ0007jCv+X/ywsaERyKPdw5MRZWk877roQksQ4A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.973.7",
- "@aws-sdk/xml-builder": "^3.972.17",
- "@smithy/core": "^3.23.14",
- "@smithy/node-config-provider": "^4.3.13",
- "@smithy/property-provider": "^4.2.13",
- "@smithy/protocol-http": "^5.3.13",
- "@smithy/signature-v4": "^5.3.13",
- "@smithy/smithy-client": "^4.12.9",
- "@smithy/types": "^4.14.0",
- "@smithy/util-base64": "^4.3.2",
- "@smithy/util-middleware": "^4.2.13",
- "@smithy/util-utf8": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-env": {
- "version": "3.972.25",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.25.tgz",
- "integrity": "sha512-6QfI0wv4jpG5CrdO/AO0JfZ2ux+tKwJPrUwmvxXF50vI5KIypKVGNF6b4vlkYEnKumDTI1NX2zUBi8JoU5QU3A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "^3.973.27",
- "@aws-sdk/types": "^3.973.7",
- "@smithy/property-provider": "^4.2.13",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-http": {
- "version": "3.972.27",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.27.tgz",
- "integrity": "sha512-3V3Usj9Gs93h865DqN4M2NWJhC5kXU9BvZskfN3+69omuYlE3TZxOEcVQtBGLOloJB7BVfJKXVLqeNhOzHqSlQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "^3.973.27",
- "@aws-sdk/types": "^3.973.7",
- "@smithy/fetch-http-handler": "^5.3.16",
- "@smithy/node-http-handler": "^4.5.2",
- "@smithy/property-provider": "^4.2.13",
- "@smithy/protocol-http": "^5.3.13",
- "@smithy/smithy-client": "^4.12.9",
- "@smithy/types": "^4.14.0",
- "@smithy/util-stream": "^4.5.22",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-ini": {
- "version": "3.972.29",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.29.tgz",
- "integrity": "sha512-SiBuAnXecCbT/OpAf3vqyI/AVE3mTaYr9ShXLybxZiPLBiPCCOIWSGAtYYGQWMRvobBTiqOewaB+wcgMMZI2Aw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "^3.973.27",
- "@aws-sdk/credential-provider-env": "^3.972.25",
- "@aws-sdk/credential-provider-http": "^3.972.27",
- "@aws-sdk/credential-provider-login": "^3.972.29",
- "@aws-sdk/credential-provider-process": "^3.972.25",
- "@aws-sdk/credential-provider-sso": "^3.972.29",
- "@aws-sdk/credential-provider-web-identity": "^3.972.29",
- "@aws-sdk/nested-clients": "^3.996.19",
- "@aws-sdk/types": "^3.973.7",
- "@smithy/credential-provider-imds": "^4.2.13",
- "@smithy/property-provider": "^4.2.13",
- "@smithy/shared-ini-file-loader": "^4.4.8",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-login": {
- "version": "3.972.29",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.29.tgz",
- "integrity": "sha512-OGOslTbOlxXexKMqhxCEbBQbUIfuhGxU5UXw3Fm56ypXHvrXH4aTt/xb5Y884LOoteP1QST1lVZzHfcTnWhiPQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "^3.973.27",
- "@aws-sdk/nested-clients": "^3.996.19",
- "@aws-sdk/types": "^3.973.7",
- "@smithy/property-provider": "^4.2.13",
- "@smithy/protocol-http": "^5.3.13",
- "@smithy/shared-ini-file-loader": "^4.4.8",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-node": {
- "version": "3.972.30",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.30.tgz",
- "integrity": "sha512-FMnAnWxc8PG+ZrZ2OBKzY4luCUJhe9CG0B9YwYr4pzrYGLXBS2rl+UoUvjGbAwiptxRL6hyA3lFn03Bv1TLqTw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/credential-provider-env": "^3.972.25",
- "@aws-sdk/credential-provider-http": "^3.972.27",
- "@aws-sdk/credential-provider-ini": "^3.972.29",
- "@aws-sdk/credential-provider-process": "^3.972.25",
- "@aws-sdk/credential-provider-sso": "^3.972.29",
- "@aws-sdk/credential-provider-web-identity": "^3.972.29",
- "@aws-sdk/types": "^3.973.7",
- "@smithy/credential-provider-imds": "^4.2.13",
- "@smithy/property-provider": "^4.2.13",
- "@smithy/shared-ini-file-loader": "^4.4.8",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-process": {
- "version": "3.972.25",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.25.tgz",
- "integrity": "sha512-HR7ynNRdNhNsdVCOCegy1HsfsRzozCOPtD3RzzT1JouuaHobWyRfJzCBue/3jP7gECHt+kQyZUvwg/cYLWurNQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "^3.973.27",
- "@aws-sdk/types": "^3.973.7",
- "@smithy/property-provider": "^4.2.13",
- "@smithy/shared-ini-file-loader": "^4.4.8",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-sso": {
- "version": "3.972.29",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.29.tgz",
- "integrity": "sha512-HWv4SEq3jZDYPlwryZVef97+U8CxxRos5mK8sgGO1dQaFZpV5giZLzqGE5hkDmh2csYcBO2uf5XHjPTpZcJlig==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "^3.973.27",
- "@aws-sdk/nested-clients": "^3.996.19",
- "@aws-sdk/token-providers": "3.1026.0",
- "@aws-sdk/types": "^3.973.7",
- "@smithy/property-provider": "^4.2.13",
- "@smithy/shared-ini-file-loader": "^4.4.8",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers": {
- "version": "3.1026.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1026.0.tgz",
- "integrity": "sha512-Ieq/HiRrbEtrYP387Nes0XlR7H1pJiJOZKv+QyQzMYpvTiDs0VKy2ZB3E2Zf+aFovWmeE7lRE4lXyF7dYM6GgA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "^3.973.27",
- "@aws-sdk/nested-clients": "^3.996.19",
- "@aws-sdk/types": "^3.973.7",
- "@smithy/property-provider": "^4.2.13",
- "@smithy/shared-ini-file-loader": "^4.4.8",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-web-identity": {
- "version": "3.972.29",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.29.tgz",
- "integrity": "sha512-PdMBza1WEKEUPFEmMGCfnU2RYCz9MskU2e8JxjyUOsMKku7j9YaDKvbDi2dzC0ihFoM6ods2SbhfAAro+Gwlew==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "^3.973.27",
- "@aws-sdk/nested-clients": "^3.996.19",
- "@aws-sdk/types": "^3.973.7",
- "@smithy/property-provider": "^4.2.13",
- "@smithy/shared-ini-file-loader": "^4.4.8",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/eventstream-handler-node": {
- "version": "3.972.13",
- "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.972.13.tgz",
- "integrity": "sha512-2Pi1kD0MDkMAxDHqvpi/hKMs9hXUYbj2GLEjCwy+0jzfLChAsF50SUYnOeTI+RztA+Ic4pnLAdB03f1e8nggxQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.973.7",
- "@smithy/eventstream-codec": "^4.2.13",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-eventstream": {
- "version": "3.972.9",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.972.9.tgz",
- "integrity": "sha512-ypgOvpWxQTCnQyDHGxnTviqqANE7FIIzII7VczJnTPCJcJlu17hMQXnvE47aKSKsawVJAaaRsyOEbHQuLJF9ng==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.973.7",
- "@smithy/protocol-http": "^5.3.13",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-host-header": {
- "version": "3.972.9",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.9.tgz",
- "integrity": "sha512-je5vRdNw4SkuTnmRbFZLdye4sQ0faLt8kwka5wnnSU30q1mHO4X+idGEJOOE+Tn1ME7Oryn05xxkDvIb3UaLaQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.973.7",
- "@smithy/protocol-http": "^5.3.13",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-logger": {
- "version": "3.972.9",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.972.9.tgz",
- "integrity": "sha512-HsVgDrruhqI28RkaXALm8grJ7Agc1wF6Et0xh6pom8NdO2VdO/SD9U/tPwUjewwK/pVoka+EShBxyCvgsPCtog==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.973.7",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-recursion-detection": {
- "version": "3.972.10",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.10.tgz",
- "integrity": "sha512-RVQQbq5orQ/GHUnXvqEOj2HHPBJm+mM+ySwZKS5UaLBwra5ugRtiH09PLUoOZRl7a1YzaOzXSuGbn9iD5j60WQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.973.7",
- "@aws/lambda-invoke-store": "^0.2.2",
- "@smithy/protocol-http": "^5.3.13",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-user-agent": {
- "version": "3.972.29",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.29.tgz",
- "integrity": "sha512-f/sIRzuTfEjg6NsbMYvye2VsmnQoNgntntleQyx5uGacUYzszbfIlO3GcI6G6daWUmTm0IDZc11qMHWwF0o0mQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "^3.973.27",
- "@aws-sdk/types": "^3.973.7",
- "@aws-sdk/util-endpoints": "^3.996.6",
- "@smithy/core": "^3.23.14",
- "@smithy/protocol-http": "^5.3.13",
- "@smithy/types": "^4.14.0",
- "@smithy/util-retry": "^4.3.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-websocket": {
- "version": "3.972.15",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.15.tgz",
- "integrity": "sha512-hsZ35FORQsN5hwNdMD6zWmHCphbXkDxO6j+xwCUiuMb0O6gzS/PWgttQNl1OAn7h/uqZAMUG4yOS0wY/yhAieg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.973.7",
- "@aws-sdk/util-format-url": "^3.972.9",
- "@smithy/eventstream-codec": "^4.2.13",
- "@smithy/eventstream-serde-browser": "^4.2.13",
- "@smithy/fetch-http-handler": "^5.3.16",
- "@smithy/protocol-http": "^5.3.13",
- "@smithy/signature-v4": "^5.3.13",
- "@smithy/types": "^4.14.0",
- "@smithy/util-base64": "^4.3.2",
- "@smithy/util-hex-encoding": "^4.2.2",
- "@smithy/util-utf8": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">= 14.0.0"
- }
- },
- "node_modules/@aws-sdk/nested-clients": {
- "version": "3.996.19",
- "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.19.tgz",
- "integrity": "sha512-uFkmCDXvmQYLanlYdOFS0+MQWkrj9wPMt/ZCc/0J0fjPim6F5jBVBmEomvGY/j77ILW6GTPwN22Jc174Mhkw6Q==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/sha256-browser": "5.2.0",
- "@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "^3.973.27",
- "@aws-sdk/middleware-host-header": "^3.972.9",
- "@aws-sdk/middleware-logger": "^3.972.9",
- "@aws-sdk/middleware-recursion-detection": "^3.972.10",
- "@aws-sdk/middleware-user-agent": "^3.972.29",
- "@aws-sdk/region-config-resolver": "^3.972.11",
- "@aws-sdk/types": "^3.973.7",
- "@aws-sdk/util-endpoints": "^3.996.6",
- "@aws-sdk/util-user-agent-browser": "^3.972.9",
- "@aws-sdk/util-user-agent-node": "^3.973.15",
- "@smithy/config-resolver": "^4.4.14",
- "@smithy/core": "^3.23.14",
- "@smithy/fetch-http-handler": "^5.3.16",
- "@smithy/hash-node": "^4.2.13",
- "@smithy/invalid-dependency": "^4.2.13",
- "@smithy/middleware-content-length": "^4.2.13",
- "@smithy/middleware-endpoint": "^4.4.29",
- "@smithy/middleware-retry": "^4.5.0",
- "@smithy/middleware-serde": "^4.2.17",
- "@smithy/middleware-stack": "^4.2.13",
- "@smithy/node-config-provider": "^4.3.13",
- "@smithy/node-http-handler": "^4.5.2",
- "@smithy/protocol-http": "^5.3.13",
- "@smithy/smithy-client": "^4.12.9",
- "@smithy/types": "^4.14.0",
- "@smithy/url-parser": "^4.2.13",
- "@smithy/util-base64": "^4.3.2",
- "@smithy/util-body-length-browser": "^4.2.2",
- "@smithy/util-body-length-node": "^4.2.3",
- "@smithy/util-defaults-mode-browser": "^4.3.45",
- "@smithy/util-defaults-mode-node": "^4.2.49",
- "@smithy/util-endpoints": "^3.3.4",
- "@smithy/util-middleware": "^4.2.13",
- "@smithy/util-retry": "^4.3.0",
- "@smithy/util-utf8": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/region-config-resolver": {
- "version": "3.972.11",
- "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.11.tgz",
- "integrity": "sha512-6Q8B1dcx6BBqUTY1Mc/eROKA0FImEEY5VPSd6AGPEUf0ErjExz4snVqa9kNJSoVDV1rKaNf3qrWojgcKW+SdDg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.973.7",
- "@smithy/config-resolver": "^4.4.14",
- "@smithy/node-config-provider": "^4.3.13",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/token-providers": {
- "version": "3.1030.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1030.0.tgz",
- "integrity": "sha512-gUuCLTnEiUgpxHEnJSidxZZlQ+rQwc/mrijz6DxeMijTwS3/e3UfJvL8C1YDvcbt8MkkXj92h0MpYtfhR+EGeg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "^3.973.27",
- "@aws-sdk/nested-clients": "^3.996.19",
- "@aws-sdk/types": "^3.973.7",
- "@smithy/property-provider": "^4.2.13",
- "@smithy/shared-ini-file-loader": "^4.4.8",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/types": {
- "version": "3.973.7",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.7.tgz",
- "integrity": "sha512-reXRwoJ6CfChoqAsBszUYajAF8Z2LRE+CRcKocvFSMpIiLOtYU3aJ9trmn6VVPAzbbY5LXF+FfmUslbXk1SYFg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/util-endpoints": {
- "version": "3.996.6",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.996.6.tgz",
- "integrity": "sha512-2nUQ+2ih7CShuKHpGSIYvvAIOHy52dOZguYG36zptBukhw6iFwcvGfG0tes0oZFWQqEWvgZe9HLWaNlvXGdOrg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.973.7",
- "@smithy/types": "^4.14.0",
- "@smithy/url-parser": "^4.2.13",
- "@smithy/util-endpoints": "^3.3.4",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/util-format-url": {
- "version": "3.972.9",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.972.9.tgz",
- "integrity": "sha512-fNJXHrs0ZT7Wx0KGIqKv7zLxlDXt2vqjx9z6oKUQFmpE5o4xxnSryvVHfHpIifYHWKz94hFccIldJ0YSZjlCBw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.973.7",
- "@smithy/querystring-builder": "^4.2.13",
- "@smithy/types": "^4.14.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/util-locate-window": {
- "version": "3.965.5",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz",
- "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws-sdk/util-user-agent-browser": {
- "version": "3.972.9",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.9.tgz",
- "integrity": "sha512-sn/LMzTbGjYqCCF24390WxPd6hkpoSptiUn5DzVp4cD71yqw+yGEGm1YCxyEoPXyc8qciM8UzLJcZBFslxo5Uw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.973.7",
- "@smithy/types": "^4.14.0",
- "bowser": "^2.11.0",
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-sdk/util-user-agent-node": {
- "version": "3.973.15",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.15.tgz",
- "integrity": "sha512-fYn3s9PtKdgQkczGZCFMgkNEe8aq1JCVbnRqjqN9RSVW43xn2RV9xdcZ3z01a48Jpkuh/xCmBKJxdLOo4Ozg7w==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/middleware-user-agent": "^3.972.29",
- "@aws-sdk/types": "^3.973.7",
- "@smithy/node-config-provider": "^4.3.13",
- "@smithy/types": "^4.14.0",
- "@smithy/util-config-provider": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "aws-crt": ">=1.0.0"
- },
- "peerDependenciesMeta": {
- "aws-crt": {
- "optional": true
- }
- }
- },
- "node_modules/@aws-sdk/xml-builder": {
- "version": "3.972.17",
- "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.17.tgz",
- "integrity": "sha512-Ra7hjqAZf1OXRRMueB13qex7mFJRDK/pgCvdSFemXBT8KCGnQDPoKzHY1SjN+TjJVmnpSF14W5tJ1vDamFu+Gg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.0",
- "fast-xml-parser": "5.5.8",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@aws/lambda-invoke-store": {
- "version": "0.2.4",
- "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz",
- "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@babel/runtime": {
- "version": "7.29.2",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz",
- "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@biomejs/biome": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.3.5.tgz",
- "integrity": "sha512-HvLhNlIlBIbAV77VysRIBEwp55oM/QAjQEin74QQX9Xb259/XP/D5AGGnZMOyF1el4zcvlNYYR3AyTMUV3ILhg==",
- "dev": true,
- "license": "MIT OR Apache-2.0",
- "bin": {
- "biome": "bin/biome"
- },
- "engines": {
- "node": ">=14.21.3"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/biome"
- },
- "optionalDependencies": {
- "@biomejs/cli-darwin-arm64": "2.3.5",
- "@biomejs/cli-darwin-x64": "2.3.5",
- "@biomejs/cli-linux-arm64": "2.3.5",
- "@biomejs/cli-linux-arm64-musl": "2.3.5",
- "@biomejs/cli-linux-x64": "2.3.5",
- "@biomejs/cli-linux-x64-musl": "2.3.5",
- "@biomejs/cli-win32-arm64": "2.3.5",
- "@biomejs/cli-win32-x64": "2.3.5"
- }
- },
- "node_modules/@biomejs/cli-darwin-arm64": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.3.5.tgz",
- "integrity": "sha512-fLdTur8cJU33HxHUUsii3GLx/TR0BsfQx8FkeqIiW33cGMtUD56fAtrh+2Fx1uhiCsVZlFh6iLKUU3pniZREQw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT OR Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=14.21.3"
- }
- },
- "node_modules/@biomejs/cli-darwin-x64": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.3.5.tgz",
- "integrity": "sha512-qpT8XDqeUlzrOW8zb4k3tjhT7rmvVRumhi2657I2aGcY4B+Ft5fNwDdZGACzn8zj7/K1fdWjgwYE3i2mSZ+vOA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT OR Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=14.21.3"
- }
- },
- "node_modules/@biomejs/cli-linux-arm64": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.3.5.tgz",
- "integrity": "sha512-u/pybjTBPGBHB66ku4pK1gj+Dxgx7/+Z0jAriZISPX1ocTO8aHh8x8e7Kb1rB4Ms0nA/SzjtNOVJ4exVavQBCw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "libc": [
- "glibc"
- ],
- "license": "MIT OR Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=14.21.3"
- }
- },
- "node_modules/@biomejs/cli-linux-arm64-musl": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.3.5.tgz",
- "integrity": "sha512-eGUG7+hcLgGnMNl1KHVZUYxahYAhC462jF/wQolqu4qso2MSk32Q+QrpN7eN4jAHAg7FUMIo897muIhK4hXhqg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "libc": [
- "musl"
- ],
- "license": "MIT OR Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=14.21.3"
- }
- },
- "node_modules/@biomejs/cli-linux-x64": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.3.5.tgz",
- "integrity": "sha512-XrIVi9YAW6ye0CGQ+yax0gLfx+BFOtKaNX74n+xHWla6Cl6huUmcKNO7HPx7BiKnJUzrxXY1qYlm7xMvi08X4g==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "libc": [
- "glibc"
- ],
- "license": "MIT OR Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=14.21.3"
- }
- },
- "node_modules/@biomejs/cli-linux-x64-musl": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.3.5.tgz",
- "integrity": "sha512-awVuycTPpVTH/+WDVnEEYSf6nbCBHf/4wB3lquwT7puhNg8R4XvonWNZzUsfHZrCkjkLhFH/vCZK5jHatD9FEg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "libc": [
- "musl"
- ],
- "license": "MIT OR Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=14.21.3"
- }
- },
- "node_modules/@biomejs/cli-win32-arm64": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.3.5.tgz",
- "integrity": "sha512-DlBiMlBZZ9eIq4H7RimDSGsYcOtfOIfZOaI5CqsWiSlbTfqbPVfWtCf92wNzx8GNMbu1s7/g3ZZESr6+GwM/SA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT OR Apache-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=14.21.3"
- }
- },
- "node_modules/@biomejs/cli-win32-x64": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.3.5.tgz",
- "integrity": "sha512-nUmR8gb6yvrKhtRgzwo/gDimPwnO5a4sCydf8ZS2kHIJhEmSmk+STsusr1LHTuM//wXppBawvSQi2xFXJCdgKQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT OR Apache-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=14.21.3"
- }
- },
- "node_modules/@borewit/text-codec": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz",
- "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz",
- "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz",
- "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz",
- "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz",
- "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz",
- "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz",
- "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz",
- "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz",
- "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz",
- "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz",
- "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz",
- "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz",
- "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz",
- "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==",
- "cpu": [
- "mips64el"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz",
- "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz",
- "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz",
- "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz",
- "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz",
- "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz",
- "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz",
- "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz",
- "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openharmony-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz",
- "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz",
- "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz",
- "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz",
- "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz",
- "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@google/genai": {
- "version": "1.50.1",
- "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.50.1.tgz",
- "integrity": "sha512-YbkX7H9+1Pt8wOt7DDREy8XSoiL6fRDzZQRyaVBarFf8MR3zHGqVdvM4cLbDXqPhxqvegZShgfxb8kw9C7YhAQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "google-auth-library": "^10.3.0",
- "p-retry": "^4.6.2",
- "protobufjs": "^7.5.4",
- "ws": "^8.18.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@modelcontextprotocol/sdk": "^1.25.2"
- },
- "peerDependenciesMeta": {
- "@modelcontextprotocol/sdk": {
- "optional": true
- }
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.13",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
- "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/remapping": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
- "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
- "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.31",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
- "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@lit-labs/ssr-dom-shim": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.5.1.tgz",
- "integrity": "sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@lit/reactive-element": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.2.tgz",
- "integrity": "sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@lit-labs/ssr-dom-shim": "^1.5.0"
- }
- },
- "node_modules/@lmstudio/lms-isomorphic": {
- "version": "0.4.6",
- "resolved": "https://registry.npmjs.org/@lmstudio/lms-isomorphic/-/lms-isomorphic-0.4.6.tgz",
- "integrity": "sha512-v0LIjXKnDe3Ff3XZO5eQjlVxTjleUHXaom14MV7QU9bvwaoo3l5p71+xJ3mmSaqZq370CQ6pTKCn1Bb7Jf+VwQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "ws": "^8.16.0"
- }
- },
- "node_modules/@lmstudio/sdk": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@lmstudio/sdk/-/sdk-1.5.0.tgz",
- "integrity": "sha512-fdY12x4hb14PEjYijh7YeCqT1ZDY5Ok6VR4l4+E/dI+F6NW8oB+P83Sxed5vqE4XgTzbgyPuSR2ZbMNxxF+6jA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@lmstudio/lms-isomorphic": "^0.4.6",
- "chalk": "^4.1.2",
- "jsonschema": "^1.5.0",
- "zod": "^3.22.4",
- "zod-to-json-schema": "^3.22.5"
- }
- },
- "node_modules/@lmstudio/sdk/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/@lmstudio/sdk/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@lmstudio/sdk/node_modules/zod": {
- "version": "3.25.76",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
- "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/colinhacks"
- }
- },
- "node_modules/@mariozechner/clipboard": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@mariozechner/clipboard/-/clipboard-0.3.2.tgz",
- "integrity": "sha512-IHQpksNjo7EAtGuHFU+tbWDp5LarH3HU/8WiB9O70ZEoBPHOg0/6afwSLK0QyNMMmx4Bpi/zl6+DcBXe95nWYA==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 10"
- },
- "optionalDependencies": {
- "@mariozechner/clipboard-darwin-arm64": "0.3.2",
- "@mariozechner/clipboard-darwin-universal": "0.3.2",
- "@mariozechner/clipboard-darwin-x64": "0.3.2",
- "@mariozechner/clipboard-linux-arm64-gnu": "0.3.2",
- "@mariozechner/clipboard-linux-arm64-musl": "0.3.2",
- "@mariozechner/clipboard-linux-riscv64-gnu": "0.3.2",
- "@mariozechner/clipboard-linux-x64-gnu": "0.3.2",
- "@mariozechner/clipboard-linux-x64-musl": "0.3.2",
- "@mariozechner/clipboard-win32-arm64-msvc": "0.3.2",
- "@mariozechner/clipboard-win32-x64-msvc": "0.3.2"
- }
- },
- "node_modules/@mariozechner/clipboard-darwin-arm64": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-darwin-arm64/-/clipboard-darwin-arm64-0.3.2.tgz",
- "integrity": "sha512-uBf6K7Je1ihsgvmWxA8UCGCeI+nbRVRXoarZdLjl6slz94Zs1tNKFZqx7aCI5O1i3e0B6ja82zZ06BWrl0MCVw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@mariozechner/clipboard-darwin-universal": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-darwin-universal/-/clipboard-darwin-universal-0.3.2.tgz",
- "integrity": "sha512-mxSheKTW2U9LsBdXy0SdmdCAE5HqNS9QUmpNHLnfJ+SsbFKALjEZc5oRrVMXxGQSirDvYf5bjmRyT0QYYonnlg==",
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@mariozechner/clipboard-darwin-x64": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-darwin-x64/-/clipboard-darwin-x64-0.3.2.tgz",
- "integrity": "sha512-U1BcVEoidvwIp95+HJswSW+xr28EQiHR7rZjH6pn8Sja5yO4Yoe3yCN0Zm8Lo72BbSOK/fTSq0je7CJpaPCspg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@mariozechner/clipboard-linux-arm64-gnu": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-arm64-gnu/-/clipboard-linux-arm64-gnu-0.3.2.tgz",
- "integrity": "sha512-BsinwG3yWTIjdgNCxsFlip7LkfwPk+ruw/aFCXHUg/fb5XC/Ksp+YMQ7u0LUtiKzIv/7LMXgZInJQH6gxbAaqQ==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@mariozechner/clipboard-linux-arm64-musl": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-arm64-musl/-/clipboard-linux-arm64-musl-0.3.2.tgz",
- "integrity": "sha512-0/Gi5Xq2V6goXBop19ePoHvXsmJD9SzFlO3S+d6+T2b+BlPcpOu3Oa0wTjl+cZrLAAEzA86aPNBI+VVAFDFPKw==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@mariozechner/clipboard-linux-riscv64-gnu": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-riscv64-gnu/-/clipboard-linux-riscv64-gnu-0.3.2.tgz",
- "integrity": "sha512-2AFFiXB24qf0zOZsxI1GJGb9wQGlOJyN6UwoXqmKS3dpQi/l6ix30IzDDA4c4ZcCcx4D+9HLYXhC1w7Sov8pXA==",
- "cpu": [
- "riscv64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@mariozechner/clipboard-linux-x64-gnu": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-x64-gnu/-/clipboard-linux-x64-gnu-0.3.2.tgz",
- "integrity": "sha512-v6fVnsn7WMGg73Dab8QMwyFce7tzGfgEixKgzLP8f1GJqkJZi5zO4k4FOHzSgUufgLil63gnxvMpjWkgfeQN7A==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@mariozechner/clipboard-linux-x64-musl": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-x64-musl/-/clipboard-linux-x64-musl-0.3.2.tgz",
- "integrity": "sha512-xVUtnoMQ8v2JVyfJLKKXACA6avdnchdbBkTsZs8BgJQo29qwCp5NIHAUO8gbJ40iaEGToW5RlmVk2M9V0HsHEw==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@mariozechner/clipboard-win32-arm64-msvc": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-win32-arm64-msvc/-/clipboard-win32-arm64-msvc-0.3.2.tgz",
- "integrity": "sha512-AEgg95TNi8TGgak2wSXZkXKCvAUTjWoU1Pqb0ON7JHrX78p616XUFNTJohtIon3e0w6k0pYPZeCuqRCza/Tqeg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@mariozechner/clipboard-win32-x64-msvc": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-win32-x64-msvc/-/clipboard-win32-x64-msvc-0.3.2.tgz",
- "integrity": "sha512-tGRuYpZwDOD7HBrCpyRuhGnHHSCknELvqwKKUG4JSfSB7JIU7LKRh6zx6fMUOQd8uISK35TjFg5UcNih+vJhFA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@mariozechner/jiti": {
- "version": "2.6.5",
- "resolved": "https://registry.npmjs.org/@mariozechner/jiti/-/jiti-2.6.5.tgz",
- "integrity": "sha512-faGUlTcXka5l7rv0lP3K3vGW/ejRuOS24RR2aSFWREUQqzjgdsuWNo/IiPqL3kWRGt6Ahl2+qcDAwtdeWeuGUw==",
- "license": "MIT",
- "dependencies": {
- "std-env": "^3.10.0",
- "yoctocolors": "^2.1.2"
- },
- "bin": {
- "jiti": "lib/jiti-cli.mjs"
- }
- },
- "node_modules/@mariozechner/mini-lit": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/@mariozechner/mini-lit/-/mini-lit-0.2.1.tgz",
- "integrity": "sha512-u300euLgCsDDlb8o2Wbz+55eSJga5X2vB58s9XBuFIr2Bi3iI+GMR7t/NYo/O6Vr6obXShXgYjR3SRUJVgo+kQ==",
- "dependencies": {
- "@preact/signals-core": "^1.12.1",
- "class-variance-authority": "^0.7.1",
- "diff": "^8.0.2",
- "highlight.js": "^11.11.1",
- "html-parse-string": "^0.0.9",
- "katex": "^0.16.22",
- "lucide": "^0.544.0",
- "marked": "^16.3.0",
- "tailwind-merge": "^3.3.1",
- "tailwind-variants": "^3.1.1",
- "uhtml": "^5.0.9"
- },
- "peerDependencies": {
- "lit": "^3.3.1"
- }
- },
- "node_modules/@mariozechner/mini-lit/node_modules/highlight.js": {
- "version": "11.11.1",
- "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
- "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/@mariozechner/mini-lit/node_modules/marked": {
- "version": "16.4.2",
- "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz",
- "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==",
- "license": "MIT",
- "bin": {
- "marked": "bin/marked.js"
- },
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@mariozechner/pi": {
- "resolved": "packages/pods",
- "link": true
- },
- "node_modules/@mariozechner/pi-agent-core": {
- "resolved": "packages/agent",
- "link": true
- },
- "node_modules/@mariozechner/pi-ai": {
- "resolved": "packages/ai",
- "link": true
- },
- "node_modules/@mariozechner/pi-coding-agent": {
- "resolved": "packages/coding-agent",
- "link": true
- },
- "node_modules/@mariozechner/pi-mom": {
- "resolved": "packages/mom",
- "link": true
- },
- "node_modules/@mariozechner/pi-tui": {
- "resolved": "packages/tui",
- "link": true
- },
- "node_modules/@mariozechner/pi-web-ui": {
- "resolved": "packages/web-ui",
- "link": true
- },
- "node_modules/@mistralai/mistralai": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-1.14.1.tgz",
- "integrity": "sha512-IiLmmZFCCTReQgPAT33r7KQ1nYo5JPdvGkrkZqA8qQ2qB1GHgs5LoP5K2ICyrjnpw2n8oSxMM/VP+liiKcGNlQ==",
- "dependencies": {
- "ws": "^8.18.0",
- "zod": "^3.25.0 || ^4.0.0",
- "zod-to-json-schema": "^3.24.1"
- }
- },
- "node_modules/@napi-rs/canvas": {
- "version": "0.1.98",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.98.tgz",
- "integrity": "sha512-WDg3lxYMqlrg49sDVUlrHVfIEPsd5AjYDRuGD6Fu82K5agJx0UnWA+l5qd53GNLRiMN2WhOw7FLR+Er5QB/0SA==",
- "license": "MIT",
- "optional": true,
- "workspaces": [
- "e2e/*"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- },
- "optionalDependencies": {
- "@napi-rs/canvas-android-arm64": "0.1.98",
- "@napi-rs/canvas-darwin-arm64": "0.1.98",
- "@napi-rs/canvas-darwin-x64": "0.1.98",
- "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.98",
- "@napi-rs/canvas-linux-arm64-gnu": "0.1.98",
- "@napi-rs/canvas-linux-arm64-musl": "0.1.98",
- "@napi-rs/canvas-linux-riscv64-gnu": "0.1.98",
- "@napi-rs/canvas-linux-x64-gnu": "0.1.98",
- "@napi-rs/canvas-linux-x64-musl": "0.1.98",
- "@napi-rs/canvas-win32-arm64-msvc": "0.1.98",
- "@napi-rs/canvas-win32-x64-msvc": "0.1.98"
- }
- },
- "node_modules/@napi-rs/canvas-android-arm64": {
- "version": "0.1.98",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.98.tgz",
- "integrity": "sha512-O45Ifr0WZJUrSyg0QgB+67TiC0zYBRkBK+d43ZV4JtlwH3XttiVxLvlxEeULiH5y1MSELruspF0bjF6xXwJNPQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-darwin-arm64": {
- "version": "0.1.98",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.98.tgz",
- "integrity": "sha512-1b/nQhw6Isdv14JokUqat+i5wrAYD+ce3egiotedBGRUjVxYSj4s2uQCh2bFsyX5/9A5iTKVGsWoQhFft+j7Lg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-darwin-x64": {
- "version": "0.1.98",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.98.tgz",
- "integrity": "sha512-oefzfBM8mwnyYp6S+yNXwjCoLdkOalFG24mssHgvrJDS0FulOryyI35Q7GdJGmrzuL4oo1XW3ZTOcTBLdJ8Zkg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": {
- "version": "0.1.98",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.98.tgz",
- "integrity": "sha512-NDH5QXGmf8wlo5yhijCNGVFiJk7an5GvHwb2LHyfLQWY/6/S48i5+YtY6FPqPVVCUckNGudYOfXEJnb3/FiJGQ==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-linux-arm64-gnu": {
- "version": "0.1.98",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.98.tgz",
- "integrity": "sha512-KBLLM6tu1xs80LSAqdSLBKkgct0S23MCEf/aq8yxzg5imAceqp1ulKeELgWaYm27MgpUhm3Q7jmegX12FfphwA==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-linux-arm64-musl": {
- "version": "0.1.98",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.98.tgz",
- "integrity": "sha512-mfMNhjN5zDcJafqQ6sHj4Tc3YMTRxP5UA3MHtp/ssytBR/k6XO0x+1IIPtscnUKwha+ql1++WjDCGEgqu8OfWQ==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-linux-riscv64-gnu": {
- "version": "0.1.98",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.98.tgz",
- "integrity": "sha512-nfW8esrcaeuhrO3qGA5cwuyk4Ak6cn2eB0LtEYtqROIl+fz06CNGNCU0M95+Tspw5ZgfSbc98SaigT5r5B3LVQ==",
- "cpu": [
- "riscv64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-linux-x64-gnu": {
- "version": "0.1.98",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.98.tgz",
- "integrity": "sha512-318UT8j6Gro2bTjtutjQXHWp9SLTNw+WRS4wQ6XIRPAyzBGnGHg7x2ndD+oqkPrrSRIbYLA5WoBcCasaF7lSTQ==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-linux-x64-musl": {
- "version": "0.1.98",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.98.tgz",
- "integrity": "sha512-0vZhI74UxnA4VqlW4UvM0dFRrjE1RLEe/OXSBjzytGIxV+yOG4exlrhGoIpAQaIpQQQXMCdb1EmbvPC1k9vEqQ==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-win32-arm64-msvc": {
- "version": "0.1.98",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-0.1.98.tgz",
- "integrity": "sha512-oiC/IxgFEEVcZ7VH7JXXlmgsqRvmFb57PIQ4gQck35IKFZCNUvdNCcN3OeoLP7Hpf5160MWJf9jj/+E5V0bSvw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-win32-x64-msvc": {
- "version": "0.1.98",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.98.tgz",
- "integrity": "sha512-ZqstKAJBSyZetU8udUvBQWPlGN9buawFvjuo9mgCAxzbOoJAgXX39ihec/nn42T5Vb6/qyn45eTimx5ND9kMEw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@parcel/watcher": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
- "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "detect-libc": "^2.0.3",
- "is-glob": "^4.0.3",
- "node-addon-api": "^7.0.0",
- "picomatch": "^4.0.3"
- },
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- },
- "optionalDependencies": {
- "@parcel/watcher-android-arm64": "2.5.6",
- "@parcel/watcher-darwin-arm64": "2.5.6",
- "@parcel/watcher-darwin-x64": "2.5.6",
- "@parcel/watcher-freebsd-x64": "2.5.6",
- "@parcel/watcher-linux-arm-glibc": "2.5.6",
- "@parcel/watcher-linux-arm-musl": "2.5.6",
- "@parcel/watcher-linux-arm64-glibc": "2.5.6",
- "@parcel/watcher-linux-arm64-musl": "2.5.6",
- "@parcel/watcher-linux-x64-glibc": "2.5.6",
- "@parcel/watcher-linux-x64-musl": "2.5.6",
- "@parcel/watcher-win32-arm64": "2.5.6",
- "@parcel/watcher-win32-ia32": "2.5.6",
- "@parcel/watcher-win32-x64": "2.5.6"
- }
- },
- "node_modules/@parcel/watcher-android-arm64": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz",
- "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher-darwin-arm64": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz",
- "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher-darwin-x64": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz",
- "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher-freebsd-x64": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz",
- "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher-linux-arm-glibc": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz",
- "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher-linux-arm-musl": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz",
- "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher-linux-arm64-glibc": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz",
- "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher-linux-arm64-musl": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz",
- "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher-linux-x64-glibc": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz",
- "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher-linux-x64-musl": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz",
- "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher-win32-arm64": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz",
- "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher-win32-ia32": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz",
- "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher-win32-x64": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz",
- "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@parcel/watcher/node_modules/picomatch": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
- "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/@pondwader/socks5-server": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/@pondwader/socks5-server/-/socks5-server-1.0.10.tgz",
- "integrity": "sha512-bQY06wzzR8D2+vVCUoBsr5QS2U6UgPUQRmErNwtsuI6vLcyRKkafjkr3KxbtGFf9aBBIV2mcvlsKD1UYaIV+sg==",
- "license": "MIT"
- },
- "node_modules/@preact/signals-core": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.14.1.tgz",
- "integrity": "sha512-vxPpfXqrwUe9lpjqfYNjAF/0RF/eFGeLgdJzdmIIZjpOnTmGmAB4BjWone562mJGMRP4frU6iZ6ei3PDsu52Ng==",
- "license": "MIT",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/preact"
- }
- },
- "node_modules/@protobufjs/aspromise": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
- "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/base64": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
- "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/codegen": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
- "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/eventemitter": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
- "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/fetch": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
- "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@protobufjs/aspromise": "^1.1.1",
- "@protobufjs/inquire": "^1.1.0"
- }
- },
- "node_modules/@protobufjs/float": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
- "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/inquire": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
- "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/path": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
- "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/pool": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
- "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/utf8": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
- "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz",
- "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-android-arm64": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz",
- "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz",
- "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz",
- "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz",
- "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz",
- "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz",
- "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==",
- "cpu": [
- "arm"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz",
- "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==",
- "cpu": [
- "arm"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz",
- "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz",
- "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-loong64-gnu": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz",
- "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==",
- "cpu": [
- "loong64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-loong64-musl": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz",
- "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==",
- "cpu": [
- "loong64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-ppc64-gnu": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz",
- "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==",
- "cpu": [
- "ppc64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-ppc64-musl": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz",
- "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==",
- "cpu": [
- "ppc64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz",
- "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==",
- "cpu": [
- "riscv64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz",
- "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==",
- "cpu": [
- "riscv64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz",
- "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==",
- "cpu": [
- "s390x"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz",
- "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz",
- "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-openbsd-x64": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz",
- "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ]
- },
- "node_modules/@rollup/rollup-openharmony-arm64": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz",
- "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ]
- },
- "node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz",
- "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz",
- "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-gnu": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz",
- "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz",
- "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@silvia-odwyer/photon-node": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/@silvia-odwyer/photon-node/-/photon-node-0.3.4.tgz",
- "integrity": "sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA==",
- "license": "Apache-2.0"
- },
- "node_modules/@sinclair/typebox": {
- "version": "0.34.49",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.49.tgz",
- "integrity": "sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==",
- "license": "MIT"
- },
- "node_modules/@slack/logger": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@slack/logger/-/logger-4.0.1.tgz",
- "integrity": "sha512-6cmdPrV/RYfd2U0mDGiMK8S7OJqpCTm7enMLRR3edccsPX8j7zXTLnaEF4fhxxJJTAIOil6+qZrnUPTuaLvwrQ==",
- "license": "MIT",
- "dependencies": {
- "@types/node": ">=18"
- },
- "engines": {
- "node": ">= 18",
- "npm": ">= 8.6.0"
- }
- },
- "node_modules/@slack/socket-mode": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/@slack/socket-mode/-/socket-mode-2.0.6.tgz",
- "integrity": "sha512-Aj5RO3MoYVJ+b2tUjHUXuA3tiIaCUMOf1Ss5tPiz29XYVUi6qNac2A8ulcU1pUPERpXVHTmT1XW6HzQIO74daQ==",
- "license": "MIT",
- "dependencies": {
- "@slack/logger": "^4.0.1",
- "@slack/web-api": "^7.15.0",
- "@types/node": ">=18",
- "@types/ws": "^8",
- "eventemitter3": "^5",
- "ws": "^8"
- },
- "engines": {
- "node": ">= 18",
- "npm": ">= 8.6.0"
- }
- },
- "node_modules/@slack/types": {
- "version": "2.20.1",
- "resolved": "https://registry.npmjs.org/@slack/types/-/types-2.20.1.tgz",
- "integrity": "sha512-eWX2mdt1ktpn8+40iiMc404uGrih+2fxiky3zBcPjtXKj6HLRdYlmhrPkJi7JTJm8dpXR6BWVWEDBXtaWMKD6A==",
- "license": "MIT",
- "engines": {
- "node": ">= 12.13.0",
- "npm": ">= 6.12.0"
- }
- },
- "node_modules/@slack/web-api": {
- "version": "7.15.1",
- "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-7.15.1.tgz",
- "integrity": "sha512-y+TAF7TszcmFzbVtBkFqAdBwKSoD+8shkNxhp4WIfFwXmCKdFje9WD6evROApPa2FTy1v1uc9yBaJs3609PPgg==",
- "license": "MIT",
- "dependencies": {
- "@slack/logger": "^4.0.1",
- "@slack/types": "^2.20.1",
- "@types/node": ">=18",
- "@types/retry": "0.12.0",
- "axios": "^1.15.0",
- "eventemitter3": "^5.0.1",
- "form-data": "^4.0.4",
- "is-electron": "2.2.2",
- "is-stream": "^2",
- "p-queue": "^6",
- "p-retry": "^4",
- "retry": "^0.13.1"
- },
- "engines": {
- "node": ">= 18",
- "npm": ">= 8.6.0"
- }
- },
- "node_modules/@smithy/config-resolver": {
- "version": "4.4.16",
- "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.16.tgz",
- "integrity": "sha512-GFlGPNLZKrGfqWpqVb31z7hvYCA9ZscfX1buYnvvMGcRYsQQnhH+4uN6mWWflcD5jB4OXP/LBrdpukEdjl41tg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/node-config-provider": "^4.3.14",
- "@smithy/types": "^4.14.1",
- "@smithy/util-config-provider": "^4.2.2",
- "@smithy/util-endpoints": "^3.4.1",
- "@smithy/util-middleware": "^4.2.14",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/core": {
- "version": "3.23.15",
- "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.23.15.tgz",
- "integrity": "sha512-E7GVCgsQttzfujEZb6Qep005wWf4xiL4x06apFEtzQMWYBPggZh/0cnOxPficw5cuK/YjjkehKoIN4YUaSh0UQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/protocol-http": "^5.3.14",
- "@smithy/types": "^4.14.1",
- "@smithy/url-parser": "^4.2.14",
- "@smithy/util-base64": "^4.3.2",
- "@smithy/util-body-length-browser": "^4.2.2",
- "@smithy/util-middleware": "^4.2.14",
- "@smithy/util-stream": "^4.5.23",
- "@smithy/util-utf8": "^4.2.2",
- "@smithy/uuid": "^1.1.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/credential-provider-imds": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.14.tgz",
- "integrity": "sha512-Au28zBN48ZAoXdooGUHemuVBrkE+Ie6RPmGNIAJsFqj33Vhb6xAgRifUydZ2aY+M+KaMAETAlKk5NC5h1G7wpg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/node-config-provider": "^4.3.14",
- "@smithy/property-provider": "^4.2.14",
- "@smithy/types": "^4.14.1",
- "@smithy/url-parser": "^4.2.14",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/eventstream-codec": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.14.tgz",
- "integrity": "sha512-erZq0nOIpzfeZdCyzZjdJb4nVSKLUmSkaQUVkRGQTXs30gyUGeKnrYEg+Xe1W5gE3aReS7IgsvANwVPxSzY6Pw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/crc32": "5.2.0",
- "@smithy/types": "^4.14.1",
- "@smithy/util-hex-encoding": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/eventstream-serde-browser": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.14.tgz",
- "integrity": "sha512-8IelTCtTctWRbb+0Dcy+C0aICh1qa0qWXqgjcXDmMuCvPJRnv26hiDZoAau2ILOniki65mCPKqOQs/BaWvO4CQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/eventstream-serde-universal": "^4.2.14",
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/eventstream-serde-config-resolver": {
- "version": "4.3.14",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.14.tgz",
- "integrity": "sha512-sqHiHpYRYo3FJlaIxD1J8PhbcmJAm7IuM16mVnwSkCToD7g00IBZzKuiLNMGmftULmEUX6/UAz8/NN5uMP8bVA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/eventstream-serde-node": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.14.tgz",
- "integrity": "sha512-Ht/8BuGlKfFTy0H3+8eEu0vdpwGztCnaLLXtpXNdQqiR7Hj4vFScU3T436vRAjATglOIPjJXronY+1WxxNLSiw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/eventstream-serde-universal": "^4.2.14",
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/eventstream-serde-universal": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.14.tgz",
- "integrity": "sha512-lWyt4T2XQZUZgK3tQ3Wn0w3XBvZsK/vjTuJl6bXbnGZBHH0ZUSONTYiK9TgjTTzU54xQr3DRFwpjmhp0oLm3gg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/eventstream-codec": "^4.2.14",
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/fetch-http-handler": {
- "version": "5.3.17",
- "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.17.tgz",
- "integrity": "sha512-bXOvQzaSm6MnmLaWA1elgfQcAtN4UP3vXqV97bHuoOrHQOJiLT3ds6o9eo5bqd0TJfRFpzdGnDQdW3FACiAVdw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/protocol-http": "^5.3.14",
- "@smithy/querystring-builder": "^4.2.14",
- "@smithy/types": "^4.14.1",
- "@smithy/util-base64": "^4.3.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/hash-node": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.14.tgz",
- "integrity": "sha512-8ZBDY2DD4wr+GGjTpPtiglEsqr0lUP+KHqgZcWczFf6qeZ/YRjMIOoQWVQlmwu7EtxKTd8YXD8lblmYcpBIA1g==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.1",
- "@smithy/util-buffer-from": "^4.2.2",
- "@smithy/util-utf8": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/invalid-dependency": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.14.tgz",
- "integrity": "sha512-c21qJiTSb25xvvOp+H2TNZzPCngrvl5vIPqPB8zQ/DmJF4QWXO19x1dWfMJZ6wZuuWUPPm0gV8C0cU3+ifcWuw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/is-array-buffer": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.2.tgz",
- "integrity": "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-content-length": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.14.tgz",
- "integrity": "sha512-xhHq7fX4/3lv5NHxLUk3OeEvl0xZ+Ek3qIbWaCL4f9JwgDZEclPBElljaZCAItdGPQl/kSM4LPMOpy1MYgprpw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/protocol-http": "^5.3.14",
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-endpoint": {
- "version": "4.4.30",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.30.tgz",
- "integrity": "sha512-qS2XqhKeXmdZ4nEQ4cOxIczSP/Y91wPAHYuRwmWDCh975B7/57uxsm5d6sisnUThn2u2FwzMdJNM7AbO1YPsPg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/core": "^3.23.15",
- "@smithy/middleware-serde": "^4.2.18",
- "@smithy/node-config-provider": "^4.3.14",
- "@smithy/shared-ini-file-loader": "^4.4.9",
- "@smithy/types": "^4.14.1",
- "@smithy/url-parser": "^4.2.14",
- "@smithy/util-middleware": "^4.2.14",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-retry": {
- "version": "4.5.3",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.5.3.tgz",
- "integrity": "sha512-TE8dJNi6JuxzGSxMCVd3i9IEWDndCl3bmluLsBNDWok8olgj65OfkndMhl9SZ7m14c+C5SQn/PcUmrDl57rSFw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/core": "^3.23.15",
- "@smithy/node-config-provider": "^4.3.14",
- "@smithy/protocol-http": "^5.3.14",
- "@smithy/service-error-classification": "^4.2.14",
- "@smithy/smithy-client": "^4.12.11",
- "@smithy/types": "^4.14.1",
- "@smithy/util-middleware": "^4.2.14",
- "@smithy/util-retry": "^4.3.2",
- "@smithy/uuid": "^1.1.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-serde": {
- "version": "4.2.18",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.18.tgz",
- "integrity": "sha512-M6CSgnp3v4tYz9ynj2JHbA60woBZcGqEwNjTKjBsNHPV26R1ZX52+0wW8WsZU18q45jD0tw2wL22S17Ze9LpEw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/core": "^3.23.15",
- "@smithy/protocol-http": "^5.3.14",
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-stack": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.14.tgz",
- "integrity": "sha512-2dvkUKLuFdKsCRmOE4Mn63co0Djtsm+JMh0bYZQupN1pJwMeE8FmQmRLLzzEMN0dnNi7CDCYYH8F0EVwWiPBeA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/node-config-provider": {
- "version": "4.3.14",
- "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.14.tgz",
- "integrity": "sha512-S+gFjyo/weSVL0P1b9Ts8C/CwIfNCgUPikk3sl6QVsfE/uUuO+QsF+NsE/JkpvWqqyz1wg7HFdiaZuj5CoBMRg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/property-provider": "^4.2.14",
- "@smithy/shared-ini-file-loader": "^4.4.9",
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/node-http-handler": {
- "version": "4.5.3",
- "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.5.3.tgz",
- "integrity": "sha512-lc5jFL++x17sPhIwMWJ3YOnqmSjw/2Po6VLDlUIXvxVWRuJwRXnJ4jOBBLB0cfI5BB5ehIl02Fxr1PDvk/kxDw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/protocol-http": "^5.3.14",
- "@smithy/querystring-builder": "^4.2.14",
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/property-provider": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.14.tgz",
- "integrity": "sha512-WuM31CgfsnQ/10i7NYr0PyxqknD72Y5uMfUMVSniPjbEPceiTErb4eIqJQ+pdxNEAUEWrewrGjIRjVbVHsxZiQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/protocol-http": {
- "version": "5.3.14",
- "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.14.tgz",
- "integrity": "sha512-dN5F8kHx8RNU0r+pCwNmFZyz6ChjMkzShy/zup6MtkRmmix4vZzJdW+di7x//b1LiynIev88FM18ie+wwPcQtQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/querystring-builder": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.14.tgz",
- "integrity": "sha512-XYA5Z0IqTeF+5XDdh4BBmSA0HvbgVZIyv4cmOoUheDNR57K1HgBp9ukUMx3Cr3XpDHHpLBnexPE3LAtDsZkj2A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.1",
- "@smithy/util-uri-escape": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/querystring-parser": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.14.tgz",
- "integrity": "sha512-hr+YyqBD23GVvRxGGrcc/oOeNlK3PzT5Fu4dzrDXxzS1LpFiuL2PQQqKPs87M79aW7ziMs+nvB3qdw77SqE7Lw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/service-error-classification": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.14.tgz",
- "integrity": "sha512-vVimoUnGxlx4eLLQbZImdOZFOe+Zh+5ACntv8VxZuGP72LdWu5GV3oEmCahSEReBgRJoWjypFkrehSj7BWx1HQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.1"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/shared-ini-file-loader": {
- "version": "4.4.9",
- "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.9.tgz",
- "integrity": "sha512-495/V2I15SHgedSJoDPD23JuSfKAp726ZI1V0wtjB07Wh7q/0tri/0e0DLefZCHgxZonrGKt/OCTpAtP1wE1kQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/signature-v4": {
- "version": "5.3.14",
- "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.14.tgz",
- "integrity": "sha512-1D9Y/nmlVjCeSivCbhZ7hgEpmHyY1h0GvpSZt3l0xcD9JjmjVC1CHOozS6+Gh+/ldMH8JuJ6cujObQqfayAVFA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^4.2.2",
- "@smithy/protocol-http": "^5.3.14",
- "@smithy/types": "^4.14.1",
- "@smithy/util-hex-encoding": "^4.2.2",
- "@smithy/util-middleware": "^4.2.14",
- "@smithy/util-uri-escape": "^4.2.2",
- "@smithy/util-utf8": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/smithy-client": {
- "version": "4.12.11",
- "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.12.11.tgz",
- "integrity": "sha512-wzz/Wa1CH/Tlhxh0s4DQPEcXSxSVfJ59AZcUh9Gu0c6JTlKuwGf4o/3P2TExv0VbtPFt8odIBG+eQGK2+vTECg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/core": "^3.23.15",
- "@smithy/middleware-endpoint": "^4.4.30",
- "@smithy/middleware-stack": "^4.2.14",
- "@smithy/protocol-http": "^5.3.14",
- "@smithy/types": "^4.14.1",
- "@smithy/util-stream": "^4.5.23",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/types": {
- "version": "4.14.1",
- "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.14.1.tgz",
- "integrity": "sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/url-parser": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.14.tgz",
- "integrity": "sha512-p06BiBigJ8bTA3MgnOfCtDUWnAMY0YfedO/GRpmc7p+wg3KW8vbXy1xwSu5ASy0wV7rRYtlfZOIKH4XqfhjSQQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/querystring-parser": "^4.2.14",
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-base64": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.2.tgz",
- "integrity": "sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^4.2.2",
- "@smithy/util-utf8": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-body-length-browser": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.2.tgz",
- "integrity": "sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-body-length-node": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.3.tgz",
- "integrity": "sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-buffer-from": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.2.tgz",
- "integrity": "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-config-provider": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.2.tgz",
- "integrity": "sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-defaults-mode-browser": {
- "version": "4.3.47",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.47.tgz",
- "integrity": "sha512-zlIuXai3/SHjQUQ8y3g/woLvrH573SK2wNjcDaHu5e9VOcC0JwM1MI0Sq0GZJyN3BwSUneIhpjZ18nsiz5AtQw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/property-provider": "^4.2.14",
- "@smithy/smithy-client": "^4.12.11",
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-defaults-mode-node": {
- "version": "4.2.52",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.52.tgz",
- "integrity": "sha512-cQBz8g68Vnw1W2meXlkb3D/hXJU+Taiyj9P8qLJtjREEV9/Td65xi4A/H1sRQ8EIgX5qbZbvdYPKygKLholZ3w==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/config-resolver": "^4.4.16",
- "@smithy/credential-provider-imds": "^4.2.14",
- "@smithy/node-config-provider": "^4.3.14",
- "@smithy/property-provider": "^4.2.14",
- "@smithy/smithy-client": "^4.12.11",
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-endpoints": {
- "version": "3.4.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.4.1.tgz",
- "integrity": "sha512-wMxNDZJrgS5mQV9oxCs4TWl5767VMgOfqfZ3JHyCkMtGC2ykW9iPqMvFur695Otcc5yxLG8OKO/80tsQBxrhXg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/node-config-provider": "^4.3.14",
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-hex-encoding": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.2.tgz",
- "integrity": "sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-middleware": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.14.tgz",
- "integrity": "sha512-1Su2vj9RYNDEv/V+2E+jXkkwGsgR7dc4sfHn9Z7ruzQHJIEni9zzw5CauvRXlFJfmgcqYP8fWa0dkh2Q2YaQyw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-retry": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.3.2.tgz",
- "integrity": "sha512-2+KTsJEwTi63NUv4uR9IQ+IFT1yu6Rf6JuoBK2WKaaJ/TRvOiOVGcXAsEqX/TQN2thR9yII21kPUJq1UV/WI2A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/service-error-classification": "^4.2.14",
- "@smithy/types": "^4.14.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-stream": {
- "version": "4.5.23",
- "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.23.tgz",
- "integrity": "sha512-N6on1+ngJ3RznZOnDWNveIwnTSlqxNnXuNAh7ez889ZZaRdXoNRTXKgmYOLe6dB0gCmAVtuRScE1hymQFl4hpg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/fetch-http-handler": "^5.3.17",
- "@smithy/node-http-handler": "^4.5.3",
- "@smithy/types": "^4.14.1",
- "@smithy/util-base64": "^4.3.2",
- "@smithy/util-buffer-from": "^4.2.2",
- "@smithy/util-hex-encoding": "^4.2.2",
- "@smithy/util-utf8": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-uri-escape": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.2.tgz",
- "integrity": "sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-utf8": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.2.tgz",
- "integrity": "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^4.2.2",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/uuid": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.2.tgz",
- "integrity": "sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@tailwindcss/cli": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/cli/-/cli-4.2.2.tgz",
- "integrity": "sha512-iJS+8kAFZ8HPqnh0O5DHCLjo4L6dD97DBQEkrhfSO4V96xeefUus2jqsBs1dUMt3OU9Ks4qIkiY0mpL5UW+4LQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@parcel/watcher": "^2.5.1",
- "@tailwindcss/node": "4.2.2",
- "@tailwindcss/oxide": "4.2.2",
- "enhanced-resolve": "^5.19.0",
- "mri": "^1.2.0",
- "picocolors": "^1.1.1",
- "tailwindcss": "4.2.2"
- },
- "bin": {
- "tailwindcss": "dist/index.mjs"
- }
- },
- "node_modules/@tailwindcss/node": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.2.tgz",
- "integrity": "sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/remapping": "^2.3.5",
- "enhanced-resolve": "^5.19.0",
- "jiti": "^2.6.1",
- "lightningcss": "1.32.0",
- "magic-string": "^0.30.21",
- "source-map-js": "^1.2.1",
- "tailwindcss": "4.2.2"
- }
- },
- "node_modules/@tailwindcss/oxide": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.2.tgz",
- "integrity": "sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 20"
- },
- "optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.2.2",
- "@tailwindcss/oxide-darwin-arm64": "4.2.2",
- "@tailwindcss/oxide-darwin-x64": "4.2.2",
- "@tailwindcss/oxide-freebsd-x64": "4.2.2",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.2",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.2.2",
- "@tailwindcss/oxide-linux-arm64-musl": "4.2.2",
- "@tailwindcss/oxide-linux-x64-gnu": "4.2.2",
- "@tailwindcss/oxide-linux-x64-musl": "4.2.2",
- "@tailwindcss/oxide-wasm32-wasi": "4.2.2",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.2.2",
- "@tailwindcss/oxide-win32-x64-msvc": "4.2.2"
- }
- },
- "node_modules/@tailwindcss/oxide-android-arm64": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.2.tgz",
- "integrity": "sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.2.tgz",
- "integrity": "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-x64": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.2.tgz",
- "integrity": "sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-freebsd-x64": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.2.tgz",
- "integrity": "sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.2.tgz",
- "integrity": "sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.2.tgz",
- "integrity": "sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.2.tgz",
- "integrity": "sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.2.tgz",
- "integrity": "sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-musl": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.2.tgz",
- "integrity": "sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-wasm32-wasi": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.2.tgz",
- "integrity": "sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==",
- "bundleDependencies": [
- "@napi-rs/wasm-runtime",
- "@emnapi/core",
- "@emnapi/runtime",
- "@tybys/wasm-util",
- "@emnapi/wasi-threads",
- "tslib"
- ],
- "cpu": [
- "wasm32"
- ],
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "^1.8.1",
- "@emnapi/runtime": "^1.8.1",
- "@emnapi/wasi-threads": "^1.1.0",
- "@napi-rs/wasm-runtime": "^1.1.1",
- "@tybys/wasm-util": "^0.10.1",
- "tslib": "^2.8.1"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.2.tgz",
- "integrity": "sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.2.tgz",
- "integrity": "sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/vite": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.2.tgz",
- "integrity": "sha512-mEiF5HO1QqCLXoNEfXVA1Tzo+cYsrqV7w9Juj2wdUFyW07JRenqMG225MvPwr3ZD9N1bFQj46X7r33iHxLUW0w==",
- "license": "MIT",
- "dependencies": {
- "@tailwindcss/node": "4.2.2",
- "@tailwindcss/oxide": "4.2.2",
- "tailwindcss": "4.2.2"
- },
- "peerDependencies": {
- "vite": "^5.2.0 || ^6 || ^7 || ^8"
- }
- },
- "node_modules/@tokenizer/inflate": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz",
- "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.3",
- "token-types": "^6.1.1"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/@tokenizer/token": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
- "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
- "license": "MIT"
- },
- "node_modules/@tootallnate/quickjs-emscripten": {
- "version": "0.23.0",
- "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
- "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
- "license": "MIT"
- },
- "node_modules/@types/chai": {
- "version": "5.2.3",
- "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
- "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/deep-eql": "*",
- "assertion-error": "^2.0.1"
- }
- },
- "node_modules/@types/deep-eql": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
- "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/diff": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/@types/diff/-/diff-7.0.2.tgz",
- "integrity": "sha512-JSWRMozjFKsGlEjiiKajUjIJVKuKdE3oVy2DNtK+fUo8q82nhFZ2CPQwicAIkXrofahDXrWJ7mjelvZphMS98Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/estree": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
- "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
- "license": "MIT"
- },
- "node_modules/@types/hosted-git-info": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/@types/hosted-git-info/-/hosted-git-info-3.0.5.tgz",
- "integrity": "sha512-Dmngh7U003cOHPhKGyA7LWqrnvcTyILNgNPmNCxlx7j8MIi54iBliiT8XqVLIQ3GchoOjVAyBzNJVyuaJjqokg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/lodash": {
- "version": "4.17.24",
- "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz",
- "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==",
- "license": "MIT"
- },
- "node_modules/@types/lodash-es": {
- "version": "4.17.12",
- "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz",
- "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
- "license": "MIT",
- "dependencies": {
- "@types/lodash": "*"
- }
- },
- "node_modules/@types/mime-types": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz",
- "integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==",
- "license": "MIT"
- },
- "node_modules/@types/ms": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
- "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/node": {
- "version": "22.19.17",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz",
- "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==",
- "license": "MIT",
- "dependencies": {
- "undici-types": "~6.21.0"
- }
- },
- "node_modules/@types/proper-lockfile": {
- "version": "4.1.4",
- "resolved": "https://registry.npmjs.org/@types/proper-lockfile/-/proper-lockfile-4.1.4.tgz",
- "integrity": "sha512-uo2ABllncSqg9F1D4nugVl9v93RmjxF6LJzQLMLDdPaXCUIDPeOJ21Gbqi43xNKzBi/WQ0Q0dICqufzQbMjipQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/retry": "*"
- }
- },
- "node_modules/@types/retry": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
- "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
- "license": "MIT"
- },
- "node_modules/@types/trusted-types": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
- "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
- "license": "MIT"
- },
- "node_modules/@types/ws": {
- "version": "8.18.1",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
- "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/yauzl": {
- "version": "2.10.3",
- "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
- "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@typescript/native-preview": {
- "version": "7.0.0-dev.20260120.1",
- "resolved": "https://registry.npmjs.org/@typescript/native-preview/-/native-preview-7.0.0-dev.20260120.1.tgz",
- "integrity": "sha512-nnEf37C9ue7OBRnF2zmV/OCBmV5Y7T/K4mCHa+nxgiXcF/1w8sA0cgdFl+gHQ0mysqUJ+Bu5btAMeWgpLyjrgg==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "tsgo": "bin/tsgo.js"
- },
- "optionalDependencies": {
- "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260120.1",
- "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260120.1",
- "@typescript/native-preview-linux-arm": "7.0.0-dev.20260120.1",
- "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260120.1",
- "@typescript/native-preview-linux-x64": "7.0.0-dev.20260120.1",
- "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260120.1",
- "@typescript/native-preview-win32-x64": "7.0.0-dev.20260120.1"
- }
- },
- "node_modules/@typescript/native-preview-darwin-arm64": {
- "version": "7.0.0-dev.20260120.1",
- "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-arm64/-/native-preview-darwin-arm64-7.0.0-dev.20260120.1.tgz",
- "integrity": "sha512-r3pWFuR2H7mn6ScwpH5jJljKQqKto0npVuJSk6pRwFwexpTyxOGmJTZJ1V0AWiisaNxU2+CNAqWFJSJYIE/QTg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@typescript/native-preview-darwin-x64": {
- "version": "7.0.0-dev.20260120.1",
- "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-x64/-/native-preview-darwin-x64-7.0.0-dev.20260120.1.tgz",
- "integrity": "sha512-cuC1+wLbUP+Ip2UT94G134fqRdp5w3b3dhcCO6/FQ4yXxvRNyv/WK+upHBUFDaeSOeHgDTyO9/QFYUWwC4If1A==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@typescript/native-preview-linux-arm": {
- "version": "7.0.0-dev.20260120.1",
- "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm/-/native-preview-linux-arm-7.0.0-dev.20260120.1.tgz",
- "integrity": "sha512-vN6OYVySol/kQZjJGmAzd6L30SyVlCgmCXS8WjUYtE5clN0YrzQHop16RK29fYZHMxpkOniVBtRPxUYQANZBlQ==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@typescript/native-preview-linux-arm64": {
- "version": "7.0.0-dev.20260120.1",
- "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm64/-/native-preview-linux-arm64-7.0.0-dev.20260120.1.tgz",
- "integrity": "sha512-zZGvEGY7wcHYefMZ87KNmvjN3NLIhsCMHEpHZiGCS3khKf+8z6ZsanrzCjOTodvL01VPyBzHxV1EtkSxAcLiQg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@typescript/native-preview-linux-x64": {
- "version": "7.0.0-dev.20260120.1",
- "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-x64/-/native-preview-linux-x64-7.0.0-dev.20260120.1.tgz",
- "integrity": "sha512-JBfNhWd/asd5MDeS3VgRvE24pGKBkmvLub6tsux6ypr+Yhy+o0WaAEzVpmlRYZUqss2ai5tvOu4dzPBXzZAtFw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@typescript/native-preview-win32-arm64": {
- "version": "7.0.0-dev.20260120.1",
- "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-arm64/-/native-preview-win32-arm64-7.0.0-dev.20260120.1.tgz",
- "integrity": "sha512-tTndRtYCq2xwgE0VkTi9ACNiJaV43+PqvBqCxk8ceYi3X36Ve+CCnwlZfZJ4k9NxZthtrAwF/kUmpC9iIYbq1w==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@typescript/native-preview-win32-x64": {
- "version": "7.0.0-dev.20260120.1",
- "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-x64/-/native-preview-win32-x64-7.0.0-dev.20260120.1.tgz",
- "integrity": "sha512-oZia7hFL6k9pVepfonuPI86Jmyz6WlJKR57tWCDwRNmpA7odxuTq1PbvcYgy1z4+wHF1nnKKJY0PMAiq6ac18w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@vitest/expect": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz",
- "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/chai": "^5.2.2",
- "@vitest/spy": "3.2.4",
- "@vitest/utils": "3.2.4",
- "chai": "^5.2.0",
- "tinyrainbow": "^2.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/mocker": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz",
- "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/spy": "3.2.4",
- "estree-walker": "^3.0.3",
- "magic-string": "^0.30.17"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- },
- "peerDependencies": {
- "msw": "^2.4.9",
- "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
- },
- "peerDependenciesMeta": {
- "msw": {
- "optional": true
- },
- "vite": {
- "optional": true
- }
- }
- },
- "node_modules/@vitest/pretty-format": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz",
- "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tinyrainbow": "^2.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/runner": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz",
- "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/utils": "3.2.4",
- "pathe": "^2.0.3",
- "strip-literal": "^3.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/snapshot": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz",
- "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/pretty-format": "3.2.4",
- "magic-string": "^0.30.17",
- "pathe": "^2.0.3"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/spy": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz",
- "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tinyspy": "^4.0.3"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/utils": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz",
- "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/pretty-format": "3.2.4",
- "loupe": "^3.1.4",
- "tinyrainbow": "^2.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@webreflection/alien-signals": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@webreflection/alien-signals/-/alien-signals-0.3.2.tgz",
- "integrity": "sha512-DmNjD8Kq5iM+Toirp3llS/izAiI3Dwav5nHRvKdR/YJBTgun3y4xK76rs9CFYD2bZwZJN/rP+HjEqKTteGK+Yw==",
- "license": "MIT",
- "dependencies": {
- "alien-signals": "^2.0.6"
- }
- },
- "node_modules/@xterm/headless": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@xterm/headless/-/headless-5.5.0.tgz",
- "integrity": "sha512-5xXB7kdQlFBP82ViMJTwwEc3gKCLGKR/eoxQm4zge7GPBl86tCdI0IdPJjoKd8mUSFXz5V7i/25sfsEkP4j46g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@xterm/xterm": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
- "integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/agent-base": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
- "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/ajv": {
- "version": "8.18.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
- "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.3",
- "fast-uri": "^3.0.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/ajv-formats": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
- "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
- "license": "MIT",
- "dependencies": {
- "ajv": "^8.0.0"
- },
- "peerDependencies": {
- "ajv": "^8.0.0"
- },
- "peerDependenciesMeta": {
- "ajv": {
- "optional": true
- }
- }
- },
- "node_modules/alien-signals": {
- "version": "2.0.8",
- "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-2.0.8.tgz",
- "integrity": "sha512-844G1VLkk0Pe2SJjY0J8vp8ADI73IM4KliNu2OGlYzWpO28NexEUvjHTcFjFX3VXoiUtwTbHxLNI9ImkcoBqzA==",
- "license": "MIT"
- },
- "node_modules/ansi-regex": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
- "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/any-promise": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
- "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
- "license": "MIT"
- },
- "node_modules/assertion-error": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
- "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/ast-types": {
- "version": "0.13.4",
- "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
- "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.0.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "license": "MIT"
- },
- "node_modules/axios": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz",
- "integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==",
- "license": "MIT",
- "dependencies": {
- "follow-redirects": "^1.15.11",
- "form-data": "^4.0.5",
- "proxy-from-env": "^2.1.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
- "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
- "license": "MIT",
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/basic-ftp": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz",
- "integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/bignumber.js": {
- "version": "9.3.1",
- "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
- "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/bl": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "buffer": "^5.5.0",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
- }
- },
- "node_modules/bowser": {
- "version": "2.14.1",
- "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz",
- "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==",
- "license": "MIT"
- },
- "node_modules/brace-expansion": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
- "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^4.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fill-range": "^7.1.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/buffer": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.1.13"
- }
- },
- "node_modules/buffer-crc32": {
- "version": "0.2.13",
- "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
- "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/buffer-equal-constant-time": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
- "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
- "license": "BSD-3-Clause"
- },
- "node_modules/cac": {
- "version": "6.7.14",
- "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
- "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/canvas": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/canvas/-/canvas-3.2.3.tgz",
- "integrity": "sha512-PzE5nJZPz72YUAfo8oTp0u3fqqY7IzlTubneAihqDYAUcBk7ryeCmBbdJBEdaH0bptSOe2VT2Zwcb3UaFyaSWw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "node-addon-api": "^7.0.0",
- "prebuild-install": "^7.1.3"
- },
- "engines": {
- "node": "^18.12.0 || >= 20.9.0"
- }
- },
- "node_modules/chai": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz",
- "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "assertion-error": "^2.0.1",
- "check-error": "^2.1.1",
- "deep-eql": "^5.0.1",
- "loupe": "^3.1.0",
- "pathval": "^2.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/chalk": {
- "version": "5.6.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
- "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
- "license": "MIT",
- "engines": {
- "node": "^12.17.0 || ^14.13 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/check-error": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz",
- "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 16"
- }
- },
- "node_modules/chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/class-variance-authority": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
- "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
- "license": "Apache-2.0",
- "dependencies": {
- "clsx": "^2.1.1"
- },
- "funding": {
- "url": "https://polar.sh/cva"
- }
- },
- "node_modules/cli-highlight": {
- "version": "2.1.11",
- "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz",
- "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==",
- "license": "ISC",
- "dependencies": {
- "chalk": "^4.0.0",
- "highlight.js": "^10.7.1",
- "mz": "^2.4.0",
- "parse5": "^5.1.1",
- "parse5-htmlparser2-tree-adapter": "^6.0.0",
- "yargs": "^16.0.0"
- },
- "bin": {
- "highlight": "bin/highlight"
- },
- "engines": {
- "node": ">=8.0.0",
- "npm": ">=5.0.0"
- }
- },
- "node_modules/cli-highlight/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/cli-highlight/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui": {
- "version": "7.0.4",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
- "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.0",
- "wrap-ansi": "^7.0.0"
- }
- },
- "node_modules/cliui/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/clsx": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
- "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "license": "MIT"
- },
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "license": "MIT",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/commander": {
- "version": "12.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
- "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/concurrently": {
- "version": "9.2.1",
- "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz",
- "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chalk": "4.1.2",
- "rxjs": "7.8.2",
- "shell-quote": "1.8.3",
- "supports-color": "8.1.1",
- "tree-kill": "1.2.2",
- "yargs": "17.7.2"
- },
- "bin": {
- "conc": "dist/bin/concurrently.js",
- "concurrently": "dist/bin/concurrently.js"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
- }
- },
- "node_modules/concurrently/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/concurrently/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/concurrently/node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/concurrently/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/concurrently/node_modules/yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/concurrently/node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/core-util-is": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
- "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
- "license": "MIT"
- },
- "node_modules/croner": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/croner/-/croner-9.1.0.tgz",
- "integrity": "sha512-p9nwwR4qyT5W996vBZhdvBCnMhicY5ytZkR4D1Xj0wuTDEiMnjwR57Q3RXYY/s0EpX6Ay3vgIcfaR+ewGHsi+g==",
- "license": "MIT",
- "engines": {
- "node": ">=18.0"
- }
- },
- "node_modules/cross-spawn": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
- "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "nice-try": "^1.0.4",
- "path-key": "^2.0.1",
- "semver": "^5.5.0",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- },
- "engines": {
- "node": ">=4.8"
- }
- },
- "node_modules/cross-spawn/node_modules/semver": {
- "version": "5.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
- "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver"
- }
- },
- "node_modules/data-uri-to-buffer": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
- "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
- "license": "MIT",
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decompress-response": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
- "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mimic-response": "^3.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/deep-eql": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
- "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/degenerator": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
- "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
- "license": "MIT",
- "dependencies": {
- "ast-types": "^0.13.4",
- "escodegen": "^2.1.0",
- "esprima": "^4.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/detect-libc": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
- "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/diff": {
- "version": "8.0.4",
- "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz",
- "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.3.1"
- }
- },
- "node_modules/docx-preview": {
- "version": "0.3.7",
- "resolved": "https://registry.npmjs.org/docx-preview/-/docx-preview-0.3.7.tgz",
- "integrity": "sha512-Lav69CTA/IYZPJTsKH7oYeoZjyg96N0wEJMNslGJnZJ+dMUZK85Lt5ASC79yUlD48ecWjuv+rkcmFt6EVPV0Xg==",
- "license": "Apache-2.0",
- "dependencies": {
- "jszip": ">=3.0.0"
- }
- },
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/ecdsa-sig-formatter": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
- "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
- },
- "node_modules/end-of-stream": {
- "version": "1.4.5",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
- "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
- "license": "MIT",
- "dependencies": {
- "once": "^1.4.0"
- }
- },
- "node_modules/enhanced-resolve": {
- "version": "5.20.1",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz",
- "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.4",
- "tapable": "^2.3.0"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-module-lexer": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
- "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-set-tostringtag": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
- "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/esbuild": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz",
- "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==",
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.27.7",
- "@esbuild/android-arm": "0.27.7",
- "@esbuild/android-arm64": "0.27.7",
- "@esbuild/android-x64": "0.27.7",
- "@esbuild/darwin-arm64": "0.27.7",
- "@esbuild/darwin-x64": "0.27.7",
- "@esbuild/freebsd-arm64": "0.27.7",
- "@esbuild/freebsd-x64": "0.27.7",
- "@esbuild/linux-arm": "0.27.7",
- "@esbuild/linux-arm64": "0.27.7",
- "@esbuild/linux-ia32": "0.27.7",
- "@esbuild/linux-loong64": "0.27.7",
- "@esbuild/linux-mips64el": "0.27.7",
- "@esbuild/linux-ppc64": "0.27.7",
- "@esbuild/linux-riscv64": "0.27.7",
- "@esbuild/linux-s390x": "0.27.7",
- "@esbuild/linux-x64": "0.27.7",
- "@esbuild/netbsd-arm64": "0.27.7",
- "@esbuild/netbsd-x64": "0.27.7",
- "@esbuild/openbsd-arm64": "0.27.7",
- "@esbuild/openbsd-x64": "0.27.7",
- "@esbuild/openharmony-arm64": "0.27.7",
- "@esbuild/sunos-x64": "0.27.7",
- "@esbuild/win32-arm64": "0.27.7",
- "@esbuild/win32-ia32": "0.27.7",
- "@esbuild/win32-x64": "0.27.7"
- }
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escodegen": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
- "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "esprima": "^4.0.1",
- "estraverse": "^5.2.0",
- "esutils": "^2.0.2"
- },
- "bin": {
- "escodegen": "bin/escodegen.js",
- "esgenerate": "bin/esgenerate.js"
- },
- "engines": {
- "node": ">=6.0"
- },
- "optionalDependencies": {
- "source-map": "~0.6.1"
- }
- },
- "node_modules/esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "license": "BSD-2-Clause",
- "bin": {
- "esparse": "bin/esparse.js",
- "esvalidate": "bin/esvalidate.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/estree-walker": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
- "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/estree": "^1.0.0"
- }
- },
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/eventemitter3": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
- "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
- "license": "MIT"
- },
- "node_modules/execa": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
- "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cross-spawn": "^6.0.0",
- "get-stream": "^4.0.0",
- "is-stream": "^1.1.0",
- "npm-run-path": "^2.0.0",
- "p-finally": "^1.0.0",
- "signal-exit": "^3.0.0",
- "strip-eof": "^1.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/execa/node_modules/get-stream": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
- "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pump": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/execa/node_modules/is-stream": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
- "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/expand-template": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
- "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
- "dev": true,
- "license": "(MIT OR WTFPL)",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/expect-type": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
- "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/extend": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
- "license": "MIT"
- },
- "node_modules/extract-zip": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
- "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "debug": "^4.1.1",
- "get-stream": "^5.1.0",
- "yauzl": "^2.10.0"
- },
- "bin": {
- "extract-zip": "cli.js"
- },
- "engines": {
- "node": ">= 10.17.0"
- },
- "optionalDependencies": {
- "@types/yauzl": "^2.9.1"
- }
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "license": "MIT"
- },
- "node_modules/fast-glob": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
- "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.8"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fast-uri": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
- "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fastify"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/fastify"
- }
- ],
- "license": "BSD-3-Clause"
- },
- "node_modules/fast-xml-builder": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz",
- "integrity": "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "path-expression-matcher": "^1.1.3"
- }
- },
- "node_modules/fast-xml-parser": {
- "version": "5.5.8",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.5.8.tgz",
- "integrity": "sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "fast-xml-builder": "^1.1.4",
- "path-expression-matcher": "^1.2.0",
- "strnum": "^2.2.0"
- },
- "bin": {
- "fxparser": "src/cli/cli.js"
- }
- },
- "node_modules/fastq": {
- "version": "1.20.1",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
- "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "node_modules/fd-slicer": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
- "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
- "license": "MIT",
- "dependencies": {
- "pend": "~1.2.0"
- }
- },
- "node_modules/fetch-blob": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
- "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "node-domexception": "^1.0.0",
- "web-streams-polyfill": "^3.0.3"
- },
- "engines": {
- "node": "^12.20 || >= 14.13"
- }
- },
- "node_modules/file-type": {
- "version": "21.3.4",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.4.tgz",
- "integrity": "sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==",
- "license": "MIT",
- "dependencies": {
- "@tokenizer/inflate": "^0.4.1",
- "strtok3": "^10.3.4",
- "token-types": "^6.1.1",
- "uint8array-extras": "^1.4.0"
- },
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/file-type?sponsor=1"
- }
- },
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/follow-redirects": {
- "version": "1.16.0",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
- "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/RubenVerborgh"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=4.0"
- },
- "peerDependenciesMeta": {
- "debug": {
- "optional": true
- }
- }
- },
- "node_modules/form-data": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
- "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
- "license": "MIT",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "es-set-tostringtag": "^2.1.0",
- "hasown": "^2.0.2",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/formdata-polyfill": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
- "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
- "license": "MIT",
- "dependencies": {
- "fetch-blob": "^3.1.2"
- },
- "engines": {
- "node": ">=12.20.0"
- }
- },
- "node_modules/fs-constants": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
- "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gaxios": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz",
- "integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==",
- "license": "Apache-2.0",
- "dependencies": {
- "extend": "^3.0.2",
- "https-proxy-agent": "^7.0.1",
- "node-fetch": "^3.3.2"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/gcp-metadata": {
- "version": "8.1.2",
- "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz",
- "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==",
- "license": "Apache-2.0",
- "dependencies": {
- "gaxios": "^7.0.0",
- "google-logging-utils": "^1.0.0",
- "json-bigint": "^1.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "license": "ISC",
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "node_modules/get-east-asian-width": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz",
- "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/get-stream": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
- "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
- "license": "MIT",
- "dependencies": {
- "pump": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/get-tsconfig": {
- "version": "4.14.0",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
- "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "resolve-pkg-maps": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
- }
- },
- "node_modules/get-uri": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz",
- "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==",
- "license": "MIT",
- "dependencies": {
- "basic-ftp": "^5.0.2",
- "data-uri-to-buffer": "^6.0.2",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/get-uri/node_modules/data-uri-to-buffer": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
- "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
- "license": "MIT",
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/github-from-package": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
- "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/glob": {
- "version": "13.0.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz",
- "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "minimatch": "^10.2.2",
- "minipass": "^7.1.3",
- "path-scurry": "^2.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/google-auth-library": {
- "version": "10.6.2",
- "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz",
- "integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==",
- "license": "Apache-2.0",
- "dependencies": {
- "base64-js": "^1.3.0",
- "ecdsa-sig-formatter": "^1.0.11",
- "gaxios": "^7.1.4",
- "gcp-metadata": "8.1.2",
- "google-logging-utils": "1.1.3",
- "jws": "^4.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/google-logging-utils": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz",
- "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "license": "ISC"
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-tostringtag": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
- "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
- "license": "MIT",
- "dependencies": {
- "has-symbols": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/highlight.js": {
- "version": "10.7.3",
- "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
- "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/hosted-git-info": {
- "version": "9.0.2",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.2.tgz",
- "integrity": "sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==",
- "license": "ISC",
- "dependencies": {
- "lru-cache": "^11.1.0"
- },
- "engines": {
- "node": "^20.17.0 || >=22.9.0"
- }
- },
- "node_modules/html-parse-string": {
- "version": "0.0.9",
- "resolved": "https://registry.npmjs.org/html-parse-string/-/html-parse-string-0.0.9.tgz",
- "integrity": "sha512-wyGnsOolHbNrcb8N6bdJF4EHyzd3zVGCb9/mBxeNjAYBDOZqD7YkqLBz7kXtdgHwNnV8lN/BpSDpsI1zm8Sd8g==",
- "license": "MIT"
- },
- "node_modules/http-proxy-agent": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
- "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
- "license": "MIT",
- "dependencies": {
- "agent-base": "^7.1.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/https-proxy-agent": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
- "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
- "license": "MIT",
- "dependencies": {
- "agent-base": "^7.1.2",
- "debug": "4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/husky": {
- "version": "9.1.7",
- "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
- "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "husky": "bin.js"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/typicode"
- }
- },
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "BSD-3-Clause"
- },
- "node_modules/ignore": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
- "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/immediate": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
- "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
- "license": "MIT"
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "license": "ISC"
- },
- "node_modules/ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/interpret": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
- "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/ip-address": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
- "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
- "license": "MIT",
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.16.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
- "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-electron": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz",
- "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==",
- "license": "MIT"
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-stream": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
- "license": "MIT"
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/jiti": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
- "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
- "license": "MIT",
- "bin": {
- "jiti": "lib/jiti-cli.mjs"
- }
- },
- "node_modules/js-tokens": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
- "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json-bigint": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
- "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
- "license": "MIT",
- "dependencies": {
- "bignumber.js": "^9.0.0"
- }
- },
- "node_modules/json-schema-to-ts": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz",
- "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.18.3",
- "ts-algebra": "^2.0.0"
- },
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "license": "MIT"
- },
- "node_modules/jsonschema": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.5.0.tgz",
- "integrity": "sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==",
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/jszip": {
- "version": "3.10.1",
- "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
- "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
- "license": "(MIT OR GPL-3.0-or-later)",
- "dependencies": {
- "lie": "~3.3.0",
- "pako": "~1.0.2",
- "readable-stream": "~2.3.6",
- "setimmediate": "^1.0.5"
- }
- },
- "node_modules/jszip/node_modules/readable-stream": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
- "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
- "license": "MIT",
- "dependencies": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "node_modules/jszip/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "license": "MIT"
- },
- "node_modules/jszip/node_modules/string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "~5.1.0"
- }
- },
- "node_modules/jwa": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
- "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
- "license": "MIT",
- "dependencies": {
- "buffer-equal-constant-time": "^1.0.1",
- "ecdsa-sig-formatter": "1.0.11",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/jws": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
- "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
- "license": "MIT",
- "dependencies": {
- "jwa": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/katex": {
- "version": "0.16.45",
- "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.45.tgz",
- "integrity": "sha512-pQpZbdBu7wCTmQUh7ufPmLr0pFoObnGUoL/yhtwJDgmmQpbkg/0HSVti25Fu4rmd1oCR6NGWe9vqTWuWv3GcNA==",
- "funding": [
- "https://opencollective.com/katex",
- "https://github.com/sponsors/katex"
- ],
- "license": "MIT",
- "dependencies": {
- "commander": "^8.3.0"
- },
- "bin": {
- "katex": "cli.js"
- }
- },
- "node_modules/katex/node_modules/commander": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
- "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
- "license": "MIT",
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/koffi": {
- "version": "2.16.0",
- "resolved": "https://registry.npmjs.org/koffi/-/koffi-2.16.0.tgz",
- "integrity": "sha512-h/2NJueOKWd0YYycEOWDspomizgNfuOKf/V7ZE2fytvuRtHoY9Tb+y4x6GJ6pFqaVndWn9dLK+sCI14eWtu5rA==",
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "funding": {
- "url": "https://liberapay.com/Koromix"
- }
- },
- "node_modules/lie": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
- "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
- "license": "MIT",
- "dependencies": {
- "immediate": "~3.0.5"
- }
- },
- "node_modules/lightningcss": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
- "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
- "license": "MPL-2.0",
- "dependencies": {
- "detect-libc": "^2.0.3"
- },
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- },
- "optionalDependencies": {
- "lightningcss-android-arm64": "1.32.0",
- "lightningcss-darwin-arm64": "1.32.0",
- "lightningcss-darwin-x64": "1.32.0",
- "lightningcss-freebsd-x64": "1.32.0",
- "lightningcss-linux-arm-gnueabihf": "1.32.0",
- "lightningcss-linux-arm64-gnu": "1.32.0",
- "lightningcss-linux-arm64-musl": "1.32.0",
- "lightningcss-linux-x64-gnu": "1.32.0",
- "lightningcss-linux-x64-musl": "1.32.0",
- "lightningcss-win32-arm64-msvc": "1.32.0",
- "lightningcss-win32-x64-msvc": "1.32.0"
- }
- },
- "node_modules/lightningcss-android-arm64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
- "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-darwin-arm64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
- "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-darwin-x64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
- "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-freebsd-x64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
- "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm-gnueabihf": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
- "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
- "cpu": [
- "arm"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm64-gnu": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
- "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm64-musl": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
- "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-gnu": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
- "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-musl": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
- "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-win32-arm64-msvc": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
- "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-win32-x64-msvc": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
- "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lit": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.2.tgz",
- "integrity": "sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@lit/reactive-element": "^2.1.0",
- "lit-element": "^4.2.0",
- "lit-html": "^3.3.0"
- }
- },
- "node_modules/lit-element": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.2.tgz",
- "integrity": "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@lit-labs/ssr-dom-shim": "^1.5.0",
- "@lit/reactive-element": "^2.1.0",
- "lit-html": "^3.3.0"
- }
- },
- "node_modules/lit-html": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.2.tgz",
- "integrity": "sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@types/trusted-types": "^2.0.2"
- }
- },
- "node_modules/lodash-es": {
- "version": "4.18.1",
- "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
- "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
- "license": "MIT"
- },
- "node_modules/long": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
- "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
- "license": "Apache-2.0"
- },
- "node_modules/loupe": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
- "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/lru-cache": {
- "version": "11.3.5",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz",
- "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": "20 || >=22"
- }
- },
- "node_modules/lucide": {
- "version": "0.544.0",
- "resolved": "https://registry.npmjs.org/lucide/-/lucide-0.544.0.tgz",
- "integrity": "sha512-U5ORwr5z9Sx7bNTDFaW55RbjVdQEnAcT3vws9uz3vRT1G4XXJUDAhRZdxhFoIyHEvjmTkzzlEhjSLYM5n4mb5w==",
- "license": "ISC"
- },
- "node_modules/magic-string": {
- "version": "0.30.21",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
- "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.5"
- }
- },
- "node_modules/marked": {
- "version": "15.0.12",
- "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz",
- "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==",
- "license": "MIT",
- "bin": {
- "marked": "bin/marked.js"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/math-intrinsics": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
- "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
- "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "braces": "^3.0.3",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mimic-response": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
- "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/minimatch": {
- "version": "10.2.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
- "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "brace-expansion": "^5.0.5"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/minipass": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
- "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/mkdirp-classic": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
- "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/mri": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
- "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
- "node_modules/mz": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
- "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
- "license": "MIT",
- "dependencies": {
- "any-promise": "^1.0.0",
- "object-assign": "^4.0.1",
- "thenify-all": "^1.0.0"
- }
- },
- "node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/napi-build-utils": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
- "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/netmask": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz",
- "integrity": "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/nice-try": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
- "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/node-abi": {
- "version": "3.89.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.89.0.tgz",
- "integrity": "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "semver": "^7.3.5"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/node-addon-api": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
- "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/node-domexception": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
- "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
- "deprecated": "Use your platform's native DOMException instead",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "github",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=10.5.0"
- }
- },
- "node_modules/node-fetch": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
- "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
- "license": "MIT",
- "dependencies": {
- "data-uri-to-buffer": "^4.0.0",
- "fetch-blob": "^3.1.4",
- "formdata-polyfill": "^4.0.10"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/node-fetch"
- }
- },
- "node_modules/npm-run-path": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
- "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-key": "^2.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/ollama": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/ollama/-/ollama-0.6.3.tgz",
- "integrity": "sha512-KEWEhIqE5wtfzEIZbDCLH51VFZ6Z3ZSa6sIOg/E/tBV8S51flyqBOXi+bRxlOYKDf8i327zG9eSTb8IJxvm3Zg==",
- "license": "MIT",
- "dependencies": {
- "whatwg-fetch": "^3.6.20"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "license": "ISC",
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/openai": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/openai/-/openai-6.26.0.tgz",
- "integrity": "sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==",
- "license": "Apache-2.0",
- "bin": {
- "openai": "bin/cli"
- },
- "peerDependencies": {
- "ws": "^8.18.0",
- "zod": "^3.25 || ^4.0"
- },
- "peerDependenciesMeta": {
- "ws": {
- "optional": true
- },
- "zod": {
- "optional": true
- }
- }
- },
- "node_modules/p-finally": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
- "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/p-queue": {
- "version": "6.6.2",
- "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
- "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==",
- "license": "MIT",
- "dependencies": {
- "eventemitter3": "^4.0.4",
- "p-timeout": "^3.2.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-queue/node_modules/eventemitter3": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
- "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
- "license": "MIT"
- },
- "node_modules/p-retry": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
- "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
- "license": "MIT",
- "dependencies": {
- "@types/retry": "0.12.0",
- "retry": "^0.13.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/p-timeout": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
- "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
- "license": "MIT",
- "dependencies": {
- "p-finally": "^1.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/pac-proxy-agent": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz",
- "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==",
- "license": "MIT",
- "dependencies": {
- "@tootallnate/quickjs-emscripten": "^0.23.0",
- "agent-base": "^7.1.2",
- "debug": "^4.3.4",
- "get-uri": "^6.0.1",
- "http-proxy-agent": "^7.0.0",
- "https-proxy-agent": "^7.0.6",
- "pac-resolver": "^7.0.1",
- "socks-proxy-agent": "^8.0.5"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/pac-resolver": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
- "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
- "license": "MIT",
- "dependencies": {
- "degenerator": "^5.0.0",
- "netmask": "^2.0.2"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/pako": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
- "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
- "license": "(MIT AND Zlib)"
- },
- "node_modules/parse5": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
- "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
- "license": "MIT"
- },
- "node_modules/parse5-htmlparser2-tree-adapter": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
- "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
- "license": "MIT",
- "dependencies": {
- "parse5": "^6.0.1"
- }
- },
- "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
- "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
- "license": "MIT"
- },
- "node_modules/partial-json": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/partial-json/-/partial-json-0.1.7.tgz",
- "integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==",
- "license": "MIT"
- },
- "node_modules/path-expression-matcher": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz",
- "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/path-key": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
- "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/path-scurry": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
- "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "lru-cache": "^11.0.0",
- "minipass": "^7.1.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/pathe": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
- "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/pathval": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz",
- "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 14.16"
- }
- },
- "node_modules/pdfjs-dist": {
- "version": "5.4.394",
- "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.4.394.tgz",
- "integrity": "sha512-9ariAYGqUJzx+V/1W4jHyiyCep6IZALmDzoaTLZ6VNu8q9LWi1/ukhzHgE2Xsx96AZi0mbZuK4/ttIbqSbLypg==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=20.16.0 || >=22.3.0"
- },
- "optionalDependencies": {
- "@napi-rs/canvas": "^0.1.81"
- }
- },
- "node_modules/pend": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
- "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
- "license": "MIT"
- },
- "node_modules/pi-extension-custom-provider-anthropic": {
- "resolved": "packages/coding-agent/examples/extensions/custom-provider-anthropic",
- "link": true
- },
- "node_modules/pi-extension-custom-provider-gitlab-duo": {
- "resolved": "packages/coding-agent/examples/extensions/custom-provider-gitlab-duo",
- "link": true
- },
- "node_modules/pi-extension-custom-provider-qwen-cli": {
- "resolved": "packages/coding-agent/examples/extensions/custom-provider-qwen-cli",
- "link": true
- },
- "node_modules/pi-extension-with-deps": {
- "resolved": "packages/coding-agent/examples/extensions/with-deps",
- "link": true
- },
- "node_modules/pi-web-ui-example": {
- "resolved": "packages/web-ui/example",
- "link": true
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "license": "ISC"
- },
- "node_modules/picomatch": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
- "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/postcss": {
- "version": "8.5.10",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz",
- "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.11",
- "picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/prebuild-install": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
- "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
- "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "detect-libc": "^2.0.0",
- "expand-template": "^2.0.3",
- "github-from-package": "0.0.0",
- "minimist": "^1.2.3",
- "mkdirp-classic": "^0.5.3",
- "napi-build-utils": "^2.0.0",
- "node-abi": "^3.3.0",
- "pump": "^3.0.0",
- "rc": "^1.2.7",
- "simple-get": "^4.0.0",
- "tar-fs": "^2.0.0",
- "tunnel-agent": "^0.6.0"
- },
- "bin": {
- "prebuild-install": "bin.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/process-nextick-args": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
- "license": "MIT"
- },
- "node_modules/proper-lockfile": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz",
- "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.4",
- "retry": "^0.12.0",
- "signal-exit": "^3.0.2"
- }
- },
- "node_modules/proper-lockfile/node_modules/retry": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
- "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/protobufjs": {
- "version": "7.5.5",
- "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.5.tgz",
- "integrity": "sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==",
- "hasInstallScript": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@protobufjs/aspromise": "^1.1.2",
- "@protobufjs/base64": "^1.1.2",
- "@protobufjs/codegen": "^2.0.4",
- "@protobufjs/eventemitter": "^1.1.0",
- "@protobufjs/fetch": "^1.1.0",
- "@protobufjs/float": "^1.0.2",
- "@protobufjs/inquire": "^1.1.0",
- "@protobufjs/path": "^1.1.2",
- "@protobufjs/pool": "^1.1.0",
- "@protobufjs/utf8": "^1.1.0",
- "@types/node": ">=13.7.0",
- "long": "^5.0.0"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/proxy-agent": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz",
- "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==",
- "license": "MIT",
- "dependencies": {
- "agent-base": "^7.1.2",
- "debug": "^4.3.4",
- "http-proxy-agent": "^7.0.1",
- "https-proxy-agent": "^7.0.6",
- "lru-cache": "^7.14.1",
- "pac-proxy-agent": "^7.1.0",
- "proxy-from-env": "^1.1.0",
- "socks-proxy-agent": "^8.0.5"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/proxy-agent/node_modules/lru-cache": {
- "version": "7.18.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
- "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/proxy-agent/node_modules/proxy-from-env": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
- "license": "MIT"
- },
- "node_modules/proxy-from-env": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
- "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/pump": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
- "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
- "license": "MIT",
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "dev": true,
- "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "bin": {
- "rc": "cli.js"
- }
- },
- "node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/rechoir": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
- "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
- "dev": true,
- "dependencies": {
- "resolve": "^1.1.6"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/require-from-string": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
- "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.12",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
- "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "is-core-module": "^2.16.1",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/resolve-pkg-maps": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
- "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
- "devOptional": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
- }
- },
- "node_modules/retry": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
- "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/reusify": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
- "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
- "node_modules/rollup": {
- "version": "4.60.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz",
- "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==",
- "license": "MIT",
- "dependencies": {
- "@types/estree": "1.0.8"
- },
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=18.0.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.60.1",
- "@rollup/rollup-android-arm64": "4.60.1",
- "@rollup/rollup-darwin-arm64": "4.60.1",
- "@rollup/rollup-darwin-x64": "4.60.1",
- "@rollup/rollup-freebsd-arm64": "4.60.1",
- "@rollup/rollup-freebsd-x64": "4.60.1",
- "@rollup/rollup-linux-arm-gnueabihf": "4.60.1",
- "@rollup/rollup-linux-arm-musleabihf": "4.60.1",
- "@rollup/rollup-linux-arm64-gnu": "4.60.1",
- "@rollup/rollup-linux-arm64-musl": "4.60.1",
- "@rollup/rollup-linux-loong64-gnu": "4.60.1",
- "@rollup/rollup-linux-loong64-musl": "4.60.1",
- "@rollup/rollup-linux-ppc64-gnu": "4.60.1",
- "@rollup/rollup-linux-ppc64-musl": "4.60.1",
- "@rollup/rollup-linux-riscv64-gnu": "4.60.1",
- "@rollup/rollup-linux-riscv64-musl": "4.60.1",
- "@rollup/rollup-linux-s390x-gnu": "4.60.1",
- "@rollup/rollup-linux-x64-gnu": "4.60.1",
- "@rollup/rollup-linux-x64-musl": "4.60.1",
- "@rollup/rollup-openbsd-x64": "4.60.1",
- "@rollup/rollup-openharmony-arm64": "4.60.1",
- "@rollup/rollup-win32-arm64-msvc": "4.60.1",
- "@rollup/rollup-win32-ia32-msvc": "4.60.1",
- "@rollup/rollup-win32-x64-gnu": "4.60.1",
- "@rollup/rollup-win32-x64-msvc": "4.60.1",
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
- "node_modules/rxjs": {
- "version": "7.8.2",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
- "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/setimmediate": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
- "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
- "license": "MIT"
- },
- "node_modules/shebang-command": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
- "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "shebang-regex": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/shebang-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
- "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/shell-quote": {
- "version": "1.8.3",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz",
- "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/shelljs": {
- "version": "0.9.2",
- "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.9.2.tgz",
- "integrity": "sha512-S3I64fEiKgTZzKCC46zT/Ib9meqofLrQVbpSswtjFfAVDW+AZ54WTnAM/3/yENoxz/V1Cy6u3kiiEbQ4DNphvw==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "execa": "^1.0.0",
- "fast-glob": "^3.3.2",
- "interpret": "^1.0.0",
- "rechoir": "^0.6.2"
- },
- "bin": {
- "shjs": "bin/shjs"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/shx": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/shx/-/shx-0.4.0.tgz",
- "integrity": "sha512-Z0KixSIlGPpijKgcH6oCMCbltPImvaKy0sGH8AkLRXw1KyzpKtaCTizP2xen+hNDqVF4xxgvA0KXSb9o4Q6hnA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "minimist": "^1.2.8",
- "shelljs": "^0.9.2"
- },
- "bin": {
- "shx": "lib/cli.js"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/siginfo": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
- "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "license": "ISC"
- },
- "node_modules/simple-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/simple-get": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
- "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "decompress-response": "^6.0.0",
- "once": "^1.3.1",
- "simple-concat": "^1.0.0"
- }
- },
- "node_modules/smart-buffer": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
- "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
- "license": "MIT",
- "engines": {
- "node": ">= 6.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/socks": {
- "version": "2.8.7",
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
- "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==",
- "license": "MIT",
- "dependencies": {
- "ip-address": "^10.0.1",
- "smart-buffer": "^4.2.0"
- },
- "engines": {
- "node": ">= 10.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/socks-proxy-agent": {
- "version": "8.0.5",
- "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
- "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
- "license": "MIT",
- "dependencies": {
- "agent-base": "^7.1.2",
- "debug": "^4.3.4",
- "socks": "^2.8.3"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "license": "BSD-3-Clause",
- "optional": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/stackback": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
- "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/std-env": {
- "version": "3.10.0",
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
- "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
- "license": "MIT"
- },
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
- "node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
- "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^6.2.2"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
- "node_modules/strip-eof": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
- "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/strip-literal": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz",
- "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "js-tokens": "^9.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/antfu"
- }
- },
- "node_modules/strnum": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.3.tgz",
- "integrity": "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- }
- ],
- "license": "MIT"
- },
- "node_modules/strtok3": {
- "version": "10.3.5",
- "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.5.tgz",
- "integrity": "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==",
- "license": "MIT",
- "dependencies": {
- "@tokenizer/token": "^0.3.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
- }
- },
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/tailwind-merge": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.5.0.tgz",
- "integrity": "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/dcastil"
- }
- },
- "node_modules/tailwind-variants": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/tailwind-variants/-/tailwind-variants-3.2.2.tgz",
- "integrity": "sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg==",
- "license": "MIT",
- "engines": {
- "node": ">=16.x",
- "pnpm": ">=7.x"
- },
- "peerDependencies": {
- "tailwind-merge": ">=3.0.0",
- "tailwindcss": "*"
- },
- "peerDependenciesMeta": {
- "tailwind-merge": {
- "optional": true
- }
- }
- },
- "node_modules/tailwindcss": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.2.tgz",
- "integrity": "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==",
- "license": "MIT"
- },
- "node_modules/tapable": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.2.tgz",
- "integrity": "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/webpack"
- }
- },
- "node_modules/tar-fs": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
- "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chownr": "^1.1.1",
- "mkdirp-classic": "^0.5.2",
- "pump": "^3.0.0",
- "tar-stream": "^2.1.4"
- }
- },
- "node_modules/tar-stream": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
- "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "bl": "^4.0.3",
- "end-of-stream": "^1.4.1",
- "fs-constants": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.1.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/thenify": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
- "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
- "license": "MIT",
- "dependencies": {
- "any-promise": "^1.0.0"
- }
- },
- "node_modules/thenify-all": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
- "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
- "license": "MIT",
- "dependencies": {
- "thenify": ">= 3.1.0 < 4"
- },
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/tinybench": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
- "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/tinyexec": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
- "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/tinyglobby": {
- "version": "0.2.16",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
- "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
- "license": "MIT",
- "dependencies": {
- "fdir": "^6.5.0",
- "picomatch": "^4.0.4"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
- }
- },
- "node_modules/tinyglobby/node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/tinyglobby/node_modules/picomatch": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
- "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/tinypool": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz",
- "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- }
- },
- "node_modules/tinyrainbow": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz",
- "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/tinyspy": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz",
- "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/token-types": {
- "version": "6.1.2",
- "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz",
- "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==",
- "license": "MIT",
- "dependencies": {
- "@borewit/text-codec": "^0.2.1",
- "@tokenizer/token": "^0.3.0",
- "ieee754": "^1.2.1"
- },
- "engines": {
- "node": ">=14.16"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/tree-kill": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
- "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "tree-kill": "cli.js"
- }
- },
- "node_modules/ts-algebra": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz",
- "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==",
- "license": "MIT"
- },
- "node_modules/tslib": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
- "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
- "license": "0BSD"
- },
- "node_modules/tsx": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
- "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "esbuild": "~0.27.0",
- "get-tsconfig": "^4.7.5"
- },
- "bin": {
- "tsx": "dist/cli.mjs"
- },
- "engines": {
- "node": ">=18.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- }
- },
- "node_modules/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/typescript": {
- "version": "5.9.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
- "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/uhtml": {
- "version": "5.0.9",
- "resolved": "https://registry.npmjs.org/uhtml/-/uhtml-5.0.9.tgz",
- "integrity": "sha512-qPyu3vGilaLe6zrjOCD/xezWEHLwdevxmbY3hzyhT25KBDF4F7YYW3YZcL3kylD/6dMoVISHjn8ggV3+9FY+5g==",
- "license": "MIT",
- "dependencies": {
- "@webreflection/alien-signals": "^0.3.2"
- }
- },
- "node_modules/uint8array-extras": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz",
- "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/undici": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.25.0.tgz",
- "integrity": "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==",
- "license": "MIT",
- "engines": {
- "node": ">=20.18.1"
- }
- },
- "node_modules/undici-types": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
- "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
- "license": "MIT"
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "license": "MIT"
- },
- "node_modules/uuid": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
- "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
- "funding": [
- "https://github.com/sponsors/broofa",
- "https://github.com/sponsors/ctavan"
- ],
- "license": "MIT",
- "bin": {
- "uuid": "dist/esm/bin/uuid"
- }
- },
- "node_modules/vite": {
- "version": "7.3.2",
- "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz",
- "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==",
- "license": "MIT",
- "dependencies": {
- "esbuild": "^0.27.0",
- "fdir": "^6.5.0",
- "picomatch": "^4.0.3",
- "postcss": "^8.5.6",
- "rollup": "^4.43.0",
- "tinyglobby": "^0.2.15"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^20.19.0 || >=22.12.0",
- "jiti": ">=1.21.0",
- "less": "^4.0.0",
- "lightningcss": "^1.21.0",
- "sass": "^1.70.0",
- "sass-embedded": "^1.70.0",
- "stylus": ">=0.54.8",
- "sugarss": "^5.0.0",
- "terser": "^5.16.0",
- "tsx": "^4.8.1",
- "yaml": "^2.4.2"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "jiti": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- },
- "tsx": {
- "optional": true
- },
- "yaml": {
- "optional": true
- }
- }
- },
- "node_modules/vite-node": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz",
- "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cac": "^6.7.14",
- "debug": "^4.4.1",
- "es-module-lexer": "^1.7.0",
- "pathe": "^2.0.3",
- "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
- },
- "bin": {
- "vite-node": "vite-node.mjs"
- },
- "engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/vite/node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/vite/node_modules/picomatch": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
- "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/vitest": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz",
- "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/chai": "^5.2.2",
- "@vitest/expect": "3.2.4",
- "@vitest/mocker": "3.2.4",
- "@vitest/pretty-format": "^3.2.4",
- "@vitest/runner": "3.2.4",
- "@vitest/snapshot": "3.2.4",
- "@vitest/spy": "3.2.4",
- "@vitest/utils": "3.2.4",
- "chai": "^5.2.0",
- "debug": "^4.4.1",
- "expect-type": "^1.2.1",
- "magic-string": "^0.30.17",
- "pathe": "^2.0.3",
- "picomatch": "^4.0.2",
- "std-env": "^3.9.0",
- "tinybench": "^2.9.0",
- "tinyexec": "^0.3.2",
- "tinyglobby": "^0.2.14",
- "tinypool": "^1.1.1",
- "tinyrainbow": "^2.0.0",
- "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0",
- "vite-node": "3.2.4",
- "why-is-node-running": "^2.3.0"
- },
- "bin": {
- "vitest": "vitest.mjs"
- },
- "engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- },
- "peerDependencies": {
- "@edge-runtime/vm": "*",
- "@types/debug": "^4.1.12",
- "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
- "@vitest/browser": "3.2.4",
- "@vitest/ui": "3.2.4",
- "happy-dom": "*",
- "jsdom": "*"
- },
- "peerDependenciesMeta": {
- "@edge-runtime/vm": {
- "optional": true
- },
- "@types/debug": {
- "optional": true
- },
- "@types/node": {
- "optional": true
- },
- "@vitest/browser": {
- "optional": true
- },
- "@vitest/ui": {
- "optional": true
- },
- "happy-dom": {
- "optional": true
- },
- "jsdom": {
- "optional": true
- }
- }
- },
- "node_modules/vitest/node_modules/picomatch": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
- "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/web-streams-polyfill": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
- "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/whatwg-fetch": {
- "version": "3.6.20",
- "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
- "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
- "license": "MIT"
- },
- "node_modules/which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "which": "bin/which"
- }
- },
- "node_modules/why-is-node-running": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
- "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "siginfo": "^2.0.0",
- "stackback": "0.0.2"
- },
- "bin": {
- "why-is-node-running": "cli.js"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrap-ansi/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "license": "ISC"
- },
- "node_modules/ws": {
- "version": "8.20.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
- "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
- "node_modules/xlsx": {
- "version": "0.20.3",
- "resolved": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
- "integrity": "sha512-oLDq3jw7AcLqKWH2AhCpVTZl8mf6X2YReP+Neh0SJUzV/BdZYjth94tG5toiMB1PPrYtxOCfaoUCkvtuH+3AJA==",
- "license": "Apache-2.0",
- "bin": {
- "xlsx": "bin/xlsx.njs"
- },
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yaml": {
- "version": "2.8.3",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz",
- "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==",
- "license": "ISC",
- "bin": {
- "yaml": "bin.mjs"
- },
- "engines": {
- "node": ">= 14.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/eemeli"
- }
- },
- "node_modules/yargs": {
- "version": "16.2.0",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
- "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
- "license": "MIT",
- "dependencies": {
- "cliui": "^7.0.2",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.0",
- "y18n": "^5.0.5",
- "yargs-parser": "^20.2.2"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yargs-parser": {
- "version": "20.2.9",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
- "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yauzl": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
- "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
- "license": "MIT",
- "dependencies": {
- "buffer-crc32": "~0.2.3",
- "fd-slicer": "~1.1.0"
- }
- },
- "node_modules/yoctocolors": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz",
- "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/zod": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
- "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/colinhacks"
- }
- },
- "node_modules/zod-to-json-schema": {
- "version": "3.25.2",
- "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz",
- "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==",
- "license": "ISC",
- "peerDependencies": {
- "zod": "^3.25.28 || ^4"
- }
- },
- "packages/agent": {
- "name": "@mariozechner/pi-agent-core",
- "version": "0.67.5",
- "license": "MIT",
- "dependencies": {
- "@mariozechner/pi-ai": "^0.67.5"
- },
- "devDependencies": {
- "@types/node": "^24.3.0",
- "typescript": "^5.7.3",
- "vitest": "^3.2.4"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "packages/agent/node_modules/@types/node": {
- "version": "24.12.2",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz",
- "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "undici-types": "~7.16.0"
- }
- },
- "packages/agent/node_modules/undici-types": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
- "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
- "dev": true,
- "license": "MIT"
- },
- "packages/ai": {
- "name": "@mariozechner/pi-ai",
- "version": "0.67.5",
- "license": "MIT",
- "dependencies": {
- "@anthropic-ai/sdk": "^0.90.0",
- "@aws-sdk/client-bedrock-runtime": "^3.1030.0",
- "@google/genai": "^1.40.0",
- "@mistralai/mistralai": "1.14.1",
- "@sinclair/typebox": "^0.34.41",
- "ajv": "^8.17.1",
- "ajv-formats": "^3.0.1",
- "chalk": "^5.6.2",
- "openai": "6.26.0",
- "partial-json": "^0.1.7",
- "proxy-agent": "^6.5.0",
- "undici": "^7.19.1",
- "zod-to-json-schema": "^3.24.6"
- },
- "bin": {
- "pi-ai": "dist/cli.js"
- },
- "devDependencies": {
- "@types/node": "^24.3.0",
- "canvas": "^3.2.0",
- "vitest": "^3.2.4"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "packages/ai/node_modules/@types/node": {
- "version": "24.12.2",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz",
- "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "undici-types": "~7.16.0"
- }
- },
- "packages/ai/node_modules/undici-types": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
- "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
- "dev": true,
- "license": "MIT"
- },
- "packages/coding-agent": {
- "name": "@mariozechner/pi-coding-agent",
- "version": "0.67.5",
- "license": "MIT",
- "dependencies": {
- "@mariozechner/jiti": "^2.6.2",
- "@mariozechner/pi-agent-core": "^0.67.5",
- "@mariozechner/pi-ai": "^0.67.5",
- "@mariozechner/pi-tui": "^0.67.5",
- "@silvia-odwyer/photon-node": "^0.3.4",
- "ajv": "^8.17.1",
- "chalk": "^5.5.0",
- "cli-highlight": "^2.1.11",
- "diff": "^8.0.2",
- "extract-zip": "^2.0.1",
- "file-type": "^21.1.1",
- "glob": "^13.0.1",
- "hosted-git-info": "^9.0.2",
- "ignore": "^7.0.5",
- "marked": "^15.0.12",
- "minimatch": "^10.2.3",
- "proper-lockfile": "^4.1.2",
- "strip-ansi": "^7.1.0",
- "undici": "^7.19.1",
- "uuid": "^11.1.0",
- "yaml": "^2.8.2"
- },
- "bin": {
- "pi": "dist/cli.js"
- },
- "devDependencies": {
- "@types/diff": "^7.0.2",
- "@types/hosted-git-info": "^3.0.5",
- "@types/ms": "^2.1.0",
- "@types/node": "^24.3.0",
- "@types/proper-lockfile": "^4.1.4",
- "shx": "^0.4.0",
- "typescript": "^5.7.3",
- "vitest": "^3.2.4"
- },
- "engines": {
- "node": ">=20.6.0"
- },
- "optionalDependencies": {
- "@mariozechner/clipboard": "^0.3.2"
- }
- },
- "packages/coding-agent/examples/extensions/custom-provider-anthropic": {
- "name": "pi-extension-custom-provider-anthropic",
- "version": "1.18.5",
- "dependencies": {
- "@anthropic-ai/sdk": "^0.52.0"
- }
- },
- "packages/coding-agent/examples/extensions/custom-provider-gitlab-duo": {
- "name": "pi-extension-custom-provider-gitlab-duo",
- "version": "1.18.5"
- },
- "packages/coding-agent/examples/extensions/custom-provider-qwen-cli": {
- "name": "pi-extension-custom-provider-qwen-cli",
- "version": "1.17.5"
- },
- "packages/coding-agent/examples/extensions/with-deps": {
- "name": "pi-extension-with-deps",
- "version": "1.31.5",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "devDependencies": {
- "@types/ms": "^2.1.0"
- }
- },
- "packages/coding-agent/node_modules/@anthropic-ai/sdk": {
- "version": "0.52.0",
- "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.52.0.tgz",
- "integrity": "sha512-d4c+fg+xy9e46c8+YnrrgIQR45CZlAi7PwdzIfDXDM6ACxEZli1/fxhURsq30ZpMZy6LvSkr41jGq5aF5TD7rQ==",
- "license": "MIT",
- "bin": {
- "anthropic-ai-sdk": "bin/cli"
- }
- },
- "packages/coding-agent/node_modules/@types/node": {
- "version": "24.12.2",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz",
- "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "undici-types": "~7.16.0"
- }
- },
- "packages/coding-agent/node_modules/undici-types": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
- "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
- "dev": true,
- "license": "MIT"
- },
- "packages/mom": {
- "name": "@mariozechner/pi-mom",
- "version": "0.67.5",
- "license": "MIT",
- "dependencies": {
- "@anthropic-ai/sandbox-runtime": "^0.0.16",
- "@mariozechner/pi-agent-core": "^0.67.5",
- "@mariozechner/pi-ai": "^0.67.5",
- "@mariozechner/pi-coding-agent": "^0.67.5",
- "@sinclair/typebox": "^0.34.0",
- "@slack/socket-mode": "^2.0.0",
- "@slack/web-api": "^7.0.0",
- "chalk": "^5.6.2",
- "croner": "^9.1.0",
- "diff": "^8.0.2"
- },
- "bin": {
- "mom": "dist/main.js"
- },
- "devDependencies": {
- "@types/diff": "^7.0.2",
- "@types/node": "^24.3.0",
- "typescript": "^5.7.3"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "packages/mom/node_modules/@types/node": {
- "version": "24.12.2",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz",
- "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "undici-types": "~7.16.0"
- }
- },
- "packages/mom/node_modules/undici-types": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
- "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
- "dev": true,
- "license": "MIT"
- },
- "packages/pods": {
- "name": "@mariozechner/pi",
- "version": "0.67.5",
- "license": "MIT",
- "dependencies": {
- "@mariozechner/pi-agent-core": "^0.67.5",
- "chalk": "^5.5.0"
- },
- "bin": {
- "pi-pods": "dist/cli.js"
- },
- "devDependencies": {},
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "packages/tui": {
- "name": "@mariozechner/pi-tui",
- "version": "0.67.5",
- "license": "MIT",
- "dependencies": {
- "@types/mime-types": "^2.1.4",
- "chalk": "^5.5.0",
- "get-east-asian-width": "^1.3.0",
- "marked": "^15.0.12",
- "mime-types": "^3.0.1"
- },
- "devDependencies": {
- "@xterm/headless": "^5.5.0",
- "@xterm/xterm": "^5.5.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "optionalDependencies": {
- "koffi": "^2.9.0"
- }
- },
- "packages/tui/node_modules/mime-db": {
- "version": "1.54.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
- "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "packages/tui/node_modules/mime-types": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
- "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "^1.54.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "packages/web-ui": {
- "name": "@mariozechner/pi-web-ui",
- "version": "0.67.5",
- "license": "MIT",
- "dependencies": {
- "@lmstudio/sdk": "^1.5.0",
- "@mariozechner/pi-ai": "^0.67.5",
- "@mariozechner/pi-tui": "^0.67.5",
- "docx-preview": "^0.3.7",
- "jszip": "^3.10.1",
- "lucide": "^0.544.0",
- "ollama": "^0.6.0",
- "pdfjs-dist": "5.4.394",
- "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
- },
- "devDependencies": {
- "@mariozechner/mini-lit": "^0.2.0",
- "@tailwindcss/cli": "^4.0.0-beta.14",
- "concurrently": "^9.2.1",
- "typescript": "^5.7.3"
- },
- "peerDependencies": {
- "@mariozechner/mini-lit": "^0.2.0",
- "lit": "^3.3.1"
- }
- },
- "packages/web-ui/example": {
- "name": "pi-web-ui-example",
- "version": "1.55.5",
- "dependencies": {
- "@mariozechner/mini-lit": "^0.2.0",
- "@mariozechner/pi-ai": "file:../../ai",
- "@mariozechner/pi-web-ui": "file:../",
- "@tailwindcss/vite": "^4.1.17",
- "lit": "^3.3.1",
- "lucide": "^0.544.0"
- },
- "devDependencies": {
- "typescript": "^5.7.3",
- "vite": "^7.1.6"
- }
- }
- }
-}
diff --git a/pi-mono-reference/package.json b/pi-mono-reference/package.json
deleted file mode 100644
index 00d96414..00000000
--- a/pi-mono-reference/package.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "name": "pi-monorepo",
- "private": true,
- "type": "module",
- "workspaces": [
- "packages/*",
- "packages/web-ui/example",
- "packages/coding-agent/examples/extensions/with-deps",
- "packages/coding-agent/examples/extensions/custom-provider-anthropic",
- "packages/coding-agent/examples/extensions/custom-provider-gitlab-duo",
- "packages/coding-agent/examples/extensions/custom-provider-qwen-cli"
- ],
- "scripts": {
- "clean": "npm run clean --workspaces",
- "build": "cd packages/tui && npm run build && cd ../ai && npm run build && cd ../agent && npm run build && cd ../coding-agent && npm run build && cd ../mom && npm run build && cd ../web-ui && npm run build && cd ../pods && npm run build",
- "dev": "concurrently --names \"ai,agent,coding-agent,mom,web-ui,tui\" --prefix-colors \"cyan,yellow,red,white,green,magenta\" \"cd packages/ai && npm run dev\" \"cd packages/agent && npm run dev\" \"cd packages/coding-agent && npm run dev\" \"cd packages/mom && npm run dev\" \"cd packages/web-ui && npm run dev\" \"cd packages/tui && npm run dev\"",
- "dev:tsc": "concurrently --names \"ai,web-ui\" --prefix-colors \"cyan,green\" \"cd packages/ai && npm run dev:tsc\" \"cd packages/web-ui && npm run dev:tsc\"",
- "check": "biome check --write --error-on-warnings . && tsgo --noEmit && npm run check:browser-smoke && cd packages/web-ui && npm run check",
- "check:browser-smoke": "node scripts/check-browser-smoke.mjs",
- "profile:tui": "node scripts/profile-coding-agent-node.mjs --mode tui",
- "profile:rpc": "node scripts/profile-coding-agent-node.mjs --mode rpc",
- "test": "npm run test --workspaces --if-present",
- "version:patch": "npm version patch -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install",
- "version:minor": "npm version minor -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install",
- "version:major": "npm version major -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install",
- "version:set": "npm version -ws",
- "prepublishOnly": "npm run clean && npm run build && npm run check",
- "publish": "npm run prepublishOnly && npm publish -ws --access public",
- "publish:dry": "npm run prepublishOnly && npm publish -ws --access public --dry-run",
- "release:patch": "node scripts/release.mjs patch",
- "release:minor": "node scripts/release.mjs minor",
- "release:major": "node scripts/release.mjs major",
- "prepare": "husky"
- },
- "devDependencies": {
- "@biomejs/biome": "2.3.5",
- "@types/node": "^22.10.5",
- "@typescript/native-preview": "7.0.0-dev.20260120.1",
- "concurrently": "^9.2.1",
- "husky": "^9.1.7",
- "tsx": "^4.20.3",
- "typescript": "^5.9.2",
- "shx": "^0.4.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "version": "0.0.3",
- "dependencies": {
- "@mariozechner/jiti": "^2.6.5",
- "@mariozechner/pi-coding-agent": "^0.30.2",
- "get-east-asian-width": "^1.4.0"
- },
- "overrides": {
- "rimraf": "6.1.2",
- "gaxios": {
- "rimraf": "6.1.2"
- }
- }
-}
diff --git a/pi-mono-reference/packages/agent/package.json b/pi-mono-reference/packages/agent/package.json
deleted file mode 100644
index 9625f167..00000000
--- a/pi-mono-reference/packages/agent/package.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "name": "@mariozechner/pi-agent-core",
- "version": "0.67.5",
- "description": "General-purpose agent with transport abstraction, state management, and attachment support",
- "type": "module",
- "main": "./dist/index.js",
- "types": "./dist/index.d.ts",
- "files": [
- "dist",
- "README.md"
- ],
- "scripts": {
- "clean": "shx rm -rf dist",
- "build": "tsgo -p tsconfig.build.json",
- "dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput",
- "test": "vitest --run",
- "prepublishOnly": "npm run clean && npm run build"
- },
- "dependencies": {
- "@mariozechner/pi-ai": "^0.67.5"
- },
- "keywords": [
- "ai",
- "agent",
- "llm",
- "transport",
- "state-management"
- ],
- "author": "Mario Zechner",
- "license": "MIT",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/badlogic/pi-mono.git",
- "directory": "packages/agent"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "devDependencies": {
- "@types/node": "^24.3.0",
- "typescript": "^5.7.3",
- "vitest": "^3.2.4"
- }
-}
diff --git a/pi-mono-reference/packages/agent/src/agent-loop.ts b/pi-mono-reference/packages/agent/src/agent-loop.ts
deleted file mode 100644
index 586a1b7d..00000000
--- a/pi-mono-reference/packages/agent/src/agent-loop.ts
+++ /dev/null
@@ -1,631 +0,0 @@
-/**
- * Agent loop that works with AgentMessage throughout.
- * Transforms to Message[] only at the LLM call boundary.
- */
-
-import {
- type AssistantMessage,
- type Context,
- EventStream,
- streamSimple,
- type ToolResultMessage,
- validateToolArguments,
-} from "@mariozechner/pi-ai";
-import type {
- AgentContext,
- AgentEvent,
- AgentLoopConfig,
- AgentMessage,
- AgentTool,
- AgentToolCall,
- AgentToolResult,
- StreamFn,
-} from "./types.js";
-
-export type AgentEventSink = (event: AgentEvent) => Promise | void;
-
-/**
- * Start an agent loop with a new prompt message.
- * The prompt is added to the context and events are emitted for it.
- */
-export function agentLoop(
- prompts: AgentMessage[],
- context: AgentContext,
- config: AgentLoopConfig,
- signal?: AbortSignal,
- streamFn?: StreamFn,
-): EventStream {
- const stream = createAgentStream();
-
- void runAgentLoop(
- prompts,
- context,
- config,
- async (event) => {
- stream.push(event);
- },
- signal,
- streamFn,
- ).then((messages) => {
- stream.end(messages);
- });
-
- return stream;
-}
-
-/**
- * Continue an agent loop from the current context without adding a new message.
- * Used for retries - context already has user message or tool results.
- *
- * **Important:** The last message in context must convert to a `user` or `toolResult` message
- * via `convertToLlm`. If it doesn't, the LLM provider will reject the request.
- * This cannot be validated here since `convertToLlm` is only called once per turn.
- */
-export function agentLoopContinue(
- context: AgentContext,
- config: AgentLoopConfig,
- signal?: AbortSignal,
- streamFn?: StreamFn,
-): EventStream {
- if (context.messages.length === 0) {
- throw new Error("Cannot continue: no messages in context");
- }
-
- if (context.messages[context.messages.length - 1].role === "assistant") {
- throw new Error("Cannot continue from message role: assistant");
- }
-
- const stream = createAgentStream();
-
- void runAgentLoopContinue(
- context,
- config,
- async (event) => {
- stream.push(event);
- },
- signal,
- streamFn,
- ).then((messages) => {
- stream.end(messages);
- });
-
- return stream;
-}
-
-export async function runAgentLoop(
- prompts: AgentMessage[],
- context: AgentContext,
- config: AgentLoopConfig,
- emit: AgentEventSink,
- signal?: AbortSignal,
- streamFn?: StreamFn,
-): Promise {
- const newMessages: AgentMessage[] = [...prompts];
- const currentContext: AgentContext = {
- ...context,
- messages: [...context.messages, ...prompts],
- };
-
- await emit({ type: "agent_start" });
- await emit({ type: "turn_start" });
- for (const prompt of prompts) {
- await emit({ type: "message_start", message: prompt });
- await emit({ type: "message_end", message: prompt });
- }
-
- await runLoop(currentContext, newMessages, config, signal, emit, streamFn);
- return newMessages;
-}
-
-export async function runAgentLoopContinue(
- context: AgentContext,
- config: AgentLoopConfig,
- emit: AgentEventSink,
- signal?: AbortSignal,
- streamFn?: StreamFn,
-): Promise {
- if (context.messages.length === 0) {
- throw new Error("Cannot continue: no messages in context");
- }
-
- if (context.messages[context.messages.length - 1].role === "assistant") {
- throw new Error("Cannot continue from message role: assistant");
- }
-
- const newMessages: AgentMessage[] = [];
- const currentContext: AgentContext = { ...context };
-
- await emit({ type: "agent_start" });
- await emit({ type: "turn_start" });
-
- await runLoop(currentContext, newMessages, config, signal, emit, streamFn);
- return newMessages;
-}
-
-function createAgentStream(): EventStream {
- return new EventStream(
- (event: AgentEvent) => event.type === "agent_end",
- (event: AgentEvent) => (event.type === "agent_end" ? event.messages : []),
- );
-}
-
-/**
- * Main loop logic shared by agentLoop and agentLoopContinue.
- */
-async function runLoop(
- currentContext: AgentContext,
- newMessages: AgentMessage[],
- config: AgentLoopConfig,
- signal: AbortSignal | undefined,
- emit: AgentEventSink,
- streamFn?: StreamFn,
-): Promise {
- let firstTurn = true;
- // Check for steering messages at start (user may have typed while waiting)
- let pendingMessages: AgentMessage[] = (await config.getSteeringMessages?.()) || [];
-
- // Outer loop: continues when queued follow-up messages arrive after agent would stop
- while (true) {
- let hasMoreToolCalls = true;
-
- // Inner loop: process tool calls and steering messages
- while (hasMoreToolCalls || pendingMessages.length > 0) {
- if (!firstTurn) {
- await emit({ type: "turn_start" });
- } else {
- firstTurn = false;
- }
-
- // Process pending messages (inject before next assistant response)
- if (pendingMessages.length > 0) {
- for (const message of pendingMessages) {
- await emit({ type: "message_start", message });
- await emit({ type: "message_end", message });
- currentContext.messages.push(message);
- newMessages.push(message);
- }
- pendingMessages = [];
- }
-
- // Stream assistant response
- const message = await streamAssistantResponse(currentContext, config, signal, emit, streamFn);
- newMessages.push(message);
-
- if (message.stopReason === "error" || message.stopReason === "aborted") {
- await emit({ type: "turn_end", message, toolResults: [] });
- await emit({ type: "agent_end", messages: newMessages });
- return;
- }
-
- // Check for tool calls
- const toolCalls = message.content.filter((c) => c.type === "toolCall");
- hasMoreToolCalls = toolCalls.length > 0;
-
- const toolResults: ToolResultMessage[] = [];
- if (hasMoreToolCalls) {
- toolResults.push(...(await executeToolCalls(currentContext, message, config, signal, emit)));
-
- for (const result of toolResults) {
- currentContext.messages.push(result);
- newMessages.push(result);
- }
- }
-
- await emit({ type: "turn_end", message, toolResults });
-
- pendingMessages = (await config.getSteeringMessages?.()) || [];
- }
-
- // Agent would stop here. Check for follow-up messages.
- const followUpMessages = (await config.getFollowUpMessages?.()) || [];
- if (followUpMessages.length > 0) {
- // Set as pending so inner loop processes them
- pendingMessages = followUpMessages;
- continue;
- }
-
- // No more messages, exit
- break;
- }
-
- await emit({ type: "agent_end", messages: newMessages });
-}
-
-/**
- * Stream an assistant response from the LLM.
- * This is where AgentMessage[] gets transformed to Message[] for the LLM.
- */
-async function streamAssistantResponse(
- context: AgentContext,
- config: AgentLoopConfig,
- signal: AbortSignal | undefined,
- emit: AgentEventSink,
- streamFn?: StreamFn,
-): Promise {
- // Apply context transform if configured (AgentMessage[] → AgentMessage[])
- let messages = context.messages;
- if (config.transformContext) {
- messages = await config.transformContext(messages, signal);
- }
-
- // Convert to LLM-compatible messages (AgentMessage[] → Message[])
- const llmMessages = await config.convertToLlm(messages);
-
- // Build LLM context
- const llmContext: Context = {
- systemPrompt: context.systemPrompt,
- messages: llmMessages,
- tools: context.tools,
- };
-
- const streamFunction = streamFn || streamSimple;
-
- // Resolve API key (important for expiring tokens)
- const resolvedApiKey =
- (config.getApiKey ? await config.getApiKey(config.model.provider) : undefined) || config.apiKey;
-
- const response = await streamFunction(config.model, llmContext, {
- ...config,
- apiKey: resolvedApiKey,
- signal,
- });
-
- let partialMessage: AssistantMessage | null = null;
- let addedPartial = false;
-
- for await (const event of response) {
- switch (event.type) {
- case "start":
- partialMessage = event.partial;
- context.messages.push(partialMessage);
- addedPartial = true;
- await emit({ type: "message_start", message: { ...partialMessage } });
- break;
-
- case "text_start":
- case "text_delta":
- case "text_end":
- case "thinking_start":
- case "thinking_delta":
- case "thinking_end":
- case "toolcall_start":
- case "toolcall_delta":
- case "toolcall_end":
- if (partialMessage) {
- partialMessage = event.partial;
- context.messages[context.messages.length - 1] = partialMessage;
- await emit({
- type: "message_update",
- assistantMessageEvent: event,
- message: { ...partialMessage },
- });
- }
- break;
-
- case "done":
- case "error": {
- const finalMessage = await response.result();
- if (addedPartial) {
- context.messages[context.messages.length - 1] = finalMessage;
- } else {
- context.messages.push(finalMessage);
- }
- if (!addedPartial) {
- await emit({ type: "message_start", message: { ...finalMessage } });
- }
- await emit({ type: "message_end", message: finalMessage });
- return finalMessage;
- }
- }
- }
-
- const finalMessage = await response.result();
- if (addedPartial) {
- context.messages[context.messages.length - 1] = finalMessage;
- } else {
- context.messages.push(finalMessage);
- await emit({ type: "message_start", message: { ...finalMessage } });
- }
- await emit({ type: "message_end", message: finalMessage });
- return finalMessage;
-}
-
-/**
- * Execute tool calls from an assistant message.
- */
-async function executeToolCalls(
- currentContext: AgentContext,
- assistantMessage: AssistantMessage,
- config: AgentLoopConfig,
- signal: AbortSignal | undefined,
- emit: AgentEventSink,
-): Promise {
- const toolCalls = assistantMessage.content.filter((c) => c.type === "toolCall");
- if (config.toolExecution === "sequential") {
- return executeToolCallsSequential(currentContext, assistantMessage, toolCalls, config, signal, emit);
- }
- return executeToolCallsParallel(currentContext, assistantMessage, toolCalls, config, signal, emit);
-}
-
-async function executeToolCallsSequential(
- currentContext: AgentContext,
- assistantMessage: AssistantMessage,
- toolCalls: AgentToolCall[],
- config: AgentLoopConfig,
- signal: AbortSignal | undefined,
- emit: AgentEventSink,
-): Promise {
- const results: ToolResultMessage[] = [];
-
- for (const toolCall of toolCalls) {
- await emit({
- type: "tool_execution_start",
- toolCallId: toolCall.id,
- toolName: toolCall.name,
- args: toolCall.arguments,
- });
-
- const preparation = await prepareToolCall(currentContext, assistantMessage, toolCall, config, signal);
- if (preparation.kind === "immediate") {
- results.push(await emitToolCallOutcome(toolCall, preparation.result, preparation.isError, emit));
- } else {
- const executed = await executePreparedToolCall(preparation, signal, emit);
- results.push(
- await finalizeExecutedToolCall(
- currentContext,
- assistantMessage,
- preparation,
- executed,
- config,
- signal,
- emit,
- ),
- );
- }
- }
-
- return results;
-}
-
-async function executeToolCallsParallel(
- currentContext: AgentContext,
- assistantMessage: AssistantMessage,
- toolCalls: AgentToolCall[],
- config: AgentLoopConfig,
- signal: AbortSignal | undefined,
- emit: AgentEventSink,
-): Promise {
- const results: ToolResultMessage[] = [];
- const runnableCalls: PreparedToolCall[] = [];
-
- for (const toolCall of toolCalls) {
- await emit({
- type: "tool_execution_start",
- toolCallId: toolCall.id,
- toolName: toolCall.name,
- args: toolCall.arguments,
- });
-
- const preparation = await prepareToolCall(currentContext, assistantMessage, toolCall, config, signal);
- if (preparation.kind === "immediate") {
- results.push(await emitToolCallOutcome(toolCall, preparation.result, preparation.isError, emit));
- } else {
- runnableCalls.push(preparation);
- }
- }
-
- const runningCalls = runnableCalls.map((prepared) => ({
- prepared,
- execution: executePreparedToolCall(prepared, signal, emit),
- }));
-
- for (const running of runningCalls) {
- const executed = await running.execution;
- results.push(
- await finalizeExecutedToolCall(
- currentContext,
- assistantMessage,
- running.prepared,
- executed,
- config,
- signal,
- emit,
- ),
- );
- }
-
- return results;
-}
-
-type PreparedToolCall = {
- kind: "prepared";
- toolCall: AgentToolCall;
- tool: AgentTool;
- args: unknown;
-};
-
-type ImmediateToolCallOutcome = {
- kind: "immediate";
- result: AgentToolResult;
- isError: boolean;
-};
-
-type ExecutedToolCallOutcome = {
- result: AgentToolResult;
- isError: boolean;
-};
-
-function prepareToolCallArguments(tool: AgentTool, toolCall: AgentToolCall): AgentToolCall {
- if (!tool.prepareArguments) {
- return toolCall;
- }
- const preparedArguments = tool.prepareArguments(toolCall.arguments);
- if (preparedArguments === toolCall.arguments) {
- return toolCall;
- }
- return {
- ...toolCall,
- arguments: preparedArguments as Record,
- };
-}
-
-async function prepareToolCall(
- currentContext: AgentContext,
- assistantMessage: AssistantMessage,
- toolCall: AgentToolCall,
- config: AgentLoopConfig,
- signal: AbortSignal | undefined,
-): Promise {
- const tool = currentContext.tools?.find((t) => t.name === toolCall.name);
- if (!tool) {
- return {
- kind: "immediate",
- result: createErrorToolResult(`Tool ${toolCall.name} not found`),
- isError: true,
- };
- }
-
- try {
- const preparedToolCall = prepareToolCallArguments(tool, toolCall);
- const validatedArgs = validateToolArguments(tool, preparedToolCall);
- if (config.beforeToolCall) {
- const beforeResult = await config.beforeToolCall(
- {
- assistantMessage,
- toolCall,
- args: validatedArgs,
- context: currentContext,
- },
- signal,
- );
- if (beforeResult?.block) {
- return {
- kind: "immediate",
- result: createErrorToolResult(beforeResult.reason || "Tool execution was blocked"),
- isError: true,
- };
- }
- }
- return {
- kind: "prepared",
- toolCall,
- tool,
- args: validatedArgs,
- };
- } catch (error) {
- return {
- kind: "immediate",
- result: createErrorToolResult(error instanceof Error ? error.message : String(error)),
- isError: true,
- };
- }
-}
-
-async function executePreparedToolCall(
- prepared: PreparedToolCall,
- signal: AbortSignal | undefined,
- emit: AgentEventSink,
-): Promise {
- const updateEvents: Promise[] = [];
-
- try {
- const result = await prepared.tool.execute(
- prepared.toolCall.id,
- prepared.args as never,
- signal,
- (partialResult) => {
- updateEvents.push(
- Promise.resolve(
- emit({
- type: "tool_execution_update",
- toolCallId: prepared.toolCall.id,
- toolName: prepared.toolCall.name,
- args: prepared.toolCall.arguments,
- partialResult,
- }),
- ),
- );
- },
- );
- await Promise.all(updateEvents);
- return { result, isError: false };
- } catch (error) {
- await Promise.all(updateEvents);
- return {
- result: createErrorToolResult(error instanceof Error ? error.message : String(error)),
- isError: true,
- };
- }
-}
-
-async function finalizeExecutedToolCall(
- currentContext: AgentContext,
- assistantMessage: AssistantMessage,
- prepared: PreparedToolCall,
- executed: ExecutedToolCallOutcome,
- config: AgentLoopConfig,
- signal: AbortSignal | undefined,
- emit: AgentEventSink,
-): Promise {
- let result = executed.result;
- let isError = executed.isError;
-
- if (config.afterToolCall) {
- const afterResult = await config.afterToolCall(
- {
- assistantMessage,
- toolCall: prepared.toolCall,
- args: prepared.args,
- result,
- isError,
- context: currentContext,
- },
- signal,
- );
- if (afterResult) {
- result = {
- content: afterResult.content ?? result.content,
- details: afterResult.details ?? result.details,
- };
- isError = afterResult.isError ?? isError;
- }
- }
-
- return await emitToolCallOutcome(prepared.toolCall, result, isError, emit);
-}
-
-function createErrorToolResult(message: string): AgentToolResult {
- return {
- content: [{ type: "text", text: message }],
- details: {},
- };
-}
-
-async function emitToolCallOutcome(
- toolCall: AgentToolCall,
- result: AgentToolResult,
- isError: boolean,
- emit: AgentEventSink,
-): Promise {
- await emit({
- type: "tool_execution_end",
- toolCallId: toolCall.id,
- toolName: toolCall.name,
- result,
- isError,
- });
-
- const toolResultMessage: ToolResultMessage = {
- role: "toolResult",
- toolCallId: toolCall.id,
- toolName: toolCall.name,
- content: result.content,
- details: result.details,
- isError,
- timestamp: Date.now(),
- };
-
- await emit({ type: "message_start", message: toolResultMessage });
- await emit({ type: "message_end", message: toolResultMessage });
- return toolResultMessage;
-}
diff --git a/pi-mono-reference/packages/agent/src/agent.ts b/pi-mono-reference/packages/agent/src/agent.ts
deleted file mode 100644
index b7d69546..00000000
--- a/pi-mono-reference/packages/agent/src/agent.ts
+++ /dev/null
@@ -1,539 +0,0 @@
-import {
- type ImageContent,
- type Message,
- type Model,
- type SimpleStreamOptions,
- streamSimple,
- type TextContent,
- type ThinkingBudgets,
- type Transport,
-} from "@mariozechner/pi-ai";
-import { runAgentLoop, runAgentLoopContinue } from "./agent-loop.js";
-import type {
- AfterToolCallContext,
- AfterToolCallResult,
- AgentContext,
- AgentEvent,
- AgentLoopConfig,
- AgentMessage,
- AgentState,
- AgentTool,
- BeforeToolCallContext,
- BeforeToolCallResult,
- StreamFn,
- ToolExecutionMode,
-} from "./types.js";
-
-function defaultConvertToLlm(messages: AgentMessage[]): Message[] {
- return messages.filter(
- (message) => message.role === "user" || message.role === "assistant" || message.role === "toolResult",
- );
-}
-
-const EMPTY_USAGE = {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
-};
-
-const DEFAULT_MODEL = {
- id: "unknown",
- name: "unknown",
- api: "unknown",
- provider: "unknown",
- baseUrl: "",
- reasoning: false,
- input: [],
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
- contextWindow: 0,
- maxTokens: 0,
-} satisfies Model;
-
-type QueueMode = "all" | "one-at-a-time";
-
-type MutableAgentState = Omit & {
- isStreaming: boolean;
- streamingMessage?: AgentMessage;
- pendingToolCalls: Set;
- errorMessage?: string;
-};
-
-function createMutableAgentState(
- initialState?: Partial>,
-): MutableAgentState {
- let tools = initialState?.tools?.slice() ?? [];
- let messages = initialState?.messages?.slice() ?? [];
-
- return {
- systemPrompt: initialState?.systemPrompt ?? "",
- model: initialState?.model ?? DEFAULT_MODEL,
- thinkingLevel: initialState?.thinkingLevel ?? "off",
- get tools() {
- return tools;
- },
- set tools(nextTools: AgentTool[]) {
- tools = nextTools.slice();
- },
- get messages() {
- return messages;
- },
- set messages(nextMessages: AgentMessage[]) {
- messages = nextMessages.slice();
- },
- isStreaming: false,
- streamingMessage: undefined,
- pendingToolCalls: new Set(),
- errorMessage: undefined,
- };
-}
-
-/** Options for constructing an {@link Agent}. */
-export interface AgentOptions {
- initialState?: Partial>;
- convertToLlm?: (messages: AgentMessage[]) => Message[] | Promise;
- transformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise;
- streamFn?: StreamFn;
- getApiKey?: (provider: string) => Promise | string | undefined;
- onPayload?: SimpleStreamOptions["onPayload"];
- beforeToolCall?: (context: BeforeToolCallContext, signal?: AbortSignal) => Promise;
- afterToolCall?: (context: AfterToolCallContext, signal?: AbortSignal) => Promise;
- steeringMode?: QueueMode;
- followUpMode?: QueueMode;
- sessionId?: string;
- thinkingBudgets?: ThinkingBudgets;
- transport?: Transport;
- maxRetryDelayMs?: number;
- toolExecution?: ToolExecutionMode;
-}
-
-class PendingMessageQueue {
- private messages: AgentMessage[] = [];
-
- constructor(public mode: QueueMode) {}
-
- enqueue(message: AgentMessage): void {
- this.messages.push(message);
- }
-
- hasItems(): boolean {
- return this.messages.length > 0;
- }
-
- drain(): AgentMessage[] {
- if (this.mode === "all") {
- const drained = this.messages.slice();
- this.messages = [];
- return drained;
- }
-
- const first = this.messages[0];
- if (!first) {
- return [];
- }
- this.messages = this.messages.slice(1);
- return [first];
- }
-
- clear(): void {
- this.messages = [];
- }
-}
-
-type ActiveRun = {
- promise: Promise;
- resolve: () => void;
- abortController: AbortController;
-};
-
-/**
- * Stateful wrapper around the low-level agent loop.
- *
- * `Agent` owns the current transcript, emits lifecycle events, executes tools,
- * and exposes queueing APIs for steering and follow-up messages.
- */
-export class Agent {
- private _state: MutableAgentState;
- private readonly listeners = new Set<(event: AgentEvent, signal: AbortSignal) => Promise | void>();
- private readonly steeringQueue: PendingMessageQueue;
- private readonly followUpQueue: PendingMessageQueue;
-
- public convertToLlm: (messages: AgentMessage[]) => Message[] | Promise;
- public transformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise;
- public streamFn: StreamFn;
- public getApiKey?: (provider: string) => Promise | string | undefined;
- public onPayload?: SimpleStreamOptions["onPayload"];
- public beforeToolCall?: (
- context: BeforeToolCallContext,
- signal?: AbortSignal,
- ) => Promise;
- public afterToolCall?: (
- context: AfterToolCallContext,
- signal?: AbortSignal,
- ) => Promise;
- private activeRun?: ActiveRun;
- /** Session identifier forwarded to providers for cache-aware backends. */
- public sessionId?: string;
- /** Optional per-level thinking token budgets forwarded to the stream function. */
- public thinkingBudgets?: ThinkingBudgets;
- /** Preferred transport forwarded to the stream function. */
- public transport: Transport;
- /** Optional cap for provider-requested retry delays. */
- public maxRetryDelayMs?: number;
- /** Tool execution strategy for assistant messages that contain multiple tool calls. */
- public toolExecution: ToolExecutionMode;
-
- constructor(options: AgentOptions = {}) {
- this._state = createMutableAgentState(options.initialState);
- this.convertToLlm = options.convertToLlm ?? defaultConvertToLlm;
- this.transformContext = options.transformContext;
- this.streamFn = options.streamFn ?? streamSimple;
- this.getApiKey = options.getApiKey;
- this.onPayload = options.onPayload;
- this.beforeToolCall = options.beforeToolCall;
- this.afterToolCall = options.afterToolCall;
- this.steeringQueue = new PendingMessageQueue(options.steeringMode ?? "one-at-a-time");
- this.followUpQueue = new PendingMessageQueue(options.followUpMode ?? "one-at-a-time");
- this.sessionId = options.sessionId;
- this.thinkingBudgets = options.thinkingBudgets;
- this.transport = options.transport ?? "sse";
- this.maxRetryDelayMs = options.maxRetryDelayMs;
- this.toolExecution = options.toolExecution ?? "parallel";
- }
-
- /**
- * Subscribe to agent lifecycle events.
- *
- * Listener promises are awaited in subscription order and are included in
- * the current run's settlement. Listeners also receive the active abort
- * signal for the current run.
- *
- * `agent_end` is the final emitted event for a run, but the agent does not
- * become idle until all awaited listeners for that event have settled.
- */
- subscribe(listener: (event: AgentEvent, signal: AbortSignal) => Promise | void): () => void {
- this.listeners.add(listener);
- return () => this.listeners.delete(listener);
- }
-
- /**
- * Current agent state.
- *
- * Assigning `state.tools` or `state.messages` copies the provided top-level array.
- */
- get state(): AgentState {
- return this._state;
- }
-
- /** Controls how queued steering messages are drained. */
- set steeringMode(mode: QueueMode) {
- this.steeringQueue.mode = mode;
- }
-
- get steeringMode(): QueueMode {
- return this.steeringQueue.mode;
- }
-
- /** Controls how queued follow-up messages are drained. */
- set followUpMode(mode: QueueMode) {
- this.followUpQueue.mode = mode;
- }
-
- get followUpMode(): QueueMode {
- return this.followUpQueue.mode;
- }
-
- /** Queue a message to be injected after the current assistant turn finishes. */
- steer(message: AgentMessage): void {
- this.steeringQueue.enqueue(message);
- }
-
- /** Queue a message to run only after the agent would otherwise stop. */
- followUp(message: AgentMessage): void {
- this.followUpQueue.enqueue(message);
- }
-
- /** Remove all queued steering messages. */
- clearSteeringQueue(): void {
- this.steeringQueue.clear();
- }
-
- /** Remove all queued follow-up messages. */
- clearFollowUpQueue(): void {
- this.followUpQueue.clear();
- }
-
- /** Remove all queued steering and follow-up messages. */
- clearAllQueues(): void {
- this.clearSteeringQueue();
- this.clearFollowUpQueue();
- }
-
- /** Returns true when either queue still contains pending messages. */
- hasQueuedMessages(): boolean {
- return this.steeringQueue.hasItems() || this.followUpQueue.hasItems();
- }
-
- /** Active abort signal for the current run, if any. */
- get signal(): AbortSignal | undefined {
- return this.activeRun?.abortController.signal;
- }
-
- /** Abort the current run, if one is active. */
- abort(): void {
- this.activeRun?.abortController.abort();
- }
-
- /**
- * Resolve when the current run and all awaited event listeners have finished.
- *
- * This resolves after `agent_end` listeners settle.
- */
- waitForIdle(): Promise {
- return this.activeRun?.promise ?? Promise.resolve();
- }
-
- /** Clear transcript state, runtime state, and queued messages. */
- reset(): void {
- this._state.messages = [];
- this._state.isStreaming = false;
- this._state.streamingMessage = undefined;
- this._state.pendingToolCalls = new Set();
- this._state.errorMessage = undefined;
- this.clearFollowUpQueue();
- this.clearSteeringQueue();
- }
-
- /** Start a new prompt from text, a single message, or a batch of messages. */
- async prompt(message: AgentMessage | AgentMessage[]): Promise;
- async prompt(input: string, images?: ImageContent[]): Promise;
- async prompt(input: string | AgentMessage | AgentMessage[], images?: ImageContent[]): Promise {
- if (this.activeRun) {
- throw new Error(
- "Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.",
- );
- }
- const messages = this.normalizePromptInput(input, images);
- await this.runPromptMessages(messages);
- }
-
- /** Continue from the current transcript. The last message must be a user or tool-result message. */
- async continue(): Promise {
- if (this.activeRun) {
- throw new Error("Agent is already processing. Wait for completion before continuing.");
- }
-
- const lastMessage = this._state.messages[this._state.messages.length - 1];
- if (!lastMessage) {
- throw new Error("No messages to continue from");
- }
-
- if (lastMessage.role === "assistant") {
- const queuedSteering = this.steeringQueue.drain();
- if (queuedSteering.length > 0) {
- await this.runPromptMessages(queuedSteering, { skipInitialSteeringPoll: true });
- return;
- }
-
- const queuedFollowUps = this.followUpQueue.drain();
- if (queuedFollowUps.length > 0) {
- await this.runPromptMessages(queuedFollowUps);
- return;
- }
-
- throw new Error("Cannot continue from message role: assistant");
- }
-
- await this.runContinuation();
- }
-
- private normalizePromptInput(
- input: string | AgentMessage | AgentMessage[],
- images?: ImageContent[],
- ): AgentMessage[] {
- if (Array.isArray(input)) {
- return input;
- }
-
- if (typeof input !== "string") {
- return [input];
- }
-
- const content: Array = [{ type: "text", text: input }];
- if (images && images.length > 0) {
- content.push(...images);
- }
- return [{ role: "user", content, timestamp: Date.now() }];
- }
-
- private async runPromptMessages(
- messages: AgentMessage[],
- options: { skipInitialSteeringPoll?: boolean } = {},
- ): Promise {
- await this.runWithLifecycle(async (signal) => {
- await runAgentLoop(
- messages,
- this.createContextSnapshot(),
- this.createLoopConfig(options),
- (event) => this.processEvents(event),
- signal,
- this.streamFn,
- );
- });
- }
-
- private async runContinuation(): Promise {
- await this.runWithLifecycle(async (signal) => {
- await runAgentLoopContinue(
- this.createContextSnapshot(),
- this.createLoopConfig(),
- (event) => this.processEvents(event),
- signal,
- this.streamFn,
- );
- });
- }
-
- private createContextSnapshot(): AgentContext {
- return {
- systemPrompt: this._state.systemPrompt,
- messages: this._state.messages.slice(),
- tools: this._state.tools.slice(),
- };
- }
-
- private createLoopConfig(options: { skipInitialSteeringPoll?: boolean } = {}): AgentLoopConfig {
- let skipInitialSteeringPoll = options.skipInitialSteeringPoll === true;
- return {
- model: this._state.model,
- reasoning: this._state.thinkingLevel === "off" ? undefined : this._state.thinkingLevel,
- sessionId: this.sessionId,
- onPayload: this.onPayload,
- transport: this.transport,
- thinkingBudgets: this.thinkingBudgets,
- maxRetryDelayMs: this.maxRetryDelayMs,
- toolExecution: this.toolExecution,
- beforeToolCall: this.beforeToolCall,
- afterToolCall: this.afterToolCall,
- convertToLlm: this.convertToLlm,
- transformContext: this.transformContext,
- getApiKey: this.getApiKey,
- getSteeringMessages: async () => {
- if (skipInitialSteeringPoll) {
- skipInitialSteeringPoll = false;
- return [];
- }
- return this.steeringQueue.drain();
- },
- getFollowUpMessages: async () => this.followUpQueue.drain(),
- };
- }
-
- private async runWithLifecycle(executor: (signal: AbortSignal) => Promise): Promise {
- if (this.activeRun) {
- throw new Error("Agent is already processing.");
- }
-
- const abortController = new AbortController();
- let resolvePromise = () => {};
- const promise = new Promise((resolve) => {
- resolvePromise = resolve;
- });
- this.activeRun = { promise, resolve: resolvePromise, abortController };
-
- this._state.isStreaming = true;
- this._state.streamingMessage = undefined;
- this._state.errorMessage = undefined;
-
- try {
- await executor(abortController.signal);
- } catch (error) {
- await this.handleRunFailure(error, abortController.signal.aborted);
- } finally {
- this.finishRun();
- }
- }
-
- private async handleRunFailure(error: unknown, aborted: boolean): Promise {
- const failureMessage = {
- role: "assistant",
- content: [{ type: "text", text: "" }],
- api: this._state.model.api,
- provider: this._state.model.provider,
- model: this._state.model.id,
- usage: EMPTY_USAGE,
- stopReason: aborted ? "aborted" : "error",
- errorMessage: error instanceof Error ? error.message : String(error),
- timestamp: Date.now(),
- } satisfies AgentMessage;
- this._state.messages.push(failureMessage);
- this._state.errorMessage = failureMessage.errorMessage;
- await this.processEvents({ type: "agent_end", messages: [failureMessage] });
- }
-
- private finishRun(): void {
- this._state.isStreaming = false;
- this._state.streamingMessage = undefined;
- this._state.pendingToolCalls = new Set();
- this.activeRun?.resolve();
- this.activeRun = undefined;
- }
-
- /**
- * Reduce internal state for a loop event, then await listeners.
- *
- * `agent_end` only means no further loop events will be emitted. The run is
- * considered idle later, after all awaited listeners for `agent_end` finish
- * and `finishRun()` clears runtime-owned state.
- */
- private async processEvents(event: AgentEvent): Promise {
- switch (event.type) {
- case "message_start":
- this._state.streamingMessage = event.message;
- break;
-
- case "message_update":
- this._state.streamingMessage = event.message;
- break;
-
- case "message_end":
- this._state.streamingMessage = undefined;
- this._state.messages.push(event.message);
- break;
-
- case "tool_execution_start": {
- const pendingToolCalls = new Set(this._state.pendingToolCalls);
- pendingToolCalls.add(event.toolCallId);
- this._state.pendingToolCalls = pendingToolCalls;
- break;
- }
-
- case "tool_execution_end": {
- const pendingToolCalls = new Set(this._state.pendingToolCalls);
- pendingToolCalls.delete(event.toolCallId);
- this._state.pendingToolCalls = pendingToolCalls;
- break;
- }
-
- case "turn_end":
- if (event.message.role === "assistant" && event.message.errorMessage) {
- this._state.errorMessage = event.message.errorMessage;
- }
- break;
-
- case "agent_end":
- this._state.streamingMessage = undefined;
- break;
- }
-
- const signal = this.activeRun?.abortController.signal;
- if (!signal) {
- throw new Error("Agent listener invoked outside active run");
- }
- for (const listener of this.listeners) {
- await listener(event, signal);
- }
- }
-}
diff --git a/pi-mono-reference/packages/agent/src/index.ts b/pi-mono-reference/packages/agent/src/index.ts
deleted file mode 100644
index d8ed5b8e..00000000
--- a/pi-mono-reference/packages/agent/src/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// Core Agent
-export * from "./agent.js";
-// Loop functions
-export * from "./agent-loop.js";
-// Proxy utilities
-export * from "./proxy.js";
-// Types
-export * from "./types.js";
diff --git a/pi-mono-reference/packages/agent/src/proxy.ts b/pi-mono-reference/packages/agent/src/proxy.ts
deleted file mode 100644
index dfa72c73..00000000
--- a/pi-mono-reference/packages/agent/src/proxy.ts
+++ /dev/null
@@ -1,340 +0,0 @@
-/**
- * Proxy stream function for apps that route LLM calls through a server.
- * The server manages auth and proxies requests to LLM providers.
- */
-
-// Internal import for JSON parsing utility
-import {
- type AssistantMessage,
- type AssistantMessageEvent,
- type Context,
- EventStream,
- type Model,
- parseStreamingJson,
- type SimpleStreamOptions,
- type StopReason,
- type ToolCall,
-} from "@mariozechner/pi-ai";
-
-// Create stream class matching ProxyMessageEventStream
-class ProxyMessageEventStream extends EventStream {
- constructor() {
- super(
- (event) => event.type === "done" || event.type === "error",
- (event) => {
- if (event.type === "done") return event.message;
- if (event.type === "error") return event.error;
- throw new Error("Unexpected event type");
- },
- );
- }
-}
-
-/**
- * Proxy event types - server sends these with partial field stripped to reduce bandwidth.
- */
-export type ProxyAssistantMessageEvent =
- | { type: "start" }
- | { type: "text_start"; contentIndex: number }
- | { type: "text_delta"; contentIndex: number; delta: string }
- | { type: "text_end"; contentIndex: number; contentSignature?: string }
- | { type: "thinking_start"; contentIndex: number }
- | { type: "thinking_delta"; contentIndex: number; delta: string }
- | { type: "thinking_end"; contentIndex: number; contentSignature?: string }
- | { type: "toolcall_start"; contentIndex: number; id: string; toolName: string }
- | { type: "toolcall_delta"; contentIndex: number; delta: string }
- | { type: "toolcall_end"; contentIndex: number }
- | {
- type: "done";
- reason: Extract;
- usage: AssistantMessage["usage"];
- }
- | {
- type: "error";
- reason: Extract;
- errorMessage?: string;
- usage: AssistantMessage["usage"];
- };
-
-export interface ProxyStreamOptions extends SimpleStreamOptions {
- /** Auth token for the proxy server */
- authToken: string;
- /** Proxy server URL (e.g., "https://genai.example.com") */
- proxyUrl: string;
-}
-
-/**
- * Stream function that proxies through a server instead of calling LLM providers directly.
- * The server strips the partial field from delta events to reduce bandwidth.
- * We reconstruct the partial message client-side.
- *
- * Use this as the `streamFn` option when creating an Agent that needs to go through a proxy.
- *
- * @example
- * ```typescript
- * const agent = new Agent({
- * streamFn: (model, context, options) =>
- * streamProxy(model, context, {
- * ...options,
- * authToken: await getAuthToken(),
- * proxyUrl: "https://genai.example.com",
- * }),
- * });
- * ```
- */
-export function streamProxy(model: Model, context: Context, options: ProxyStreamOptions): ProxyMessageEventStream {
- const stream = new ProxyMessageEventStream();
-
- (async () => {
- // Initialize the partial message that we'll build up from events
- const partial: AssistantMessage = {
- role: "assistant",
- stopReason: "stop",
- content: [],
- api: model.api,
- provider: model.provider,
- model: model.id,
- usage: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- timestamp: Date.now(),
- };
-
- let reader: ReadableStreamDefaultReader | undefined;
-
- const abortHandler = () => {
- if (reader) {
- reader.cancel("Request aborted by user").catch(() => {});
- }
- };
-
- if (options.signal) {
- options.signal.addEventListener("abort", abortHandler);
- }
-
- try {
- const response = await fetch(`${options.proxyUrl}/api/stream`, {
- method: "POST",
- headers: {
- Authorization: `Bearer ${options.authToken}`,
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- model,
- context,
- options: {
- temperature: options.temperature,
- maxTokens: options.maxTokens,
- reasoning: options.reasoning,
- },
- }),
- signal: options.signal,
- });
-
- if (!response.ok) {
- let errorMessage = `Proxy error: ${response.status} ${response.statusText}`;
- try {
- const errorData = (await response.json()) as { error?: string };
- if (errorData.error) {
- errorMessage = `Proxy error: ${errorData.error}`;
- }
- } catch {
- // Couldn't parse error response
- }
- throw new Error(errorMessage);
- }
-
- reader = response.body!.getReader();
- const decoder = new TextDecoder();
- let buffer = "";
-
- while (true) {
- const { done, value } = await reader.read();
- if (done) break;
-
- if (options.signal?.aborted) {
- throw new Error("Request aborted by user");
- }
-
- buffer += decoder.decode(value, { stream: true });
- const lines = buffer.split("\n");
- buffer = lines.pop() || "";
-
- for (const line of lines) {
- if (line.startsWith("data: ")) {
- const data = line.slice(6).trim();
- if (data) {
- const proxyEvent = JSON.parse(data) as ProxyAssistantMessageEvent;
- const event = processProxyEvent(proxyEvent, partial);
- if (event) {
- stream.push(event);
- }
- }
- }
- }
- }
-
- if (options.signal?.aborted) {
- throw new Error("Request aborted by user");
- }
-
- stream.end();
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
- const reason = options.signal?.aborted ? "aborted" : "error";
- partial.stopReason = reason;
- partial.errorMessage = errorMessage;
- stream.push({
- type: "error",
- reason,
- error: partial,
- });
- stream.end();
- } finally {
- if (options.signal) {
- options.signal.removeEventListener("abort", abortHandler);
- }
- }
- })();
-
- return stream;
-}
-
-/**
- * Process a proxy event and update the partial message.
- */
-function processProxyEvent(
- proxyEvent: ProxyAssistantMessageEvent,
- partial: AssistantMessage,
-): AssistantMessageEvent | undefined {
- switch (proxyEvent.type) {
- case "start":
- return { type: "start", partial };
-
- case "text_start":
- partial.content[proxyEvent.contentIndex] = { type: "text", text: "" };
- return { type: "text_start", contentIndex: proxyEvent.contentIndex, partial };
-
- case "text_delta": {
- const content = partial.content[proxyEvent.contentIndex];
- if (content?.type === "text") {
- content.text += proxyEvent.delta;
- return {
- type: "text_delta",
- contentIndex: proxyEvent.contentIndex,
- delta: proxyEvent.delta,
- partial,
- };
- }
- throw new Error("Received text_delta for non-text content");
- }
-
- case "text_end": {
- const content = partial.content[proxyEvent.contentIndex];
- if (content?.type === "text") {
- content.textSignature = proxyEvent.contentSignature;
- return {
- type: "text_end",
- contentIndex: proxyEvent.contentIndex,
- content: content.text,
- partial,
- };
- }
- throw new Error("Received text_end for non-text content");
- }
-
- case "thinking_start":
- partial.content[proxyEvent.contentIndex] = { type: "thinking", thinking: "" };
- return { type: "thinking_start", contentIndex: proxyEvent.contentIndex, partial };
-
- case "thinking_delta": {
- const content = partial.content[proxyEvent.contentIndex];
- if (content?.type === "thinking") {
- content.thinking += proxyEvent.delta;
- return {
- type: "thinking_delta",
- contentIndex: proxyEvent.contentIndex,
- delta: proxyEvent.delta,
- partial,
- };
- }
- throw new Error("Received thinking_delta for non-thinking content");
- }
-
- case "thinking_end": {
- const content = partial.content[proxyEvent.contentIndex];
- if (content?.type === "thinking") {
- content.thinkingSignature = proxyEvent.contentSignature;
- return {
- type: "thinking_end",
- contentIndex: proxyEvent.contentIndex,
- content: content.thinking,
- partial,
- };
- }
- throw new Error("Received thinking_end for non-thinking content");
- }
-
- case "toolcall_start":
- partial.content[proxyEvent.contentIndex] = {
- type: "toolCall",
- id: proxyEvent.id,
- name: proxyEvent.toolName,
- arguments: {},
- partialJson: "",
- } satisfies ToolCall & { partialJson: string } as ToolCall;
- return { type: "toolcall_start", contentIndex: proxyEvent.contentIndex, partial };
-
- case "toolcall_delta": {
- const content = partial.content[proxyEvent.contentIndex];
- if (content?.type === "toolCall") {
- (content as any).partialJson += proxyEvent.delta;
- content.arguments = parseStreamingJson((content as any).partialJson) || {};
- partial.content[proxyEvent.contentIndex] = { ...content }; // Trigger reactivity
- return {
- type: "toolcall_delta",
- contentIndex: proxyEvent.contentIndex,
- delta: proxyEvent.delta,
- partial,
- };
- }
- throw new Error("Received toolcall_delta for non-toolCall content");
- }
-
- case "toolcall_end": {
- const content = partial.content[proxyEvent.contentIndex];
- if (content?.type === "toolCall") {
- delete (content as any).partialJson;
- return {
- type: "toolcall_end",
- contentIndex: proxyEvent.contentIndex,
- toolCall: content,
- partial,
- };
- }
- return undefined;
- }
-
- case "done":
- partial.stopReason = proxyEvent.reason;
- partial.usage = proxyEvent.usage;
- return { type: "done", reason: proxyEvent.reason, message: partial };
-
- case "error":
- partial.stopReason = proxyEvent.reason;
- partial.errorMessage = proxyEvent.errorMessage;
- partial.usage = proxyEvent.usage;
- return { type: "error", reason: proxyEvent.reason, error: partial };
-
- default: {
- const _exhaustiveCheck: never = proxyEvent;
- console.warn(`Unhandled proxy event type: ${(proxyEvent as any).type}`);
- return undefined;
- }
- }
-}
diff --git a/pi-mono-reference/packages/agent/src/types.ts b/pi-mono-reference/packages/agent/src/types.ts
deleted file mode 100644
index b1214c9a..00000000
--- a/pi-mono-reference/packages/agent/src/types.ts
+++ /dev/null
@@ -1,341 +0,0 @@
-import type {
- AssistantMessage,
- AssistantMessageEvent,
- ImageContent,
- Message,
- Model,
- SimpleStreamOptions,
- streamSimple,
- TextContent,
- Tool,
- ToolResultMessage,
-} from "@mariozechner/pi-ai";
-import type { Static, TSchema } from "@sinclair/typebox";
-
-/**
- * Stream function used by the agent loop.
- *
- * Contract:
- * - Must not throw or return a rejected promise for request/model/runtime failures.
- * - Must return an AssistantMessageEventStream.
- * - Failures must be encoded in the returned stream via protocol events and a
- * final AssistantMessage with stopReason "error" or "aborted" and errorMessage.
- */
-export type StreamFn = (
- ...args: Parameters
-) => ReturnType | Promise>;
-
-/**
- * Configuration for how tool calls from a single assistant message are executed.
- *
- * - "sequential": each tool call is prepared, executed, and finalized before the next one starts.
- * - "parallel": tool calls are prepared sequentially, then allowed tools execute concurrently.
- * Final tool results are still emitted in assistant source order.
- */
-export type ToolExecutionMode = "sequential" | "parallel";
-
-/** A single tool call content block emitted by an assistant message. */
-export type AgentToolCall = Extract;
-
-/**
- * Result returned from `beforeToolCall`.
- *
- * Returning `{ block: true }` prevents the tool from executing. The loop emits an error tool result instead.
- * `reason` becomes the text shown in that error result. If omitted, a default blocked message is used.
- */
-export interface BeforeToolCallResult {
- block?: boolean;
- reason?: string;
-}
-
-/**
- * Partial override returned from `afterToolCall`.
- *
- * Merge semantics are field-by-field:
- * - `content`: if provided, replaces the tool result content array in full
- * - `details`: if provided, replaces the tool result details value in full
- * - `isError`: if provided, replaces the tool result error flag
- *
- * Omitted fields keep the original executed tool result values.
- * There is no deep merge for `content` or `details`.
- */
-export interface AfterToolCallResult {
- content?: (TextContent | ImageContent)[];
- details?: unknown;
- isError?: boolean;
-}
-
-/** Context passed to `beforeToolCall`. */
-export interface BeforeToolCallContext {
- /** The assistant message that requested the tool call. */
- assistantMessage: AssistantMessage;
- /** The raw tool call block from `assistantMessage.content`. */
- toolCall: AgentToolCall;
- /** Validated tool arguments for the target tool schema. */
- args: unknown;
- /** Current agent context at the time the tool call is prepared. */
- context: AgentContext;
-}
-
-/** Context passed to `afterToolCall`. */
-export interface AfterToolCallContext {
- /** The assistant message that requested the tool call. */
- assistantMessage: AssistantMessage;
- /** The raw tool call block from `assistantMessage.content`. */
- toolCall: AgentToolCall;
- /** Validated tool arguments for the target tool schema. */
- args: unknown;
- /** The executed tool result before any `afterToolCall` overrides are applied. */
- result: AgentToolResult;
- /** Whether the executed tool result is currently treated as an error. */
- isError: boolean;
- /** Current agent context at the time the tool call is finalized. */
- context: AgentContext;
-}
-
-export interface AgentLoopConfig extends SimpleStreamOptions {
- model: Model;
-
- /**
- * Converts AgentMessage[] to LLM-compatible Message[] before each LLM call.
- *
- * Each AgentMessage must be converted to a UserMessage, AssistantMessage, or ToolResultMessage
- * that the LLM can understand. AgentMessages that cannot be converted (e.g., UI-only notifications,
- * status messages) should be filtered out.
- *
- * Contract: must not throw or reject. Return a safe fallback value instead.
- * Throwing interrupts the low-level agent loop without producing a normal event sequence.
- *
- * @example
- * ```typescript
- * convertToLlm: (messages) => messages.flatMap(m => {
- * if (m.role === "custom") {
- * // Convert custom message to user message
- * return [{ role: "user", content: m.content, timestamp: m.timestamp }];
- * }
- * if (m.role === "notification") {
- * // Filter out UI-only messages
- * return [];
- * }
- * // Pass through standard LLM messages
- * return [m];
- * })
- * ```
- */
- convertToLlm: (messages: AgentMessage[]) => Message[] | Promise;
-
- /**
- * Optional transform applied to the context before `convertToLlm`.
- *
- * Use this for operations that work at the AgentMessage level:
- * - Context window management (pruning old messages)
- * - Injecting context from external sources
- *
- * Contract: must not throw or reject. Return the original messages or another
- * safe fallback value instead.
- *
- * @example
- * ```typescript
- * transformContext: async (messages) => {
- * if (estimateTokens(messages) > MAX_TOKENS) {
- * return pruneOldMessages(messages);
- * }
- * return messages;
- * }
- * ```
- */
- transformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise;
-
- /**
- * Resolves an API key dynamically for each LLM call.
- *
- * Useful for short-lived OAuth tokens (e.g., GitHub Copilot) that may expire
- * during long-running tool execution phases.
- *
- * Contract: must not throw or reject. Return undefined when no key is available.
- */
- getApiKey?: (provider: string) => Promise | string | undefined;
-
- /**
- * Returns steering messages to inject into the conversation mid-run.
- *
- * Called after the current assistant turn finishes executing its tool calls.
- * If messages are returned, they are added to the context before the next LLM call.
- * Tool calls from the current assistant message are not skipped.
- *
- * Use this for "steering" the agent while it's working.
- *
- * Contract: must not throw or reject. Return [] when no steering messages are available.
- */
- getSteeringMessages?: () => Promise;
-
- /**
- * Returns follow-up messages to process after the agent would otherwise stop.
- *
- * Called when the agent has no more tool calls and no steering messages.
- * If messages are returned, they're added to the context and the agent
- * continues with another turn.
- *
- * Use this for follow-up messages that should wait until the agent finishes.
- *
- * Contract: must not throw or reject. Return [] when no follow-up messages are available.
- */
- getFollowUpMessages?: () => Promise;
-
- /**
- * Tool execution mode.
- * - "sequential": execute tool calls one by one
- * - "parallel": preflight tool calls sequentially, then execute allowed tools concurrently
- *
- * Default: "parallel"
- */
- toolExecution?: ToolExecutionMode;
-
- /**
- * Called before a tool is executed, after arguments have been validated.
- *
- * Return `{ block: true }` to prevent execution. The loop emits an error tool result instead.
- * The hook receives the agent abort signal and is responsible for honoring it.
- */
- beforeToolCall?: (context: BeforeToolCallContext, signal?: AbortSignal) => Promise;
-
- /**
- * Called after a tool finishes executing, before final tool events are emitted.
- *
- * Return an `AfterToolCallResult` to override parts of the executed tool result:
- * - `content` replaces the full content array
- * - `details` replaces the full details payload
- * - `isError` replaces the error flag
- *
- * Any omitted fields keep their original values. No deep merge is performed.
- * The hook receives the agent abort signal and is responsible for honoring it.
- */
- afterToolCall?: (context: AfterToolCallContext, signal?: AbortSignal) => Promise;
-}
-
-/**
- * Thinking/reasoning level for models that support it.
- * Note: "xhigh" is only supported by OpenAI gpt-5.1-codex-max, gpt-5.2, gpt-5.2-codex, gpt-5.3, and gpt-5.3-codex models.
- */
-export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
-
-/**
- * Extensible interface for custom app messages.
- * Apps can extend via declaration merging:
- *
- * @example
- * ```typescript
- * declare module "@mariozechner/agent" {
- * interface CustomAgentMessages {
- * artifact: ArtifactMessage;
- * notification: NotificationMessage;
- * }
- * }
- * ```
- */
-export interface CustomAgentMessages {
- // Empty by default - apps extend via declaration merging
-}
-
-/**
- * AgentMessage: Union of LLM messages + custom messages.
- * This abstraction allows apps to add custom message types while maintaining
- * type safety and compatibility with the base LLM messages.
- */
-export type AgentMessage = Message | CustomAgentMessages[keyof CustomAgentMessages];
-
-/**
- * Public agent state.
- *
- * `tools` and `messages` use accessor properties so implementations can copy
- * assigned arrays before storing them.
- */
-export interface AgentState {
- /** System prompt sent with each model request. */
- systemPrompt: string;
- /** Active model used for future turns. */
- model: Model;
- /** Requested reasoning level for future turns. */
- thinkingLevel: ThinkingLevel;
- /** Available tools. Assigning a new array copies the top-level array. */
- set tools(tools: AgentTool[]);
- get tools(): AgentTool[];
- /** Conversation transcript. Assigning a new array copies the top-level array. */
- set messages(messages: AgentMessage[]);
- get messages(): AgentMessage[];
- /**
- * True while the agent is processing a prompt or continuation.
- *
- * This remains true until awaited `agent_end` listeners settle.
- */
- readonly isStreaming: boolean;
- /** Partial assistant message for the current streamed response, if any. */
- readonly streamingMessage?: AgentMessage;
- /** Tool call ids currently executing. */
- readonly pendingToolCalls: ReadonlySet;
- /** Error message from the most recent failed or aborted assistant turn, if any. */
- readonly errorMessage?: string;
-}
-
-/** Final or partial result produced by a tool. */
-export interface AgentToolResult {
- /** Text or image content returned to the model. */
- content: (TextContent | ImageContent)[];
- /** Arbitrary structured details for logs or UI rendering. */
- details: T;
-}
-
-/** Callback used by tools to stream partial execution updates. */
-export type AgentToolUpdateCallback = (partialResult: AgentToolResult) => void;
-
-/** Tool definition used by the agent runtime. */
-export interface AgentTool extends Tool {
- /** Human-readable label for UI display. */
- label: string;
- /**
- * Optional compatibility shim for raw tool-call arguments before schema validation.
- * Must return an object that matches `TParameters`.
- */
- prepareArguments?: (args: unknown) => Static;
- /** Execute the tool call. Throw on failure instead of encoding errors in `content`. */
- execute: (
- toolCallId: string,
- params: Static,
- signal?: AbortSignal,
- onUpdate?: AgentToolUpdateCallback,
- ) => Promise>;
-}
-
-/** Context snapshot passed into the low-level agent loop. */
-export interface AgentContext {
- /** System prompt included with the request. */
- systemPrompt: string;
- /** Transcript visible to the model. */
- messages: AgentMessage[];
- /** Tools available for this run. */
- tools?: AgentTool[];
-}
-
-/**
- * Events emitted by the Agent for UI updates.
- *
- * `agent_end` is the last event emitted for a run, but awaited `Agent.subscribe()`
- * listeners for that event are still part of run settlement. The agent becomes
- * idle only after those listeners finish.
- */
-export type AgentEvent =
- // Agent lifecycle
- | { type: "agent_start" }
- | { type: "agent_end"; messages: AgentMessage[] }
- // Turn lifecycle - a turn is one assistant response + any tool calls/results
- | { type: "turn_start" }
- | { type: "turn_end"; message: AgentMessage; toolResults: ToolResultMessage[] }
- // Message lifecycle - emitted for user, assistant, and toolResult messages
- | { type: "message_start"; message: AgentMessage }
- // Only emitted for assistant messages during streaming
- | { type: "message_update"; message: AgentMessage; assistantMessageEvent: AssistantMessageEvent }
- | { type: "message_end"; message: AgentMessage }
- // Tool execution lifecycle
- | { type: "tool_execution_start"; toolCallId: string; toolName: string; args: any }
- | { type: "tool_execution_update"; toolCallId: string; toolName: string; args: any; partialResult: any }
- | { type: "tool_execution_end"; toolCallId: string; toolName: string; result: any; isError: boolean };
diff --git a/pi-mono-reference/packages/agent/test/agent-loop.test.ts b/pi-mono-reference/packages/agent/test/agent-loop.test.ts
deleted file mode 100644
index 00efc688..00000000
--- a/pi-mono-reference/packages/agent/test/agent-loop.test.ts
+++ /dev/null
@@ -1,758 +0,0 @@
-import {
- type AssistantMessage,
- type AssistantMessageEvent,
- EventStream,
- type Message,
- type Model,
- type UserMessage,
-} from "@mariozechner/pi-ai";
-import { Type } from "@sinclair/typebox";
-import { describe, expect, it } from "vitest";
-import { agentLoop, agentLoopContinue } from "../src/agent-loop.js";
-import type { AgentContext, AgentEvent, AgentLoopConfig, AgentMessage, AgentTool } from "../src/types.js";
-
-// Mock stream for testing - mimics MockAssistantStream
-class MockAssistantStream extends EventStream {
- constructor() {
- super(
- (event) => event.type === "done" || event.type === "error",
- (event) => {
- if (event.type === "done") return event.message;
- if (event.type === "error") return event.error;
- throw new Error("Unexpected event type");
- },
- );
- }
-}
-
-function createUsage() {
- return {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- };
-}
-
-function createModel(): Model<"openai-responses"> {
- return {
- id: "mock",
- name: "mock",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://example.invalid",
- reasoning: false,
- input: ["text"],
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
- contextWindow: 8192,
- maxTokens: 2048,
- };
-}
-
-function createAssistantMessage(
- content: AssistantMessage["content"],
- stopReason: AssistantMessage["stopReason"] = "stop",
-): AssistantMessage {
- return {
- role: "assistant",
- content,
- api: "openai-responses",
- provider: "openai",
- model: "mock",
- usage: createUsage(),
- stopReason,
- timestamp: Date.now(),
- };
-}
-
-function createUserMessage(text: string): UserMessage {
- return {
- role: "user",
- content: text,
- timestamp: Date.now(),
- };
-}
-
-// Simple identity converter for tests - just passes through standard messages
-function identityConverter(messages: AgentMessage[]): Message[] {
- return messages.filter((m) => m.role === "user" || m.role === "assistant" || m.role === "toolResult") as Message[];
-}
-
-describe("agentLoop with AgentMessage", () => {
- it("should emit events with AgentMessage types", async () => {
- const context: AgentContext = {
- systemPrompt: "You are helpful.",
- messages: [],
- tools: [],
- };
-
- const userPrompt: AgentMessage = createUserMessage("Hello");
-
- const config: AgentLoopConfig = {
- model: createModel(),
- convertToLlm: identityConverter,
- };
-
- const streamFn = () => {
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- const message = createAssistantMessage([{ type: "text", text: "Hi there!" }]);
- stream.push({ type: "done", reason: "stop", message });
- });
- return stream;
- };
-
- const events: AgentEvent[] = [];
- const stream = agentLoop([userPrompt], context, config, undefined, streamFn);
-
- for await (const event of stream) {
- events.push(event);
- }
-
- const messages = await stream.result();
-
- // Should have user message and assistant message
- expect(messages.length).toBe(2);
- expect(messages[0].role).toBe("user");
- expect(messages[1].role).toBe("assistant");
-
- // Verify event sequence
- const eventTypes = events.map((e) => e.type);
- expect(eventTypes).toContain("agent_start");
- expect(eventTypes).toContain("turn_start");
- expect(eventTypes).toContain("message_start");
- expect(eventTypes).toContain("message_end");
- expect(eventTypes).toContain("turn_end");
- expect(eventTypes).toContain("agent_end");
- });
-
- it("should handle custom message types via convertToLlm", async () => {
- // Create a custom message type
- interface CustomNotification {
- role: "notification";
- text: string;
- timestamp: number;
- }
-
- const notification: CustomNotification = {
- role: "notification",
- text: "This is a notification",
- timestamp: Date.now(),
- };
-
- const context: AgentContext = {
- systemPrompt: "You are helpful.",
- messages: [notification as unknown as AgentMessage], // Custom message in context
- tools: [],
- };
-
- const userPrompt: AgentMessage = createUserMessage("Hello");
-
- let convertedMessages: Message[] = [];
- const config: AgentLoopConfig = {
- model: createModel(),
- convertToLlm: (messages) => {
- // Filter out notifications, convert rest
- convertedMessages = messages
- .filter((m) => (m as { role: string }).role !== "notification")
- .filter((m) => m.role === "user" || m.role === "assistant" || m.role === "toolResult") as Message[];
- return convertedMessages;
- },
- };
-
- const streamFn = () => {
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- const message = createAssistantMessage([{ type: "text", text: "Response" }]);
- stream.push({ type: "done", reason: "stop", message });
- });
- return stream;
- };
-
- const events: AgentEvent[] = [];
- const stream = agentLoop([userPrompt], context, config, undefined, streamFn);
-
- for await (const event of stream) {
- events.push(event);
- }
-
- // The notification should have been filtered out in convertToLlm
- expect(convertedMessages.length).toBe(1); // Only user message
- expect(convertedMessages[0].role).toBe("user");
- });
-
- it("should apply transformContext before convertToLlm", async () => {
- const context: AgentContext = {
- systemPrompt: "You are helpful.",
- messages: [
- createUserMessage("old message 1"),
- createAssistantMessage([{ type: "text", text: "old response 1" }]),
- createUserMessage("old message 2"),
- createAssistantMessage([{ type: "text", text: "old response 2" }]),
- ],
- tools: [],
- };
-
- const userPrompt: AgentMessage = createUserMessage("new message");
-
- let transformedMessages: AgentMessage[] = [];
- let convertedMessages: Message[] = [];
-
- const config: AgentLoopConfig = {
- model: createModel(),
- transformContext: async (messages) => {
- // Keep only last 2 messages (prune old ones)
- transformedMessages = messages.slice(-2);
- return transformedMessages;
- },
- convertToLlm: (messages) => {
- convertedMessages = messages.filter(
- (m) => m.role === "user" || m.role === "assistant" || m.role === "toolResult",
- ) as Message[];
- return convertedMessages;
- },
- };
-
- const streamFn = () => {
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- const message = createAssistantMessage([{ type: "text", text: "Response" }]);
- stream.push({ type: "done", reason: "stop", message });
- });
- return stream;
- };
-
- const stream = agentLoop([userPrompt], context, config, undefined, streamFn);
-
- for await (const _ of stream) {
- // consume
- }
-
- // transformContext should have been called first, keeping only last 2
- expect(transformedMessages.length).toBe(2);
- // Then convertToLlm receives the pruned messages
- expect(convertedMessages.length).toBe(2);
- });
-
- it("should handle tool calls and results", async () => {
- const toolSchema = Type.Object({ value: Type.String() });
- const executed: string[] = [];
- const tool: AgentTool = {
- name: "echo",
- label: "Echo",
- description: "Echo tool",
- parameters: toolSchema,
- async execute(_toolCallId, params) {
- executed.push(params.value);
- return {
- content: [{ type: "text", text: `echoed: ${params.value}` }],
- details: { value: params.value },
- };
- },
- };
-
- const context: AgentContext = {
- systemPrompt: "",
- messages: [],
- tools: [tool],
- };
-
- const userPrompt: AgentMessage = createUserMessage("echo something");
-
- const config: AgentLoopConfig = {
- model: createModel(),
- convertToLlm: identityConverter,
- };
-
- let callIndex = 0;
- const streamFn = () => {
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- if (callIndex === 0) {
- // First call: return tool call
- const message = createAssistantMessage(
- [{ type: "toolCall", id: "tool-1", name: "echo", arguments: { value: "hello" } }],
- "toolUse",
- );
- stream.push({ type: "done", reason: "toolUse", message });
- } else {
- // Second call: return final response
- const message = createAssistantMessage([{ type: "text", text: "done" }]);
- stream.push({ type: "done", reason: "stop", message });
- }
- callIndex++;
- });
- return stream;
- };
-
- const events: AgentEvent[] = [];
- const stream = agentLoop([userPrompt], context, config, undefined, streamFn);
-
- for await (const event of stream) {
- events.push(event);
- }
-
- // Tool should have been executed
- expect(executed).toEqual(["hello"]);
-
- // Should have tool execution events
- const toolStart = events.find((e) => e.type === "tool_execution_start");
- const toolEnd = events.find((e) => e.type === "tool_execution_end");
- expect(toolStart).toBeDefined();
- expect(toolEnd).toBeDefined();
- if (toolEnd?.type === "tool_execution_end") {
- expect(toolEnd.isError).toBe(false);
- }
- });
-
- it("should execute mutated beforeToolCall args without revalidation", async () => {
- const toolSchema = Type.Object({ value: Type.String() });
- const executed: Array = [];
- const tool: AgentTool = {
- name: "echo",
- label: "Echo",
- description: "Echo tool",
- parameters: toolSchema,
- async execute(_toolCallId, params) {
- executed.push(params.value as string | number);
- return {
- content: [{ type: "text", text: `echoed: ${String(params.value)}` }],
- details: { value: params.value as string | number },
- };
- },
- };
-
- const context: AgentContext = {
- systemPrompt: "",
- messages: [],
- tools: [tool],
- };
-
- const userPrompt: AgentMessage = createUserMessage("echo something");
-
- const config: AgentLoopConfig = {
- model: createModel(),
- convertToLlm: identityConverter,
- beforeToolCall: async ({ args }) => {
- const mutableArgs = args as { value: string | number };
- mutableArgs.value = 123;
- return undefined;
- },
- };
-
- let callIndex = 0;
- const streamFn = () => {
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- if (callIndex === 0) {
- const message = createAssistantMessage(
- [{ type: "toolCall", id: "tool-1", name: "echo", arguments: { value: "hello" } }],
- "toolUse",
- );
- stream.push({ type: "done", reason: "toolUse", message });
- } else {
- const message = createAssistantMessage([{ type: "text", text: "done" }]);
- stream.push({ type: "done", reason: "stop", message });
- }
- callIndex++;
- });
- return stream;
- };
-
- const stream = agentLoop([userPrompt], context, config, undefined, streamFn);
- for await (const _event of stream) {
- // consume
- }
-
- expect(executed).toEqual([123]);
- });
-
- it("should prepare tool arguments for validation", async () => {
- const replaceSchema = Type.Object({ oldText: Type.String(), newText: Type.String() });
- const toolSchema = Type.Object({ edits: Type.Array(replaceSchema) });
- const executed: Array> = [];
- const tool: AgentTool = {
- name: "edit",
- label: "Edit",
- description: "Edit tool",
- parameters: toolSchema,
- prepareArguments(args) {
- if (!args || typeof args !== "object") {
- return args as { edits: { oldText: string; newText: string }[] };
- }
- const input = args as {
- edits?: Array<{ oldText: string; newText: string }>;
- oldText?: string;
- newText?: string;
- };
- if (typeof input.oldText !== "string" || typeof input.newText !== "string") {
- return args as { edits: { oldText: string; newText: string }[] };
- }
- return {
- edits: [...(input.edits ?? []), { oldText: input.oldText, newText: input.newText }],
- };
- },
- async execute(_toolCallId, params) {
- executed.push(params.edits);
- return {
- content: [{ type: "text", text: `edited ${params.edits.length}` }],
- details: { count: params.edits.length },
- };
- },
- };
-
- const context: AgentContext = {
- systemPrompt: "",
- messages: [],
- tools: [tool],
- };
-
- const userPrompt: AgentMessage = createUserMessage("edit something");
- const config: AgentLoopConfig = {
- model: createModel(),
- convertToLlm: identityConverter,
- };
-
- let callIndex = 0;
- const streamFn = () => {
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- if (callIndex === 0) {
- const message = createAssistantMessage(
- [
- {
- type: "toolCall",
- id: "tool-1",
- name: "edit",
- arguments: { oldText: "before", newText: "after" },
- },
- ],
- "toolUse",
- );
- stream.push({ type: "done", reason: "toolUse", message });
- } else {
- const message = createAssistantMessage([{ type: "text", text: "done" }]);
- stream.push({ type: "done", reason: "stop", message });
- }
- callIndex++;
- });
- return stream;
- };
-
- const stream = agentLoop([userPrompt], context, config, undefined, streamFn);
- for await (const _event of stream) {
- // consume
- }
-
- expect(executed).toEqual([[{ oldText: "before", newText: "after" }]]);
- });
-
- it("should execute tool calls in parallel and emit tool results in source order", async () => {
- const toolSchema = Type.Object({ value: Type.String() });
- let firstResolved = false;
- let parallelObserved = false;
- let releaseFirst: (() => void) | undefined;
- const firstDone = new Promise((resolve) => {
- releaseFirst = resolve;
- });
-
- const tool: AgentTool = {
- name: "echo",
- label: "Echo",
- description: "Echo tool",
- parameters: toolSchema,
- async execute(_toolCallId, params) {
- if (params.value === "first") {
- await firstDone;
- firstResolved = true;
- }
- if (params.value === "second" && !firstResolved) {
- parallelObserved = true;
- }
- return {
- content: [{ type: "text", text: `echoed: ${params.value}` }],
- details: { value: params.value },
- };
- },
- };
-
- const context: AgentContext = {
- systemPrompt: "",
- messages: [],
- tools: [tool],
- };
-
- const userPrompt: AgentMessage = createUserMessage("echo both");
- const config: AgentLoopConfig = {
- model: createModel(),
- convertToLlm: identityConverter,
- toolExecution: "parallel",
- };
-
- let callIndex = 0;
- const stream = agentLoop([userPrompt], context, config, undefined, () => {
- const mockStream = new MockAssistantStream();
- queueMicrotask(() => {
- if (callIndex === 0) {
- const message = createAssistantMessage(
- [
- { type: "toolCall", id: "tool-1", name: "echo", arguments: { value: "first" } },
- { type: "toolCall", id: "tool-2", name: "echo", arguments: { value: "second" } },
- ],
- "toolUse",
- );
- mockStream.push({ type: "done", reason: "toolUse", message });
- setTimeout(() => releaseFirst?.(), 20);
- } else {
- const message = createAssistantMessage([{ type: "text", text: "done" }]);
- mockStream.push({ type: "done", reason: "stop", message });
- }
- callIndex++;
- });
- return mockStream;
- });
-
- const events: AgentEvent[] = [];
- for await (const event of stream) {
- events.push(event);
- }
-
- const toolResultIds = events.flatMap((event) => {
- if (event.type !== "message_end" || event.message.role !== "toolResult") {
- return [];
- }
- return [event.message.toolCallId];
- });
-
- expect(parallelObserved).toBe(true);
- expect(toolResultIds).toEqual(["tool-1", "tool-2"]);
- });
-
- it("should inject queued messages after all tool calls complete", async () => {
- const toolSchema = Type.Object({ value: Type.String() });
- const executed: string[] = [];
- const tool: AgentTool = {
- name: "echo",
- label: "Echo",
- description: "Echo tool",
- parameters: toolSchema,
- async execute(_toolCallId, params) {
- executed.push(params.value);
- return {
- content: [{ type: "text", text: `ok:${params.value}` }],
- details: { value: params.value },
- };
- },
- };
-
- const context: AgentContext = {
- systemPrompt: "",
- messages: [],
- tools: [tool],
- };
-
- const userPrompt: AgentMessage = createUserMessage("start");
- const queuedUserMessage: AgentMessage = createUserMessage("interrupt");
-
- let queuedDelivered = false;
- let callIndex = 0;
- let sawInterruptInContext = false;
-
- const config: AgentLoopConfig = {
- model: createModel(),
- convertToLlm: identityConverter,
- toolExecution: "sequential",
- getSteeringMessages: async () => {
- // Return steering message after tool execution has started.
- if (executed.length >= 1 && !queuedDelivered) {
- queuedDelivered = true;
- return [queuedUserMessage];
- }
- return [];
- },
- };
-
- const events: AgentEvent[] = [];
- const stream = agentLoop([userPrompt], context, config, undefined, (_model, ctx, _options) => {
- // Check if interrupt message is in context on second call
- if (callIndex === 1) {
- sawInterruptInContext = ctx.messages.some(
- (m) => m.role === "user" && typeof m.content === "string" && m.content === "interrupt",
- );
- }
-
- const mockStream = new MockAssistantStream();
- queueMicrotask(() => {
- if (callIndex === 0) {
- // First call: return two tool calls
- const message = createAssistantMessage(
- [
- { type: "toolCall", id: "tool-1", name: "echo", arguments: { value: "first" } },
- { type: "toolCall", id: "tool-2", name: "echo", arguments: { value: "second" } },
- ],
- "toolUse",
- );
- mockStream.push({ type: "done", reason: "toolUse", message });
- } else {
- // Second call: return final response
- const message = createAssistantMessage([{ type: "text", text: "done" }]);
- mockStream.push({ type: "done", reason: "stop", message });
- }
- callIndex++;
- });
- return mockStream;
- });
-
- for await (const event of stream) {
- events.push(event);
- }
-
- // Both tools should execute before steering is injected
- expect(executed).toEqual(["first", "second"]);
-
- const toolEnds = events.filter(
- (e): e is Extract => e.type === "tool_execution_end",
- );
- expect(toolEnds.length).toBe(2);
- expect(toolEnds[0].isError).toBe(false);
- expect(toolEnds[1].isError).toBe(false);
-
- // Queued message should appear in events after both tool result messages
- const eventSequence = events.flatMap((event) => {
- if (event.type !== "message_start") return [];
- if (event.message.role === "toolResult") return [`tool:${event.message.toolCallId}`];
- if (event.message.role === "user" && typeof event.message.content === "string") {
- return [event.message.content];
- }
- return [];
- });
- expect(eventSequence).toContain("interrupt");
- expect(eventSequence.indexOf("tool:tool-1")).toBeLessThan(eventSequence.indexOf("interrupt"));
- expect(eventSequence.indexOf("tool:tool-2")).toBeLessThan(eventSequence.indexOf("interrupt"));
-
- // Interrupt message should be in context when second LLM call is made
- expect(sawInterruptInContext).toBe(true);
- });
-});
-
-describe("agentLoopContinue with AgentMessage", () => {
- it("should throw when context has no messages", () => {
- const context: AgentContext = {
- systemPrompt: "You are helpful.",
- messages: [],
- tools: [],
- };
-
- const config: AgentLoopConfig = {
- model: createModel(),
- convertToLlm: identityConverter,
- };
-
- expect(() => agentLoopContinue(context, config)).toThrow("Cannot continue: no messages in context");
- });
-
- it("should continue from existing context without emitting user message events", async () => {
- const userMessage: AgentMessage = createUserMessage("Hello");
-
- const context: AgentContext = {
- systemPrompt: "You are helpful.",
- messages: [userMessage],
- tools: [],
- };
-
- const config: AgentLoopConfig = {
- model: createModel(),
- convertToLlm: identityConverter,
- };
-
- const streamFn = () => {
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- const message = createAssistantMessage([{ type: "text", text: "Response" }]);
- stream.push({ type: "done", reason: "stop", message });
- });
- return stream;
- };
-
- const events: AgentEvent[] = [];
- const stream = agentLoopContinue(context, config, undefined, streamFn);
-
- for await (const event of stream) {
- events.push(event);
- }
-
- const messages = await stream.result();
-
- // Should only return the new assistant message (not the existing user message)
- expect(messages.length).toBe(1);
- expect(messages[0].role).toBe("assistant");
-
- // Should NOT have user message events (that's the key difference from agentLoop)
- const messageEndEvents = events.filter((e) => e.type === "message_end");
- expect(messageEndEvents.length).toBe(1);
- expect((messageEndEvents[0] as any).message.role).toBe("assistant");
- });
-
- it("should allow custom message types as last message (caller responsibility)", async () => {
- // Custom message that will be converted to user message by convertToLlm
- interface CustomMessage {
- role: "custom";
- text: string;
- timestamp: number;
- }
-
- const customMessage: CustomMessage = {
- role: "custom",
- text: "Hook content",
- timestamp: Date.now(),
- };
-
- const context: AgentContext = {
- systemPrompt: "You are helpful.",
- messages: [customMessage as unknown as AgentMessage],
- tools: [],
- };
-
- const config: AgentLoopConfig = {
- model: createModel(),
- convertToLlm: (messages) => {
- // Convert custom to user message
- return messages
- .map((m) => {
- if ((m as any).role === "custom") {
- return {
- role: "user" as const,
- content: (m as any).text,
- timestamp: m.timestamp,
- };
- }
- return m;
- })
- .filter((m) => m.role === "user" || m.role === "assistant" || m.role === "toolResult") as Message[];
- },
- };
-
- const streamFn = () => {
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- const message = createAssistantMessage([{ type: "text", text: "Response to custom message" }]);
- stream.push({ type: "done", reason: "stop", message });
- });
- return stream;
- };
-
- // Should not throw - the custom message will be converted to user message
- const stream = agentLoopContinue(context, config, undefined, streamFn);
-
- const events: AgentEvent[] = [];
- for await (const event of stream) {
- events.push(event);
- }
-
- const messages = await stream.result();
- expect(messages.length).toBe(1);
- expect(messages[0].role).toBe("assistant");
- });
-});
diff --git a/pi-mono-reference/packages/agent/test/agent.test.ts b/pi-mono-reference/packages/agent/test/agent.test.ts
deleted file mode 100644
index 94be88cb..00000000
--- a/pi-mono-reference/packages/agent/test/agent.test.ts
+++ /dev/null
@@ -1,463 +0,0 @@
-import { type AssistantMessage, type AssistantMessageEvent, EventStream, getModel } from "@mariozechner/pi-ai";
-import { describe, expect, it } from "vitest";
-import { Agent } from "../src/index.js";
-
-// Mock stream that mimics AssistantMessageEventStream
-class MockAssistantStream extends EventStream {
- constructor() {
- super(
- (event) => event.type === "done" || event.type === "error",
- (event) => {
- if (event.type === "done") return event.message;
- if (event.type === "error") return event.error;
- throw new Error("Unexpected event type");
- },
- );
- }
-}
-
-function createAssistantMessage(text: string): AssistantMessage {
- return {
- role: "assistant",
- content: [{ type: "text", text }],
- api: "openai-responses",
- provider: "openai",
- model: "mock",
- usage: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- stopReason: "stop",
- timestamp: Date.now(),
- };
-}
-
-function createDeferred(): {
- promise: Promise;
- resolve: () => void;
-} {
- let resolve = () => {};
- const promise = new Promise((resolvePromise) => {
- resolve = resolvePromise;
- });
- return { promise, resolve };
-}
-
-describe("Agent", () => {
- it("should create an agent instance with default state", () => {
- const agent = new Agent();
-
- expect(agent.state).toBeDefined();
- expect(agent.state.systemPrompt).toBe("");
- expect(agent.state.model).toBeDefined();
- expect(agent.state.thinkingLevel).toBe("off");
- expect(agent.state.tools).toEqual([]);
- expect(agent.state.messages).toEqual([]);
- expect(agent.state.isStreaming).toBe(false);
- expect(agent.state.streamingMessage).toBe(undefined);
- expect(agent.state.pendingToolCalls).toEqual(new Set());
- expect(agent.state.errorMessage).toBeUndefined();
- });
-
- it("should create an agent instance with custom initial state", () => {
- const customModel = getModel("openai", "gpt-4o-mini");
- const agent = new Agent({
- initialState: {
- systemPrompt: "You are a helpful assistant.",
- model: customModel,
- thinkingLevel: "low",
- },
- });
-
- expect(agent.state.systemPrompt).toBe("You are a helpful assistant.");
- expect(agent.state.model).toBe(customModel);
- expect(agent.state.thinkingLevel).toBe("low");
- });
-
- it("should subscribe to events", () => {
- const agent = new Agent();
-
- let eventCount = 0;
- const unsubscribe = agent.subscribe((_event) => {
- eventCount++;
- });
-
- // No initial event on subscribe
- expect(eventCount).toBe(0);
-
- // State mutators don't emit events
- agent.state.systemPrompt = "Test prompt";
- expect(eventCount).toBe(0);
- expect(agent.state.systemPrompt).toBe("Test prompt");
-
- // Unsubscribe should work
- unsubscribe();
- agent.state.systemPrompt = "Another prompt";
- expect(eventCount).toBe(0); // Should not increase
- });
-
- it("should await async subscribers before prompt resolves", async () => {
- const barrier = createDeferred();
- const agent = new Agent({
- streamFn: () => {
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- stream.push({ type: "done", reason: "stop", message: createAssistantMessage("ok") });
- });
- return stream;
- },
- });
-
- let listenerFinished = false;
- agent.subscribe(async (event) => {
- if (event.type === "agent_end") {
- await barrier.promise;
- listenerFinished = true;
- }
- });
-
- let promptResolved = false;
- const promptPromise = agent.prompt("hello").then(() => {
- promptResolved = true;
- });
-
- await new Promise((resolve) => setTimeout(resolve, 10));
- expect(promptResolved).toBe(false);
- expect(listenerFinished).toBe(false);
- expect(agent.state.isStreaming).toBe(true);
-
- barrier.resolve();
- await promptPromise;
-
- expect(listenerFinished).toBe(true);
- expect(promptResolved).toBe(true);
- expect(agent.state.isStreaming).toBe(false);
- });
-
- it("waitForIdle should wait for async subscribers", async () => {
- const barrier = createDeferred();
- const agent = new Agent({
- streamFn: () => {
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- stream.push({ type: "done", reason: "stop", message: createAssistantMessage("ok") });
- });
- return stream;
- },
- });
-
- agent.subscribe(async (event) => {
- if (event.type === "message_end" && event.message.role === "assistant") {
- await barrier.promise;
- }
- });
-
- const promptPromise = agent.prompt("hello");
- let idleResolved = false;
- const idlePromise = agent.waitForIdle().then(() => {
- idleResolved = true;
- });
-
- await new Promise((resolve) => setTimeout(resolve, 10));
- expect(idleResolved).toBe(false);
- expect(agent.state.isStreaming).toBe(true);
-
- barrier.resolve();
- await Promise.all([promptPromise, idlePromise]);
-
- expect(idleResolved).toBe(true);
- expect(agent.state.isStreaming).toBe(false);
- });
-
- it("should pass the active abort signal to subscribers", async () => {
- let receivedSignal: AbortSignal | undefined;
- const agent = new Agent({
- streamFn: (_model, _context, options) => {
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- stream.push({ type: "start", partial: createAssistantMessage("") });
- const checkAbort = () => {
- if (options?.signal?.aborted) {
- stream.push({ type: "error", reason: "aborted", error: createAssistantMessage("Aborted") });
- } else {
- setTimeout(checkAbort, 5);
- }
- };
- checkAbort();
- });
- return stream;
- },
- });
-
- agent.subscribe((event, signal) => {
- if (event.type === "agent_start") {
- receivedSignal = signal;
- }
- });
-
- const promptPromise = agent.prompt("hello");
- await new Promise((resolve) => setTimeout(resolve, 10));
-
- expect(receivedSignal).toBeDefined();
- expect(receivedSignal?.aborted).toBe(false);
-
- agent.abort();
- await promptPromise;
-
- expect(receivedSignal?.aborted).toBe(true);
- });
-
- it("should update state with mutators", () => {
- const agent = new Agent();
-
- // Test setSystemPrompt
- agent.state.systemPrompt = "Custom prompt";
- expect(agent.state.systemPrompt).toBe("Custom prompt");
-
- // Test setModel
- const newModel = getModel("google", "gemini-2.5-flash");
- agent.state.model = newModel;
- expect(agent.state.model).toBe(newModel);
-
- // Test setThinkingLevel
- agent.state.thinkingLevel = "high";
- expect(agent.state.thinkingLevel).toBe("high");
-
- // Test setTools
- const tools = [{ name: "test", description: "test tool" } as any];
- agent.state.tools = tools;
- expect(agent.state.tools).toEqual(tools);
- expect(agent.state.tools).not.toBe(tools); // Should be a copy
-
- // Test replaceMessages
- const messages = [{ role: "user" as const, content: "Hello", timestamp: Date.now() }];
- agent.state.messages = messages;
- expect(agent.state.messages).toEqual(messages);
- expect(agent.state.messages).not.toBe(messages); // Should be a copy
-
- // Test appendMessage
- const newMessage = { role: "assistant" as const, content: [{ type: "text" as const, text: "Hi" }] };
- agent.state.messages.push(newMessage as any);
- expect(agent.state.messages).toHaveLength(2);
- expect(agent.state.messages[1]).toBe(newMessage);
-
- // Test clearMessages
- agent.state.messages = [];
- expect(agent.state.messages).toEqual([]);
- });
-
- it("should support steering message queue", async () => {
- const agent = new Agent();
-
- const message = { role: "user" as const, content: "Steering message", timestamp: Date.now() };
- agent.steer(message);
-
- // The message is queued but not yet in state.messages
- expect(agent.state.messages).not.toContainEqual(message);
- });
-
- it("should support follow-up message queue", async () => {
- const agent = new Agent();
-
- const message = { role: "user" as const, content: "Follow-up message", timestamp: Date.now() };
- agent.followUp(message);
-
- // The message is queued but not yet in state.messages
- expect(agent.state.messages).not.toContainEqual(message);
- });
-
- it("should handle abort controller", () => {
- const agent = new Agent();
-
- // Should not throw even if nothing is running
- expect(() => agent.abort()).not.toThrow();
- });
-
- it("should throw when prompt() called while streaming", async () => {
- let abortSignal: AbortSignal | undefined;
- const agent = new Agent({
- // Use a stream function that responds to abort
- streamFn: (_model, _context, options) => {
- abortSignal = options?.signal;
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- stream.push({ type: "start", partial: createAssistantMessage("") });
- // Check abort signal periodically
- const checkAbort = () => {
- if (abortSignal?.aborted) {
- stream.push({ type: "error", reason: "aborted", error: createAssistantMessage("Aborted") });
- } else {
- setTimeout(checkAbort, 5);
- }
- };
- checkAbort();
- });
- return stream;
- },
- });
-
- // Start first prompt (don't await, it will block until abort)
- const firstPrompt = agent.prompt("First message");
-
- // Wait a tick for isStreaming to be set
- await new Promise((resolve) => setTimeout(resolve, 10));
- expect(agent.state.isStreaming).toBe(true);
-
- // Second prompt should reject
- await expect(agent.prompt("Second message")).rejects.toThrow(
- "Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.",
- );
-
- // Cleanup - abort to stop the stream
- agent.abort();
- await firstPrompt.catch(() => {}); // Ignore abort error
- });
-
- it("should throw when continue() called while streaming", async () => {
- let abortSignal: AbortSignal | undefined;
- const agent = new Agent({
- streamFn: (_model, _context, options) => {
- abortSignal = options?.signal;
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- stream.push({ type: "start", partial: createAssistantMessage("") });
- const checkAbort = () => {
- if (abortSignal?.aborted) {
- stream.push({ type: "error", reason: "aborted", error: createAssistantMessage("Aborted") });
- } else {
- setTimeout(checkAbort, 5);
- }
- };
- checkAbort();
- });
- return stream;
- },
- });
-
- // Start first prompt
- const firstPrompt = agent.prompt("First message");
- await new Promise((resolve) => setTimeout(resolve, 10));
- expect(agent.state.isStreaming).toBe(true);
-
- // continue() should reject
- await expect(agent.continue()).rejects.toThrow(
- "Agent is already processing. Wait for completion before continuing.",
- );
-
- // Cleanup
- agent.abort();
- await firstPrompt.catch(() => {});
- });
-
- it("continue() should process queued follow-up messages after an assistant turn", async () => {
- const agent = new Agent({
- streamFn: () => {
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- stream.push({ type: "done", reason: "stop", message: createAssistantMessage("Processed") });
- });
- return stream;
- },
- });
-
- agent.state.messages = [
- {
- role: "user",
- content: [{ type: "text", text: "Initial" }],
- timestamp: Date.now() - 10,
- },
- createAssistantMessage("Initial response"),
- ];
-
- agent.followUp({
- role: "user",
- content: [{ type: "text", text: "Queued follow-up" }],
- timestamp: Date.now(),
- });
-
- await expect(agent.continue()).resolves.toBeUndefined();
-
- const hasQueuedFollowUp = agent.state.messages.some((message) => {
- if (message.role !== "user") return false;
- if (typeof message.content === "string") return message.content === "Queued follow-up";
- return message.content.some((part) => part.type === "text" && part.text === "Queued follow-up");
- });
-
- expect(hasQueuedFollowUp).toBe(true);
- expect(agent.state.messages[agent.state.messages.length - 1].role).toBe("assistant");
- });
-
- it("continue() should keep one-at-a-time steering semantics from assistant tail", async () => {
- let responseCount = 0;
- const agent = new Agent({
- streamFn: () => {
- const stream = new MockAssistantStream();
- responseCount++;
- queueMicrotask(() => {
- stream.push({
- type: "done",
- reason: "stop",
- message: createAssistantMessage(`Processed ${responseCount}`),
- });
- });
- return stream;
- },
- });
-
- agent.state.messages = [
- {
- role: "user",
- content: [{ type: "text", text: "Initial" }],
- timestamp: Date.now() - 10,
- },
- createAssistantMessage("Initial response"),
- ];
-
- agent.steer({
- role: "user",
- content: [{ type: "text", text: "Steering 1" }],
- timestamp: Date.now(),
- });
- agent.steer({
- role: "user",
- content: [{ type: "text", text: "Steering 2" }],
- timestamp: Date.now() + 1,
- });
-
- await expect(agent.continue()).resolves.toBeUndefined();
-
- const recentMessages = agent.state.messages.slice(-4);
- expect(recentMessages.map((m) => m.role)).toEqual(["user", "assistant", "user", "assistant"]);
- expect(responseCount).toBe(2);
- });
-
- it("forwards sessionId to streamFn options", async () => {
- let receivedSessionId: string | undefined;
- const agent = new Agent({
- sessionId: "session-abc",
- streamFn: (_model, _context, options) => {
- receivedSessionId = options?.sessionId;
- const stream = new MockAssistantStream();
- queueMicrotask(() => {
- const message = createAssistantMessage("ok");
- stream.push({ type: "done", reason: "stop", message });
- });
- return stream;
- },
- });
-
- await agent.prompt("hello");
- expect(receivedSessionId).toBe("session-abc");
-
- // Test setter
- agent.sessionId = "session-def";
- expect(agent.sessionId).toBe("session-def");
-
- await agent.prompt("hello again");
- expect(receivedSessionId).toBe("session-def");
- });
-});
diff --git a/pi-mono-reference/packages/agent/test/e2e.test.ts b/pi-mono-reference/packages/agent/test/e2e.test.ts
deleted file mode 100644
index f032555e..00000000
--- a/pi-mono-reference/packages/agent/test/e2e.test.ts
+++ /dev/null
@@ -1,404 +0,0 @@
-import {
- type AssistantMessage,
- type FauxProviderRegistration,
- fauxAssistantMessage,
- fauxText,
- fauxThinking,
- fauxToolCall,
- type Model,
- registerFauxProvider,
- type ToolResultMessage,
- type UserMessage,
-} from "@mariozechner/pi-ai";
-import { afterEach, describe, expect, it } from "vitest";
-import { Agent, type AgentEvent } from "../src/index.js";
-import { calculateTool } from "./utils/calculate.js";
-
-const registrations: FauxProviderRegistration[] = [];
-
-function createFauxRegistration(options: Parameters[0] = {}): FauxProviderRegistration {
- const registration = registerFauxProvider(options);
- registrations.push(registration);
- return registration;
-}
-
-function getTextContent(message: AssistantMessage | ToolResultMessage): string {
- return message.content
- .filter((block) => block.type === "text")
- .map((block) => block.text)
- .join("\n");
-}
-
-afterEach(() => {
- while (registrations.length > 0) {
- registrations.pop()?.unregister();
- }
-});
-
-async function basicPrompt(model: Model) {
- const agent = new Agent({
- initialState: {
- systemPrompt: "You are a helpful assistant. Keep your responses concise.",
- model,
- thinkingLevel: "off",
- tools: [],
- },
- });
-
- await agent.prompt("What is 2+2? Answer with just the number.");
-
- expect(agent.state.isStreaming).toBe(false);
- expect(agent.state.messages.length).toBe(2);
- expect(agent.state.messages[0].role).toBe("user");
- expect(agent.state.messages[1].role).toBe("assistant");
-
- const assistantMessage = agent.state.messages[1];
- if (assistantMessage.role !== "assistant") throw new Error("Expected assistant message");
- expect(getTextContent(assistantMessage)).toContain("4");
-}
-
-async function toolExecution(model: Model) {
- const agent = new Agent({
- initialState: {
- systemPrompt: "You are a helpful assistant. Always use the calculator tool for math.",
- model,
- thinkingLevel: "off",
- tools: [calculateTool],
- },
- });
-
- const pendingToolCallsDuringEvents: Array<{ type: AgentEvent["type"]; ids: string[] }> = [];
- agent.subscribe((event) => {
- if (event.type === "tool_execution_start" || event.type === "tool_execution_end") {
- pendingToolCallsDuringEvents.push({
- type: event.type,
- ids: [...agent.state.pendingToolCalls],
- });
- }
- });
-
- await agent.prompt("Calculate 123 * 456 using the calculator tool.");
-
- expect(agent.state.isStreaming).toBe(false);
- expect(agent.state.messages.length).toBeGreaterThanOrEqual(4);
- const toolResultMsg = agent.state.messages.find((message) => message.role === "toolResult");
- expect(toolResultMsg).toBeDefined();
- if (toolResultMsg?.role !== "toolResult") throw new Error("Expected tool result message");
- expect(getTextContent(toolResultMsg)).toContain("123 * 456 = 56088");
-
- const finalMessage = agent.state.messages[agent.state.messages.length - 1];
- if (finalMessage.role !== "assistant") throw new Error("Expected final assistant message");
- expect(getTextContent(finalMessage)).toContain("56088");
- expect(agent.state.pendingToolCalls.size).toBe(0);
- expect(pendingToolCallsDuringEvents).toEqual([
- { type: "tool_execution_start", ids: ["calc-1"] },
- { type: "tool_execution_end", ids: [] },
- ]);
-}
-
-async function abortExecution(model: Model) {
- const agent = new Agent({
- initialState: {
- systemPrompt: "You are a helpful assistant.",
- model,
- thinkingLevel: "off",
- tools: [],
- },
- });
-
- const promptPromise = agent.prompt("Count slowly from 1 to 20.");
- setTimeout(() => {
- agent.abort();
- }, 30);
-
- await promptPromise;
-
- expect(agent.state.isStreaming).toBe(false);
- expect(agent.state.messages.length).toBeGreaterThanOrEqual(2);
-
- const lastMessage = agent.state.messages[agent.state.messages.length - 1];
- if (lastMessage.role !== "assistant") throw new Error("Expected assistant message");
- expect(lastMessage.stopReason).toBe("aborted");
- expect(lastMessage.errorMessage).toBeDefined();
- expect(agent.state.errorMessage).toBe(lastMessage.errorMessage);
-}
-
-async function stateUpdates(model: Model) {
- const agent = new Agent({
- initialState: {
- systemPrompt: "You are a helpful assistant.",
- model,
- thinkingLevel: "off",
- tools: [],
- },
- });
-
- const events: AgentEvent["type"][] = [];
- agent.subscribe((event) => {
- events.push(event.type);
- });
-
- await agent.prompt("Count from 1 to 5.");
-
- expect(events).toContain("agent_start");
- expect(events).toContain("turn_start");
- expect(events).toContain("message_start");
- expect(events).toContain("message_update");
- expect(events).toContain("message_end");
- expect(events).toContain("turn_end");
- expect(events).toContain("agent_end");
- expect(events.indexOf("agent_start")).toBeLessThan(events.indexOf("message_start"));
- expect(events.indexOf("message_start")).toBeLessThan(events.indexOf("message_end"));
- expect(events.indexOf("message_end")).toBeLessThan(events.lastIndexOf("agent_end"));
-
- expect(agent.state.isStreaming).toBe(false);
- expect(agent.state.messages.length).toBe(2);
-}
-
-async function multiTurnConversation(model: Model) {
- const agent = new Agent({
- initialState: {
- systemPrompt: "You are a helpful assistant.",
- model,
- thinkingLevel: "off",
- tools: [],
- },
- });
-
- await agent.prompt("My name is Alice.");
- expect(agent.state.messages.length).toBe(2);
-
- await agent.prompt("What is my name?");
- expect(agent.state.messages.length).toBe(4);
-
- const lastMessage = agent.state.messages[3];
- if (lastMessage.role !== "assistant") throw new Error("Expected assistant message");
- expect(getTextContent(lastMessage).toLowerCase()).toContain("alice");
-}
-
-describe("Agent integration with faux provider", () => {
- it("handles a basic text prompt", async () => {
- const faux = createFauxRegistration();
- faux.setResponses([fauxAssistantMessage("4")]);
- await basicPrompt(faux.getModel());
- });
-
- it("executes tools and tracks pending tool calls", async () => {
- const faux = createFauxRegistration();
- faux.setResponses([
- fauxAssistantMessage(
- [
- fauxText("Let me calculate that."),
- fauxToolCall("calculate", { expression: "123 * 456" }, { id: "calc-1" }),
- ],
- { stopReason: "toolUse" },
- ),
- fauxAssistantMessage("The result is 56088."),
- ]);
- await toolExecution(faux.getModel());
- });
-
- it("handles abort during streaming", async () => {
- const faux = createFauxRegistration({
- tokensPerSecond: 20,
- tokenSize: { min: 2, max: 2 },
- });
- faux.setResponses([
- fauxAssistantMessage(
- "one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen",
- ),
- ]);
- await abortExecution(faux.getModel());
- });
-
- it("emits lifecycle updates while streaming", async () => {
- const faux = createFauxRegistration({ tokenSize: { min: 1, max: 1 } });
- faux.setResponses([fauxAssistantMessage("1 2 3 4 5")]);
- await stateUpdates(faux.getModel());
- });
-
- it("maintains context across multiple turns", async () => {
- const faux = createFauxRegistration();
- faux.setResponses([
- fauxAssistantMessage("Nice to meet you, Alice."),
- (context) => {
- const hasAlice = context.messages.some((message) => {
- if (message.role !== "user") return false;
- if (typeof message.content === "string") return message.content.includes("Alice");
- return message.content.some((block) => block.type === "text" && block.text.includes("Alice"));
- });
- return fauxAssistantMessage(hasAlice ? "Your name is Alice." : "I do not know your name.");
- },
- ]);
- await multiTurnConversation(faux.getModel());
- });
-
- it("preserves thinking content blocks", async () => {
- const faux = createFauxRegistration({ models: [{ id: "faux-reasoning", reasoning: true }] });
- faux.setResponses([fauxAssistantMessage([fauxThinking("step by step"), fauxText("4")])]);
-
- const agent = new Agent({
- initialState: {
- systemPrompt: "You are a helpful assistant.",
- model: faux.getModel(),
- thinkingLevel: "low",
- tools: [],
- },
- });
-
- await agent.prompt("What is 2+2?");
-
- const assistantMessage = agent.state.messages[1];
- if (assistantMessage?.role !== "assistant") throw new Error("Expected assistant message");
- expect(assistantMessage.content).toEqual([
- { type: "thinking", thinking: "step by step" },
- { type: "text", text: "4" },
- ]);
- });
-});
-
-describe("Agent.continue() with faux provider", () => {
- describe("validation", () => {
- it("throws when no messages in context", async () => {
- const faux = createFauxRegistration();
- const agent = new Agent({
- initialState: {
- systemPrompt: "Test",
- model: faux.getModel(),
- },
- });
-
- await expect(agent.continue()).rejects.toThrow("No messages to continue from");
- });
-
- it("throws when last message is assistant", async () => {
- const faux = createFauxRegistration();
- const model = faux.getModel();
- const agent = new Agent({
- initialState: {
- systemPrompt: "Test",
- model,
- },
- });
-
- const assistantMessage: AssistantMessage = {
- role: "assistant",
- content: [{ type: "text", text: "Hello" }],
- api: model.api,
- provider: model.provider,
- model: model.id,
- usage: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- stopReason: "stop",
- timestamp: Date.now(),
- };
- agent.state.messages = [assistantMessage];
-
- await expect(agent.continue()).rejects.toThrow("Cannot continue from message role: assistant");
- });
- });
-
- describe("continue from user message", () => {
- it("continues and gets a response when last message is user", async () => {
- const faux = createFauxRegistration();
- faux.setResponses([fauxAssistantMessage("HELLO WORLD")]);
- const agent = new Agent({
- initialState: {
- systemPrompt: "You are a helpful assistant. Follow instructions exactly.",
- model: faux.getModel(),
- thinkingLevel: "off",
- tools: [],
- },
- });
-
- const userMessage: UserMessage = {
- role: "user",
- content: [{ type: "text", text: "Say exactly: HELLO WORLD" }],
- timestamp: Date.now(),
- };
- agent.state.messages = [userMessage];
-
- await agent.continue();
-
- expect(agent.state.isStreaming).toBe(false);
- expect(agent.state.messages.length).toBe(2);
- expect(agent.state.messages[0].role).toBe("user");
- expect(agent.state.messages[1].role).toBe("assistant");
-
- const assistantMsg = agent.state.messages[1];
- if (assistantMsg.role !== "assistant") throw new Error("Expected assistant message");
- expect(getTextContent(assistantMsg).toUpperCase()).toContain("HELLO WORLD");
- });
- });
-
- describe("continue from tool result", () => {
- it("continues and processes tool results", async () => {
- const faux = createFauxRegistration();
- const model = faux.getModel();
- faux.setResponses([fauxAssistantMessage("The answer is 8.")]);
- const agent = new Agent({
- initialState: {
- systemPrompt:
- "You are a helpful assistant. After getting a calculation result, state the answer clearly.",
- model,
- thinkingLevel: "off",
- tools: [calculateTool],
- },
- });
-
- const userMessage: UserMessage = {
- role: "user",
- content: [{ type: "text", text: "What is 5 + 3?" }],
- timestamp: Date.now(),
- };
-
- const assistantMessage: AssistantMessage = {
- role: "assistant",
- content: [
- { type: "text", text: "Let me calculate that." },
- { type: "toolCall", id: "calc-1", name: "calculate", arguments: { expression: "5 + 3" } },
- ],
- api: model.api,
- provider: model.provider,
- model: model.id,
- usage: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- stopReason: "toolUse",
- timestamp: Date.now(),
- };
-
- const toolResult: ToolResultMessage = {
- role: "toolResult",
- toolCallId: "calc-1",
- toolName: "calculate",
- content: [{ type: "text", text: "5 + 3 = 8" }],
- isError: false,
- timestamp: Date.now(),
- };
-
- agent.state.messages = [userMessage, assistantMessage, toolResult];
-
- await agent.continue();
-
- expect(agent.state.isStreaming).toBe(false);
- expect(agent.state.messages.length).toBeGreaterThanOrEqual(4);
-
- const lastMessage = agent.state.messages[agent.state.messages.length - 1];
- expect(lastMessage.role).toBe("assistant");
- if (lastMessage.role !== "assistant") throw new Error("Expected assistant message");
- expect(getTextContent(lastMessage)).toContain("8");
- });
- });
-});
diff --git a/pi-mono-reference/packages/agent/test/utils/calculate.ts b/pi-mono-reference/packages/agent/test/utils/calculate.ts
deleted file mode 100644
index af5b17c4..00000000
--- a/pi-mono-reference/packages/agent/test/utils/calculate.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { type Static, Type } from "@sinclair/typebox";
-import type { AgentTool, AgentToolResult } from "../../src/types.js";
-
-export interface CalculateResult extends AgentToolResult {
- content: Array<{ type: "text"; text: string }>;
- details: undefined;
-}
-
-export function calculate(expression: string): CalculateResult {
- try {
- const result = new Function(`return ${expression}`)();
- return { content: [{ type: "text", text: `${expression} = ${result}` }], details: undefined };
- } catch (e: any) {
- throw new Error(e.message || String(e));
- }
-}
-
-const calculateSchema = Type.Object({
- expression: Type.String({ description: "The mathematical expression to evaluate" }),
-});
-
-type CalculateParams = Static;
-
-export const calculateTool: AgentTool = {
- label: "Calculator",
- name: "calculate",
- description: "Evaluate mathematical expressions",
- parameters: calculateSchema,
- execute: async (_toolCallId: string, args: CalculateParams) => {
- return calculate(args.expression);
- },
-};
diff --git a/pi-mono-reference/packages/agent/test/utils/get-current-time.ts b/pi-mono-reference/packages/agent/test/utils/get-current-time.ts
deleted file mode 100644
index 814233b1..00000000
--- a/pi-mono-reference/packages/agent/test/utils/get-current-time.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { type Static, Type } from "@sinclair/typebox";
-import type { AgentTool, AgentToolResult } from "../../src/types.js";
-
-export interface GetCurrentTimeResult extends AgentToolResult<{ utcTimestamp: number }> {}
-
-export async function getCurrentTime(timezone?: string): Promise {
- const date = new Date();
- if (timezone) {
- try {
- const timeStr = date.toLocaleString("en-US", {
- timeZone: timezone,
- dateStyle: "full",
- timeStyle: "long",
- });
- return {
- content: [{ type: "text", text: timeStr }],
- details: { utcTimestamp: date.getTime() },
- };
- } catch (_e) {
- throw new Error(`Invalid timezone: ${timezone}. Current UTC time: ${date.toISOString()}`);
- }
- }
- const timeStr = date.toLocaleString("en-US", { dateStyle: "full", timeStyle: "long" });
- return {
- content: [{ type: "text", text: timeStr }],
- details: { utcTimestamp: date.getTime() },
- };
-}
-
-const getCurrentTimeSchema = Type.Object({
- timezone: Type.Optional(
- Type.String({ description: "Optional timezone (e.g., 'America/New_York', 'Europe/London')" }),
- ),
-});
-
-type GetCurrentTimeParams = Static;
-
-export const getCurrentTimeTool: AgentTool = {
- label: "Current Time",
- name: "get_current_time",
- description: "Get the current date and time",
- parameters: getCurrentTimeSchema,
- execute: async (_toolCallId: string, args: GetCurrentTimeParams) => {
- return getCurrentTime(args.timezone);
- },
-};
diff --git a/pi-mono-reference/packages/agent/tsconfig.build.json b/pi-mono-reference/packages/agent/tsconfig.build.json
deleted file mode 100644
index 695dd9ad..00000000
--- a/pi-mono-reference/packages/agent/tsconfig.build.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "outDir": "./dist",
- "rootDir": "./src"
- },
- "include": ["src/**/*.ts"],
- "exclude": ["node_modules", "dist", "**/*.d.ts", "src/**/*.d.ts"]
-}
diff --git a/pi-mono-reference/packages/agent/vitest.config.ts b/pi-mono-reference/packages/agent/vitest.config.ts
deleted file mode 100644
index bcc497fa..00000000
--- a/pi-mono-reference/packages/agent/vitest.config.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { defineConfig } from "vitest/config";
-
-export default defineConfig({
- test: {
- globals: true,
- environment: "node",
- testTimeout: 30000, // 30 seconds for API calls
- },
-});
diff --git a/pi-mono-reference/packages/ai/bedrock-provider.d.ts b/pi-mono-reference/packages/ai/bedrock-provider.d.ts
deleted file mode 100644
index a66eabee..00000000
--- a/pi-mono-reference/packages/ai/bedrock-provider.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./dist/bedrock-provider.js";
diff --git a/pi-mono-reference/packages/ai/bedrock-provider.js b/pi-mono-reference/packages/ai/bedrock-provider.js
deleted file mode 100644
index a66eabee..00000000
--- a/pi-mono-reference/packages/ai/bedrock-provider.js
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./dist/bedrock-provider.js";
diff --git a/pi-mono-reference/packages/ai/package.json b/pi-mono-reference/packages/ai/package.json
deleted file mode 100644
index c68ca28b..00000000
--- a/pi-mono-reference/packages/ai/package.json
+++ /dev/null
@@ -1,114 +0,0 @@
-{
- "name": "@mariozechner/pi-ai",
- "version": "0.67.5",
- "description": "Unified LLM API with automatic model discovery and provider configuration",
- "type": "module",
- "main": "./dist/index.js",
- "types": "./dist/index.d.ts",
- "exports": {
- ".": {
- "types": "./dist/index.d.ts",
- "import": "./dist/index.js"
- },
- "./anthropic": {
- "types": "./dist/providers/anthropic.d.ts",
- "import": "./dist/providers/anthropic.js"
- },
- "./azure-openai-responses": {
- "types": "./dist/providers/azure-openai-responses.d.ts",
- "import": "./dist/providers/azure-openai-responses.js"
- },
- "./google": {
- "types": "./dist/providers/google.d.ts",
- "import": "./dist/providers/google.js"
- },
- "./google-gemini-cli": {
- "types": "./dist/providers/google-gemini-cli.d.ts",
- "import": "./dist/providers/google-gemini-cli.js"
- },
- "./google-vertex": {
- "types": "./dist/providers/google-vertex.d.ts",
- "import": "./dist/providers/google-vertex.js"
- },
- "./mistral": {
- "types": "./dist/providers/mistral.d.ts",
- "import": "./dist/providers/mistral.js"
- },
- "./openai-codex-responses": {
- "types": "./dist/providers/openai-codex-responses.d.ts",
- "import": "./dist/providers/openai-codex-responses.js"
- },
- "./openai-completions": {
- "types": "./dist/providers/openai-completions.d.ts",
- "import": "./dist/providers/openai-completions.js"
- },
- "./openai-responses": {
- "types": "./dist/providers/openai-responses.d.ts",
- "import": "./dist/providers/openai-responses.js"
- },
- "./oauth": {
- "types": "./dist/oauth.d.ts",
- "import": "./dist/oauth.js"
- },
- "./bedrock-provider": {
- "types": "./dist/bedrock-provider.d.ts",
- "import": "./dist/bedrock-provider.js"
- }
- },
- "bin": {
- "pi-ai": "./dist/cli.js"
- },
- "files": [
- "dist",
- "README.md"
- ],
- "scripts": {
- "clean": "shx rm -rf dist",
- "generate-models": "npx tsx scripts/generate-models.ts",
- "build": "npm run generate-models && tsgo -p tsconfig.build.json",
- "dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput",
- "dev:tsc": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput",
- "test": "vitest --run",
- "prepublishOnly": "npm run clean && npm run build"
- },
- "dependencies": {
- "@anthropic-ai/sdk": "^0.90.0",
- "@aws-sdk/client-bedrock-runtime": "^3.1030.0",
- "@google/genai": "^1.40.0",
- "@mistralai/mistralai": "1.14.1",
- "@sinclair/typebox": "^0.34.41",
- "ajv": "^8.17.1",
- "ajv-formats": "^3.0.1",
- "chalk": "^5.6.2",
- "openai": "6.26.0",
- "partial-json": "^0.1.7",
- "proxy-agent": "^6.5.0",
- "undici": "^7.19.1",
- "zod-to-json-schema": "^3.24.6"
- },
- "keywords": [
- "ai",
- "llm",
- "openai",
- "anthropic",
- "gemini",
- "bedrock",
- "unified",
- "api"
- ],
- "author": "Mario Zechner",
- "license": "MIT",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/badlogic/pi-mono.git",
- "directory": "packages/ai"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "devDependencies": {
- "@types/node": "^24.3.0",
- "canvas": "^3.2.0",
- "vitest": "^3.2.4"
- }
-}
diff --git a/pi-mono-reference/packages/ai/scripts/generate-models.ts b/pi-mono-reference/packages/ai/scripts/generate-models.ts
deleted file mode 100644
index ea5e14a1..00000000
--- a/pi-mono-reference/packages/ai/scripts/generate-models.ts
+++ /dev/null
@@ -1,1584 +0,0 @@
-#!/usr/bin/env tsx
-
-import { writeFileSync } from "fs";
-import { join, dirname } from "path";
-import { fileURLToPath } from "url";
-import { Api, KnownProvider, Model } from "../src/types.js";
-
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
-const packageRoot = join(__dirname, "..");
-
-interface ModelsDevModel {
- id: string;
- name: string;
- tool_call?: boolean;
- reasoning?: boolean;
- limit?: {
- context?: number;
- output?: number;
- };
- cost?: {
- input?: number;
- output?: number;
- cache_read?: number;
- cache_write?: number;
- };
- modalities?: {
- input?: string[];
- };
- provider?: {
- npm?: string;
- };
-}
-
-interface AiGatewayModel {
- id: string;
- name?: string;
- context_window?: number;
- max_tokens?: number;
- tags?: string[];
- pricing?: {
- input?: string | number;
- output?: string | number;
- input_cache_read?: string | number;
- input_cache_write?: string | number;
- };
-}
-
-const COPILOT_STATIC_HEADERS = {
- "User-Agent": "GitHubCopilotChat/0.35.0",
- "Editor-Version": "vscode/1.107.0",
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
- "Copilot-Integration-Id": "vscode-chat",
-} as const;
-
-const AI_GATEWAY_MODELS_URL = "https://ai-gateway.vercel.sh/v1";
-const AI_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
-const ZAI_TOOL_STREAM_UNSUPPORTED_MODELS = new Set(["glm-4.5", "glm-4.5-air", "glm-4.5-flash", "glm-4.5v"]);
-
-async function fetchOpenRouterModels(): Promise[]> {
- try {
- console.log("Fetching models from OpenRouter API...");
- const response = await fetch("https://openrouter.ai/api/v1/models");
- const data = await response.json();
-
- const models: Model[] = [];
-
- for (const model of data.data) {
- // Only include models that support tools
- if (!model.supported_parameters?.includes("tools")) continue;
-
- // Parse provider from model ID
- let provider: KnownProvider = "openrouter";
- let modelKey = model.id;
-
- modelKey = model.id; // Keep full ID for OpenRouter
-
- // Parse input modalities
- const input: ("text" | "image")[] = ["text"];
- if (model.architecture?.modality?.includes("image")) {
- input.push("image");
- }
-
- // Convert pricing from $/token to $/million tokens
- const inputCost = parseFloat(model.pricing?.prompt || "0") * 1_000_000;
- const outputCost = parseFloat(model.pricing?.completion || "0") * 1_000_000;
- const cacheReadCost = parseFloat(model.pricing?.input_cache_read || "0") * 1_000_000;
- const cacheWriteCost = parseFloat(model.pricing?.input_cache_write || "0") * 1_000_000;
-
- const normalizedModel: Model = {
- id: modelKey,
- name: model.name,
- api: "openai-completions",
- baseUrl: "https://openrouter.ai/api/v1",
- provider,
- reasoning: model.supported_parameters?.includes("reasoning") || false,
- input,
- cost: {
- input: inputCost,
- output: outputCost,
- cacheRead: cacheReadCost,
- cacheWrite: cacheWriteCost,
- },
- contextWindow: model.context_length || 4096,
- maxTokens: model.top_provider?.max_completion_tokens || 4096,
- };
- models.push(normalizedModel);
- }
-
- console.log(`Fetched ${models.length} tool-capable models from OpenRouter`);
- return models;
- } catch (error) {
- console.error("Failed to fetch OpenRouter models:", error);
- return [];
- }
-}
-
-async function fetchAiGatewayModels(): Promise[]> {
- try {
- console.log("Fetching models from Vercel AI Gateway API...");
- const response = await fetch(`${AI_GATEWAY_MODELS_URL}/models`);
- const data = await response.json();
- const models: Model[] = [];
-
- const toNumber = (value: string | number | undefined): number => {
- if (typeof value === "number") {
- return Number.isFinite(value) ? value : 0;
- }
- const parsed = parseFloat(value ?? "0");
- return Number.isFinite(parsed) ? parsed : 0;
- };
-
- const items = Array.isArray(data.data) ? (data.data as AiGatewayModel[]) : [];
- for (const model of items) {
- const tags = Array.isArray(model.tags) ? model.tags : [];
- // Only include models that support tools
- if (!tags.includes("tool-use")) continue;
-
- const input: ("text" | "image")[] = ["text"];
- if (tags.includes("vision")) {
- input.push("image");
- }
-
- const inputCost = toNumber(model.pricing?.input) * 1_000_000;
- const outputCost = toNumber(model.pricing?.output) * 1_000_000;
- const cacheReadCost = toNumber(model.pricing?.input_cache_read) * 1_000_000;
- const cacheWriteCost = toNumber(model.pricing?.input_cache_write) * 1_000_000;
-
- models.push({
- id: model.id,
- name: model.name || model.id,
- api: "anthropic-messages",
- baseUrl: AI_GATEWAY_BASE_URL,
- provider: "vercel-ai-gateway",
- reasoning: tags.includes("reasoning"),
- input,
- cost: {
- input: inputCost,
- output: outputCost,
- cacheRead: cacheReadCost,
- cacheWrite: cacheWriteCost,
- },
- contextWindow: model.context_window || 4096,
- maxTokens: model.max_tokens || 4096,
- });
- }
-
- console.log(`Fetched ${models.length} tool-capable models from Vercel AI Gateway`);
- return models;
- } catch (error) {
- console.error("Failed to fetch Vercel AI Gateway models:", error);
- return [];
- }
-}
-
-async function loadModelsDevData(): Promise[]> {
- try {
- console.log("Fetching models from models.dev API...");
- const response = await fetch("https://models.dev/api.json");
- const data = await response.json();
-
- const models: Model[] = [];
-
- // Process Amazon Bedrock models
- if (data["amazon-bedrock"]?.models) {
- for (const [modelId, model] of Object.entries(data["amazon-bedrock"].models)) {
- const m = model as ModelsDevModel;
- if (m.tool_call !== true) continue;
-
- let id = modelId;
-
- if (id.startsWith("ai21.jamba")) {
- // These models doesn't support tool use in streaming mode
- continue;
- }
-
- if (id.startsWith("mistral.mistral-7b-instruct-v0")) {
- // These models doesn't support system messages
- continue;
- }
-
- models.push({
- id,
- name: m.name || id,
- api: "bedrock-converse-stream" as const,
- provider: "amazon-bedrock" as const,
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: m.reasoning === true,
- input: (m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"]) as ("text" | "image")[],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
-
- // Process Anthropic models
- if (data.anthropic?.models) {
- for (const [modelId, model] of Object.entries(data.anthropic.models)) {
- const m = model as ModelsDevModel;
- if (m.tool_call !== true) continue;
-
- models.push({
- id: modelId,
- name: m.name || modelId,
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: m.reasoning === true,
- input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
-
- // Process Google models
- if (data.google?.models) {
- for (const [modelId, model] of Object.entries(data.google.models)) {
- const m = model as ModelsDevModel;
- if (m.tool_call !== true) continue;
-
- models.push({
- id: modelId,
- name: m.name || modelId,
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: m.reasoning === true,
- input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
-
- // Process OpenAI models
- if (data.openai?.models) {
- for (const [modelId, model] of Object.entries(data.openai.models)) {
- const m = model as ModelsDevModel;
- if (m.tool_call !== true) continue;
-
- models.push({
- id: modelId,
- name: m.name || modelId,
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: m.reasoning === true,
- input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
-
- // Process Groq models
- if (data.groq?.models) {
- for (const [modelId, model] of Object.entries(data.groq.models)) {
- const m = model as ModelsDevModel;
- if (m.tool_call !== true) continue;
-
- models.push({
- id: modelId,
- name: m.name || modelId,
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: m.reasoning === true,
- input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
-
- // Process Cerebras models
- if (data.cerebras?.models) {
- for (const [modelId, model] of Object.entries(data.cerebras.models)) {
- const m = model as ModelsDevModel;
- if (m.tool_call !== true) continue;
-
- models.push({
- id: modelId,
- name: m.name || modelId,
- api: "openai-completions",
- provider: "cerebras",
- baseUrl: "https://api.cerebras.ai/v1",
- reasoning: m.reasoning === true,
- input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
-
- // Process xAi models
- if (data.xai?.models) {
- for (const [modelId, model] of Object.entries(data.xai.models)) {
- const m = model as ModelsDevModel;
- if (m.tool_call !== true) continue;
-
- models.push({
- id: modelId,
- name: m.name || modelId,
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: m.reasoning === true,
- input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
-
- // Process zAi models
- if (data["zai-coding-plan"]?.models) {
- for (const [modelId, model] of Object.entries(data["zai-coding-plan"].models)) {
- const m = model as ModelsDevModel;
- if (m.tool_call !== true) continue;
- const supportsImage = m.modalities?.input?.includes("image");
-
- models.push({
- id: modelId,
- name: m.name || modelId,
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- reasoning: m.reasoning === true,
- input: supportsImage ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- compat: {
- supportsDeveloperRole: false,
- thinkingFormat: "zai",
- ...(!ZAI_TOOL_STREAM_UNSUPPORTED_MODELS.has(modelId) ? { zaiToolStream: true } : {}),
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
-
- // Process Mistral models
- if (data.mistral?.models) {
- for (const [modelId, model] of Object.entries(data.mistral.models)) {
- const m = model as ModelsDevModel;
- if (m.tool_call !== true) continue;
-
- models.push({
- id: modelId,
- name: m.name || modelId,
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: m.reasoning === true,
- input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
-
- // Process Hugging Face models
- if (data.huggingface?.models) {
- for (const [modelId, model] of Object.entries(data.huggingface.models)) {
- const m = model as ModelsDevModel;
- if (m.tool_call !== true) continue;
-
- models.push({
- id: modelId,
- name: m.name || modelId,
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- reasoning: m.reasoning === true,
- input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- compat: {
- supportsDeveloperRole: false,
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
-
- // Process OpenCode models (Zen and Go)
- // API mapping based on provider.npm field:
- // - @ai-sdk/openai → openai-responses
- // - @ai-sdk/anthropic → anthropic-messages
- // - @ai-sdk/google → google-generative-ai
- // - null/undefined/@ai-sdk/openai-compatible → openai-completions
- const opencodeVariants = [
- { key: "opencode", provider: "opencode", basePath: "https://opencode.ai/zen" },
- { key: "opencode-go", provider: "opencode-go", basePath: "https://opencode.ai/zen/go" },
- ] as const;
-
- for (const variant of opencodeVariants) {
- if (!data[variant.key]?.models) continue;
-
- for (const [modelId, model] of Object.entries(data[variant.key].models)) {
- const m = model as ModelsDevModel & { status?: string };
- if (m.tool_call !== true) continue;
- if (m.status === "deprecated") continue;
-
- const npm = m.provider?.npm;
- let api: Api;
- let baseUrl: string;
-
- if (npm === "@ai-sdk/openai") {
- api = "openai-responses";
- baseUrl = `${variant.basePath}/v1`;
- } else if (npm === "@ai-sdk/anthropic") {
- api = "anthropic-messages";
- // Anthropic SDK appends /v1/messages to baseURL
- baseUrl = variant.basePath;
- } else if (npm === "@ai-sdk/google") {
- api = "google-generative-ai";
- baseUrl = `${variant.basePath}/v1`;
- } else {
- // null, undefined, or @ai-sdk/openai-compatible
- api = "openai-completions";
- baseUrl = `${variant.basePath}/v1`;
- }
-
- models.push({
- id: modelId,
- name: m.name || modelId,
- api,
- provider: variant.provider,
- baseUrl,
- reasoning: m.reasoning === true,
- input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
-
- // Process GitHub Copilot models
- if (data["github-copilot"]?.models) {
- for (const [modelId, model] of Object.entries(data["github-copilot"].models)) {
- const m = model as ModelsDevModel & { status?: string };
- if (m.tool_call !== true) continue;
- if (m.status === "deprecated") continue;
-
- // Claude 4.x models route to Anthropic Messages API
- const isCopilotClaude4 = /^claude-(haiku|sonnet|opus)-4([.\-]|$)/.test(modelId);
- // gpt-5 models require responses API, others use completions
- const needsResponsesApi = modelId.startsWith("gpt-5") || modelId.startsWith("oswe");
-
- const api: Api = isCopilotClaude4
- ? "anthropic-messages"
- : needsResponsesApi
- ? "openai-responses"
- : "openai-completions";
-
- const copilotModel: Model = {
- id: modelId,
- name: m.name || modelId,
- api,
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- reasoning: m.reasoning === true,
- input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- contextWindow: m.limit?.context || 128000,
- maxTokens: m.limit?.output || 8192,
- headers: { ...COPILOT_STATIC_HEADERS },
- // compat only applies to openai-completions
- ...(api === "openai-completions" ? {
- compat: {
- supportsStore: false,
- supportsDeveloperRole: false,
- supportsReasoningEffort: false,
- },
- } : {}),
- };
-
- models.push(copilotModel);
- }
- }
-
- // Process MiniMax models
- const minimaxVariants = [
- { key: "minimax", provider: "minimax", baseUrl: "https://api.minimax.io/anthropic" },
- { key: "minimax-cn", provider: "minimax-cn", baseUrl: "https://api.minimaxi.com/anthropic" },
- ] as const;
-
- for (const { key, provider, baseUrl } of minimaxVariants) {
- if (data[key]?.models) {
- for (const [modelId, model] of Object.entries(data[key].models)) {
- const m = model as ModelsDevModel;
- if (m.tool_call !== true) continue;
-
- models.push({
- id: modelId,
- name: m.name || modelId,
- api: "anthropic-messages",
- provider,
- // MiniMax's Anthropic-compatible API - SDK appends /v1/messages
- baseUrl,
- reasoning: m.reasoning === true,
- input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
- }
-
- // Process Kimi For Coding models
- if (data["kimi-for-coding"]?.models) {
- const kimiModels = data["kimi-for-coding"].models as Record;
- const hasCanonicalModel = Object.prototype.hasOwnProperty.call(kimiModels, "kimi-for-coding");
-
- for (const [modelId, model] of Object.entries(kimiModels)) {
- const m = model as ModelsDevModel;
- if (m.tool_call !== true) continue;
- // models.dev still exposes deprecated "k2p5" in some snapshots.
- // Normalize to the canonical model id and drop duplicates when canonical exists.
- if (modelId === "k2p5" && hasCanonicalModel) continue;
-
- const normalizedId = modelId === "k2p5" ? "kimi-for-coding" : modelId;
- const normalizedName = modelId === "k2p5" ? "Kimi For Coding" : m.name || normalizedId;
-
- models.push({
- id: normalizedId,
- name: normalizedName,
- api: "anthropic-messages",
- provider: "kimi-coding",
- // Kimi For Coding's Anthropic-compatible API - SDK appends /v1/messages
- baseUrl: "https://api.kimi.com/coding",
- reasoning: m.reasoning === true,
- input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
- cost: {
- input: m.cost?.input || 0,
- output: m.cost?.output || 0,
- cacheRead: m.cost?.cache_read || 0,
- cacheWrite: m.cost?.cache_write || 0,
- },
- contextWindow: m.limit?.context || 4096,
- maxTokens: m.limit?.output || 4096,
- });
- }
- }
-
- console.log(`Loaded ${models.length} tool-capable models from models.dev`);
- return models;
- } catch (error) {
- console.error("Failed to load models.dev data:", error);
- return [];
- }
-}
-
-async function generateModels() {
- // Fetch models from both sources
- // models.dev: Anthropic, Google, OpenAI, Groq, Cerebras
- // OpenRouter: xAI and other providers (excluding Anthropic, Google, OpenAI)
- // AI Gateway: OpenAI-compatible catalog with tool-capable models
- const modelsDevModels = await loadModelsDevData();
- const openRouterModels = await fetchOpenRouterModels();
- const aiGatewayModels = await fetchAiGatewayModels();
-
- // Combine models (models.dev has priority)
- const allModels = [...modelsDevModels, ...openRouterModels, ...aiGatewayModels].filter(
- (model) =>
- !((model.provider === "opencode" || model.provider === "opencode-go") && model.id === "gpt-5.3-codex-spark"),
- );
-
- // Fix incorrect cache pricing for Claude Opus 4.5 from models.dev
- // models.dev has 3x the correct pricing (1.5/18.75 instead of 0.5/6.25)
- const opus45 = allModels.find(m => m.provider === "anthropic" && m.id === "claude-opus-4-5");
- if (opus45) {
- opus45.cost.cacheRead = 0.5;
- opus45.cost.cacheWrite = 6.25;
- }
-
- // Temporary overrides until upstream model metadata is corrected.
- for (const candidate of allModels) {
- if (candidate.provider === "amazon-bedrock" && candidate.id.includes("anthropic.claude-opus-4-6-v1")) {
- candidate.cost.cacheRead = 0.5;
- candidate.cost.cacheWrite = 6.25;
- }
- if (
- (candidate.provider === "anthropic" ||
- candidate.provider === "opencode" ||
- candidate.provider === "opencode-go" ||
- candidate.provider === "github-copilot") &&
- (candidate.id === "claude-opus-4-6" ||
- candidate.id === "claude-sonnet-4-6" ||
- candidate.id === "claude-opus-4.6" ||
- candidate.id === "claude-sonnet-4.6")
- ) {
- candidate.contextWindow = 1000000;
- }
- if (
- candidate.provider === "google-antigravity" &&
- (candidate.id === "claude-opus-4-6-thinking" || candidate.id === "claude-sonnet-4-6")
- ) {
- candidate.contextWindow = 1000000;
- }
-
- // OpenCode variants list Claude Sonnet 4/4.5 with 1M context, actual limit is 200K
- if (
- (candidate.provider === "opencode" || candidate.provider === "opencode-go") &&
- (candidate.id === "claude-sonnet-4-5" || candidate.id === "claude-sonnet-4")
- ) {
- candidate.contextWindow = 200000;
- }
- if ((candidate.provider === "opencode" || candidate.provider === "opencode-go") && candidate.id === "gpt-5.4") {
- candidate.contextWindow = 272000;
- candidate.maxTokens = 128000;
- }
- if (candidate.provider === "openai" && candidate.id === "gpt-5.4") {
- candidate.contextWindow = 272000;
- candidate.maxTokens = 128000;
- }
- // Keep selected OpenRouter model metadata stable until upstream settles.
- if (candidate.provider === "openrouter" && candidate.id === "moonshotai/kimi-k2.5") {
- candidate.cost.input = 0.41;
- candidate.cost.output = 2.06;
- candidate.cost.cacheRead = 0.07;
- candidate.maxTokens = 4096;
- }
- if (candidate.provider === "openrouter" && candidate.id === "z-ai/glm-5") {
- candidate.cost.input = 0.6;
- candidate.cost.output = 1.9;
- candidate.cost.cacheRead = 0.119;
- }
-
- }
-
-
- // Add missing EU Opus 4.6 profile
- if (!allModels.some((m) => m.provider === "amazon-bedrock" && m.id === "eu.anthropic.claude-opus-4-6-v1")) {
- allModels.push({
- id: "eu.anthropic.claude-opus-4-6-v1",
- name: "Claude Opus 4.6 (EU)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 200000,
- maxTokens: 128000,
- });
- }
-
- // Add missing Claude Opus 4.6
- if (!allModels.some(m => m.provider === "anthropic" && m.id === "claude-opus-4-6")) {
- allModels.push({
- id: "claude-opus-4-6",
- name: "Claude Opus 4.6",
- api: "anthropic-messages",
- baseUrl: "https://api.anthropic.com",
- provider: "anthropic",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- });
- }
-
- // Add missing Claude Opus 4.7
- if (!allModels.some(m => m.provider === "anthropic" && m.id === "claude-opus-4-7")) {
- allModels.push({
- id: "claude-opus-4-7",
- name: "Claude Opus 4.7",
- api: "anthropic-messages",
- baseUrl: "https://api.anthropic.com",
- provider: "anthropic",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- });
- }
-
- // Add missing Claude Sonnet 4.6
- if (!allModels.some(m => m.provider === "anthropic" && m.id === "claude-sonnet-4-6")) {
- allModels.push({
- id: "claude-sonnet-4-6",
- name: "Claude Sonnet 4.6",
- api: "anthropic-messages",
- baseUrl: "https://api.anthropic.com",
- provider: "anthropic",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- });
- }
-
- // Add missing Gemini 3.1 Flash Lite Preview until models.dev includes it.
- if (!allModels.some((m) => m.provider === "google" && m.id === "gemini-3.1-flash-lite-preview")) {
- allModels.push({
- id: "gemini-3.1-flash-lite-preview",
- name: "Gemini 3.1 Flash Lite Preview",
- api: "google-generative-ai",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- provider: "google",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- });
- }
-
- // Add missing gpt models
- if (!allModels.some(m => m.provider === "openai" && m.id === "gpt-5-chat-latest")) {
- allModels.push({
- id: "gpt-5-chat-latest",
- name: "GPT-5 Chat Latest",
- api: "openai-responses",
- baseUrl: "https://api.openai.com/v1",
- provider: "openai",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- });
- }
-
- if (!allModels.some(m => m.provider === "openai" && m.id === "gpt-5.1-codex")) {
- allModels.push({
- id: "gpt-5.1-codex",
- name: "GPT-5.1 Codex",
- api: "openai-responses",
- baseUrl: "https://api.openai.com/v1",
- provider: "openai",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 5,
- cacheRead: 0.125,
- cacheWrite: 1.25,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- });
- }
-
- if (!allModels.some(m => m.provider === "openai" && m.id === "gpt-5.1-codex-max")) {
- allModels.push({
- id: "gpt-5.1-codex-max",
- name: "GPT-5.1 Codex Max",
- api: "openai-responses",
- baseUrl: "https://api.openai.com/v1",
- provider: "openai",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- });
- }
-
- if (!allModels.some(m => m.provider === "openai" && m.id === "gpt-5.3-codex-spark")) {
- allModels.push({
- id: "gpt-5.3-codex-spark",
- name: "GPT-5.3 Codex Spark",
- api: "openai-responses",
- baseUrl: "https://api.openai.com/v1",
- provider: "openai",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- });
- }
-
- // Add missing GitHub Copilot GPT-5.3 models until models.dev includes them.
- const copilotBaseModel = allModels.find(
- (m) => m.provider === "github-copilot" && m.id === "gpt-5.2-codex",
- );
- if (copilotBaseModel) {
- if (!allModels.some((m) => m.provider === "github-copilot" && m.id === "gpt-5.3-codex")) {
- allModels.push({
- ...copilotBaseModel,
- id: "gpt-5.3-codex",
- name: "GPT-5.3 Codex",
- });
- }
- }
-
- if (!allModels.some((m) => m.provider === "openai" && m.id === "gpt-5.4")) {
- allModels.push({
- id: "gpt-5.4",
- name: "GPT-5.4",
- api: "openai-responses",
- baseUrl: "https://api.openai.com/v1",
- provider: "openai",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 15,
- cacheRead: 0.25,
- cacheWrite: 0,
- },
- contextWindow: 272000,
- maxTokens: 128000,
- });
- }
-
- const minimaxDirectSupportedIds = new Set(["MiniMax-M2.7", "MiniMax-M2.7-highspeed"]);
-
- for (const candidate of allModels) {
- if (
- (candidate.provider === "minimax" || candidate.provider === "minimax-cn") &&
- minimaxDirectSupportedIds.has(candidate.id)
- ) {
- candidate.contextWindow = 204800;
- candidate.maxTokens = 131072;
- }
- }
-
- for (let i = allModels.length - 1; i >= 0; i--) {
- const candidate = allModels[i];
- if (
- (candidate.provider === "minimax" || candidate.provider === "minimax-cn") &&
- !minimaxDirectSupportedIds.has(candidate.id)
- ) {
- allModels.splice(i, 1);
- }
- }
-
- // OpenAI Codex (ChatGPT OAuth) models
- // NOTE: These are not fetched from models.dev; we keep a small, explicit list to avoid aliases.
- // Context window is based on observed server limits (400s above ~272k), not marketing numbers.
- const CODEX_BASE_URL = "https://chatgpt.com/backend-api";
- const CODEX_CONTEXT = 272000;
- const CODEX_MAX_TOKENS = 128000;
- const codexModels: Model<"openai-codex-responses">[] = [
- {
- id: "gpt-5.1",
- name: "GPT-5.1",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: CODEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 },
- contextWindow: CODEX_CONTEXT,
- maxTokens: CODEX_MAX_TOKENS,
- },
- {
- id: "gpt-5.1-codex-max",
- name: "GPT-5.1 Codex Max",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: CODEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 },
- contextWindow: CODEX_CONTEXT,
- maxTokens: CODEX_MAX_TOKENS,
- },
- {
- id: "gpt-5.1-codex-mini",
- name: "GPT-5.1 Codex Mini",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: CODEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0.25, output: 2, cacheRead: 0.025, cacheWrite: 0 },
- contextWindow: CODEX_CONTEXT,
- maxTokens: CODEX_MAX_TOKENS,
- },
- {
- id: "gpt-5.2",
- name: "GPT-5.2",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: CODEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },
- contextWindow: CODEX_CONTEXT,
- maxTokens: CODEX_MAX_TOKENS,
- },
- {
- id: "gpt-5.2-codex",
- name: "GPT-5.2 Codex",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: CODEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },
- contextWindow: CODEX_CONTEXT,
- maxTokens: CODEX_MAX_TOKENS,
- },
- {
- id: "gpt-5.3-codex",
- name: "GPT-5.3 Codex",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: CODEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },
- contextWindow: CODEX_CONTEXT,
- maxTokens: CODEX_MAX_TOKENS,
- },
- {
- id: "gpt-5.4",
- name: "GPT-5.4",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: CODEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 },
- contextWindow: CODEX_CONTEXT,
- maxTokens: CODEX_MAX_TOKENS,
- },
- {
- id: "gpt-5.4-mini",
- name: "GPT-5.4 Mini",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: CODEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 },
- contextWindow: CODEX_CONTEXT,
- maxTokens: CODEX_MAX_TOKENS,
- },
- {
- id: "gpt-5.3-codex-spark",
- name: "GPT-5.3 Codex Spark",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: CODEX_BASE_URL,
- reasoning: true,
- input: ["text"],
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
- contextWindow: 128000,
- maxTokens: CODEX_MAX_TOKENS,
- },
- ];
- allModels.push(...codexModels);
-
- // Add missing Grok models
- if (!allModels.some(m => m.provider === "xai" && m.id === "grok-code-fast-1")) {
- allModels.push({
- id: "grok-code-fast-1",
- name: "Grok Code Fast 1",
- api: "openai-completions",
- baseUrl: "https://api.x.ai/v1",
- provider: "xai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.2,
- output: 1.5,
- cacheRead: 0.02,
- cacheWrite: 0,
- },
- contextWindow: 32768,
- maxTokens: 8192,
- });
- }
-
- // Add "auto" alias for openrouter/auto
- if (!allModels.some(m => m.provider === "openrouter" && m.id === "auto")) {
- allModels.push({
- id: "auto",
- name: "Auto",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- // we dont know about the costs because OpenRouter auto routes to different models
- // and then charges you for the underlying used model
- input:0,
- output:0,
- cacheRead:0,
- cacheWrite:0,
- },
- contextWindow: 2000000,
- maxTokens: 30000,
- });
- }
-
- // Google Cloud Code Assist models (Gemini CLI)
- // Uses production endpoint, standard Gemini models only
- const CLOUD_CODE_ASSIST_ENDPOINT = "https://cloudcode-pa.googleapis.com";
- const cloudCodeAssistModels: Model<"google-gemini-cli">[] = [
- {
- id: "gemini-2.5-pro",
- name: "Gemini 2.5 Pro (Cloud Code Assist)",
- api: "google-gemini-cli",
- provider: "google-gemini-cli",
- baseUrl: CLOUD_CODE_ASSIST_ENDPOINT,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65535,
- },
- {
- id: "gemini-2.5-flash",
- name: "Gemini 2.5 Flash (Cloud Code Assist)",
- api: "google-gemini-cli",
- provider: "google-gemini-cli",
- baseUrl: CLOUD_CODE_ASSIST_ENDPOINT,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65535,
- },
- {
- id: "gemini-2.0-flash",
- name: "Gemini 2.0 Flash (Cloud Code Assist)",
- api: "google-gemini-cli",
- provider: "google-gemini-cli",
- baseUrl: CLOUD_CODE_ASSIST_ENDPOINT,
- reasoning: false,
- input: ["text", "image"],
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 8192,
- },
- {
- id: "gemini-3-pro-preview",
- name: "Gemini 3 Pro Preview (Cloud Code Assist)",
- api: "google-gemini-cli",
- provider: "google-gemini-cli",
- baseUrl: CLOUD_CODE_ASSIST_ENDPOINT,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65535,
- },
- {
- id: "gemini-3-flash-preview",
- name: "Gemini 3 Flash Preview (Cloud Code Assist)",
- api: "google-gemini-cli",
- provider: "google-gemini-cli",
- baseUrl: CLOUD_CODE_ASSIST_ENDPOINT,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65535,
- },
- {
- id: "gemini-3.1-pro-preview",
- name: "Gemini 3.1 Pro Preview (Cloud Code Assist)",
- api: "google-gemini-cli",
- provider: "google-gemini-cli",
- baseUrl: CLOUD_CODE_ASSIST_ENDPOINT,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65535,
- },
- ];
- allModels.push(...cloudCodeAssistModels);
-
- // Antigravity models (Gemini 3, Claude, GPT-OSS via Google Cloud)
- // Uses sandbox endpoint and different OAuth credentials for access to additional models
- const ANTIGRAVITY_ENDPOINT = "https://daily-cloudcode-pa.sandbox.googleapis.com";
- const antigravityModels: Model<"google-gemini-cli">[] = [
- {
- id: "gemini-3.1-pro-high",
- name: "Gemini 3.1 Pro High (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: ANTIGRAVITY_ENDPOINT,
- reasoning: true,
- input: ["text", "image"],
- // the Model type doesn't seem to support having extended-context costs, so I'm just using the pricing for <200k input
- cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.375 },
- contextWindow: 1048576,
- maxTokens: 65535,
- },
- {
- id: "gemini-3.1-pro-low",
- name: "Gemini 3.1 Pro Low (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: ANTIGRAVITY_ENDPOINT,
- reasoning: true,
- input: ["text", "image"],
- // the Model type doesn't seem to support having extended-context costs, so I'm just using the pricing for <200k input
- cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.375 },
- contextWindow: 1048576,
- maxTokens: 65535,
- },
- {
- id: "gemini-3-flash",
- name: "Gemini 3 Flash (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: ANTIGRAVITY_ENDPOINT,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0.5, output: 3, cacheRead: 0.5, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65535,
- },
- {
- id: "claude-sonnet-4-5",
- name: "Claude Sonnet 4.5 (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: ANTIGRAVITY_ENDPOINT,
- reasoning: false,
- input: ["text", "image"],
- cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
- contextWindow: 200000,
- maxTokens: 64000,
- },
- {
- id: "claude-sonnet-4-5-thinking",
- name: "Claude Sonnet 4.5 Thinking (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: ANTIGRAVITY_ENDPOINT,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
- contextWindow: 200000,
- maxTokens: 64000,
- },
- {
- id: "claude-opus-4-5-thinking",
- name: "Claude Opus 4.5 Thinking (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: ANTIGRAVITY_ENDPOINT,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
- contextWindow: 200000,
- maxTokens: 64000,
- },
- {
- id: "claude-opus-4-6-thinking",
- name: "Claude Opus 4.6 Thinking (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: ANTIGRAVITY_ENDPOINT,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
- contextWindow: 200000,
- maxTokens: 128000,
- },
- {
- id: "claude-sonnet-4-6",
- name: "Claude Sonnet 4.6 (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: ANTIGRAVITY_ENDPOINT,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
- contextWindow: 200000,
- maxTokens: 64000,
- },
- {
- id: "gpt-oss-120b-medium",
- name: "GPT-OSS 120B Medium (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: ANTIGRAVITY_ENDPOINT,
- reasoning: false,
- input: ["text"],
- cost: { input: 0.09, output: 0.36, cacheRead: 0, cacheWrite: 0 },
- contextWindow: 131072,
- maxTokens: 32768,
- },
- ];
- allModels.push(...antigravityModels);
-
- const VERTEX_BASE_URL = "https://{location}-aiplatform.googleapis.com";
- const vertexModels: Model<"google-vertex">[] = [
- {
- id: "gemini-3-pro-preview",
- name: "Gemini 3 Pro Preview (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0 },
- contextWindow: 1000000,
- maxTokens: 64000,
- },
- {
- id: "gemini-3.1-pro-preview",
- name: "Gemini 3.1 Pro Preview (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65536,
- },
- {
- id: "gemini-3.1-pro-preview-customtools",
- name: "Gemini 3.1 Pro Preview Custom Tools (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65536,
- },
- {
- id: "gemini-3-flash-preview",
- name: "Gemini 3 Flash Preview (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0.5, output: 3, cacheRead: 0.05, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65536,
- },
- {
- id: "gemini-2.0-flash",
- name: "Gemini 2.0 Flash (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: false,
- input: ["text", "image"],
- cost: { input: 0.15, output: 0.6, cacheRead: 0.0375, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 8192,
- },
- {
- id: "gemini-2.0-flash-lite",
- name: "Gemini 2.0 Flash Lite (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0.075, output: 0.3, cacheRead: 0.01875, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65536,
- },
- {
- id: "gemini-2.5-pro",
- name: "Gemini 2.5 Pro (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65536,
- },
- {
- id: "gemini-2.5-flash",
- name: "Gemini 2.5 Flash (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65536,
- },
- {
- id: "gemini-2.5-flash-lite-preview-09-2025",
- name: "Gemini 2.5 Flash Lite Preview 09-25 (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0.1, output: 0.4, cacheRead: 0.01, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65536,
- },
- {
- id: "gemini-2.5-flash-lite",
- name: "Gemini 2.5 Flash Lite (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: true,
- input: ["text", "image"],
- cost: { input: 0.1, output: 0.4, cacheRead: 0.01, cacheWrite: 0 },
- contextWindow: 1048576,
- maxTokens: 65536,
- },
- {
- id: "gemini-1.5-pro",
- name: "Gemini 1.5 Pro (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: false,
- input: ["text", "image"],
- cost: { input: 1.25, output: 5, cacheRead: 0.3125, cacheWrite: 0 },
- contextWindow: 1000000,
- maxTokens: 8192,
- },
- {
- id: "gemini-1.5-flash",
- name: "Gemini 1.5 Flash (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: false,
- input: ["text", "image"],
- cost: { input: 0.075, output: 0.3, cacheRead: 0.01875, cacheWrite: 0 },
- contextWindow: 1000000,
- maxTokens: 8192,
- },
- {
- id: "gemini-1.5-flash-8b",
- name: "Gemini 1.5 Flash-8B (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: VERTEX_BASE_URL,
- reasoning: false,
- input: ["text", "image"],
- cost: { input: 0.0375, output: 0.15, cacheRead: 0.01, cacheWrite: 0 },
- contextWindow: 1000000,
- maxTokens: 8192,
- },
- ];
- allModels.push(...vertexModels);
-
- const azureOpenAiModels: Model[] = allModels
- .filter((model) => model.provider === "openai" && model.api === "openai-responses")
- .map((model) => ({
- ...model,
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- }));
- allModels.push(...azureOpenAiModels);
-
- // Group by provider and deduplicate by model ID
- const providers: Record>> = {};
- for (const model of allModels) {
- if (!providers[model.provider]) {
- providers[model.provider] = {};
- }
- // Use model ID as key to automatically deduplicate
- // Only add if not already present (models.dev takes priority over OpenRouter)
- if (!providers[model.provider][model.id]) {
- providers[model.provider][model.id] = model;
- }
- }
-
- // Generate TypeScript file
- let output = `// This file is auto-generated by scripts/generate-models.ts
-// Do not edit manually - run 'npm run generate-models' to update
-
-import type { Model } from "./types.js";
-
-export const MODELS = {
-`;
-
- // Generate provider sections (sorted for deterministic output)
- const sortedProviderIds = Object.keys(providers).sort();
- for (const providerId of sortedProviderIds) {
- const models = providers[providerId];
- output += `\t${JSON.stringify(providerId)}: {\n`;
-
- const sortedModelIds = Object.keys(models).sort();
- for (const modelId of sortedModelIds) {
- const model = models[modelId];
- output += `\t\t"${model.id}": {\n`;
- output += `\t\t\tid: "${model.id}",\n`;
- output += `\t\t\tname: "${model.name}",\n`;
- output += `\t\t\tapi: "${model.api}",\n`;
- output += `\t\t\tprovider: "${model.provider}",\n`;
- if (model.baseUrl !== undefined) {
- output += `\t\t\tbaseUrl: "${model.baseUrl}",\n`;
- }
- if (model.headers) {
- output += `\t\t\theaders: ${JSON.stringify(model.headers)},\n`;
- }
- if (model.compat) {
- output += ` compat: ${JSON.stringify(model.compat)},
-`;
- }
- output += `\t\t\treasoning: ${model.reasoning},\n`;
- output += `\t\t\tinput: [${model.input.map(i => `"${i}"`).join(", ")}],\n`;
- output += `\t\t\tcost: {\n`;
- output += `\t\t\t\tinput: ${model.cost.input},\n`;
- output += `\t\t\t\toutput: ${model.cost.output},\n`;
- output += `\t\t\t\tcacheRead: ${model.cost.cacheRead},\n`;
- output += `\t\t\t\tcacheWrite: ${model.cost.cacheWrite},\n`;
- output += `\t\t\t},\n`;
- output += `\t\t\tcontextWindow: ${model.contextWindow},\n`;
- output += `\t\t\tmaxTokens: ${model.maxTokens},\n`;
- output += `\t\t} satisfies Model<"${model.api}">,\n`;
- }
-
- output += `\t},\n`;
- }
-
- output += `} as const;
-`;
-
- // Write file
- writeFileSync(join(packageRoot, "src/models.generated.ts"), output);
- console.log("Generated src/models.generated.ts");
-
- // Print statistics
- const totalModels = allModels.length;
- const reasoningModels = allModels.filter(m => m.reasoning).length;
-
- console.log(`\nModel Statistics:`);
- console.log(` Total tool-capable models: ${totalModels}`);
- console.log(` Reasoning-capable models: ${reasoningModels}`);
-
- for (const [provider, models] of Object.entries(providers)) {
- console.log(` ${provider}: ${Object.keys(models).length} models`);
- }
-}
-
-// Run the generator
-generateModels().catch(console.error);
diff --git a/pi-mono-reference/packages/ai/scripts/generate-test-image.ts b/pi-mono-reference/packages/ai/scripts/generate-test-image.ts
deleted file mode 100644
index 29a473d4..00000000
--- a/pi-mono-reference/packages/ai/scripts/generate-test-image.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env tsx
-
-import { createCanvas } from "canvas";
-import { writeFileSync } from "fs";
-import { join, dirname } from "path";
-import { fileURLToPath } from "url";
-
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
-
-// Create a 200x200 canvas
-const canvas = createCanvas(200, 200);
-const ctx = canvas.getContext("2d");
-
-// Fill background with white
-ctx.fillStyle = "white";
-ctx.fillRect(0, 0, 200, 200);
-
-// Draw a red circle in the center
-ctx.fillStyle = "red";
-ctx.beginPath();
-ctx.arc(100, 100, 50, 0, Math.PI * 2);
-ctx.fill();
-
-// Save the image
-const buffer = canvas.toBuffer("image/png");
-const outputPath = join(__dirname, "..", "test", "data", "red-circle.png");
-
-// Ensure the directory exists
-import { mkdirSync } from "fs";
-mkdirSync(join(__dirname, "..", "test", "data"), { recursive: true });
-
-writeFileSync(outputPath, buffer);
-console.log(`Generated test image at: ${outputPath}`);
\ No newline at end of file
diff --git a/pi-mono-reference/packages/ai/src/api-registry.ts b/pi-mono-reference/packages/ai/src/api-registry.ts
deleted file mode 100644
index ca0e0610..00000000
--- a/pi-mono-reference/packages/ai/src/api-registry.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-import type {
- Api,
- AssistantMessageEventStream,
- Context,
- Model,
- SimpleStreamOptions,
- StreamFunction,
- StreamOptions,
-} from "./types.js";
-
-export type ApiStreamFunction = (
- model: Model,
- context: Context,
- options?: StreamOptions,
-) => AssistantMessageEventStream;
-
-export type ApiStreamSimpleFunction = (
- model: Model,
- context: Context,
- options?: SimpleStreamOptions,
-) => AssistantMessageEventStream;
-
-export interface ApiProvider {
- api: TApi;
- stream: StreamFunction;
- streamSimple: StreamFunction;
-}
-
-interface ApiProviderInternal {
- api: Api;
- stream: ApiStreamFunction;
- streamSimple: ApiStreamSimpleFunction;
-}
-
-type RegisteredApiProvider = {
- provider: ApiProviderInternal;
- sourceId?: string;
-};
-
-const apiProviderRegistry = new Map();
-
-function wrapStream(
- api: TApi,
- stream: StreamFunction,
-): ApiStreamFunction {
- return (model, context, options) => {
- if (model.api !== api) {
- throw new Error(`Mismatched api: ${model.api} expected ${api}`);
- }
- return stream(model as Model, context, options as TOptions);
- };
-}
-
-function wrapStreamSimple(
- api: TApi,
- streamSimple: StreamFunction,
-): ApiStreamSimpleFunction {
- return (model, context, options) => {
- if (model.api !== api) {
- throw new Error(`Mismatched api: ${model.api} expected ${api}`);
- }
- return streamSimple(model as Model, context, options);
- };
-}
-
-export function registerApiProvider(
- provider: ApiProvider,
- sourceId?: string,
-): void {
- apiProviderRegistry.set(provider.api, {
- provider: {
- api: provider.api,
- stream: wrapStream(provider.api, provider.stream),
- streamSimple: wrapStreamSimple(provider.api, provider.streamSimple),
- },
- sourceId,
- });
-}
-
-export function getApiProvider(api: Api): ApiProviderInternal | undefined {
- return apiProviderRegistry.get(api)?.provider;
-}
-
-export function getApiProviders(): ApiProviderInternal[] {
- return Array.from(apiProviderRegistry.values(), (entry) => entry.provider);
-}
-
-export function unregisterApiProviders(sourceId: string): void {
- for (const [api, entry] of apiProviderRegistry.entries()) {
- if (entry.sourceId === sourceId) {
- apiProviderRegistry.delete(api);
- }
- }
-}
-
-export function clearApiProviders(): void {
- apiProviderRegistry.clear();
-}
diff --git a/pi-mono-reference/packages/ai/src/bedrock-provider.ts b/pi-mono-reference/packages/ai/src/bedrock-provider.ts
deleted file mode 100644
index 07305418..00000000
--- a/pi-mono-reference/packages/ai/src/bedrock-provider.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { streamBedrock, streamSimpleBedrock } from "./providers/amazon-bedrock.js";
-
-export const bedrockProviderModule = {
- streamBedrock,
- streamSimpleBedrock,
-};
diff --git a/pi-mono-reference/packages/ai/src/cli.ts b/pi-mono-reference/packages/ai/src/cli.ts
deleted file mode 100644
index 12f3f204..00000000
--- a/pi-mono-reference/packages/ai/src/cli.ts
+++ /dev/null
@@ -1,133 +0,0 @@
-#!/usr/bin/env node
-
-import { createInterface } from "node:readline";
-import { existsSync, readFileSync, writeFileSync } from "fs";
-import { getOAuthProvider, getOAuthProviders } from "./utils/oauth/index.js";
-import type { OAuthCredentials, OAuthProviderId } from "./utils/oauth/types.js";
-
-const AUTH_FILE = "auth.json";
-const PROVIDERS = getOAuthProviders();
-
-function prompt(rl: ReturnType, question: string): Promise {
- return new Promise((resolve) => rl.question(question, resolve));
-}
-
-function loadAuth(): Record {
- if (!existsSync(AUTH_FILE)) return {};
- try {
- return JSON.parse(readFileSync(AUTH_FILE, "utf-8"));
- } catch {
- return {};
- }
-}
-
-function saveAuth(auth: Record): void {
- writeFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), "utf-8");
-}
-
-async function login(providerId: OAuthProviderId): Promise {
- const provider = getOAuthProvider(providerId);
- if (!provider) {
- console.error(`Unknown provider: ${providerId}`);
- process.exit(1);
- }
-
- const rl = createInterface({ input: process.stdin, output: process.stdout });
- const promptFn = (msg: string) => prompt(rl, `${msg} `);
-
- try {
- const credentials = await provider.login({
- onAuth: (info) => {
- console.log(`\nOpen this URL in your browser:\n${info.url}`);
- if (info.instructions) console.log(info.instructions);
- console.log();
- },
- onPrompt: async (p) => {
- return await promptFn(`${p.message}${p.placeholder ? ` (${p.placeholder})` : ""}:`);
- },
- onProgress: (msg) => console.log(msg),
- });
-
- const auth = loadAuth();
- auth[providerId] = { type: "oauth", ...credentials };
- saveAuth(auth);
-
- console.log(`\nCredentials saved to ${AUTH_FILE}`);
- } finally {
- rl.close();
- }
-}
-
-async function main(): Promise {
- const args = process.argv.slice(2);
- const command = args[0];
-
- if (!command || command === "help" || command === "--help" || command === "-h") {
- const providerList = PROVIDERS.map((p) => ` ${p.id.padEnd(20)} ${p.name}`).join("\n");
- console.log(`Usage: npx @mariozechner/pi-ai [provider]
-
-Commands:
- login [provider] Login to an OAuth provider
- list List available providers
-
-Providers:
-${providerList}
-
-Examples:
- npx @mariozechner/pi-ai login # interactive provider selection
- npx @mariozechner/pi-ai login anthropic # login to specific provider
- npx @mariozechner/pi-ai list # list providers
-`);
- return;
- }
-
- if (command === "list") {
- console.log("Available OAuth providers:\n");
- for (const p of PROVIDERS) {
- console.log(` ${p.id.padEnd(20)} ${p.name}`);
- }
- return;
- }
-
- if (command === "login") {
- let provider = args[1] as OAuthProviderId | undefined;
-
- if (!provider) {
- const rl = createInterface({ input: process.stdin, output: process.stdout });
- console.log("Select a provider:\n");
- for (let i = 0; i < PROVIDERS.length; i++) {
- console.log(` ${i + 1}. ${PROVIDERS[i].name}`);
- }
- console.log();
-
- const choice = await prompt(rl, `Enter number (1-${PROVIDERS.length}): `);
- rl.close();
-
- const index = parseInt(choice, 10) - 1;
- if (index < 0 || index >= PROVIDERS.length) {
- console.error("Invalid selection");
- process.exit(1);
- }
- provider = PROVIDERS[index].id;
- }
-
- if (!PROVIDERS.some((p) => p.id === provider)) {
- console.error(`Unknown provider: ${provider}`);
- console.error(`Use 'npx @mariozechner/pi-ai list' to see available providers`);
- process.exit(1);
- }
-
- console.log(`Logging in to ${provider}...`);
- await login(provider);
- return;
- }
-
- console.error(`Unknown command: ${command}`);
- console.error(`Use 'npx @mariozechner/pi-ai --help' for usage`);
- process.exit(1);
-}
-
-main().catch((err) => {
- console.error("Error:", err.message);
- process.exit(1);
-});
diff --git a/pi-mono-reference/packages/ai/src/env-api-keys.ts b/pi-mono-reference/packages/ai/src/env-api-keys.ts
deleted file mode 100644
index 95e91417..00000000
--- a/pi-mono-reference/packages/ai/src/env-api-keys.ts
+++ /dev/null
@@ -1,133 +0,0 @@
-// NEVER convert to top-level imports - breaks browser/Vite builds (web-ui)
-let _existsSync: typeof import("node:fs").existsSync | null = null;
-let _homedir: typeof import("node:os").homedir | null = null;
-let _join: typeof import("node:path").join | null = null;
-
-type DynamicImport = (specifier: string) => Promise;
-
-const dynamicImport: DynamicImport = (specifier) => import(specifier);
-const NODE_FS_SPECIFIER = "node:" + "fs";
-const NODE_OS_SPECIFIER = "node:" + "os";
-const NODE_PATH_SPECIFIER = "node:" + "path";
-
-// Eagerly load in Node.js/Bun environment only
-if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
- dynamicImport(NODE_FS_SPECIFIER).then((m) => {
- _existsSync = (m as typeof import("node:fs")).existsSync;
- });
- dynamicImport(NODE_OS_SPECIFIER).then((m) => {
- _homedir = (m as typeof import("node:os")).homedir;
- });
- dynamicImport(NODE_PATH_SPECIFIER).then((m) => {
- _join = (m as typeof import("node:path")).join;
- });
-}
-
-import type { KnownProvider } from "./types.js";
-
-let cachedVertexAdcCredentialsExists: boolean | null = null;
-
-function hasVertexAdcCredentials(): boolean {
- if (cachedVertexAdcCredentialsExists === null) {
- // If node modules haven't loaded yet (async import race at startup),
- // return false WITHOUT caching so the next call retries once they're ready.
- // Only cache false permanently in a browser environment where fs is never available.
- if (!_existsSync || !_homedir || !_join) {
- const isNode = typeof process !== "undefined" && (process.versions?.node || process.versions?.bun);
- if (!isNode) {
- // Definitively in a browser — safe to cache false permanently
- cachedVertexAdcCredentialsExists = false;
- }
- return false;
- }
-
- // Check GOOGLE_APPLICATION_CREDENTIALS env var first (standard way)
- const gacPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;
- if (gacPath) {
- cachedVertexAdcCredentialsExists = _existsSync(gacPath);
- } else {
- // Fall back to default ADC path (lazy evaluation)
- cachedVertexAdcCredentialsExists = _existsSync(
- _join(_homedir(), ".config", "gcloud", "application_default_credentials.json"),
- );
- }
- }
- return cachedVertexAdcCredentialsExists;
-}
-
-/**
- * Get API key for provider from known environment variables, e.g. OPENAI_API_KEY.
- *
- * Will not return API keys for providers that require OAuth tokens.
- */
-export function getEnvApiKey(provider: KnownProvider): string | undefined;
-export function getEnvApiKey(provider: string): string | undefined;
-export function getEnvApiKey(provider: any): string | undefined {
- // Fall back to environment variables
- if (provider === "github-copilot") {
- return process.env.COPILOT_GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_TOKEN;
- }
-
- // ANTHROPIC_OAUTH_TOKEN takes precedence over ANTHROPIC_API_KEY
- if (provider === "anthropic") {
- return process.env.ANTHROPIC_OAUTH_TOKEN || process.env.ANTHROPIC_API_KEY;
- }
-
- // Vertex AI supports either an explicit API key or Application Default Credentials
- // Auth is configured via `gcloud auth application-default login`
- if (provider === "google-vertex") {
- if (process.env.GOOGLE_CLOUD_API_KEY) {
- return process.env.GOOGLE_CLOUD_API_KEY;
- }
-
- const hasCredentials = hasVertexAdcCredentials();
- const hasProject = !!(process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT);
- const hasLocation = !!process.env.GOOGLE_CLOUD_LOCATION;
-
- if (hasCredentials && hasProject && hasLocation) {
- return "";
- }
- }
-
- if (provider === "amazon-bedrock") {
- // Amazon Bedrock supports multiple credential sources:
- // 1. AWS_PROFILE - named profile from ~/.aws/credentials
- // 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - standard IAM keys
- // 3. AWS_BEARER_TOKEN_BEDROCK - Bedrock API keys (bearer token)
- // 4. AWS_CONTAINER_CREDENTIALS_RELATIVE_URI - ECS task roles
- // 5. AWS_CONTAINER_CREDENTIALS_FULL_URI - ECS task roles (full URI)
- // 6. AWS_WEB_IDENTITY_TOKEN_FILE - IRSA (IAM Roles for Service Accounts)
- if (
- process.env.AWS_PROFILE ||
- (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||
- process.env.AWS_BEARER_TOKEN_BEDROCK ||
- process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ||
- process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI ||
- process.env.AWS_WEB_IDENTITY_TOKEN_FILE
- ) {
- return "";
- }
- }
-
- const envMap: Record = {
- openai: "OPENAI_API_KEY",
- "azure-openai-responses": "AZURE_OPENAI_API_KEY",
- google: "GEMINI_API_KEY",
- groq: "GROQ_API_KEY",
- cerebras: "CEREBRAS_API_KEY",
- xai: "XAI_API_KEY",
- openrouter: "OPENROUTER_API_KEY",
- "vercel-ai-gateway": "AI_GATEWAY_API_KEY",
- zai: "ZAI_API_KEY",
- mistral: "MISTRAL_API_KEY",
- minimax: "MINIMAX_API_KEY",
- "minimax-cn": "MINIMAX_CN_API_KEY",
- huggingface: "HF_TOKEN",
- opencode: "OPENCODE_API_KEY",
- "opencode-go": "OPENCODE_API_KEY",
- "kimi-coding": "KIMI_API_KEY",
- };
-
- const envVar = envMap[provider];
- return envVar ? process.env[envVar] : undefined;
-}
diff --git a/pi-mono-reference/packages/ai/src/index.ts b/pi-mono-reference/packages/ai/src/index.ts
deleted file mode 100644
index 1c885a85..00000000
--- a/pi-mono-reference/packages/ai/src/index.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-export type { Static, TSchema } from "@sinclair/typebox";
-export { Type } from "@sinclair/typebox";
-
-export * from "./api-registry.js";
-export * from "./env-api-keys.js";
-export * from "./models.js";
-export type { BedrockOptions } from "./providers/amazon-bedrock.js";
-export type { AnthropicOptions } from "./providers/anthropic.js";
-export type { AzureOpenAIResponsesOptions } from "./providers/azure-openai-responses.js";
-export * from "./providers/faux.js";
-export type { GoogleOptions } from "./providers/google.js";
-export type { GoogleGeminiCliOptions, GoogleThinkingLevel } from "./providers/google-gemini-cli.js";
-export type { GoogleVertexOptions } from "./providers/google-vertex.js";
-export type { MistralOptions } from "./providers/mistral.js";
-export type { OpenAICodexResponsesOptions } from "./providers/openai-codex-responses.js";
-export type { OpenAICompletionsOptions } from "./providers/openai-completions.js";
-export type { OpenAIResponsesOptions } from "./providers/openai-responses.js";
-export * from "./providers/register-builtins.js";
-export * from "./stream.js";
-export * from "./types.js";
-export * from "./utils/event-stream.js";
-export * from "./utils/json-parse.js";
-export type {
- OAuthAuthInfo,
- OAuthCredentials,
- OAuthLoginCallbacks,
- OAuthPrompt,
- OAuthProvider,
- OAuthProviderId,
- OAuthProviderInfo,
- OAuthProviderInterface,
-} from "./utils/oauth/types.js";
-export * from "./utils/overflow.js";
-export * from "./utils/typebox-helpers.js";
-export * from "./utils/validation.js";
diff --git a/pi-mono-reference/packages/ai/src/models.generated.ts b/pi-mono-reference/packages/ai/src/models.generated.ts
deleted file mode 100644
index 1104fa13..00000000
--- a/pi-mono-reference/packages/ai/src/models.generated.ts
+++ /dev/null
@@ -1,14431 +0,0 @@
-// This file is auto-generated by scripts/generate-models.ts
-// Do not edit manually - run 'npm run generate-models' to update
-
-import type { Model } from "./types.js";
-
-export const MODELS = {
- "amazon-bedrock": {
- "amazon.nova-2-lite-v1:0": {
- id: "amazon.nova-2-lite-v1:0",
- name: "Nova 2 Lite",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.33,
- output: 2.75,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "amazon.nova-lite-v1:0": {
- id: "amazon.nova-lite-v1:0",
- name: "Nova Lite",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.06,
- output: 0.24,
- cacheRead: 0.015,
- cacheWrite: 0,
- },
- contextWindow: 300000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "amazon.nova-micro-v1:0": {
- id: "amazon.nova-micro-v1:0",
- name: "Nova Micro",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.035,
- output: 0.14,
- cacheRead: 0.00875,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "amazon.nova-premier-v1:0": {
- id: "amazon.nova-premier-v1:0",
- name: "Nova Premier",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 12.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 16384,
- } satisfies Model<"bedrock-converse-stream">,
- "amazon.nova-pro-v1:0": {
- id: "amazon.nova-pro-v1:0",
- name: "Nova Pro",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.8,
- output: 3.2,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 300000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-3-5-haiku-20241022-v1:0": {
- id: "anthropic.claude-3-5-haiku-20241022-v1:0",
- name: "Claude Haiku 3.5",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.8,
- output: 4,
- cacheRead: 0.08,
- cacheWrite: 1,
- },
- contextWindow: 200000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-3-5-sonnet-20240620-v1:0": {
- id: "anthropic.claude-3-5-sonnet-20240620-v1:0",
- name: "Claude Sonnet 3.5",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-3-5-sonnet-20241022-v2:0": {
- id: "anthropic.claude-3-5-sonnet-20241022-v2:0",
- name: "Claude Sonnet 3.5 v2",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-3-7-sonnet-20250219-v1:0": {
- id: "anthropic.claude-3-7-sonnet-20250219-v1:0",
- name: "Claude Sonnet 3.7",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-3-haiku-20240307-v1:0": {
- id: "anthropic.claude-3-haiku-20240307-v1:0",
- name: "Claude Haiku 3",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 1.25,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-haiku-4-5-20251001-v1:0": {
- id: "anthropic.claude-haiku-4-5-20251001-v1:0",
- name: "Claude Haiku 4.5",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1,
- output: 5,
- cacheRead: 0.1,
- cacheWrite: 1.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-opus-4-1-20250805-v1:0": {
- id: "anthropic.claude-opus-4-1-20250805-v1:0",
- name: "Claude Opus 4.1",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-opus-4-20250514-v1:0": {
- id: "anthropic.claude-opus-4-20250514-v1:0",
- name: "Claude Opus 4",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-opus-4-5-20251101-v1:0": {
- id: "anthropic.claude-opus-4-5-20251101-v1:0",
- name: "Claude Opus 4.5",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-opus-4-6-v1": {
- id: "anthropic.claude-opus-4-6-v1",
- name: "Claude Opus 4.6",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-opus-4-7": {
- id: "anthropic.claude-opus-4-7",
- name: "Claude Opus 4.7",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-sonnet-4-20250514-v1:0": {
- id: "anthropic.claude-sonnet-4-20250514-v1:0",
- name: "Claude Sonnet 4",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-sonnet-4-5-20250929-v1:0": {
- id: "anthropic.claude-sonnet-4-5-20250929-v1:0",
- name: "Claude Sonnet 4.5",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "anthropic.claude-sonnet-4-6": {
- id: "anthropic.claude-sonnet-4-6",
- name: "Claude Sonnet 4.6",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "deepseek.r1-v1:0": {
- id: "deepseek.r1-v1:0",
- name: "DeepSeek-R1",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.35,
- output: 5.4,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 32768,
- } satisfies Model<"bedrock-converse-stream">,
- "deepseek.v3-v1:0": {
- id: "deepseek.v3-v1:0",
- name: "DeepSeek-V3.1",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.58,
- output: 1.68,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 81920,
- } satisfies Model<"bedrock-converse-stream">,
- "deepseek.v3.2": {
- id: "deepseek.v3.2",
- name: "DeepSeek-V3.2",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.62,
- output: 1.85,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 81920,
- } satisfies Model<"bedrock-converse-stream">,
- "eu.anthropic.claude-haiku-4-5-20251001-v1:0": {
- id: "eu.anthropic.claude-haiku-4-5-20251001-v1:0",
- name: "Claude Haiku 4.5 (EU)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1,
- output: 5,
- cacheRead: 0.1,
- cacheWrite: 1.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "eu.anthropic.claude-opus-4-5-20251101-v1:0": {
- id: "eu.anthropic.claude-opus-4-5-20251101-v1:0",
- name: "Claude Opus 4.5 (EU)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "eu.anthropic.claude-opus-4-6-v1": {
- id: "eu.anthropic.claude-opus-4-6-v1",
- name: "Claude Opus 4.6 (EU)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"bedrock-converse-stream">,
- "eu.anthropic.claude-opus-4-7": {
- id: "eu.anthropic.claude-opus-4-7",
- name: "Claude Opus 4.7 (EU)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"bedrock-converse-stream">,
- "eu.anthropic.claude-sonnet-4-20250514-v1:0": {
- id: "eu.anthropic.claude-sonnet-4-20250514-v1:0",
- name: "Claude Sonnet 4 (EU)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "eu.anthropic.claude-sonnet-4-5-20250929-v1:0": {
- id: "eu.anthropic.claude-sonnet-4-5-20250929-v1:0",
- name: "Claude Sonnet 4.5 (EU)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "eu.anthropic.claude-sonnet-4-6": {
- id: "eu.anthropic.claude-sonnet-4-6",
- name: "Claude Sonnet 4.6 (EU)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "global.anthropic.claude-haiku-4-5-20251001-v1:0": {
- id: "global.anthropic.claude-haiku-4-5-20251001-v1:0",
- name: "Claude Haiku 4.5 (Global)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1,
- output: 5,
- cacheRead: 0.1,
- cacheWrite: 1.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "global.anthropic.claude-opus-4-5-20251101-v1:0": {
- id: "global.anthropic.claude-opus-4-5-20251101-v1:0",
- name: "Claude Opus 4.5 (Global)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "global.anthropic.claude-opus-4-6-v1": {
- id: "global.anthropic.claude-opus-4-6-v1",
- name: "Claude Opus 4.6 (Global)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"bedrock-converse-stream">,
- "global.anthropic.claude-opus-4-7": {
- id: "global.anthropic.claude-opus-4-7",
- name: "Claude Opus 4.7 (Global)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"bedrock-converse-stream">,
- "global.anthropic.claude-sonnet-4-20250514-v1:0": {
- id: "global.anthropic.claude-sonnet-4-20250514-v1:0",
- name: "Claude Sonnet 4 (Global)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "global.anthropic.claude-sonnet-4-5-20250929-v1:0": {
- id: "global.anthropic.claude-sonnet-4-5-20250929-v1:0",
- name: "Claude Sonnet 4.5 (Global)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "global.anthropic.claude-sonnet-4-6": {
- id: "global.anthropic.claude-sonnet-4-6",
- name: "Claude Sonnet 4.6 (Global)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "google.gemma-3-27b-it": {
- id: "google.gemma-3-27b-it",
- name: "Google Gemma 3 27B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.12,
- output: 0.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 202752,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "google.gemma-3-4b-it": {
- id: "google.gemma-3-4b-it",
- name: "Gemma 3 4B IT",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.04,
- output: 0.08,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "meta.llama3-1-405b-instruct-v1:0": {
- id: "meta.llama3-1-405b-instruct-v1:0",
- name: "Llama 3.1 405B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2.4,
- output: 2.4,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "meta.llama3-1-70b-instruct-v1:0": {
- id: "meta.llama3-1-70b-instruct-v1:0",
- name: "Llama 3.1 70B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.72,
- output: 0.72,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "meta.llama3-1-8b-instruct-v1:0": {
- id: "meta.llama3-1-8b-instruct-v1:0",
- name: "Llama 3.1 8B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.22,
- output: 0.22,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "meta.llama3-2-11b-instruct-v1:0": {
- id: "meta.llama3-2-11b-instruct-v1:0",
- name: "Llama 3.2 11B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.16,
- output: 0.16,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "meta.llama3-2-1b-instruct-v1:0": {
- id: "meta.llama3-2-1b-instruct-v1:0",
- name: "Llama 3.2 1B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.1,
- output: 0.1,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "meta.llama3-2-3b-instruct-v1:0": {
- id: "meta.llama3-2-3b-instruct-v1:0",
- name: "Llama 3.2 3B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.15,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "meta.llama3-2-90b-instruct-v1:0": {
- id: "meta.llama3-2-90b-instruct-v1:0",
- name: "Llama 3.2 90B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.72,
- output: 0.72,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "meta.llama3-3-70b-instruct-v1:0": {
- id: "meta.llama3-3-70b-instruct-v1:0",
- name: "Llama 3.3 70B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.72,
- output: 0.72,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "meta.llama4-maverick-17b-instruct-v1:0": {
- id: "meta.llama4-maverick-17b-instruct-v1:0",
- name: "Llama 4 Maverick 17B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.24,
- output: 0.97,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 16384,
- } satisfies Model<"bedrock-converse-stream">,
- "meta.llama4-scout-17b-instruct-v1:0": {
- id: "meta.llama4-scout-17b-instruct-v1:0",
- name: "Llama 4 Scout 17B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.17,
- output: 0.66,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 3500000,
- maxTokens: 16384,
- } satisfies Model<"bedrock-converse-stream">,
- "minimax.minimax-m2": {
- id: "minimax.minimax-m2",
- name: "MiniMax M2",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 204608,
- maxTokens: 128000,
- } satisfies Model<"bedrock-converse-stream">,
- "minimax.minimax-m2.1": {
- id: "minimax.minimax-m2.1",
- name: "MiniMax M2.1",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"bedrock-converse-stream">,
- "minimax.minimax-m2.5": {
- id: "minimax.minimax-m2.5",
- name: "MiniMax M2.5",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 196608,
- maxTokens: 98304,
- } satisfies Model<"bedrock-converse-stream">,
- "mistral.devstral-2-123b": {
- id: "mistral.devstral-2-123b",
- name: "Devstral 2 123B",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.4,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "mistral.magistral-small-2509": {
- id: "mistral.magistral-small-2509",
- name: "Magistral Small 1.2",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 1.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 40000,
- } satisfies Model<"bedrock-converse-stream">,
- "mistral.ministral-3-14b-instruct": {
- id: "mistral.ministral-3-14b-instruct",
- name: "Ministral 14B 3.0",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.2,
- output: 0.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "mistral.ministral-3-3b-instruct": {
- id: "mistral.ministral-3-3b-instruct",
- name: "Ministral 3 3B",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.1,
- output: 0.1,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "mistral.ministral-3-8b-instruct": {
- id: "mistral.ministral-3-8b-instruct",
- name: "Ministral 3 8B",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.15,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "mistral.mistral-large-3-675b-instruct": {
- id: "mistral.mistral-large-3-675b-instruct",
- name: "Mistral Large 3",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 1.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "mistral.pixtral-large-2502-v1:0": {
- id: "mistral.pixtral-large-2502-v1:0",
- name: "Pixtral Large (25.02)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "mistral.voxtral-mini-3b-2507": {
- id: "mistral.voxtral-mini-3b-2507",
- name: "Voxtral Mini 3B 2507",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.04,
- output: 0.04,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "mistral.voxtral-small-24b-2507": {
- id: "mistral.voxtral-small-24b-2507",
- name: "Voxtral Small 24B 2507",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.35,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "moonshot.kimi-k2-thinking": {
- id: "moonshot.kimi-k2-thinking",
- name: "Kimi K2 Thinking",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 256000,
- } satisfies Model<"bedrock-converse-stream">,
- "moonshotai.kimi-k2.5": {
- id: "moonshotai.kimi-k2.5",
- name: "Kimi K2.5",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.6,
- output: 3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 256000,
- } satisfies Model<"bedrock-converse-stream">,
- "nvidia.nemotron-nano-12b-v2": {
- id: "nvidia.nemotron-nano-12b-v2",
- name: "NVIDIA Nemotron Nano 12B v2 VL BF16",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.2,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "nvidia.nemotron-nano-3-30b": {
- id: "nvidia.nemotron-nano-3-30b",
- name: "NVIDIA Nemotron Nano 3 30B",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.06,
- output: 0.24,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "nvidia.nemotron-nano-9b-v2": {
- id: "nvidia.nemotron-nano-9b-v2",
- name: "NVIDIA Nemotron Nano 9B v2",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.06,
- output: 0.23,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "nvidia.nemotron-super-3-120b": {
- id: "nvidia.nemotron-super-3-120b",
- name: "NVIDIA Nemotron 3 Super 120B A12B",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.65,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 131072,
- } satisfies Model<"bedrock-converse-stream">,
- "openai.gpt-oss-120b-1:0": {
- id: "openai.gpt-oss-120b-1:0",
- name: "gpt-oss-120b",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "openai.gpt-oss-20b-1:0": {
- id: "openai.gpt-oss-20b-1:0",
- name: "gpt-oss-20b",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.07,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "openai.gpt-oss-safeguard-120b": {
- id: "openai.gpt-oss-safeguard-120b",
- name: "GPT OSS Safeguard 120B",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "openai.gpt-oss-safeguard-20b": {
- id: "openai.gpt-oss-safeguard-20b",
- name: "GPT OSS Safeguard 20B",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.07,
- output: 0.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"bedrock-converse-stream">,
- "qwen.qwen3-235b-a22b-2507-v1:0": {
- id: "qwen.qwen3-235b-a22b-2507-v1:0",
- name: "Qwen3 235B A22B 2507",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.22,
- output: 0.88,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 131072,
- } satisfies Model<"bedrock-converse-stream">,
- "qwen.qwen3-32b-v1:0": {
- id: "qwen.qwen3-32b-v1:0",
- name: "Qwen3 32B (dense)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 16384,
- maxTokens: 16384,
- } satisfies Model<"bedrock-converse-stream">,
- "qwen.qwen3-coder-30b-a3b-v1:0": {
- id: "qwen.qwen3-coder-30b-a3b-v1:0",
- name: "Qwen3 Coder 30B A3B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 131072,
- } satisfies Model<"bedrock-converse-stream">,
- "qwen.qwen3-coder-480b-a35b-v1:0": {
- id: "qwen.qwen3-coder-480b-a35b-v1:0",
- name: "Qwen3 Coder 480B A35B Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.22,
- output: 1.8,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 65536,
- } satisfies Model<"bedrock-converse-stream">,
- "qwen.qwen3-coder-next": {
- id: "qwen.qwen3-coder-next",
- name: "Qwen3 Coder Next",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.22,
- output: 1.8,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 65536,
- } satisfies Model<"bedrock-converse-stream">,
- "qwen.qwen3-next-80b-a3b": {
- id: "qwen.qwen3-next-80b-a3b",
- name: "Qwen/Qwen3-Next-80B-A3B-Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.14,
- output: 1.4,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262000,
- maxTokens: 262000,
- } satisfies Model<"bedrock-converse-stream">,
- "qwen.qwen3-vl-235b-a22b": {
- id: "qwen.qwen3-vl-235b-a22b",
- name: "Qwen/Qwen3-VL-235B-A22B-Instruct",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.3,
- output: 1.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262000,
- maxTokens: 262000,
- } satisfies Model<"bedrock-converse-stream">,
- "us.anthropic.claude-haiku-4-5-20251001-v1:0": {
- id: "us.anthropic.claude-haiku-4-5-20251001-v1:0",
- name: "Claude Haiku 4.5 (US)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1,
- output: 5,
- cacheRead: 0.1,
- cacheWrite: 1.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "us.anthropic.claude-opus-4-1-20250805-v1:0": {
- id: "us.anthropic.claude-opus-4-1-20250805-v1:0",
- name: "Claude Opus 4.1 (US)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"bedrock-converse-stream">,
- "us.anthropic.claude-opus-4-20250514-v1:0": {
- id: "us.anthropic.claude-opus-4-20250514-v1:0",
- name: "Claude Opus 4 (US)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"bedrock-converse-stream">,
- "us.anthropic.claude-opus-4-5-20251101-v1:0": {
- id: "us.anthropic.claude-opus-4-5-20251101-v1:0",
- name: "Claude Opus 4.5 (US)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "us.anthropic.claude-opus-4-6-v1": {
- id: "us.anthropic.claude-opus-4-6-v1",
- name: "Claude Opus 4.6 (US)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"bedrock-converse-stream">,
- "us.anthropic.claude-opus-4-7": {
- id: "us.anthropic.claude-opus-4-7",
- name: "Claude Opus 4.7 (US)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"bedrock-converse-stream">,
- "us.anthropic.claude-sonnet-4-20250514-v1:0": {
- id: "us.anthropic.claude-sonnet-4-20250514-v1:0",
- name: "Claude Sonnet 4 (US)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "us.anthropic.claude-sonnet-4-5-20250929-v1:0": {
- id: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
- name: "Claude Sonnet 4.5 (US)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "us.anthropic.claude-sonnet-4-6": {
- id: "us.anthropic.claude-sonnet-4-6",
- name: "Claude Sonnet 4.6 (US)",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"bedrock-converse-stream">,
- "writer.palmyra-x4-v1:0": {
- id: "writer.palmyra-x4-v1:0",
- name: "Palmyra X4",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 122880,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "writer.palmyra-x5-v1:0": {
- id: "writer.palmyra-x5-v1:0",
- name: "Palmyra X5",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1040000,
- maxTokens: 8192,
- } satisfies Model<"bedrock-converse-stream">,
- "zai.glm-4.7": {
- id: "zai.glm-4.7",
- name: "GLM-4.7",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"bedrock-converse-stream">,
- "zai.glm-4.7-flash": {
- id: "zai.glm-4.7-flash",
- name: "GLM-4.7-Flash",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.07,
- output: 0.4,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 131072,
- } satisfies Model<"bedrock-converse-stream">,
- "zai.glm-5": {
- id: "zai.glm-5",
- name: "GLM-5",
- api: "bedrock-converse-stream",
- provider: "amazon-bedrock",
- baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1,
- output: 3.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 202752,
- maxTokens: 101376,
- } satisfies Model<"bedrock-converse-stream">,
- },
- "anthropic": {
- "claude-3-5-haiku-20241022": {
- id: "claude-3-5-haiku-20241022",
- name: "Claude Haiku 3.5",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.8,
- output: 4,
- cacheRead: 0.08,
- cacheWrite: 1,
- },
- contextWindow: 200000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "claude-3-5-haiku-latest": {
- id: "claude-3-5-haiku-latest",
- name: "Claude Haiku 3.5 (latest)",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.8,
- output: 4,
- cacheRead: 0.08,
- cacheWrite: 1,
- },
- contextWindow: 200000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "claude-3-5-sonnet-20240620": {
- id: "claude-3-5-sonnet-20240620",
- name: "Claude Sonnet 3.5",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "claude-3-5-sonnet-20241022": {
- id: "claude-3-5-sonnet-20241022",
- name: "Claude Sonnet 3.5 v2",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "claude-3-7-sonnet-20250219": {
- id: "claude-3-7-sonnet-20250219",
- name: "Claude Sonnet 3.7",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-3-haiku-20240307": {
- id: "claude-3-haiku-20240307",
- name: "Claude Haiku 3",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 1.25,
- cacheRead: 0.03,
- cacheWrite: 0.3,
- },
- contextWindow: 200000,
- maxTokens: 4096,
- } satisfies Model<"anthropic-messages">,
- "claude-3-opus-20240229": {
- id: "claude-3-opus-20240229",
- name: "Claude Opus 3",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 4096,
- } satisfies Model<"anthropic-messages">,
- "claude-3-sonnet-20240229": {
- id: "claude-3-sonnet-20240229",
- name: "Claude Sonnet 3",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 0.3,
- },
- contextWindow: 200000,
- maxTokens: 4096,
- } satisfies Model<"anthropic-messages">,
- "claude-haiku-4-5": {
- id: "claude-haiku-4-5",
- name: "Claude Haiku 4.5 (latest)",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1,
- output: 5,
- cacheRead: 0.1,
- cacheWrite: 1.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-haiku-4-5-20251001": {
- id: "claude-haiku-4-5-20251001",
- name: "Claude Haiku 4.5",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1,
- output: 5,
- cacheRead: 0.1,
- cacheWrite: 1.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4-0": {
- id: "claude-opus-4-0",
- name: "Claude Opus 4 (latest)",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4-1": {
- id: "claude-opus-4-1",
- name: "Claude Opus 4.1 (latest)",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4-1-20250805": {
- id: "claude-opus-4-1-20250805",
- name: "Claude Opus 4.1",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4-20250514": {
- id: "claude-opus-4-20250514",
- name: "Claude Opus 4",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4-5": {
- id: "claude-opus-4-5",
- name: "Claude Opus 4.5 (latest)",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4-5-20251101": {
- id: "claude-opus-4-5-20251101",
- name: "Claude Opus 4.5",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4-6": {
- id: "claude-opus-4-6",
- name: "Claude Opus 4.6",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4-7": {
- id: "claude-opus-4-7",
- name: "Claude Opus 4.7",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "claude-sonnet-4-0": {
- id: "claude-sonnet-4-0",
- name: "Claude Sonnet 4 (latest)",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-sonnet-4-20250514": {
- id: "claude-sonnet-4-20250514",
- name: "Claude Sonnet 4",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-sonnet-4-5": {
- id: "claude-sonnet-4-5",
- name: "Claude Sonnet 4.5 (latest)",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-sonnet-4-5-20250929": {
- id: "claude-sonnet-4-5-20250929",
- name: "Claude Sonnet 4.5",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-sonnet-4-6": {
- id: "claude-sonnet-4-6",
- name: "Claude Sonnet 4.6",
- api: "anthropic-messages",
- provider: "anthropic",
- baseUrl: "https://api.anthropic.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- },
- "azure-openai-responses": {
- "codex-mini-latest": {
- id: "codex-mini-latest",
- name: "Codex Mini",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.5,
- output: 6,
- cacheRead: 0.375,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-4": {
- id: "gpt-4",
- name: "GPT-4",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 30,
- output: 60,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 8192,
- maxTokens: 8192,
- } satisfies Model<"azure-openai-responses">,
- "gpt-4-turbo": {
- id: "gpt-4-turbo",
- name: "GPT-4 Turbo",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 10,
- output: 30,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"azure-openai-responses">,
- "gpt-4.1": {
- id: "gpt-4.1",
- name: "GPT-4.1",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 8,
- cacheRead: 0.5,
- cacheWrite: 0,
- },
- contextWindow: 1047576,
- maxTokens: 32768,
- } satisfies Model<"azure-openai-responses">,
- "gpt-4.1-mini": {
- id: "gpt-4.1-mini",
- name: "GPT-4.1 mini",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.4,
- output: 1.6,
- cacheRead: 0.1,
- cacheWrite: 0,
- },
- contextWindow: 1047576,
- maxTokens: 32768,
- } satisfies Model<"azure-openai-responses">,
- "gpt-4.1-nano": {
- id: "gpt-4.1-nano",
- name: "GPT-4.1 nano",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.1,
- output: 0.4,
- cacheRead: 0.03,
- cacheWrite: 0,
- },
- contextWindow: 1047576,
- maxTokens: 32768,
- } satisfies Model<"azure-openai-responses">,
- "gpt-4o": {
- id: "gpt-4o",
- name: "GPT-4o",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"azure-openai-responses">,
- "gpt-4o-2024-05-13": {
- id: "gpt-4o-2024-05-13",
- name: "GPT-4o (2024-05-13)",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 15,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"azure-openai-responses">,
- "gpt-4o-2024-08-06": {
- id: "gpt-4o-2024-08-06",
- name: "GPT-4o (2024-08-06)",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"azure-openai-responses">,
- "gpt-4o-2024-11-20": {
- id: "gpt-4o-2024-11-20",
- name: "GPT-4o (2024-11-20)",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"azure-openai-responses">,
- "gpt-4o-mini": {
- id: "gpt-4o-mini",
- name: "GPT-4o mini",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0.08,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5": {
- id: "gpt-5",
- name: "GPT-5",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5-chat-latest": {
- id: "gpt-5-chat-latest",
- name: "GPT-5 Chat Latest",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5-codex": {
- id: "gpt-5-codex",
- name: "GPT-5-Codex",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5-mini": {
- id: "gpt-5-mini",
- name: "GPT-5 Mini",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0.025,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5-nano": {
- id: "gpt-5-nano",
- name: "GPT-5 Nano",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.05,
- output: 0.4,
- cacheRead: 0.005,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5-pro": {
- id: "gpt-5-pro",
- name: "GPT-5 Pro",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 120,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 272000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.1": {
- id: "gpt-5.1",
- name: "GPT-5.1",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.13,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.1-chat-latest": {
- id: "gpt-5.1-chat-latest",
- name: "GPT-5.1 Chat",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.1-codex": {
- id: "gpt-5.1-codex",
- name: "GPT-5.1 Codex",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.1-codex-max": {
- id: "gpt-5.1-codex-max",
- name: "GPT-5.1 Codex Max",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.1-codex-mini": {
- id: "gpt-5.1-codex-mini",
- name: "GPT-5.1 Codex mini",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0.025,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.2": {
- id: "gpt-5.2",
- name: "GPT-5.2",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.2-chat-latest": {
- id: "gpt-5.2-chat-latest",
- name: "GPT-5.2 Chat",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.2-codex": {
- id: "gpt-5.2-codex",
- name: "GPT-5.2 Codex",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.2-pro": {
- id: "gpt-5.2-pro",
- name: "GPT-5.2 Pro",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 21,
- output: 168,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.3-chat-latest": {
- id: "gpt-5.3-chat-latest",
- name: "GPT-5.3 Chat (latest)",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.3-codex": {
- id: "gpt-5.3-codex",
- name: "GPT-5.3 Codex",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.3-codex-spark": {
- id: "gpt-5.3-codex-spark",
- name: "GPT-5.3 Codex Spark",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 32000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.4": {
- id: "gpt-5.4",
- name: "GPT-5.4",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 15,
- cacheRead: 0.25,
- cacheWrite: 0,
- },
- contextWindow: 272000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.4-mini": {
- id: "gpt-5.4-mini",
- name: "GPT-5.4 mini",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.75,
- output: 4.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.4-nano": {
- id: "gpt-5.4-nano",
- name: "GPT-5.4 nano",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.2,
- output: 1.25,
- cacheRead: 0.02,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "gpt-5.4-pro": {
- id: "gpt-5.4-pro",
- name: "GPT-5.4 Pro",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 30,
- output: 180,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1050000,
- maxTokens: 128000,
- } satisfies Model<"azure-openai-responses">,
- "o1": {
- id: "o1",
- name: "o1",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 60,
- cacheRead: 7.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"azure-openai-responses">,
- "o1-pro": {
- id: "o1-pro",
- name: "o1-pro",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 150,
- output: 600,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"azure-openai-responses">,
- "o3": {
- id: "o3",
- name: "o3",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 8,
- cacheRead: 0.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"azure-openai-responses">,
- "o3-deep-research": {
- id: "o3-deep-research",
- name: "o3-deep-research",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 10,
- output: 40,
- cacheRead: 2.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"azure-openai-responses">,
- "o3-mini": {
- id: "o3-mini",
- name: "o3-mini",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.1,
- output: 4.4,
- cacheRead: 0.55,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"azure-openai-responses">,
- "o3-pro": {
- id: "o3-pro",
- name: "o3-pro",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 20,
- output: 80,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"azure-openai-responses">,
- "o4-mini": {
- id: "o4-mini",
- name: "o4-mini",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.1,
- output: 4.4,
- cacheRead: 0.28,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"azure-openai-responses">,
- "o4-mini-deep-research": {
- id: "o4-mini-deep-research",
- name: "o4-mini-deep-research",
- api: "azure-openai-responses",
- provider: "azure-openai-responses",
- baseUrl: "",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 8,
- cacheRead: 0.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"azure-openai-responses">,
- },
- "cerebras": {
- "gpt-oss-120b": {
- id: "gpt-oss-120b",
- name: "GPT OSS 120B",
- api: "openai-completions",
- provider: "cerebras",
- baseUrl: "https://api.cerebras.ai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.25,
- output: 0.69,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "llama3.1-8b": {
- id: "llama3.1-8b",
- name: "Llama 3.1 8B",
- api: "openai-completions",
- provider: "cerebras",
- baseUrl: "https://api.cerebras.ai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.1,
- output: 0.1,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32000,
- maxTokens: 8000,
- } satisfies Model<"openai-completions">,
- "qwen-3-235b-a22b-instruct-2507": {
- id: "qwen-3-235b-a22b-instruct-2507",
- name: "Qwen 3 235B Instruct",
- api: "openai-completions",
- provider: "cerebras",
- baseUrl: "https://api.cerebras.ai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 1.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131000,
- maxTokens: 32000,
- } satisfies Model<"openai-completions">,
- "zai-glm-4.7": {
- id: "zai-glm-4.7",
- name: "Z.AI GLM-4.7",
- api: "openai-completions",
- provider: "cerebras",
- baseUrl: "https://api.cerebras.ai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2.25,
- output: 2.75,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 40000,
- } satisfies Model<"openai-completions">,
- },
- "github-copilot": {
- "claude-haiku-4.5": {
- id: "claude-haiku-4.5",
- name: "Claude Haiku 4.5",
- api: "anthropic-messages",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 144000,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4.5": {
- id: "claude-opus-4.5",
- name: "Claude Opus 4.5",
- api: "anthropic-messages",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 160000,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4.6": {
- id: "claude-opus-4.6",
- name: "Claude Opus 4.6",
- api: "anthropic-messages",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-sonnet-4": {
- id: "claude-sonnet-4",
- name: "Claude Sonnet 4",
- api: "anthropic-messages",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 216000,
- maxTokens: 16000,
- } satisfies Model<"anthropic-messages">,
- "claude-sonnet-4.5": {
- id: "claude-sonnet-4.5",
- name: "Claude Sonnet 4.5",
- api: "anthropic-messages",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 144000,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "claude-sonnet-4.6": {
- id: "claude-sonnet-4.6",
- name: "Claude Sonnet 4.6",
- api: "anthropic-messages",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "gemini-2.5-pro": {
- id: "gemini-2.5-pro",
- name: "Gemini 2.5 Pro",
- api: "openai-completions",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "gemini-3-flash-preview": {
- id: "gemini-3-flash-preview",
- name: "Gemini 3 Flash",
- api: "openai-completions",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "gemini-3-pro-preview": {
- id: "gemini-3-pro-preview",
- name: "Gemini 3 Pro Preview",
- api: "openai-completions",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "gemini-3.1-pro-preview": {
- id: "gemini-3.1-pro-preview",
- name: "Gemini 3.1 Pro Preview",
- api: "openai-completions",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "gpt-4.1": {
- id: "gpt-4.1",
- name: "GPT-4.1",
- api: "openai-completions",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "gpt-4o": {
- id: "gpt-4o",
- name: "GPT-4o",
- api: "openai-completions",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "gpt-5": {
- id: "gpt-5",
- name: "GPT-5",
- api: "openai-responses",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5-mini": {
- id: "gpt-5-mini",
- name: "GPT-5-mini",
- api: "openai-responses",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 264000,
- maxTokens: 64000,
- } satisfies Model<"openai-responses">,
- "gpt-5.1": {
- id: "gpt-5.1",
- name: "GPT-5.1",
- api: "openai-responses",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 264000,
- maxTokens: 64000,
- } satisfies Model<"openai-responses">,
- "gpt-5.1-codex": {
- id: "gpt-5.1-codex",
- name: "GPT-5.1-Codex",
- api: "openai-responses",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.1-codex-max": {
- id: "gpt-5.1-codex-max",
- name: "GPT-5.1-Codex-max",
- api: "openai-responses",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.1-codex-mini": {
- id: "gpt-5.1-codex-mini",
- name: "GPT-5.1-Codex-mini",
- api: "openai-responses",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.2": {
- id: "gpt-5.2",
- name: "GPT-5.2",
- api: "openai-responses",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 264000,
- maxTokens: 64000,
- } satisfies Model<"openai-responses">,
- "gpt-5.2-codex": {
- id: "gpt-5.2-codex",
- name: "GPT-5.2-Codex",
- api: "openai-responses",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.3-codex": {
- id: "gpt-5.3-codex",
- name: "GPT-5.3-Codex",
- api: "openai-responses",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.4": {
- id: "gpt-5.4",
- name: "GPT-5.4",
- api: "openai-responses",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.4-mini": {
- id: "gpt-5.4-mini",
- name: "GPT-5.4 Mini",
- api: "openai-responses",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "grok-code-fast-1": {
- id: "grok-code-fast-1",
- name: "Grok Code Fast 1",
- api: "openai-completions",
- provider: "github-copilot",
- baseUrl: "https://api.individual.githubcopilot.com",
- headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
- compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- },
- "google": {
- "gemini-1.5-flash": {
- id: "gemini-1.5-flash",
- name: "Gemini 1.5 Flash",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.075,
- output: 0.3,
- cacheRead: 0.01875,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 8192,
- } satisfies Model<"google-generative-ai">,
- "gemini-1.5-flash-8b": {
- id: "gemini-1.5-flash-8b",
- name: "Gemini 1.5 Flash-8B",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.0375,
- output: 0.15,
- cacheRead: 0.01,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 8192,
- } satisfies Model<"google-generative-ai">,
- "gemini-1.5-pro": {
- id: "gemini-1.5-pro",
- name: "Gemini 1.5 Pro",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 5,
- cacheRead: 0.3125,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 8192,
- } satisfies Model<"google-generative-ai">,
- "gemini-2.0-flash": {
- id: "gemini-2.0-flash",
- name: "Gemini 2.0 Flash",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.1,
- output: 0.4,
- cacheRead: 0.025,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 8192,
- } satisfies Model<"google-generative-ai">,
- "gemini-2.0-flash-lite": {
- id: "gemini-2.0-flash-lite",
- name: "Gemini 2.0 Flash Lite",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.075,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 8192,
- } satisfies Model<"google-generative-ai">,
- "gemini-2.5-flash": {
- id: "gemini-2.5-flash",
- name: "Gemini 2.5 Flash",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.3,
- output: 2.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-2.5-flash-lite": {
- id: "gemini-2.5-flash-lite",
- name: "Gemini 2.5 Flash Lite",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.1,
- output: 0.4,
- cacheRead: 0.025,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-2.5-flash-lite-preview-06-17": {
- id: "gemini-2.5-flash-lite-preview-06-17",
- name: "Gemini 2.5 Flash Lite Preview 06-17",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.1,
- output: 0.4,
- cacheRead: 0.025,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-2.5-flash-lite-preview-09-2025": {
- id: "gemini-2.5-flash-lite-preview-09-2025",
- name: "Gemini 2.5 Flash Lite Preview 09-25",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.1,
- output: 0.4,
- cacheRead: 0.025,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-2.5-flash-preview-04-17": {
- id: "gemini-2.5-flash-preview-04-17",
- name: "Gemini 2.5 Flash Preview 04-17",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0.0375,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-2.5-flash-preview-05-20": {
- id: "gemini-2.5-flash-preview-05-20",
- name: "Gemini 2.5 Flash Preview 05-20",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0.0375,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-2.5-flash-preview-09-2025": {
- id: "gemini-2.5-flash-preview-09-2025",
- name: "Gemini 2.5 Flash Preview 09-25",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.3,
- output: 2.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-2.5-pro": {
- id: "gemini-2.5-pro",
- name: "Gemini 2.5 Pro",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.31,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-2.5-pro-preview-05-06": {
- id: "gemini-2.5-pro-preview-05-06",
- name: "Gemini 2.5 Pro Preview 05-06",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.31,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-2.5-pro-preview-06-05": {
- id: "gemini-2.5-pro-preview-06-05",
- name: "Gemini 2.5 Pro Preview 06-05",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.31,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-3-flash-preview": {
- id: "gemini-3-flash-preview",
- name: "Gemini 3 Flash Preview",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 3,
- cacheRead: 0.05,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-3-pro-preview": {
- id: "gemini-3-pro-preview",
- name: "Gemini 3 Pro Preview",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"google-generative-ai">,
- "gemini-3.1-flash-lite-preview": {
- id: "gemini-3.1-flash-lite-preview",
- name: "Gemini 3.1 Flash Lite Preview",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 1.5,
- cacheRead: 0.025,
- cacheWrite: 1,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-3.1-pro-preview": {
- id: "gemini-3.1-pro-preview",
- name: "Gemini 3.1 Pro Preview",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-3.1-pro-preview-customtools": {
- id: "gemini-3.1-pro-preview-customtools",
- name: "Gemini 3.1 Pro Preview Custom Tools",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-flash-latest": {
- id: "gemini-flash-latest",
- name: "Gemini Flash Latest",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.3,
- output: 2.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-flash-lite-latest": {
- id: "gemini-flash-lite-latest",
- name: "Gemini Flash-Lite Latest",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.1,
- output: 0.4,
- cacheRead: 0.025,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-live-2.5-flash": {
- id: "gemini-live-2.5-flash",
- name: "Gemini Live 2.5 Flash",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8000,
- } satisfies Model<"google-generative-ai">,
- "gemini-live-2.5-flash-preview-native-audio": {
- id: "gemini-live-2.5-flash-preview-native-audio",
- name: "Gemini Live 2.5 Flash Preview Native Audio",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.5,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemma-3-27b-it": {
- id: "gemma-3-27b-it",
- name: "Gemma 3 27B",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"google-generative-ai">,
- "gemma-4-26b-it": {
- id: "gemma-4-26b-it",
- name: "Gemma 4 26B",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 8192,
- } satisfies Model<"google-generative-ai">,
- "gemma-4-31b-it": {
- id: "gemma-4-31b-it",
- name: "Gemma 4 31B",
- api: "google-generative-ai",
- provider: "google",
- baseUrl: "https://generativelanguage.googleapis.com/v1beta",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 8192,
- } satisfies Model<"google-generative-ai">,
- },
- "google-antigravity": {
- "claude-opus-4-5-thinking": {
- id: "claude-opus-4-5-thinking",
- name: "Claude Opus 4.5 Thinking (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"google-gemini-cli">,
- "claude-opus-4-6-thinking": {
- id: "claude-opus-4-6-thinking",
- name: "Claude Opus 4.6 Thinking (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 200000,
- maxTokens: 128000,
- } satisfies Model<"google-gemini-cli">,
- "claude-sonnet-4-5": {
- id: "claude-sonnet-4-5",
- name: "Claude Sonnet 4.5 (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"google-gemini-cli">,
- "claude-sonnet-4-5-thinking": {
- id: "claude-sonnet-4-5-thinking",
- name: "Claude Sonnet 4.5 Thinking (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"google-gemini-cli">,
- "claude-sonnet-4-6": {
- id: "claude-sonnet-4-6",
- name: "Claude Sonnet 4.6 (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"google-gemini-cli">,
- "gemini-3-flash": {
- id: "gemini-3-flash",
- name: "Gemini 3 Flash (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 3,
- cacheRead: 0.5,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65535,
- } satisfies Model<"google-gemini-cli">,
- "gemini-3.1-pro-high": {
- id: "gemini-3.1-pro-high",
- name: "Gemini 3.1 Pro High (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.2,
- cacheWrite: 2.375,
- },
- contextWindow: 1048576,
- maxTokens: 65535,
- } satisfies Model<"google-gemini-cli">,
- "gemini-3.1-pro-low": {
- id: "gemini-3.1-pro-low",
- name: "Gemini 3.1 Pro Low (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.2,
- cacheWrite: 2.375,
- },
- contextWindow: 1048576,
- maxTokens: 65535,
- } satisfies Model<"google-gemini-cli">,
- "gpt-oss-120b-medium": {
- id: "gpt-oss-120b-medium",
- name: "GPT-OSS 120B Medium (Antigravity)",
- api: "google-gemini-cli",
- provider: "google-antigravity",
- baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.09,
- output: 0.36,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"google-gemini-cli">,
- },
- "google-gemini-cli": {
- "gemini-2.0-flash": {
- id: "gemini-2.0-flash",
- name: "Gemini 2.0 Flash (Cloud Code Assist)",
- api: "google-gemini-cli",
- provider: "google-gemini-cli",
- baseUrl: "https://cloudcode-pa.googleapis.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 8192,
- } satisfies Model<"google-gemini-cli">,
- "gemini-2.5-flash": {
- id: "gemini-2.5-flash",
- name: "Gemini 2.5 Flash (Cloud Code Assist)",
- api: "google-gemini-cli",
- provider: "google-gemini-cli",
- baseUrl: "https://cloudcode-pa.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65535,
- } satisfies Model<"google-gemini-cli">,
- "gemini-2.5-pro": {
- id: "gemini-2.5-pro",
- name: "Gemini 2.5 Pro (Cloud Code Assist)",
- api: "google-gemini-cli",
- provider: "google-gemini-cli",
- baseUrl: "https://cloudcode-pa.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65535,
- } satisfies Model<"google-gemini-cli">,
- "gemini-3-flash-preview": {
- id: "gemini-3-flash-preview",
- name: "Gemini 3 Flash Preview (Cloud Code Assist)",
- api: "google-gemini-cli",
- provider: "google-gemini-cli",
- baseUrl: "https://cloudcode-pa.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65535,
- } satisfies Model<"google-gemini-cli">,
- "gemini-3-pro-preview": {
- id: "gemini-3-pro-preview",
- name: "Gemini 3 Pro Preview (Cloud Code Assist)",
- api: "google-gemini-cli",
- provider: "google-gemini-cli",
- baseUrl: "https://cloudcode-pa.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65535,
- } satisfies Model<"google-gemini-cli">,
- "gemini-3.1-pro-preview": {
- id: "gemini-3.1-pro-preview",
- name: "Gemini 3.1 Pro Preview (Cloud Code Assist)",
- api: "google-gemini-cli",
- provider: "google-gemini-cli",
- baseUrl: "https://cloudcode-pa.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65535,
- } satisfies Model<"google-gemini-cli">,
- },
- "google-vertex": {
- "gemini-1.5-flash": {
- id: "gemini-1.5-flash",
- name: "Gemini 1.5 Flash (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.075,
- output: 0.3,
- cacheRead: 0.01875,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 8192,
- } satisfies Model<"google-vertex">,
- "gemini-1.5-flash-8b": {
- id: "gemini-1.5-flash-8b",
- name: "Gemini 1.5 Flash-8B (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.0375,
- output: 0.15,
- cacheRead: 0.01,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 8192,
- } satisfies Model<"google-vertex">,
- "gemini-1.5-pro": {
- id: "gemini-1.5-pro",
- name: "Gemini 1.5 Pro (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 5,
- cacheRead: 0.3125,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 8192,
- } satisfies Model<"google-vertex">,
- "gemini-2.0-flash": {
- id: "gemini-2.0-flash",
- name: "Gemini 2.0 Flash (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0.0375,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 8192,
- } satisfies Model<"google-vertex">,
- "gemini-2.0-flash-lite": {
- id: "gemini-2.0-flash-lite",
- name: "Gemini 2.0 Flash Lite (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.075,
- output: 0.3,
- cacheRead: 0.01875,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-vertex">,
- "gemini-2.5-flash": {
- id: "gemini-2.5-flash",
- name: "Gemini 2.5 Flash (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.3,
- output: 2.5,
- cacheRead: 0.03,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-vertex">,
- "gemini-2.5-flash-lite": {
- id: "gemini-2.5-flash-lite",
- name: "Gemini 2.5 Flash Lite (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.1,
- output: 0.4,
- cacheRead: 0.01,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-vertex">,
- "gemini-2.5-flash-lite-preview-09-2025": {
- id: "gemini-2.5-flash-lite-preview-09-2025",
- name: "Gemini 2.5 Flash Lite Preview 09-25 (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.1,
- output: 0.4,
- cacheRead: 0.01,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-vertex">,
- "gemini-2.5-pro": {
- id: "gemini-2.5-pro",
- name: "Gemini 2.5 Pro (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-vertex">,
- "gemini-3-flash-preview": {
- id: "gemini-3-flash-preview",
- name: "Gemini 3 Flash Preview (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 3,
- cacheRead: 0.05,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-vertex">,
- "gemini-3-pro-preview": {
- id: "gemini-3-pro-preview",
- name: "Gemini 3 Pro Preview (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"google-vertex">,
- "gemini-3.1-pro-preview": {
- id: "gemini-3.1-pro-preview",
- name: "Gemini 3.1 Pro Preview (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-vertex">,
- "gemini-3.1-pro-preview-customtools": {
- id: "gemini-3.1-pro-preview-customtools",
- name: "Gemini 3.1 Pro Preview Custom Tools (Vertex)",
- api: "google-vertex",
- provider: "google-vertex",
- baseUrl: "https://{location}-aiplatform.googleapis.com",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-vertex">,
- },
- "groq": {
- "deepseek-r1-distill-llama-70b": {
- id: "deepseek-r1-distill-llama-70b",
- name: "DeepSeek R1 Distill Llama 70B",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.75,
- output: 0.99,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "gemma2-9b-it": {
- id: "gemma2-9b-it",
- name: "Gemma 2 9B",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.2,
- output: 0.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 8192,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "groq/compound": {
- id: "groq/compound",
- name: "Compound",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "groq/compound-mini": {
- id: "groq/compound-mini",
- name: "Compound Mini",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "llama-3.1-8b-instant": {
- id: "llama-3.1-8b-instant",
- name: "Llama 3.1 8B Instant",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.05,
- output: 0.08,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "llama-3.3-70b-versatile": {
- id: "llama-3.3-70b-versatile",
- name: "Llama 3.3 70B Versatile",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.59,
- output: 0.79,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "llama3-70b-8192": {
- id: "llama3-70b-8192",
- name: "Llama 3 70B",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.59,
- output: 0.79,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 8192,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "llama3-8b-8192": {
- id: "llama3-8b-8192",
- name: "Llama 3 8B",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.05,
- output: 0.08,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 8192,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "meta-llama/llama-4-maverick-17b-128e-instruct": {
- id: "meta-llama/llama-4-maverick-17b-128e-instruct",
- name: "Llama 4 Maverick 17B",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.2,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "meta-llama/llama-4-scout-17b-16e-instruct": {
- id: "meta-llama/llama-4-scout-17b-16e-instruct",
- name: "Llama 4 Scout 17B",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.11,
- output: 0.34,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "mistral-saba-24b": {
- id: "mistral-saba-24b",
- name: "Mistral Saba 24B",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.79,
- output: 0.79,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32768,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "moonshotai/kimi-k2-instruct": {
- id: "moonshotai/kimi-k2-instruct",
- name: "Kimi K2 Instruct",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1,
- output: 3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "moonshotai/kimi-k2-instruct-0905": {
- id: "moonshotai/kimi-k2-instruct-0905",
- name: "Kimi K2 Instruct 0905",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1,
- output: 3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "openai/gpt-oss-120b": {
- id: "openai/gpt-oss-120b",
- name: "GPT OSS 120B",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "openai/gpt-oss-20b": {
- id: "openai/gpt-oss-20b",
- name: "GPT OSS 20B",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.075,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "openai/gpt-oss-safeguard-20b": {
- id: "openai/gpt-oss-safeguard-20b",
- name: "Safety GPT OSS 20B",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.075,
- output: 0.3,
- cacheRead: 0.037,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "qwen-qwq-32b": {
- id: "qwen-qwq-32b",
- name: "Qwen QwQ 32B",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.29,
- output: 0.39,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-32b": {
- id: "qwen/qwen3-32b",
- name: "Qwen3 32B",
- api: "openai-completions",
- provider: "groq",
- baseUrl: "https://api.groq.com/openai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.29,
- output: 0.59,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 40960,
- } satisfies Model<"openai-completions">,
- },
- "huggingface": {
- "MiniMaxAI/MiniMax-M2.1": {
- id: "MiniMaxAI/MiniMax-M2.1",
- name: "MiniMax-M2.1",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "MiniMaxAI/MiniMax-M2.5": {
- id: "MiniMaxAI/MiniMax-M2.5",
- name: "MiniMax-M2.5",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.03,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "MiniMaxAI/MiniMax-M2.7": {
- id: "MiniMaxAI/MiniMax-M2.7",
- name: "MiniMax-M2.7",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.06,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "Qwen/Qwen3-235B-A22B-Thinking-2507": {
- id: "Qwen/Qwen3-235B-A22B-Thinking-2507",
- name: "Qwen3-235B-A22B-Thinking-2507",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "Qwen/Qwen3-Coder-480B-A35B-Instruct": {
- id: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
- name: "Qwen3-Coder-480B-A35B-Instruct",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 66536,
- } satisfies Model<"openai-completions">,
- "Qwen/Qwen3-Coder-Next": {
- id: "Qwen/Qwen3-Coder-Next",
- name: "Qwen3-Coder-Next",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.2,
- output: 1.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "Qwen/Qwen3-Next-80B-A3B-Instruct": {
- id: "Qwen/Qwen3-Next-80B-A3B-Instruct",
- name: "Qwen3-Next-80B-A3B-Instruct",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.25,
- output: 1,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 66536,
- } satisfies Model<"openai-completions">,
- "Qwen/Qwen3-Next-80B-A3B-Thinking": {
- id: "Qwen/Qwen3-Next-80B-A3B-Thinking",
- name: "Qwen3-Next-80B-A3B-Thinking",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "Qwen/Qwen3.5-397B-A17B": {
- id: "Qwen/Qwen3.5-397B-A17B",
- name: "Qwen3.5-397B-A17B",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.6,
- output: 3.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "XiaomiMiMo/MiMo-V2-Flash": {
- id: "XiaomiMiMo/MiMo-V2-Flash",
- name: "MiMo-V2-Flash",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.1,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "deepseek-ai/DeepSeek-R1-0528": {
- id: "deepseek-ai/DeepSeek-R1-0528",
- name: "DeepSeek-R1-0528",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 3,
- output: 5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 163840,
- } satisfies Model<"openai-completions">,
- "deepseek-ai/DeepSeek-V3.2": {
- id: "deepseek-ai/DeepSeek-V3.2",
- name: "DeepSeek-V3.2",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.28,
- output: 0.4,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "moonshotai/Kimi-K2-Instruct": {
- id: "moonshotai/Kimi-K2-Instruct",
- name: "Kimi-K2-Instruct",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1,
- output: 3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "moonshotai/Kimi-K2-Instruct-0905": {
- id: "moonshotai/Kimi-K2-Instruct-0905",
- name: "Kimi-K2-Instruct-0905",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1,
- output: 3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "moonshotai/Kimi-K2-Thinking": {
- id: "moonshotai/Kimi-K2-Thinking",
- name: "Kimi-K2-Thinking",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.5,
- cacheRead: 0.15,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"openai-completions">,
- "moonshotai/Kimi-K2.5": {
- id: "moonshotai/Kimi-K2.5",
- name: "Kimi-K2.5",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.6,
- output: 3,
- cacheRead: 0.1,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"openai-completions">,
- "zai-org/GLM-4.7": {
- id: "zai-org/GLM-4.7",
- name: "GLM-4.7",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.2,
- cacheRead: 0.11,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "zai-org/GLM-4.7-Flash": {
- id: "zai-org/GLM-4.7-Flash",
- name: "GLM-4.7-Flash",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "zai-org/GLM-5": {
- id: "zai-org/GLM-5",
- name: "GLM-5",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1,
- output: 3.2,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 202752,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "zai-org/GLM-5.1": {
- id: "zai-org/GLM-5.1",
- name: "GLM-5.1",
- api: "openai-completions",
- provider: "huggingface",
- baseUrl: "https://router.huggingface.co/v1",
- compat: {"supportsDeveloperRole":false},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1,
- output: 3.2,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 202752,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- },
- "kimi-coding": {
- "kimi-for-coding": {
- id: "kimi-for-coding",
- name: "Kimi For Coding",
- api: "anthropic-messages",
- provider: "kimi-coding",
- baseUrl: "https://api.kimi.com/coding",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32768,
- } satisfies Model<"anthropic-messages">,
- "kimi-k2-thinking": {
- id: "kimi-k2-thinking",
- name: "Kimi K2 Thinking",
- api: "anthropic-messages",
- provider: "kimi-coding",
- baseUrl: "https://api.kimi.com/coding",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32768,
- } satisfies Model<"anthropic-messages">,
- },
- "minimax": {
- "MiniMax-M2.7": {
- id: "MiniMax-M2.7",
- name: "MiniMax-M2.7",
- api: "anthropic-messages",
- provider: "minimax",
- baseUrl: "https://api.minimax.io/anthropic",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.06,
- cacheWrite: 0.375,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "MiniMax-M2.7-highspeed": {
- id: "MiniMax-M2.7-highspeed",
- name: "MiniMax-M2.7-highspeed",
- api: "anthropic-messages",
- provider: "minimax",
- baseUrl: "https://api.minimax.io/anthropic",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.4,
- cacheRead: 0.06,
- cacheWrite: 0.375,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- },
- "minimax-cn": {
- "MiniMax-M2.7": {
- id: "MiniMax-M2.7",
- name: "MiniMax-M2.7",
- api: "anthropic-messages",
- provider: "minimax-cn",
- baseUrl: "https://api.minimaxi.com/anthropic",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.06,
- cacheWrite: 0.375,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "MiniMax-M2.7-highspeed": {
- id: "MiniMax-M2.7-highspeed",
- name: "MiniMax-M2.7-highspeed",
- api: "anthropic-messages",
- provider: "minimax-cn",
- baseUrl: "https://api.minimaxi.com/anthropic",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.4,
- cacheRead: 0.06,
- cacheWrite: 0.375,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- },
- "mistral": {
- "codestral-latest": {
- id: "codestral-latest",
- name: "Codestral (latest)",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 0.9,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 4096,
- } satisfies Model<"mistral-conversations">,
- "devstral-2512": {
- id: "devstral-2512",
- name: "Devstral 2",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.4,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"mistral-conversations">,
- "devstral-medium-2507": {
- id: "devstral-medium-2507",
- name: "Devstral Medium",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.4,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"mistral-conversations">,
- "devstral-medium-latest": {
- id: "devstral-medium-latest",
- name: "Devstral 2 (latest)",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.4,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"mistral-conversations">,
- "devstral-small-2505": {
- id: "devstral-small-2505",
- name: "Devstral Small 2505",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.1,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"mistral-conversations">,
- "devstral-small-2507": {
- id: "devstral-small-2507",
- name: "Devstral Small",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.1,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"mistral-conversations">,
- "labs-devstral-small-2512": {
- id: "labs-devstral-small-2512",
- name: "Devstral Small 2",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 256000,
- } satisfies Model<"mistral-conversations">,
- "magistral-medium-latest": {
- id: "magistral-medium-latest",
- name: "Magistral Medium (latest)",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 2,
- output: 5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"mistral-conversations">,
- "magistral-small": {
- id: "magistral-small",
- name: "Magistral Small",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.5,
- output: 1.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"mistral-conversations">,
- "ministral-3b-latest": {
- id: "ministral-3b-latest",
- name: "Ministral 3B (latest)",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.04,
- output: 0.04,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"mistral-conversations">,
- "ministral-8b-latest": {
- id: "ministral-8b-latest",
- name: "Ministral 8B (latest)",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.1,
- output: 0.1,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"mistral-conversations">,
- "mistral-large-2411": {
- id: "mistral-large-2411",
- name: "Mistral Large 2.1",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 16384,
- } satisfies Model<"mistral-conversations">,
- "mistral-large-2512": {
- id: "mistral-large-2512",
- name: "Mistral Large 3",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 1.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"mistral-conversations">,
- "mistral-large-latest": {
- id: "mistral-large-latest",
- name: "Mistral Large (latest)",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 1.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"mistral-conversations">,
- "mistral-medium-2505": {
- id: "mistral-medium-2505",
- name: "Mistral Medium 3",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.4,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"mistral-conversations">,
- "mistral-medium-2508": {
- id: "mistral-medium-2508",
- name: "Mistral Medium 3.1",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.4,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"mistral-conversations">,
- "mistral-medium-latest": {
- id: "mistral-medium-latest",
- name: "Mistral Medium (latest)",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.4,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"mistral-conversations">,
- "mistral-nemo": {
- id: "mistral-nemo",
- name: "Mistral Nemo",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.15,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"mistral-conversations">,
- "mistral-small-2506": {
- id: "mistral-small-2506",
- name: "Mistral Small 3.2",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.1,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"mistral-conversations">,
- "mistral-small-2603": {
- id: "mistral-small-2603",
- name: "Mistral Small 4",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 256000,
- } satisfies Model<"mistral-conversations">,
- "mistral-small-latest": {
- id: "mistral-small-latest",
- name: "Mistral Small (latest)",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 256000,
- } satisfies Model<"mistral-conversations">,
- "open-mistral-7b": {
- id: "open-mistral-7b",
- name: "Mistral 7B",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.25,
- output: 0.25,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 8000,
- maxTokens: 8000,
- } satisfies Model<"mistral-conversations">,
- "open-mixtral-8x22b": {
- id: "open-mixtral-8x22b",
- name: "Mixtral 8x22B",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 64000,
- maxTokens: 64000,
- } satisfies Model<"mistral-conversations">,
- "open-mixtral-8x7b": {
- id: "open-mixtral-8x7b",
- name: "Mixtral 8x7B",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.7,
- output: 0.7,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32000,
- maxTokens: 32000,
- } satisfies Model<"mistral-conversations">,
- "pixtral-12b": {
- id: "pixtral-12b",
- name: "Pixtral 12B",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.15,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"mistral-conversations">,
- "pixtral-large-latest": {
- id: "pixtral-large-latest",
- name: "Pixtral Large (latest)",
- api: "mistral-conversations",
- provider: "mistral",
- baseUrl: "https://api.mistral.ai",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"mistral-conversations">,
- },
- "openai": {
- "codex-mini-latest": {
- id: "codex-mini-latest",
- name: "Codex Mini",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.5,
- output: 6,
- cacheRead: 0.375,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-responses">,
- "gpt-4": {
- id: "gpt-4",
- name: "GPT-4",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 30,
- output: 60,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 8192,
- maxTokens: 8192,
- } satisfies Model<"openai-responses">,
- "gpt-4-turbo": {
- id: "gpt-4-turbo",
- name: "GPT-4 Turbo",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 10,
- output: 30,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"openai-responses">,
- "gpt-4.1": {
- id: "gpt-4.1",
- name: "GPT-4.1",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 8,
- cacheRead: 0.5,
- cacheWrite: 0,
- },
- contextWindow: 1047576,
- maxTokens: 32768,
- } satisfies Model<"openai-responses">,
- "gpt-4.1-mini": {
- id: "gpt-4.1-mini",
- name: "GPT-4.1 mini",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.4,
- output: 1.6,
- cacheRead: 0.1,
- cacheWrite: 0,
- },
- contextWindow: 1047576,
- maxTokens: 32768,
- } satisfies Model<"openai-responses">,
- "gpt-4.1-nano": {
- id: "gpt-4.1-nano",
- name: "GPT-4.1 nano",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.1,
- output: 0.4,
- cacheRead: 0.03,
- cacheWrite: 0,
- },
- contextWindow: 1047576,
- maxTokens: 32768,
- } satisfies Model<"openai-responses">,
- "gpt-4o": {
- id: "gpt-4o",
- name: "GPT-4o",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-responses">,
- "gpt-4o-2024-05-13": {
- id: "gpt-4o-2024-05-13",
- name: "GPT-4o (2024-05-13)",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 15,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"openai-responses">,
- "gpt-4o-2024-08-06": {
- id: "gpt-4o-2024-08-06",
- name: "GPT-4o (2024-08-06)",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-responses">,
- "gpt-4o-2024-11-20": {
- id: "gpt-4o-2024-11-20",
- name: "GPT-4o (2024-11-20)",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-responses">,
- "gpt-4o-mini": {
- id: "gpt-4o-mini",
- name: "GPT-4o mini",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0.08,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-responses">,
- "gpt-5": {
- id: "gpt-5",
- name: "GPT-5",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5-chat-latest": {
- id: "gpt-5-chat-latest",
- name: "GPT-5 Chat Latest",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-responses">,
- "gpt-5-codex": {
- id: "gpt-5-codex",
- name: "GPT-5-Codex",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5-mini": {
- id: "gpt-5-mini",
- name: "GPT-5 Mini",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0.025,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5-nano": {
- id: "gpt-5-nano",
- name: "GPT-5 Nano",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.05,
- output: 0.4,
- cacheRead: 0.005,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5-pro": {
- id: "gpt-5-pro",
- name: "GPT-5 Pro",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 120,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 272000,
- } satisfies Model<"openai-responses">,
- "gpt-5.1": {
- id: "gpt-5.1",
- name: "GPT-5.1",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.13,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.1-chat-latest": {
- id: "gpt-5.1-chat-latest",
- name: "GPT-5.1 Chat",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-responses">,
- "gpt-5.1-codex": {
- id: "gpt-5.1-codex",
- name: "GPT-5.1 Codex",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.1-codex-max": {
- id: "gpt-5.1-codex-max",
- name: "GPT-5.1 Codex Max",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.1-codex-mini": {
- id: "gpt-5.1-codex-mini",
- name: "GPT-5.1 Codex mini",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0.025,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.2": {
- id: "gpt-5.2",
- name: "GPT-5.2",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.2-chat-latest": {
- id: "gpt-5.2-chat-latest",
- name: "GPT-5.2 Chat",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-responses">,
- "gpt-5.2-codex": {
- id: "gpt-5.2-codex",
- name: "GPT-5.2 Codex",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.2-pro": {
- id: "gpt-5.2-pro",
- name: "GPT-5.2 Pro",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 21,
- output: 168,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.3-chat-latest": {
- id: "gpt-5.3-chat-latest",
- name: "GPT-5.3 Chat (latest)",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-responses">,
- "gpt-5.3-codex": {
- id: "gpt-5.3-codex",
- name: "GPT-5.3 Codex",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.3-codex-spark": {
- id: "gpt-5.3-codex-spark",
- name: "GPT-5.3 Codex Spark",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 32000,
- } satisfies Model<"openai-responses">,
- "gpt-5.4": {
- id: "gpt-5.4",
- name: "GPT-5.4",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 15,
- cacheRead: 0.25,
- cacheWrite: 0,
- },
- contextWindow: 272000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.4-mini": {
- id: "gpt-5.4-mini",
- name: "GPT-5.4 mini",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.75,
- output: 4.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.4-nano": {
- id: "gpt-5.4-nano",
- name: "GPT-5.4 nano",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.2,
- output: 1.25,
- cacheRead: 0.02,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.4-pro": {
- id: "gpt-5.4-pro",
- name: "GPT-5.4 Pro",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 30,
- output: 180,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1050000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "o1": {
- id: "o1",
- name: "o1",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 60,
- cacheRead: 7.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-responses">,
- "o1-pro": {
- id: "o1-pro",
- name: "o1-pro",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 150,
- output: 600,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-responses">,
- "o3": {
- id: "o3",
- name: "o3",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 8,
- cacheRead: 0.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-responses">,
- "o3-deep-research": {
- id: "o3-deep-research",
- name: "o3-deep-research",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 10,
- output: 40,
- cacheRead: 2.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-responses">,
- "o3-mini": {
- id: "o3-mini",
- name: "o3-mini",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.1,
- output: 4.4,
- cacheRead: 0.55,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-responses">,
- "o3-pro": {
- id: "o3-pro",
- name: "o3-pro",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 20,
- output: 80,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-responses">,
- "o4-mini": {
- id: "o4-mini",
- name: "o4-mini",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.1,
- output: 4.4,
- cacheRead: 0.28,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-responses">,
- "o4-mini-deep-research": {
- id: "o4-mini-deep-research",
- name: "o4-mini-deep-research",
- api: "openai-responses",
- provider: "openai",
- baseUrl: "https://api.openai.com/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 8,
- cacheRead: 0.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-responses">,
- },
- "openai-codex": {
- "gpt-5.1": {
- id: "gpt-5.1",
- name: "GPT-5.1",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: "https://chatgpt.com/backend-api",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 272000,
- maxTokens: 128000,
- } satisfies Model<"openai-codex-responses">,
- "gpt-5.1-codex-max": {
- id: "gpt-5.1-codex-max",
- name: "GPT-5.1 Codex Max",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: "https://chatgpt.com/backend-api",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 272000,
- maxTokens: 128000,
- } satisfies Model<"openai-codex-responses">,
- "gpt-5.1-codex-mini": {
- id: "gpt-5.1-codex-mini",
- name: "GPT-5.1 Codex Mini",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: "https://chatgpt.com/backend-api",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0.025,
- cacheWrite: 0,
- },
- contextWindow: 272000,
- maxTokens: 128000,
- } satisfies Model<"openai-codex-responses">,
- "gpt-5.2": {
- id: "gpt-5.2",
- name: "GPT-5.2",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: "https://chatgpt.com/backend-api",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 272000,
- maxTokens: 128000,
- } satisfies Model<"openai-codex-responses">,
- "gpt-5.2-codex": {
- id: "gpt-5.2-codex",
- name: "GPT-5.2 Codex",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: "https://chatgpt.com/backend-api",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 272000,
- maxTokens: 128000,
- } satisfies Model<"openai-codex-responses">,
- "gpt-5.3-codex": {
- id: "gpt-5.3-codex",
- name: "GPT-5.3 Codex",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: "https://chatgpt.com/backend-api",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 272000,
- maxTokens: 128000,
- } satisfies Model<"openai-codex-responses">,
- "gpt-5.3-codex-spark": {
- id: "gpt-5.3-codex-spark",
- name: "GPT-5.3 Codex Spark",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: "https://chatgpt.com/backend-api",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"openai-codex-responses">,
- "gpt-5.4": {
- id: "gpt-5.4",
- name: "GPT-5.4",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: "https://chatgpt.com/backend-api",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 15,
- cacheRead: 0.25,
- cacheWrite: 0,
- },
- contextWindow: 272000,
- maxTokens: 128000,
- } satisfies Model<"openai-codex-responses">,
- "gpt-5.4-mini": {
- id: "gpt-5.4-mini",
- name: "GPT-5.4 Mini",
- api: "openai-codex-responses",
- provider: "openai-codex",
- baseUrl: "https://chatgpt.com/backend-api",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.75,
- output: 4.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 272000,
- maxTokens: 128000,
- } satisfies Model<"openai-codex-responses">,
- },
- "opencode": {
- "big-pickle": {
- id: "big-pickle",
- name: "Big Pickle",
- api: "anthropic-messages",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "claude-3-5-haiku": {
- id: "claude-3-5-haiku",
- name: "Claude Haiku 3.5",
- api: "anthropic-messages",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.8,
- output: 4,
- cacheRead: 0.08,
- cacheWrite: 1,
- },
- contextWindow: 200000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "claude-haiku-4-5": {
- id: "claude-haiku-4-5",
- name: "Claude Haiku 4.5",
- api: "anthropic-messages",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1,
- output: 5,
- cacheRead: 0.1,
- cacheWrite: 1.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4-1": {
- id: "claude-opus-4-1",
- name: "Claude Opus 4.1",
- api: "anthropic-messages",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4-5": {
- id: "claude-opus-4-5",
- name: "Claude Opus 4.5",
- api: "anthropic-messages",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4-6": {
- id: "claude-opus-4-6",
- name: "Claude Opus 4.6",
- api: "anthropic-messages",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "claude-opus-4-7": {
- id: "claude-opus-4-7",
- name: "Claude Opus 4.7",
- api: "anthropic-messages",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "claude-sonnet-4": {
- id: "claude-sonnet-4",
- name: "Claude Sonnet 4",
- api: "anthropic-messages",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-sonnet-4-5": {
- id: "claude-sonnet-4-5",
- name: "Claude Sonnet 4.5",
- api: "anthropic-messages",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "claude-sonnet-4-6": {
- id: "claude-sonnet-4-6",
- name: "Claude Sonnet 4.6",
- api: "anthropic-messages",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "gemini-3-flash": {
- id: "gemini-3-flash",
- name: "Gemini 3 Flash",
- api: "google-generative-ai",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 3,
- cacheRead: 0.05,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "gemini-3.1-pro": {
- id: "gemini-3.1-pro",
- name: "Gemini 3.1 Pro Preview",
- api: "google-generative-ai",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"google-generative-ai">,
- "glm-5": {
- id: "glm-5",
- name: "GLM-5",
- api: "openai-completions",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1,
- output: 3.2,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "glm-5.1": {
- id: "glm-5.1",
- name: "GLM-5.1",
- api: "openai-completions",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.4,
- output: 4.4,
- cacheRead: 0.26,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "gpt-5": {
- id: "gpt-5",
- name: "GPT-5",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.07,
- output: 8.5,
- cacheRead: 0.107,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5-codex": {
- id: "gpt-5-codex",
- name: "GPT-5 Codex",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.07,
- output: 8.5,
- cacheRead: 0.107,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5-nano": {
- id: "gpt-5-nano",
- name: "GPT-5 Nano",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.1": {
- id: "gpt-5.1",
- name: "GPT-5.1",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.07,
- output: 8.5,
- cacheRead: 0.107,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.1-codex": {
- id: "gpt-5.1-codex",
- name: "GPT-5.1 Codex",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.07,
- output: 8.5,
- cacheRead: 0.107,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.1-codex-max": {
- id: "gpt-5.1-codex-max",
- name: "GPT-5.1 Codex Max",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.1-codex-mini": {
- id: "gpt-5.1-codex-mini",
- name: "GPT-5.1 Codex Mini",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0.025,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.2": {
- id: "gpt-5.2",
- name: "GPT-5.2",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.2-codex": {
- id: "gpt-5.2-codex",
- name: "GPT-5.2 Codex",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.3-codex": {
- id: "gpt-5.3-codex",
- name: "GPT-5.3 Codex",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.4": {
- id: "gpt-5.4",
- name: "GPT-5.4",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 15,
- cacheRead: 0.25,
- cacheWrite: 0,
- },
- contextWindow: 272000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.4-mini": {
- id: "gpt-5.4-mini",
- name: "GPT-5.4 Mini",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.75,
- output: 4.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.4-nano": {
- id: "gpt-5.4-nano",
- name: "GPT-5.4 Nano",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.2,
- output: 1.25,
- cacheRead: 0.02,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "gpt-5.4-pro": {
- id: "gpt-5.4-pro",
- name: "GPT-5.4 Pro",
- api: "openai-responses",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 30,
- output: 180,
- cacheRead: 30,
- cacheWrite: 0,
- },
- contextWindow: 1050000,
- maxTokens: 128000,
- } satisfies Model<"openai-responses">,
- "kimi-k2.5": {
- id: "kimi-k2.5",
- name: "Kimi K2.5",
- api: "openai-completions",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.6,
- output: 3,
- cacheRead: 0.08,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "minimax-m2.5": {
- id: "minimax-m2.5",
- name: "MiniMax M2.5",
- api: "openai-completions",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.06,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "minimax-m2.5-free": {
- id: "minimax-m2.5-free",
- name: "MiniMax M2.5 Free",
- api: "anthropic-messages",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "nemotron-3-super-free": {
- id: "nemotron-3-super-free",
- name: "Nemotron 3 Super Free",
- api: "openai-completions",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "qwen3.5-plus": {
- id: "qwen3.5-plus",
- name: "Qwen3.5 Plus",
- api: "openai-completions",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.2,
- output: 1.2,
- cacheRead: 0.02,
- cacheWrite: 0.25,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "qwen3.6-plus": {
- id: "qwen3.6-plus",
- name: "Qwen3.6 Plus",
- api: "openai-completions",
- provider: "opencode",
- baseUrl: "https://opencode.ai/zen/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 3,
- cacheRead: 0.05,
- cacheWrite: 0.625,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- },
- "opencode-go": {
- "glm-5": {
- id: "glm-5",
- name: "GLM-5",
- api: "openai-completions",
- provider: "opencode-go",
- baseUrl: "https://opencode.ai/zen/go/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1,
- output: 3.2,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "glm-5.1": {
- id: "glm-5.1",
- name: "GLM-5.1",
- api: "openai-completions",
- provider: "opencode-go",
- baseUrl: "https://opencode.ai/zen/go/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.4,
- output: 4.4,
- cacheRead: 0.26,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "kimi-k2.5": {
- id: "kimi-k2.5",
- name: "Kimi K2.5",
- api: "openai-completions",
- provider: "opencode-go",
- baseUrl: "https://opencode.ai/zen/go/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.6,
- output: 3,
- cacheRead: 0.1,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "mimo-v2-omni": {
- id: "mimo-v2-omni",
- name: "MiMo V2 Omni",
- api: "openai-completions",
- provider: "opencode-go",
- baseUrl: "https://opencode.ai/zen/go/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.4,
- output: 2,
- cacheRead: 0.08,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "mimo-v2-pro": {
- id: "mimo-v2-pro",
- name: "MiMo V2 Pro",
- api: "openai-completions",
- provider: "opencode-go",
- baseUrl: "https://opencode.ai/zen/go/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1,
- output: 3,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "minimax-m2.5": {
- id: "minimax-m2.5",
- name: "MiniMax M2.5",
- api: "anthropic-messages",
- provider: "opencode-go",
- baseUrl: "https://opencode.ai/zen/go",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.03,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "minimax-m2.7": {
- id: "minimax-m2.7",
- name: "MiniMax M2.7",
- api: "anthropic-messages",
- provider: "opencode-go",
- baseUrl: "https://opencode.ai/zen/go",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.06,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "qwen3.5-plus": {
- id: "qwen3.5-plus",
- name: "Qwen3.5 Plus",
- api: "openai-completions",
- provider: "opencode-go",
- baseUrl: "https://opencode.ai/zen/go/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.2,
- output: 1.2,
- cacheRead: 0.02,
- cacheWrite: 0.25,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "qwen3.6-plus": {
- id: "qwen3.6-plus",
- name: "Qwen3.6 Plus",
- api: "openai-completions",
- provider: "opencode-go",
- baseUrl: "https://opencode.ai/zen/go/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 3,
- cacheRead: 0.05,
- cacheWrite: 0.625,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- },
- "openrouter": {
- "ai21/jamba-large-1.7": {
- id: "ai21/jamba-large-1.7",
- name: "AI21: Jamba Large 1.7",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2,
- output: 8,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "alibaba/tongyi-deepresearch-30b-a3b": {
- id: "alibaba/tongyi-deepresearch-30b-a3b",
- name: "Tongyi DeepResearch 30B A3B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.09,
- output: 0.44999999999999996,
- cacheRead: 0.09,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "allenai/olmo-3.1-32b-instruct": {
- id: "allenai/olmo-3.1-32b-instruct",
- name: "AllenAI: Olmo 3.1 32B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.19999999999999998,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 65536,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "amazon/nova-2-lite-v1": {
- id: "amazon/nova-2-lite-v1",
- name: "Amazon: Nova 2 Lite",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.3,
- output: 2.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 65535,
- } satisfies Model<"openai-completions">,
- "amazon/nova-lite-v1": {
- id: "amazon/nova-lite-v1",
- name: "Amazon: Nova Lite 1.0",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.06,
- output: 0.24,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 300000,
- maxTokens: 5120,
- } satisfies Model<"openai-completions">,
- "amazon/nova-micro-v1": {
- id: "amazon/nova-micro-v1",
- name: "Amazon: Nova Micro 1.0",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.035,
- output: 0.14,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 5120,
- } satisfies Model<"openai-completions">,
- "amazon/nova-premier-v1": {
- id: "amazon/nova-premier-v1",
- name: "Amazon: Nova Premier 1.0",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 12.5,
- cacheRead: 0.625,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 32000,
- } satisfies Model<"openai-completions">,
- "amazon/nova-pro-v1": {
- id: "amazon/nova-pro-v1",
- name: "Amazon: Nova Pro 1.0",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.7999999999999999,
- output: 3.1999999999999997,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 300000,
- maxTokens: 5120,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-3-haiku": {
- id: "anthropic/claude-3-haiku",
- name: "Anthropic: Claude 3 Haiku",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 1.25,
- cacheRead: 0.03,
- cacheWrite: 0.3,
- },
- contextWindow: 200000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-3.5-haiku": {
- id: "anthropic/claude-3.5-haiku",
- name: "Anthropic: Claude 3.5 Haiku",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.7999999999999999,
- output: 4,
- cacheRead: 0.08,
- cacheWrite: 1,
- },
- contextWindow: 200000,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-3.7-sonnet": {
- id: "anthropic/claude-3.7-sonnet",
- name: "Anthropic: Claude 3.7 Sonnet",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-3.7-sonnet:thinking": {
- id: "anthropic/claude-3.7-sonnet:thinking",
- name: "Anthropic: Claude 3.7 Sonnet (thinking)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-haiku-4.5": {
- id: "anthropic/claude-haiku-4.5",
- name: "Anthropic: Claude Haiku 4.5",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1,
- output: 5,
- cacheRead: 0.09999999999999999,
- cacheWrite: 1.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-opus-4": {
- id: "anthropic/claude-opus-4",
- name: "Anthropic: Claude Opus 4",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-opus-4.1": {
- id: "anthropic/claude-opus-4.1",
- name: "Anthropic: Claude Opus 4.1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-opus-4.5": {
- id: "anthropic/claude-opus-4.5",
- name: "Anthropic: Claude Opus 4.5",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-opus-4.6": {
- id: "anthropic/claude-opus-4.6",
- name: "Anthropic: Claude Opus 4.6",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-opus-4.6-fast": {
- id: "anthropic/claude-opus-4.6-fast",
- name: "Anthropic: Claude Opus 4.6 (Fast)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 30,
- output: 150,
- cacheRead: 3,
- cacheWrite: 37.5,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-opus-4.7": {
- id: "anthropic/claude-opus-4.7",
- name: "Anthropic: Claude Opus 4.7",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-sonnet-4": {
- id: "anthropic/claude-sonnet-4",
- name: "Anthropic: Claude Sonnet 4",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-sonnet-4.5": {
- id: "anthropic/claude-sonnet-4.5",
- name: "Anthropic: Claude Sonnet 4.5",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "anthropic/claude-sonnet-4.6": {
- id: "anthropic/claude-sonnet-4.6",
- name: "Anthropic: Claude Sonnet 4.6",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "arcee-ai/trinity-large-preview:free": {
- id: "arcee-ai/trinity-large-preview:free",
- name: "Arcee AI: Trinity Large Preview (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "arcee-ai/trinity-large-thinking": {
- id: "arcee-ai/trinity-large-thinking",
- name: "Arcee AI: Trinity Large Thinking",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.22,
- output: 0.85,
- cacheRead: 0.06,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"openai-completions">,
- "arcee-ai/trinity-mini": {
- id: "arcee-ai/trinity-mini",
- name: "Arcee AI: Trinity Mini",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.045,
- output: 0.15,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "arcee-ai/virtuoso-large": {
- id: "arcee-ai/virtuoso-large",
- name: "Arcee AI: Virtuoso Large",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.75,
- output: 1.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "auto": {
- id: "auto",
- name: "Auto",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 30000,
- } satisfies Model<"openai-completions">,
- "baidu/ernie-4.5-21b-a3b": {
- id: "baidu/ernie-4.5-21b-a3b",
- name: "Baidu: ERNIE 4.5 21B A3B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.07,
- output: 0.28,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 120000,
- maxTokens: 8000,
- } satisfies Model<"openai-completions">,
- "baidu/ernie-4.5-vl-28b-a3b": {
- id: "baidu/ernie-4.5-vl-28b-a3b",
- name: "Baidu: ERNIE 4.5 VL 28B A3B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.14,
- output: 0.56,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 30000,
- maxTokens: 8000,
- } satisfies Model<"openai-completions">,
- "bytedance-seed/seed-1.6": {
- id: "bytedance-seed/seed-1.6",
- name: "ByteDance Seed: Seed 1.6",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "bytedance-seed/seed-1.6-flash": {
- id: "bytedance-seed/seed-1.6-flash",
- name: "ByteDance Seed: Seed 1.6 Flash",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.075,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "bytedance-seed/seed-2.0-lite": {
- id: "bytedance-seed/seed-2.0-lite",
- name: "ByteDance Seed: Seed-2.0-Lite",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "bytedance-seed/seed-2.0-mini": {
- id: "bytedance-seed/seed-2.0-mini",
- name: "ByteDance Seed: Seed-2.0-Mini",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.09999999999999999,
- output: 0.39999999999999997,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "cohere/command-r-08-2024": {
- id: "cohere/command-r-08-2024",
- name: "Cohere: Command R (08-2024)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4000,
- } satisfies Model<"openai-completions">,
- "cohere/command-r-plus-08-2024": {
- id: "cohere/command-r-plus-08-2024",
- name: "Cohere: Command R+ (08-2024)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4000,
- } satisfies Model<"openai-completions">,
- "deepseek/deepseek-chat": {
- id: "deepseek/deepseek-chat",
- name: "DeepSeek: DeepSeek V3",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.32,
- output: 0.8899999999999999,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 163840,
- } satisfies Model<"openai-completions">,
- "deepseek/deepseek-chat-v3-0324": {
- id: "deepseek/deepseek-chat-v3-0324",
- name: "DeepSeek: DeepSeek V3 0324",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.19999999999999998,
- output: 0.77,
- cacheRead: 0.135,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "deepseek/deepseek-chat-v3.1": {
- id: "deepseek/deepseek-chat-v3.1",
- name: "DeepSeek: DeepSeek V3.1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.75,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32768,
- maxTokens: 7168,
- } satisfies Model<"openai-completions">,
- "deepseek/deepseek-r1": {
- id: "deepseek/deepseek-r1",
- name: "DeepSeek: R1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.7,
- output: 2.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 64000,
- maxTokens: 16000,
- } satisfies Model<"openai-completions">,
- "deepseek/deepseek-r1-0528": {
- id: "deepseek/deepseek-r1-0528",
- name: "DeepSeek: R1 0528",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.5,
- output: 2.1500000000000004,
- cacheRead: 0.35,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "deepseek/deepseek-v3.1-terminus": {
- id: "deepseek/deepseek-v3.1-terminus",
- name: "DeepSeek: DeepSeek V3.1 Terminus",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.21,
- output: 0.7899999999999999,
- cacheRead: 0.1300000002,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "deepseek/deepseek-v3.2": {
- id: "deepseek/deepseek-v3.2",
- name: "DeepSeek: DeepSeek V3.2",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.26,
- output: 0.38,
- cacheRead: 0.13,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "deepseek/deepseek-v3.2-exp": {
- id: "deepseek/deepseek-v3.2-exp",
- name: "DeepSeek: DeepSeek V3.2 Exp",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.27,
- output: 0.41,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "essentialai/rnj-1-instruct": {
- id: "essentialai/rnj-1-instruct",
- name: "EssentialAI: Rnj 1 Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.15,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32768,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "google/gemini-2.0-flash-001": {
- id: "google/gemini-2.0-flash-001",
- name: "Google: Gemini 2.0 Flash",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.09999999999999999,
- output: 0.39999999999999997,
- cacheRead: 0.024999999999999998,
- cacheWrite: 0.08333333333333334,
- },
- contextWindow: 1048576,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "google/gemini-2.0-flash-lite-001": {
- id: "google/gemini-2.0-flash-lite-001",
- name: "Google: Gemini 2.0 Flash Lite",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.075,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "google/gemini-2.5-flash": {
- id: "google/gemini-2.5-flash",
- name: "Google: Gemini 2.5 Flash",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.3,
- output: 2.5,
- cacheRead: 0.03,
- cacheWrite: 0.08333333333333334,
- },
- contextWindow: 1048576,
- maxTokens: 65535,
- } satisfies Model<"openai-completions">,
- "google/gemini-2.5-flash-lite": {
- id: "google/gemini-2.5-flash-lite",
- name: "Google: Gemini 2.5 Flash Lite",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.09999999999999999,
- output: 0.39999999999999997,
- cacheRead: 0.01,
- cacheWrite: 0.08333333333333334,
- },
- contextWindow: 1048576,
- maxTokens: 65535,
- } satisfies Model<"openai-completions">,
- "google/gemini-2.5-flash-lite-preview-09-2025": {
- id: "google/gemini-2.5-flash-lite-preview-09-2025",
- name: "Google: Gemini 2.5 Flash Lite Preview 09-2025",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.09999999999999999,
- output: 0.39999999999999997,
- cacheRead: 0.01,
- cacheWrite: 0.08333333333333334,
- },
- contextWindow: 1048576,
- maxTokens: 65535,
- } satisfies Model<"openai-completions">,
- "google/gemini-2.5-pro": {
- id: "google/gemini-2.5-pro",
- name: "Google: Gemini 2.5 Pro",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0.375,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "google/gemini-2.5-pro-preview": {
- id: "google/gemini-2.5-pro-preview",
- name: "Google: Gemini 2.5 Pro Preview 06-05",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0.375,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "google/gemini-2.5-pro-preview-05-06": {
- id: "google/gemini-2.5-pro-preview-05-06",
- name: "Google: Gemini 2.5 Pro Preview 05-06",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0.375,
- },
- contextWindow: 1048576,
- maxTokens: 65535,
- } satisfies Model<"openai-completions">,
- "google/gemini-3-flash-preview": {
- id: "google/gemini-3-flash-preview",
- name: "Google: Gemini 3 Flash Preview",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 3,
- cacheRead: 0.049999999999999996,
- cacheWrite: 0.08333333333333334,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "google/gemini-3.1-flash-lite-preview": {
- id: "google/gemini-3.1-flash-lite-preview",
- name: "Google: Gemini 3.1 Flash Lite Preview",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 1.5,
- cacheRead: 0.024999999999999998,
- cacheWrite: 0.08333333333333334,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "google/gemini-3.1-pro-preview": {
- id: "google/gemini-3.1-pro-preview",
- name: "Google: Gemini 3.1 Pro Preview",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0.375,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "google/gemini-3.1-pro-preview-customtools": {
- id: "google/gemini-3.1-pro-preview-customtools",
- name: "Google: Gemini 3.1 Pro Preview Custom Tools",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0.375,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "google/gemma-4-26b-a4b-it": {
- id: "google/gemma-4-26b-a4b-it",
- name: "Google: Gemma 4 26B A4B ",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.07,
- output: 0.39999999999999997,
- cacheRead: 0.04,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"openai-completions">,
- "google/gemma-4-26b-a4b-it:free": {
- id: "google/gemma-4-26b-a4b-it:free",
- name: "Google: Gemma 4 26B A4B (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "google/gemma-4-31b-it": {
- id: "google/gemma-4-31b-it",
- name: "Google: Gemma 4 31B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.13,
- output: 0.38,
- cacheRead: 0.019999999499999997,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "google/gemma-4-31b-it:free": {
- id: "google/gemma-4-31b-it:free",
- name: "Google: Gemma 4 31B (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "inception/mercury-2": {
- id: "inception/mercury-2",
- name: "Inception: Mercury 2",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.25,
- output: 0.75,
- cacheRead: 0.024999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 50000,
- } satisfies Model<"openai-completions">,
- "kwaipilot/kat-coder-pro-v2": {
- id: "kwaipilot/kat-coder-pro-v2",
- name: "Kwaipilot: KAT-Coder-Pro V2",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.06,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 80000,
- } satisfies Model<"openai-completions">,
- "meta-llama/llama-3-8b-instruct": {
- id: "meta-llama/llama-3-8b-instruct",
- name: "Meta: Llama 3 8B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.03,
- output: 0.04,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 8192,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "meta-llama/llama-3.1-70b-instruct": {
- id: "meta-llama/llama-3.1-70b-instruct",
- name: "Meta: Llama 3.1 70B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.39999999999999997,
- output: 0.39999999999999997,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "meta-llama/llama-3.1-8b-instruct": {
- id: "meta-llama/llama-3.1-8b-instruct",
- name: "Meta: Llama 3.1 8B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.02,
- output: 0.049999999999999996,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 16384,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "meta-llama/llama-3.3-70b-instruct": {
- id: "meta-llama/llama-3.3-70b-instruct",
- name: "Meta: Llama 3.3 70B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.09999999999999999,
- output: 0.32,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "meta-llama/llama-3.3-70b-instruct:free": {
- id: "meta-llama/llama-3.3-70b-instruct:free",
- name: "Meta: Llama 3.3 70B Instruct (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 65536,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "meta-llama/llama-4-maverick": {
- id: "meta-llama/llama-4-maverick",
- name: "Meta: Llama 4 Maverick",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "meta-llama/llama-4-scout": {
- id: "meta-llama/llama-4-scout",
- name: "Meta: Llama 4 Scout",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.08,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 327680,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "minimax/minimax-m1": {
- id: "minimax/minimax-m1",
- name: "MiniMax: MiniMax M1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.39999999999999997,
- output: 2.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 40000,
- } satisfies Model<"openai-completions">,
- "minimax/minimax-m2": {
- id: "minimax/minimax-m2",
- name: "MiniMax: MiniMax M2",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.255,
- output: 1,
- cacheRead: 0.03,
- cacheWrite: 0,
- },
- contextWindow: 196608,
- maxTokens: 196608,
- } satisfies Model<"openai-completions">,
- "minimax/minimax-m2.1": {
- id: "minimax/minimax-m2.1",
- name: "MiniMax: MiniMax M2.1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.29,
- output: 0.95,
- cacheRead: 0.03,
- cacheWrite: 0,
- },
- contextWindow: 196608,
- maxTokens: 196608,
- } satisfies Model<"openai-completions">,
- "minimax/minimax-m2.5": {
- id: "minimax/minimax-m2.5",
- name: "MiniMax: MiniMax M2.5",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.118,
- output: 0.9900000000000001,
- cacheRead: 0.059,
- cacheWrite: 0,
- },
- contextWindow: 196608,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "minimax/minimax-m2.5:free": {
- id: "minimax/minimax-m2.5:free",
- name: "MiniMax: MiniMax M2.5 (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 196608,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "minimax/minimax-m2.7": {
- id: "minimax/minimax-m2.7",
- name: "MiniMax: MiniMax M2.7",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.059,
- cacheWrite: 0,
- },
- contextWindow: 196608,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/codestral-2508": {
- id: "mistralai/codestral-2508",
- name: "Mistral: Codestral 2508",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 0.8999999999999999,
- cacheRead: 0.03,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/devstral-2512": {
- id: "mistralai/devstral-2512",
- name: "Mistral: Devstral 2 2512",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.39999999999999997,
- output: 2,
- cacheRead: 0.04,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/devstral-medium": {
- id: "mistralai/devstral-medium",
- name: "Mistral: Devstral Medium",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.39999999999999997,
- output: 2,
- cacheRead: 0.04,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/devstral-small": {
- id: "mistralai/devstral-small",
- name: "Mistral: Devstral Small 1.1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.09999999999999999,
- output: 0.3,
- cacheRead: 0.01,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/ministral-14b-2512": {
- id: "mistralai/ministral-14b-2512",
- name: "Mistral: Ministral 3 14B 2512",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.19999999999999998,
- output: 0.19999999999999998,
- cacheRead: 0.02,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/ministral-3b-2512": {
- id: "mistralai/ministral-3b-2512",
- name: "Mistral: Ministral 3 3B 2512",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.09999999999999999,
- output: 0.09999999999999999,
- cacheRead: 0.01,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/ministral-8b-2512": {
- id: "mistralai/ministral-8b-2512",
- name: "Mistral: Ministral 3 8B 2512",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.15,
- cacheRead: 0.015,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/mistral-large": {
- id: "mistralai/mistral-large",
- name: "Mistral Large",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/mistral-large-2407": {
- id: "mistralai/mistral-large-2407",
- name: "Mistral Large 2407",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/mistral-large-2411": {
- id: "mistralai/mistral-large-2411",
- name: "Mistral Large 2411",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/mistral-large-2512": {
- id: "mistralai/mistral-large-2512",
- name: "Mistral: Mistral Large 3 2512",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 1.5,
- cacheRead: 0.049999999999999996,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/mistral-medium-3": {
- id: "mistralai/mistral-medium-3",
- name: "Mistral: Mistral Medium 3",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.39999999999999997,
- output: 2,
- cacheRead: 0.04,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/mistral-medium-3.1": {
- id: "mistralai/mistral-medium-3.1",
- name: "Mistral: Mistral Medium 3.1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.39999999999999997,
- output: 2,
- cacheRead: 0.04,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/mistral-nemo": {
- id: "mistralai/mistral-nemo",
- name: "Mistral: Mistral Nemo",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.02,
- output: 0.04,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "mistralai/mistral-saba": {
- id: "mistralai/mistral-saba",
- name: "Mistral: Saba",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.19999999999999998,
- output: 0.6,
- cacheRead: 0.02,
- cacheWrite: 0,
- },
- contextWindow: 32768,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/mistral-small-2603": {
- id: "mistralai/mistral-small-2603",
- name: "Mistral: Mistral Small 4",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0.015,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/mistral-small-3.2-24b-instruct": {
- id: "mistralai/mistral-small-3.2-24b-instruct",
- name: "Mistral: Mistral Small 3.2 24B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.075,
- output: 0.19999999999999998,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/mistral-small-creative": {
- id: "mistralai/mistral-small-creative",
- name: "Mistral: Mistral Small Creative",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.09999999999999999,
- output: 0.3,
- cacheRead: 0.01,
- cacheWrite: 0,
- },
- contextWindow: 32768,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/mixtral-8x22b-instruct": {
- id: "mistralai/mixtral-8x22b-instruct",
- name: "Mistral: Mixtral 8x22B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 65536,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/mixtral-8x7b-instruct": {
- id: "mistralai/mixtral-8x7b-instruct",
- name: "Mistral: Mixtral 8x7B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.54,
- output: 0.54,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32768,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "mistralai/pixtral-large-2411": {
- id: "mistralai/pixtral-large-2411",
- name: "Mistral: Pixtral Large 2411",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "mistralai/voxtral-small-24b-2507": {
- id: "mistralai/voxtral-small-24b-2507",
- name: "Mistral: Voxtral Small 24B 2507",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.09999999999999999,
- output: 0.3,
- cacheRead: 0.01,
- cacheWrite: 0,
- },
- contextWindow: 32000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "moonshotai/kimi-k2": {
- id: "moonshotai/kimi-k2",
- name: "MoonshotAI: Kimi K2 0711",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.5700000000000001,
- output: 2.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "moonshotai/kimi-k2-0905": {
- id: "moonshotai/kimi-k2-0905",
- name: "MoonshotAI: Kimi K2 0905",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.39999999999999997,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"openai-completions">,
- "moonshotai/kimi-k2-thinking": {
- id: "moonshotai/kimi-k2-thinking",
- name: "MoonshotAI: Kimi K2 Thinking",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.5,
- cacheRead: 0.15,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"openai-completions">,
- "moonshotai/kimi-k2.5": {
- id: "moonshotai/kimi-k2.5",
- name: "MoonshotAI: Kimi K2.5",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.41,
- output: 2.06,
- cacheRead: 0.07,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "nex-agi/deepseek-v3.1-nex-n1": {
- id: "nex-agi/deepseek-v3.1-nex-n1",
- name: "Nex AGI: DeepSeek V3.1 Nex N1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.135,
- output: 0.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 163840,
- } satisfies Model<"openai-completions">,
- "nvidia/llama-3.1-nemotron-70b-instruct": {
- id: "nvidia/llama-3.1-nemotron-70b-instruct",
- name: "NVIDIA: Llama 3.1 Nemotron 70B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1.2,
- output: 1.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "nvidia/llama-3.3-nemotron-super-49b-v1.5": {
- id: "nvidia/llama-3.3-nemotron-super-49b-v1.5",
- name: "NVIDIA: Llama 3.3 Nemotron Super 49B V1.5",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.09999999999999999,
- output: 0.39999999999999997,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "nvidia/nemotron-3-nano-30b-a3b": {
- id: "nvidia/nemotron-3-nano-30b-a3b",
- name: "NVIDIA: Nemotron 3 Nano 30B A3B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.049999999999999996,
- output: 0.19999999999999998,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "nvidia/nemotron-3-nano-30b-a3b:free": {
- id: "nvidia/nemotron-3-nano-30b-a3b:free",
- name: "NVIDIA: Nemotron 3 Nano 30B A3B (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "nvidia/nemotron-3-super-120b-a12b": {
- id: "nvidia/nemotron-3-super-120b-a12b",
- name: "NVIDIA: Nemotron 3 Super",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.09999999999999999,
- output: 0.5,
- cacheRead: 0.09999999999999999,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "nvidia/nemotron-3-super-120b-a12b:free": {
- id: "nvidia/nemotron-3-super-120b-a12b:free",
- name: "NVIDIA: Nemotron 3 Super (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"openai-completions">,
- "nvidia/nemotron-nano-12b-v2-vl:free": {
- id: "nvidia/nemotron-nano-12b-v2-vl:free",
- name: "NVIDIA: Nemotron Nano 12B 2 VL (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "nvidia/nemotron-nano-9b-v2": {
- id: "nvidia/nemotron-nano-9b-v2",
- name: "NVIDIA: Nemotron Nano 9B V2",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.04,
- output: 0.16,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "nvidia/nemotron-nano-9b-v2:free": {
- id: "nvidia/nemotron-nano-9b-v2:free",
- name: "NVIDIA: Nemotron Nano 9B V2 (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-3.5-turbo": {
- id: "openai/gpt-3.5-turbo",
- name: "OpenAI: GPT-3.5 Turbo",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.5,
- output: 1.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 16385,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-3.5-turbo-0613": {
- id: "openai/gpt-3.5-turbo-0613",
- name: "OpenAI: GPT-3.5 Turbo (older v0613)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 4095,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-3.5-turbo-16k": {
- id: "openai/gpt-3.5-turbo-16k",
- name: "OpenAI: GPT-3.5 Turbo 16k",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 3,
- output: 4,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 16385,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4": {
- id: "openai/gpt-4",
- name: "OpenAI: GPT-4",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 30,
- output: 60,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 8191,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4-0314": {
- id: "openai/gpt-4-0314",
- name: "OpenAI: GPT-4 (older v0314)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 30,
- output: 60,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 8191,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4-1106-preview": {
- id: "openai/gpt-4-1106-preview",
- name: "OpenAI: GPT-4 Turbo (older v1106)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 10,
- output: 30,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4-turbo": {
- id: "openai/gpt-4-turbo",
- name: "OpenAI: GPT-4 Turbo",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 10,
- output: 30,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4-turbo-preview": {
- id: "openai/gpt-4-turbo-preview",
- name: "OpenAI: GPT-4 Turbo Preview",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 10,
- output: 30,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4.1": {
- id: "openai/gpt-4.1",
- name: "OpenAI: GPT-4.1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 8,
- cacheRead: 0.5,
- cacheWrite: 0,
- },
- contextWindow: 1047576,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4.1-mini": {
- id: "openai/gpt-4.1-mini",
- name: "OpenAI: GPT-4.1 Mini",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.39999999999999997,
- output: 1.5999999999999999,
- cacheRead: 0.09999999999999999,
- cacheWrite: 0,
- },
- contextWindow: 1047576,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4.1-nano": {
- id: "openai/gpt-4.1-nano",
- name: "OpenAI: GPT-4.1 Nano",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.09999999999999999,
- output: 0.39999999999999997,
- cacheRead: 0.024999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 1047576,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4o": {
- id: "openai/gpt-4o",
- name: "OpenAI: GPT-4o",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4o-2024-05-13": {
- id: "openai/gpt-4o-2024-05-13",
- name: "OpenAI: GPT-4o (2024-05-13)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 15,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4o-2024-08-06": {
- id: "openai/gpt-4o-2024-08-06",
- name: "OpenAI: GPT-4o (2024-08-06)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4o-2024-11-20": {
- id: "openai/gpt-4o-2024-11-20",
- name: "OpenAI: GPT-4o (2024-11-20)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4o-audio-preview": {
- id: "openai/gpt-4o-audio-preview",
- name: "OpenAI: GPT-4o Audio",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4o-mini": {
- id: "openai/gpt-4o-mini",
- name: "OpenAI: GPT-4o-mini",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4o-mini-2024-07-18": {
- id: "openai/gpt-4o-mini-2024-07-18",
- name: "OpenAI: GPT-4o-mini (2024-07-18)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "openai/gpt-4o:extended": {
- id: "openai/gpt-4o:extended",
- name: "OpenAI: GPT-4o (extended)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 6,
- output: 18,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5": {
- id: "openai/gpt-5",
- name: "OpenAI: GPT-5",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5-codex": {
- id: "openai/gpt-5-codex",
- name: "OpenAI: GPT-5 Codex",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5-image": {
- id: "openai/gpt-5-image",
- name: "OpenAI: GPT-5 Image",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 10,
- output: 10,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5-image-mini": {
- id: "openai/gpt-5-image-mini",
- name: "OpenAI: GPT-5 Image Mini",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 2,
- cacheRead: 0.25,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5-mini": {
- id: "openai/gpt-5-mini",
- name: "OpenAI: GPT-5 Mini",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0.024999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5-nano": {
- id: "openai/gpt-5-nano",
- name: "OpenAI: GPT-5 Nano",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.049999999999999996,
- output: 0.39999999999999997,
- cacheRead: 0.01,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5-pro": {
- id: "openai/gpt-5-pro",
- name: "OpenAI: GPT-5 Pro",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 120,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.1": {
- id: "openai/gpt-5.1",
- name: "OpenAI: GPT-5.1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.13,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.1-chat": {
- id: "openai/gpt-5.1-chat",
- name: "OpenAI: GPT-5.1 Chat",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.1-codex": {
- id: "openai/gpt-5.1-codex",
- name: "OpenAI: GPT-5.1-Codex",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.1-codex-max": {
- id: "openai/gpt-5.1-codex-max",
- name: "OpenAI: GPT-5.1-Codex-Max",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.1-codex-mini": {
- id: "openai/gpt-5.1-codex-mini",
- name: "OpenAI: GPT-5.1-Codex-Mini",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0.03,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.2": {
- id: "openai/gpt-5.2",
- name: "OpenAI: GPT-5.2",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.2-chat": {
- id: "openai/gpt-5.2-chat",
- name: "OpenAI: GPT-5.2 Chat",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 32000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.2-codex": {
- id: "openai/gpt-5.2-codex",
- name: "OpenAI: GPT-5.2-Codex",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.2-pro": {
- id: "openai/gpt-5.2-pro",
- name: "OpenAI: GPT-5.2 Pro",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 21,
- output: 168,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.3-chat": {
- id: "openai/gpt-5.3-chat",
- name: "OpenAI: GPT-5.3 Chat",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.3-codex": {
- id: "openai/gpt-5.3-codex",
- name: "OpenAI: GPT-5.3-Codex",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.4": {
- id: "openai/gpt-5.4",
- name: "OpenAI: GPT-5.4",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 15,
- cacheRead: 0.25,
- cacheWrite: 0,
- },
- contextWindow: 1050000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.4-mini": {
- id: "openai/gpt-5.4-mini",
- name: "OpenAI: GPT-5.4 Mini",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.75,
- output: 4.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.4-nano": {
- id: "openai/gpt-5.4-nano",
- name: "OpenAI: GPT-5.4 Nano",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.19999999999999998,
- output: 1.25,
- cacheRead: 0.02,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-5.4-pro": {
- id: "openai/gpt-5.4-pro",
- name: "OpenAI: GPT-5.4 Pro",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 30,
- output: 180,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1050000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "openai/gpt-audio": {
- id: "openai/gpt-audio",
- name: "OpenAI: GPT Audio",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "openai/gpt-audio-mini": {
- id: "openai/gpt-audio-mini",
- name: "OpenAI: GPT Audio Mini",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.4,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "openai/gpt-oss-120b": {
- id: "openai/gpt-oss-120b",
- name: "OpenAI: gpt-oss-120b",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.039,
- output: 0.19,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-oss-120b:free": {
- id: "openai/gpt-oss-120b:free",
- name: "OpenAI: gpt-oss-120b (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "openai/gpt-oss-20b": {
- id: "openai/gpt-oss-20b",
- name: "OpenAI: gpt-oss-20b",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.03,
- output: 0.14,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openai/gpt-oss-20b:free": {
- id: "openai/gpt-oss-20b:free",
- name: "OpenAI: gpt-oss-20b (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "openai/gpt-oss-safeguard-20b": {
- id: "openai/gpt-oss-safeguard-20b",
- name: "OpenAI: gpt-oss-safeguard-20b",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.075,
- output: 0.3,
- cacheRead: 0.037,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "openai/o1": {
- id: "openai/o1",
- name: "OpenAI: o1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 60,
- cacheRead: 7.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-completions">,
- "openai/o3": {
- id: "openai/o3",
- name: "OpenAI: o3",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 8,
- cacheRead: 0.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-completions">,
- "openai/o3-deep-research": {
- id: "openai/o3-deep-research",
- name: "OpenAI: o3 Deep Research",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 10,
- output: 40,
- cacheRead: 2.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-completions">,
- "openai/o3-mini": {
- id: "openai/o3-mini",
- name: "OpenAI: o3 Mini",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.1,
- output: 4.4,
- cacheRead: 0.55,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-completions">,
- "openai/o3-mini-high": {
- id: "openai/o3-mini-high",
- name: "OpenAI: o3 Mini High",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.1,
- output: 4.4,
- cacheRead: 0.55,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-completions">,
- "openai/o3-pro": {
- id: "openai/o3-pro",
- name: "OpenAI: o3 Pro",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 20,
- output: 80,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-completions">,
- "openai/o4-mini": {
- id: "openai/o4-mini",
- name: "OpenAI: o4 Mini",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.1,
- output: 4.4,
- cacheRead: 0.275,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-completions">,
- "openai/o4-mini-deep-research": {
- id: "openai/o4-mini-deep-research",
- name: "OpenAI: o4 Mini Deep Research",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 8,
- cacheRead: 0.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-completions">,
- "openai/o4-mini-high": {
- id: "openai/o4-mini-high",
- name: "OpenAI: o4 Mini High",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.1,
- output: 4.4,
- cacheRead: 0.275,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"openai-completions">,
- "openrouter/auto": {
- id: "openrouter/auto",
- name: "Auto Router",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: -1000000,
- output: -1000000,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "openrouter/elephant-alpha": {
- id: "openrouter/elephant-alpha",
- name: "Elephant",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "openrouter/free": {
- id: "openrouter/free",
- name: "Free Models Router",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "prime-intellect/intellect-3": {
- id: "prime-intellect/intellect-3",
- name: "Prime Intellect: INTELLECT-3",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.19999999999999998,
- output: 1.1,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "qwen/qwen-2.5-72b-instruct": {
- id: "qwen/qwen-2.5-72b-instruct",
- name: "Qwen2.5 72B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.12,
- output: 0.39,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32768,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "qwen/qwen-2.5-7b-instruct": {
- id: "qwen/qwen-2.5-7b-instruct",
- name: "Qwen: Qwen2.5 7B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.04,
- output: 0.09999999999999999,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32768,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen-max": {
- id: "qwen/qwen-max",
- name: "Qwen: Qwen-Max ",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1.04,
- output: 4.16,
- cacheRead: 0.20800000000000002,
- cacheWrite: 0,
- },
- contextWindow: 32768,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "qwen/qwen-plus": {
- id: "qwen/qwen-plus",
- name: "Qwen: Qwen-Plus",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.26,
- output: 0.78,
- cacheRead: 0.052000000000000005,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen-plus-2025-07-28": {
- id: "qwen/qwen-plus-2025-07-28",
- name: "Qwen: Qwen Plus 0728",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.26,
- output: 0.78,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen-plus-2025-07-28:thinking": {
- id: "qwen/qwen-plus-2025-07-28:thinking",
- name: "Qwen: Qwen Plus 0728 (thinking)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.26,
- output: 0.78,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen-turbo": {
- id: "qwen/qwen-turbo",
- name: "Qwen: Qwen-Turbo",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.0325,
- output: 0.13,
- cacheRead: 0.006500000000000001,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "qwen/qwen-vl-max": {
- id: "qwen/qwen-vl-max",
- name: "Qwen: Qwen VL Max",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.52,
- output: 2.08,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-14b": {
- id: "qwen/qwen3-14b",
- name: "Qwen: Qwen3 14B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.06,
- output: 0.24,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 40960,
- maxTokens: 40960,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-235b-a22b": {
- id: "qwen/qwen3-235b-a22b",
- name: "Qwen: Qwen3 235B A22B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.45499999999999996,
- output: 1.8199999999999998,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-235b-a22b-2507": {
- id: "qwen/qwen3-235b-a22b-2507",
- name: "Qwen: Qwen3 235B A22B Instruct 2507",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.071,
- output: 0.09999999999999999,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-235b-a22b-thinking-2507": {
- id: "qwen/qwen3-235b-a22b-thinking-2507",
- name: "Qwen: Qwen3 235B A22B Thinking 2507",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.14950000000000002,
- output: 1.495,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-30b-a3b": {
- id: "qwen/qwen3-30b-a3b",
- name: "Qwen: Qwen3 30B A3B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.08,
- output: 0.28,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 40960,
- maxTokens: 40960,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-30b-a3b-instruct-2507": {
- id: "qwen/qwen3-30b-a3b-instruct-2507",
- name: "Qwen: Qwen3 30B A3B Instruct 2507",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.09,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-30b-a3b-thinking-2507": {
- id: "qwen/qwen3-30b-a3b-thinking-2507",
- name: "Qwen: Qwen3 30B A3B Thinking 2507",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.08,
- output: 0.39999999999999997,
- cacheRead: 0.08,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-32b": {
- id: "qwen/qwen3-32b",
- name: "Qwen: Qwen3 32B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.08,
- output: 0.24,
- cacheRead: 0.04,
- cacheWrite: 0,
- },
- contextWindow: 40960,
- maxTokens: 40960,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-8b": {
- id: "qwen/qwen3-8b",
- name: "Qwen: Qwen3 8B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.049999999999999996,
- output: 0.39999999999999997,
- cacheRead: 0.049999999999999996,
- cacheWrite: 0,
- },
- contextWindow: 40960,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-coder": {
- id: "qwen/qwen3-coder",
- name: "Qwen: Qwen3 Coder 480B A35B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.22,
- output: 1,
- cacheRead: 0.022,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-coder-30b-a3b-instruct": {
- id: "qwen/qwen3-coder-30b-a3b-instruct",
- name: "Qwen: Qwen3 Coder 30B A3B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.07,
- output: 0.27,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 160000,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-coder-flash": {
- id: "qwen/qwen3-coder-flash",
- name: "Qwen: Qwen3 Coder Flash",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.195,
- output: 0.975,
- cacheRead: 0.039,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-coder-next": {
- id: "qwen/qwen3-coder-next",
- name: "Qwen: Qwen3 Coder Next",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.7999999999999999,
- cacheRead: 0.12,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 262144,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-coder-plus": {
- id: "qwen/qwen3-coder-plus",
- name: "Qwen: Qwen3 Coder Plus",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.65,
- output: 3.25,
- cacheRead: 0.13,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-coder:free": {
- id: "qwen/qwen3-coder:free",
- name: "Qwen: Qwen3 Coder 480B A35B (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262000,
- maxTokens: 262000,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-max": {
- id: "qwen/qwen3-max",
- name: "Qwen: Qwen3 Max",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.78,
- output: 3.9,
- cacheRead: 0.156,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-max-thinking": {
- id: "qwen/qwen3-max-thinking",
- name: "Qwen: Qwen3 Max Thinking",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.78,
- output: 3.9,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-next-80b-a3b-instruct": {
- id: "qwen/qwen3-next-80b-a3b-instruct",
- name: "Qwen: Qwen3 Next 80B A3B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.09,
- output: 1.1,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-next-80b-a3b-instruct:free": {
- id: "qwen/qwen3-next-80b-a3b-instruct:free",
- name: "Qwen: Qwen3 Next 80B A3B Instruct (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-next-80b-a3b-thinking": {
- id: "qwen/qwen3-next-80b-a3b-thinking",
- name: "Qwen: Qwen3 Next 80B A3B Thinking",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.0975,
- output: 0.78,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-vl-235b-a22b-instruct": {
- id: "qwen/qwen3-vl-235b-a22b-instruct",
- name: "Qwen: Qwen3 VL 235B A22B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.19999999999999998,
- output: 0.88,
- cacheRead: 0.11,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-vl-235b-a22b-thinking": {
- id: "qwen/qwen3-vl-235b-a22b-thinking",
- name: "Qwen: Qwen3 VL 235B A22B Thinking",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.26,
- output: 2.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-vl-30b-a3b-instruct": {
- id: "qwen/qwen3-vl-30b-a3b-instruct",
- name: "Qwen: Qwen3 VL 30B A3B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.13,
- output: 0.52,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-vl-30b-a3b-thinking": {
- id: "qwen/qwen3-vl-30b-a3b-thinking",
- name: "Qwen: Qwen3 VL 30B A3B Thinking",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.13,
- output: 1.56,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-vl-32b-instruct": {
- id: "qwen/qwen3-vl-32b-instruct",
- name: "Qwen: Qwen3 VL 32B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.10400000000000001,
- output: 0.41600000000000004,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-vl-8b-instruct": {
- id: "qwen/qwen3-vl-8b-instruct",
- name: "Qwen: Qwen3 VL 8B Instruct",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.08,
- output: 0.5,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3-vl-8b-thinking": {
- id: "qwen/qwen3-vl-8b-thinking",
- name: "Qwen: Qwen3 VL 8B Thinking",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.117,
- output: 1.365,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3.5-122b-a10b": {
- id: "qwen/qwen3.5-122b-a10b",
- name: "Qwen: Qwen3.5-122B-A10B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.26,
- output: 2.08,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3.5-27b": {
- id: "qwen/qwen3.5-27b",
- name: "Qwen: Qwen3.5-27B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.195,
- output: 1.56,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3.5-35b-a3b": {
- id: "qwen/qwen3.5-35b-a3b",
- name: "Qwen: Qwen3.5-35B-A3B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.1625,
- output: 1.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3.5-397b-a17b": {
- id: "qwen/qwen3.5-397b-a17b",
- name: "Qwen: Qwen3.5 397B A17B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.39,
- output: 2.34,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3.5-9b": {
- id: "qwen/qwen3.5-9b",
- name: "Qwen: Qwen3.5-9B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.049999999999999996,
- output: 0.15,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3.5-flash-02-23": {
- id: "qwen/qwen3.5-flash-02-23",
- name: "Qwen: Qwen3.5-Flash",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.065,
- output: 0.26,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3.5-plus-02-15": {
- id: "qwen/qwen3.5-plus-02-15",
- name: "Qwen: Qwen3.5 Plus 2026-02-15",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.26,
- output: 1.56,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "qwen/qwen3.6-plus": {
- id: "qwen/qwen3.6-plus",
- name: "Qwen: Qwen3.6 Plus",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.325,
- output: 1.95,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "qwen/qwq-32b": {
- id: "qwen/qwq-32b",
- name: "Qwen: QwQ 32B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.58,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "rekaai/reka-edge": {
- id: "rekaai/reka-edge",
- name: "Reka Edge",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.09999999999999999,
- output: 0.09999999999999999,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 16384,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "relace/relace-search": {
- id: "relace/relace-search",
- name: "Relace: Relace Search",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1,
- output: 3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 128000,
- } satisfies Model<"openai-completions">,
- "sao10k/l3-euryale-70b": {
- id: "sao10k/l3-euryale-70b",
- name: "Sao10k: Llama 3 Euryale 70B v2.1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1.48,
- output: 1.48,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 8192,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "sao10k/l3.1-euryale-70b": {
- id: "sao10k/l3.1-euryale-70b",
- name: "Sao10K: Llama 3.1 Euryale 70B v2.2",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.85,
- output: 0.85,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "stepfun/step-3.5-flash": {
- id: "stepfun/step-3.5-flash",
- name: "StepFun: Step 3.5 Flash",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.09999999999999999,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "thedrummer/rocinante-12b": {
- id: "thedrummer/rocinante-12b",
- name: "TheDrummer: Rocinante 12B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.16999999999999998,
- output: 0.43,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32768,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "thedrummer/unslopnemo-12b": {
- id: "thedrummer/unslopnemo-12b",
- name: "TheDrummer: UnslopNemo 12B",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.39999999999999997,
- output: 0.39999999999999997,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32768,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "tngtech/deepseek-r1t2-chimera": {
- id: "tngtech/deepseek-r1t2-chimera",
- name: "TNG: DeepSeek R1T2 Chimera",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.1,
- cacheRead: 0.15,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 163840,
- } satisfies Model<"openai-completions">,
- "upstage/solar-pro-3": {
- id: "upstage/solar-pro-3",
- name: "Upstage: Solar Pro 3",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0.015,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "x-ai/grok-3": {
- id: "x-ai/grok-3",
- name: "xAI: Grok 3",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.75,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "x-ai/grok-3-beta": {
- id: "x-ai/grok-3-beta",
- name: "xAI: Grok 3 Beta",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.75,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "x-ai/grok-3-mini": {
- id: "x-ai/grok-3-mini",
- name: "xAI: Grok 3 Mini",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 0.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "x-ai/grok-3-mini-beta": {
- id: "x-ai/grok-3-mini-beta",
- name: "xAI: Grok 3 Mini Beta",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 0.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "x-ai/grok-4": {
- id: "x-ai/grok-4",
- name: "xAI: Grok 4",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.75,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "x-ai/grok-4-fast": {
- id: "x-ai/grok-4-fast",
- name: "xAI: Grok 4 Fast",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.19999999999999998,
- output: 0.5,
- cacheRead: 0.049999999999999996,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 30000,
- } satisfies Model<"openai-completions">,
- "x-ai/grok-4.1-fast": {
- id: "x-ai/grok-4.1-fast",
- name: "xAI: Grok 4.1 Fast",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.19999999999999998,
- output: 0.5,
- cacheRead: 0.049999999999999996,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 30000,
- } satisfies Model<"openai-completions">,
- "x-ai/grok-4.20": {
- id: "x-ai/grok-4.20",
- name: "xAI: Grok 4.20",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "x-ai/grok-code-fast-1": {
- id: "x-ai/grok-code-fast-1",
- name: "xAI: Grok Code Fast 1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.19999999999999998,
- output: 1.5,
- cacheRead: 0.02,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 10000,
- } satisfies Model<"openai-completions">,
- "xiaomi/mimo-v2-flash": {
- id: "xiaomi/mimo-v2-flash",
- name: "Xiaomi: MiMo-V2-Flash",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.09,
- output: 0.29,
- cacheRead: 0.045,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "xiaomi/mimo-v2-omni": {
- id: "xiaomi/mimo-v2-omni",
- name: "Xiaomi: MiMo-V2-Omni",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.39999999999999997,
- output: 2,
- cacheRead: 0.08,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"openai-completions">,
- "xiaomi/mimo-v2-pro": {
- id: "xiaomi/mimo-v2-pro",
- name: "Xiaomi: MiMo-V2-Pro",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1,
- output: 3,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-4-32b": {
- id: "z-ai/glm-4-32b",
- name: "Z.ai: GLM 4 32B ",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.09999999999999999,
- output: 0.09999999999999999,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-4.5": {
- id: "z-ai/glm-4.5",
- name: "Z.ai: GLM 4.5",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.2,
- cacheRead: 0.11,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 98304,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-4.5-air": {
- id: "z-ai/glm-4.5-air",
- name: "Z.ai: GLM 4.5 Air",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.13,
- output: 0.85,
- cacheRead: 0.024999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 98304,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-4.5-air:free": {
- id: "z-ai/glm-4.5-air:free",
- name: "Z.ai: GLM 4.5 Air (free)",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 96000,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-4.5v": {
- id: "z-ai/glm-4.5v",
- name: "Z.ai: GLM 4.5V",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.6,
- output: 1.7999999999999998,
- cacheRead: 0.11,
- cacheWrite: 0,
- },
- contextWindow: 65536,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-4.6": {
- id: "z-ai/glm-4.6",
- name: "Z.ai: GLM 4.6",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.39,
- output: 1.9,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 204800,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-4.6v": {
- id: "z-ai/glm-4.6v",
- name: "Z.ai: GLM 4.6V",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.3,
- output: 0.8999999999999999,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-4.7": {
- id: "z-ai/glm-4.7",
- name: "Z.ai: GLM 4.7",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.39,
- output: 1.75,
- cacheRead: 0.195,
- cacheWrite: 0,
- },
- contextWindow: 202752,
- maxTokens: 65535,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-4.7-flash": {
- id: "z-ai/glm-4.7-flash",
- name: "Z.ai: GLM 4.7 Flash",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.06,
- output: 0.39999999999999997,
- cacheRead: 0.0100000002,
- cacheWrite: 0,
- },
- contextWindow: 202752,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-5": {
- id: "z-ai/glm-5",
- name: "Z.ai: GLM 5",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 1.9,
- cacheRead: 0.119,
- cacheWrite: 0,
- },
- contextWindow: 80000,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-5-turbo": {
- id: "z-ai/glm-5-turbo",
- name: "Z.ai: GLM 5 Turbo",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.2,
- output: 4,
- cacheRead: 0.24,
- cacheWrite: 0,
- },
- contextWindow: 202752,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-5.1": {
- id: "z-ai/glm-5.1",
- name: "Z.ai: GLM 5.1",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.95,
- output: 3.15,
- cacheRead: 0.475,
- cacheWrite: 0,
- },
- contextWindow: 202752,
- maxTokens: 65535,
- } satisfies Model<"openai-completions">,
- "z-ai/glm-5v-turbo": {
- id: "z-ai/glm-5v-turbo",
- name: "Z.ai: GLM 5V Turbo",
- api: "openai-completions",
- provider: "openrouter",
- baseUrl: "https://openrouter.ai/api/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.2,
- output: 4,
- cacheRead: 0.24,
- cacheWrite: 0,
- },
- contextWindow: 202752,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- },
- "vercel-ai-gateway": {
- "alibaba/qwen-3-14b": {
- id: "alibaba/qwen-3-14b",
- name: "Qwen3-14B",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.12,
- output: 0.24,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 40960,
- maxTokens: 16384,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen-3-235b": {
- id: "alibaba/qwen-3-235b",
- name: "Qwen3 235B A22b Instruct 2507",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 1.2,
- cacheRead: 0.6,
- cacheWrite: 0,
- },
- contextWindow: 131000,
- maxTokens: 40000,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen-3-30b": {
- id: "alibaba/qwen-3-30b",
- name: "Qwen3-30B-A3B",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.08,
- output: 0.29,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 40960,
- maxTokens: 16384,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen-3-32b": {
- id: "alibaba/qwen-3-32b",
- name: "Qwen 3 32B",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.16,
- output: 0.64,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen3-235b-a22b-thinking": {
- id: "alibaba/qwen3-235b-a22b-thinking",
- name: "Qwen3 235B A22B Thinking 2507",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.22999999999999998,
- output: 2.3,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 262114,
- maxTokens: 262114,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen3-coder": {
- id: "alibaba/qwen3-coder",
- name: "Qwen3 Coder 480B A35B Instruct",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1.5,
- output: 7.5,
- cacheRead: 0.3,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 65536,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen3-coder-30b-a3b": {
- id: "alibaba/qwen3-coder-30b-a3b",
- name: "Qwen 3 Coder 30B A3B Instruct",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen3-coder-next": {
- id: "alibaba/qwen3-coder-next",
- name: "Qwen3 Coder Next",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.5,
- output: 1.2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 256000,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen3-coder-plus": {
- id: "alibaba/qwen3-coder-plus",
- name: "Qwen3 Coder Plus",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1,
- output: 5,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 65536,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen3-max": {
- id: "alibaba/qwen3-max",
- name: "Qwen3 Max",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1.2,
- output: 6,
- cacheRead: 0.24,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32768,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen3-max-preview": {
- id: "alibaba/qwen3-max-preview",
- name: "Qwen3 Max Preview",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1.2,
- output: 6,
- cacheRead: 0.24,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32768,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen3-max-thinking": {
- id: "alibaba/qwen3-max-thinking",
- name: "Qwen 3 Max Thinking",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.2,
- output: 6,
- cacheRead: 0.24,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 65536,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen3-vl-thinking": {
- id: "alibaba/qwen3-vl-thinking",
- name: "Qwen3 VL 235B A22B Thinking",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.39999999999999997,
- output: 4,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 32768,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen3.5-flash": {
- id: "alibaba/qwen3.5-flash",
- name: "Qwen 3.5 Flash",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.09999999999999999,
- output: 0.39999999999999997,
- cacheRead: 0.001,
- cacheWrite: 0.125,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen3.5-plus": {
- id: "alibaba/qwen3.5-plus",
- name: "Qwen 3.5 Plus",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.39999999999999997,
- output: 2.4,
- cacheRead: 0.04,
- cacheWrite: 0.5,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "alibaba/qwen3.6-plus": {
- id: "alibaba/qwen3.6-plus",
- name: "Qwen 3.6 Plus",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 3,
- cacheRead: 0.09999999999999999,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "anthropic/claude-3-haiku": {
- id: "anthropic/claude-3-haiku",
- name: "Claude 3 Haiku",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 1.25,
- cacheRead: 0.03,
- cacheWrite: 0.3,
- },
- contextWindow: 200000,
- maxTokens: 4096,
- } satisfies Model<"anthropic-messages">,
- "anthropic/claude-3.5-haiku": {
- id: "anthropic/claude-3.5-haiku",
- name: "Claude 3.5 Haiku",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.7999999999999999,
- output: 4,
- cacheRead: 0.08,
- cacheWrite: 1,
- },
- contextWindow: 200000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "anthropic/claude-3.7-sonnet": {
- id: "anthropic/claude-3.7-sonnet",
- name: "Claude 3.7 Sonnet",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 200000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "anthropic/claude-haiku-4.5": {
- id: "anthropic/claude-haiku-4.5",
- name: "Claude Haiku 4.5",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1,
- output: 5,
- cacheRead: 0.09999999999999999,
- cacheWrite: 1.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "anthropic/claude-opus-4": {
- id: "anthropic/claude-opus-4",
- name: "Claude Opus 4",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "anthropic/claude-opus-4.1": {
- id: "anthropic/claude-opus-4.1",
- name: "Claude Opus 4.1",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 75,
- cacheRead: 1.5,
- cacheWrite: 18.75,
- },
- contextWindow: 200000,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "anthropic/claude-opus-4.5": {
- id: "anthropic/claude-opus-4.5",
- name: "Claude Opus 4.5",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 200000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "anthropic/claude-opus-4.6": {
- id: "anthropic/claude-opus-4.6",
- name: "Claude Opus 4.6",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "anthropic/claude-opus-4.7": {
- id: "anthropic/claude-opus-4.7",
- name: "Claude Opus 4.7",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 0.5,
- cacheWrite: 6.25,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "anthropic/claude-sonnet-4": {
- id: "anthropic/claude-sonnet-4",
- name: "Claude Sonnet 4",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "anthropic/claude-sonnet-4.5": {
- id: "anthropic/claude-sonnet-4.5",
- name: "Claude Sonnet 4.5",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "anthropic/claude-sonnet-4.6": {
- id: "anthropic/claude-sonnet-4.6",
- name: "Claude Sonnet 4.6",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.3,
- cacheWrite: 3.75,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "arcee-ai/trinity-large-preview": {
- id: "arcee-ai/trinity-large-preview",
- name: "Trinity Large Preview",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.25,
- output: 1,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131000,
- maxTokens: 131000,
- } satisfies Model<"anthropic-messages">,
- "arcee-ai/trinity-large-thinking": {
- id: "arcee-ai/trinity-large-thinking",
- name: "Trinity Large Thinking",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.25,
- output: 0.8999999999999999,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262100,
- maxTokens: 80000,
- } satisfies Model<"anthropic-messages">,
- "bytedance/seed-1.6": {
- id: "bytedance/seed-1.6",
- name: "Seed 1.6",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0.049999999999999996,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "cohere/command-a": {
- id: "cohere/command-a",
- name: "Command A",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 8000,
- } satisfies Model<"anthropic-messages">,
- "deepseek/deepseek-r1": {
- id: "deepseek/deepseek-r1",
- name: "DeepSeek-R1",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.35,
- output: 5.4,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "deepseek/deepseek-v3": {
- id: "deepseek/deepseek-v3",
- name: "DeepSeek V3 0324",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.77,
- output: 0.77,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 16384,
- } satisfies Model<"anthropic-messages">,
- "deepseek/deepseek-v3.1": {
- id: "deepseek/deepseek-v3.1",
- name: "DeepSeek-V3.1",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.56,
- output: 1.68,
- cacheRead: 0.28,
- cacheWrite: 0,
- },
- contextWindow: 163840,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "deepseek/deepseek-v3.1-terminus": {
- id: "deepseek/deepseek-v3.1-terminus",
- name: "DeepSeek V3.1 Terminus",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.27,
- output: 1,
- cacheRead: 0.135,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 65536,
- } satisfies Model<"anthropic-messages">,
- "deepseek/deepseek-v3.2": {
- id: "deepseek/deepseek-v3.2",
- name: "DeepSeek V3.2",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.28,
- output: 0.42,
- cacheRead: 0.028,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8000,
- } satisfies Model<"anthropic-messages">,
- "deepseek/deepseek-v3.2-thinking": {
- id: "deepseek/deepseek-v3.2-thinking",
- name: "DeepSeek V3.2 Thinking",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.28,
- output: 0.42,
- cacheRead: 0.028,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "google/gemini-2.0-flash": {
- id: "google/gemini-2.0-flash",
- name: "Gemini 2.0 Flash",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0.024999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "google/gemini-2.0-flash-lite": {
- id: "google/gemini-2.0-flash-lite",
- name: "Gemini 2.0 Flash Lite",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.075,
- output: 0.3,
- cacheRead: 0.02,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "google/gemini-2.5-flash": {
- id: "google/gemini-2.5-flash",
- name: "Gemini 2.5 Flash",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.3,
- output: 2.5,
- cacheRead: 0.03,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 65536,
- } satisfies Model<"anthropic-messages">,
- "google/gemini-2.5-flash-lite": {
- id: "google/gemini-2.5-flash-lite",
- name: "Gemini 2.5 Flash Lite",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.09999999999999999,
- output: 0.39999999999999997,
- cacheRead: 0.01,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"anthropic-messages">,
- "google/gemini-2.5-pro": {
- id: "google/gemini-2.5-pro",
- name: "Gemini 2.5 Pro",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 1048576,
- maxTokens: 65536,
- } satisfies Model<"anthropic-messages">,
- "google/gemini-3-flash": {
- id: "google/gemini-3-flash",
- name: "Gemini 3 Flash",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.5,
- output: 3,
- cacheRead: 0.049999999999999996,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 65000,
- } satisfies Model<"anthropic-messages">,
- "google/gemini-3-pro-preview": {
- id: "google/gemini-3-pro-preview",
- name: "Gemini 3 Pro Preview",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "google/gemini-3.1-flash-lite-preview": {
- id: "google/gemini-3.1-flash-lite-preview",
- name: "Gemini 3.1 Flash Lite Preview",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 1.5,
- cacheRead: 0.03,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 65000,
- } satisfies Model<"anthropic-messages">,
- "google/gemini-3.1-pro-preview": {
- id: "google/gemini-3.1-pro-preview",
- name: "Gemini 3.1 Pro Preview",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 12,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "google/gemma-4-26b-a4b-it": {
- id: "google/gemma-4-26b-a4b-it",
- name: "Gemma 4 26B A4B IT",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.13,
- output: 0.39999999999999997,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "google/gemma-4-31b-it": {
- id: "google/gemma-4-31b-it",
- name: "Gemma 4 31B IT",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.14,
- output: 0.39999999999999997,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "inception/mercury-2": {
- id: "inception/mercury-2",
- name: "Mercury 2",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.25,
- output: 0.75,
- cacheRead: 0.024999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "inception/mercury-coder-small": {
- id: "inception/mercury-coder-small",
- name: "Mercury Coder Small Beta",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.25,
- output: 1,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32000,
- maxTokens: 16384,
- } satisfies Model<"anthropic-messages">,
- "kwaipilot/kat-coder-pro-v2": {
- id: "kwaipilot/kat-coder-pro-v2",
- name: "Kat Coder Pro V2",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.06,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 256000,
- } satisfies Model<"anthropic-messages">,
- "meituan/longcat-flash-chat": {
- id: "meituan/longcat-flash-chat",
- name: "LongCat Flash Chat",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 100000,
- } satisfies Model<"anthropic-messages">,
- "meta/llama-3.1-70b": {
- id: "meta/llama-3.1-70b",
- name: "Llama 3.1 70B Instruct",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.72,
- output: 0.72,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "meta/llama-3.1-8b": {
- id: "meta/llama-3.1-8b",
- name: "Llama 3.1 8B Instruct",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.22,
- output: 0.22,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "meta/llama-3.2-11b": {
- id: "meta/llama-3.2-11b",
- name: "Llama 3.2 11B Vision Instruct",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.16,
- output: 0.16,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "meta/llama-3.2-90b": {
- id: "meta/llama-3.2-90b",
- name: "Llama 3.2 90B Vision Instruct",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.72,
- output: 0.72,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "meta/llama-3.3-70b": {
- id: "meta/llama-3.3-70b",
- name: "Llama 3.3 70B Instruct",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.72,
- output: 0.72,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "meta/llama-4-maverick": {
- id: "meta/llama-4-maverick",
- name: "Llama 4 Maverick 17B Instruct",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.24,
- output: 0.9700000000000001,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "meta/llama-4-scout": {
- id: "meta/llama-4-scout",
- name: "Llama 4 Scout 17B Instruct",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.16999999999999998,
- output: 0.66,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "minimax/minimax-m2": {
- id: "minimax/minimax-m2",
- name: "MiniMax M2",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.03,
- cacheWrite: 0.375,
- },
- contextWindow: 205000,
- maxTokens: 205000,
- } satisfies Model<"anthropic-messages">,
- "minimax/minimax-m2.1": {
- id: "minimax/minimax-m2.1",
- name: "MiniMax M2.1",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.03,
- cacheWrite: 0.375,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "minimax/minimax-m2.1-lightning": {
- id: "minimax/minimax-m2.1-lightning",
- name: "MiniMax M2.1 Lightning",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 2.4,
- cacheRead: 0.03,
- cacheWrite: 0.375,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "minimax/minimax-m2.5": {
- id: "minimax/minimax-m2.5",
- name: "MiniMax M2.5",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.03,
- cacheWrite: 0.375,
- },
- contextWindow: 204800,
- maxTokens: 131000,
- } satisfies Model<"anthropic-messages">,
- "minimax/minimax-m2.5-highspeed": {
- id: "minimax/minimax-m2.5-highspeed",
- name: "MiniMax M2.5 High Speed",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.4,
- cacheRead: 0.03,
- cacheWrite: 0.375,
- },
- contextWindow: 204800,
- maxTokens: 131000,
- } satisfies Model<"anthropic-messages">,
- "minimax/minimax-m2.7": {
- id: "minimax/minimax-m2.7",
- name: "Minimax M2.7",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.3,
- output: 1.2,
- cacheRead: 0.06,
- cacheWrite: 0.375,
- },
- contextWindow: 204800,
- maxTokens: 131000,
- } satisfies Model<"anthropic-messages">,
- "minimax/minimax-m2.7-highspeed": {
- id: "minimax/minimax-m2.7-highspeed",
- name: "MiniMax M2.7 High Speed",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.6,
- output: 2.4,
- cacheRead: 0.06,
- cacheWrite: 0.375,
- },
- contextWindow: 204800,
- maxTokens: 131100,
- } satisfies Model<"anthropic-messages">,
- "mistral/codestral": {
- id: "mistral/codestral",
- name: "Mistral Codestral",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 0.8999999999999999,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4000,
- } satisfies Model<"anthropic-messages">,
- "mistral/devstral-2": {
- id: "mistral/devstral-2",
- name: "Devstral 2",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.39999999999999997,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 256000,
- } satisfies Model<"anthropic-messages">,
- "mistral/devstral-small": {
- id: "mistral/devstral-small",
- name: "Devstral Small 1.1",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.09999999999999999,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "mistral/devstral-small-2": {
- id: "mistral/devstral-small-2",
- name: "Devstral Small 2",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.09999999999999999,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 256000,
- } satisfies Model<"anthropic-messages">,
- "mistral/ministral-3b": {
- id: "mistral/ministral-3b",
- name: "Ministral 3B",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.09999999999999999,
- output: 0.09999999999999999,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4000,
- } satisfies Model<"anthropic-messages">,
- "mistral/ministral-8b": {
- id: "mistral/ministral-8b",
- name: "Ministral 8B",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.15,
- output: 0.15,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4000,
- } satisfies Model<"anthropic-messages">,
- "mistral/mistral-medium": {
- id: "mistral/mistral-medium",
- name: "Mistral Medium 3.1",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.39999999999999997,
- output: 2,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 64000,
- } satisfies Model<"anthropic-messages">,
- "mistral/mistral-small": {
- id: "mistral/mistral-small",
- name: "Mistral Small",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.09999999999999999,
- output: 0.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 32000,
- maxTokens: 4000,
- } satisfies Model<"anthropic-messages">,
- "mistral/pixtral-12b": {
- id: "mistral/pixtral-12b",
- name: "Pixtral 12B 2409",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.15,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4000,
- } satisfies Model<"anthropic-messages">,
- "mistral/pixtral-large": {
- id: "mistral/pixtral-large",
- name: "Pixtral Large",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4000,
- } satisfies Model<"anthropic-messages">,
- "moonshotai/kimi-k2": {
- id: "moonshotai/kimi-k2",
- name: "Kimi K2 Instruct",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.5700000000000001,
- output: 2.3,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "moonshotai/kimi-k2-0905": {
- id: "moonshotai/kimi-k2-0905",
- name: "Kimi K2 0905",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.5,
- cacheRead: 0.3,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "moonshotai/kimi-k2-thinking": {
- id: "moonshotai/kimi-k2-thinking",
- name: "Kimi K2 Thinking",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.5,
- cacheRead: 0.15,
- cacheWrite: 0,
- },
- contextWindow: 262114,
- maxTokens: 262114,
- } satisfies Model<"anthropic-messages">,
- "moonshotai/kimi-k2-thinking-turbo": {
- id: "moonshotai/kimi-k2-thinking-turbo",
- name: "Kimi K2 Thinking Turbo",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.15,
- output: 8,
- cacheRead: 0.15,
- cacheWrite: 0,
- },
- contextWindow: 262114,
- maxTokens: 262114,
- } satisfies Model<"anthropic-messages">,
- "moonshotai/kimi-k2-turbo": {
- id: "moonshotai/kimi-k2-turbo",
- name: "Kimi K2 Turbo",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 1.15,
- output: 8,
- cacheRead: 0.15,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 16384,
- } satisfies Model<"anthropic-messages">,
- "moonshotai/kimi-k2.5": {
- id: "moonshotai/kimi-k2.5",
- name: "Kimi K2.5",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.6,
- output: 3,
- cacheRead: 0.09999999999999999,
- cacheWrite: 0,
- },
- contextWindow: 262114,
- maxTokens: 262114,
- } satisfies Model<"anthropic-messages">,
- "nvidia/nemotron-nano-12b-v2-vl": {
- id: "nvidia/nemotron-nano-12b-v2-vl",
- name: "Nvidia Nemotron Nano 12B V2 VL",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.19999999999999998,
- output: 0.6,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "nvidia/nemotron-nano-9b-v2": {
- id: "nvidia/nemotron-nano-9b-v2",
- name: "Nvidia Nemotron Nano 9B V2",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.06,
- output: 0.22999999999999998,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-4-turbo": {
- id: "openai/gpt-4-turbo",
- name: "GPT-4 Turbo",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 10,
- output: 30,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 4096,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-4.1": {
- id: "openai/gpt-4.1",
- name: "GPT-4.1",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 8,
- cacheRead: 0.5,
- cacheWrite: 0,
- },
- contextWindow: 1047576,
- maxTokens: 32768,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-4.1-mini": {
- id: "openai/gpt-4.1-mini",
- name: "GPT-4.1 mini",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.39999999999999997,
- output: 1.5999999999999999,
- cacheRead: 0.09999999999999999,
- cacheWrite: 0,
- },
- contextWindow: 1047576,
- maxTokens: 32768,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-4.1-nano": {
- id: "openai/gpt-4.1-nano",
- name: "GPT-4.1 nano",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.09999999999999999,
- output: 0.39999999999999997,
- cacheRead: 0.024999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 1047576,
- maxTokens: 32768,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-4o": {
- id: "openai/gpt-4o",
- name: "GPT-4o",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 10,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-4o-mini": {
- id: "openai/gpt-4o-mini",
- name: "GPT-4o mini",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.15,
- output: 0.6,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5": {
- id: "openai/gpt-5",
- name: "GPT-5",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5-chat": {
- id: "openai/gpt-5-chat",
- name: "GPT 5 Chat",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5-codex": {
- id: "openai/gpt-5-codex",
- name: "GPT-5-Codex",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5-mini": {
- id: "openai/gpt-5-mini",
- name: "GPT-5 mini",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0.024999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5-nano": {
- id: "openai/gpt-5-nano",
- name: "GPT-5 nano",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.049999999999999996,
- output: 0.39999999999999997,
- cacheRead: 0.005,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5-pro": {
- id: "openai/gpt-5-pro",
- name: "GPT-5 pro",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 120,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 272000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.1-codex": {
- id: "openai/gpt-5.1-codex",
- name: "GPT-5.1-Codex",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.1-codex-max": {
- id: "openai/gpt-5.1-codex-max",
- name: "GPT 5.1 Codex Max",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.1-codex-mini": {
- id: "openai/gpt-5.1-codex-mini",
- name: "GPT 5.1 Codex Mini",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.25,
- output: 2,
- cacheRead: 0.024999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.1-instant": {
- id: "openai/gpt-5.1-instant",
- name: "GPT-5.1 Instant",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.1-thinking": {
- id: "openai/gpt-5.1-thinking",
- name: "GPT 5.1 Thinking",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.25,
- output: 10,
- cacheRead: 0.125,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.2": {
- id: "openai/gpt-5.2",
- name: "GPT 5.2",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.2-chat": {
- id: "openai/gpt-5.2-chat",
- name: "GPT 5.2 Chat",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.2-codex": {
- id: "openai/gpt-5.2-codex",
- name: "GPT 5.2 Codex",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.2-pro": {
- id: "openai/gpt-5.2-pro",
- name: "GPT 5.2 ",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 21,
- output: 168,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.3-chat": {
- id: "openai/gpt-5.3-chat",
- name: "GPT-5.3 Chat",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 16384,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.3-codex": {
- id: "openai/gpt-5.3-codex",
- name: "GPT 5.3 Codex",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.75,
- output: 14,
- cacheRead: 0.175,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.4": {
- id: "openai/gpt-5.4",
- name: "GPT 5.4",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2.5,
- output: 15,
- cacheRead: 0.25,
- cacheWrite: 0,
- },
- contextWindow: 1050000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.4-mini": {
- id: "openai/gpt-5.4-mini",
- name: "GPT 5.4 Mini",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.75,
- output: 4.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.4-nano": {
- id: "openai/gpt-5.4-nano",
- name: "GPT 5.4 Nano",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.19999999999999998,
- output: 1.25,
- cacheRead: 0.02,
- cacheWrite: 0,
- },
- contextWindow: 400000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-5.4-pro": {
- id: "openai/gpt-5.4-pro",
- name: "GPT 5.4 Pro",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 30,
- output: 180,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 1050000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-oss-20b": {
- id: "openai/gpt-oss-20b",
- name: "gpt-oss-20b",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.049999999999999996,
- output: 0.19999999999999998,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"anthropic-messages">,
- "openai/gpt-oss-safeguard-20b": {
- id: "openai/gpt-oss-safeguard-20b",
- name: "gpt-oss-safeguard-20b",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.075,
- output: 0.3,
- cacheRead: 0.037,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 65536,
- } satisfies Model<"anthropic-messages">,
- "openai/o1": {
- id: "openai/o1",
- name: "o1",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 15,
- output: 60,
- cacheRead: 7.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"anthropic-messages">,
- "openai/o3": {
- id: "openai/o3",
- name: "o3",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 8,
- cacheRead: 0.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"anthropic-messages">,
- "openai/o3-deep-research": {
- id: "openai/o3-deep-research",
- name: "o3-deep-research",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 10,
- output: 40,
- cacheRead: 2.5,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"anthropic-messages">,
- "openai/o3-mini": {
- id: "openai/o3-mini",
- name: "o3-mini",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.1,
- output: 4.4,
- cacheRead: 0.55,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"anthropic-messages">,
- "openai/o3-pro": {
- id: "openai/o3-pro",
- name: "o3 Pro",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 20,
- output: 80,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"anthropic-messages">,
- "openai/o4-mini": {
- id: "openai/o4-mini",
- name: "o4-mini",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.1,
- output: 4.4,
- cacheRead: 0.275,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 100000,
- } satisfies Model<"anthropic-messages">,
- "perplexity/sonar": {
- id: "perplexity/sonar",
- name: "Sonar",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 127000,
- maxTokens: 8000,
- } satisfies Model<"anthropic-messages">,
- "perplexity/sonar-pro": {
- id: "perplexity/sonar-pro",
- name: "Sonar Pro",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 8000,
- } satisfies Model<"anthropic-messages">,
- "prime-intellect/intellect-3": {
- id: "prime-intellect/intellect-3",
- name: "INTELLECT 3",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.19999999999999998,
- output: 1.1,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-3": {
- id: "xai/grok-3",
- name: "Grok 3 Beta",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.75,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-3-fast": {
- id: "xai/grok-3-fast",
- name: "Grok 3 Fast Beta",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-3-mini": {
- id: "xai/grok-3-mini",
- name: "Grok 3 Mini Beta",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 0.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-3-mini-fast": {
- id: "xai/grok-3-mini-fast",
- name: "Grok 3 Mini Fast Beta",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 4,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 131072,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-4": {
- id: "xai/grok-4",
- name: "Grok 4",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.75,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 256000,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-4-fast-non-reasoning": {
- id: "xai/grok-4-fast-non-reasoning",
- name: "Grok 4 Fast Non-Reasoning",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.19999999999999998,
- output: 0.5,
- cacheRead: 0.049999999999999996,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 256000,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-4-fast-reasoning": {
- id: "xai/grok-4-fast-reasoning",
- name: "Grok 4 Fast Reasoning",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.19999999999999998,
- output: 0.5,
- cacheRead: 0.049999999999999996,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 256000,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-4.1-fast-non-reasoning": {
- id: "xai/grok-4.1-fast-non-reasoning",
- name: "Grok 4.1 Fast Non-Reasoning",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 0.19999999999999998,
- output: 0.5,
- cacheRead: 0.049999999999999996,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 30000,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-4.1-fast-reasoning": {
- id: "xai/grok-4.1-fast-reasoning",
- name: "Grok 4.1 Fast Reasoning",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.19999999999999998,
- output: 0.5,
- cacheRead: 0.049999999999999996,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 30000,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-4.20-multi-agent": {
- id: "xai/grok-4.20-multi-agent",
- name: "Grok 4.20 Multi-Agent",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 2000000,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-4.20-multi-agent-beta": {
- id: "xai/grok-4.20-multi-agent-beta",
- name: "Grok 4.20 Multi Agent Beta",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 2000000,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-4.20-non-reasoning": {
- id: "xai/grok-4.20-non-reasoning",
- name: "Grok 4.20 Non-Reasoning",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 2000000,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-4.20-non-reasoning-beta": {
- id: "xai/grok-4.20-non-reasoning-beta",
- name: "Grok 4.20 Beta Non-Reasoning",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 2000000,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-4.20-reasoning": {
- id: "xai/grok-4.20-reasoning",
- name: "Grok 4.20 Reasoning",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 2000000,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-4.20-reasoning-beta": {
- id: "xai/grok-4.20-reasoning-beta",
- name: "Grok 4.20 Beta Reasoning",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 2000000,
- } satisfies Model<"anthropic-messages">,
- "xai/grok-code-fast-1": {
- id: "xai/grok-code-fast-1",
- name: "Grok Code Fast 1",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.19999999999999998,
- output: 1.5,
- cacheRead: 0.02,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 256000,
- } satisfies Model<"anthropic-messages">,
- "xiaomi/mimo-v2-flash": {
- id: "xiaomi/mimo-v2-flash",
- name: "MiMo V2 Flash",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.09,
- output: 0.29,
- cacheRead: 0.045,
- cacheWrite: 0,
- },
- contextWindow: 262144,
- maxTokens: 32000,
- } satisfies Model<"anthropic-messages">,
- "xiaomi/mimo-v2-pro": {
- id: "xiaomi/mimo-v2-pro",
- name: "MiMo V2 Pro",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1,
- output: 3,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 1000000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-4.5": {
- id: "zai/glm-4.5",
- name: "GLM-4.5",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.2,
- cacheRead: 0.11,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 96000,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-4.5-air": {
- id: "zai/glm-4.5-air",
- name: "GLM 4.5 Air",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.19999999999999998,
- output: 1.1,
- cacheRead: 0.03,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 96000,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-4.5v": {
- id: "zai/glm-4.5v",
- name: "GLM 4.5V",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.6,
- output: 1.7999999999999998,
- cacheRead: 0.11,
- cacheWrite: 0,
- },
- contextWindow: 66000,
- maxTokens: 16000,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-4.6": {
- id: "zai/glm-4.6",
- name: "GLM 4.6",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 2.2,
- cacheRead: 0.11,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 96000,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-4.6v": {
- id: "zai/glm-4.6v",
- name: "GLM-4.6V",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.3,
- output: 0.8999999999999999,
- cacheRead: 0.049999999999999996,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 24000,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-4.6v-flash": {
- id: "zai/glm-4.6v-flash",
- name: "GLM-4.6V-Flash",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 24000,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-4.7": {
- id: "zai/glm-4.7",
- name: "GLM 4.7",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 2.25,
- output: 2.75,
- cacheRead: 2.25,
- cacheWrite: 0,
- },
- contextWindow: 131000,
- maxTokens: 40000,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-4.7-flash": {
- id: "zai/glm-4.7-flash",
- name: "GLM 4.7 Flash",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.07,
- output: 0.39999999999999997,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 131000,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-4.7-flashx": {
- id: "zai/glm-4.7-flashx",
- name: "GLM 4.7 FlashX",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.06,
- output: 0.39999999999999997,
- cacheRead: 0.01,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-5": {
- id: "zai/glm-5",
- name: "GLM 5",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1,
- output: 3.1999999999999997,
- cacheRead: 0.19999999999999998,
- cacheWrite: 0,
- },
- contextWindow: 202800,
- maxTokens: 131100,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-5-turbo": {
- id: "zai/glm-5-turbo",
- name: "GLM 5 Turbo",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 1.2,
- output: 4,
- cacheRead: 0.24,
- cacheWrite: 0,
- },
- contextWindow: 202800,
- maxTokens: 131100,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-5.1": {
- id: "zai/glm-5.1",
- name: "GLM 5.1",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.4,
- output: 4.4,
- cacheRead: 0.26,
- cacheWrite: 0,
- },
- contextWindow: 202752,
- maxTokens: 202752,
- } satisfies Model<"anthropic-messages">,
- "zai/glm-5v-turbo": {
- id: "zai/glm-5v-turbo",
- name: "GLM 5V Turbo",
- api: "anthropic-messages",
- provider: "vercel-ai-gateway",
- baseUrl: "https://ai-gateway.vercel.sh",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 1.2,
- output: 4,
- cacheRead: 0.24,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 128000,
- } satisfies Model<"anthropic-messages">,
- },
- "xai": {
- "grok-2": {
- id: "grok-2",
- name: "Grok 2",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2,
- output: 10,
- cacheRead: 2,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "grok-2-1212": {
- id: "grok-2-1212",
- name: "Grok 2 (1212)",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2,
- output: 10,
- cacheRead: 2,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "grok-2-latest": {
- id: "grok-2-latest",
- name: "Grok 2 Latest",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 2,
- output: 10,
- cacheRead: 2,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "grok-2-vision": {
- id: "grok-2-vision",
- name: "Grok 2 Vision",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 10,
- cacheRead: 2,
- cacheWrite: 0,
- },
- contextWindow: 8192,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "grok-2-vision-1212": {
- id: "grok-2-vision-1212",
- name: "Grok 2 Vision (1212)",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 10,
- cacheRead: 2,
- cacheWrite: 0,
- },
- contextWindow: 8192,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "grok-2-vision-latest": {
- id: "grok-2-vision-latest",
- name: "Grok 2 Vision Latest",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 10,
- cacheRead: 2,
- cacheWrite: 0,
- },
- contextWindow: 8192,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "grok-3": {
- id: "grok-3",
- name: "Grok 3",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.75,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "grok-3-fast": {
- id: "grok-3-fast",
- name: "Grok 3 Fast",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "grok-3-fast-latest": {
- id: "grok-3-fast-latest",
- name: "Grok 3 Fast Latest",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 5,
- output: 25,
- cacheRead: 1.25,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "grok-3-latest": {
- id: "grok-3-latest",
- name: "Grok 3 Latest",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.75,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "grok-3-mini": {
- id: "grok-3-mini",
- name: "Grok 3 Mini",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 0.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "grok-3-mini-fast": {
- id: "grok-3-mini-fast",
- name: "Grok 3 Mini Fast",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 4,
- cacheRead: 0.15,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "grok-3-mini-fast-latest": {
- id: "grok-3-mini-fast-latest",
- name: "Grok 3 Mini Fast Latest",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.6,
- output: 4,
- cacheRead: 0.15,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "grok-3-mini-latest": {
- id: "grok-3-mini-latest",
- name: "Grok 3 Mini Latest",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.3,
- output: 0.5,
- cacheRead: 0.075,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 8192,
- } satisfies Model<"openai-completions">,
- "grok-4": {
- id: "grok-4",
- name: "Grok 4",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 3,
- output: 15,
- cacheRead: 0.75,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 64000,
- } satisfies Model<"openai-completions">,
- "grok-4-1-fast": {
- id: "grok-4-1-fast",
- name: "Grok 4.1 Fast",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.2,
- output: 0.5,
- cacheRead: 0.05,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 30000,
- } satisfies Model<"openai-completions">,
- "grok-4-1-fast-non-reasoning": {
- id: "grok-4-1-fast-non-reasoning",
- name: "Grok 4.1 Fast (Non-Reasoning)",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.2,
- output: 0.5,
- cacheRead: 0.05,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 30000,
- } satisfies Model<"openai-completions">,
- "grok-4-fast": {
- id: "grok-4-fast",
- name: "Grok 4 Fast",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0.2,
- output: 0.5,
- cacheRead: 0.05,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 30000,
- } satisfies Model<"openai-completions">,
- "grok-4-fast-non-reasoning": {
- id: "grok-4-fast-non-reasoning",
- name: "Grok 4 Fast (Non-Reasoning)",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 0.2,
- output: 0.5,
- cacheRead: 0.05,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 30000,
- } satisfies Model<"openai-completions">,
- "grok-4.20-0309-non-reasoning": {
- id: "grok-4.20-0309-non-reasoning",
- name: "Grok 4.20 (Non-Reasoning)",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 30000,
- } satisfies Model<"openai-completions">,
- "grok-4.20-0309-reasoning": {
- id: "grok-4.20-0309-reasoning",
- name: "Grok 4.20 (Reasoning)",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 2,
- output: 6,
- cacheRead: 0.2,
- cacheWrite: 0,
- },
- contextWindow: 2000000,
- maxTokens: 30000,
- } satisfies Model<"openai-completions">,
- "grok-beta": {
- id: "grok-beta",
- name: "Grok Beta",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text"],
- cost: {
- input: 5,
- output: 15,
- cacheRead: 5,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- "grok-code-fast-1": {
- id: "grok-code-fast-1",
- name: "Grok Code Fast 1",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.2,
- output: 1.5,
- cacheRead: 0.02,
- cacheWrite: 0,
- },
- contextWindow: 256000,
- maxTokens: 10000,
- } satisfies Model<"openai-completions">,
- "grok-vision-beta": {
- id: "grok-vision-beta",
- name: "Grok Vision Beta",
- api: "openai-completions",
- provider: "xai",
- baseUrl: "https://api.x.ai/v1",
- reasoning: false,
- input: ["text", "image"],
- cost: {
- input: 5,
- output: 15,
- cacheRead: 5,
- cacheWrite: 0,
- },
- contextWindow: 8192,
- maxTokens: 4096,
- } satisfies Model<"openai-completions">,
- },
- "zai": {
- "glm-4.5": {
- id: "glm-4.5",
- name: "GLM-4.5",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai"},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 98304,
- } satisfies Model<"openai-completions">,
- "glm-4.5-air": {
- id: "glm-4.5-air",
- name: "GLM-4.5-Air",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai"},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 98304,
- } satisfies Model<"openai-completions">,
- "glm-4.5-flash": {
- id: "glm-4.5-flash",
- name: "GLM-4.5-Flash",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai"},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 131072,
- maxTokens: 98304,
- } satisfies Model<"openai-completions">,
- "glm-4.5v": {
- id: "glm-4.5v",
- name: "GLM-4.5V",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai"},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 64000,
- maxTokens: 16384,
- } satisfies Model<"openai-completions">,
- "glm-4.6": {
- id: "glm-4.6",
- name: "GLM-4.6",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "glm-4.6v": {
- id: "glm-4.6v",
- name: "GLM-4.6V",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 128000,
- maxTokens: 32768,
- } satisfies Model<"openai-completions">,
- "glm-4.7": {
- id: "glm-4.7",
- name: "GLM-4.7",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "glm-4.7-flash": {
- id: "glm-4.7-flash",
- name: "GLM-4.7-Flash",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "glm-4.7-flashx": {
- id: "glm-4.7-flashx",
- name: "GLM-4.7-FlashX",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0.07,
- output: 0.4,
- cacheRead: 0.01,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "glm-5": {
- id: "glm-5",
- name: "GLM-5",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 204800,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "glm-5-turbo": {
- id: "glm-5-turbo",
- name: "GLM-5-Turbo",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "glm-5.1": {
- id: "glm-5.1",
- name: "GLM-5.1",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
- reasoning: true,
- input: ["text"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- "glm-5v-turbo": {
- id: "glm-5v-turbo",
- name: "glm-5v-turbo",
- api: "openai-completions",
- provider: "zai",
- baseUrl: "https://api.z.ai/api/coding/paas/v4",
- compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
- reasoning: true,
- input: ["text", "image"],
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- },
- contextWindow: 200000,
- maxTokens: 131072,
- } satisfies Model<"openai-completions">,
- },
-} as const;
diff --git a/pi-mono-reference/packages/ai/src/models.ts b/pi-mono-reference/packages/ai/src/models.ts
deleted file mode 100644
index 8944d07e..00000000
--- a/pi-mono-reference/packages/ai/src/models.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-import { MODELS } from "./models.generated.js";
-import type { Api, KnownProvider, Model, Usage } from "./types.js";
-
-const modelRegistry: Map>> = new Map();
-
-// Initialize registry from MODELS on module load
-for (const [provider, models] of Object.entries(MODELS)) {
- const providerModels = new Map>();
- for (const [id, model] of Object.entries(models)) {
- providerModels.set(id, model as Model);
- }
- modelRegistry.set(provider, providerModels);
-}
-
-type ModelApi<
- TProvider extends KnownProvider,
- TModelId extends keyof (typeof MODELS)[TProvider],
-> = (typeof MODELS)[TProvider][TModelId] extends { api: infer TApi } ? (TApi extends Api ? TApi : never) : never;
-
-export function getModel(
- provider: TProvider,
- modelId: TModelId,
-): Model> {
- const providerModels = modelRegistry.get(provider);
- return providerModels?.get(modelId as string) as Model>;
-}
-
-export function getProviders(): KnownProvider[] {
- return Array.from(modelRegistry.keys()) as KnownProvider[];
-}
-
-export function getModels(
- provider: TProvider,
-): Model>[] {
- const models = modelRegistry.get(provider);
- return models ? (Array.from(models.values()) as Model>[]) : [];
-}
-
-export function calculateCost(model: Model, usage: Usage): Usage["cost"] {
- usage.cost.input = (model.cost.input / 1000000) * usage.input;
- usage.cost.output = (model.cost.output / 1000000) * usage.output;
- usage.cost.cacheRead = (model.cost.cacheRead / 1000000) * usage.cacheRead;
- usage.cost.cacheWrite = (model.cost.cacheWrite / 1000000) * usage.cacheWrite;
- usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
- return usage.cost;
-}
-
-/**
- * Check if a model supports xhigh thinking level.
- *
- * Supported today:
- * - GPT-5.2 / GPT-5.3 / GPT-5.4 model families
- * - Opus 4.6+ models (xhigh maps to adaptive effort "max" on Anthropic-compatible providers)
- */
-export function supportsXhigh(model: Model): boolean {
- if (model.id.includes("gpt-5.2") || model.id.includes("gpt-5.3") || model.id.includes("gpt-5.4")) {
- return true;
- }
-
- if (
- model.id.includes("opus-4-6") ||
- model.id.includes("opus-4.6") ||
- model.id.includes("opus-4-7") ||
- model.id.includes("opus-4.7")
- ) {
- return true;
- }
-
- return false;
-}
-
-/**
- * Check if two models are equal by comparing both their id and provider.
- * Returns false if either model is null or undefined.
- */
-export function modelsAreEqual(
- a: Model | null | undefined,
- b: Model | null | undefined,
-): boolean {
- if (!a || !b) return false;
- return a.id === b.id && a.provider === b.provider;
-}
diff --git a/pi-mono-reference/packages/ai/src/oauth.ts b/pi-mono-reference/packages/ai/src/oauth.ts
deleted file mode 100644
index d768a0fe..00000000
--- a/pi-mono-reference/packages/ai/src/oauth.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./utils/oauth/index.js";
diff --git a/pi-mono-reference/packages/ai/src/providers/amazon-bedrock.ts b/pi-mono-reference/packages/ai/src/providers/amazon-bedrock.ts
deleted file mode 100644
index 00333f0c..00000000
--- a/pi-mono-reference/packages/ai/src/providers/amazon-bedrock.ts
+++ /dev/null
@@ -1,818 +0,0 @@
-import {
- BedrockRuntimeClient,
- type BedrockRuntimeClientConfig,
- BedrockRuntimeServiceException,
- StopReason as BedrockStopReason,
- type Tool as BedrockTool,
- CachePointType,
- CacheTTL,
- type ContentBlock,
- type ContentBlockDeltaEvent,
- type ContentBlockStartEvent,
- type ContentBlockStopEvent,
- ConversationRole,
- ConverseStreamCommand,
- type ConverseStreamMetadataEvent,
- ImageFormat,
- type Message,
- type SystemContentBlock,
- type ToolChoice,
- type ToolConfiguration,
- ToolResultStatus,
-} from "@aws-sdk/client-bedrock-runtime";
-
-import { calculateCost } from "../models.js";
-import type {
- Api,
- AssistantMessage,
- CacheRetention,
- Context,
- Model,
- SimpleStreamOptions,
- StopReason,
- StreamFunction,
- StreamOptions,
- TextContent,
- ThinkingBudgets,
- ThinkingContent,
- ThinkingLevel,
- Tool,
- ToolCall,
- ToolResultMessage,
-} from "../types.js";
-import { AssistantMessageEventStream } from "../utils/event-stream.js";
-import { parseStreamingJson } from "../utils/json-parse.js";
-import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
-import { adjustMaxTokensForThinking, buildBaseOptions, clampReasoning } from "./simple-options.js";
-import { transformMessages } from "./transform-messages.js";
-
-export interface BedrockOptions extends StreamOptions {
- region?: string;
- profile?: string;
- toolChoice?: "auto" | "any" | "none" | { type: "tool"; name: string };
- /* See https://docs.aws.amazon.com/bedrock/latest/userguide/inference-reasoning.html for supported models. */
- reasoning?: ThinkingLevel;
- /* Custom token budgets per thinking level. Overrides default budgets. */
- thinkingBudgets?: ThinkingBudgets;
- /* Only supported by Claude 4.x models, see https://docs.aws.amazon.com/bedrock/latest/userguide/claude-messages-extended-thinking.html#claude-messages-extended-thinking-tool-use-interleaved */
- interleavedThinking?: boolean;
- /** Key-value pairs attached to the inference request for cost allocation tagging.
- * Keys: max 64 chars, no `aws:` prefix. Values: max 256 chars. Max 50 pairs.
- * Tags appear in AWS Cost Explorer split cost allocation data.
- * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ConverseStream.html */
- requestMetadata?: Record;
-}
-
-type Block = (TextContent | ThinkingContent | ToolCall) & { index?: number; partialJson?: string };
-
-export const streamBedrock: StreamFunction<"bedrock-converse-stream", BedrockOptions> = (
- model: Model<"bedrock-converse-stream">,
- context: Context,
- options: BedrockOptions = {},
-): AssistantMessageEventStream => {
- const stream = new AssistantMessageEventStream();
-
- (async () => {
- const output: AssistantMessage = {
- role: "assistant",
- content: [],
- api: "bedrock-converse-stream" as Api,
- provider: model.provider,
- model: model.id,
- usage: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- stopReason: "stop",
- timestamp: Date.now(),
- };
-
- const blocks = output.content as Block[];
-
- const config: BedrockRuntimeClientConfig = {
- profile: options.profile,
- };
-
- // in Node.js/Bun environment only
- if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
- // Region resolution: explicit option > env vars > SDK default chain.
- // When AWS_PROFILE is set, we leave region undefined so the SDK can
- // resovle it from aws profile configs. Otherwise fall back to us-east-1.
- const explicitRegion = options.region || process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION;
- if (explicitRegion) {
- config.region = explicitRegion;
- } else if (!process.env.AWS_PROFILE) {
- config.region = "us-east-1";
- }
-
- // Support proxies that don't need authentication
- if (process.env.AWS_BEDROCK_SKIP_AUTH === "1") {
- config.credentials = {
- accessKeyId: "dummy-access-key",
- secretAccessKey: "dummy-secret-key",
- };
- }
-
- if (
- process.env.HTTP_PROXY ||
- process.env.HTTPS_PROXY ||
- process.env.NO_PROXY ||
- process.env.http_proxy ||
- process.env.https_proxy ||
- process.env.no_proxy
- ) {
- const nodeHttpHandler = await import("@smithy/node-http-handler");
- const proxyAgent = await import("proxy-agent");
-
- const agent = new proxyAgent.ProxyAgent();
-
- // Bedrock runtime uses NodeHttp2Handler by default since v3.798.0, which is based
- // on `http2` module and has no support for http agent.
- // Use NodeHttpHandler to support http agent.
- config.requestHandler = new nodeHttpHandler.NodeHttpHandler({
- httpAgent: agent,
- httpsAgent: agent,
- });
- } else if (process.env.AWS_BEDROCK_FORCE_HTTP1 === "1") {
- // Some custom endpoints require HTTP/1.1 instead of HTTP/2
- const nodeHttpHandler = await import("@smithy/node-http-handler");
- config.requestHandler = new nodeHttpHandler.NodeHttpHandler();
- }
- } else {
- // Non-Node environment (browser): fall back to us-east-1 since
- // there's no config file resolution available.
- config.region = options.region || "us-east-1";
- }
-
- try {
- const client = new BedrockRuntimeClient(config);
-
- const cacheRetention = resolveCacheRetention(options.cacheRetention);
- let commandInput = {
- modelId: model.id,
- messages: convertMessages(context, model, cacheRetention),
- system: buildSystemPrompt(context.systemPrompt, model, cacheRetention),
- inferenceConfig: { maxTokens: options.maxTokens, temperature: options.temperature },
- toolConfig: convertToolConfig(context.tools, options.toolChoice),
- additionalModelRequestFields: buildAdditionalModelRequestFields(model, options),
- ...(options.requestMetadata !== undefined && { requestMetadata: options.requestMetadata }),
- };
- const nextCommandInput = await options?.onPayload?.(commandInput, model);
- if (nextCommandInput !== undefined) {
- commandInput = nextCommandInput as typeof commandInput;
- }
- const command = new ConverseStreamCommand(commandInput);
-
- const response = await client.send(command, { abortSignal: options.signal });
-
- for await (const item of response.stream!) {
- if (item.messageStart) {
- if (item.messageStart.role !== ConversationRole.ASSISTANT) {
- throw new Error("Unexpected assistant message start but got user message start instead");
- }
- stream.push({ type: "start", partial: output });
- } else if (item.contentBlockStart) {
- handleContentBlockStart(item.contentBlockStart, blocks, output, stream);
- } else if (item.contentBlockDelta) {
- handleContentBlockDelta(item.contentBlockDelta, blocks, output, stream);
- } else if (item.contentBlockStop) {
- handleContentBlockStop(item.contentBlockStop, blocks, output, stream);
- } else if (item.messageStop) {
- output.stopReason = mapStopReason(item.messageStop.stopReason);
- } else if (item.metadata) {
- handleMetadata(item.metadata, model, output);
- } else if (item.internalServerException) {
- throw item.internalServerException;
- } else if (item.modelStreamErrorException) {
- throw item.modelStreamErrorException;
- } else if (item.validationException) {
- throw item.validationException;
- } else if (item.throttlingException) {
- throw item.throttlingException;
- } else if (item.serviceUnavailableException) {
- throw item.serviceUnavailableException;
- }
- }
-
- if (options.signal?.aborted) {
- throw new Error("Request was aborted");
- }
-
- if (output.stopReason === "error" || output.stopReason === "aborted") {
- throw new Error("An unknown error occurred");
- }
-
- stream.push({ type: "done", reason: output.stopReason, message: output });
- stream.end();
- } catch (error) {
- for (const block of output.content) {
- delete (block as Block).index;
- // partialJson is only a streaming scratch buffer; never persist it.
- delete (block as Block).partialJson;
- }
- output.stopReason = options.signal?.aborted ? "aborted" : "error";
- output.errorMessage = formatBedrockError(error);
- stream.push({ type: "error", reason: output.stopReason, error: output });
- stream.end();
- }
- })();
-
- return stream;
-};
-
-/**
- * Human-readable prefixes for Bedrock SDK exception names.
- * The downstream retry logic in agent-session matches patterns like
- * `server.?error` and `service.?unavailable`, so we preserve the legacy
- * prefix format rather than using the raw SDK exception name.
- */
-const BEDROCK_ERROR_PREFIXES: Record = {
- InternalServerException: "Internal server error",
- ModelStreamErrorException: "Model stream error",
- ValidationException: "Validation error",
- ThrottlingException: "Throttling error",
- ServiceUnavailableException: "Service unavailable",
-};
-
-/**
- * Format a Bedrock error with a human-readable prefix.
- * AWS SDK exceptions (both from `client.send()` and from stream event items)
- * extend BedrockRuntimeServiceException. We map the `.name` to a stable
- * human-readable prefix so downstream consumers (retry logic, context-overflow
- * detection) can distinguish error categories via simple string matching.
- */
-function formatBedrockError(error: unknown): string {
- const message = error instanceof Error ? error.message : JSON.stringify(error);
- if (error instanceof BedrockRuntimeServiceException) {
- const prefix = BEDROCK_ERROR_PREFIXES[error.name] ?? error.name;
- return `${prefix}: ${message}`;
- }
- return message;
-}
-
-export const streamSimpleBedrock: StreamFunction<"bedrock-converse-stream", SimpleStreamOptions> = (
- model: Model<"bedrock-converse-stream">,
- context: Context,
- options?: SimpleStreamOptions,
-): AssistantMessageEventStream => {
- const base = buildBaseOptions(model, options, undefined);
- if (!options?.reasoning) {
- return streamBedrock(model, context, { ...base, reasoning: undefined } satisfies BedrockOptions);
- }
-
- if (model.id.includes("anthropic.claude") || model.id.includes("anthropic/claude")) {
- if (supportsAdaptiveThinking(model.id)) {
- return streamBedrock(model, context, {
- ...base,
- reasoning: options.reasoning,
- thinkingBudgets: options.thinkingBudgets,
- } satisfies BedrockOptions);
- }
-
- const adjusted = adjustMaxTokensForThinking(
- base.maxTokens || 0,
- model.maxTokens,
- options.reasoning,
- options.thinkingBudgets,
- );
-
- return streamBedrock(model, context, {
- ...base,
- maxTokens: adjusted.maxTokens,
- reasoning: options.reasoning,
- thinkingBudgets: {
- ...(options.thinkingBudgets || {}),
- [clampReasoning(options.reasoning)!]: adjusted.thinkingBudget,
- },
- } satisfies BedrockOptions);
- }
-
- return streamBedrock(model, context, {
- ...base,
- reasoning: options.reasoning,
- thinkingBudgets: options.thinkingBudgets,
- } satisfies BedrockOptions);
-};
-
-function handleContentBlockStart(
- event: ContentBlockStartEvent,
- blocks: Block[],
- output: AssistantMessage,
- stream: AssistantMessageEventStream,
-): void {
- const index = event.contentBlockIndex!;
- const start = event.start;
-
- if (start?.toolUse) {
- const block: Block = {
- type: "toolCall",
- id: start.toolUse.toolUseId || "",
- name: start.toolUse.name || "",
- arguments: {},
- partialJson: "",
- index,
- };
- output.content.push(block);
- stream.push({ type: "toolcall_start", contentIndex: blocks.length - 1, partial: output });
- }
-}
-
-function handleContentBlockDelta(
- event: ContentBlockDeltaEvent,
- blocks: Block[],
- output: AssistantMessage,
- stream: AssistantMessageEventStream,
-): void {
- const contentBlockIndex = event.contentBlockIndex!;
- const delta = event.delta;
- let index = blocks.findIndex((b) => b.index === contentBlockIndex);
- let block = blocks[index];
-
- if (delta?.text !== undefined) {
- // If no text block exists yet, create one, as `handleContentBlockStart` is not sent for text blocks
- if (!block) {
- const newBlock: Block = { type: "text", text: "", index: contentBlockIndex };
- output.content.push(newBlock);
- index = blocks.length - 1;
- block = blocks[index];
- stream.push({ type: "text_start", contentIndex: index, partial: output });
- }
- if (block.type === "text") {
- block.text += delta.text;
- stream.push({ type: "text_delta", contentIndex: index, delta: delta.text, partial: output });
- }
- } else if (delta?.toolUse && block?.type === "toolCall") {
- block.partialJson = (block.partialJson || "") + (delta.toolUse.input || "");
- block.arguments = parseStreamingJson(block.partialJson);
- stream.push({ type: "toolcall_delta", contentIndex: index, delta: delta.toolUse.input || "", partial: output });
- } else if (delta?.reasoningContent) {
- let thinkingBlock = block;
- let thinkingIndex = index;
-
- if (!thinkingBlock) {
- const newBlock: Block = { type: "thinking", thinking: "", thinkingSignature: "", index: contentBlockIndex };
- output.content.push(newBlock);
- thinkingIndex = blocks.length - 1;
- thinkingBlock = blocks[thinkingIndex];
- stream.push({ type: "thinking_start", contentIndex: thinkingIndex, partial: output });
- }
-
- if (thinkingBlock?.type === "thinking") {
- if (delta.reasoningContent.text) {
- thinkingBlock.thinking += delta.reasoningContent.text;
- stream.push({
- type: "thinking_delta",
- contentIndex: thinkingIndex,
- delta: delta.reasoningContent.text,
- partial: output,
- });
- }
- if (delta.reasoningContent.signature) {
- thinkingBlock.thinkingSignature =
- (thinkingBlock.thinkingSignature || "") + delta.reasoningContent.signature;
- }
- }
- }
-}
-
-function handleMetadata(
- event: ConverseStreamMetadataEvent,
- model: Model<"bedrock-converse-stream">,
- output: AssistantMessage,
-): void {
- if (event.usage) {
- output.usage.input = event.usage.inputTokens || 0;
- output.usage.output = event.usage.outputTokens || 0;
- output.usage.cacheRead = event.usage.cacheReadInputTokens || 0;
- output.usage.cacheWrite = event.usage.cacheWriteInputTokens || 0;
- output.usage.totalTokens = event.usage.totalTokens || output.usage.input + output.usage.output;
- calculateCost(model, output.usage);
- }
-}
-
-function handleContentBlockStop(
- event: ContentBlockStopEvent,
- blocks: Block[],
- output: AssistantMessage,
- stream: AssistantMessageEventStream,
-): void {
- const index = blocks.findIndex((b) => b.index === event.contentBlockIndex);
- const block = blocks[index];
- if (!block) return;
- delete (block as Block).index;
-
- switch (block.type) {
- case "text":
- stream.push({ type: "text_end", contentIndex: index, content: block.text, partial: output });
- break;
- case "thinking":
- stream.push({ type: "thinking_end", contentIndex: index, content: block.thinking, partial: output });
- break;
- case "toolCall":
- block.arguments = parseStreamingJson(block.partialJson);
- // Finalize in-place and strip the scratch buffer so replay only
- // carries parsed arguments.
- delete (block as Block).partialJson;
- stream.push({ type: "toolcall_end", contentIndex: index, toolCall: block, partial: output });
- break;
- }
-}
-
-/**
- * Check if the model supports adaptive thinking (Opus 4.6+, Sonnet 4.6).
- */
-function supportsAdaptiveThinking(modelId: string): boolean {
- return (
- modelId.includes("opus-4-6") ||
- modelId.includes("opus-4.6") ||
- modelId.includes("opus-4-7") ||
- modelId.includes("opus-4.7") ||
- modelId.includes("sonnet-4-6") ||
- modelId.includes("sonnet-4.6")
- );
-}
-
-function mapThinkingLevelToEffort(
- level: SimpleStreamOptions["reasoning"],
- modelId: string,
-): "low" | "medium" | "high" | "xhigh" | "max" {
- switch (level) {
- case "minimal":
- case "low":
- return "low";
- case "medium":
- return "medium";
- case "high":
- return "high";
- case "xhigh":
- if (modelId.includes("opus-4-6") || modelId.includes("opus-4.6")) {
- return "max";
- }
- if (modelId.includes("opus-4-7") || modelId.includes("opus-4.7")) {
- return "xhigh";
- }
- return "high";
- default:
- return "high";
- }
-}
-
-/**
- * Resolve cache retention preference.
- * Defaults to "short" and uses PI_CACHE_RETENTION for backward compatibility.
- */
-function resolveCacheRetention(cacheRetention?: CacheRetention): CacheRetention {
- if (cacheRetention) {
- return cacheRetention;
- }
- if (typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long") {
- return "long";
- }
- return "short";
-}
-
-/**
- * Check if the model supports prompt caching.
- * Supported: Claude 3.5 Haiku, Claude 3.7 Sonnet, Claude 4.x models
- *
- * For base models and system-defined inference profiles the model ID / ARN
- * contains the model name, so we can decide locally.
- *
- * For application inference profiles (whose ARNs don't contain the model name),
- * set AWS_BEDROCK_FORCE_CACHE=1 to enable cache points. Amazon Nova models
- * have automatic caching and don't need explicit cache points.
- */
-function supportsPromptCaching(model: Model<"bedrock-converse-stream">): boolean {
- const id = model.id.toLowerCase();
- if (!id.includes("claude")) {
- // Application inference profiles don't contain the model name in the ARN.
- // Allow users to force cache points via environment variable.
- if (typeof process !== "undefined" && process.env.AWS_BEDROCK_FORCE_CACHE === "1") return true;
- return false;
- }
- // Claude 4.x models (opus-4, sonnet-4, haiku-4)
- if (id.includes("-4-") || id.includes("-4.")) return true;
- // Claude 3.7 Sonnet
- if (id.includes("claude-3-7-sonnet")) return true;
- // Claude 3.5 Haiku
- if (id.includes("claude-3-5-haiku")) return true;
- return false;
-}
-
-/**
- * Check if the model supports thinking signatures in reasoningContent.
- * Only Anthropic Claude models support the signature field.
- * Other models (OpenAI, Qwen, Minimax, Moonshot, etc.) reject it with:
- * "This model doesn't support the reasoningContent.reasoningText.signature field"
- */
-function supportsThinkingSignature(model: Model<"bedrock-converse-stream">): boolean {
- const id = model.id.toLowerCase();
- return id.includes("anthropic.claude") || id.includes("anthropic/claude");
-}
-
-function buildSystemPrompt(
- systemPrompt: string | undefined,
- model: Model<"bedrock-converse-stream">,
- cacheRetention: CacheRetention,
-): SystemContentBlock[] | undefined {
- if (!systemPrompt) return undefined;
-
- const blocks: SystemContentBlock[] = [{ text: sanitizeSurrogates(systemPrompt) }];
-
- // Add cache point for supported Claude models when caching is enabled
- if (cacheRetention !== "none" && supportsPromptCaching(model)) {
- blocks.push({
- cachePoint: { type: CachePointType.DEFAULT, ...(cacheRetention === "long" ? { ttl: CacheTTL.ONE_HOUR } : {}) },
- });
- }
-
- return blocks;
-}
-
-function normalizeToolCallId(id: string): string {
- const sanitized = id.replace(/[^a-zA-Z0-9_-]/g, "_");
- return sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized;
-}
-
-function convertMessages(
- context: Context,
- model: Model<"bedrock-converse-stream">,
- cacheRetention: CacheRetention,
-): Message[] {
- const result: Message[] = [];
- const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
-
- for (let i = 0; i < transformedMessages.length; i++) {
- const m = transformedMessages[i];
-
- switch (m.role) {
- case "user":
- result.push({
- role: ConversationRole.USER,
- content:
- typeof m.content === "string"
- ? [{ text: sanitizeSurrogates(m.content) }]
- : m.content.map((c) => {
- switch (c.type) {
- case "text":
- return { text: sanitizeSurrogates(c.text) };
- case "image":
- return { image: createImageBlock(c.mimeType, c.data) };
- default:
- throw new Error("Unknown user content type");
- }
- }),
- });
- break;
- case "assistant": {
- // Skip assistant messages with empty content (e.g., from aborted requests)
- // Bedrock rejects messages with empty content arrays
- if (m.content.length === 0) {
- continue;
- }
- const contentBlocks: ContentBlock[] = [];
- for (const c of m.content) {
- switch (c.type) {
- case "text":
- // Skip empty text blocks
- if (c.text.trim().length === 0) continue;
- contentBlocks.push({ text: sanitizeSurrogates(c.text) });
- break;
- case "toolCall":
- contentBlocks.push({
- toolUse: { toolUseId: c.id, name: c.name, input: c.arguments },
- });
- break;
- case "thinking":
- // Skip empty thinking blocks
- if (c.thinking.trim().length === 0) continue;
- // Only Anthropic models support the signature field in reasoningText.
- // For other models, we omit the signature to avoid errors like:
- // "This model doesn't support the reasoningContent.reasoningText.signature field"
- if (supportsThinkingSignature(model)) {
- // Signatures arrive after thinking deltas. If a partial or externally
- // persisted message lacks a signature, Bedrock rejects the replayed
- // reasoning block. Fall back to plain text, matching Anthropic.
- if (!c.thinkingSignature || c.thinkingSignature.trim().length === 0) {
- contentBlocks.push({ text: sanitizeSurrogates(c.thinking) });
- } else {
- contentBlocks.push({
- reasoningContent: {
- reasoningText: {
- text: sanitizeSurrogates(c.thinking),
- signature: c.thinkingSignature,
- },
- },
- });
- }
- } else {
- contentBlocks.push({
- reasoningContent: {
- reasoningText: { text: sanitizeSurrogates(c.thinking) },
- },
- });
- }
- break;
- default:
- throw new Error("Unknown assistant content type");
- }
- }
- // Skip if all content blocks were filtered out
- if (contentBlocks.length === 0) {
- continue;
- }
- result.push({
- role: ConversationRole.ASSISTANT,
- content: contentBlocks,
- });
- break;
- }
- case "toolResult": {
- // Collect all consecutive toolResult messages into a single user message
- // Bedrock requires all tool results to be in one message
- const toolResults: ContentBlock.ToolResultMember[] = [];
-
- // Add current tool result with all content blocks combined
- toolResults.push({
- toolResult: {
- toolUseId: m.toolCallId,
- content: m.content.map((c) =>
- c.type === "image"
- ? { image: createImageBlock(c.mimeType, c.data) }
- : { text: sanitizeSurrogates(c.text) },
- ),
- status: m.isError ? ToolResultStatus.ERROR : ToolResultStatus.SUCCESS,
- },
- });
-
- // Look ahead for consecutive toolResult messages
- let j = i + 1;
- while (j < transformedMessages.length && transformedMessages[j].role === "toolResult") {
- const nextMsg = transformedMessages[j] as ToolResultMessage;
- toolResults.push({
- toolResult: {
- toolUseId: nextMsg.toolCallId,
- content: nextMsg.content.map((c) =>
- c.type === "image"
- ? { image: createImageBlock(c.mimeType, c.data) }
- : { text: sanitizeSurrogates(c.text) },
- ),
- status: nextMsg.isError ? ToolResultStatus.ERROR : ToolResultStatus.SUCCESS,
- },
- });
- j++;
- }
-
- // Skip the messages we've already processed
- i = j - 1;
-
- result.push({
- role: ConversationRole.USER,
- content: toolResults,
- });
- break;
- }
- default:
- throw new Error("Unknown message role");
- }
- }
-
- // Add cache point to the last user message for supported Claude models when caching is enabled
- if (cacheRetention !== "none" && supportsPromptCaching(model) && result.length > 0) {
- const lastMessage = result[result.length - 1];
- if (lastMessage.role === ConversationRole.USER && lastMessage.content) {
- (lastMessage.content as ContentBlock[]).push({
- cachePoint: {
- type: CachePointType.DEFAULT,
- ...(cacheRetention === "long" ? { ttl: CacheTTL.ONE_HOUR } : {}),
- },
- });
- }
- }
-
- return result;
-}
-
-function convertToolConfig(
- tools: Tool[] | undefined,
- toolChoice: BedrockOptions["toolChoice"],
-): ToolConfiguration | undefined {
- if (!tools?.length || toolChoice === "none") return undefined;
-
- const bedrockTools: BedrockTool[] = tools.map((tool) => ({
- toolSpec: {
- name: tool.name,
- description: tool.description,
- inputSchema: { json: tool.parameters },
- },
- }));
-
- let bedrockToolChoice: ToolChoice | undefined;
- switch (toolChoice) {
- case "auto":
- bedrockToolChoice = { auto: {} };
- break;
- case "any":
- bedrockToolChoice = { any: {} };
- break;
- default:
- if (toolChoice?.type === "tool") {
- bedrockToolChoice = { tool: { name: toolChoice.name } };
- }
- }
-
- return { tools: bedrockTools, toolChoice: bedrockToolChoice };
-}
-
-function mapStopReason(reason: string | undefined): StopReason {
- switch (reason) {
- case BedrockStopReason.END_TURN:
- case BedrockStopReason.STOP_SEQUENCE:
- return "stop";
- case BedrockStopReason.MAX_TOKENS:
- case BedrockStopReason.MODEL_CONTEXT_WINDOW_EXCEEDED:
- return "length";
- case BedrockStopReason.TOOL_USE:
- return "toolUse";
- default:
- return "error";
- }
-}
-
-function buildAdditionalModelRequestFields(
- model: Model<"bedrock-converse-stream">,
- options: BedrockOptions,
-): Record | undefined {
- if (!options.reasoning || !model.reasoning) {
- return undefined;
- }
-
- if (model.id.includes("anthropic.claude") || model.id.includes("anthropic/claude")) {
- const result: Record = supportsAdaptiveThinking(model.id)
- ? {
- thinking: { type: "adaptive" },
- output_config: { effort: mapThinkingLevelToEffort(options.reasoning, model.id) },
- }
- : (() => {
- const defaultBudgets: Record = {
- minimal: 1024,
- low: 2048,
- medium: 8192,
- high: 16384,
- xhigh: 16384, // Claude doesn't support xhigh, clamp to high
- };
-
- // Custom budgets override defaults (xhigh not in ThinkingBudgets, use high)
- const level = options.reasoning === "xhigh" ? "high" : options.reasoning;
- const budget = options.thinkingBudgets?.[level] ?? defaultBudgets[options.reasoning];
-
- return {
- thinking: {
- type: "enabled",
- budget_tokens: budget,
- },
- };
- })();
-
- if (!supportsAdaptiveThinking(model.id) && (options.interleavedThinking ?? true)) {
- result.anthropic_beta = ["interleaved-thinking-2025-05-14"];
- }
-
- return result;
- }
-
- return undefined;
-}
-
-function createImageBlock(mimeType: string, data: string) {
- let format: ImageFormat;
- switch (mimeType) {
- case "image/jpeg":
- case "image/jpg":
- format = ImageFormat.JPEG;
- break;
- case "image/png":
- format = ImageFormat.PNG;
- break;
- case "image/gif":
- format = ImageFormat.GIF;
- break;
- case "image/webp":
- format = ImageFormat.WEBP;
- break;
- default:
- throw new Error(`Unknown image type: ${mimeType}`);
- }
-
- const binaryString = atob(data);
- const bytes = new Uint8Array(binaryString.length);
- for (let i = 0; i < binaryString.length; i++) {
- bytes[i] = binaryString.charCodeAt(i);
- }
-
- return { source: { bytes }, format };
-}
diff --git a/pi-mono-reference/packages/ai/src/providers/anthropic.ts b/pi-mono-reference/packages/ai/src/providers/anthropic.ts
deleted file mode 100644
index 1741b400..00000000
--- a/pi-mono-reference/packages/ai/src/providers/anthropic.ts
+++ /dev/null
@@ -1,926 +0,0 @@
-import Anthropic from "@anthropic-ai/sdk";
-import type {
- CacheControlEphemeral,
- ContentBlockParam,
- MessageCreateParamsStreaming,
- MessageParam,
-} from "@anthropic-ai/sdk/resources/messages.js";
-import { getEnvApiKey } from "../env-api-keys.js";
-import { calculateCost } from "../models.js";
-import type {
- Api,
- AssistantMessage,
- CacheRetention,
- Context,
- ImageContent,
- Message,
- Model,
- SimpleStreamOptions,
- StopReason,
- StreamFunction,
- StreamOptions,
- TextContent,
- ThinkingContent,
- Tool,
- ToolCall,
- ToolResultMessage,
-} from "../types.js";
-import { AssistantMessageEventStream } from "../utils/event-stream.js";
-import { parseStreamingJson } from "../utils/json-parse.js";
-import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
-
-import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
-import { adjustMaxTokensForThinking, buildBaseOptions } from "./simple-options.js";
-import { transformMessages } from "./transform-messages.js";
-
-/**
- * Resolve cache retention preference.
- * Defaults to "short" and uses PI_CACHE_RETENTION for backward compatibility.
- */
-function resolveCacheRetention(cacheRetention?: CacheRetention): CacheRetention {
- if (cacheRetention) {
- return cacheRetention;
- }
- if (typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long") {
- return "long";
- }
- return "short";
-}
-
-function getCacheControl(
- baseUrl: string,
- cacheRetention?: CacheRetention,
-): { retention: CacheRetention; cacheControl?: CacheControlEphemeral } {
- const retention = resolveCacheRetention(cacheRetention);
- if (retention === "none") {
- return { retention };
- }
- const ttl = retention === "long" && baseUrl.includes("api.anthropic.com") ? "1h" : undefined;
- return {
- retention,
- cacheControl: { type: "ephemeral", ...(ttl && { ttl }) },
- };
-}
-
-// Stealth mode: Mimic Claude Code's tool naming exactly
-const claudeCodeVersion = "2.1.75";
-
-// Claude Code 2.x tool names (canonical casing)
-// Source: https://cchistory.mariozechner.at/data/prompts-2.1.11.md
-// To update: https://github.com/badlogic/cchistory
-const claudeCodeTools = [
- "Read",
- "Write",
- "Edit",
- "Bash",
- "Grep",
- "Glob",
- "AskUserQuestion",
- "EnterPlanMode",
- "ExitPlanMode",
- "KillShell",
- "NotebookEdit",
- "Skill",
- "Task",
- "TaskOutput",
- "TodoWrite",
- "WebFetch",
- "WebSearch",
-];
-
-const ccToolLookup = new Map(claudeCodeTools.map((t) => [t.toLowerCase(), t]));
-
-// Convert tool name to CC canonical casing if it matches (case-insensitive)
-const toClaudeCodeName = (name: string) => ccToolLookup.get(name.toLowerCase()) ?? name;
-const fromClaudeCodeName = (name: string, tools?: Tool[]) => {
- if (tools && tools.length > 0) {
- const lowerName = name.toLowerCase();
- const matchedTool = tools.find((tool) => tool.name.toLowerCase() === lowerName);
- if (matchedTool) return matchedTool.name;
- }
- return name;
-};
-
-/**
- * Convert content blocks to Anthropic API format
- */
-function convertContentBlocks(content: (TextContent | ImageContent)[]):
- | string
- | Array<
- | { type: "text"; text: string }
- | {
- type: "image";
- source: {
- type: "base64";
- media_type: "image/jpeg" | "image/png" | "image/gif" | "image/webp";
- data: string;
- };
- }
- > {
- // If only text blocks, return as concatenated string for simplicity
- const hasImages = content.some((c) => c.type === "image");
- if (!hasImages) {
- return sanitizeSurrogates(content.map((c) => (c as TextContent).text).join("\n"));
- }
-
- // If we have images, convert to content block array
- const blocks = content.map((block) => {
- if (block.type === "text") {
- return {
- type: "text" as const,
- text: sanitizeSurrogates(block.text),
- };
- }
- return {
- type: "image" as const,
- source: {
- type: "base64" as const,
- media_type: block.mimeType as "image/jpeg" | "image/png" | "image/gif" | "image/webp",
- data: block.data,
- },
- };
- });
-
- // If only images (no text), add placeholder text block
- const hasText = blocks.some((b) => b.type === "text");
- if (!hasText) {
- blocks.unshift({
- type: "text" as const,
- text: "(see attached image)",
- });
- }
-
- return blocks;
-}
-
-export type AnthropicEffort = "low" | "medium" | "high" | "xhigh" | "max";
-
-export interface AnthropicOptions extends StreamOptions {
- /**
- * Enable extended thinking.
- * For Opus 4.6 and Sonnet 4.6: uses adaptive thinking (model decides when/how much to think).
- * For older models: uses budget-based thinking with thinkingBudgetTokens.
- */
- thinkingEnabled?: boolean;
- /**
- * Token budget for extended thinking (older models only).
- * Ignored for Opus 4.6 and Sonnet 4.6, which use adaptive thinking.
- */
- thinkingBudgetTokens?: number;
- /**
- * Effort level for adaptive thinking (Opus 4.6+ and Sonnet 4.6).
- * Controls how much thinking Claude allocates:
- * - "max": Always thinks with no constraints (Opus 4.6 only)
- * - "xhigh": Highest reasoning level (Opus 4.7)
- * - "high": Always thinks, deep reasoning (default)
- * - "medium": Moderate thinking, may skip for simple queries
- * - "low": Minimal thinking, skips for simple tasks
- * Ignored for older models.
- */
- effort?: AnthropicEffort;
- interleavedThinking?: boolean;
- toolChoice?: "auto" | "any" | "none" | { type: "tool"; name: string };
- /**
- * Pre-built Anthropic client instance. When provided, skips internal client
- * construction entirely. Use this to inject alternative SDK clients such as
- * `AnthropicVertex` that shares the same messaging API.
- */
- client?: Anthropic;
-}
-
-function mergeHeaders(...headerSources: (Record | undefined)[]): Record {
- const merged: Record = {};
- for (const headers of headerSources) {
- if (headers) {
- Object.assign(merged, headers);
- }
- }
- return merged;
-}
-
-export const streamAnthropic: StreamFunction<"anthropic-messages", AnthropicOptions> = (
- model: Model<"anthropic-messages">,
- context: Context,
- options?: AnthropicOptions,
-): AssistantMessageEventStream => {
- const stream = new AssistantMessageEventStream();
-
- (async () => {
- const output: AssistantMessage = {
- role: "assistant",
- content: [],
- api: model.api as Api,
- provider: model.provider,
- model: model.id,
- usage: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- stopReason: "stop",
- timestamp: Date.now(),
- };
-
- try {
- let client: Anthropic;
- let isOAuth: boolean;
-
- if (options?.client) {
- client = options.client;
- isOAuth = false;
- } else {
- const apiKey = options?.apiKey ?? getEnvApiKey(model.provider) ?? "";
-
- let copilotDynamicHeaders: Record | undefined;
- if (model.provider === "github-copilot") {
- const hasImages = hasCopilotVisionInput(context.messages);
- copilotDynamicHeaders = buildCopilotDynamicHeaders({
- messages: context.messages,
- hasImages,
- });
- }
-
- const created = createClient(
- model,
- apiKey,
- options?.interleavedThinking ?? true,
- options?.headers,
- copilotDynamicHeaders,
- );
- client = created.client;
- isOAuth = created.isOAuthToken;
- }
- let params = buildParams(model, context, isOAuth, options);
- const nextParams = await options?.onPayload?.(params, model);
- if (nextParams !== undefined) {
- params = nextParams as MessageCreateParamsStreaming;
- }
- const anthropicStream = client.messages.stream({ ...params, stream: true }, { signal: options?.signal });
- stream.push({ type: "start", partial: output });
-
- type Block = (ThinkingContent | TextContent | (ToolCall & { partialJson: string })) & { index: number };
- const blocks = output.content as Block[];
-
- for await (const event of anthropicStream) {
- if (event.type === "message_start") {
- output.responseId = event.message.id;
- // Capture initial token usage from message_start event
- // This ensures we have input token counts even if the stream is aborted early
- output.usage.input = event.message.usage.input_tokens || 0;
- output.usage.output = event.message.usage.output_tokens || 0;
- output.usage.cacheRead = event.message.usage.cache_read_input_tokens || 0;
- output.usage.cacheWrite = event.message.usage.cache_creation_input_tokens || 0;
- // Anthropic doesn't provide total_tokens, compute from components
- output.usage.totalTokens =
- output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
- calculateCost(model, output.usage);
- } else if (event.type === "content_block_start") {
- if (event.content_block.type === "text") {
- const block: Block = {
- type: "text",
- text: "",
- index: event.index,
- };
- output.content.push(block);
- stream.push({ type: "text_start", contentIndex: output.content.length - 1, partial: output });
- } else if (event.content_block.type === "thinking") {
- const block: Block = {
- type: "thinking",
- thinking: "",
- thinkingSignature: "",
- index: event.index,
- };
- output.content.push(block);
- stream.push({ type: "thinking_start", contentIndex: output.content.length - 1, partial: output });
- } else if (event.content_block.type === "redacted_thinking") {
- const block: Block = {
- type: "thinking",
- thinking: "[Reasoning redacted]",
- thinkingSignature: event.content_block.data,
- redacted: true,
- index: event.index,
- };
- output.content.push(block);
- stream.push({ type: "thinking_start", contentIndex: output.content.length - 1, partial: output });
- } else if (event.content_block.type === "tool_use") {
- const block: Block = {
- type: "toolCall",
- id: event.content_block.id,
- name: isOAuth
- ? fromClaudeCodeName(event.content_block.name, context.tools)
- : event.content_block.name,
- arguments: (event.content_block.input as Record) ?? {},
- partialJson: "",
- index: event.index,
- };
- output.content.push(block);
- stream.push({ type: "toolcall_start", contentIndex: output.content.length - 1, partial: output });
- }
- } else if (event.type === "content_block_delta") {
- if (event.delta.type === "text_delta") {
- const index = blocks.findIndex((b) => b.index === event.index);
- const block = blocks[index];
- if (block && block.type === "text") {
- block.text += event.delta.text;
- stream.push({
- type: "text_delta",
- contentIndex: index,
- delta: event.delta.text,
- partial: output,
- });
- }
- } else if (event.delta.type === "thinking_delta") {
- const index = blocks.findIndex((b) => b.index === event.index);
- const block = blocks[index];
- if (block && block.type === "thinking") {
- block.thinking += event.delta.thinking;
- stream.push({
- type: "thinking_delta",
- contentIndex: index,
- delta: event.delta.thinking,
- partial: output,
- });
- }
- } else if (event.delta.type === "input_json_delta") {
- const index = blocks.findIndex((b) => b.index === event.index);
- const block = blocks[index];
- if (block && block.type === "toolCall") {
- block.partialJson += event.delta.partial_json;
- block.arguments = parseStreamingJson(block.partialJson);
- stream.push({
- type: "toolcall_delta",
- contentIndex: index,
- delta: event.delta.partial_json,
- partial: output,
- });
- }
- } else if (event.delta.type === "signature_delta") {
- const index = blocks.findIndex((b) => b.index === event.index);
- const block = blocks[index];
- if (block && block.type === "thinking") {
- block.thinkingSignature = block.thinkingSignature || "";
- block.thinkingSignature += event.delta.signature;
- }
- }
- } else if (event.type === "content_block_stop") {
- const index = blocks.findIndex((b) => b.index === event.index);
- const block = blocks[index];
- if (block) {
- delete (block as any).index;
- if (block.type === "text") {
- stream.push({
- type: "text_end",
- contentIndex: index,
- content: block.text,
- partial: output,
- });
- } else if (block.type === "thinking") {
- stream.push({
- type: "thinking_end",
- contentIndex: index,
- content: block.thinking,
- partial: output,
- });
- } else if (block.type === "toolCall") {
- block.arguments = parseStreamingJson(block.partialJson);
- // Finalize in-place and strip the scratch buffer so replay only
- // carries parsed arguments.
- delete (block as { partialJson?: string }).partialJson;
- stream.push({
- type: "toolcall_end",
- contentIndex: index,
- toolCall: block,
- partial: output,
- });
- }
- }
- } else if (event.type === "message_delta") {
- if (event.delta.stop_reason) {
- output.stopReason = mapStopReason(event.delta.stop_reason);
- }
- // Only update usage fields if present (not null).
- // Preserves input_tokens from message_start when proxies omit it in message_delta.
- if (event.usage.input_tokens != null) {
- output.usage.input = event.usage.input_tokens;
- }
- if (event.usage.output_tokens != null) {
- output.usage.output = event.usage.output_tokens;
- }
- if (event.usage.cache_read_input_tokens != null) {
- output.usage.cacheRead = event.usage.cache_read_input_tokens;
- }
- if (event.usage.cache_creation_input_tokens != null) {
- output.usage.cacheWrite = event.usage.cache_creation_input_tokens;
- }
- // Anthropic doesn't provide total_tokens, compute from components
- output.usage.totalTokens =
- output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
- calculateCost(model, output.usage);
- }
- }
-
- if (options?.signal?.aborted) {
- throw new Error("Request was aborted");
- }
-
- if (output.stopReason === "aborted" || output.stopReason === "error") {
- throw new Error("An unknown error occurred");
- }
-
- stream.push({ type: "done", reason: output.stopReason, message: output });
- stream.end();
- } catch (error) {
- for (const block of output.content) {
- delete (block as { index?: number }).index;
- // partialJson is only a streaming scratch buffer; never persist it.
- delete (block as { partialJson?: string }).partialJson;
- }
- output.stopReason = options?.signal?.aborted ? "aborted" : "error";
- output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
- stream.push({ type: "error", reason: output.stopReason, error: output });
- stream.end();
- }
- })();
-
- return stream;
-};
-
-/**
- * Check if a model supports adaptive thinking (Opus 4.6+, Sonnet 4.6)
- */
-function supportsAdaptiveThinking(modelId: string): boolean {
- // Adaptive-thinking model IDs (with or without date suffix)
- return (
- modelId.includes("opus-4-6") ||
- modelId.includes("opus-4.6") ||
- modelId.includes("opus-4-7") ||
- modelId.includes("opus-4.7") ||
- modelId.includes("sonnet-4-6") ||
- modelId.includes("sonnet-4.6")
- );
-}
-
-/**
- * Map ThinkingLevel to Anthropic effort levels for adaptive thinking.
- * Note: effort "max" is only valid on Opus 4.6, while Opus 4.7 supports "xhigh".
- */
-function mapThinkingLevelToEffort(level: SimpleStreamOptions["reasoning"], modelId: string): AnthropicEffort {
- switch (level) {
- case "minimal":
- return "low";
- case "low":
- return "low";
- case "medium":
- return "medium";
- case "high":
- return "high";
- case "xhigh":
- if (modelId.includes("opus-4-6") || modelId.includes("opus-4.6")) {
- return "max";
- }
- if (modelId.includes("opus-4-7") || modelId.includes("opus-4.7")) {
- return "xhigh";
- }
- return "high";
- default:
- return "high";
- }
-}
-
-export const streamSimpleAnthropic: StreamFunction<"anthropic-messages", SimpleStreamOptions> = (
- model: Model<"anthropic-messages">,
- context: Context,
- options?: SimpleStreamOptions,
-): AssistantMessageEventStream => {
- const apiKey = options?.apiKey || getEnvApiKey(model.provider);
- if (!apiKey) {
- throw new Error(`No API key for provider: ${model.provider}`);
- }
-
- const base = buildBaseOptions(model, options, apiKey);
- if (!options?.reasoning) {
- return streamAnthropic(model, context, { ...base, thinkingEnabled: false } satisfies AnthropicOptions);
- }
-
- // For Opus 4.6 and Sonnet 4.6: use adaptive thinking with effort level
- // For older models: use budget-based thinking
- if (supportsAdaptiveThinking(model.id)) {
- const effort = mapThinkingLevelToEffort(options.reasoning, model.id);
- return streamAnthropic(model, context, {
- ...base,
- thinkingEnabled: true,
- effort,
- } satisfies AnthropicOptions);
- }
-
- const adjusted = adjustMaxTokensForThinking(
- base.maxTokens || 0,
- model.maxTokens,
- options.reasoning,
- options.thinkingBudgets,
- );
-
- return streamAnthropic(model, context, {
- ...base,
- maxTokens: adjusted.maxTokens,
- thinkingEnabled: true,
- thinkingBudgetTokens: adjusted.thinkingBudget,
- } satisfies AnthropicOptions);
-};
-
-function isOAuthToken(apiKey: string): boolean {
- return apiKey.includes("sk-ant-oat");
-}
-
-function createClient(
- model: Model<"anthropic-messages">,
- apiKey: string,
- interleavedThinking: boolean,
- optionsHeaders?: Record,
- dynamicHeaders?: Record,
-): { client: Anthropic; isOAuthToken: boolean } {
- // Adaptive thinking models (Opus 4.6, Sonnet 4.6) have interleaved thinking built-in.
- // The beta header is deprecated on Opus 4.6 and redundant on Sonnet 4.6, so skip it.
- const needsInterleavedBeta = interleavedThinking && !supportsAdaptiveThinking(model.id);
-
- // Copilot: Bearer auth, selective betas (no fine-grained-tool-streaming)
- if (model.provider === "github-copilot") {
- const betaFeatures: string[] = [];
- if (needsInterleavedBeta) {
- betaFeatures.push("interleaved-thinking-2025-05-14");
- }
-
- const client = new Anthropic({
- apiKey: null,
- authToken: apiKey,
- baseURL: model.baseUrl,
- dangerouslyAllowBrowser: true,
- defaultHeaders: mergeHeaders(
- {
- accept: "application/json",
- "anthropic-dangerous-direct-browser-access": "true",
- ...(betaFeatures.length > 0 ? { "anthropic-beta": betaFeatures.join(",") } : {}),
- },
- model.headers,
- dynamicHeaders,
- optionsHeaders,
- ),
- });
-
- return { client, isOAuthToken: false };
- }
-
- const betaFeatures = ["fine-grained-tool-streaming-2025-05-14"];
- if (needsInterleavedBeta) {
- betaFeatures.push("interleaved-thinking-2025-05-14");
- }
-
- // OAuth: Bearer auth, Claude Code identity headers
- if (isOAuthToken(apiKey)) {
- const client = new Anthropic({
- apiKey: null,
- authToken: apiKey,
- baseURL: model.baseUrl,
- dangerouslyAllowBrowser: true,
- defaultHeaders: mergeHeaders(
- {
- accept: "application/json",
- "anthropic-dangerous-direct-browser-access": "true",
- "anthropic-beta": `claude-code-20250219,oauth-2025-04-20,${betaFeatures.join(",")}`,
- "user-agent": `claude-cli/${claudeCodeVersion}`,
- "x-app": "cli",
- },
- model.headers,
- optionsHeaders,
- ),
- });
-
- return { client, isOAuthToken: true };
- }
-
- // API key auth
- const client = new Anthropic({
- apiKey,
- baseURL: model.baseUrl,
- dangerouslyAllowBrowser: true,
- defaultHeaders: mergeHeaders(
- {
- accept: "application/json",
- "anthropic-dangerous-direct-browser-access": "true",
- "anthropic-beta": betaFeatures.join(","),
- },
- model.headers,
- optionsHeaders,
- ),
- });
-
- return { client, isOAuthToken: false };
-}
-
-function buildParams(
- model: Model<"anthropic-messages">,
- context: Context,
- isOAuthToken: boolean,
- options?: AnthropicOptions,
-): MessageCreateParamsStreaming {
- const { cacheControl } = getCacheControl(model.baseUrl, options?.cacheRetention);
- const params: MessageCreateParamsStreaming = {
- model: model.id,
- messages: convertMessages(context.messages, model, isOAuthToken, cacheControl),
- max_tokens: options?.maxTokens || (model.maxTokens / 3) | 0,
- stream: true,
- };
-
- // For OAuth tokens, we MUST include Claude Code identity
- if (isOAuthToken) {
- params.system = [
- {
- type: "text",
- text: "You are Claude Code, Anthropic's official CLI for Claude.",
- ...(cacheControl ? { cache_control: cacheControl } : {}),
- },
- ];
- if (context.systemPrompt) {
- params.system.push({
- type: "text",
- text: sanitizeSurrogates(context.systemPrompt),
- ...(cacheControl ? { cache_control: cacheControl } : {}),
- });
- }
- } else if (context.systemPrompt) {
- // Add cache control to system prompt for non-OAuth tokens
- params.system = [
- {
- type: "text",
- text: sanitizeSurrogates(context.systemPrompt),
- ...(cacheControl ? { cache_control: cacheControl } : {}),
- },
- ];
- }
-
- // Temperature is incompatible with extended thinking (adaptive or budget-based).
- if (options?.temperature !== undefined && !options?.thinkingEnabled) {
- params.temperature = options.temperature;
- }
-
- if (context.tools) {
- params.tools = convertTools(context.tools, isOAuthToken, cacheControl);
- }
-
- // Configure thinking mode: adaptive (Opus 4.6 and Sonnet 4.6),
- // budget-based (older models), or explicitly disabled.
- if (model.reasoning) {
- if (options?.thinkingEnabled) {
- if (supportsAdaptiveThinking(model.id)) {
- // Adaptive thinking: Claude decides when and how much to think
- params.thinking = { type: "adaptive" };
- if (options.effort) {
- params.output_config = { effort: options.effort };
- }
- } else {
- // Budget-based thinking for older models
- params.thinking = {
- type: "enabled",
- budget_tokens: options.thinkingBudgetTokens || 1024,
- };
- }
- } else if (options?.thinkingEnabled === false) {
- params.thinking = { type: "disabled" };
- }
- }
-
- if (options?.metadata) {
- const userId = options.metadata.user_id;
- if (typeof userId === "string") {
- params.metadata = { user_id: userId };
- }
- }
-
- if (options?.toolChoice) {
- if (typeof options.toolChoice === "string") {
- params.tool_choice = { type: options.toolChoice };
- } else {
- params.tool_choice = options.toolChoice;
- }
- }
-
- return params;
-}
-
-// Normalize tool call IDs to match Anthropic's required pattern and length
-function normalizeToolCallId(id: string): string {
- return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
-}
-
-function convertMessages(
- messages: Message[],
- model: Model<"anthropic-messages">,
- isOAuthToken: boolean,
- cacheControl?: CacheControlEphemeral,
-): MessageParam[] {
- const params: MessageParam[] = [];
-
- // Transform messages for cross-provider compatibility
- const transformedMessages = transformMessages(messages, model, normalizeToolCallId);
-
- for (let i = 0; i < transformedMessages.length; i++) {
- const msg = transformedMessages[i];
-
- if (msg.role === "user") {
- if (typeof msg.content === "string") {
- if (msg.content.trim().length > 0) {
- params.push({
- role: "user",
- content: sanitizeSurrogates(msg.content),
- });
- }
- } else {
- const blocks: ContentBlockParam[] = msg.content.map((item) => {
- if (item.type === "text") {
- return {
- type: "text",
- text: sanitizeSurrogates(item.text),
- };
- } else {
- return {
- type: "image",
- source: {
- type: "base64",
- media_type: item.mimeType as "image/jpeg" | "image/png" | "image/gif" | "image/webp",
- data: item.data,
- },
- };
- }
- });
- let filteredBlocks = !model?.input.includes("image") ? blocks.filter((b) => b.type !== "image") : blocks;
- filteredBlocks = filteredBlocks.filter((b) => {
- if (b.type === "text") {
- return b.text.trim().length > 0;
- }
- return true;
- });
- if (filteredBlocks.length === 0) continue;
- params.push({
- role: "user",
- content: filteredBlocks,
- });
- }
- } else if (msg.role === "assistant") {
- const blocks: ContentBlockParam[] = [];
-
- for (const block of msg.content) {
- if (block.type === "text") {
- if (block.text.trim().length === 0) continue;
- blocks.push({
- type: "text",
- text: sanitizeSurrogates(block.text),
- });
- } else if (block.type === "thinking") {
- // Redacted thinking: pass the opaque payload back as redacted_thinking
- if (block.redacted) {
- blocks.push({
- type: "redacted_thinking",
- data: block.thinkingSignature!,
- });
- continue;
- }
- if (block.thinking.trim().length === 0) continue;
- // If thinking signature is missing/empty (e.g., from aborted stream),
- // convert to plain text block without tags to avoid API rejection
- // and prevent Claude from mimicking the tags in responses
- if (!block.thinkingSignature || block.thinkingSignature.trim().length === 0) {
- blocks.push({
- type: "text",
- text: sanitizeSurrogates(block.thinking),
- });
- } else {
- blocks.push({
- type: "thinking",
- thinking: sanitizeSurrogates(block.thinking),
- signature: block.thinkingSignature,
- });
- }
- } else if (block.type === "toolCall") {
- blocks.push({
- type: "tool_use",
- id: block.id,
- name: isOAuthToken ? toClaudeCodeName(block.name) : block.name,
- input: block.arguments ?? {},
- });
- }
- }
- if (blocks.length === 0) continue;
- params.push({
- role: "assistant",
- content: blocks,
- });
- } else if (msg.role === "toolResult") {
- // Collect all consecutive toolResult messages, needed for z.ai Anthropic endpoint
- const toolResults: ContentBlockParam[] = [];
-
- // Add the current tool result
- toolResults.push({
- type: "tool_result",
- tool_use_id: msg.toolCallId,
- content: convertContentBlocks(msg.content),
- is_error: msg.isError,
- });
-
- // Look ahead for consecutive toolResult messages
- let j = i + 1;
- while (j < transformedMessages.length && transformedMessages[j].role === "toolResult") {
- const nextMsg = transformedMessages[j] as ToolResultMessage; // We know it's a toolResult
- toolResults.push({
- type: "tool_result",
- tool_use_id: nextMsg.toolCallId,
- content: convertContentBlocks(nextMsg.content),
- is_error: nextMsg.isError,
- });
- j++;
- }
-
- // Skip the messages we've already processed
- i = j - 1;
-
- // Add a single user message with all tool results
- params.push({
- role: "user",
- content: toolResults,
- });
- }
- }
-
- // Add cache_control to the last user message to cache conversation history
- if (cacheControl && params.length > 0) {
- const lastMessage = params[params.length - 1];
- if (lastMessage.role === "user") {
- if (Array.isArray(lastMessage.content)) {
- const lastBlock = lastMessage.content[lastMessage.content.length - 1];
- if (
- lastBlock &&
- (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "tool_result")
- ) {
- (lastBlock as any).cache_control = cacheControl;
- }
- } else if (typeof lastMessage.content === "string") {
- lastMessage.content = [
- {
- type: "text",
- text: lastMessage.content,
- cache_control: cacheControl,
- },
- ] as any;
- }
- }
- }
-
- return params;
-}
-
-function convertTools(
- tools: Tool[],
- isOAuthToken: boolean,
- cacheControl?: CacheControlEphemeral,
-): Anthropic.Messages.Tool[] {
- if (!tools) return [];
-
- return tools.map((tool, index) => {
- const schema = tool.parameters as { properties?: unknown; required?: string[] };
-
- return {
- name: isOAuthToken ? toClaudeCodeName(tool.name) : tool.name,
- description: tool.description,
- input_schema: {
- type: "object",
- properties: schema.properties ?? {},
- required: schema.required ?? [],
- },
- ...(cacheControl && index === tools.length - 1 ? { cache_control: cacheControl } : {}),
- };
- });
-}
-
-function mapStopReason(reason: Anthropic.Messages.StopReason | string): StopReason {
- switch (reason) {
- case "end_turn":
- return "stop";
- case "max_tokens":
- return "length";
- case "tool_use":
- return "toolUse";
- case "refusal":
- return "error";
- case "pause_turn": // Stop is good enough -> resubmit
- return "stop";
- case "stop_sequence":
- return "stop"; // We don't supply stop sequences, so this should never happen
- case "sensitive": // Content flagged by safety filters (not yet in SDK types)
- return "error";
- default:
- // Handle unknown stop reasons gracefully (API may add new values)
- throw new Error(`Unhandled stop reason: ${reason}`);
- }
-}
diff --git a/pi-mono-reference/packages/ai/src/providers/azure-openai-responses.ts b/pi-mono-reference/packages/ai/src/providers/azure-openai-responses.ts
deleted file mode 100644
index 9dc5261e..00000000
--- a/pi-mono-reference/packages/ai/src/providers/azure-openai-responses.ts
+++ /dev/null
@@ -1,252 +0,0 @@
-import { AzureOpenAI } from "openai";
-import type { ResponseCreateParamsStreaming } from "openai/resources/responses/responses.js";
-import { getEnvApiKey } from "../env-api-keys.js";
-import { supportsXhigh } from "../models.js";
-import type {
- Api,
- AssistantMessage,
- Context,
- Model,
- SimpleStreamOptions,
- StreamFunction,
- StreamOptions,
-} from "../types.js";
-import { AssistantMessageEventStream } from "../utils/event-stream.js";
-import { convertResponsesMessages, convertResponsesTools, processResponsesStream } from "./openai-responses-shared.js";
-import { buildBaseOptions, clampReasoning } from "./simple-options.js";
-
-const DEFAULT_AZURE_API_VERSION = "v1";
-const AZURE_TOOL_CALL_PROVIDERS = new Set(["openai", "openai-codex", "opencode", "azure-openai-responses"]);
-
-function parseDeploymentNameMap(value: string | undefined): Map {
- const map = new Map();
- if (!value) return map;
- for (const entry of value.split(",")) {
- const trimmed = entry.trim();
- if (!trimmed) continue;
- const [modelId, deploymentName] = trimmed.split("=", 2);
- if (!modelId || !deploymentName) continue;
- map.set(modelId.trim(), deploymentName.trim());
- }
- return map;
-}
-
-function resolveDeploymentName(model: Model<"azure-openai-responses">, options?: AzureOpenAIResponsesOptions): string {
- if (options?.azureDeploymentName) {
- return options.azureDeploymentName;
- }
- const mappedDeployment = parseDeploymentNameMap(process.env.AZURE_OPENAI_DEPLOYMENT_NAME_MAP).get(model.id);
- return mappedDeployment || model.id;
-}
-
-// Azure OpenAI Responses-specific options
-export interface AzureOpenAIResponsesOptions extends StreamOptions {
- reasoningEffort?: "minimal" | "low" | "medium" | "high" | "xhigh";
- reasoningSummary?: "auto" | "detailed" | "concise" | null;
- azureApiVersion?: string;
- azureResourceName?: string;
- azureBaseUrl?: string;
- azureDeploymentName?: string;
-}
-
-/**
- * Generate function for Azure OpenAI Responses API
- */
-export const streamAzureOpenAIResponses: StreamFunction<"azure-openai-responses", AzureOpenAIResponsesOptions> = (
- model: Model<"azure-openai-responses">,
- context: Context,
- options?: AzureOpenAIResponsesOptions,
-): AssistantMessageEventStream => {
- const stream = new AssistantMessageEventStream();
-
- // Start async processing
- (async () => {
- const deploymentName = resolveDeploymentName(model, options);
-
- const output: AssistantMessage = {
- role: "assistant",
- content: [],
- api: "azure-openai-responses" as Api,
- provider: model.provider,
- model: model.id,
- usage: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- stopReason: "stop",
- timestamp: Date.now(),
- };
-
- try {
- // Create Azure OpenAI client
- const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
- const client = createClient(model, apiKey, options);
- let params = buildParams(model, context, options, deploymentName);
- const nextParams = await options?.onPayload?.(params, model);
- if (nextParams !== undefined) {
- params = nextParams as ResponseCreateParamsStreaming;
- }
- const openaiStream = await client.responses.create(
- params,
- options?.signal ? { signal: options.signal } : undefined,
- );
- stream.push({ type: "start", partial: output });
-
- await processResponsesStream(openaiStream, output, stream, model);
-
- if (options?.signal?.aborted) {
- throw new Error("Request was aborted");
- }
-
- if (output.stopReason === "aborted" || output.stopReason === "error") {
- throw new Error("An unknown error occurred");
- }
-
- stream.push({ type: "done", reason: output.stopReason, message: output });
- stream.end();
- } catch (error) {
- for (const block of output.content) {
- delete (block as { index?: number }).index;
- // partialJson is only a streaming scratch buffer; never persist it.
- delete (block as { partialJson?: string }).partialJson;
- }
- output.stopReason = options?.signal?.aborted ? "aborted" : "error";
- output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
- stream.push({ type: "error", reason: output.stopReason, error: output });
- stream.end();
- }
- })();
-
- return stream;
-};
-
-export const streamSimpleAzureOpenAIResponses: StreamFunction<"azure-openai-responses", SimpleStreamOptions> = (
- model: Model<"azure-openai-responses">,
- context: Context,
- options?: SimpleStreamOptions,
-): AssistantMessageEventStream => {
- const apiKey = options?.apiKey || getEnvApiKey(model.provider);
- if (!apiKey) {
- throw new Error(`No API key for provider: ${model.provider}`);
- }
-
- const base = buildBaseOptions(model, options, apiKey);
- const reasoningEffort = supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning);
-
- return streamAzureOpenAIResponses(model, context, {
- ...base,
- reasoningEffort,
- } satisfies AzureOpenAIResponsesOptions);
-};
-
-function normalizeAzureBaseUrl(baseUrl: string): string {
- return baseUrl.replace(/\/+$/, "");
-}
-
-function buildDefaultBaseUrl(resourceName: string): string {
- return `https://${resourceName}.openai.azure.com/openai/v1`;
-}
-
-function resolveAzureConfig(
- model: Model<"azure-openai-responses">,
- options?: AzureOpenAIResponsesOptions,
-): { baseUrl: string; apiVersion: string } {
- const apiVersion = options?.azureApiVersion || process.env.AZURE_OPENAI_API_VERSION || DEFAULT_AZURE_API_VERSION;
-
- const baseUrl = options?.azureBaseUrl?.trim() || process.env.AZURE_OPENAI_BASE_URL?.trim() || undefined;
- const resourceName = options?.azureResourceName || process.env.AZURE_OPENAI_RESOURCE_NAME;
-
- let resolvedBaseUrl = baseUrl;
-
- if (!resolvedBaseUrl && resourceName) {
- resolvedBaseUrl = buildDefaultBaseUrl(resourceName);
- }
-
- if (!resolvedBaseUrl && model.baseUrl) {
- resolvedBaseUrl = model.baseUrl;
- }
-
- if (!resolvedBaseUrl) {
- throw new Error(
- "Azure OpenAI base URL is required. Set AZURE_OPENAI_BASE_URL or AZURE_OPENAI_RESOURCE_NAME, or pass azureBaseUrl, azureResourceName, or model.baseUrl.",
- );
- }
-
- return {
- baseUrl: normalizeAzureBaseUrl(resolvedBaseUrl),
- apiVersion,
- };
-}
-
-function createClient(model: Model<"azure-openai-responses">, apiKey: string, options?: AzureOpenAIResponsesOptions) {
- if (!apiKey) {
- if (!process.env.AZURE_OPENAI_API_KEY) {
- throw new Error(
- "Azure OpenAI API key is required. Set AZURE_OPENAI_API_KEY environment variable or pass it as an argument.",
- );
- }
- apiKey = process.env.AZURE_OPENAI_API_KEY;
- }
-
- const headers = { ...model.headers };
-
- if (options?.headers) {
- Object.assign(headers, options.headers);
- }
-
- const { baseUrl, apiVersion } = resolveAzureConfig(model, options);
-
- return new AzureOpenAI({
- apiKey,
- apiVersion,
- dangerouslyAllowBrowser: true,
- defaultHeaders: headers,
- baseURL: baseUrl,
- });
-}
-
-function buildParams(
- model: Model<"azure-openai-responses">,
- context: Context,
- options: AzureOpenAIResponsesOptions | undefined,
- deploymentName: string,
-) {
- const messages = convertResponsesMessages(model, context, AZURE_TOOL_CALL_PROVIDERS);
-
- const params: ResponseCreateParamsStreaming = {
- model: deploymentName,
- input: messages,
- stream: true,
- prompt_cache_key: options?.sessionId,
- };
-
- if (options?.maxTokens) {
- params.max_output_tokens = options?.maxTokens;
- }
-
- if (options?.temperature !== undefined) {
- params.temperature = options?.temperature;
- }
-
- if (context.tools) {
- params.tools = convertResponsesTools(context.tools);
- }
-
- if (model.reasoning) {
- if (options?.reasoningEffort || options?.reasoningSummary) {
- params.reasoning = {
- effort: options?.reasoningEffort || "medium",
- summary: options?.reasoningSummary || "auto",
- };
- params.include = ["reasoning.encrypted_content"];
- } else {
- params.reasoning = { effort: "none" };
- }
- }
-
- return params;
-}
diff --git a/pi-mono-reference/packages/ai/src/providers/faux.ts b/pi-mono-reference/packages/ai/src/providers/faux.ts
deleted file mode 100644
index 328fd87f..00000000
--- a/pi-mono-reference/packages/ai/src/providers/faux.ts
+++ /dev/null
@@ -1,498 +0,0 @@
-import { registerApiProvider, unregisterApiProviders } from "../api-registry.js";
-import type {
- AssistantMessage,
- AssistantMessageEventStream,
- Context,
- ImageContent,
- Message,
- Model,
- SimpleStreamOptions,
- StreamFunction,
- StreamOptions,
- TextContent,
- ThinkingContent,
- ToolCall,
- ToolResultMessage,
- Usage,
-} from "../types.js";
-import { createAssistantMessageEventStream } from "../utils/event-stream.js";
-
-const DEFAULT_API = "faux";
-const DEFAULT_PROVIDER = "faux";
-const DEFAULT_MODEL_ID = "faux-1";
-const DEFAULT_MODEL_NAME = "Faux Model";
-const DEFAULT_BASE_URL = "http://localhost:0";
-const DEFAULT_MIN_TOKEN_SIZE = 3;
-const DEFAULT_MAX_TOKEN_SIZE = 5;
-
-const DEFAULT_USAGE: Usage = {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
-};
-
-export interface FauxModelDefinition {
- id: string;
- name?: string;
- reasoning?: boolean;
- input?: ("text" | "image")[];
- cost?: { input: number; output: number; cacheRead: number; cacheWrite: number };
- contextWindow?: number;
- maxTokens?: number;
-}
-
-export type FauxContentBlock = TextContent | ThinkingContent | ToolCall;
-
-export function fauxText(text: string): TextContent {
- return { type: "text", text };
-}
-
-export function fauxThinking(thinking: string): ThinkingContent {
- return { type: "thinking", thinking };
-}
-
-export function fauxToolCall(name: string, arguments_: ToolCall["arguments"], options: { id?: string } = {}): ToolCall {
- return {
- type: "toolCall",
- id: options.id ?? randomId("tool"),
- name,
- arguments: arguments_,
- };
-}
-
-function normalizeFauxAssistantContent(content: string | FauxContentBlock | FauxContentBlock[]): FauxContentBlock[] {
- if (typeof content === "string") {
- return [fauxText(content)];
- }
- return Array.isArray(content) ? content : [content];
-}
-
-export function fauxAssistantMessage(
- content: string | FauxContentBlock | FauxContentBlock[],
- options: {
- stopReason?: AssistantMessage["stopReason"];
- errorMessage?: string;
- responseId?: string;
- timestamp?: number;
- } = {},
-): AssistantMessage {
- return {
- role: "assistant",
- content: normalizeFauxAssistantContent(content),
- api: DEFAULT_API,
- provider: DEFAULT_PROVIDER,
- model: DEFAULT_MODEL_ID,
- usage: DEFAULT_USAGE,
- stopReason: options.stopReason ?? "stop",
- errorMessage: options.errorMessage,
- responseId: options.responseId,
- timestamp: options.timestamp ?? Date.now(),
- };
-}
-
-export type FauxResponseFactory = (
- context: Context,
- options: StreamOptions | undefined,
- state: { callCount: number },
- model: Model,
-) => AssistantMessage | Promise;
-
-export type FauxResponseStep = AssistantMessage | FauxResponseFactory;
-
-export interface RegisterFauxProviderOptions {
- api?: string;
- provider?: string;
- models?: FauxModelDefinition[];
- tokensPerSecond?: number;
- tokenSize?: {
- min?: number;
- max?: number;
- };
-}
-
-export interface FauxProviderRegistration {
- api: string;
- models: [Model, ...Model[]];
- getModel(): Model;
- getModel(modelId: string): Model | undefined;
- state: { callCount: number };
- setResponses: (responses: FauxResponseStep[]) => void;
- appendResponses: (responses: FauxResponseStep[]) => void;
- getPendingResponseCount: () => number;
- unregister: () => void;
-}
-
-function estimateTokens(text: string): number {
- return Math.ceil(text.length / 4);
-}
-
-function randomId(prefix: string): string {
- return `${prefix}:${Date.now()}:${Math.random().toString(36).slice(2)}`;
-}
-
-function contentToText(content: string | Array): string {
- if (typeof content === "string") {
- return content;
- }
- return content
- .map((block) => {
- if (block.type === "text") {
- return block.text;
- }
- return `[image:${block.mimeType}:${block.data.length}]`;
- })
- .join("\n");
-}
-
-function assistantContentToText(content: Array): string {
- return content
- .map((block) => {
- if (block.type === "text") {
- return block.text;
- }
- if (block.type === "thinking") {
- return block.thinking;
- }
- return `${block.name}:${JSON.stringify(block.arguments)}`;
- })
- .join("\n");
-}
-
-function toolResultToText(message: ToolResultMessage): string {
- return [message.toolName, ...message.content.map((block) => contentToText([block]))].join("\n");
-}
-
-function messageToText(message: Message): string {
- if (message.role === "user") {
- return contentToText(message.content);
- }
- if (message.role === "assistant") {
- return assistantContentToText(message.content);
- }
- return toolResultToText(message);
-}
-
-function serializeContext(context: Context): string {
- const parts: string[] = [];
- if (context.systemPrompt) {
- parts.push(`system:${context.systemPrompt}`);
- }
- for (const message of context.messages) {
- parts.push(`${message.role}:${messageToText(message)}`);
- }
- if (context.tools?.length) {
- parts.push(`tools:${JSON.stringify(context.tools)}`);
- }
- return parts.join("\n\n");
-}
-
-function commonPrefixLength(a: string, b: string): number {
- const length = Math.min(a.length, b.length);
- let index = 0;
- while (index < length && a[index] === b[index]) {
- index++;
- }
- return index;
-}
-
-function withUsageEstimate(
- message: AssistantMessage,
- context: Context,
- options: StreamOptions | undefined,
- promptCache: Map,
-): AssistantMessage {
- const promptText = serializeContext(context);
- const promptTokens = estimateTokens(promptText);
- const outputTokens = estimateTokens(assistantContentToText(message.content));
- let input = promptTokens;
- let cacheRead = 0;
- let cacheWrite = 0;
- const sessionId = options?.sessionId;
-
- if (sessionId && options?.cacheRetention !== "none") {
- const previousPrompt = promptCache.get(sessionId);
- if (previousPrompt) {
- const cachedChars = commonPrefixLength(previousPrompt, promptText);
- cacheRead = estimateTokens(previousPrompt.slice(0, cachedChars));
- cacheWrite = estimateTokens(promptText.slice(cachedChars));
- input = Math.max(0, promptTokens - cacheRead);
- } else {
- cacheWrite = promptTokens;
- }
- promptCache.set(sessionId, promptText);
- }
-
- return {
- ...message,
- usage: {
- input,
- output: outputTokens,
- cacheRead,
- cacheWrite,
- totalTokens: input + outputTokens + cacheRead + cacheWrite,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- };
-}
-
-function splitStringByTokenSize(text: string, minTokenSize: number, maxTokenSize: number): string[] {
- const chunks: string[] = [];
- let index = 0;
- while (index < text.length) {
- const tokenSize = minTokenSize + Math.floor(Math.random() * (maxTokenSize - minTokenSize + 1));
- const charSize = Math.max(1, tokenSize * 4);
- chunks.push(text.slice(index, index + charSize));
- index += charSize;
- }
- return chunks.length > 0 ? chunks : [""];
-}
-
-function cloneMessage(message: AssistantMessage, api: string, provider: string, modelId: string): AssistantMessage {
- const cloned = structuredClone(message);
- return {
- ...cloned,
- api,
- provider,
- model: modelId,
- timestamp: cloned.timestamp ?? Date.now(),
- usage: cloned.usage ?? DEFAULT_USAGE,
- };
-}
-
-function createErrorMessage(error: unknown, api: string, provider: string, modelId: string): AssistantMessage {
- return {
- role: "assistant",
- content: [],
- api,
- provider,
- model: modelId,
- usage: DEFAULT_USAGE,
- stopReason: "error",
- errorMessage: error instanceof Error ? error.message : String(error),
- timestamp: Date.now(),
- };
-}
-
-function createAbortedMessage(partial: AssistantMessage): AssistantMessage {
- return {
- ...partial,
- stopReason: "aborted",
- errorMessage: "Request was aborted",
- timestamp: Date.now(),
- };
-}
-
-function scheduleChunk(chunk: string, tokensPerSecond: number | undefined): Promise {
- if (!tokensPerSecond || tokensPerSecond <= 0) {
- return new Promise((resolve) => queueMicrotask(resolve));
- }
- const delayMs = (estimateTokens(chunk) / tokensPerSecond) * 1000;
- return new Promise((resolve) => setTimeout(resolve, delayMs));
-}
-
-async function streamWithDeltas(
- stream: AssistantMessageEventStream,
- message: AssistantMessage,
- minTokenSize: number,
- maxTokenSize: number,
- tokensPerSecond: number | undefined,
- signal: AbortSignal | undefined,
-): Promise {
- const partial: AssistantMessage = { ...message, content: [] };
- if (signal?.aborted) {
- const aborted = createAbortedMessage(partial);
- stream.push({ type: "error", reason: "aborted", error: aborted });
- stream.end(aborted);
- return;
- }
-
- stream.push({ type: "start", partial: { ...partial } });
-
- for (let index = 0; index < message.content.length; index++) {
- if (signal?.aborted) {
- const aborted = createAbortedMessage(partial);
- stream.push({ type: "error", reason: "aborted", error: aborted });
- stream.end(aborted);
- return;
- }
-
- const block = message.content[index];
-
- if (block.type === "thinking") {
- partial.content = [...partial.content, { type: "thinking", thinking: "" }];
- stream.push({ type: "thinking_start", contentIndex: index, partial: { ...partial } });
- for (const chunk of splitStringByTokenSize(block.thinking, minTokenSize, maxTokenSize)) {
- await scheduleChunk(chunk, tokensPerSecond);
- if (signal?.aborted) {
- const aborted = createAbortedMessage(partial);
- stream.push({ type: "error", reason: "aborted", error: aborted });
- stream.end(aborted);
- return;
- }
- (partial.content[index] as ThinkingContent).thinking += chunk;
- stream.push({ type: "thinking_delta", contentIndex: index, delta: chunk, partial: { ...partial } });
- }
- stream.push({
- type: "thinking_end",
- contentIndex: index,
- content: block.thinking,
- partial: { ...partial },
- });
- continue;
- }
-
- if (block.type === "text") {
- partial.content = [...partial.content, { type: "text", text: "" }];
- stream.push({ type: "text_start", contentIndex: index, partial: { ...partial } });
- for (const chunk of splitStringByTokenSize(block.text, minTokenSize, maxTokenSize)) {
- await scheduleChunk(chunk, tokensPerSecond);
- if (signal?.aborted) {
- const aborted = createAbortedMessage(partial);
- stream.push({ type: "error", reason: "aborted", error: aborted });
- stream.end(aborted);
- return;
- }
- (partial.content[index] as TextContent).text += chunk;
- stream.push({ type: "text_delta", contentIndex: index, delta: chunk, partial: { ...partial } });
- }
- stream.push({ type: "text_end", contentIndex: index, content: block.text, partial: { ...partial } });
- continue;
- }
-
- partial.content = [...partial.content, { type: "toolCall", id: block.id, name: block.name, arguments: {} }];
- stream.push({ type: "toolcall_start", contentIndex: index, partial: { ...partial } });
- for (const chunk of splitStringByTokenSize(JSON.stringify(block.arguments), minTokenSize, maxTokenSize)) {
- await scheduleChunk(chunk, tokensPerSecond);
- if (signal?.aborted) {
- const aborted = createAbortedMessage(partial);
- stream.push({ type: "error", reason: "aborted", error: aborted });
- stream.end(aborted);
- return;
- }
- stream.push({ type: "toolcall_delta", contentIndex: index, delta: chunk, partial: { ...partial } });
- }
- (partial.content[index] as ToolCall).arguments = block.arguments;
- stream.push({ type: "toolcall_end", contentIndex: index, toolCall: block, partial: { ...partial } });
- }
-
- if (message.stopReason === "error" || message.stopReason === "aborted") {
- stream.push({ type: "error", reason: message.stopReason, error: message });
- stream.end(message);
- return;
- }
-
- stream.push({ type: "done", reason: message.stopReason, message });
- stream.end(message);
-}
-
-export function registerFauxProvider(options: RegisterFauxProviderOptions = {}): FauxProviderRegistration {
- const api = options.api ?? randomId(DEFAULT_API);
- const provider = options.provider ?? DEFAULT_PROVIDER;
- const sourceId = randomId("faux-provider");
- const minTokenSize = Math.max(
- 1,
- Math.min(options.tokenSize?.min ?? DEFAULT_MIN_TOKEN_SIZE, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE),
- );
- const maxTokenSize = Math.max(minTokenSize, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE);
- let pendingResponses: FauxResponseStep[] = [];
- const tokensPerSecond = options.tokensPerSecond;
- const state = { callCount: 0 };
- const promptCache = new Map();
-
- const modelDefinitions = options.models?.length
- ? options.models
- : [
- {
- id: DEFAULT_MODEL_ID,
- name: DEFAULT_MODEL_NAME,
- reasoning: false,
- input: ["text", "image"] as ("text" | "image")[],
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
- contextWindow: 128000,
- maxTokens: 16384,
- },
- ];
- const models = modelDefinitions.map((definition) => ({
- id: definition.id,
- name: definition.name ?? definition.id,
- api,
- provider,
- baseUrl: DEFAULT_BASE_URL,
- reasoning: definition.reasoning ?? false,
- input: definition.input ?? ["text", "image"],
- cost: definition.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
- contextWindow: definition.contextWindow ?? 128000,
- maxTokens: definition.maxTokens ?? 16384,
- })) as [Model, ...Model[]];
-
- const stream: StreamFunction = (requestModel, context, streamOptions) => {
- const outer = createAssistantMessageEventStream();
- const step = pendingResponses.shift();
- state.callCount++;
-
- queueMicrotask(async () => {
- try {
- if (!step) {
- let message = createErrorMessage(
- new Error("No more faux responses queued"),
- api,
- provider,
- requestModel.id,
- );
- message = withUsageEstimate(message, context, streamOptions, promptCache);
- outer.push({ type: "error", reason: "error", error: message });
- outer.end(message);
- return;
- }
-
- const resolved =
- typeof step === "function" ? await step(context, streamOptions, state, requestModel) : step;
- let message = cloneMessage(resolved, api, provider, requestModel.id);
- message = withUsageEstimate(message, context, streamOptions, promptCache);
- await streamWithDeltas(outer, message, minTokenSize, maxTokenSize, tokensPerSecond, streamOptions?.signal);
- } catch (error) {
- const message = createErrorMessage(error, api, provider, requestModel.id);
- outer.push({ type: "error", reason: "error", error: message });
- outer.end(message);
- }
- });
-
- return outer;
- };
-
- const streamSimple: StreamFunction = (streamModel, context, streamOptions) =>
- stream(streamModel, context, streamOptions);
-
- registerApiProvider({ api, stream, streamSimple }, sourceId);
-
- function getModel(): Model;
- function getModel(requestedModelId: string): Model | undefined;
- function getModel(requestedModelId?: string): Model | undefined {
- if (!requestedModelId) {
- return models[0];
- }
- return models.find((candidate) => candidate.id === requestedModelId);
- }
-
- return {
- api,
- models,
- getModel,
- state,
- setResponses(responses) {
- pendingResponses = [...responses];
- },
- appendResponses(responses) {
- pendingResponses.push(...responses);
- },
- getPendingResponseCount() {
- return pendingResponses.length;
- },
- unregister() {
- unregisterApiProviders(sourceId);
- },
- };
-}
diff --git a/pi-mono-reference/packages/ai/src/providers/github-copilot-headers.ts b/pi-mono-reference/packages/ai/src/providers/github-copilot-headers.ts
deleted file mode 100644
index 4f01a9d2..00000000
--- a/pi-mono-reference/packages/ai/src/providers/github-copilot-headers.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import type { Message } from "../types.js";
-
-// Copilot expects X-Initiator to indicate whether the request is user-initiated
-// or agent-initiated (e.g. follow-up after assistant/tool messages).
-export function inferCopilotInitiator(messages: Message[]): "user" | "agent" {
- const last = messages[messages.length - 1];
- return last && last.role !== "user" ? "agent" : "user";
-}
-
-// Copilot requires Copilot-Vision-Request header when sending images
-export function hasCopilotVisionInput(messages: Message[]): boolean {
- return messages.some((msg) => {
- if (msg.role === "user" && Array.isArray(msg.content)) {
- return msg.content.some((c) => c.type === "image");
- }
- if (msg.role === "toolResult" && Array.isArray(msg.content)) {
- return msg.content.some((c) => c.type === "image");
- }
- return false;
- });
-}
-
-export function buildCopilotDynamicHeaders(params: {
- messages: Message[];
- hasImages: boolean;
-}): Record {
- const headers: Record = {
- "X-Initiator": inferCopilotInitiator(params.messages),
- "Openai-Intent": "conversation-edits",
- };
-
- if (params.hasImages) {
- headers["Copilot-Vision-Request"] = "true";
- }
-
- return headers;
-}
diff --git a/pi-mono-reference/packages/ai/src/providers/google-gemini-cli.ts b/pi-mono-reference/packages/ai/src/providers/google-gemini-cli.ts
deleted file mode 100644
index 259ca069..00000000
--- a/pi-mono-reference/packages/ai/src/providers/google-gemini-cli.ts
+++ /dev/null
@@ -1,987 +0,0 @@
-/**
- * Google Gemini CLI / Antigravity provider.
- * Shared implementation for both google-gemini-cli and google-antigravity providers.
- * Uses the Cloud Code Assist API endpoint to access Gemini and Claude models.
- */
-
-import type { Content, ThinkingConfig } from "@google/genai";
-import { calculateCost } from "../models.js";
-import type {
- Api,
- AssistantMessage,
- Context,
- Model,
- SimpleStreamOptions,
- StreamFunction,
- StreamOptions,
- TextContent,
- ThinkingBudgets,
- ThinkingContent,
- ThinkingLevel,
- ToolCall,
-} from "../types.js";
-import { AssistantMessageEventStream } from "../utils/event-stream.js";
-import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
-import {
- convertMessages,
- convertTools,
- isThinkingPart,
- mapStopReasonString,
- mapToolChoice,
- retainThoughtSignature,
-} from "./google-shared.js";
-import { buildBaseOptions, clampReasoning } from "./simple-options.js";
-
-/**
- * Thinking level for Gemini 3 models.
- * Mirrors Google's ThinkingLevel enum values.
- */
-export type GoogleThinkingLevel = "THINKING_LEVEL_UNSPECIFIED" | "MINIMAL" | "LOW" | "MEDIUM" | "HIGH";
-
-export interface GoogleGeminiCliOptions extends StreamOptions {
- toolChoice?: "auto" | "none" | "any";
- /**
- * Thinking/reasoning configuration.
- * - Gemini 2.x models: use `budgetTokens` to set the thinking budget
- * - Gemini 3 models (gemini-3-pro-*, gemini-3-flash-*): use `level` instead
- *
- * When using `streamSimple`, this is handled automatically based on the model.
- */
- thinking?: {
- enabled: boolean;
- /** Thinking budget in tokens. Use for Gemini 2.x models. */
- budgetTokens?: number;
- /** Thinking level. Use for Gemini 3 models (LOW/HIGH for Pro, MINIMAL/LOW/MEDIUM/HIGH for Flash). */
- level?: GoogleThinkingLevel;
- };
- projectId?: string;
-}
-
-const DEFAULT_ENDPOINT = "https://cloudcode-pa.googleapis.com";
-const ANTIGRAVITY_DAILY_ENDPOINT = "https://daily-cloudcode-pa.sandbox.googleapis.com";
-const ANTIGRAVITY_AUTOPUSH_ENDPOINT = "https://autopush-cloudcode-pa.sandbox.googleapis.com";
-const ANTIGRAVITY_ENDPOINT_FALLBACKS = [
- ANTIGRAVITY_DAILY_ENDPOINT,
- ANTIGRAVITY_AUTOPUSH_ENDPOINT,
- DEFAULT_ENDPOINT,
-] as const;
-// Headers for Gemini CLI (prod endpoint)
-const GEMINI_CLI_HEADERS = {
- "User-Agent": "google-cloud-sdk vscode_cloudshelleditor/0.1",
- "X-Goog-Api-Client": "gl-node/22.17.0",
- "Client-Metadata": JSON.stringify({
- ideType: "IDE_UNSPECIFIED",
- platform: "PLATFORM_UNSPECIFIED",
- pluginType: "GEMINI",
- }),
-};
-
-// Headers for Antigravity (sandbox endpoint) - requires specific User-Agent
-const DEFAULT_ANTIGRAVITY_VERSION = "1.21.9";
-
-function getAntigravityHeaders() {
- const version = process.env.PI_AI_ANTIGRAVITY_VERSION || DEFAULT_ANTIGRAVITY_VERSION;
- return {
- "User-Agent": `antigravity/${version} darwin/arm64`,
- };
-}
-
-// Antigravity system instruction (compact version from CLIProxyAPI).
-const ANTIGRAVITY_SYSTEM_INSTRUCTION =
- "You are Antigravity, a powerful agentic AI coding assistant designed by the Google Deepmind team working on Advanced Agentic Coding." +
- "You are pair programming with a USER to solve their coding task. The task may require creating a new codebase, modifying or debugging an existing codebase, or simply answering a question." +
- "**Absolute paths only**" +
- "**Proactiveness**";
-
-// Counter for generating unique tool call IDs
-let toolCallCounter = 0;
-
-// Retry configuration
-const MAX_RETRIES = 3;
-const BASE_DELAY_MS = 1000;
-const MAX_EMPTY_STREAM_RETRIES = 2;
-const EMPTY_STREAM_BASE_DELAY_MS = 500;
-const CLAUDE_THINKING_BETA_HEADER = "interleaved-thinking-2025-05-14";
-
-/**
- * Extract retry delay from Gemini error response (in milliseconds).
- * Checks headers first (Retry-After, x-ratelimit-reset, x-ratelimit-reset-after),
- * then parses body patterns like:
- * - "Your quota will reset after 39s"
- * - "Your quota will reset after 18h31m10s"
- * - "Please retry in Xs" or "Please retry in Xms"
- * - "retryDelay": "34.074824224s" (JSON field)
- */
-export function extractRetryDelay(errorText: string, response?: Response | Headers): number | undefined {
- const normalizeDelay = (ms: number): number | undefined => (ms > 0 ? Math.ceil(ms + 1000) : undefined);
-
- const headers = response instanceof Headers ? response : response?.headers;
- if (headers) {
- const retryAfter = headers.get("retry-after");
- if (retryAfter) {
- const retryAfterSeconds = Number(retryAfter);
- if (Number.isFinite(retryAfterSeconds)) {
- const delay = normalizeDelay(retryAfterSeconds * 1000);
- if (delay !== undefined) {
- return delay;
- }
- }
- const retryAfterDate = new Date(retryAfter);
- const retryAfterMs = retryAfterDate.getTime();
- if (!Number.isNaN(retryAfterMs)) {
- const delay = normalizeDelay(retryAfterMs - Date.now());
- if (delay !== undefined) {
- return delay;
- }
- }
- }
-
- const rateLimitReset = headers.get("x-ratelimit-reset");
- if (rateLimitReset) {
- const resetSeconds = Number.parseInt(rateLimitReset, 10);
- if (!Number.isNaN(resetSeconds)) {
- const delay = normalizeDelay(resetSeconds * 1000 - Date.now());
- if (delay !== undefined) {
- return delay;
- }
- }
- }
-
- const rateLimitResetAfter = headers.get("x-ratelimit-reset-after");
- if (rateLimitResetAfter) {
- const resetAfterSeconds = Number(rateLimitResetAfter);
- if (Number.isFinite(resetAfterSeconds)) {
- const delay = normalizeDelay(resetAfterSeconds * 1000);
- if (delay !== undefined) {
- return delay;
- }
- }
- }
- }
-
- // Pattern 1: "Your quota will reset after ..." (formats: "18h31m10s", "10m15s", "6s", "39s")
- const durationMatch = errorText.match(/reset after (?:(\d+)h)?(?:(\d+)m)?(\d+(?:\.\d+)?)s/i);
- if (durationMatch) {
- const hours = durationMatch[1] ? parseInt(durationMatch[1], 10) : 0;
- const minutes = durationMatch[2] ? parseInt(durationMatch[2], 10) : 0;
- const seconds = parseFloat(durationMatch[3]);
- if (!Number.isNaN(seconds)) {
- const totalMs = ((hours * 60 + minutes) * 60 + seconds) * 1000;
- const delay = normalizeDelay(totalMs);
- if (delay !== undefined) {
- return delay;
- }
- }
- }
-
- // Pattern 2: "Please retry in X[ms|s]"
- const retryInMatch = errorText.match(/Please retry in ([0-9.]+)(ms|s)/i);
- if (retryInMatch?.[1]) {
- const value = parseFloat(retryInMatch[1]);
- if (!Number.isNaN(value) && value > 0) {
- const ms = retryInMatch[2].toLowerCase() === "ms" ? value : value * 1000;
- const delay = normalizeDelay(ms);
- if (delay !== undefined) {
- return delay;
- }
- }
- }
-
- // Pattern 3: "retryDelay": "34.074824224s" (JSON field in error details)
- const retryDelayMatch = errorText.match(/"retryDelay":\s*"([0-9.]+)(ms|s)"/i);
- if (retryDelayMatch?.[1]) {
- const value = parseFloat(retryDelayMatch[1]);
- if (!Number.isNaN(value) && value > 0) {
- const ms = retryDelayMatch[2].toLowerCase() === "ms" ? value : value * 1000;
- const delay = normalizeDelay(ms);
- if (delay !== undefined) {
- return delay;
- }
- }
- }
-
- return undefined;
-}
-
-function needsClaudeThinkingBetaHeader(model: Model<"google-gemini-cli">): boolean {
- return model.provider === "google-antigravity" && model.id.startsWith("claude-") && model.reasoning;
-}
-
-function isGemini3ProModel(modelId: string): boolean {
- return /gemini-3(?:\.1)?-pro/.test(modelId.toLowerCase());
-}
-
-function isGemini3FlashModel(modelId: string): boolean {
- return /gemini-3(?:\.1)?-flash/.test(modelId.toLowerCase());
-}
-
-function isGemini3Model(modelId: string): boolean {
- return isGemini3ProModel(modelId) || isGemini3FlashModel(modelId);
-}
-
-/**
- * Check if an error is retryable (rate limit, server error, network error, etc.)
- */
-function isRetryableError(status: number, errorText: string): boolean {
- if (status === 429 || status === 500 || status === 502 || status === 503 || status === 504) {
- return true;
- }
- return /resource.?exhausted|rate.?limit|overloaded|service.?unavailable|other.?side.?closed/i.test(errorText);
-}
-
-/**
- * Extract a clean, user-friendly error message from Google API error response.
- * Parses JSON error responses and returns just the message field.
- */
-function extractErrorMessage(errorText: string): string {
- try {
- const parsed = JSON.parse(errorText) as { error?: { message?: string } };
- if (parsed.error?.message) {
- return parsed.error.message;
- }
- } catch {
- // Not JSON, return as-is
- }
- return errorText;
-}
-
-/**
- * Sleep for a given number of milliseconds, respecting abort signal.
- */
-function sleep(ms: number, signal?: AbortSignal): Promise {
- return new Promise((resolve, reject) => {
- if (signal?.aborted) {
- reject(new Error("Request was aborted"));
- return;
- }
- const timeout = setTimeout(resolve, ms);
- signal?.addEventListener("abort", () => {
- clearTimeout(timeout);
- reject(new Error("Request was aborted"));
- });
- });
-}
-
-interface CloudCodeAssistRequest {
- project: string;
- model: string;
- request: {
- contents: Content[];
- sessionId?: string;
- systemInstruction?: { role?: string; parts: { text: string }[] };
- generationConfig?: {
- maxOutputTokens?: number;
- temperature?: number;
- thinkingConfig?: ThinkingConfig;
- };
- tools?: ReturnType;
- toolConfig?: {
- functionCallingConfig: {
- mode: ReturnType;
- };
- };
- };
- requestType?: string;
- userAgent?: string;
- requestId?: string;
-}
-
-interface CloudCodeAssistResponseChunk {
- response?: {
- candidates?: Array<{
- content?: {
- role: string;
- parts?: Array<{
- text?: string;
- thought?: boolean;
- thoughtSignature?: string;
- functionCall?: {
- name: string;
- args: Record;
- id?: string;
- };
- }>;
- };
- finishReason?: string;
- }>;
- usageMetadata?: {
- promptTokenCount?: number;
- candidatesTokenCount?: number;
- thoughtsTokenCount?: number;
- totalTokenCount?: number;
- cachedContentTokenCount?: number;
- };
- modelVersion?: string;
- responseId?: string;
- };
- traceId?: string;
-}
-
-export const streamGoogleGeminiCli: StreamFunction<"google-gemini-cli", GoogleGeminiCliOptions> = (
- model: Model<"google-gemini-cli">,
- context: Context,
- options?: GoogleGeminiCliOptions,
-): AssistantMessageEventStream => {
- const stream = new AssistantMessageEventStream();
-
- (async () => {
- const output: AssistantMessage = {
- role: "assistant",
- content: [],
- api: "google-gemini-cli" as Api,
- provider: model.provider,
- model: model.id,
- usage: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- stopReason: "stop",
- timestamp: Date.now(),
- };
-
- try {
- // apiKey is JSON-encoded: { token, projectId }
- const apiKeyRaw = options?.apiKey;
- if (!apiKeyRaw) {
- throw new Error("Google Cloud Code Assist requires OAuth authentication. Use /login to authenticate.");
- }
-
- let accessToken: string;
- let projectId: string;
-
- try {
- const parsed = JSON.parse(apiKeyRaw) as { token: string; projectId: string };
- accessToken = parsed.token;
- projectId = parsed.projectId;
- } catch {
- throw new Error("Invalid Google Cloud Code Assist credentials. Use /login to re-authenticate.");
- }
-
- if (!accessToken || !projectId) {
- throw new Error("Missing token or projectId in Google Cloud credentials. Use /login to re-authenticate.");
- }
-
- const isAntigravity = model.provider === "google-antigravity";
- const baseUrl = model.baseUrl?.trim();
- const endpoints = baseUrl ? [baseUrl] : isAntigravity ? ANTIGRAVITY_ENDPOINT_FALLBACKS : [DEFAULT_ENDPOINT];
-
- let requestBody = buildRequest(model, context, projectId, options, isAntigravity);
- const nextRequestBody = await options?.onPayload?.(requestBody, model);
- if (nextRequestBody !== undefined) {
- requestBody = nextRequestBody as CloudCodeAssistRequest;
- }
- const headers = isAntigravity ? getAntigravityHeaders() : GEMINI_CLI_HEADERS;
-
- const requestHeaders = {
- Authorization: `Bearer ${accessToken}`,
- "Content-Type": "application/json",
- Accept: "text/event-stream",
- ...headers,
- ...(needsClaudeThinkingBetaHeader(model) ? { "anthropic-beta": CLAUDE_THINKING_BETA_HEADER } : {}),
- ...options?.headers,
- };
- const requestBodyJson = JSON.stringify(requestBody);
-
- // Fetch with retry logic for rate limits, transient errors, and endpoint fallbacks.
- // On 403/404, immediately try the next endpoint (no delay).
- // On 429/5xx, retry with backoff on the same or next endpoint.
- let response: Response | undefined;
- let lastError: Error | undefined;
- let requestUrl: string | undefined;
- let endpointIndex = 0;
-
- for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
- if (options?.signal?.aborted) {
- throw new Error("Request was aborted");
- }
-
- try {
- const endpoint = endpoints[endpointIndex];
- requestUrl = `${endpoint}/v1internal:streamGenerateContent?alt=sse`;
- response = await fetch(requestUrl, {
- method: "POST",
- headers: requestHeaders,
- body: requestBodyJson,
- signal: options?.signal,
- });
-
- if (response.ok) {
- break; // Success, exit retry loop
- }
-
- const errorText = await response.text();
-
- // On 403/404, cascade to the next endpoint immediately (no delay)
- if ((response.status === 403 || response.status === 404) && endpointIndex < endpoints.length - 1) {
- endpointIndex++;
- continue;
- }
-
- // Check if retryable (429, 5xx, network patterns)
- if (attempt < MAX_RETRIES && isRetryableError(response.status, errorText)) {
- // Advance endpoint if possible
- if (endpointIndex < endpoints.length - 1) {
- endpointIndex++;
- }
-
- // Use server-provided delay or exponential backoff
- const serverDelay = extractRetryDelay(errorText, response);
- const delayMs = serverDelay ?? BASE_DELAY_MS * 2 ** attempt;
-
- // Check if server delay exceeds max allowed (default: 60s)
- const maxDelayMs = options?.maxRetryDelayMs ?? 60000;
- if (maxDelayMs > 0 && serverDelay && serverDelay > maxDelayMs) {
- const delaySeconds = Math.ceil(serverDelay / 1000);
- throw new Error(
- `Server requested ${delaySeconds}s retry delay (max: ${Math.ceil(maxDelayMs / 1000)}s). ${extractErrorMessage(errorText)}`,
- );
- }
-
- await sleep(delayMs, options?.signal);
- continue;
- }
-
- // Not retryable or max retries exceeded
- throw new Error(`Cloud Code Assist API error (${response.status}): ${extractErrorMessage(errorText)}`);
- } catch (error) {
- // Check for abort - fetch throws AbortError, our code throws "Request was aborted"
- if (error instanceof Error) {
- if (error.name === "AbortError" || error.message === "Request was aborted") {
- throw new Error("Request was aborted");
- }
- }
- // Extract detailed error message from fetch errors (Node includes cause)
- lastError = error instanceof Error ? error : new Error(String(error));
- if (lastError.message === "fetch failed" && lastError.cause instanceof Error) {
- lastError = new Error(`Network error: ${lastError.cause.message}`);
- }
- // Network errors are retryable
- if (attempt < MAX_RETRIES) {
- const delayMs = BASE_DELAY_MS * 2 ** attempt;
- await sleep(delayMs, options?.signal);
- continue;
- }
- throw lastError;
- }
- }
-
- if (!response || !response.ok) {
- throw lastError ?? new Error("Failed to get response after retries");
- }
-
- let started = false;
- const ensureStarted = () => {
- if (!started) {
- stream.push({ type: "start", partial: output });
- started = true;
- }
- };
-
- const resetOutput = () => {
- output.content = [];
- output.usage = {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- };
- output.stopReason = "stop";
- output.errorMessage = undefined;
- output.timestamp = Date.now();
- started = false;
- };
-
- const streamResponse = async (activeResponse: Response): Promise => {
- if (!activeResponse.body) {
- throw new Error("No response body");
- }
-
- let hasContent = false;
- let currentBlock: TextContent | ThinkingContent | null = null;
- const blocks = output.content;
- const blockIndex = () => blocks.length - 1;
-
- // Read SSE stream
- const reader = activeResponse.body.getReader();
- const decoder = new TextDecoder();
- let buffer = "";
-
- // Set up abort handler to cancel reader when signal fires
- const abortHandler = () => {
- void reader.cancel().catch(() => {});
- };
- options?.signal?.addEventListener("abort", abortHandler);
-
- try {
- while (true) {
- // Check abort signal before each read
- if (options?.signal?.aborted) {
- throw new Error("Request was aborted");
- }
-
- const { done, value } = await reader.read();
- if (done) break;
-
- buffer += decoder.decode(value, { stream: true });
- const lines = buffer.split("\n");
- buffer = lines.pop() || "";
-
- for (const line of lines) {
- if (!line.startsWith("data:")) continue;
-
- const jsonStr = line.slice(5).trim();
- if (!jsonStr) continue;
-
- let chunk: CloudCodeAssistResponseChunk;
- try {
- chunk = JSON.parse(jsonStr);
- } catch {
- continue;
- }
-
- // Unwrap the response
- const responseData = chunk.response;
- if (!responseData) continue;
- // Cloud Code Assist mirrors Gemini's responseId field. Keep the first non-empty one.
- // A single streamed response should retain the same ID across chunks.
- output.responseId ||= responseData.responseId;
-
- const candidate = responseData.candidates?.[0];
- if (candidate?.content?.parts) {
- for (const part of candidate.content.parts) {
- if (part.text !== undefined) {
- hasContent = true;
- const isThinking = isThinkingPart(part);
- if (
- !currentBlock ||
- (isThinking && currentBlock.type !== "thinking") ||
- (!isThinking && currentBlock.type !== "text")
- ) {
- if (currentBlock) {
- if (currentBlock.type === "text") {
- stream.push({
- type: "text_end",
- contentIndex: blocks.length - 1,
- content: currentBlock.text,
- partial: output,
- });
- } else {
- stream.push({
- type: "thinking_end",
- contentIndex: blockIndex(),
- content: currentBlock.thinking,
- partial: output,
- });
- }
- }
- if (isThinking) {
- currentBlock = { type: "thinking", thinking: "", thinkingSignature: undefined };
- output.content.push(currentBlock);
- ensureStarted();
- stream.push({
- type: "thinking_start",
- contentIndex: blockIndex(),
- partial: output,
- });
- } else {
- currentBlock = { type: "text", text: "" };
- output.content.push(currentBlock);
- ensureStarted();
- stream.push({ type: "text_start", contentIndex: blockIndex(), partial: output });
- }
- }
- if (currentBlock.type === "thinking") {
- currentBlock.thinking += part.text;
- currentBlock.thinkingSignature = retainThoughtSignature(
- currentBlock.thinkingSignature,
- part.thoughtSignature,
- );
- stream.push({
- type: "thinking_delta",
- contentIndex: blockIndex(),
- delta: part.text,
- partial: output,
- });
- } else {
- currentBlock.text += part.text;
- currentBlock.textSignature = retainThoughtSignature(
- currentBlock.textSignature,
- part.thoughtSignature,
- );
- stream.push({
- type: "text_delta",
- contentIndex: blockIndex(),
- delta: part.text,
- partial: output,
- });
- }
- }
-
- if (part.functionCall) {
- hasContent = true;
- if (currentBlock) {
- if (currentBlock.type === "text") {
- stream.push({
- type: "text_end",
- contentIndex: blockIndex(),
- content: currentBlock.text,
- partial: output,
- });
- } else {
- stream.push({
- type: "thinking_end",
- contentIndex: blockIndex(),
- content: currentBlock.thinking,
- partial: output,
- });
- }
- currentBlock = null;
- }
-
- const providedId = part.functionCall.id;
- const needsNewId =
- !providedId ||
- output.content.some((b) => b.type === "toolCall" && b.id === providedId);
- const toolCallId = needsNewId
- ? `${part.functionCall.name}_${Date.now()}_${++toolCallCounter}`
- : providedId;
-
- const toolCall: ToolCall = {
- type: "toolCall",
- id: toolCallId,
- name: part.functionCall.name || "",
- arguments: (part.functionCall.args as Record) ?? {},
- ...(part.thoughtSignature && { thoughtSignature: part.thoughtSignature }),
- };
-
- output.content.push(toolCall);
- ensureStarted();
- stream.push({ type: "toolcall_start", contentIndex: blockIndex(), partial: output });
- stream.push({
- type: "toolcall_delta",
- contentIndex: blockIndex(),
- delta: JSON.stringify(toolCall.arguments),
- partial: output,
- });
- stream.push({
- type: "toolcall_end",
- contentIndex: blockIndex(),
- toolCall,
- partial: output,
- });
- }
- }
- }
-
- if (candidate?.finishReason) {
- output.stopReason = mapStopReasonString(candidate.finishReason);
- if (output.content.some((b) => b.type === "toolCall")) {
- output.stopReason = "toolUse";
- }
- }
-
- if (responseData.usageMetadata) {
- // promptTokenCount includes cachedContentTokenCount, so subtract to get fresh input
- const promptTokens = responseData.usageMetadata.promptTokenCount || 0;
- const cacheReadTokens = responseData.usageMetadata.cachedContentTokenCount || 0;
- output.usage = {
- input: promptTokens - cacheReadTokens,
- output:
- (responseData.usageMetadata.candidatesTokenCount || 0) +
- (responseData.usageMetadata.thoughtsTokenCount || 0),
- cacheRead: cacheReadTokens,
- cacheWrite: 0,
- totalTokens: responseData.usageMetadata.totalTokenCount || 0,
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- total: 0,
- },
- };
- calculateCost(model, output.usage);
- }
- }
- }
- } finally {
- options?.signal?.removeEventListener("abort", abortHandler);
- }
-
- if (currentBlock) {
- if (currentBlock.type === "text") {
- stream.push({
- type: "text_end",
- contentIndex: blockIndex(),
- content: currentBlock.text,
- partial: output,
- });
- } else {
- stream.push({
- type: "thinking_end",
- contentIndex: blockIndex(),
- content: currentBlock.thinking,
- partial: output,
- });
- }
- }
-
- return hasContent;
- };
-
- let receivedContent = false;
- let currentResponse = response;
-
- for (let emptyAttempt = 0; emptyAttempt <= MAX_EMPTY_STREAM_RETRIES; emptyAttempt++) {
- if (options?.signal?.aborted) {
- throw new Error("Request was aborted");
- }
-
- if (emptyAttempt > 0) {
- const backoffMs = EMPTY_STREAM_BASE_DELAY_MS * 2 ** (emptyAttempt - 1);
- await sleep(backoffMs, options?.signal);
-
- if (!requestUrl) {
- throw new Error("Missing request URL");
- }
-
- currentResponse = await fetch(requestUrl, {
- method: "POST",
- headers: requestHeaders,
- body: requestBodyJson,
- signal: options?.signal,
- });
-
- if (!currentResponse.ok) {
- const retryErrorText = await currentResponse.text();
- throw new Error(`Cloud Code Assist API error (${currentResponse.status}): ${retryErrorText}`);
- }
- }
-
- const streamed = await streamResponse(currentResponse);
- if (streamed) {
- receivedContent = true;
- break;
- }
-
- if (emptyAttempt < MAX_EMPTY_STREAM_RETRIES) {
- resetOutput();
- }
- }
-
- if (!receivedContent) {
- throw new Error("Cloud Code Assist API returned an empty response");
- }
-
- if (options?.signal?.aborted) {
- throw new Error("Request was aborted");
- }
-
- if (output.stopReason === "aborted" || output.stopReason === "error") {
- throw new Error("An unknown error occurred");
- }
-
- stream.push({ type: "done", reason: output.stopReason, message: output });
- stream.end();
- } catch (error) {
- for (const block of output.content) {
- if ("index" in block) {
- delete (block as { index?: number }).index;
- }
- }
- output.stopReason = options?.signal?.aborted ? "aborted" : "error";
- output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
- stream.push({ type: "error", reason: output.stopReason, error: output });
- stream.end();
- }
- })();
-
- return stream;
-};
-
-export const streamSimpleGoogleGeminiCli: StreamFunction<"google-gemini-cli", SimpleStreamOptions> = (
- model: Model<"google-gemini-cli">,
- context: Context,
- options?: SimpleStreamOptions,
-): AssistantMessageEventStream => {
- const apiKey = options?.apiKey;
- if (!apiKey) {
- throw new Error("Google Cloud Code Assist requires OAuth authentication. Use /login to authenticate.");
- }
-
- const base = buildBaseOptions(model, options, apiKey);
- if (!options?.reasoning) {
- return streamGoogleGeminiCli(model, context, {
- ...base,
- thinking: { enabled: false },
- } satisfies GoogleGeminiCliOptions);
- }
-
- const effort = clampReasoning(options.reasoning)!;
- if (isGemini3Model(model.id)) {
- return streamGoogleGeminiCli(model, context, {
- ...base,
- thinking: {
- enabled: true,
- level: getGeminiCliThinkingLevel(effort, model.id),
- },
- } satisfies GoogleGeminiCliOptions);
- }
-
- const defaultBudgets: ThinkingBudgets = {
- minimal: 1024,
- low: 2048,
- medium: 8192,
- high: 16384,
- };
- const budgets = { ...defaultBudgets, ...options.thinkingBudgets };
-
- const minOutputTokens = 1024;
- let thinkingBudget = budgets[effort]!;
- const maxTokens = Math.min((base.maxTokens || 0) + thinkingBudget, model.maxTokens);
-
- if (maxTokens <= thinkingBudget) {
- thinkingBudget = Math.max(0, maxTokens - minOutputTokens);
- }
-
- return streamGoogleGeminiCli(model, context, {
- ...base,
- maxTokens,
- thinking: {
- enabled: true,
- budgetTokens: thinkingBudget,
- },
- } satisfies GoogleGeminiCliOptions);
-};
-
-export function buildRequest(
- model: Model<"google-gemini-cli">,
- context: Context,
- projectId: string,
- options: GoogleGeminiCliOptions = {},
- isAntigravity = false,
-): CloudCodeAssistRequest {
- const contents = convertMessages(model, context);
-
- const generationConfig: CloudCodeAssistRequest["request"]["generationConfig"] = {};
- if (options.temperature !== undefined) {
- generationConfig.temperature = options.temperature;
- }
- if (options.maxTokens !== undefined) {
- generationConfig.maxOutputTokens = options.maxTokens;
- }
-
- // Thinking config
- if (options.thinking?.enabled && model.reasoning) {
- generationConfig.thinkingConfig = {
- includeThoughts: true,
- };
- // Gemini 3 models use thinkingLevel, older models use thinkingBudget
- if (options.thinking.level !== undefined) {
- // Cast to any since our GoogleThinkingLevel mirrors Google's ThinkingLevel enum values
- generationConfig.thinkingConfig.thinkingLevel = options.thinking.level as any;
- } else if (options.thinking.budgetTokens !== undefined) {
- generationConfig.thinkingConfig.thinkingBudget = options.thinking.budgetTokens;
- }
- } else if (model.reasoning && options.thinking && !options.thinking.enabled) {
- generationConfig.thinkingConfig = getDisabledThinkingConfig(model.id);
- }
-
- const request: CloudCodeAssistRequest["request"] = {
- contents,
- };
-
- request.sessionId = options.sessionId;
-
- // System instruction must be object with parts, not plain string
- if (context.systemPrompt) {
- request.systemInstruction = {
- parts: [{ text: sanitizeSurrogates(context.systemPrompt) }],
- };
- }
-
- if (Object.keys(generationConfig).length > 0) {
- request.generationConfig = generationConfig;
- }
-
- if (context.tools && context.tools.length > 0) {
- // Claude models on Cloud Code Assist need the legacy `parameters` field;
- // the API translates it into Anthropic's `input_schema`.
- const useParameters = model.id.startsWith("claude-");
- request.tools = convertTools(context.tools, useParameters);
- if (options.toolChoice) {
- request.toolConfig = {
- functionCallingConfig: {
- mode: mapToolChoice(options.toolChoice),
- },
- };
- }
- }
-
- if (isAntigravity) {
- const existingParts = request.systemInstruction?.parts ?? [];
- request.systemInstruction = {
- role: "user",
- parts: [
- { text: ANTIGRAVITY_SYSTEM_INSTRUCTION },
- { text: `Please ignore following [ignore]${ANTIGRAVITY_SYSTEM_INSTRUCTION}[/ignore]` },
- ...existingParts,
- ],
- };
- }
-
- return {
- project: projectId,
- model: model.id,
- request,
- ...(isAntigravity ? { requestType: "agent" } : {}),
- userAgent: isAntigravity ? "antigravity" : "pi-coding-agent",
- requestId: `${isAntigravity ? "agent" : "pi"}-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
- };
-}
-
-type ClampedThinkingLevel = Exclude;
-
-function getDisabledThinkingConfig(modelId: string): ThinkingConfig {
- // Google docs: Gemini 3.1 Pro cannot disable thinking, and Gemini 3 Flash / Flash-Lite
- // do not support full thinking-off either. For Gemini 3 models, use the lowest supported
- // thinkingLevel without includeThoughts so hidden thinking remains invisible to pi.
- if (isGemini3ProModel(modelId)) {
- return { thinkingLevel: "LOW" as any };
- }
- if (isGemini3FlashModel(modelId)) {
- return { thinkingLevel: "MINIMAL" as any };
- }
-
- // Gemini 2.x supports disabling via thinkingBudget = 0.
- return { thinkingBudget: 0 };
-}
-
-function getGeminiCliThinkingLevel(effort: ClampedThinkingLevel, modelId: string): GoogleThinkingLevel {
- if (isGemini3ProModel(modelId)) {
- switch (effort) {
- case "minimal":
- case "low":
- return "LOW";
- case "medium":
- case "high":
- return "HIGH";
- }
- }
- switch (effort) {
- case "minimal":
- return "MINIMAL";
- case "low":
- return "LOW";
- case "medium":
- return "MEDIUM";
- case "high":
- return "HIGH";
- }
-}
diff --git a/pi-mono-reference/packages/ai/src/providers/google-shared.ts b/pi-mono-reference/packages/ai/src/providers/google-shared.ts
deleted file mode 100644
index 57b59238..00000000
--- a/pi-mono-reference/packages/ai/src/providers/google-shared.ts
+++ /dev/null
@@ -1,326 +0,0 @@
-/**
- * Shared utilities for Google Generative AI and Google Cloud Code Assist providers.
- */
-
-import { type Content, FinishReason, FunctionCallingConfigMode, type Part } from "@google/genai";
-import type { Context, ImageContent, Model, StopReason, TextContent, Tool } from "../types.js";
-import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
-import { transformMessages } from "./transform-messages.js";
-
-type GoogleApiType = "google-generative-ai" | "google-gemini-cli" | "google-vertex";
-
-/**
- * Determines whether a streamed Gemini `Part` should be treated as "thinking".
- *
- * Protocol note (Gemini / Vertex AI thought signatures):
- * - `thought: true` is the definitive marker for thinking content (thought summaries).
- * - `thoughtSignature` is an encrypted representation of the model's internal thought process
- * used to preserve reasoning context across multi-turn interactions.
- * - `thoughtSignature` can appear on ANY part type (text, functionCall, etc.) - it does NOT
- * indicate the part itself is thinking content.
- * - For non-functionCall responses, the signature appears on the last part for context replay.
- * - When persisting/replaying model outputs, signature-bearing parts must be preserved as-is;
- * do not merge/move signatures across parts.
- *
- * See: https://ai.google.dev/gemini-api/docs/thought-signatures
- */
-export function isThinkingPart(part: Pick): boolean {
- return part.thought === true;
-}
-
-/**
- * Retain thought signatures during streaming.
- *
- * Some backends only send `thoughtSignature` on the first delta for a given part/block; later deltas may omit it.
- * This helper preserves the last non-empty signature for the current block.
- *
- * Note: this does NOT merge or move signatures across distinct response parts. It only prevents
- * a signature from being overwritten with `undefined` within the same streamed block.
- */
-export function retainThoughtSignature(existing: string | undefined, incoming: string | undefined): string | undefined {
- if (typeof incoming === "string" && incoming.length > 0) return incoming;
- return existing;
-}
-
-// Thought signatures must be base64 for Google APIs (TYPE_BYTES).
-const base64SignaturePattern = /^[A-Za-z0-9+/]+={0,2}$/;
-
-// Sentinel value that tells the Gemini API to skip thought signature validation.
-// Used for unsigned function call parts (e.g. replayed from providers without thought signatures).
-// See: https://ai.google.dev/gemini-api/docs/thought-signatures
-const SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
-
-function isValidThoughtSignature(signature: string | undefined): boolean {
- if (!signature) return false;
- if (signature.length % 4 !== 0) return false;
- return base64SignaturePattern.test(signature);
-}
-
-/**
- * Only keep signatures from the same provider/model and with valid base64.
- */
-function resolveThoughtSignature(isSameProviderAndModel: boolean, signature: string | undefined): string | undefined {
- return isSameProviderAndModel && isValidThoughtSignature(signature) ? signature : undefined;
-}
-
-/**
- * Models via Google APIs that require explicit tool call IDs in function calls/responses.
- */
-export function requiresToolCallId(modelId: string): boolean {
- return modelId.startsWith("claude-") || modelId.startsWith("gpt-oss-");
-}
-
-function getGeminiMajorVersion(modelId: string): number | undefined {
- const match = modelId.toLowerCase().match(/^gemini(?:-live)?-(\d+)/);
- if (!match) return undefined;
- return Number.parseInt(match[1], 10);
-}
-
-function supportsMultimodalFunctionResponse(modelId: string): boolean {
- const geminiMajorVersion = getGeminiMajorVersion(modelId);
- if (geminiMajorVersion !== undefined) {
- return geminiMajorVersion >= 3;
- }
- return true;
-}
-
-/**
- * Convert internal messages to Gemini Content[] format.
- */
-export function convertMessages(model: Model, context: Context): Content[] {
- const contents: Content[] = [];
- const normalizeToolCallId = (id: string): string => {
- if (!requiresToolCallId(model.id)) return id;
- return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
- };
-
- const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
-
- for (const msg of transformedMessages) {
- if (msg.role === "user") {
- if (typeof msg.content === "string") {
- contents.push({
- role: "user",
- parts: [{ text: sanitizeSurrogates(msg.content) }],
- });
- } else {
- const parts: Part[] = msg.content.map((item) => {
- if (item.type === "text") {
- return { text: sanitizeSurrogates(item.text) };
- } else {
- return {
- inlineData: {
- mimeType: item.mimeType,
- data: item.data,
- },
- };
- }
- });
- const filteredParts = !model.input.includes("image") ? parts.filter((p) => p.text !== undefined) : parts;
- if (filteredParts.length === 0) continue;
- contents.push({
- role: "user",
- parts: filteredParts,
- });
- }
- } else if (msg.role === "assistant") {
- const parts: Part[] = [];
- // Check if message is from same provider and model - only then keep thinking blocks
- const isSameProviderAndModel = msg.provider === model.provider && msg.model === model.id;
-
- for (const block of msg.content) {
- if (block.type === "text") {
- // Skip empty text blocks - they can cause issues with some models (e.g. Claude via Antigravity)
- if (!block.text || block.text.trim() === "") continue;
- const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.textSignature);
- parts.push({
- text: sanitizeSurrogates(block.text),
- ...(thoughtSignature && { thoughtSignature }),
- });
- } else if (block.type === "thinking") {
- // Skip empty thinking blocks
- if (!block.thinking || block.thinking.trim() === "") continue;
- // Only keep as thinking block if same provider AND same model
- // Otherwise convert to plain text (no tags to avoid model mimicking them)
- if (isSameProviderAndModel) {
- const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.thinkingSignature);
- parts.push({
- thought: true,
- text: sanitizeSurrogates(block.thinking),
- ...(thoughtSignature && { thoughtSignature }),
- });
- } else {
- parts.push({
- text: sanitizeSurrogates(block.thinking),
- });
- }
- } else if (block.type === "toolCall") {
- const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.thoughtSignature);
- // Gemini 3 requires thoughtSignature on all function calls when thinking mode is enabled.
- // Use the skip_thought_signature_validator sentinel for unsigned function calls
- // (e.g. replayed from providers without thought signatures like Claude via Antigravity).
- const isGemini3 = model.id.toLowerCase().includes("gemini-3");
- const effectiveSignature = thoughtSignature || (isGemini3 ? SKIP_THOUGHT_SIGNATURE : undefined);
- const part: Part = {
- functionCall: {
- name: block.name,
- args: block.arguments ?? {},
- ...(requiresToolCallId(model.id) ? { id: block.id } : {}),
- },
- ...(effectiveSignature && { thoughtSignature: effectiveSignature }),
- };
- parts.push(part);
- }
- }
-
- if (parts.length === 0) continue;
- contents.push({
- role: "model",
- parts,
- });
- } else if (msg.role === "toolResult") {
- // Extract text and image content
- const textContent = msg.content.filter((c): c is TextContent => c.type === "text");
- const textResult = textContent.map((c) => c.text).join("\n");
- const imageContent = model.input.includes("image")
- ? msg.content.filter((c): c is ImageContent => c.type === "image")
- : [];
-
- const hasText = textResult.length > 0;
- const hasImages = imageContent.length > 0;
-
- // Gemini 3+ models support multimodal function responses with images nested inside
- // functionResponse.parts. Claude and other non-Gemini models behind Cloud Code Assist /
- // Antigravity also accept this shape. Gemini < 3 still needs a separate user image turn.
- const modelSupportsMultimodalFunctionResponse = supportsMultimodalFunctionResponse(model.id);
-
- // Use "output" key for success, "error" key for errors as per SDK documentation
- const responseValue = hasText ? sanitizeSurrogates(textResult) : hasImages ? "(see attached image)" : "";
-
- const imageParts: Part[] = imageContent.map((imageBlock) => ({
- inlineData: {
- mimeType: imageBlock.mimeType,
- data: imageBlock.data,
- },
- }));
-
- const includeId = requiresToolCallId(model.id);
- const functionResponsePart: Part = {
- functionResponse: {
- name: msg.toolName,
- response: msg.isError ? { error: responseValue } : { output: responseValue },
- ...(hasImages && modelSupportsMultimodalFunctionResponse && { parts: imageParts }),
- ...(includeId ? { id: msg.toolCallId } : {}),
- },
- };
-
- // Cloud Code Assist API requires all function responses to be in a single user turn.
- // Check if the last content is already a user turn with function responses and merge.
- const lastContent = contents[contents.length - 1];
- if (lastContent?.role === "user" && lastContent.parts?.some((p) => p.functionResponse)) {
- lastContent.parts.push(functionResponsePart);
- } else {
- contents.push({
- role: "user",
- parts: [functionResponsePart],
- });
- }
-
- // For Gemini < 3, add images in a separate user message
- if (hasImages && !modelSupportsMultimodalFunctionResponse) {
- contents.push({
- role: "user",
- parts: [{ text: "Tool result image:" }, ...imageParts],
- });
- }
- }
- }
-
- return contents;
-}
-
-/**
- * Convert tools to Gemini function declarations format.
- *
- * By default uses `parametersJsonSchema` which supports full JSON Schema (including
- * anyOf, oneOf, const, etc.). Set `useParameters` to true to use the legacy `parameters`
- * field instead (OpenAPI 3.03 Schema). This is needed for Cloud Code Assist with Claude
- * models, where the API translates `parameters` into Anthropic's `input_schema`.
- */
-export function convertTools(
- tools: Tool[],
- useParameters = false,
-): { functionDeclarations: Record[] }[] | undefined {
- if (tools.length === 0) return undefined;
- return [
- {
- functionDeclarations: tools.map((tool) => ({
- name: tool.name,
- description: tool.description,
- ...(useParameters ? { parameters: tool.parameters } : { parametersJsonSchema: tool.parameters }),
- })),
- },
- ];
-}
-
-/**
- * Map tool choice string to Gemini FunctionCallingConfigMode.
- */
-export function mapToolChoice(choice: string): FunctionCallingConfigMode {
- switch (choice) {
- case "auto":
- return FunctionCallingConfigMode.AUTO;
- case "none":
- return FunctionCallingConfigMode.NONE;
- case "any":
- return FunctionCallingConfigMode.ANY;
- default:
- return FunctionCallingConfigMode.AUTO;
- }
-}
-
-/**
- * Map Gemini FinishReason to our StopReason.
- */
-export function mapStopReason(reason: FinishReason): StopReason {
- switch (reason) {
- case FinishReason.STOP:
- return "stop";
- case FinishReason.MAX_TOKENS:
- return "length";
- case FinishReason.BLOCKLIST:
- case FinishReason.PROHIBITED_CONTENT:
- case FinishReason.SPII:
- case FinishReason.SAFETY:
- case FinishReason.IMAGE_SAFETY:
- case FinishReason.IMAGE_PROHIBITED_CONTENT:
- case FinishReason.IMAGE_RECITATION:
- case FinishReason.IMAGE_OTHER:
- case FinishReason.RECITATION:
- case FinishReason.FINISH_REASON_UNSPECIFIED:
- case FinishReason.OTHER:
- case FinishReason.LANGUAGE:
- case FinishReason.MALFORMED_FUNCTION_CALL:
- case FinishReason.UNEXPECTED_TOOL_CALL:
- case FinishReason.NO_IMAGE:
- return "error";
- default: {
- const _exhaustive: never = reason;
- throw new Error(`Unhandled stop reason: ${_exhaustive}`);
- }
- }
-}
-
-/**
- * Map string finish reason to our StopReason (for raw API responses).
- */
-export function mapStopReasonString(reason: string): StopReason {
- switch (reason) {
- case "STOP":
- return "stop";
- case "MAX_TOKENS":
- return "length";
- default:
- return "error";
- }
-}
diff --git a/pi-mono-reference/packages/ai/src/providers/google-vertex.ts b/pi-mono-reference/packages/ai/src/providers/google-vertex.ts
deleted file mode 100644
index 4e52be08..00000000
--- a/pi-mono-reference/packages/ai/src/providers/google-vertex.ts
+++ /dev/null
@@ -1,543 +0,0 @@
-import {
- type GenerateContentConfig,
- type GenerateContentParameters,
- GoogleGenAI,
- type ThinkingConfig,
- ThinkingLevel,
-} from "@google/genai";
-import { calculateCost } from "../models.js";
-import type {
- Api,
- AssistantMessage,
- Context,
- Model,
- ThinkingLevel as PiThinkingLevel,
- SimpleStreamOptions,
- StreamFunction,
- StreamOptions,
- TextContent,
- ThinkingBudgets,
- ThinkingContent,
- ToolCall,
-} from "../types.js";
-import { AssistantMessageEventStream } from "../utils/event-stream.js";
-import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
-import type { GoogleThinkingLevel } from "./google-gemini-cli.js";
-import {
- convertMessages,
- convertTools,
- isThinkingPart,
- mapStopReason,
- mapToolChoice,
- retainThoughtSignature,
-} from "./google-shared.js";
-import { buildBaseOptions, clampReasoning } from "./simple-options.js";
-
-export interface GoogleVertexOptions extends StreamOptions {
- toolChoice?: "auto" | "none" | "any";
- thinking?: {
- enabled: boolean;
- budgetTokens?: number; // -1 for dynamic, 0 to disable
- level?: GoogleThinkingLevel;
- };
- project?: string;
- location?: string;
-}
-
-const API_VERSION = "v1";
-const GCP_VERTEX_CREDENTIALS_MARKER = "gcp-vertex-credentials";
-
-const THINKING_LEVEL_MAP: Record = {
- THINKING_LEVEL_UNSPECIFIED: ThinkingLevel.THINKING_LEVEL_UNSPECIFIED,
- MINIMAL: ThinkingLevel.MINIMAL,
- LOW: ThinkingLevel.LOW,
- MEDIUM: ThinkingLevel.MEDIUM,
- HIGH: ThinkingLevel.HIGH,
-};
-
-// Counter for generating unique tool call IDs
-let toolCallCounter = 0;
-
-export const streamGoogleVertex: StreamFunction<"google-vertex", GoogleVertexOptions> = (
- model: Model<"google-vertex">,
- context: Context,
- options?: GoogleVertexOptions,
-): AssistantMessageEventStream => {
- const stream = new AssistantMessageEventStream();
-
- (async () => {
- const output: AssistantMessage = {
- role: "assistant",
- content: [],
- api: "google-vertex" as Api,
- provider: model.provider,
- model: model.id,
- usage: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- stopReason: "stop",
- timestamp: Date.now(),
- };
-
- try {
- const apiKey = resolveApiKey(options);
- // Create the client using either a Vertex API key, if provided, or ADC with project and location
- const client = apiKey
- ? createClientWithApiKey(model, apiKey, options?.headers)
- : createClient(model, resolveProject(options), resolveLocation(options), options?.headers);
- let params = buildParams(model, context, options);
- const nextParams = await options?.onPayload?.(params, model);
- if (nextParams !== undefined) {
- params = nextParams as GenerateContentParameters;
- }
- const googleStream = await client.models.generateContentStream(params);
-
- stream.push({ type: "start", partial: output });
- let currentBlock: TextContent | ThinkingContent | null = null;
- const blocks = output.content;
- const blockIndex = () => blocks.length - 1;
- for await (const chunk of googleStream) {
- // Vertex uses the same @google/genai GenerateContentResponse type as Gemini.
- // responseId is documented there as an output-only identifier for each response.
- output.responseId ||= chunk.responseId;
- const candidate = chunk.candidates?.[0];
- if (candidate?.content?.parts) {
- for (const part of candidate.content.parts) {
- if (part.text !== undefined) {
- const isThinking = isThinkingPart(part);
- if (
- !currentBlock ||
- (isThinking && currentBlock.type !== "thinking") ||
- (!isThinking && currentBlock.type !== "text")
- ) {
- if (currentBlock) {
- if (currentBlock.type === "text") {
- stream.push({
- type: "text_end",
- contentIndex: blocks.length - 1,
- content: currentBlock.text,
- partial: output,
- });
- } else {
- stream.push({
- type: "thinking_end",
- contentIndex: blockIndex(),
- content: currentBlock.thinking,
- partial: output,
- });
- }
- }
- if (isThinking) {
- currentBlock = { type: "thinking", thinking: "", thinkingSignature: undefined };
- output.content.push(currentBlock);
- stream.push({ type: "thinking_start", contentIndex: blockIndex(), partial: output });
- } else {
- currentBlock = { type: "text", text: "" };
- output.content.push(currentBlock);
- stream.push({ type: "text_start", contentIndex: blockIndex(), partial: output });
- }
- }
- if (currentBlock.type === "thinking") {
- currentBlock.thinking += part.text;
- currentBlock.thinkingSignature = retainThoughtSignature(
- currentBlock.thinkingSignature,
- part.thoughtSignature,
- );
- stream.push({
- type: "thinking_delta",
- contentIndex: blockIndex(),
- delta: part.text,
- partial: output,
- });
- } else {
- currentBlock.text += part.text;
- currentBlock.textSignature = retainThoughtSignature(
- currentBlock.textSignature,
- part.thoughtSignature,
- );
- stream.push({
- type: "text_delta",
- contentIndex: blockIndex(),
- delta: part.text,
- partial: output,
- });
- }
- }
-
- if (part.functionCall) {
- if (currentBlock) {
- if (currentBlock.type === "text") {
- stream.push({
- type: "text_end",
- contentIndex: blockIndex(),
- content: currentBlock.text,
- partial: output,
- });
- } else {
- stream.push({
- type: "thinking_end",
- contentIndex: blockIndex(),
- content: currentBlock.thinking,
- partial: output,
- });
- }
- currentBlock = null;
- }
-
- const providedId = part.functionCall.id;
- const needsNewId =
- !providedId || output.content.some((b) => b.type === "toolCall" && b.id === providedId);
- const toolCallId = needsNewId
- ? `${part.functionCall.name}_${Date.now()}_${++toolCallCounter}`
- : providedId;
-
- const toolCall: ToolCall = {
- type: "toolCall",
- id: toolCallId,
- name: part.functionCall.name || "",
- arguments: (part.functionCall.args as Record) ?? {},
- ...(part.thoughtSignature && { thoughtSignature: part.thoughtSignature }),
- };
-
- output.content.push(toolCall);
- stream.push({ type: "toolcall_start", contentIndex: blockIndex(), partial: output });
- stream.push({
- type: "toolcall_delta",
- contentIndex: blockIndex(),
- delta: JSON.stringify(toolCall.arguments),
- partial: output,
- });
- stream.push({ type: "toolcall_end", contentIndex: blockIndex(), toolCall, partial: output });
- }
- }
- }
-
- if (candidate?.finishReason) {
- output.stopReason = mapStopReason(candidate.finishReason);
- if (output.content.some((b) => b.type === "toolCall")) {
- output.stopReason = "toolUse";
- }
- }
-
- if (chunk.usageMetadata) {
- output.usage = {
- input:
- (chunk.usageMetadata.promptTokenCount || 0) - (chunk.usageMetadata.cachedContentTokenCount || 0),
- output:
- (chunk.usageMetadata.candidatesTokenCount || 0) + (chunk.usageMetadata.thoughtsTokenCount || 0),
- cacheRead: chunk.usageMetadata.cachedContentTokenCount || 0,
- cacheWrite: 0,
- totalTokens: chunk.usageMetadata.totalTokenCount || 0,
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- total: 0,
- },
- };
- calculateCost(model, output.usage);
- }
- }
-
- if (currentBlock) {
- if (currentBlock.type === "text") {
- stream.push({
- type: "text_end",
- contentIndex: blockIndex(),
- content: currentBlock.text,
- partial: output,
- });
- } else {
- stream.push({
- type: "thinking_end",
- contentIndex: blockIndex(),
- content: currentBlock.thinking,
- partial: output,
- });
- }
- }
-
- if (options?.signal?.aborted) {
- throw new Error("Request was aborted");
- }
-
- if (output.stopReason === "aborted" || output.stopReason === "error") {
- throw new Error("An unknown error occurred");
- }
-
- stream.push({ type: "done", reason: output.stopReason, message: output });
- stream.end();
- } catch (error) {
- // Remove internal index property used during streaming
- for (const block of output.content) {
- if ("index" in block) {
- delete (block as { index?: number }).index;
- }
- }
- output.stopReason = options?.signal?.aborted ? "aborted" : "error";
- output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
- stream.push({ type: "error", reason: output.stopReason, error: output });
- stream.end();
- }
- })();
-
- return stream;
-};
-
-export const streamSimpleGoogleVertex: StreamFunction<"google-vertex", SimpleStreamOptions> = (
- model: Model<"google-vertex">,
- context: Context,
- options?: SimpleStreamOptions,
-): AssistantMessageEventStream => {
- const base = buildBaseOptions(model, options, undefined);
- if (!options?.reasoning) {
- return streamGoogleVertex(model, context, {
- ...base,
- thinking: { enabled: false },
- } satisfies GoogleVertexOptions);
- }
-
- const effort = clampReasoning(options.reasoning)!;
- const geminiModel = model as unknown as Model<"google-generative-ai">;
-
- if (isGemini3ProModel(geminiModel) || isGemini3FlashModel(geminiModel)) {
- return streamGoogleVertex(model, context, {
- ...base,
- thinking: {
- enabled: true,
- level: getGemini3ThinkingLevel(effort, geminiModel),
- },
- } satisfies GoogleVertexOptions);
- }
-
- return streamGoogleVertex(model, context, {
- ...base,
- thinking: {
- enabled: true,
- budgetTokens: getGoogleBudget(geminiModel, effort, options.thinkingBudgets),
- },
- } satisfies GoogleVertexOptions);
-};
-
-function createClient(
- model: Model<"google-vertex">,
- project: string,
- location: string,
- optionsHeaders?: Record,
-): GoogleGenAI {
- const httpOptions: { headers?: Record } = {};
-
- if (model.headers || optionsHeaders) {
- httpOptions.headers = { ...model.headers, ...optionsHeaders };
- }
-
- const hasHttpOptions = Object.values(httpOptions).some(Boolean);
-
- return new GoogleGenAI({
- vertexai: true,
- project,
- location,
- apiVersion: API_VERSION,
- httpOptions: hasHttpOptions ? httpOptions : undefined,
- });
-}
-
-function createClientWithApiKey(
- model: Model<"google-vertex">,
- apiKey: string,
- optionsHeaders?: Record,
-): GoogleGenAI {
- const httpOptions: { headers?: Record } = {};
-
- if (model.headers || optionsHeaders) {
- httpOptions.headers = { ...model.headers, ...optionsHeaders };
- }
-
- const hasHttpOptions = Object.values(httpOptions).some(Boolean);
-
- return new GoogleGenAI({
- vertexai: true,
- apiKey,
- apiVersion: API_VERSION,
- httpOptions: hasHttpOptions ? httpOptions : undefined,
- });
-}
-
-function resolveApiKey(options?: GoogleVertexOptions): string | undefined {
- const apiKey = options?.apiKey?.trim() || process.env.GOOGLE_CLOUD_API_KEY?.trim();
- if (!apiKey || apiKey === GCP_VERTEX_CREDENTIALS_MARKER || isPlaceholderApiKey(apiKey)) {
- return undefined;
- }
- return apiKey;
-}
-
-function isPlaceholderApiKey(apiKey: string): boolean {
- return /^<[^>]+>$/.test(apiKey);
-}
-
-function resolveProject(options?: GoogleVertexOptions): string {
- const project = options?.project || process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT;
- if (!project) {
- throw new Error(
- "Vertex AI requires a project ID. Set GOOGLE_CLOUD_PROJECT/GCLOUD_PROJECT or pass project in options.",
- );
- }
- return project;
-}
-
-function resolveLocation(options?: GoogleVertexOptions): string {
- const location = options?.location || process.env.GOOGLE_CLOUD_LOCATION;
- if (!location) {
- throw new Error("Vertex AI requires a location. Set GOOGLE_CLOUD_LOCATION or pass location in options.");
- }
- return location;
-}
-
-function buildParams(
- model: Model<"google-vertex">,
- context: Context,
- options: GoogleVertexOptions = {},
-): GenerateContentParameters {
- const contents = convertMessages(model, context);
-
- const generationConfig: GenerateContentConfig = {};
- if (options.temperature !== undefined) {
- generationConfig.temperature = options.temperature;
- }
- if (options.maxTokens !== undefined) {
- generationConfig.maxOutputTokens = options.maxTokens;
- }
-
- const config: GenerateContentConfig = {
- ...(Object.keys(generationConfig).length > 0 && generationConfig),
- ...(context.systemPrompt && { systemInstruction: sanitizeSurrogates(context.systemPrompt) }),
- ...(context.tools && context.tools.length > 0 && { tools: convertTools(context.tools) }),
- };
-
- if (context.tools && context.tools.length > 0 && options.toolChoice) {
- config.toolConfig = {
- functionCallingConfig: {
- mode: mapToolChoice(options.toolChoice),
- },
- };
- } else {
- config.toolConfig = undefined;
- }
-
- if (options.thinking?.enabled && model.reasoning) {
- const thinkingConfig: ThinkingConfig = { includeThoughts: true };
- if (options.thinking.level !== undefined) {
- thinkingConfig.thinkingLevel = THINKING_LEVEL_MAP[options.thinking.level];
- } else if (options.thinking.budgetTokens !== undefined) {
- thinkingConfig.thinkingBudget = options.thinking.budgetTokens;
- }
- config.thinkingConfig = thinkingConfig;
- } else if (model.reasoning && options.thinking && !options.thinking.enabled) {
- config.thinkingConfig = getDisabledThinkingConfig(model);
- }
-
- if (options.signal) {
- if (options.signal.aborted) {
- throw new Error("Request aborted");
- }
- config.abortSignal = options.signal;
- }
-
- const params: GenerateContentParameters = {
- model: model.id,
- contents,
- config,
- };
-
- return params;
-}
-
-type ClampedThinkingLevel = Exclude;
-
-function isGemini3ProModel(model: Model<"google-generative-ai">): boolean {
- return /gemini-3(?:\.\d+)?-pro/.test(model.id.toLowerCase());
-}
-
-function isGemini3FlashModel(model: Model<"google-generative-ai">): boolean {
- return /gemini-3(?:\.\d+)?-flash/.test(model.id.toLowerCase());
-}
-
-function getDisabledThinkingConfig(model: Model<"google-vertex">): ThinkingConfig {
- // Google docs: Gemini 3.1 Pro cannot disable thinking, and Gemini 3 Flash / Flash-Lite
- // do not support full thinking-off either. For Gemini 3 models, use the lowest supported
- // thinkingLevel without includeThoughts so hidden thinking remains invisible to pi.
- const geminiModel = model as unknown as Model<"google-generative-ai">;
- if (isGemini3ProModel(geminiModel)) {
- return { thinkingLevel: ThinkingLevel.LOW };
- }
- if (isGemini3FlashModel(geminiModel)) {
- return { thinkingLevel: ThinkingLevel.MINIMAL };
- }
-
- // Gemini 2.x supports disabling via thinkingBudget = 0.
- return { thinkingBudget: 0 };
-}
-
-function getGemini3ThinkingLevel(
- effort: ClampedThinkingLevel,
- model: Model<"google-generative-ai">,
-): GoogleThinkingLevel {
- if (isGemini3ProModel(model)) {
- switch (effort) {
- case "minimal":
- case "low":
- return "LOW";
- case "medium":
- case "high":
- return "HIGH";
- }
- }
- switch (effort) {
- case "minimal":
- return "MINIMAL";
- case "low":
- return "LOW";
- case "medium":
- return "MEDIUM";
- case "high":
- return "HIGH";
- }
-}
-
-function getGoogleBudget(
- model: Model<"google-generative-ai">,
- effort: ClampedThinkingLevel,
- customBudgets?: ThinkingBudgets,
-): number {
- if (customBudgets?.[effort] !== undefined) {
- return customBudgets[effort]!;
- }
-
- if (model.id.includes("2.5-pro")) {
- const budgets: Record = {
- minimal: 128,
- low: 2048,
- medium: 8192,
- high: 32768,
- };
- return budgets[effort];
- }
-
- if (model.id.includes("2.5-flash")) {
- const budgets: Record = {
- minimal: 128,
- low: 2048,
- medium: 8192,
- high: 24576,
- };
- return budgets[effort];
- }
-
- return -1;
-}
diff --git a/pi-mono-reference/packages/ai/src/providers/google.ts b/pi-mono-reference/packages/ai/src/providers/google.ts
deleted file mode 100644
index 46cc5ba6..00000000
--- a/pi-mono-reference/packages/ai/src/providers/google.ts
+++ /dev/null
@@ -1,500 +0,0 @@
-import {
- type GenerateContentConfig,
- type GenerateContentParameters,
- GoogleGenAI,
- type ThinkingConfig,
-} from "@google/genai";
-import { getEnvApiKey } from "../env-api-keys.js";
-import { calculateCost } from "../models.js";
-import type {
- Api,
- AssistantMessage,
- Context,
- Model,
- SimpleStreamOptions,
- StreamFunction,
- StreamOptions,
- TextContent,
- ThinkingBudgets,
- ThinkingContent,
- ThinkingLevel,
- ToolCall,
-} from "../types.js";
-import { AssistantMessageEventStream } from "../utils/event-stream.js";
-import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
-import type { GoogleThinkingLevel } from "./google-gemini-cli.js";
-import {
- convertMessages,
- convertTools,
- isThinkingPart,
- mapStopReason,
- mapToolChoice,
- retainThoughtSignature,
-} from "./google-shared.js";
-import { buildBaseOptions, clampReasoning } from "./simple-options.js";
-
-export interface GoogleOptions extends StreamOptions {
- toolChoice?: "auto" | "none" | "any";
- thinking?: {
- enabled: boolean;
- budgetTokens?: number; // -1 for dynamic, 0 to disable
- level?: GoogleThinkingLevel;
- };
-}
-
-// Counter for generating unique tool call IDs
-let toolCallCounter = 0;
-
-export const streamGoogle: StreamFunction<"google-generative-ai", GoogleOptions> = (
- model: Model<"google-generative-ai">,
- context: Context,
- options?: GoogleOptions,
-): AssistantMessageEventStream => {
- const stream = new AssistantMessageEventStream();
-
- (async () => {
- const output: AssistantMessage = {
- role: "assistant",
- content: [],
- api: "google-generative-ai" as Api,
- provider: model.provider,
- model: model.id,
- usage: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- stopReason: "stop",
- timestamp: Date.now(),
- };
-
- try {
- const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
- const client = createClient(model, apiKey, options?.headers);
- let params = buildParams(model, context, options);
- const nextParams = await options?.onPayload?.(params, model);
- if (nextParams !== undefined) {
- params = nextParams as GenerateContentParameters;
- }
- const googleStream = await client.models.generateContentStream(params);
-
- stream.push({ type: "start", partial: output });
- let currentBlock: TextContent | ThinkingContent | null = null;
- const blocks = output.content;
- const blockIndex = () => blocks.length - 1;
- for await (const chunk of googleStream) {
- // @google/genai documents GenerateContentResponse.responseId as an output-only field
- // used to identify each response. Keep the first non-empty one from the stream.
- output.responseId ||= chunk.responseId;
- const candidate = chunk.candidates?.[0];
- if (candidate?.content?.parts) {
- for (const part of candidate.content.parts) {
- if (part.text !== undefined) {
- const isThinking = isThinkingPart(part);
- if (
- !currentBlock ||
- (isThinking && currentBlock.type !== "thinking") ||
- (!isThinking && currentBlock.type !== "text")
- ) {
- if (currentBlock) {
- if (currentBlock.type === "text") {
- stream.push({
- type: "text_end",
- contentIndex: blocks.length - 1,
- content: currentBlock.text,
- partial: output,
- });
- } else {
- stream.push({
- type: "thinking_end",
- contentIndex: blockIndex(),
- content: currentBlock.thinking,
- partial: output,
- });
- }
- }
- if (isThinking) {
- currentBlock = { type: "thinking", thinking: "", thinkingSignature: undefined };
- output.content.push(currentBlock);
- stream.push({ type: "thinking_start", contentIndex: blockIndex(), partial: output });
- } else {
- currentBlock = { type: "text", text: "" };
- output.content.push(currentBlock);
- stream.push({ type: "text_start", contentIndex: blockIndex(), partial: output });
- }
- }
- if (currentBlock.type === "thinking") {
- currentBlock.thinking += part.text;
- currentBlock.thinkingSignature = retainThoughtSignature(
- currentBlock.thinkingSignature,
- part.thoughtSignature,
- );
- stream.push({
- type: "thinking_delta",
- contentIndex: blockIndex(),
- delta: part.text,
- partial: output,
- });
- } else {
- currentBlock.text += part.text;
- currentBlock.textSignature = retainThoughtSignature(
- currentBlock.textSignature,
- part.thoughtSignature,
- );
- stream.push({
- type: "text_delta",
- contentIndex: blockIndex(),
- delta: part.text,
- partial: output,
- });
- }
- }
-
- if (part.functionCall) {
- if (currentBlock) {
- if (currentBlock.type === "text") {
- stream.push({
- type: "text_end",
- contentIndex: blockIndex(),
- content: currentBlock.text,
- partial: output,
- });
- } else {
- stream.push({
- type: "thinking_end",
- contentIndex: blockIndex(),
- content: currentBlock.thinking,
- partial: output,
- });
- }
- currentBlock = null;
- }
-
- // Generate unique ID if not provided or if it's a duplicate
- const providedId = part.functionCall.id;
- const needsNewId =
- !providedId || output.content.some((b) => b.type === "toolCall" && b.id === providedId);
- const toolCallId = needsNewId
- ? `${part.functionCall.name}_${Date.now()}_${++toolCallCounter}`
- : providedId;
-
- const toolCall: ToolCall = {
- type: "toolCall",
- id: toolCallId,
- name: part.functionCall.name || "",
- arguments: (part.functionCall.args as Record) ?? {},
- ...(part.thoughtSignature && { thoughtSignature: part.thoughtSignature }),
- };
-
- output.content.push(toolCall);
- stream.push({ type: "toolcall_start", contentIndex: blockIndex(), partial: output });
- stream.push({
- type: "toolcall_delta",
- contentIndex: blockIndex(),
- delta: JSON.stringify(toolCall.arguments),
- partial: output,
- });
- stream.push({ type: "toolcall_end", contentIndex: blockIndex(), toolCall, partial: output });
- }
- }
- }
-
- if (candidate?.finishReason) {
- output.stopReason = mapStopReason(candidate.finishReason);
- if (output.content.some((b) => b.type === "toolCall")) {
- output.stopReason = "toolUse";
- }
- }
-
- if (chunk.usageMetadata) {
- output.usage = {
- input:
- (chunk.usageMetadata.promptTokenCount || 0) - (chunk.usageMetadata.cachedContentTokenCount || 0),
- output:
- (chunk.usageMetadata.candidatesTokenCount || 0) + (chunk.usageMetadata.thoughtsTokenCount || 0),
- cacheRead: chunk.usageMetadata.cachedContentTokenCount || 0,
- cacheWrite: 0,
- totalTokens: chunk.usageMetadata.totalTokenCount || 0,
- cost: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- total: 0,
- },
- };
- calculateCost(model, output.usage);
- }
- }
-
- if (currentBlock) {
- if (currentBlock.type === "text") {
- stream.push({
- type: "text_end",
- contentIndex: blockIndex(),
- content: currentBlock.text,
- partial: output,
- });
- } else {
- stream.push({
- type: "thinking_end",
- contentIndex: blockIndex(),
- content: currentBlock.thinking,
- partial: output,
- });
- }
- }
-
- if (options?.signal?.aborted) {
- throw new Error("Request was aborted");
- }
-
- if (output.stopReason === "aborted" || output.stopReason === "error") {
- throw new Error("An unknown error occurred");
- }
-
- stream.push({ type: "done", reason: output.stopReason, message: output });
- stream.end();
- } catch (error) {
- // Remove internal index property used during streaming
- for (const block of output.content) {
- if ("index" in block) {
- delete (block as { index?: number }).index;
- }
- }
- output.stopReason = options?.signal?.aborted ? "aborted" : "error";
- output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
- stream.push({ type: "error", reason: output.stopReason, error: output });
- stream.end();
- }
- })();
-
- return stream;
-};
-
-export const streamSimpleGoogle: StreamFunction<"google-generative-ai", SimpleStreamOptions> = (
- model: Model<"google-generative-ai">,
- context: Context,
- options?: SimpleStreamOptions,
-): AssistantMessageEventStream => {
- const apiKey = options?.apiKey || getEnvApiKey(model.provider);
- if (!apiKey) {
- throw new Error(`No API key for provider: ${model.provider}`);
- }
-
- const base = buildBaseOptions(model, options, apiKey);
- if (!options?.reasoning) {
- return streamGoogle(model, context, { ...base, thinking: { enabled: false } } satisfies GoogleOptions);
- }
-
- const effort = clampReasoning(options.reasoning)!;
- const googleModel = model as Model<"google-generative-ai">;
-
- if (isGemini3ProModel(googleModel) || isGemini3FlashModel(googleModel) || isGemma4Model(googleModel)) {
- return streamGoogle(model, context, {
- ...base,
- thinking: {
- enabled: true,
- level: getThinkingLevel(effort, googleModel),
- },
- } satisfies GoogleOptions);
- }
-
- return streamGoogle(model, context, {
- ...base,
- thinking: {
- enabled: true,
- budgetTokens: getGoogleBudget(googleModel, effort, options.thinkingBudgets),
- },
- } satisfies GoogleOptions);
-};
-
-function createClient(
- model: Model<"google-generative-ai">,
- apiKey?: string,
- optionsHeaders?: Record,
-): GoogleGenAI {
- const httpOptions: { baseUrl?: string; apiVersion?: string; headers?: Record } = {};
- if (model.baseUrl) {
- httpOptions.baseUrl = model.baseUrl;
- httpOptions.apiVersion = ""; // baseUrl already includes version path, don't append
- }
- if (model.headers || optionsHeaders) {
- httpOptions.headers = { ...model.headers, ...optionsHeaders };
- }
-
- return new GoogleGenAI({
- apiKey,
- httpOptions: Object.keys(httpOptions).length > 0 ? httpOptions : undefined,
- });
-}
-
-function buildParams(
- model: Model<"google-generative-ai">,
- context: Context,
- options: GoogleOptions = {},
-): GenerateContentParameters {
- const contents = convertMessages(model, context);
-
- const generationConfig: GenerateContentConfig = {};
- if (options.temperature !== undefined) {
- generationConfig.temperature = options.temperature;
- }
- if (options.maxTokens !== undefined) {
- generationConfig.maxOutputTokens = options.maxTokens;
- }
-
- const config: GenerateContentConfig = {
- ...(Object.keys(generationConfig).length > 0 && generationConfig),
- ...(context.systemPrompt && { systemInstruction: sanitizeSurrogates(context.systemPrompt) }),
- ...(context.tools && context.tools.length > 0 && { tools: convertTools(context.tools) }),
- };
-
- if (context.tools && context.tools.length > 0 && options.toolChoice) {
- config.toolConfig = {
- functionCallingConfig: {
- mode: mapToolChoice(options.toolChoice),
- },
- };
- } else {
- config.toolConfig = undefined;
- }
-
- if (options.thinking?.enabled && model.reasoning) {
- const thinkingConfig: ThinkingConfig = { includeThoughts: true };
- if (options.thinking.level !== undefined) {
- // Cast to any since our GoogleThinkingLevel mirrors Google's ThinkingLevel enum values
- thinkingConfig.thinkingLevel = options.thinking.level as any;
- } else if (options.thinking.budgetTokens !== undefined) {
- thinkingConfig.thinkingBudget = options.thinking.budgetTokens;
- }
- config.thinkingConfig = thinkingConfig;
- } else if (model.reasoning && options.thinking && !options.thinking.enabled) {
- config.thinkingConfig = getDisabledThinkingConfig(model);
- }
-
- if (options.signal) {
- if (options.signal.aborted) {
- throw new Error("Request aborted");
- }
- config.abortSignal = options.signal;
- }
-
- const params: GenerateContentParameters = {
- model: model.id,
- contents,
- config,
- };
-
- return params;
-}
-
-type ClampedThinkingLevel = Exclude;
-
-function isGemma4Model(model: Model<"google-generative-ai">): boolean {
- return /gemma-?4/.test(model.id.toLowerCase());
-}
-
-function isGemini3ProModel(model: Model<"google-generative-ai">): boolean {
- return /gemini-3(?:\.\d+)?-pro/.test(model.id.toLowerCase());
-}
-
-function isGemini3FlashModel(model: Model<"google-generative-ai">): boolean {
- return /gemini-3(?:\.\d+)?-flash/.test(model.id.toLowerCase());
-}
-
-function getDisabledThinkingConfig(model: Model<"google-generative-ai">): ThinkingConfig {
- // Google docs: Gemini 3.1 Pro cannot disable thinking, and Gemini 3 Flash / Flash-Lite
- // do not support full thinking-off either. For Gemini 3 models, use the lowest supported
- // thinkingLevel without includeThoughts so hidden thinking remains invisible to pi.
- if (isGemini3ProModel(model)) {
- return { thinkingLevel: "LOW" as any };
- }
- if (isGemini3FlashModel(model)) {
- return { thinkingLevel: "MINIMAL" as any };
- }
- if (isGemma4Model(model)) {
- return { thinkingLevel: "MINIMAL" as any };
- }
-
- // Gemini 2.x supports disabling via thinkingBudget = 0.
- return { thinkingBudget: 0 };
-}
-
-function getThinkingLevel(effort: ClampedThinkingLevel, model: Model<"google-generative-ai">): GoogleThinkingLevel {
- if (isGemini3ProModel(model)) {
- switch (effort) {
- case "minimal":
- case "low":
- return "LOW";
- case "medium":
- case "high":
- return "HIGH";
- }
- }
- if (isGemma4Model(model)) {
- switch (effort) {
- case "minimal":
- case "low":
- return "MINIMAL";
- case "medium":
- case "high":
- return "HIGH";
- }
- }
- switch (effort) {
- case "minimal":
- return "MINIMAL";
- case "low":
- return "LOW";
- case "medium":
- return "MEDIUM";
- case "high":
- return "HIGH";
- }
-}
-
-function getGoogleBudget(
- model: Model<"google-generative-ai">,
- effort: ClampedThinkingLevel,
- customBudgets?: ThinkingBudgets,
-): number {
- if (customBudgets?.[effort] !== undefined) {
- return customBudgets[effort]!;
- }
-
- if (model.id.includes("2.5-pro")) {
- const budgets: Record = {
- minimal: 128,
- low: 2048,
- medium: 8192,
- high: 32768,
- };
- return budgets[effort];
- }
-
- if (model.id.includes("2.5-flash-lite")) {
- const budgets: Record = {
- minimal: 512,
- low: 2048,
- medium: 8192,
- high: 24576,
- };
- return budgets[effort];
- }
-
- if (model.id.includes("2.5-flash")) {
- const budgets: Record = {
- minimal: 128,
- low: 2048,
- medium: 8192,
- high: 24576,
- };
- return budgets[effort];
- }
-
- return -1;
-}
diff --git a/pi-mono-reference/packages/ai/src/providers/mistral.ts b/pi-mono-reference/packages/ai/src/providers/mistral.ts
deleted file mode 100644
index 9685a296..00000000
--- a/pi-mono-reference/packages/ai/src/providers/mistral.ts
+++ /dev/null
@@ -1,591 +0,0 @@
-import { Mistral } from "@mistralai/mistralai";
-import type { RequestOptions } from "@mistralai/mistralai/lib/sdks.js";
-import type {
- ChatCompletionStreamRequest,
- ChatCompletionStreamRequestMessages,
- CompletionEvent,
- ContentChunk,
- FunctionTool,
-} from "@mistralai/mistralai/models/components/index.js";
-import { getEnvApiKey } from "../env-api-keys.js";
-import { calculateCost } from "../models.js";
-import type {
- AssistantMessage,
- Context,
- Message,
- Model,
- SimpleStreamOptions,
- StopReason,
- StreamFunction,
- StreamOptions,
- TextContent,
- ThinkingContent,
- Tool,
- ToolCall,
-} from "../types.js";
-import { AssistantMessageEventStream } from "../utils/event-stream.js";
-import { shortHash } from "../utils/hash.js";
-import { parseStreamingJson } from "../utils/json-parse.js";
-import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
-import { buildBaseOptions, clampReasoning } from "./simple-options.js";
-import { transformMessages } from "./transform-messages.js";
-
-const MISTRAL_TOOL_CALL_ID_LENGTH = 9;
-const MAX_MISTRAL_ERROR_BODY_CHARS = 4000;
-
-/**
- * Provider-specific options for the Mistral API.
- */
-export interface MistralOptions extends StreamOptions {
- toolChoice?: "auto" | "none" | "any" | "required" | { type: "function"; function: { name: string } };
- promptMode?: "reasoning";
-}
-
-/**
- * Stream responses from Mistral using `chat.stream`.
- */
-export const streamMistral: StreamFunction<"mistral-conversations", MistralOptions> = (
- model: Model<"mistral-conversations">,
- context: Context,
- options?: MistralOptions,
-): AssistantMessageEventStream => {
- const stream = new AssistantMessageEventStream();
-
- (async () => {
- const output = createOutput(model);
-
- try {
- const apiKey = options?.apiKey || getEnvApiKey(model.provider);
- if (!apiKey) {
- throw new Error(`No API key for provider: ${model.provider}`);
- }
-
- // Intentionally per-request: avoids shared SDK mutable state across concurrent consumers.
- const mistral = new Mistral({
- apiKey,
- serverURL: model.baseUrl,
- });
-
- const normalizeMistralToolCallId = createMistralToolCallIdNormalizer();
- const transformedMessages = transformMessages(context.messages, model, (id) => normalizeMistralToolCallId(id));
-
- let payload = buildChatPayload(model, context, transformedMessages, options);
- const nextPayload = await options?.onPayload?.(payload, model);
- if (nextPayload !== undefined) {
- payload = nextPayload as ChatCompletionStreamRequest;
- }
- const mistralStream = await mistral.chat.stream(payload, buildRequestOptions(model, options));
- stream.push({ type: "start", partial: output });
- await consumeChatStream(model, output, stream, mistralStream);
-
- if (options?.signal?.aborted) {
- throw new Error("Request was aborted");
- }
-
- if (output.stopReason === "aborted" || output.stopReason === "error") {
- throw new Error("An unknown error occurred");
- }
-
- stream.push({ type: "done", reason: output.stopReason, message: output });
- stream.end();
- } catch (error) {
- for (const block of output.content) {
- // partialArgs is only a streaming scratch buffer; never persist it.
- delete (block as { partialArgs?: string }).partialArgs;
- }
- output.stopReason = options?.signal?.aborted ? "aborted" : "error";
- output.errorMessage = formatMistralError(error);
- stream.push({ type: "error", reason: output.stopReason, error: output });
- stream.end();
- }
- })();
-
- return stream;
-};
-
-/**
- * Maps provider-agnostic `SimpleStreamOptions` to Mistral options.
- */
-export const streamSimpleMistral: StreamFunction<"mistral-conversations", SimpleStreamOptions> = (
- model: Model<"mistral-conversations">,
- context: Context,
- options?: SimpleStreamOptions,
-): AssistantMessageEventStream => {
- const apiKey = options?.apiKey || getEnvApiKey(model.provider);
- if (!apiKey) {
- throw new Error(`No API key for provider: ${model.provider}`);
- }
-
- const base = buildBaseOptions(model, options, apiKey);
- const reasoning = clampReasoning(options?.reasoning);
-
- return streamMistral(model, context, {
- ...base,
- promptMode: model.reasoning && reasoning ? "reasoning" : undefined,
- } satisfies MistralOptions);
-};
-
-function createOutput(model: Model<"mistral-conversations">): AssistantMessage {
- return {
- role: "assistant",
- content: [],
- api: model.api,
- provider: model.provider,
- model: model.id,
- usage: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- stopReason: "stop",
- timestamp: Date.now(),
- };
-}
-
-function createMistralToolCallIdNormalizer(): (id: string) => string {
- const idMap = new Map();
- const reverseMap = new Map();
-
- return (id: string): string => {
- const existing = idMap.get(id);
- if (existing) return existing;
-
- let attempt = 0;
- while (true) {
- const candidate = deriveMistralToolCallId(id, attempt);
- const owner = reverseMap.get(candidate);
- if (!owner || owner === id) {
- idMap.set(id, candidate);
- reverseMap.set(candidate, id);
- return candidate;
- }
- attempt++;
- }
- };
-}
-
-function deriveMistralToolCallId(id: string, attempt: number): string {
- const normalized = id.replace(/[^a-zA-Z0-9]/g, "");
- if (attempt === 0 && normalized.length === MISTRAL_TOOL_CALL_ID_LENGTH) return normalized;
- const seedBase = normalized || id;
- const seed = attempt === 0 ? seedBase : `${seedBase}:${attempt}`;
- return shortHash(seed)
- .replace(/[^a-zA-Z0-9]/g, "")
- .slice(0, MISTRAL_TOOL_CALL_ID_LENGTH);
-}
-
-function formatMistralError(error: unknown): string {
- if (error instanceof Error) {
- const sdkError = error as Error & { statusCode?: unknown; body?: unknown };
- const statusCode = typeof sdkError.statusCode === "number" ? sdkError.statusCode : undefined;
- const bodyText = typeof sdkError.body === "string" ? sdkError.body.trim() : undefined;
- if (statusCode !== undefined && bodyText) {
- return `Mistral API error (${statusCode}): ${truncateErrorText(bodyText, MAX_MISTRAL_ERROR_BODY_CHARS)}`;
- }
- if (statusCode !== undefined) return `Mistral API error (${statusCode}): ${error.message}`;
- return error.message;
- }
- return safeJsonStringify(error);
-}
-
-function truncateErrorText(text: string, maxChars: number): string {
- if (text.length <= maxChars) return text;
- return `${text.slice(0, maxChars)}... [truncated ${text.length - maxChars} chars]`;
-}
-
-function safeJsonStringify(value: unknown): string {
- try {
- const serialized = JSON.stringify(value);
- return serialized === undefined ? String(value) : serialized;
- } catch {
- return String(value);
- }
-}
-
-function buildRequestOptions(model: Model<"mistral-conversations">, options?: MistralOptions): RequestOptions {
- const requestOptions: RequestOptions = {};
- if (options?.signal) requestOptions.signal = options.signal;
- requestOptions.retries = { strategy: "none" };
-
- const headers: Record = {};
- if (model.headers) Object.assign(headers, model.headers);
- if (options?.headers) Object.assign(headers, options.headers);
-
- // Mistral infrastructure uses `x-affinity` for KV-cache reuse (prefix caching).
- // Respect explicit caller-provided header values.
- if (options?.sessionId && !headers["x-affinity"]) {
- headers["x-affinity"] = options.sessionId;
- }
-
- if (Object.keys(headers).length > 0) {
- requestOptions.headers = headers;
- }
-
- return requestOptions;
-}
-
-function buildChatPayload(
- model: Model<"mistral-conversations">,
- context: Context,
- messages: Message[],
- options?: MistralOptions,
-): ChatCompletionStreamRequest {
- const payload: ChatCompletionStreamRequest = {
- model: model.id,
- stream: true,
- messages: toChatMessages(messages, model.input.includes("image")),
- };
-
- if (context.tools?.length) payload.tools = toFunctionTools(context.tools);
- if (options?.temperature !== undefined) payload.temperature = options.temperature;
- if (options?.maxTokens !== undefined) payload.maxTokens = options.maxTokens;
- if (options?.toolChoice) payload.toolChoice = mapToolChoice(options.toolChoice);
- if (options?.promptMode) payload.promptMode = options.promptMode as any;
-
- if (context.systemPrompt) {
- payload.messages.unshift({
- role: "system",
- content: sanitizeSurrogates(context.systemPrompt),
- });
- }
-
- return payload;
-}
-
-async function consumeChatStream(
- model: Model<"mistral-conversations">,
- output: AssistantMessage,
- stream: AssistantMessageEventStream,
- mistralStream: AsyncIterable,
-): Promise {
- let currentBlock: TextContent | ThinkingContent | null = null;
- const blocks = output.content;
- const blockIndex = () => blocks.length - 1;
- const toolBlocksByKey = new Map();
-
- const finishCurrentBlock = (block?: typeof currentBlock) => {
- if (!block) return;
- if (block.type === "text") {
- stream.push({
- type: "text_end",
- contentIndex: blockIndex(),
- content: block.text,
- partial: output,
- });
- return;
- }
- if (block.type === "thinking") {
- stream.push({
- type: "thinking_end",
- contentIndex: blockIndex(),
- content: block.thinking,
- partial: output,
- });
- }
- };
-
- for await (const event of mistralStream) {
- const chunk = event.data;
- // Mistral's streamed CompletionChunk carries an id field. Keep the first non-empty one,
- // mirroring how OpenAI-style streaming exposes a stable response identifier per stream.
- output.responseId ||= chunk.id;
-
- if (chunk.usage) {
- output.usage.input = chunk.usage.promptTokens || 0;
- output.usage.output = chunk.usage.completionTokens || 0;
- output.usage.cacheRead = 0;
- output.usage.cacheWrite = 0;
- output.usage.totalTokens = chunk.usage.totalTokens || output.usage.input + output.usage.output;
- calculateCost(model, output.usage);
- }
-
- const choice = chunk.choices[0];
- if (!choice) continue;
-
- if (choice.finishReason) {
- output.stopReason = mapChatStopReason(choice.finishReason);
- }
-
- const delta = choice.delta;
- if (delta.content !== null && delta.content !== undefined) {
- const contentItems = typeof delta.content === "string" ? [delta.content] : delta.content;
- for (const item of contentItems) {
- if (typeof item === "string") {
- const textDelta = sanitizeSurrogates(item);
- if (!currentBlock || currentBlock.type !== "text") {
- finishCurrentBlock(currentBlock);
- currentBlock = { type: "text", text: "" };
- output.content.push(currentBlock);
- stream.push({ type: "text_start", contentIndex: blockIndex(), partial: output });
- }
- currentBlock.text += textDelta;
- stream.push({
- type: "text_delta",
- contentIndex: blockIndex(),
- delta: textDelta,
- partial: output,
- });
- continue;
- }
-
- if (item.type === "thinking") {
- const deltaText = item.thinking
- .map((part) => ("text" in part ? part.text : ""))
- .filter((text) => text.length > 0)
- .join("");
- const thinkingDelta = sanitizeSurrogates(deltaText);
- if (!thinkingDelta) continue;
- if (!currentBlock || currentBlock.type !== "thinking") {
- finishCurrentBlock(currentBlock);
- currentBlock = { type: "thinking", thinking: "" };
- output.content.push(currentBlock);
- stream.push({ type: "thinking_start", contentIndex: blockIndex(), partial: output });
- }
- currentBlock.thinking += thinkingDelta;
- stream.push({
- type: "thinking_delta",
- contentIndex: blockIndex(),
- delta: thinkingDelta,
- partial: output,
- });
- continue;
- }
-
- if (item.type === "text") {
- const textDelta = sanitizeSurrogates(item.text);
- if (!currentBlock || currentBlock.type !== "text") {
- finishCurrentBlock(currentBlock);
- currentBlock = { type: "text", text: "" };
- output.content.push(currentBlock);
- stream.push({ type: "text_start", contentIndex: blockIndex(), partial: output });
- }
- currentBlock.text += textDelta;
- stream.push({
- type: "text_delta",
- contentIndex: blockIndex(),
- delta: textDelta,
- partial: output,
- });
- }
- }
- }
-
- const toolCalls = delta.toolCalls || [];
- for (const toolCall of toolCalls) {
- if (currentBlock) {
- finishCurrentBlock(currentBlock);
- currentBlock = null;
- }
- const callId =
- toolCall.id && toolCall.id !== "null"
- ? toolCall.id
- : deriveMistralToolCallId(`toolcall:${toolCall.index ?? 0}`, 0);
- const key = `${callId}:${toolCall.index || 0}`;
- const existingIndex = toolBlocksByKey.get(key);
- let block: (ToolCall & { partialArgs?: string }) | undefined;
-
- if (existingIndex !== undefined) {
- const existing = output.content[existingIndex];
- if (existing?.type === "toolCall") {
- block = existing as ToolCall & { partialArgs?: string };
- }
- }
-
- if (!block) {
- block = {
- type: "toolCall",
- id: callId,
- name: toolCall.function.name,
- arguments: {},
- partialArgs: "",
- };
- output.content.push(block);
- toolBlocksByKey.set(key, output.content.length - 1);
- stream.push({ type: "toolcall_start", contentIndex: output.content.length - 1, partial: output });
- }
-
- const argsDelta =
- typeof toolCall.function.arguments === "string"
- ? toolCall.function.arguments
- : JSON.stringify(toolCall.function.arguments || {});
- block.partialArgs = (block.partialArgs || "") + argsDelta;
- block.arguments = parseStreamingJson>(block.partialArgs);
- stream.push({
- type: "toolcall_delta",
- contentIndex: toolBlocksByKey.get(key)!,
- delta: argsDelta,
- partial: output,
- });
- }
- }
-
- finishCurrentBlock(currentBlock);
- for (const index of toolBlocksByKey.values()) {
- const block = output.content[index];
- if (block.type !== "toolCall") continue;
- const toolBlock = block as ToolCall & { partialArgs?: string };
- toolBlock.arguments = parseStreamingJson>(toolBlock.partialArgs);
- // Finalize in-place and strip the scratch buffer so replay only
- // carries parsed arguments.
- delete toolBlock.partialArgs;
- stream.push({
- type: "toolcall_end",
- contentIndex: index,
- toolCall: toolBlock,
- partial: output,
- });
- }
-}
-
-function toFunctionTools(tools: Tool[]): Array {
- return tools.map((tool) => ({
- type: "function",
- function: {
- name: tool.name,
- description: tool.description,
- parameters: tool.parameters as unknown as Record,
- strict: false,
- },
- }));
-}
-
-function toChatMessages(messages: Message[], supportsImages: boolean): ChatCompletionStreamRequestMessages[] {
- const result: ChatCompletionStreamRequestMessages[] = [];
-
- for (const msg of messages) {
- if (msg.role === "user") {
- if (typeof msg.content === "string") {
- result.push({ role: "user", content: sanitizeSurrogates(msg.content) });
- continue;
- }
- const hadImages = msg.content.some((item) => item.type === "image");
- const content: ContentChunk[] = msg.content
- .filter((item) => item.type === "text" || supportsImages)
- .map((item) => {
- if (item.type === "text") return { type: "text", text: sanitizeSurrogates(item.text) };
- return { type: "image_url", imageUrl: `data:${item.mimeType};base64,${item.data}` };
- });
- if (content.length > 0) {
- result.push({ role: "user", content });
- continue;
- }
- if (hadImages && !supportsImages) {
- result.push({ role: "user", content: "(image omitted: model does not support images)" });
- }
- continue;
- }
-
- if (msg.role === "assistant") {
- const contentParts: ContentChunk[] = [];
- const toolCalls: Array<{ id: string; type: "function"; function: { name: string; arguments: string } }> = [];
-
- for (const block of msg.content) {
- if (block.type === "text") {
- if (block.text.trim().length > 0) {
- contentParts.push({ type: "text", text: sanitizeSurrogates(block.text) });
- }
- continue;
- }
- if (block.type === "thinking") {
- if (block.thinking.trim().length > 0) {
- contentParts.push({
- type: "thinking",
- thinking: [{ type: "text", text: sanitizeSurrogates(block.thinking) }],
- });
- }
- continue;
- }
- toolCalls.push({
- id: block.id,
- type: "function",
- function: { name: block.name, arguments: JSON.stringify(block.arguments || {}) },
- });
- }
-
- const assistantMessage: ChatCompletionStreamRequestMessages = { role: "assistant" };
- if (contentParts.length > 0) assistantMessage.content = contentParts;
- if (toolCalls.length > 0) assistantMessage.toolCalls = toolCalls;
- if (contentParts.length > 0 || toolCalls.length > 0) result.push(assistantMessage);
- continue;
- }
-
- const toolContent: ContentChunk[] = [];
- const textResult = msg.content
- .filter((part) => part.type === "text")
- .map((part) => (part.type === "text" ? sanitizeSurrogates(part.text) : ""))
- .join("\n");
- const hasImages = msg.content.some((part) => part.type === "image");
- const toolText = buildToolResultText(textResult, hasImages, supportsImages, msg.isError);
- toolContent.push({ type: "text", text: toolText });
- for (const part of msg.content) {
- if (!supportsImages) continue;
- if (part.type !== "image") continue;
- toolContent.push({
- type: "image_url",
- imageUrl: `data:${part.mimeType};base64,${part.data}`,
- });
- }
- result.push({
- role: "tool",
- toolCallId: msg.toolCallId,
- name: msg.toolName,
- content: toolContent,
- });
- }
-
- return result;
-}
-
-function buildToolResultText(text: string, hasImages: boolean, supportsImages: boolean, isError: boolean): string {
- const trimmed = text.trim();
- const errorPrefix = isError ? "[tool error] " : "";
-
- if (trimmed.length > 0) {
- const imageSuffix = hasImages && !supportsImages ? "\n[tool image omitted: model does not support images]" : "";
- return `${errorPrefix}${trimmed}${imageSuffix}`;
- }
-
- if (hasImages) {
- if (supportsImages) {
- return isError ? "[tool error] (see attached image)" : "(see attached image)";
- }
- return isError
- ? "[tool error] (image omitted: model does not support images)"
- : "(image omitted: model does not support images)";
- }
-
- return isError ? "[tool error] (no tool output)" : "(no tool output)";
-}
-
-function mapToolChoice(
- choice: MistralOptions["toolChoice"],
-): "auto" | "none" | "any" | "required" | { type: "function"; function: { name: string } } | undefined {
- if (!choice) return undefined;
- if (choice === "auto" || choice === "none" || choice === "any" || choice === "required") {
- return choice as any;
- }
- return {
- type: "function",
- function: { name: choice.function.name },
- };
-}
-
-function mapChatStopReason(reason: string | null): StopReason {
- if (reason === null) return "stop";
- switch (reason) {
- case "stop":
- return "stop";
- case "length":
- case "model_length":
- return "length";
- case "tool_calls":
- return "toolUse";
- case "error":
- return "error";
- default:
- return "stop";
- }
-}
diff --git a/pi-mono-reference/packages/ai/src/providers/openai-codex-responses.ts b/pi-mono-reference/packages/ai/src/providers/openai-codex-responses.ts
deleted file mode 100644
index 4cca39b7..00000000
--- a/pi-mono-reference/packages/ai/src/providers/openai-codex-responses.ts
+++ /dev/null
@@ -1,975 +0,0 @@
-import type * as NodeOs from "node:os";
-import type {
- Tool as OpenAITool,
- ResponseCreateParamsStreaming,
- ResponseInput,
- ResponseStreamEvent,
-} from "openai/resources/responses/responses.js";
-
-// NEVER convert to top-level runtime imports - breaks browser/Vite builds (web-ui)
-let _os: typeof NodeOs | null = null;
-
-type DynamicImport = (specifier: string) => Promise;
-
-const dynamicImport: DynamicImport = (specifier) => import(specifier);
-const NODE_OS_SPECIFIER = "node:" + "os";
-
-if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
- dynamicImport(NODE_OS_SPECIFIER).then((m) => {
- _os = m as typeof NodeOs;
- });
-}
-
-import { getEnvApiKey } from "../env-api-keys.js";
-import { supportsXhigh } from "../models.js";
-import type {
- Api,
- AssistantMessage,
- Context,
- Model,
- SimpleStreamOptions,
- StreamFunction,
- StreamOptions,
- Usage,
-} from "../types.js";
-import { AssistantMessageEventStream } from "../utils/event-stream.js";
-import { convertResponsesMessages, convertResponsesTools, processResponsesStream } from "./openai-responses-shared.js";
-import { buildBaseOptions, clampReasoning } from "./simple-options.js";
-
-// ============================================================================
-// Configuration
-// ============================================================================
-
-const DEFAULT_CODEX_BASE_URL = "https://chatgpt.com/backend-api";
-const JWT_CLAIM_PATH = "https://api.openai.com/auth" as const;
-const MAX_RETRIES = 3;
-const BASE_DELAY_MS = 1000;
-const CODEX_TOOL_CALL_PROVIDERS = new Set(["openai", "openai-codex", "opencode"]);
-
-const CODEX_RESPONSE_STATUSES = new Set([
- "completed",
- "incomplete",
- "failed",
- "cancelled",
- "queued",
- "in_progress",
-]);
-
-// ============================================================================
-// Types
-// ============================================================================
-
-export interface OpenAICodexResponsesOptions extends StreamOptions {
- reasoningEffort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh";
- reasoningSummary?: "auto" | "concise" | "detailed" | "off" | "on" | null;
- serviceTier?: ResponseCreateParamsStreaming["service_tier"];
- textVerbosity?: "low" | "medium" | "high";
-}
-
-type CodexResponseStatus = "completed" | "incomplete" | "failed" | "cancelled" | "queued" | "in_progress";
-
-interface RequestBody {
- model: string;
- store?: boolean;
- stream?: boolean;
- instructions?: string;
- input?: ResponseInput;
- tools?: OpenAITool[];
- tool_choice?: "auto";
- parallel_tool_calls?: boolean;
- temperature?: number;
- reasoning?: { effort?: string; summary?: string };
- service_tier?: ResponseCreateParamsStreaming["service_tier"];
- text?: { verbosity?: string };
- include?: string[];
- prompt_cache_key?: string;
- [key: string]: unknown;
-}
-
-// ============================================================================
-// Retry Helpers
-// ============================================================================
-
-function isRetryableError(status: number, errorText: string): boolean {
- if (status === 429 || status === 500 || status === 502 || status === 503 || status === 504) {
- return true;
- }
- return /rate.?limit|overloaded|service.?unavailable|upstream.?connect|connection.?refused/i.test(errorText);
-}
-
-function sleep(ms: number, signal?: AbortSignal): Promise {
- return new Promise((resolve, reject) => {
- if (signal?.aborted) {
- reject(new Error("Request was aborted"));
- return;
- }
- const timeout = setTimeout(resolve, ms);
- signal?.addEventListener("abort", () => {
- clearTimeout(timeout);
- reject(new Error("Request was aborted"));
- });
- });
-}
-
-// ============================================================================
-// Main Stream Function
-// ============================================================================
-
-export const streamOpenAICodexResponses: StreamFunction<"openai-codex-responses", OpenAICodexResponsesOptions> = (
- model: Model<"openai-codex-responses">,
- context: Context,
- options?: OpenAICodexResponsesOptions,
-): AssistantMessageEventStream => {
- const stream = new AssistantMessageEventStream();
-
- (async () => {
- const output: AssistantMessage = {
- role: "assistant",
- content: [],
- api: "openai-codex-responses" as Api,
- provider: model.provider,
- model: model.id,
- usage: {
- input: 0,
- output: 0,
- cacheRead: 0,
- cacheWrite: 0,
- totalTokens: 0,
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
- },
- stopReason: "stop",
- timestamp: Date.now(),
- };
-
- try {
- const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
- if (!apiKey) {
- throw new Error(`No API key for provider: ${model.provider}`);
- }
-
- const accountId = extractAccountId(apiKey);
- let body = buildRequestBody(model, context, options);
- const nextBody = await options?.onPayload?.(body, model);
- if (nextBody !== undefined) {
- body = nextBody as RequestBody;
- }
- const websocketRequestId = options?.sessionId || createCodexRequestId();
- const sseHeaders = buildSSEHeaders(model.headers, options?.headers, accountId, apiKey, options?.sessionId);
- const websocketHeaders = buildWebSocketHeaders(
- model.headers,
- options?.headers,
- accountId,
- apiKey,
- websocketRequestId,
- );
- const bodyJson = JSON.stringify(body);
- const transport = options?.transport || "sse";
-
- if (transport !== "sse") {
- let websocketStarted = false;
- try {
- await processWebSocketStream(
- resolveCodexWebSocketUrl(model.baseUrl),
- body,
- websocketHeaders,
- output,
- stream,
- model,
- () => {
- websocketStarted = true;
- },
- options,
- );
-
- if (options?.signal?.aborted) {
- throw new Error("Request was aborted");
- }
- stream.push({
- type: "done",
- reason: output.stopReason as "stop" | "length" | "toolUse",
- message: output,
- });
- stream.end();
- return;
- } catch (error) {
- if (transport === "websocket" || websocketStarted) {
- throw error;
- }
- }
- }
-
- // Fetch with retry logic for rate limits and transient errors
- let response: Response | undefined;
- let lastError: Error | undefined;
-
- for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
- if (options?.signal?.aborted) {
- throw new Error("Request was aborted");
- }
-
- try {
- response = await fetch(resolveCodexUrl(model.baseUrl), {
- method: "POST",
- headers: sseHeaders,
- body: bodyJson,
- signal: options?.signal,
- });
-
- if (response.ok) {
- break;
- }
-
- const errorText = await response.text();
- if (attempt < MAX_RETRIES && isRetryableError(response.status, errorText)) {
- const delayMs = BASE_DELAY_MS * 2 ** attempt;
- await sleep(delayMs, options?.signal);
- continue;
- }
-
- // Parse error for friendly message on final attempt or non-retryable error
- const fakeResponse = new Response(errorText, {
- status: response.status,
- statusText: response.statusText,
- });
- const info = await parseErrorResponse(fakeResponse);
- throw new Error(info.friendlyMessage || info.message);
- } catch (error) {
- if (error instanceof Error) {
- if (error.name === "AbortError" || error.message === "Request was aborted") {
- throw new Error("Request was aborted");
- }
- }
- lastError = error instanceof Error ? error : new Error(String(error));
- // Network errors are retryable
- if (attempt < MAX_RETRIES && !lastError.message.includes("usage limit")) {
- const delayMs = BASE_DELAY_MS * 2 ** attempt;
- await sleep(delayMs, options?.signal);
- continue;
- }
- throw lastError;
- }
- }
-
- if (!response?.ok) {
- throw lastError ?? new Error("Failed after retries");
- }
-
- if (!response.body) {
- throw new Error("No response body");
- }
-
- stream.push({ type: "start", partial: output });
- await processStream(response, output, stream, model, options);
-
- if (options?.signal?.aborted) {
- throw new Error("Request was aborted");
- }
-
- stream.push({ type: "done", reason: output.stopReason as "stop" | "length" | "toolUse", message: output });
- stream.end();
- } catch (error) {
- for (const block of output.content) {
- // partialJson is only a streaming scratch buffer; never persist it.
- delete (block as { partialJson?: string }).partialJson;
- }
- output.stopReason = options?.signal?.aborted ? "aborted" : "error";
- output.errorMessage = error instanceof Error ? error.message : String(error);
- stream.push({ type: "error", reason: output.stopReason, error: output });
- stream.end();
- }
- })();
-
- return stream;
-};
-
-export const streamSimpleOpenAICodexResponses: StreamFunction<"openai-codex-responses", SimpleStreamOptions> = (
- model: Model<"openai-codex-responses">,
- context: Context,
- options?: SimpleStreamOptions,
-): AssistantMessageEventStream => {
- const apiKey = options?.apiKey || getEnvApiKey(model.provider);
- if (!apiKey) {
- throw new Error(`No API key for provider: ${model.provider}`);
- }
-
- const base = buildBaseOptions(model, options, apiKey);
- const reasoningEffort = supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning);
-
- return streamOpenAICodexResponses(model, context, {
- ...base,
- reasoningEffort,
- } satisfies OpenAICodexResponsesOptions);
-};
-
-// ============================================================================
-// Request Building
-// ============================================================================
-
-function buildRequestBody(
- model: Model<"openai-codex-responses">,
- context: Context,
- options?: OpenAICodexResponsesOptions,
-): RequestBody {
- const messages = convertResponsesMessages(model, context, CODEX_TOOL_CALL_PROVIDERS, {
- includeSystemPrompt: false,
- });
-
- const body: RequestBody = {
- model: model.id,
- store: false,
- stream: true,
- instructions: context.systemPrompt,
- input: messages,
- text: { verbosity: options?.textVerbosity || "medium" },
- include: ["reasoning.encrypted_content"],
- prompt_cache_key: options?.sessionId,
- tool_choice: "auto",
- parallel_tool_calls: true,
- };
-
- if (options?.temperature !== undefined) {
- body.temperature = options.temperature;
- }
-
- if (options?.serviceTier !== undefined) {
- body.service_tier = options.serviceTier;
- }
-
- if (context.tools) {
- body.tools = convertResponsesTools(context.tools, { strict: null });
- }
-
- if (options?.reasoningEffort !== undefined) {
- body.reasoning = {
- effort: clampReasoningEffort(model.id, options.reasoningEffort),
- summary: options.reasoningSummary ?? "auto",
- };
- }
-
- return body;
-}
-
-function clampReasoningEffort(modelId: string, effort: string): string {
- const id = modelId.includes("/") ? modelId.split("/").pop()! : modelId;
- if ((id.startsWith("gpt-5.2") || id.startsWith("gpt-5.3") || id.startsWith("gpt-5.4")) && effort === "minimal")
- return "low";
- if (id === "gpt-5.1" && effort === "xhigh") return "high";
- if (id === "gpt-5.1-codex-mini") return effort === "high" || effort === "xhigh" ? "high" : "medium";
- return effort;
-}
-
-function getServiceTierCostMultiplier(serviceTier: ResponseCreateParamsStreaming["service_tier"] | undefined): number {
- switch (serviceTier) {
- case "flex":
- return 0.5;
- case "priority":
- return 2;
- default:
- return 1;
- }
-}
-
-function applyServiceTierPricing(usage: Usage, serviceTier: ResponseCreateParamsStreaming["service_tier"] | undefined) {
- const multiplier = getServiceTierCostMultiplier(serviceTier);
- if (multiplier === 1) return;
-
- usage.cost.input *= multiplier;
- usage.cost.output *= multiplier;
- usage.cost.cacheRead *= multiplier;
- usage.cost.cacheWrite *= multiplier;
- usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
-}
-
-function resolveCodexUrl(baseUrl?: string): string {
- const raw = baseUrl && baseUrl.trim().length > 0 ? baseUrl : DEFAULT_CODEX_BASE_URL;
- const normalized = raw.replace(/\/+$/, "");
- if (normalized.endsWith("/codex/responses")) return normalized;
- if (normalized.endsWith("/codex")) return `${normalized}/responses`;
- return `${normalized}/codex/responses`;
-}
-
-function resolveCodexWebSocketUrl(baseUrl?: string): string {
- const url = new URL(resolveCodexUrl(baseUrl));
- if (url.protocol === "https:") url.protocol = "wss:";
- if (url.protocol === "http:") url.protocol = "ws:";
- return url.toString();
-}
-
-// ============================================================================
-// Response Processing
-// ============================================================================
-
-async function processStream(
- response: Response,
- output: AssistantMessage,
- stream: AssistantMessageEventStream,
- model: Model<"openai-codex-responses">,
- options?: OpenAICodexResponsesOptions,
-): Promise {
- await processResponsesStream(mapCodexEvents(parseSSE(response)), output, stream, model, {
- serviceTier: options?.serviceTier,
- applyServiceTierPricing,
- });
-}
-
-async function* mapCodexEvents(events: AsyncIterable>): AsyncGenerator {
- for await (const event of events) {
- const type = typeof event.type === "string" ? event.type : undefined;
- if (!type) continue;
-
- if (type === "error") {
- const code = (event as { code?: string }).code || "";
- const message = (event as { message?: string }).message || "";
- throw new Error(`Codex error: ${message || code || JSON.stringify(event)}`);
- }
-
- if (type === "response.failed") {
- const msg = (event as { response?: { error?: { message?: string } } }).response?.error?.message;
- throw new Error(msg || "Codex response failed");
- }
-
- if (type === "response.done" || type === "response.completed" || type === "response.incomplete") {
- const response = (event as { response?: { status?: unknown } }).response;
- const normalizedResponse = response
- ? { ...response, status: normalizeCodexStatus(response.status) }
- : response;
- yield { ...event, type: "response.completed", response: normalizedResponse } as ResponseStreamEvent;
- return;
- }
-
- yield event as unknown as ResponseStreamEvent;
- }
-}
-
-function normalizeCodexStatus(status: unknown): CodexResponseStatus | undefined {
- if (typeof status !== "string") return undefined;
- return CODEX_RESPONSE_STATUSES.has(status as CodexResponseStatus) ? (status as CodexResponseStatus) : undefined;
-}
-
-// ============================================================================
-// SSE Parsing
-// ============================================================================
-
-async function* parseSSE(response: Response): AsyncGenerator> {
- if (!response.body) return;
-
- const reader = response.body.getReader();
- const decoder = new TextDecoder();
- let buffer = "";
-
- try {
- while (true) {
- const { done, value } = await reader.read();
- if (done) break;
- buffer += decoder.decode(value, { stream: true });
-
- let idx = buffer.indexOf("\n\n");
- while (idx !== -1) {
- const chunk = buffer.slice(0, idx);
- buffer = buffer.slice(idx + 2);
-
- const dataLines = chunk
- .split("\n")
- .filter((l) => l.startsWith("data:"))
- .map((l) => l.slice(5).trim());
- if (dataLines.length > 0) {
- const data = dataLines.join("\n").trim();
- if (data && data !== "[DONE]") {
- try {
- yield JSON.parse(data);
- } catch {}
- }
- }
- idx = buffer.indexOf("\n\n");
- }
- }
- } finally {
- try {
- await reader.cancel();
- } catch {}
- try {
- reader.releaseLock();
- } catch {}
- }
-}
-
-// ============================================================================
-// WebSocket Parsing
-// ============================================================================
-
-const OPENAI_BETA_RESPONSES_WEBSOCKETS = "responses_websockets=2026-02-06";
-const SESSION_WEBSOCKET_CACHE_TTL_MS = 5 * 60 * 1000;
-
-type WebSocketEventType = "open" | "message" | "error" | "close";
-type WebSocketListener = (event: unknown) => void;
-
-interface WebSocketLike {
- close(code?: number, reason?: string): void;
- send(data: string): void;
- addEventListener(type: WebSocketEventType, listener: WebSocketListener): void;
- removeEventListener(type: WebSocketEventType, listener: WebSocketListener): void;
-}
-
-interface CachedWebSocketConnection {
- socket: WebSocketLike;
- busy: boolean;
- idleTimer?: ReturnType;
-}
-
-const websocketSessionCache = new Map();
-
-type WebSocketConstructor = new (
- url: string,
- protocols?: string | string[] | { headers?: Record