diff --git a/.github/workflows/check-data-health.yml b/.github/workflows/check-data-health.yml new file mode 100644 index 00000000..67510236 --- /dev/null +++ b/.github/workflows/check-data-health.yml @@ -0,0 +1,119 @@ +name: Check Current Data Health + +on: + schedule: + - cron: '0 3 * * 1' + workflow_dispatch: + +concurrency: + group: check-current-data-health + cancel-in-progress: false + +permissions: + contents: read + issues: write + +jobs: + check-data-health: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v7 + + - name: Setup Node.js + uses: actions/setup-node@v7 + with: + node-version: '22' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Check current data health + id: data-health + continue-on-error: true + run: | + npx tsx scripts/validate/data-health.ts \ + --as-of="$(TZ=Asia/Shanghai date +%F)" \ + --fail-on=error \ + --fail-on-code=stale-verification,future-verification-date \ + 2>&1 | tee data-health-current.log + + - name: Report stale or invalid data + if: steps.data-health.outcome == 'failure' + uses: actions/github-script@v8 + with: + script: | + const fs = require('node:fs'); + const title = 'Current manifest data requires review'; + const output = fs.readFileSync('data-health-current.log', 'utf8').slice(-6000); + const body = `## Current Data Health Check Failed + + The scheduled check evaluates freshness against today's date in Asia/Shanghai without + rewriting the committed snapshot. + + **Check run:** [View details](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) + + \`\`\`text + ${output} + \`\`\``; + + const issues = await github.paginate(github.rest.issues.listForRepo, { + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + labels: 'automated', + per_page: 100 + }); + const existingIssue = issues.find(issue => issue.title === title); + + if (!existingIssue) { + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title, + body, + labels: ['automated', 'maintenance'] + }); + } else { + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: existingIssue.number, + body + }); + } + + - name: Close resolved data-health issues + if: steps.data-health.outcome == 'success' + uses: actions/github-script@v8 + with: + script: | + const issues = await github.paginate(github.rest.issues.listForRepo, { + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + labels: 'automated', + per_page: 100 + }); + + for (const issue of issues.filter(issue => issue.title === 'Current manifest data requires review')) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + body: `Current-date data health passed in ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}.` + }); + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + state: 'closed', + state_reason: 'completed' + }); + } + + - name: Fail after reporting + if: steps.data-health.outcome == 'failure' + run: exit 1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 861675dd..1cf4b0b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,11 +73,6 @@ jobs: - name: Check data health run: npm run data-health:check - - name: Check manifest changelog - run: npm run changelog:check - env: - CHANGELOG_BASE: ${{ github.event.pull_request.base.sha || github.event.before }} - spell-check: name: Spell Check runs-on: ubuntu-latest diff --git a/.github/workflows/monitor-model-sources.yml b/.github/workflows/monitor-model-sources.yml new file mode 100644 index 00000000..3bea449f --- /dev/null +++ b/.github/workflows/monitor-model-sources.yml @@ -0,0 +1,65 @@ +name: Monitor Model Pricing and Lifecycle Sources + +on: + schedule: + - cron: '0 4 * * 1' + workflow_dispatch: + +concurrency: + group: monitor-model-sources + cancel-in-progress: false + +permissions: + contents: write + pull-requests: write + +jobs: + monitor-model-sources: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v7 + + - name: Setup Node.js + uses: actions/setup-node@v7 + with: + node-version: '22' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Check monitored official sources + run: npm run fetch:model-sources + + - name: Validate monitoring metadata + run: | + npm run test:validate + npm run format:check + npm run biome:check + git diff --check + + - name: Check for changes + id: git-check + run: | + git diff --exit-code manifests/models || echo "changes=true" >> "$GITHUB_OUTPUT" + + - name: Create review pull request + if: steps.git-check.outputs.changes == 'true' + uses: peter-evans/create-pull-request@v8 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: 'chore(data): flag changed model sources' + title: 'chore(data): review changed model sources' + body: | + ## Review required + One or more monitored official pricing or lifecycle pages changed. + + This automation updates only normalized source-content digests and observation dates. + It deliberately does **not** change token prices, model availability, lifecycle status, + or any other model fact. Review the cited official pages before changing those fields. + branch: auto-review-model-sources + delete-branch: true + labels: | + automated diff --git a/.github/workflows/update-benchmarks.yml b/.github/workflows/update-benchmarks.yml new file mode 100644 index 00000000..2dc59c28 --- /dev/null +++ b/.github/workflows/update-benchmarks.yml @@ -0,0 +1,73 @@ +name: Update Benchmarks + +on: + schedule: + - cron: '30 2 * * 1' + workflow_dispatch: + +concurrency: + group: update-benchmarks + cancel-in-progress: false + +permissions: + contents: write + pull-requests: write + +jobs: + update-benchmarks: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v7 + + - name: Setup Node.js + uses: actions/setup-node@v7 + with: + node-version: '22' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Refresh exact benchmark mappings + run: npm run fetch:benchmarks + + - name: Regenerate manifest modules + run: npm run generate:manifests + + - name: Validate updated data + run: | + npm run test:validate + npm run data-health:check + npm run format:check + npm run biome:check + git diff --check + + - name: Check for changes + id: git-check + run: | + git diff --exit-code manifests src/lib/generated || echo "changes=true" >> "$GITHUB_OUTPUT" + + - name: Create pull request + if: steps.git-check.outputs.changes == 'true' + uses: peter-evans/create-pull-request@v8 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: 'chore(data): refresh benchmark scores' + title: 'chore(data): refresh benchmark scores' + body: | + ## Summary + Automated refresh from exact entries in the official SWE-bench leaderboard data. + + Each model manifest declares the upstream result ID and exact displayed label. The + refresh fails rather than applying fuzzy model-name matching. + + ## Validation + - Manifest schemas + - Generated manifest modules + - Data health + branch: auto-update-benchmarks + delete-branch: true + labels: | + automated diff --git a/.github/workflows/update-product-versions.yml b/.github/workflows/update-product-versions.yml new file mode 100644 index 00000000..46f51898 --- /dev/null +++ b/.github/workflows/update-product-versions.yml @@ -0,0 +1,76 @@ +name: Update Product Versions + +on: + schedule: + - cron: '0 2 * * 1' + workflow_dispatch: + +concurrency: + group: update-product-versions + cancel-in-progress: false + +permissions: + contents: write + pull-requests: write + +jobs: + update-product-versions: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v7 + + - name: Setup Node.js + uses: actions/setup-node@v7 + with: + node-version: '22' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Refresh tracked product versions + run: npm run fetch:product-versions + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Regenerate manifest modules + run: npm run generate:manifests + + - name: Validate updated data + run: | + npm run test:validate + npm run validate:i18n + npm run data-health:check + npm run format:check + npm run biome:check + git diff --check + + - name: Check for changes + id: git-check + run: | + git diff --exit-code manifests src/lib/generated || echo "changes=true" >> "$GITHUB_OUTPUT" + + - name: Create pull request + if: steps.git-check.outputs.changes == 'true' + uses: peter-evans/create-pull-request@v8 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: 'chore(data): refresh product versions' + title: 'chore(data): refresh product versions' + body: | + ## Summary + Automated refresh of product versions from the registry sources declared in each manifest. + + ## Validation + - Manifest schemas + - Generated manifest modules + - Internationalization structure + - Data health + + The workflow preserves existing values when any configured source cannot be verified. + branch: auto-update-product-versions + delete-branch: true + labels: | + automated diff --git a/AGENTS.md b/AGENTS.md index 9b553914..45d0922f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,104 +1,37 @@ # AGENTS.md -This file provides guidance to Codex (Codex.ai/code) when working with code in this repository. +## Internationalization -## Internationalization (i18n) +- Translation resources live under `translations/`. Every page, module, and data change must support every locale configured in `src/i18n/config.ts`; never hardcode a locale subset. +- Always use `Link` from `@/i18n/navigation`, not the Next.js default. +- Localize page metadata and reuse existing translation keys and shared phrases before adding new ones. +- Follow [docs/I18N-ARCHITECTURE-RULES.md](docs/I18N-ARCHITECTURE-RULES.md): keep page and component translations in their prescribed namespaces, co-locate page metadata under `meta`, and minimize cross-namespace `@:` references. +- Add new keys to every locale with English placeholders first; perform proper translation as a separate batch. -**Translation Resources Location:** All translation files are located in the `translations/` directory at the project root, organized by locale code (e.g., `translations/en/`, `translations/zh-Hans/`). +## Data and Schema -When creating or modifying any page, module, or data: -- **MUST support all configured languages (12 total):** - - English (en) - - German (de) - - Spanish (es) - - French (fr) - - Indonesian (id) - - Japanese (ja) - - Korean (ko) - - Portuguese (pt) - - Russian (ru) - - Turkish (tr) - - Simplified Chinese (zh-Hans) - - Traditional Chinese (zh-Hant) +- Never store product, catalog, editorial, ranking, pricing, benchmark, configuration, or other independently adjustable data in `.ts` or `.tsx` files. +- Store data in schema-validated JSON under `data/`, the appropriate manifest, or translation resources. This includes curated selections, display order, metadata, prices, scores, timelines, chart-label placement, and ranking weights. +- TypeScript may contain types, loaders, validators, transformations, calculations, presentation logic, and implementation-only constants with no product or editorial meaning. When uncertain, treat a value as data. +- Update the JSON schema, corresponding TypeScript type, and validation tests together whenever a data shape changes. +- Keep `src/types/manifests.ts` in one-to-one correspondence with the schemas under `manifests/$schemas/`. -- **NEVER hardcode** a subset of locales like `'en' | 'zh-Hans'` -- **MUST use the localized Link component:** Always import and use `import { Link } from '@/i18n/navigation'` instead of Next.js default Link +## Design -### Localization Best Practices +- Use the existing extremely minimalist visual language: sharp corners, restrained low-saturation color, and accents only where necessary. +- Prefer Lucide SVG icons; do not use emoji or text characters as icons. +- Use `max-w-8xl` globally and `max-w-6xl` for content pages and the homepage. -- **Metadata localization:** All meta information (titles, descriptions, keywords, OG tags, etc.) in pages MUST be properly localized -- **DRY principle for translations:** Before creating new translation keys, search existing translation modules thoroughly to reuse existing terms and phrases -- **Consistency:** Use the same translation keys across similar contexts +## Metadata and SEO -### Translation File Organization - -Follow the detailed architecture rules in [docs/I18N-ARCHITECTURE-RULES.md](docs/I18N-ARCHITECTURE-RULES.md) for organizing translation resources. - -**Core Principles:** -1. **Page translations**: Each page or page group should have its own JSON file (e.g., `ides.json`, `ide-detail.json`) -2. **Component translations**: Organize by component directory: - - `components/common.json` - Root-level components (Header, Footer, etc.) - - `components/navigation.json` - All navigation/* components - - `components/controls.json` - All controls/* components - - `components/sidebar.json` - All sidebar/* components - - `components/product.json` - All product/* components -3. **Minimize `@:` references**: Use `tPage + tShared` or `tComponent + tShared` patterns in code instead of cross-namespace references in JSON -4. **Metadata placement**: Co-locate page metadata (title, description, etc.) with page translations under a `meta` object -5. **Multi-language workflow**: New translation keys should initially use English placeholders across all locales, with proper translation in a separate batch step - -**Usage Pattern:** -```tsx -// Pages -const tPage = useTranslations('pages.modelDetail') -const tShared = useTranslations('shared') - -// Components (root-level) -const tComponent = useTranslations('components.common.header') - -// Components (subdirectories) -const tComponent = useTranslations('components.navigation.breadcrumb') -``` - -## Design System - -**Global Design Principles:** - -- **Minimalist approach:** Follow a unified, extremely minimalist design style throughout the entire application -- **No rounded corners:** All controls, components, labels, and UI elements MUST use sharp corners (border-radius: 0) -- **Restrained color usage:** Use colors extremely sparingly and intentionally. Prefer grayscale and limit accent colors to essential UI elements only. If colors must be used, prefer low-saturation designs. -- **Icon usage:** Prefer using Lucide SVG icons. Avoid using emoji or any other characters as icons. -- **Page width:** - - `max-w-8xl`: for all pages globally - - `max-w-6xl`: for content pages and homepage - -## Coding Principles - -### DRY - Don't Repeat Yourself -- Eliminate code duplication by extracting common logic -- Reuse existing components, functions, and translation keys -- Create shared utilities when patterns emerge - -### Type Safety & Schema Alignment -- **Manifest type definitions:** Always ensure that `src/types/manifests.ts` stays in one-to-one correspondence with the JSON schemas in `manifests/$schemas/` -- When modifying schema files, update the corresponding TypeScript types accordingly -- When adding new types, verify they match the schema structure exactly -- Maintain consistency between schema definitions and type definitions to prevent runtime errors - -## Metadata & SEO - -- **File-based OG images:** Use `opengraph-image.tsx` files for all routes, NOT code-based image paths -- **Request memoization:** Wrap all data fetchers with React `cache()` to prevent duplicate fetching in `generateMetadata()` and page components -- **Type-safe locales:** Always use `import type { Locale } from '@/i18n/config'` -- **Auto-detected OG images:** Do NOT manually specify `images` in OpenGraph metadata - Next.js auto-detects `opengraph-image.tsx` files - -**OG Image Design:** -- Size: 1200x630px (OpenGraph standard) -- Follow global design system strictly +- Use route-level `opengraph-image.tsx` files; do not manually set OpenGraph image paths. OG images are 1200×630 and follow the design system. +- Wrap data fetchers shared by `generateMetadata()` and page rendering with React `cache()`. +- Use `Locale` from `@/i18n/config` for locale types. ## Development Workflow -- **Development server:** Do not start `npm run dev` automatically. User will start it manually when needed. -- **Standalone preview assets:** Before starting `.next/standalone/server.js`, sync `public/` into `.next/standalone/public/` and `.next/static/` into `.next/standalone/.next/static/`. Repeat this after every production build because Next.js regenerates `.next/standalone/`. Never start the standalone server without these assets. -- **Standalone preview host:** The standalone server `HOSTNAME` must match the hostname used in the preview URL. For a `http://localhost:` preview, start with `HOSTNAME=localhost`; do not substitute `127.0.0.1`, because locale middleware rewrites can otherwise become self-redirects. -- **Standalone preview verification:** After starting or restarting a standalone preview, verify that one default-locale URL without a locale prefix returns `200`, one locale-prefixed URL returns `200`, and a stylesheet referenced by the page returns `200` with a CSS content type. When using tmux, include the asset sync and matching `HOSTNAME` in the pane start command. -- **Git commits:** Do not create commits autonomously. Always ask the user before committing changes. +- Do not start `npm run dev` automatically; the user starts it when needed. +- Before every `.next/standalone/server.js` start, including after each production build, sync `public/` to `.next/standalone/public/` and `.next/static/` to `.next/standalone/.next/static/`. +- Match standalone `HOSTNAME` to the preview URL hostname. For `http://localhost:`, use `HOSTNAME=localhost`, never `127.0.0.1`. +- After each standalone start or restart, verify a default-locale URL, a locale-prefixed URL, and a referenced stylesheet all return `200`, with the stylesheet served as CSS. A tmux start command must include asset sync and the matching `HOSTNAME`. +- Never create a commit without asking the user first. diff --git a/cspell.json b/cspell.json index ce31117e..9cc860e4 100644 --- a/cspell.json +++ b/cspell.json @@ -241,6 +241,7 @@ "mengdebug", "menginstal", "mnda", + "mistralai", "modalli", "modaliteleri", "modlu", @@ -248,6 +249,7 @@ "Modları", "multilíngue", "npmjs", + "pypi", "orkestr", "мультимодальный", "мультимодального", diff --git a/data/$schemas/model-intelligence-index.schema.json b/data/$schemas/model-intelligence-index.schema.json deleted file mode 100644 index c7e61ca1..00000000 --- a/data/$schemas/model-intelligence-index.schema.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "title": "Model Intelligence Index Configuration", - "description": "Editorial display configuration for the model intelligence ranking.", - "type": "object", - "properties": { - "$schema": { - "type": "string" - }, - "hiddenVendorIds": { - "type": "array", - "items": { - "type": "string", - "pattern": "^[a-z0-9-]+$" - }, - "uniqueItems": true - } - }, - "required": ["$schema", "hiddenVendorIds"], - "additionalProperties": false -} diff --git a/data/$schemas/model-price-intelligence-index.schema.json b/data/$schemas/model-price-intelligence-index.schema.json index 741d8183..019674fe 100644 --- a/data/$schemas/model-price-intelligence-index.schema.json +++ b/data/$schemas/model-price-intelligence-index.schema.json @@ -57,33 +57,10 @@ }, "linearLabelAnchor": { "$ref": "#/$defs/labelAnchor" - }, - "usdPriceOverride": { - "$ref": "#/$defs/usdPriceOverride" } }, "required": ["modelId", "labelDx", "labelDy", "labelAnchor"], "additionalProperties": false - }, - "usdPriceOverride": { - "type": "object", - "properties": { - "input": { - "type": "number", - "exclusiveMinimum": 0 - }, - "output": { - "type": "number", - "exclusiveMinimum": 0 - }, - "sourceUrl": { - "type": "string", - "format": "uri", - "pattern": "^https://" - } - }, - "required": ["input", "output", "sourceUrl"], - "additionalProperties": false } } } diff --git a/data/changelogs.json b/data/changelogs.json deleted file mode 100644 index 83e05aca..00000000 --- a/data/changelogs.json +++ /dev/null @@ -1,7937 +0,0 @@ -{ - "version": 1, - "entries": [ - { - "id": "2026-07-28-manifest-update", - "date": "2026-07-28", - "summary": "Catalog provenance and community links completed", - "changes": [ - { - "category": "clis", - "id": "amazon-q-developer-cli", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "clis", - "id": "amp-cli", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "clis", - "id": "augment-code-cli", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "clis", - "id": "claude-code-cli", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "clis", - "id": "cline-cli", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "clis", - "id": "codebuddy-cli", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "clis", - "id": "codex-cli", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "clis", - "id": "continue-cli", - "change": "updated", - "fields": [ - "communityUrls", - "description", - "latestVersion", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "translations", - "verified", - "confidence", - "deprecated", - "familyId", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "clis", - "id": "cursor-cli", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "clis", - "id": "droid-cli", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "clis", - "id": "gemini-cli", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "clis", - "id": "github-copilot-cli", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "clis", - "id": "gitlab-duo-cli", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "clis", - "id": "grok-build", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "clis", - "id": "junie-cli", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "clis", - "id": "kilo-code-cli", - "change": "updated", - "fields": [ - "communityUrls", - "docsUrl", - "latestVersion", - "resourceUrls", - "websiteUrl", - "confidence", - "familyId", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "clis", - "id": "kiro-cli", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "clis", - "id": "kode", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "clis", - "id": "neovate-code", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "clis", - "id": "omp", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "clis", - "id": "opencode", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "clis", - "id": "qoder-cli", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "clis", - "id": "rovo-dev-cli", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "desktops", - "id": "air", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "desktops", - "id": "codex-app", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "desktops", - "id": "factory-desktop", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "desktops", - "id": "opencode-desktop", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "desktops", - "id": "qoder", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "desktops", - "id": "stagewise", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "desktops", - "id": "trae-work", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "desktops", - "id": "verdent-deck", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "extensions", - "id": "amp", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "extensions", - "id": "augment-code", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "extensions", - "id": "claude-code", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "extensions", - "id": "cline", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "extensions", - "id": "codex", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "extensions", - "id": "continue", - "change": "updated", - "fields": [ - "communityUrls", - "description", - "latestVersion", - "pricing", - "relatedProducts", - "resourceUrls", - "supportedIdes", - "translations", - "verified", - "confidence", - "deprecated", - "familyId", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "extensions", - "id": "droid", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "extensions", - "id": "gemini-code-assist", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "extensions", - "id": "github-copilot", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "extensions", - "id": "jetbrains-junie", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "extensions", - "id": "kilo-code", - "change": "updated", - "fields": [ - "communityUrls", - "latestVersion", - "confidence", - "familyId", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "extensions", - "id": "opencode-extension", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "extensions", - "id": "qoder", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "extensions", - "id": "roo-code", - "change": "updated", - "fields": [ - "communityUrls", - "description", - "docsUrl", - "latestVersion", - "pricing", - "resourceUrls", - "translations", - "verified", - "websiteUrl", - "confidence", - "deprecated", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "extensions", - "id": "rovo-dev", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "extensions", - "id": "tabnine", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "extensions", - "id": "verdent", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "ides", - "id": "antigravity", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "ides", - "id": "codebuddy", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "ides", - "id": "cursor", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "ides", - "id": "intellij-idea", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "ides", - "id": "kiro", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "ides", - "id": "trae", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "ides", - "id": "vscode", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "ides", - "id": "windsurf", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "ides", - "id": "zed", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "models", - "id": "glm-4-6", - "change": "updated", - "fields": [ - "description", - "size", - "translations", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "glm-4-6v", - "change": "updated", - "fields": [ - "benchmarks", - "description", - "knowledgeCutoff", - "lifecycle", - "maxOutput", - "size", - "translations", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "gpt-4-1", - "change": "updated", - "fields": ["confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "models", - "id": "gpt-4o", - "change": "updated", - "fields": [ - "docsUrl", - "lifecycle", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "gpt-5", - "change": "updated", - "fields": ["docsUrl", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "models", - "id": "gpt-5-1", - "change": "updated", - "fields": ["docsUrl", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "models", - "id": "gpt-5-1-codex", - "change": "updated", - "fields": [ - "docsUrl", - "lifecycle", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "gpt-5-codex", - "change": "updated", - "fields": [ - "docsUrl", - "lifecycle", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "minimax-m2", - "change": "updated", - "fields": [ - "docsUrl", - "knowledgeCutoff", - "maxOutput", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "minimax-m2-1", - "change": "updated", - "fields": [ - "docsUrl", - "knowledgeCutoff", - "lifecycle", - "maxOutput", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "qwen3-coder-30b-a3b", - "change": "updated", - "fields": [ - "description", - "knowledgeCutoff", - "lifecycle", - "size", - "tokenPricing", - "translations", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "qwen3-coder-480b-a35b", - "change": "updated", - "fields": [ - "description", - "knowledgeCutoff", - "lifecycle", - "tokenPricing", - "translations", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "providers", - "id": "alibaba", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "providers", - "id": "anthropic", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "providers", - "id": "deepseek", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "providers", - "id": "google", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "providers", - "id": "meta", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "providers", - "id": "moonshot", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "providers", - "id": "openai", - "change": "updated", - "fields": ["communityUrls", "sources"] - }, - { - "category": "providers", - "id": "openrouter", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "providers", - "id": "siliconflow", - "change": "updated", - "fields": ["communityUrls", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "providers", - "id": "xai", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "providers", - "id": "z-ai", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "vendors", - "id": "alibaba", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "anomaly", - "change": "updated", - "fields": ["lastVerifiedAt", "sources", "verified"] - }, - { - "category": "vendors", - "id": "ant-group", - "change": "updated", - "fields": [ - "description", - "translations", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "anthropic", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "anysphere", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "atlassian", - "change": "updated", - "fields": ["lastVerifiedAt", "sources", "verified"] - }, - { - "category": "vendors", - "id": "augment", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "aws", - "change": "updated", - "fields": [ - "description", - "translations", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "bytedance", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "cline", - "change": "updated", - "fields": [ - "description", - "translations", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "cognition", - "change": "updated", - "fields": [ - "verified", - "websiteUrl", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "continue", - "change": "updated", - "fields": [ - "description", - "translations", - "verified", - "confidence", - "deprecated", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "deepseek", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "factory-ai", - "change": "updated", - "fields": [ - "description", - "translations", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "github", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "gitlab", - "change": "updated", - "fields": ["lastVerifiedAt", "sources", "verified"] - }, - { - "category": "vendors", - "id": "google", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "jetbrains", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "kilo", - "change": "updated", - "fields": ["confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "meta", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "microsoft", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "minimax", - "change": "updated", - "fields": [ - "communityUrls", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "mistral-ai", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "vendors", - "id": "moonshot", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "oh-my-pi", - "change": "updated", - "fields": ["lastVerifiedAt", "sources", "verified"] - }, - { - "category": "vendors", - "id": "openai", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "openrouter", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "roo-code", - "change": "updated", - "fields": [ - "description", - "translations", - "verified", - "websiteUrl", - "confidence", - "deprecated", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "shareai-lab", - "change": "updated", - "fields": [ - "description", - "translations", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "siliconflow", - "change": "updated", - "fields": ["confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "sourcegraph", - "change": "updated", - "fields": [ - "description", - "translations", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "sst", - "change": "updated", - "fields": [ - "communityUrls", - "description", - "translations", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "stagewise", - "change": "updated", - "fields": ["lastVerifiedAt", "sources", "verified"] - }, - { - "category": "vendors", - "id": "tabnine", - "change": "updated", - "fields": [ - "description", - "translations", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "tencent", - "change": "updated", - "fields": [ - "description", - "translations", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "verdent-ai", - "change": "updated", - "fields": [ - "description", - "translations", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "vendors", - "id": "xai", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "z-ai", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "zed-industries", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - } - ] - }, - { - "id": "2026-07-27-manifest-update", - "date": "2026-07-27", - "summary": "22 manifest records changed", - "changes": [ - { - "category": "models", - "id": "claude-opus-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemma-4-26b-a4b", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemma-4-31b", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "hy3", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "mimo-v2-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "mimo-v2-5-pro", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "mimo-v2-flash", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-5-122b-a10b", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-5-35b-a3b", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-5-397b-a17b", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "alibaba", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "anthropic", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "deepseek", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "google", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "kilo", - "change": "updated", - "fields": ["confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "moonshot", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "openai", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "siliconflow", - "change": "updated", - "fields": ["confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "tencent", - "change": "updated", - "fields": ["themeColor"] - }, - { - "category": "vendors", - "id": "xai", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "vendors", - "id": "xiaomi", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "id", - "lastVerifiedAt", - "name", - "sources", - "themeColor", - "translations", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "z-ai", - "change": "updated", - "fields": ["verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - } - ] - }, - { - "id": "2026-07-26-manifest-update", - "date": "2026-07-26", - "summary": "77 manifest records changed", - "changes": [ - { - "category": "clis", - "id": "antigravity-cli", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "clis", - "id": "deepv-code", - "change": "removed", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "clis", - "id": "gemini-cli", - "change": "updated", - "fields": [ - "latestVersion", - "pricing", - "relatedProducts", - "verified", - "confidence", - "deprecated", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "clis", - "id": "grok-build", - "change": "updated", - "fields": [ - "communityUrls", - "githubUrl", - "lastVerifiedAt", - "latestVersion", - "resourceUrls", - "sources" - ] - }, - { - "category": "ides", - "id": "antigravity", - "change": "updated", - "fields": ["relatedProducts", "familyId"] - }, - { - "category": "ides", - "id": "codeflicker", - "change": "removed", - "fields": [ - "communityUrls", - "description", - "docsUrl", - "githubUrl", - "id", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "translations", - "vendor", - "verified", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-fable-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-haiku-4-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-mythos-5", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-opus-4", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-opus-4-1", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-opus-4-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-opus-4-8", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-sonnet-4", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-sonnet-4-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-sonnet-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "codestral-2405", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "codestral-2501", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "codestral-2508", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "composer", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "deepseek-coder-v2-0724", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "devstral-medium-1-0", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "devstral-small-1-0", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "devstral-small-1-1", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-2-0-flash-lite", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-3-1-flash-lite", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-3-1-pro-preview", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gemini-3-5-flash", - "change": "updated", - "fields": ["lastVerifiedAt", "lifecycle", "size"] - }, - { - "category": "models", - "id": "gemini-3-5-flash-lite", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-3-6-flash", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-3-flash", - "change": "updated", - "fields": ["lastVerifiedAt", "lifecycle", "size"] - }, - { - "category": "models", - "id": "gemini-3-pro", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "glm-4-5-air", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "glm-4-5v", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "glm-4-7-flash", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "glm-5-turbo", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "glm-5v-turbo", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-4-1", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-4o", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-1", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-1-codex", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-1-codex-max", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-2", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-2-pro", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-4-pro", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-5-pro", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-6-luna", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-6-sol", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-6-terra", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-codex", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-pro", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "grok-build-0-1", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "grok-code-fast-1", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "kat-coder-pro-v1", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "tokenPricing", - "translations", - "vendor", - "verified", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "kimi-dev-72b", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-5-plus", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-6-27b", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-6-35b-a3b", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-6-max-preview", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "deprecated", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-coder-flash", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-coder-plus", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "tokenPricing", - "translations", - "vendor", - "verified", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-max-2026-01-23", - "change": "removed", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "providers", - "id": "kwaikatonai", - "change": "removed", - "fields": [ - "applyKeyUrl", - "communityUrls", - "description", - "docsUrl", - "id", - "name", - "platformUrls", - "translations", - "type", - "vendor", - "verified", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "alibaba", - "change": "updated", - "fields": ["themeColor"] - }, - { - "category": "vendors", - "id": "anthropic", - "change": "updated", - "fields": ["themeColor"] - }, - { - "category": "vendors", - "id": "deepseek", - "change": "updated", - "fields": ["themeColor"] - }, - { - "category": "vendors", - "id": "google", - "change": "updated", - "fields": ["themeColor"] - }, - { - "category": "vendors", - "id": "meta", - "change": "updated", - "fields": ["themeColor"] - }, - { - "category": "vendors", - "id": "minimax", - "change": "updated", - "fields": ["themeColor"] - }, - { - "category": "vendors", - "id": "mistral-ai", - "change": "updated", - "fields": ["themeColor"] - }, - { - "category": "vendors", - "id": "moonshot", - "change": "updated", - "fields": ["themeColor"] - }, - { - "category": "vendors", - "id": "openai", - "change": "updated", - "fields": ["themeColor"] - }, - { - "category": "vendors", - "id": "orionstar", - "change": "removed", - "fields": [ - "communityUrls", - "description", - "id", - "name", - "translations", - "verified", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "streamlake", - "change": "removed", - "fields": [ - "aliases", - "communityUrls", - "description", - "id", - "name", - "translations", - "verified", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "xai", - "change": "updated", - "fields": ["themeColor"] - }, - { - "category": "vendors", - "id": "z-ai", - "change": "updated", - "fields": ["themeColor"] - } - ] - }, - { - "id": "2026-07-25-manifest-update", - "date": "2026-07-25", - "summary": "33 manifest records changed", - "changes": [ - { - "category": "clis", - "id": "antigravity-cli", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "clis", - "id": "gemini-cli", - "change": "updated", - "fields": [ - "latestVersion", - "pricing", - "relatedProducts", - "verified", - "confidence", - "deprecated", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "clis", - "id": "grok-build", - "change": "updated", - "fields": [ - "communityUrls", - "githubUrl", - "lastVerifiedAt", - "latestVersion", - "resourceUrls", - "sources" - ] - }, - { - "category": "ides", - "id": "antigravity", - "change": "updated", - "fields": ["relatedProducts", "familyId"] - }, - { - "category": "models", - "id": "claude-fable-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-haiku-4-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-opus-4", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-opus-4-1", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-opus-4-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-opus-4-8", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-sonnet-4", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-sonnet-4-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-sonnet-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "composer", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gemini-3-1-flash-lite", - "change": "updated", - "fields": ["lastVerifiedAt", "lifecycle", "size"] - }, - { - "category": "models", - "id": "gemini-3-1-pro-preview", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gemini-3-5-flash", - "change": "updated", - "fields": ["lastVerifiedAt", "lifecycle", "size"] - }, - { - "category": "models", - "id": "gemini-3-5-flash-lite", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-3-6-flash", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-3-flash", - "change": "updated", - "fields": ["lastVerifiedAt", "lifecycle", "size"] - }, - { - "category": "models", - "id": "gemini-3-pro", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-4-1", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-4o", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-1", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-1-codex", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-2", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-6-luna", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-6-sol", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-6-terra", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-codex", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "grok-code-fast-1", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "kat-coder-pro-v1", - "change": "updated", - "fields": ["size"] - } - ] - }, - { - "id": "2026-07-22-manifest-update", - "date": "2026-07-22", - "summary": "33 manifest records changed", - "changes": [ - { - "category": "clis", - "id": "antigravity-cli", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "clis", - "id": "gemini-cli", - "change": "updated", - "fields": [ - "latestVersion", - "pricing", - "relatedProducts", - "verified", - "confidence", - "deprecated", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "clis", - "id": "grok-build", - "change": "updated", - "fields": [ - "communityUrls", - "githubUrl", - "lastVerifiedAt", - "latestVersion", - "resourceUrls", - "sources" - ] - }, - { - "category": "ides", - "id": "antigravity", - "change": "updated", - "fields": ["relatedProducts", "familyId"] - }, - { - "category": "models", - "id": "claude-fable-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-haiku-4-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-opus-4", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-opus-4-1", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-opus-4-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-opus-4-8", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-sonnet-4", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-sonnet-4-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "claude-sonnet-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "composer", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gemini-3-1-flash-lite", - "change": "updated", - "fields": ["lastVerifiedAt", "lifecycle", "size"] - }, - { - "category": "models", - "id": "gemini-3-1-pro-preview", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gemini-3-5-flash", - "change": "updated", - "fields": ["lastVerifiedAt", "lifecycle", "size"] - }, - { - "category": "models", - "id": "gemini-3-5-flash-lite", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-3-6-flash", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-3-flash", - "change": "updated", - "fields": ["lastVerifiedAt", "lifecycle", "size"] - }, - { - "category": "models", - "id": "gemini-3-pro", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-4-1", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-4o", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-1", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-1-codex", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-2", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-6-luna", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-6-sol", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-6-terra", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "gpt-5-codex", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "grok-code-fast-1", - "change": "updated", - "fields": ["size"] - }, - { - "category": "models", - "id": "kat-coder-pro-v1", - "change": "updated", - "fields": ["size"] - } - ] - }, - { - "id": "2026-07-21-url-validation", - "date": "2026-07-21", - "summary": "Normalized and repaired manifest URLs flagged by scheduled validation", - "changes": [ - { - "category": "clis", - "id": "amazon-q-developer-cli", - "change": "updated", - "fields": ["websiteUrl"] - }, - { - "category": "clis", - "id": "deepv-code", - "change": "updated", - "fields": ["docsUrl", "websiteUrl"] - }, - { - "category": "clis", - "id": "droid-cli", - "change": "updated", - "fields": ["resourceUrls"] - }, - { - "category": "clis", - "id": "qoder-cli", - "change": "updated", - "fields": ["docsUrl"] - }, - { - "category": "extensions", - "id": "gemini-code-assist", - "change": "updated", - "fields": ["communityUrls", "websiteUrl"] - }, - { - "category": "ides", - "id": "air", - "change": "updated", - "fields": ["docsUrl", "resourceUrls", "websiteUrl"] - }, - { - "category": "models", - "id": "gemini-3-1-pro-preview", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "models", - "id": "gemini-3-flash", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "models", - "id": "glm-4-6v", - "change": "updated", - "fields": ["websiteUrl"] - }, - { - "category": "models", - "id": "gpt-5-2", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "models", - "id": "gpt-5-6-luna", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "models", - "id": "gpt-5-6-sol", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "models", - "id": "gpt-5-6-terra", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "providers", - "id": "alibaba", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "providers", - "id": "anthropic", - "change": "updated", - "fields": ["applyKeyUrl", "sources"] - }, - { - "category": "providers", - "id": "google", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "providers", - "id": "meta", - "change": "updated", - "fields": ["applyKeyUrl", "docsUrl"] - }, - { - "category": "providers", - "id": "moonshot", - "change": "updated", - "fields": ["platformUrls"] - }, - { - "category": "providers", - "id": "openai", - "change": "updated", - "fields": ["sources"] - }, - { - "category": "vendors", - "id": "orionstar", - "change": "updated", - "fields": ["communityUrls"] - }, - { - "category": "vendors", - "id": "tabnine", - "change": "updated", - "fields": ["communityUrls"] - } - ] - }, - { - "id": "2026-07-21-manifest-update", - "date": "2026-07-21", - "summary": "183 manifest records changed", - "changes": [ - { - "category": "clis", - "id": "claude-code-cli", - "change": "updated", - "fields": ["relatedProducts", "familyId"] - }, - { - "category": "clis", - "id": "codex-cli", - "change": "updated", - "fields": ["relatedProducts", "familyId"] - }, - { - "category": "clis", - "id": "deepv-code", - "change": "updated", - "fields": [ - "githubUrl", - "resourceUrls", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "clis", - "id": "droid-cli", - "change": "updated", - "fields": ["relatedProducts", "familyId"] - }, - { - "category": "clis", - "id": "gitlab-duo-cli", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "clis", - "id": "grok-build", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "clis", - "id": "junie-cli", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "clis", - "id": "kimi-cli", - "change": "updated", - "fields": [ - "communityUrls", - "description", - "docsUrl", - "githubUrl", - "latestVersion", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "translations", - "websiteUrl", - "confidence", - "familyId", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "clis", - "id": "mistral-vibe-cli", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "clis", - "id": "omp", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "clis", - "id": "opencode", - "change": "updated", - "fields": [ - "communityUrls", - "githubUrl", - "relatedProducts", - "resourceUrls", - "vendor", - "familyId" - ] - }, - { - "category": "clis", - "id": "qoder-cli", - "change": "updated", - "fields": ["relatedProducts", "familyId"] - }, - { - "category": "clis", - "id": "qwen-code", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "clis", - "id": "rovo-dev-cli", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "desktops", - "id": "air", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "desktops", - "id": "claude-code-desktop", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "desktops", - "id": "codex-app", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "desktops", - "id": "factory-desktop", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "desktops", - "id": "minimax-code", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "desktops", - "id": "opencode-desktop", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "desktops", - "id": "qoder", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "desktops", - "id": "stagewise", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "desktops", - "id": "trae-work", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "desktops", - "id": "verdent-deck", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "desktops", - "id": "workbuddy", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "desktops", - "id": "zcode", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "extensions", - "id": "claude-code", - "change": "updated", - "fields": ["relatedProducts", "familyId"] - }, - { - "category": "extensions", - "id": "codex", - "change": "updated", - "fields": [ - "communityUrls", - "docsUrl", - "githubUrl", - "latestVersion", - "license", - "relatedProducts", - "resourceUrls", - "confidence", - "familyId", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "extensions", - "id": "droid", - "change": "updated", - "fields": ["relatedProducts", "familyId"] - }, - { - "category": "extensions", - "id": "jetbrains-junie", - "change": "updated", - "fields": ["relatedProducts", "familyId"] - }, - { - "category": "extensions", - "id": "kimi-code", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "supportedIdes", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "extensions", - "id": "mistral-vibe", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "supportedIdes", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "extensions", - "id": "opencode-extension", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "supportedIdes", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "extensions", - "id": "qoder", - "change": "updated", - "fields": ["relatedProducts", "familyId"] - }, - { - "category": "extensions", - "id": "rovo-dev", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "docsUrl", - "familyId", - "githubUrl", - "id", - "lastVerifiedAt", - "latestVersion", - "license", - "name", - "pricing", - "relatedProducts", - "resourceUrls", - "sources", - "supportedIdes", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "extensions", - "id": "verdent", - "change": "updated", - "fields": ["relatedProducts", "familyId"] - }, - { - "category": "ides", - "id": "air", - "change": "removed", - "fields": [ - "communityUrls", - "description", - "docsUrl", - "githubUrl", - "id", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "translations", - "vendor", - "verified", - "websiteUrl" - ] - }, - { - "category": "ides", - "id": "qoder", - "change": "removed", - "fields": [ - "communityUrls", - "description", - "docsUrl", - "githubUrl", - "id", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "translations", - "vendor", - "verified", - "websiteUrl" - ] - }, - { - "category": "ides", - "id": "trae", - "change": "updated", - "fields": [ - "latestVersion", - "name", - "pricing", - "relatedProducts", - "websiteUrl", - "confidence", - "familyId", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "ides", - "id": "verdent-deck", - "change": "removed", - "fields": [ - "communityUrls", - "description", - "docsUrl", - "githubUrl", - "id", - "latestVersion", - "license", - "name", - "platforms", - "pricing", - "relatedProducts", - "resourceUrls", - "translations", - "vendor", - "verified", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-fable-5", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "claude-haiku-3", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-haiku-3-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-haiku-4-5", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "claude-mythos-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-opus-3", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-opus-4", - "change": "updated", - "fields": [ - "lifecycle", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "claude-opus-4-1", - "change": "updated", - "fields": [ - "lifecycle", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "claude-opus-4-5", - "change": "updated", - "fields": [ - "lifecycle", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "claude-opus-4-6", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-opus-4-7", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-opus-4-8", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "claude-sonnet-3", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-sonnet-3-5-20240620", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-sonnet-3-5-20241022", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-sonnet-3-7", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-sonnet-4", - "change": "updated", - "fields": [ - "lifecycle", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "claude-sonnet-4-5", - "change": "updated", - "fields": [ - "lifecycle", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "claude-sonnet-4-6", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-sonnet-5", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "codestral-2405", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "codestral-2501", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "codestral-2508", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "composer", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "cursor-composer-2", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "cursor-composer-2-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "deepseek-3-2", - "change": "updated", - "fields": [ - "lifecycle", - "tokenPricing", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "deepseek-coder-v2-0724", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "deepseek-r1", - "change": "updated", - "fields": [ - "contextWindow", - "description", - "lifecycle", - "maxOutput", - "releaseDate", - "tokenPricing", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "deepseek-r1-0528", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "deepseek-v3", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "deepseek-v3-1", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "deepseek-v3-2-exp", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "deepseek-v3-terminus", - "change": "updated", - "fields": [ - "contextWindow", - "description", - "lifecycle", - "maxOutput", - "releaseDate", - "tokenPricing", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "deepseek-v4-flash", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "deepseek-v4-pro", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "devstral-2", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "devstral-medium-1-0", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "devstral-small-1-0", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "devstral-small-1-1", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "devstral-small-2", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-2-0-flash", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-2-0-flash-lite", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-2-5-flash", - "change": "updated", - "fields": [ - "knowledgeCutoff", - "releaseDate", - "size", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "gemini-2-5-flash-lite", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-2-5-pro", - "change": "updated", - "fields": [ - "knowledgeCutoff", - "releaseDate", - "size", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "gemini-3-1-flash-lite", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gemini-3-1-pro-preview", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gemini-3-5-flash", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gemini-3-flash", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gemini-3-pro", - "change": "updated", - "fields": [ - "lifecycle", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "glm-4-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "glm-4-6", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "glm-4-6v", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "glm-4-7", - "change": "updated", - "fields": [ - "description", - "docsUrl", - "knowledgeCutoff", - "lifecycle", - "tokenPricing", - "translations", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "glm-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "glm-5-1", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "glm-5-2", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-4-1", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gpt-4-1-mini", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-4-1-nano", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-4o", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gpt-4o-mini", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gpt-5-1", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gpt-5-1-codex", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gpt-5-1-codex-max", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-1-codex-mini", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-2", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gpt-5-2-codex", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-2-pro", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-3-codex", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-4", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-4-mini", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-4-nano", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-4-pro", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-5-pro", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-6-luna", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gpt-5-6-sol", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gpt-5-6-terra", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gpt-5-codex", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "gpt-5-mini", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-nano", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-pro", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "grok-4", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "grok-4-1-fast", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "grok-4-20", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "grok-4-3", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "grok-4-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "grok-4-fast", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "grok-build-0-1", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "grok-code-fast-1", - "change": "updated", - "fields": [ - "lifecycle", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "kat-coder-pro-v1", - "change": "updated", - "fields": ["benchmarks", "tokenPricing", "vendor"] - }, - { - "category": "models", - "id": "kimi-dev-72b", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "kimi-k2-0905", - "change": "updated", - "fields": [ - "lifecycle", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "kimi-k2-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "kimi-k2-6", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "kimi-k2-7-code", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "kimi-k2-instruct", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "kimi-k2-thinking", - "change": "updated", - "fields": [ - "lifecycle", - "tokenPricing", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "models", - "id": "kimi-k3", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "llama-4-maverick", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "llama-4-scout", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "minimax-m2", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "minimax-m2-1", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "minimax-m2-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "minimax-m2-7", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "minimax-m3", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "mistral-medium-3-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "mistral-small-4", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "muse-spark-1-1", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "o3", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "o3-mini", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "o4-mini", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-5-plus", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-6-plus", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-7-max", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-7-plus", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-coder-30b-a3b", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "qwen3-coder-480b-a35b", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "qwen3-coder-flash", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-coder-next", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "qwen3-coder-plus", - "change": "updated", - "fields": ["tokenPricing"] - }, - { - "category": "models", - "id": "qwen3-max-2026-01-23", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "providers", - "id": "kwaikatonai", - "change": "updated", - "fields": ["vendor"] - }, - { - "category": "vendors", - "id": "anomaly", - "change": "added", - "fields": [ - "aliases", - "communityUrls", - "confidence", - "description", - "id", - "lastVerifiedAt", - "name", - "sources", - "translations", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "atlassian", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "id", - "lastVerifiedAt", - "name", - "sources", - "translations", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "cline", - "change": "updated", - "fields": ["aliases"] - }, - { - "category": "vendors", - "id": "cline-bot", - "change": "removed", - "fields": [ - "communityUrls", - "description", - "id", - "name", - "translations", - "verified", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "continue", - "change": "updated", - "fields": ["aliases"] - }, - { - "category": "vendors", - "id": "continue-dev", - "change": "removed", - "fields": [ - "communityUrls", - "description", - "id", - "name", - "translations", - "verified", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "factory-ai", - "change": "updated", - "fields": ["aliases"] - }, - { - "category": "vendors", - "id": "gitlab", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "id", - "lastVerifiedAt", - "name", - "sources", - "translations", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "kwai", - "change": "removed", - "fields": [ - "communityUrls", - "description", - "id", - "name", - "translations", - "verified", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "kwaikat", - "change": "removed", - "fields": [ - "communityUrls", - "description", - "id", - "name", - "translations", - "verified", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "mistral-ai", - "change": "added", - "fields": [ - "aliases", - "communityUrls", - "confidence", - "description", - "id", - "lastVerifiedAt", - "name", - "sources", - "translations", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "moonshot", - "change": "updated", - "fields": ["name", "aliases"] - }, - { - "category": "vendors", - "id": "moonshot-ai", - "change": "removed", - "fields": [ - "communityUrls", - "description", - "id", - "name", - "translations", - "verified", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "oh-my-pi", - "change": "added", - "fields": [ - "aliases", - "communityUrls", - "confidence", - "description", - "id", - "lastVerifiedAt", - "name", - "sources", - "translations", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "stagewise", - "change": "added", - "fields": [ - "communityUrls", - "confidence", - "description", - "id", - "lastVerifiedAt", - "name", - "sources", - "translations", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "vendors", - "id": "streamlake", - "change": "updated", - "fields": ["aliases"] - }, - { - "category": "vendors", - "id": "z-ai", - "change": "updated", - "fields": ["aliases"] - } - ] - }, - { - "id": "2026-07-20-latest-models", - "date": "2026-07-20", - "summary": "Added current flagship model families from OpenAI, Anthropic, and Google", - "changes": [ - { - "category": "models", - "id": "claude-fable-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-opus-4-8", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "claude-sonnet-5", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-3-1-flash-lite", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-3-1-pro-preview", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gemini-3-5-flash", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-6-luna", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-6-sol", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - }, - { - "category": "models", - "id": "gpt-5-6-terra", - "change": "added", - "fields": [ - "benchmarks", - "capabilities", - "confidence", - "contextWindow", - "description", - "docsUrl", - "id", - "inputModalities", - "knowledgeCutoff", - "lastVerifiedAt", - "lifecycle", - "maxOutput", - "name", - "outputModalities", - "platformUrls", - "releaseDate", - "size", - "sources", - "tokenPricing", - "translations", - "vendor", - "verified", - "verifiedBy", - "websiteUrl" - ] - } - ] - }, - { - "id": "2026-07-19-data-integrity", - "date": "2026-07-19", - "summary": "Fixed product relationships and expanded official-source provenance for coding assistants", - "changes": [ - { - "category": "clis", - "id": "claude-code-cli", - "change": "updated", - "fields": [ - "docsUrl", - "latestVersion", - "resourceUrls", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "extensions", - "id": "claude-code", - "change": "updated", - "fields": [ - "docsUrl", - "latestVersion", - "resourceUrls", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "extensions", - "id": "droid", - "change": "updated", - "fields": ["relatedProducts"] - }, - { - "category": "extensions", - "id": "gemini-code-assist", - "change": "updated", - "fields": [ - "docsUrl", - "latestVersion", - "license", - "pricing", - "resourceUrls", - "supportedIdes", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "extensions", - "id": "qoder", - "change": "updated", - "fields": ["relatedProducts"] - }, - { - "category": "ides", - "id": "intellij-idea", - "change": "updated", - "fields": ["relatedProducts"] - }, - { - "category": "ides", - "id": "vscode", - "change": "updated", - "fields": ["relatedProducts"] - }, - { - "category": "ides", - "id": "zed", - "change": "updated", - "fields": ["relatedProducts"] - } - ] - }, - { - "id": "2026-07-18-project-review", - "date": "2026-07-18", - "summary": "Backfilled official-source provenance for priority providers and models", - "changes": [ - { - "category": "models", - "id": "claude-haiku-4-5", - "change": "updated", - "fields": ["docsUrl", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "models", - "id": "gemini-3-flash", - "change": "updated", - "fields": ["docsUrl", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "models", - "id": "gpt-5-2", - "change": "updated", - "fields": [ - "docsUrl", - "lifecycle", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "providers", - "id": "anthropic", - "change": "updated", - "fields": [ - "applyKeyUrl", - "docsUrl", - "verified", - "confidence", - "lastVerifiedAt", - "sources", - "verifiedBy" - ] - }, - { - "category": "providers", - "id": "google", - "change": "updated", - "fields": ["docsUrl", "verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - }, - { - "category": "providers", - "id": "openai", - "change": "updated", - "fields": ["docsUrl", "verified", "confidence", "lastVerifiedAt", "sources", "verifiedBy"] - } - ] - } - ] -} diff --git a/data/data-health.json b/data/data-health.json index 04df5675..534f249d 100644 --- a/data/data-health.json +++ b/data/data-health.json @@ -1,5 +1,5 @@ { - "asOf": "2026-07-28", + "asOf": "2026-07-29", "thresholds": { "models": 30, "providers": 30, diff --git a/data/model-intelligence-index.json b/data/model-intelligence-index.json deleted file mode 100644 index f74dd810..00000000 --- a/data/model-intelligence-index.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "./$schemas/model-intelligence-index.schema.json", - "hiddenVendorIds": ["mistral-ai"] -} diff --git a/data/model-price-intelligence-index.json b/data/model-price-intelligence-index.json index 0cbfff38..f1574da6 100644 --- a/data/model-price-intelligence-index.json +++ b/data/model-price-intelligence-index.json @@ -28,12 +28,7 @@ "labelAnchor": "start", "linearLabelDx": -16, "linearLabelDy": -46, - "linearLabelAnchor": "end", - "usdPriceOverride": { - "input": 0.14, - "output": 0.58, - "sourceUrl": "https://artificialanalysis.ai/models/hy3" - } + "linearLabelAnchor": "end" }, { "modelId": "minimax-m3", @@ -60,12 +55,7 @@ "labelAnchor": "start", "linearLabelDx": 18, "linearLabelDy": -22, - "linearLabelAnchor": "start", - "usdPriceOverride": { - "input": 0.4, - "output": 1.6, - "sourceUrl": "https://artificialanalysis.ai/models/qwen3-7-plus" - } + "linearLabelAnchor": "start" }, { "modelId": "glm-5-2", @@ -113,12 +103,7 @@ "modelId": "qwen3-7-max", "labelDx": -10, "labelDy": 24, - "labelAnchor": "end", - "usdPriceOverride": { - "input": 2.5, - "output": 7.5, - "sourceUrl": "https://artificialanalysis.ai/models/qwen3-7-max" - } + "labelAnchor": "end" }, { "modelId": "gemini-3-1-pro-preview", @@ -144,6 +129,15 @@ "labelDy": 34, "labelAnchor": "end" }, + { + "modelId": "claude-fable-5", + "labelDx": 12, + "labelDy": -14, + "labelAnchor": "start", + "linearLabelDx": -10, + "linearLabelDy": -14, + "linearLabelAnchor": "end" + }, { "modelId": "gpt-5-6-sol", "labelDx": 8, diff --git a/docs/DATA-HEALTH.md b/docs/DATA-HEALTH.md index 9c82ec80..243cf0c4 100644 --- a/docs/DATA-HEALTH.md +++ b/docs/DATA-HEALTH.md @@ -1,6 +1,6 @@ # Data Health Report -Snapshot date: 2026-07-28. Regenerate with `npm run data-health:report`. +Snapshot date: 2026-07-29. Regenerate with `npm run data-health:report`. ## Scorecard diff --git a/docs/PROJECT-REVIEW-2026-07-18.md b/docs/PROJECT-REVIEW-2026-07-18.md index ce81809e..5ac78abd 100644 --- a/docs/PROJECT-REVIEW-2026-07-18.md +++ b/docs/PROJECT-REVIEW-2026-07-18.md @@ -74,7 +74,6 @@ Baseline captured on 2026-07-18: integrity, translation placeholders, and missing pricing/benchmark values. - [x] Add freshness policies (for example 30/60/90-day review thresholds by field/category). - [ ] Automate change discovery from official sources, but keep human review before merge. -- [x] Populate a real changelog from manifest diffs instead of keeping an empty static file. ## P1 — Product Experience @@ -173,8 +172,6 @@ evidence; completed items are reflected in the checklists and implementation log canonical pair URLs, and the comparison selector; adding a third model replaces the oldest pick. - Added Playwright browser smoke coverage for search-to-detail navigation, locale-preserving route switches, and persistent model comparison selections, and made it a required CI job. -- Replaced the empty changelog placeholder with a deterministic manifest-diff record and added a CI - guard requiring future manifest changes to be represented in `data/changelogs.json`. - Fixed the search result category badge to use the shared translated category names after browser testing exposed a missing runtime message lookup. - Upgraded Next.js, OpenNext Cloudflare, next-intl, React, Vitest, Wrangler, and AJV to compatible diff --git a/manifests/$schemas/model.schema.json b/manifests/$schemas/model.schema.json index bd24099b..a79666a6 100644 --- a/manifests/$schemas/model.schema.json +++ b/manifests/$schemas/model.schema.json @@ -27,6 +27,10 @@ "tokenPricing": { "$ref": "#/$defs/tokenPricing" }, + "referenceTokenPricing": { + "$ref": "#/$defs/referenceTokenPricing", + "description": "Optional externally tracked token pricing used when the first-party offer is unavailable or not directly comparable. This must not replace tokenPricing." + }, "releaseDate": { "type": ["string", "null"], "format": "date", @@ -115,6 +119,15 @@ ], "additionalProperties": false }, + "benchmarkTracking": { + "type": "array", + "description": "Exact upstream leaderboard entries used to refresh benchmark fields without fuzzy model-name matching", + "items": { + "$ref": "#/$defs/benchmarkTracking" + }, + "minItems": 1, + "uniqueItems": true + }, "platformUrls": { "$ref": "./ref/platform-urls.schema.json", "description": "URLs to various third-party platform pages for this model" @@ -137,6 +150,30 @@ } ], "$defs": { + "benchmarkTracking": { + "type": "object", + "properties": { + "provider": { + "const": "swe-bench" + }, + "benchmark": { + "const": "sweBench" + }, + "leaderboard": { + "const": "Verified" + }, + "resultId": { + "type": "string", + "minLength": 1 + }, + "modelLabel": { + "type": "string", + "minLength": 1 + } + }, + "required": ["provider", "benchmark", "leaderboard", "resultId", "modelLabel"], + "additionalProperties": false + }, "tokenPricing": { "description": "First-party, pay-as-you-go standard API token pricing. Rates use the offer's native currency per million tokens.", "oneOf": [ @@ -320,6 +357,46 @@ }, "required": ["input", "output", "cacheRead", "cacheWrite"], "additionalProperties": false + }, + "referenceTokenPricing": { + "type": "object", + "properties": { + "currency": { + "type": "string", + "pattern": "^[A-Z]{3}$", + "description": "ISO 4217 currency code" + }, + "basis": { + "type": "string", + "enum": ["first-party-api", "provider-median"], + "description": "Whether the tracked price represents the model vendor's API or a median across third-party API providers" + }, + "rates": { + "$ref": "#/$defs/tokenPricingRates" + }, + "source": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "url": { + "type": "string", + "format": "uri", + "pattern": "^https://" + }, + "observedAt": { + "type": "string", + "format": "date" + } + }, + "required": ["name", "url", "observedAt"], + "additionalProperties": false + } + }, + "required": ["currency", "basis", "rates", "source"], + "additionalProperties": false } } } diff --git a/manifests/$schemas/ref/entity.schema.json b/manifests/$schemas/ref/entity.schema.json index 627e8771..e1b2adad 100644 --- a/manifests/$schemas/ref/entity.schema.json +++ b/manifests/$schemas/ref/entity.schema.json @@ -84,10 +84,32 @@ }, "minItems": 1, "uniqueItems": true + }, + "changeTracking": { + "$ref": "#/$defs/sourceChangeTracking", + "description": "Optional content fingerprint used to detect upstream source changes without automatically accepting field-value changes" } }, "required": ["url"], "additionalProperties": false + }, + "sourceChangeTracking": { + "type": "object", + "properties": { + "method": { + "const": "normalized-content-sha256" + }, + "digest": { + "type": ["string", "null"], + "pattern": "^sha256:[a-f0-9]{64}$" + }, + "observedAt": { + "type": ["string", "null"], + "format": "date" + } + }, + "required": ["method", "digest", "observedAt"], + "additionalProperties": false } } } diff --git a/manifests/$schemas/ref/product.schema.json b/manifests/$schemas/ref/product.schema.json index 3c2d9e8a..8579501c 100644 --- a/manifests/$schemas/ref/product.schema.json +++ b/manifests/$schemas/ref/product.schema.json @@ -19,6 +19,10 @@ "type": "string", "description": "The latest stable version number (typically found on download page or changelog page)" }, + "releaseTracking": { + "$ref": "#/$defs/releaseTracking", + "description": "Optional declarative source used to refresh latestVersion without embedding product data in synchronization code" + }, "githubUrl": { "type": ["string", "null"], "format": "uri", @@ -62,6 +66,70 @@ } ], "$defs": { + "releaseTracking": { + "oneOf": [ + { + "type": "object", + "properties": { + "provider": { + "const": "npm" + }, + "identifier": { + "type": "string", + "minLength": 1 + }, + "channel": { + "type": "string", + "pattern": "^[a-z][a-z0-9._-]*$" + } + }, + "required": ["provider", "identifier"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "enum": ["homebrew-formula", "homebrew-cask", "crates-io", "pypi"] + }, + "identifier": { + "type": "string", + "pattern": "^[a-z0-9][a-z0-9+._@-]*$" + } + }, + "required": ["provider", "identifier"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "const": "vscode-marketplace" + }, + "identifier": { + "type": "string", + "pattern": "^[a-zA-Z0-9][a-zA-Z0-9_-]*\\.[a-zA-Z0-9][a-zA-Z0-9._-]*$" + } + }, + "required": ["provider", "identifier"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "const": "github-release" + }, + "identifier": { + "type": "string", + "pattern": "^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$" + } + }, + "required": ["provider", "identifier"], + "additionalProperties": false + } + ] + }, "relatedProducts": { "type": "array", "description": "Related products (IDEs, CLIs, extensions, or desktop apps)", diff --git a/manifests/clis/claude-code-cli.json b/manifests/clis/claude-code-cli.json index 27f8825d..0eb90cb7 100644 --- a/manifests/clis/claude-code-cli.json +++ b/manifests/clis/claude-code-cli.json @@ -108,7 +108,11 @@ "websiteUrl": "https://code.claude.com", "docsUrl": "https://code.claude.com/docs", "vendor": "Anthropic", - "latestVersion": "2.1.215", + "latestVersion": "2.1.220", + "releaseTracking": { + "provider": "npm", + "identifier": "@anthropic-ai/claude-code" + }, "githubUrl": "https://github.com/anthropics/claude-code", "license": "Proprietary", "pricing": [ diff --git a/manifests/clis/cline-cli.json b/manifests/clis/cline-cli.json index cfaa2989..cf4954b5 100644 --- a/manifests/clis/cline-cli.json +++ b/manifests/clis/cline-cli.json @@ -42,7 +42,11 @@ "websiteUrl": "https://cline.bot/cline-cli", "docsUrl": "https://cline.bot/docs", "vendor": "Cline Bot", - "latestVersion": "Preview", + "latestVersion": "3.0.46", + "releaseTracking": { + "provider": "npm", + "identifier": "cline" + }, "githubUrl": null, "license": "Proprietary", "pricing": [ diff --git a/manifests/clis/codebuddy-cli.json b/manifests/clis/codebuddy-cli.json index 9cdb4322..9634581c 100644 --- a/manifests/clis/codebuddy-cli.json +++ b/manifests/clis/codebuddy-cli.json @@ -42,7 +42,11 @@ "websiteUrl": "https://www.codebuddy.ai/cli", "docsUrl": "https://www.codebuddy.ai/docs/cli", "vendor": "Tencent", - "latestVersion": "Latest", + "latestVersion": "1.0.0", + "releaseTracking": { + "provider": "npm", + "identifier": "codebuddy-cli" + }, "githubUrl": null, "license": "Proprietary", "pricing": [ diff --git a/manifests/clis/codex-cli.json b/manifests/clis/codex-cli.json index 1afbd7c6..921d4329 100644 --- a/manifests/clis/codex-cli.json +++ b/manifests/clis/codex-cli.json @@ -43,7 +43,11 @@ "websiteUrl": "https://openai.com/codex", "docsUrl": "https://developers.openai.com/codex/cli", "vendor": "OpenAI", - "latestVersion": "0.44.0", + "latestVersion": "0.145.0", + "releaseTracking": { + "provider": "npm", + "identifier": "@openai/codex" + }, "githubUrl": "https://github.com/openai/codex", "license": "Apache-2.0", "pricing": [ diff --git a/manifests/clis/cursor-cli.json b/manifests/clis/cursor-cli.json index 8488197d..0ac25135 100644 --- a/manifests/clis/cursor-cli.json +++ b/manifests/clis/cursor-cli.json @@ -42,7 +42,11 @@ "websiteUrl": "https://cursor.com/cli", "docsUrl": "https://cursor.com/docs/cli/overview", "vendor": "Anysphere", - "latestVersion": "2025.11.25-e276529", + "latestVersion": "2026.07.23-e383d2b", + "releaseTracking": { + "provider": "homebrew-cask", + "identifier": "cursor-cli" + }, "githubUrl": "https://github.com/cursor/cursor", "license": "Proprietary", "pricing": [ diff --git a/manifests/clis/gemini-cli.json b/manifests/clis/gemini-cli.json index 573c4743..b568c374 100644 --- a/manifests/clis/gemini-cli.json +++ b/manifests/clis/gemini-cli.json @@ -73,7 +73,11 @@ "websiteUrl": "https://geminicli.com", "docsUrl": "https://geminicli.com/docs", "vendor": "Google", - "latestVersion": "0.50.0", + "latestVersion": "0.52.0", + "releaseTracking": { + "provider": "npm", + "identifier": "@google/gemini-cli" + }, "githubUrl": "https://github.com/google-gemini/gemini-cli", "license": "Apache-2.0", "pricing": [ diff --git a/manifests/clis/github-copilot-cli.json b/manifests/clis/github-copilot-cli.json index 9a3686fb..73be6122 100644 --- a/manifests/clis/github-copilot-cli.json +++ b/manifests/clis/github-copilot-cli.json @@ -42,7 +42,11 @@ "websiteUrl": "https://github.com/features/copilot/cli", "docsUrl": "https://docs.github.com/en/copilot/concepts/agents/about-copilot-cli", "vendor": "GitHub", - "latestVersion": "0.0.365", + "latestVersion": "1.0.75", + "releaseTracking": { + "provider": "npm", + "identifier": "@github/copilot" + }, "githubUrl": "https://github.com/github/copilot-cli", "license": "Proprietary", "pricing": [ diff --git a/manifests/clis/kilo-code-cli.json b/manifests/clis/kilo-code-cli.json index bb4312fa..9b08071d 100644 --- a/manifests/clis/kilo-code-cli.json +++ b/manifests/clis/kilo-code-cli.json @@ -43,6 +43,10 @@ "docsUrl": "https://kilo.ai/docs/code-with-ai/platforms/cli", "vendor": "Kilo", "latestVersion": "7.4.16", + "releaseTracking": { + "provider": "npm", + "identifier": "@kilocode/cli" + }, "githubUrl": "https://github.com/Kilo-Org/kilocode", "license": "Apache-2.0", "familyId": "kilo-code", diff --git a/manifests/clis/kode.json b/manifests/clis/kode.json index 32fe86fd..53e8c6d6 100644 --- a/manifests/clis/kode.json +++ b/manifests/clis/kode.json @@ -42,7 +42,11 @@ "websiteUrl": "https://github.com/shareAI-lab/Kode", "docsUrl": "https://github.com/shareAI-lab/Kode/blob/main/README.md", "vendor": "shareAI Lab", - "latestVersion": "1.2.0", + "latestVersion": "2.2.1", + "releaseTracking": { + "provider": "npm", + "identifier": "@shareai-lab/kode" + }, "githubUrl": "https://github.com/shareAI-lab/Kode-cli", "license": "Apache-2.0", "pricing": [ diff --git a/manifests/clis/mistral-vibe-cli.json b/manifests/clis/mistral-vibe-cli.json index 4a9492c4..32c1ac44 100644 --- a/manifests/clis/mistral-vibe-cli.json +++ b/manifests/clis/mistral-vibe-cli.json @@ -56,7 +56,11 @@ "websiteUrl": "https://mistral.ai/products/vibe", "docsUrl": "https://docs.mistral.ai/vibe/code/overview", "vendor": "Mistral AI", - "latestVersion": "Latest", + "latestVersion": "2.23.0", + "releaseTracking": { + "provider": "pypi", + "identifier": "mistral-vibe" + }, "githubUrl": null, "license": "Proprietary", "pricing": [ diff --git a/manifests/clis/neovate-code.json b/manifests/clis/neovate-code.json index bcb3a05f..8ab03fc7 100644 --- a/manifests/clis/neovate-code.json +++ b/manifests/clis/neovate-code.json @@ -42,7 +42,11 @@ "websiteUrl": "https://neovateai.dev", "docsUrl": "https://neovateai.dev/en/docs/overview", "vendor": "Ant Group", - "latestVersion": "0.12.7", + "latestVersion": "0.28.5", + "releaseTracking": { + "provider": "npm", + "identifier": "@neovate/code" + }, "githubUrl": "https://github.com/neovateai/neovate-code", "license": "MIT", "pricing": [ diff --git a/manifests/clis/opencode.json b/manifests/clis/opencode.json index 2b1300b5..855b39ad 100644 --- a/manifests/clis/opencode.json +++ b/manifests/clis/opencode.json @@ -43,7 +43,11 @@ "websiteUrl": "https://opencode.ai", "docsUrl": "https://opencode.ai", "vendor": "Anomaly", - "latestVersion": "0.15.16", + "latestVersion": "1.18.8", + "releaseTracking": { + "provider": "npm", + "identifier": "opencode-ai" + }, "githubUrl": "https://github.com/anomalyco/opencode", "license": "MIT", "pricing": [ diff --git a/manifests/clis/qoder-cli.json b/manifests/clis/qoder-cli.json index 3b939355..92e06572 100644 --- a/manifests/clis/qoder-cli.json +++ b/manifests/clis/qoder-cli.json @@ -43,7 +43,11 @@ "websiteUrl": "https://qoder.com/cli", "docsUrl": "https://docs.qoder.com/en/cli/quick-start", "vendor": "Alibaba", - "latestVersion": "Latest", + "latestVersion": "1.1.7", + "releaseTracking": { + "provider": "npm", + "identifier": "@qoder-ai/qodercli" + }, "githubUrl": null, "license": "Proprietary", "pricing": [ diff --git a/manifests/clis/qwen-code.json b/manifests/clis/qwen-code.json index 5f3eb410..c61ad4e4 100644 --- a/manifests/clis/qwen-code.json +++ b/manifests/clis/qwen-code.json @@ -56,7 +56,11 @@ "websiteUrl": "https://qwenlm.github.io/qwen-code-docs", "docsUrl": "https://qwenlm.github.io/qwen-code-docs", "vendor": "Alibaba", - "latestVersion": "0.18.0", + "latestVersion": "0.21.0", + "releaseTracking": { + "provider": "npm", + "identifier": "@qwen-code/qwen-code" + }, "githubUrl": "https://github.com/QwenLM/qwen-code", "license": "Apache-2.0", "pricing": [ diff --git a/manifests/desktops/opencode-desktop.json b/manifests/desktops/opencode-desktop.json index d8d8e028..c91fd8cc 100644 --- a/manifests/desktops/opencode-desktop.json +++ b/manifests/desktops/opencode-desktop.json @@ -56,7 +56,11 @@ "websiteUrl": "https://opencode.ai/download", "docsUrl": "https://opencode.ai/docs", "vendor": "Anomaly", - "latestVersion": "Latest", + "latestVersion": "1.18.8", + "releaseTracking": { + "provider": "homebrew-cask", + "identifier": "opencode-desktop" + }, "githubUrl": "https://github.com/anomalyco/opencode", "license": "MIT", "pricing": [ diff --git a/manifests/extensions/claude-code.json b/manifests/extensions/claude-code.json index bac53aa6..084d220f 100644 --- a/manifests/extensions/claude-code.json +++ b/manifests/extensions/claude-code.json @@ -103,7 +103,11 @@ "websiteUrl": "https://code.claude.com", "docsUrl": "https://code.claude.com/docs/en/ide-integrations", "vendor": "Anthropic", - "latestVersion": "Latest", + "latestVersion": "2.1.220", + "releaseTracking": { + "provider": "vscode-marketplace", + "identifier": "anthropic.claude-code" + }, "githubUrl": "https://github.com/anthropics/claude-code", "license": "Proprietary", "pricing": [ diff --git a/manifests/extensions/codex.json b/manifests/extensions/codex.json index 201534a6..f1bc8192 100644 --- a/manifests/extensions/codex.json +++ b/manifests/extensions/codex.json @@ -63,7 +63,11 @@ "websiteUrl": "https://openai.com/codex", "docsUrl": "https://developers.openai.com/codex/ide", "vendor": "OpenAI", - "latestVersion": "Latest", + "latestVersion": "26.5721.30844", + "releaseTracking": { + "provider": "vscode-marketplace", + "identifier": "openai.chatgpt" + }, "githubUrl": null, "license": "Proprietary", "pricing": [ diff --git a/manifests/extensions/droid.json b/manifests/extensions/droid.json index 2594f654..36890ad4 100644 --- a/manifests/extensions/droid.json +++ b/manifests/extensions/droid.json @@ -43,7 +43,11 @@ "websiteUrl": "https://factory.ai", "docsUrl": "https://docs.factory.ai", "vendor": "Factory.ai", - "latestVersion": "Latest", + "latestVersion": "0.2.3", + "releaseTracking": { + "provider": "vscode-marketplace", + "identifier": "Factory.factory-vscode-extension" + }, "githubUrl": null, "license": "Proprietary", "pricing": [ diff --git a/manifests/extensions/kimi-code.json b/manifests/extensions/kimi-code.json index b656add8..dc254f43 100644 --- a/manifests/extensions/kimi-code.json +++ b/manifests/extensions/kimi-code.json @@ -56,7 +56,11 @@ "websiteUrl": "https://www.kimi.com/code", "docsUrl": "https://www.kimi.com/code/docs/en", "vendor": "Moonshot AI", - "latestVersion": "Latest", + "latestVersion": "0.6.4", + "releaseTracking": { + "provider": "vscode-marketplace", + "identifier": "moonshot-ai.kimi-code" + }, "githubUrl": "https://github.com/MoonshotAI/kimi-code", "license": "Apache-2.0", "pricing": [ diff --git a/manifests/extensions/mistral-vibe.json b/manifests/extensions/mistral-vibe.json index 94a6555d..23f8ad8d 100644 --- a/manifests/extensions/mistral-vibe.json +++ b/manifests/extensions/mistral-vibe.json @@ -56,7 +56,11 @@ "websiteUrl": "https://mistral.ai/products/vibe", "docsUrl": "https://docs.mistral.ai/vibe/code/overview", "vendor": "Mistral AI", - "latestVersion": "Latest", + "latestVersion": "1.14.4", + "releaseTracking": { + "provider": "vscode-marketplace", + "identifier": "mistralai.mistral-vibe-code" + }, "githubUrl": null, "license": "Proprietary", "pricing": [ diff --git a/manifests/extensions/opencode-extension.json b/manifests/extensions/opencode-extension.json index eb0d6153..47ca4117 100644 --- a/manifests/extensions/opencode-extension.json +++ b/manifests/extensions/opencode-extension.json @@ -56,7 +56,11 @@ "websiteUrl": "https://opencode.ai/download", "docsUrl": "https://opencode.ai/docs/ide", "vendor": "Anomaly", - "latestVersion": "Latest", + "latestVersion": "0.0.13", + "releaseTracking": { + "provider": "vscode-marketplace", + "identifier": "sst-dev.opencode" + }, "githubUrl": "https://github.com/anomalyco/opencode", "license": "MIT", "pricing": [ diff --git a/manifests/extensions/rovo-dev.json b/manifests/extensions/rovo-dev.json index 1d1df147..bb4369f8 100644 --- a/manifests/extensions/rovo-dev.json +++ b/manifests/extensions/rovo-dev.json @@ -60,7 +60,11 @@ "websiteUrl": "https://marketplace.visualstudio.com/items?itemName=Atlassian.atlascode", "docsUrl": "https://support.atlassian.com/rovo/docs/work-with-rovo-dev-agents/", "vendor": "Atlassian", - "latestVersion": "Latest", + "latestVersion": "4.1.191", + "releaseTracking": { + "provider": "vscode-marketplace", + "identifier": "Atlassian.atlascode" + }, "githubUrl": null, "license": "Proprietary", "pricing": [ diff --git a/manifests/models/claude-haiku-4-5.json b/manifests/models/claude-haiku-4-5.json index 36a912c2..4b160ab4 100644 --- a/manifests/models/claude-haiku-4-5.json +++ b/manifests/models/claude-haiku-4-5.json @@ -57,7 +57,12 @@ { "url": "https://platform.claude.com/docs/en/about-claude/pricing", "title": "Claude API pricing", - "fields": ["tokenPricing"] + "fields": ["tokenPricing"], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:2ff7f541d89a824c7125b0cfab826e4b839e85f2ded2613c746415903266274b", + "observedAt": "2026-07-28" + } }, { "url": "https://www.anthropic.com/news/claude-haiku-4-5", diff --git a/manifests/models/claude-opus-4.json b/manifests/models/claude-opus-4.json index 3aa15822..8cf0c338 100644 --- a/manifests/models/claude-opus-4.json +++ b/manifests/models/claude-opus-4.json @@ -43,7 +43,12 @@ { "url": "https://platform.claude.com/docs/en/about-claude/model-deprecations", "title": "Anthropic model deprecations", - "fields": ["lifecycle"] + "fields": ["lifecycle"], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:af2e27075e6c7826cf4d7ef23f722bcbf0406d5bc0adaa0facf07e3b92b9c0b0", + "observedAt": "2026-07-28" + } } ], "lastVerifiedAt": "2026-07-21", @@ -95,6 +100,15 @@ "sciCode": 1.5, "liveCodeBench": 46.9 }, + "benchmarkTracking": [ + { + "provider": "swe-bench", + "benchmark": "sweBench", + "leaderboard": "Verified", + "resultId": "20250802_mini-v1.0.0_claude-4-opus-20250514", + "modelLabel": "mini-SWE-agent + Claude 4 Opus (20250514)" + } + ], "platformUrls": { "huggingface": null, "artificialAnalysis": "https://artificialanalysis.ai/models/claude-4-opus", diff --git a/manifests/models/claude-sonnet-4-5.json b/manifests/models/claude-sonnet-4-5.json index 2d665cbd..f827a761 100644 --- a/manifests/models/claude-sonnet-4-5.json +++ b/manifests/models/claude-sonnet-4-5.json @@ -95,6 +95,15 @@ "sciCode": null, "liveCodeBench": 46.9 }, + "benchmarkTracking": [ + { + "provider": "swe-bench", + "benchmark": "sweBench", + "leaderboard": "Verified", + "resultId": "20250929_mini-v1.13.3_sonnet-4-5-20250929", + "modelLabel": "mini-SWE-agent + Claude 4.5 Sonnet (20250929)" + } + ], "platformUrls": { "huggingface": null, "artificialAnalysis": "https://artificialanalysis.ai/models/claude-4-5-sonnet", diff --git a/manifests/models/claude-sonnet-4.json b/manifests/models/claude-sonnet-4.json index 05dcfb46..55198c4e 100644 --- a/manifests/models/claude-sonnet-4.json +++ b/manifests/models/claude-sonnet-4.json @@ -95,6 +95,15 @@ "sciCode": null, "liveCodeBench": 55.9 }, + "benchmarkTracking": [ + { + "provider": "swe-bench", + "benchmark": "sweBench", + "leaderboard": "Verified", + "resultId": "20250726_mini-v1.0.0_claude-sonnet-4-20250514", + "modelLabel": "mini-SWE-agent + Claude 4 Sonnet (20250514)" + } + ], "platformUrls": { "huggingface": null, "artificialAnalysis": "https://artificialanalysis.ai/models/claude-4-sonnet", diff --git a/manifests/models/deepseek-3-2.json b/manifests/models/deepseek-3-2.json index 83cb2ffd..8723a164 100644 --- a/manifests/models/deepseek-3-2.json +++ b/manifests/models/deepseek-3-2.json @@ -60,7 +60,12 @@ { "url": "https://api-docs.deepseek.com/quick_start/pricing", "title": "DeepSeek API pricing", - "fields": ["tokenPricing"] + "fields": ["tokenPricing"], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:d1c1fc8b58ad75475827f978beac79318391da95b942891f47a8aafe811712ba", + "observedAt": "2026-07-28" + } } ], "lastVerifiedAt": "2026-07-21", diff --git a/manifests/models/gemini-2-5-flash.json b/manifests/models/gemini-2-5-flash.json index 7758bc92..33ce1fbf 100644 --- a/manifests/models/gemini-2-5-flash.json +++ b/manifests/models/gemini-2-5-flash.json @@ -111,6 +111,15 @@ "sciCode": null, "liveCodeBench": 60.6 }, + "benchmarkTracking": [ + { + "provider": "swe-bench", + "benchmark": "sweBench", + "leaderboard": "Verified", + "resultId": "20250726_mini-v1.0.0_gemini-2.5-flash", + "modelLabel": "mini-SWE-agent + Gemini 2.5 Flash (2025-04-17)" + } + ], "platformUrls": { "huggingface": null, "artificialAnalysis": "https://artificialanalysis.ai/models/gemini-2-5-flash", diff --git a/manifests/models/gemini-2-5-pro.json b/manifests/models/gemini-2-5-pro.json index 2d1e3b84..486fdd98 100644 --- a/manifests/models/gemini-2-5-pro.json +++ b/manifests/models/gemini-2-5-pro.json @@ -111,6 +111,15 @@ "sciCode": 1.5, "liveCodeBench": 71.8 }, + "benchmarkTracking": [ + { + "provider": "swe-bench", + "benchmark": "sweBench", + "leaderboard": "Verified", + "resultId": "20250726_mini-v1.0.0_gemini-2.5-pro", + "modelLabel": "mini-SWE-agent + Gemini 2.5 Pro (2025-05-06)" + } + ], "platformUrls": { "huggingface": null, "artificialAnalysis": "https://artificialanalysis.ai/models/gemini-2-5-pro", diff --git a/manifests/models/gemini-3-5-flash.json b/manifests/models/gemini-3-5-flash.json index 10d8dad5..9ad61384 100644 --- a/manifests/models/gemini-3-5-flash.json +++ b/manifests/models/gemini-3-5-flash.json @@ -56,12 +56,22 @@ { "url": "https://ai.google.dev/gemini-api/docs/pricing", "title": "Gemini Developer API pricing", - "fields": ["tokenPricing"] + "fields": ["tokenPricing"], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:aab4d993819344eb390d8e59a37ab5d9712daca3ed395b4271bbebb586bb0c50", + "observedAt": "2026-07-28" + } }, { "url": "https://ai.google.dev/gemini-api/docs/changelog", "title": "Gemini API release notes", - "fields": ["name", "description", "releaseDate", "lifecycle"] + "fields": ["name", "description", "releaseDate", "lifecycle"], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:d903a1d48cc08625d5514f5f0d800daed7c207f46cfa33dcef4dcbb98ab16065", + "observedAt": "2026-07-28" + } } ], "lastVerifiedAt": "2026-07-22", diff --git a/manifests/models/glm-4-6.json b/manifests/models/glm-4-6.json index 9cc531e0..fe6461d5 100644 --- a/manifests/models/glm-4-6.json +++ b/manifests/models/glm-4-6.json @@ -85,6 +85,15 @@ "sciCode": null, "liveCodeBench": null }, + "benchmarkTracking": [ + { + "provider": "swe-bench", + "benchmark": "sweBench", + "leaderboard": "Verified", + "resultId": "20251201_mini-v1.17.1_glm-4.6", + "modelLabel": "mini-SWE-agent + GLM-4.6 (T=1)" + } + ], "platformUrls": { "huggingface": "https://huggingface.co/zai-org/GLM-4.6", "artificialAnalysis": "https://artificialanalysis.ai/models/glm-4-6", diff --git a/manifests/models/glm-5-2.json b/manifests/models/glm-5-2.json index ddc50861..86341d6f 100644 --- a/manifests/models/glm-5-2.json +++ b/manifests/models/glm-5-2.json @@ -57,12 +57,22 @@ { "url": "https://docs.z.ai/release-notes/new-released", "title": "Z.ai model release notes", - "fields": ["releaseDate", "lifecycle"] + "fields": ["releaseDate", "lifecycle"], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:5b5ab3620167e1331f3de0aeeefe0cb5df12d59e706e0228bac5dcab6248a6fe", + "observedAt": "2026-07-28" + } }, { "url": "https://docs.z.ai/guides/overview/pricing", "title": "Z.ai API pricing", - "fields": ["tokenPricing"] + "fields": ["tokenPricing"], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:3f331fe3d6f5ed696378e4c29c6ce553f463417299d5aa2d222ad8b48fe3ec7a", + "observedAt": "2026-07-28" + } }, { "url": "https://huggingface.co/zai-org/GLM-5.2", diff --git a/manifests/models/gpt-4-1.json b/manifests/models/gpt-4-1.json index 6598e070..703f6606 100644 --- a/manifests/models/gpt-4-1.json +++ b/manifests/models/gpt-4-1.json @@ -85,6 +85,15 @@ "sciCode": null, "liveCodeBench": null }, + "benchmarkTracking": [ + { + "provider": "swe-bench", + "benchmark": "sweBench", + "leaderboard": "Verified", + "resultId": "20250726_mini-v1.0.0_gpt-4.1-2025-04-14", + "modelLabel": "mini-SWE-agent + GPT-4.1 (2025-04-14)" + } + ], "platformUrls": { "huggingface": null, "artificialAnalysis": "https://artificialanalysis.ai/models/gpt-4-1", diff --git a/manifests/models/gpt-4o.json b/manifests/models/gpt-4o.json index c6f55a61..0c3f58f3 100644 --- a/manifests/models/gpt-4o.json +++ b/manifests/models/gpt-4o.json @@ -85,6 +85,15 @@ "sciCode": 1.5, "liveCodeBench": 29.5 }, + "benchmarkTracking": [ + { + "provider": "swe-bench", + "benchmark": "sweBench", + "leaderboard": "Verified", + "resultId": "20250720_mini-v0.0.0-gpt-4o-2024-11-20", + "modelLabel": "mini-SWE-agent + GPT-4o (2024-11-20)" + } + ], "platformUrls": { "huggingface": null, "artificialAnalysis": "https://artificialanalysis.ai/models/gpt-4o", diff --git a/manifests/models/gpt-5-1.json b/manifests/models/gpt-5-1.json index da92f19a..362baffa 100644 --- a/manifests/models/gpt-5-1.json +++ b/manifests/models/gpt-5-1.json @@ -85,6 +85,15 @@ "sciCode": null, "liveCodeBench": null }, + "benchmarkTracking": [ + { + "provider": "swe-bench", + "benchmark": "sweBench", + "leaderboard": "Verified", + "resultId": "20251120_mini-v1.15.0_gpt-5.1-2025-11-13", + "modelLabel": "mini-SWE-agent + GPT-5.1 (2025-11-13) (medium reasoning)" + } + ], "platformUrls": { "huggingface": null, "artificialAnalysis": "https://artificialanalysis.ai/models/gpt-5-1", diff --git a/manifests/models/gpt-5-6-sol.json b/manifests/models/gpt-5-6-sol.json index 6fdb183e..fe7fd379 100644 --- a/manifests/models/gpt-5-6-sol.json +++ b/manifests/models/gpt-5-6-sol.json @@ -52,7 +52,12 @@ "inputModalities", "outputModalities", "capabilities" - ] + ], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:a8689d63a32710a7b7c1ecb3b7898d57820ce6de6a68f5bec671e606685af349", + "observedAt": "2026-07-28" + } }, { "url": "https://openai.com/index/gpt-5-6", diff --git a/manifests/models/gpt-5.json b/manifests/models/gpt-5.json index daa47e20..b33b2732 100644 --- a/manifests/models/gpt-5.json +++ b/manifests/models/gpt-5.json @@ -85,6 +85,15 @@ "sciCode": 1.5, "liveCodeBench": 28.7 }, + "benchmarkTracking": [ + { + "provider": "swe-bench", + "benchmark": "sweBench", + "leaderboard": "Verified", + "resultId": "20250807_openhands_gpt5", + "modelLabel": "OpenHands + GPT-5" + } + ], "platformUrls": { "huggingface": null, "artificialAnalysis": "https://artificialanalysis.ai/models/gpt-5", diff --git a/manifests/models/grok-4-20.json b/manifests/models/grok-4-20.json index 83051760..4d5a054a 100644 --- a/manifests/models/grok-4-20.json +++ b/manifests/models/grok-4-20.json @@ -57,7 +57,12 @@ "inputModalities", "outputModalities", "capabilities" - ] + ], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:ce3ca747e8bec4e13b038be6f1c3ccfafc8a0ec7d70c12ccada9bb27c4fa9ed6", + "observedAt": "2026-07-28" + } } ], "lastVerifiedAt": "2026-07-21", diff --git a/manifests/models/hy3.json b/manifests/models/hy3.json index 7c4420a0..dc9414f5 100644 --- a/manifests/models/hy3.json +++ b/manifests/models/hy3.json @@ -63,10 +63,10 @@ { "url": "https://artificialanalysis.ai/models/hy3", "title": "Artificial Analysis Hy3 model page", - "fields": ["releaseDate", "platformUrls.artificialAnalysis"] + "fields": ["releaseDate", "referenceTokenPricing", "platformUrls.artificialAnalysis"] } ], - "lastVerifiedAt": "2026-07-27", + "lastVerifiedAt": "2026-07-28", "verifiedBy": "codex-agent", "confidence": "high", "websiteUrl": "https://www.tencent.com", @@ -81,6 +81,21 @@ "primaryOffer": null, "offers": [] }, + "referenceTokenPricing": { + "currency": "USD", + "basis": "provider-median", + "rates": { + "input": 0.14, + "output": 0.58, + "cacheRead": 0.035, + "cacheWrite": null + }, + "source": { + "name": "Artificial Analysis", + "url": "https://artificialanalysis.ai/models/hy3", + "observedAt": "2026-07-28" + } + }, "releaseDate": "2026-07-06", "lifecycle": "latest", "knowledgeCutoff": null, diff --git a/manifests/models/kimi-k2-thinking.json b/manifests/models/kimi-k2-thinking.json index d3d40b49..a571c595 100644 --- a/manifests/models/kimi-k2-thinking.json +++ b/manifests/models/kimi-k2-thinking.json @@ -43,7 +43,12 @@ { "url": "https://platform.kimi.ai/docs/models", "title": "Kimi API model availability and K2 retirement notice", - "fields": ["lifecycle", "tokenPricing"] + "fields": ["lifecycle", "tokenPricing"], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:50692812b00a1b51ddd80947258f053d2317be53e34384d7421d2e9034d3b60d", + "observedAt": "2026-07-28" + } } ], "lastVerifiedAt": "2026-07-21", diff --git a/manifests/models/minimax-m2-7.json b/manifests/models/minimax-m2-7.json index e8ad7875..d9d9a5dd 100644 --- a/manifests/models/minimax-m2-7.json +++ b/manifests/models/minimax-m2-7.json @@ -53,7 +53,12 @@ { "url": "https://platform.minimax.io/docs/guides/pricing-paygo", "title": "MiniMax pay-as-you-go pricing", - "fields": ["tokenPricing"] + "fields": ["tokenPricing"], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:40b4c27c5a485ab71d531141a4f328d3bff0f1c2eb6c9d31103523119aadaae3", + "observedAt": "2026-07-28" + } }, { "url": "https://huggingface.co/MiniMaxAI/MiniMax-M2.7", diff --git a/manifests/models/minimax-m2.json b/manifests/models/minimax-m2.json index c3724ea2..d7b098e1 100644 --- a/manifests/models/minimax-m2.json +++ b/manifests/models/minimax-m2.json @@ -85,6 +85,15 @@ "sciCode": null, "liveCodeBench": null }, + "benchmarkTracking": [ + { + "provider": "swe-bench", + "benchmark": "sweBench", + "leaderboard": "Verified", + "resultId": "20251124_mini-v1.17.0_minimax-m2", + "modelLabel": "mini-SWE-agent + Minimax M2" + } + ], "platformUrls": { "huggingface": "https://huggingface.co/MiniMaxAI/MiniMax-M2", "artificialAnalysis": "https://artificialanalysis.ai/models/minimax-m2", diff --git a/manifests/models/mistral-small-4.json b/manifests/models/mistral-small-4.json index d86fcc4e..ca40d89b 100644 --- a/manifests/models/mistral-small-4.json +++ b/manifests/models/mistral-small-4.json @@ -63,7 +63,12 @@ { "url": "https://mistral.ai/pricing/api/", "title": "Mistral API pricing", - "fields": ["tokenPricing"] + "fields": ["tokenPricing"], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:740ecd45540ba01718b7682233cefd2f5b1f4dae7d40a16887e750dc9a0b84f0", + "observedAt": "2026-07-28" + } } ], "lastVerifiedAt": "2026-07-21", diff --git a/manifests/models/qwen3-7-max.json b/manifests/models/qwen3-7-max.json index 6c3f49e6..aacce795 100644 --- a/manifests/models/qwen3-7-max.json +++ b/manifests/models/qwen3-7-max.json @@ -51,15 +51,30 @@ "contextWindow", "capabilities", "inputModalities" - ] + ], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:1d3b2eb8b5a808acf23c0f5183039c4fd5056eca009e35c4a896a3661a82c108", + "observedAt": "2026-07-28" + } }, { "url": "https://help.aliyun.com/en/model-studio/model-pricing", "title": "Alibaba Cloud Model Studio model pricing", - "fields": ["docsUrl", "contextWindow", "tokenPricing"] + "fields": ["docsUrl", "contextWindow", "tokenPricing"], + "changeTracking": { + "method": "normalized-content-sha256", + "digest": "sha256:ea84e2dc7741e6a43646a6c2576e6c78384434821fac0d1774a79993cbc85023", + "observedAt": "2026-07-28" + } + }, + { + "url": "https://artificialanalysis.ai/models/qwen3-7-max", + "title": "Artificial Analysis Qwen3.7 Max model page", + "fields": ["referenceTokenPricing", "platformUrls.artificialAnalysis"] } ], - "lastVerifiedAt": "2026-07-21", + "lastVerifiedAt": "2026-07-28", "verifiedBy": "codex-agent", "confidence": "high", "websiteUrl": "https://qwen.ai", @@ -93,6 +108,21 @@ } ] }, + "referenceTokenPricing": { + "currency": "USD", + "basis": "first-party-api", + "rates": { + "input": 2.5, + "output": 7.5, + "cacheRead": 0.25, + "cacheWrite": 3.125 + }, + "source": { + "name": "Artificial Analysis", + "url": "https://artificialanalysis.ai/models/qwen3-7-max", + "observedAt": "2026-07-28" + } + }, "releaseDate": "2026-05-21", "lifecycle": "latest", "knowledgeCutoff": null, @@ -108,5 +138,9 @@ "sciCode": null, "liveCodeBench": null }, - "platformUrls": { "huggingface": null, "artificialAnalysis": null, "openrouter": null } + "platformUrls": { + "huggingface": null, + "artificialAnalysis": "https://artificialanalysis.ai/models/qwen3-7-max", + "openrouter": null + } } diff --git a/manifests/models/qwen3-7-plus.json b/manifests/models/qwen3-7-plus.json index 87059f62..dadd89a4 100644 --- a/manifests/models/qwen3-7-plus.json +++ b/manifests/models/qwen3-7-plus.json @@ -54,9 +54,14 @@ "url": "https://help.aliyun.com/en/model-studio/coding-plan", "title": "Model Studio Coding Plan", "fields": ["lifecycle"] + }, + { + "url": "https://artificialanalysis.ai/models/qwen3-7-plus", + "title": "Artificial Analysis Qwen3.7 Plus model page", + "fields": ["referenceTokenPricing", "platformUrls.artificialAnalysis"] } ], - "lastVerifiedAt": "2026-07-21", + "lastVerifiedAt": "2026-07-28", "verifiedBy": "codex-agent", "confidence": "high", "websiteUrl": "https://www.alibabacloud.com/product/modelstudio", @@ -99,6 +104,21 @@ } ] }, + "referenceTokenPricing": { + "currency": "USD", + "basis": "first-party-api", + "rates": { + "input": 0.4, + "output": 1.6, + "cacheRead": 0.04, + "cacheWrite": 0.5 + }, + "source": { + "name": "Artificial Analysis", + "url": "https://artificialanalysis.ai/models/qwen3-7-plus", + "observedAt": "2026-07-28" + } + }, "releaseDate": "2026-05-26", "lifecycle": "latest", "knowledgeCutoff": null, @@ -114,5 +134,9 @@ "sciCode": null, "liveCodeBench": null }, - "platformUrls": { "huggingface": null, "artificialAnalysis": null, "openrouter": null } + "platformUrls": { + "huggingface": null, + "artificialAnalysis": "https://artificialanalysis.ai/models/qwen3-7-plus", + "openrouter": null + } } diff --git a/package-lock.json b/package-lock.json index 861e2ec6..e3b21873 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3790,7 +3790,7 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "license": "MIT", "dependencies": { @@ -3803,7 +3803,7 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "license": "MIT", "engines": { @@ -3812,7 +3812,7 @@ }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "license": "MIT", "dependencies": { @@ -8598,7 +8598,7 @@ }, "node_modules/fast-glob": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "license": "MIT", "dependencies": { @@ -8614,7 +8614,7 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "license": "ISC", "dependencies": { @@ -8658,7 +8658,7 @@ }, "node_modules/fastq": { "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.20.1.tgz", "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "license": "ISC", "dependencies": { @@ -10720,7 +10720,7 @@ }, "node_modules/merge2": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "license": "MIT", "engines": { @@ -11827,7 +11827,7 @@ }, "node_modules/next-intl/node_modules/@swc/helpers": { "version": "0.5.23", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "resolved": "https://registry.npmmirror.com/@swc/helpers/-/helpers-0.5.23.tgz", "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", "license": "Apache-2.0", "optional": true, @@ -12319,7 +12319,7 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "funding": [ { @@ -12811,7 +12811,7 @@ }, "node_modules/reusify": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz", "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "license": "MIT", "engines": { @@ -12888,7 +12888,7 @@ }, "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "funding": [ { @@ -14623,7 +14623,7 @@ }, "node_modules/vitest/node_modules/@esbuild/aix-ppc64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "cpu": [ "ppc64" @@ -14641,7 +14641,7 @@ }, "node_modules/vitest/node_modules/@esbuild/android-arm": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.28.1.tgz", "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "cpu": [ "arm" @@ -14659,7 +14659,7 @@ }, "node_modules/vitest/node_modules/@esbuild/android-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "cpu": [ "arm64" @@ -14677,7 +14677,7 @@ }, "node_modules/vitest/node_modules/@esbuild/android-x64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.28.1.tgz", "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "cpu": [ "x64" @@ -14695,7 +14695,7 @@ }, "node_modules/vitest/node_modules/@esbuild/darwin-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "cpu": [ "arm64" @@ -14713,7 +14713,7 @@ }, "node_modules/vitest/node_modules/@esbuild/darwin-x64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "cpu": [ "x64" @@ -14731,7 +14731,7 @@ }, "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "cpu": [ "arm64" @@ -14749,7 +14749,7 @@ }, "node_modules/vitest/node_modules/@esbuild/freebsd-x64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "cpu": [ "x64" @@ -14767,7 +14767,7 @@ }, "node_modules/vitest/node_modules/@esbuild/linux-arm": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "cpu": [ "arm" @@ -14785,7 +14785,7 @@ }, "node_modules/vitest/node_modules/@esbuild/linux-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "cpu": [ "arm64" @@ -14803,7 +14803,7 @@ }, "node_modules/vitest/node_modules/@esbuild/linux-ia32": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "cpu": [ "ia32" @@ -14821,7 +14821,7 @@ }, "node_modules/vitest/node_modules/@esbuild/linux-loong64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "cpu": [ "loong64" @@ -14839,7 +14839,7 @@ }, "node_modules/vitest/node_modules/@esbuild/linux-mips64el": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "cpu": [ "mips64el" @@ -14857,7 +14857,7 @@ }, "node_modules/vitest/node_modules/@esbuild/linux-ppc64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "cpu": [ "ppc64" @@ -14875,7 +14875,7 @@ }, "node_modules/vitest/node_modules/@esbuild/linux-riscv64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "cpu": [ "riscv64" @@ -14893,7 +14893,7 @@ }, "node_modules/vitest/node_modules/@esbuild/linux-s390x": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "cpu": [ "s390x" @@ -14911,7 +14911,7 @@ }, "node_modules/vitest/node_modules/@esbuild/linux-x64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "cpu": [ "x64" @@ -14929,7 +14929,7 @@ }, "node_modules/vitest/node_modules/@esbuild/netbsd-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "cpu": [ "arm64" @@ -14947,7 +14947,7 @@ }, "node_modules/vitest/node_modules/@esbuild/netbsd-x64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "cpu": [ "x64" @@ -14965,7 +14965,7 @@ }, "node_modules/vitest/node_modules/@esbuild/openbsd-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "cpu": [ "arm64" @@ -14983,7 +14983,7 @@ }, "node_modules/vitest/node_modules/@esbuild/openbsd-x64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "cpu": [ "x64" @@ -15001,7 +15001,7 @@ }, "node_modules/vitest/node_modules/@esbuild/sunos-x64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "cpu": [ "x64" @@ -15019,7 +15019,7 @@ }, "node_modules/vitest/node_modules/@esbuild/win32-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "cpu": [ "arm64" @@ -15037,7 +15037,7 @@ }, "node_modules/vitest/node_modules/@esbuild/win32-ia32": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "cpu": [ "ia32" @@ -15055,7 +15055,7 @@ }, "node_modules/vitest/node_modules/@esbuild/win32-x64": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "cpu": [ "x64" @@ -15100,7 +15100,7 @@ }, "node_modules/vitest/node_modules/esbuild": { "version": "0.28.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.28.1.tgz", "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "dev": true, "hasInstallScript": true, diff --git a/package.json b/package.json index 5d4af954..70a9067c 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,6 @@ "data-health": "npx tsx scripts/validate/data-health.ts", "data-health:check": "npx tsx scripts/validate/data-health.ts --check-snapshot --fail-on=error", "data-health:report": "npx tsx scripts/validate/data-health.ts --write", - "changelog:check": "npx tsx scripts/validate/changelog.ts --check", - "changelog:generate": "npx tsx scripts/validate/changelog.ts --write", "dev:e2e": "next dev --turbopack -p 3100", "generate": "npx tsx scripts/generate/index.ts", "generate:manifests": "npx tsx scripts/generate/index.ts manifest-indexes", @@ -44,7 +42,12 @@ "refactor:sort-fields": "npx tsx scripts/refactor/index.ts sort-manifest-fields", "fetch": "npx tsx scripts/fetch/index.ts", "fetch:github-stars": "npx tsx scripts/fetch/index.ts github-stars", - "fetch:benchmarks": "npx tsx scripts/fetch/index.ts benchmarks", + "fetch:product-versions": "npx tsx scripts/fetch/fetch-product-versions.ts --write", + "fetch:product-versions:check": "npx tsx scripts/fetch/fetch-product-versions.ts --check", + "fetch:benchmarks": "npx tsx scripts/fetch/fetch-benchmarks.ts --write", + "fetch:benchmarks:check": "npx tsx scripts/fetch/fetch-benchmarks.ts --check", + "fetch:model-sources": "npx tsx scripts/fetch/fetch-model-sources.ts --write", + "fetch:model-sources:check": "npx tsx scripts/fetch/fetch-model-sources.ts --check", "deploy": "npm run build:next && opennextjs-cloudflare build --skipBuild && opennextjs-cloudflare deploy", "preview": "npm run build:next && opennextjs-cloudflare build --skipBuild && opennextjs-cloudflare preview", "cf-typegen": "wrangler types --env-interface CloudflareEnv ./cloudflare-env.d.ts", diff --git a/scripts/README.md b/scripts/README.md index 09de6053..0e2c3d1c 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -11,13 +11,17 @@ Repository automation is written in TypeScript and executed with `tsx`. Prefer t | Generate content metadata | `npm run generate:metadata` | Rebuilds article, docs, FAQ, and manifesto metadata | | Sort manifest fields | `npm run refactor:sort-fields` | Reorders manifest JSON using schema order | | Fetch GitHub stars | `npm run fetch:github-stars` | Updates `data/github-stars.json` | +| Refresh product versions | `npm run fetch:product-versions` | Updates manifest `latestVersion` values from configured package registries | +| Check product versions | `npm run fetch:product-versions:check` | Fails when a configured registry reports a newer stable version | +| Refresh benchmark scores | `npm run fetch:benchmarks` | Updates exact configured entries from official structured leaderboards | +| Check benchmark scores | `npm run fetch:benchmarks:check` | Fails when an exact configured leaderboard score changed | +| Record model source changes | `npm run fetch:model-sources` | Updates only monitored official-source content digests | +| Check model sources | `npm run fetch:model-sources:check` | Fails when monitored pricing or lifecycle source content changed | | Validate manifests and data | `npm run test:validate` | Runs the validation test suite | | Run browser smoke tests | `npm run test:e2e` | Exercises core journeys in Chromium against a local Next.js server | | Audit dependencies | `npm run security:audit` | Fails on high or critical npm advisories in the full dependency tree | | Check data health | `npm run data-health:check` | Fails on invalid health-report data | | Refresh data-health snapshot | `npm run data-health:report` | Writes `data/data-health.json` and `docs/DATA-HEALTH.md` | -| Check manifest changelog | `npm run changelog:check` | Requires manifest diffs to be represented in `data/changelogs.json` | -| Generate manifest changelog | `npm run changelog:generate -- --base= --id= --summary=""` | Adds or replaces one entry from a Git diff | | Validate i18n structure | `npm run validate:i18n` | Checks locale alignment and translation shape | | Validate i18n usage | `npm run validate:i18n-usage` | Checks translation keys referenced by source | | Validate duplicate i18n values | `npm run validate:i18n-duplicates` | Reports duplicated translation content | @@ -44,6 +48,9 @@ Each category with an `index.ts` auto-discovers sibling `.ts` scripts. A filenam npx tsx scripts/generate/index.ts manifest-indexes npx tsx scripts/refactor/index.ts export-vendors npx tsx scripts/fetch/index.ts github-stars +npx tsx scripts/fetch/fetch-product-versions.ts --check +npx tsx scripts/fetch/fetch-benchmarks.ts --check +npx tsx scripts/fetch/fetch-model-sources.ts --check ``` ## Generated files @@ -52,6 +59,12 @@ Generated modules under `src/lib/generated/` are committed. After changing manif `data/github-stars.json` is source data, not generated build output. Update it with `npm run fetch:github-stars`; the dedicated scheduled workflow also opens a pull request when values change. +Product-version synchronization is declarative and runs separately from the generic `npm run fetch` batch. Add `releaseTracking` to a product manifest with an official npm, PyPI, Homebrew, crates.io, GitHub Releases, or Visual Studio Marketplace identifier. The generic version fetcher reads that manifest configuration; product identifiers must not be hardcoded in TypeScript. Failed lookups leave every manifest unchanged, and the scheduled workflow opens a pull request rather than pushing directly to `main`. + +Benchmark synchronization also keeps model-to-result mappings in JSON manifests. An exact upstream result ID and exact displayed label are both required; a renamed or missing result fails closed instead of fuzzy matching another model or evaluation setup. + +Pricing and lifecycle monitoring fingerprints only explicitly configured official source pages. A source-content change updates the source digest in a review pull request; it never modifies `tokenPricing`, `lifecycle`, or other model facts automatically. + ## Adding a script 1. Add a TypeScript file to the relevant category. diff --git a/scripts/fetch/fetch-benchmarks.ts b/scripts/fetch/fetch-benchmarks.ts new file mode 100644 index 00000000..312ed361 --- /dev/null +++ b/scripts/fetch/fetch-benchmarks.ts @@ -0,0 +1,43 @@ +#!/usr/bin/env node + +import { syncBenchmarks } from './lib/benchmark-sync' + +function hasFlag(flag: string): boolean { + return process.argv.slice(2).includes(flag) +} + +async function main(): Promise { + const write = hasFlag('--write') + const check = hasFlag('--check') + if (write && check) { + throw new Error('Use either --write or --check, not both.') + } + + const result = await syncBenchmarks({ + rootDir: process.cwd(), + write, + }) + + console.log(`Checked ${result.checked} exact benchmark mappings.`) + if (result.changes.length === 0) { + console.log('All tracked benchmark scores are current.') + return + } + + for (const change of result.changes) { + console.log( + `${write ? 'Updated' : 'Would update'} models/${change.modelId} ${change.benchmark}: ${change.previousScore} -> ${change.nextScore}` + ) + console.log(` ${change.modelLabel}`) + console.log(` Source: ${change.sourceUrl}`) + } + + if (check) { + process.exitCode = 1 + } +} + +main().catch(error => { + console.error(error instanceof Error ? error.message : error) + process.exit(1) +}) diff --git a/scripts/fetch/fetch-model-sources.ts b/scripts/fetch/fetch-model-sources.ts new file mode 100644 index 00000000..a5cc5c27 --- /dev/null +++ b/scripts/fetch/fetch-model-sources.ts @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +import { syncModelSourceDigests } from './lib/model-source-sync' + +function hasFlag(flag: string): boolean { + return process.argv.slice(2).includes(flag) +} + +function currentShanghaiDate(): string { + return new Intl.DateTimeFormat('en-CA', { + timeZone: 'Asia/Shanghai', + year: 'numeric', + month: '2-digit', + day: '2-digit', + }).format(new Date()) +} + +async function main(): Promise { + const write = hasFlag('--write') + const check = hasFlag('--check') + if (write && check) { + throw new Error('Use either --write or --check, not both.') + } + + const result = await syncModelSourceDigests({ + rootDir: process.cwd(), + write, + observedAt: currentShanghaiDate(), + }) + + console.log(`Checked ${result.checked} monitored model sources.`) + if (result.changes.length === 0) { + console.log('All monitored pricing and lifecycle sources are unchanged.') + return + } + + for (const change of result.changes) { + console.log( + `${write ? 'Recorded' : 'Detected'} source change for models/${change.modelId}: ${change.fields.join(', ')}` + ) + console.log(` ${change.url}`) + } + + if (check) { + process.exitCode = 1 + } +} + +main().catch(error => { + console.error(error instanceof Error ? error.message : error) + process.exit(1) +}) diff --git a/scripts/fetch/fetch-product-versions.ts b/scripts/fetch/fetch-product-versions.ts new file mode 100644 index 00000000..401743a3 --- /dev/null +++ b/scripts/fetch/fetch-product-versions.ts @@ -0,0 +1,42 @@ +#!/usr/bin/env node + +import { syncProductVersions } from './lib/product-version-sync' + +function hasFlag(flag: string): boolean { + return process.argv.slice(2).includes(flag) +} + +async function main(): Promise { + const write = hasFlag('--write') + const check = hasFlag('--check') + if (write && check) { + throw new Error('Use either --write or --check, not both.') + } + + const result = await syncProductVersions({ + rootDir: process.cwd(), + write, + }) + + console.log(`Checked ${result.checked} tracked products.`) + if (result.changes.length === 0) { + console.log('All tracked product versions are current.') + return + } + + for (const change of result.changes) { + console.log( + `${write ? 'Updated' : 'Would update'} ${change.category}/${change.id}: ${change.previousVersion} -> ${change.nextVersion}` + ) + console.log(` Source: ${change.sourceUrl}`) + } + + if (check) { + process.exitCode = 1 + } +} + +main().catch(error => { + console.error(error instanceof Error ? error.message : error) + process.exit(1) +}) diff --git a/scripts/fetch/index.ts b/scripts/fetch/index.ts index d3269053..5a310879 100644 --- a/scripts/fetch/index.ts +++ b/scripts/fetch/index.ts @@ -16,6 +16,7 @@ import { runCategoryScripts } from '../_shared/runner' runCategoryScripts({ categoryName: 'fetch', + excludes: ['benchmarks', 'model-sources', 'product-versions'], }).catch(error => { console.error('Fatal error:', error) process.exit(1) diff --git a/scripts/fetch/lib/benchmark-sync.ts b/scripts/fetch/lib/benchmark-sync.ts new file mode 100644 index 00000000..36596b46 --- /dev/null +++ b/scripts/fetch/lib/benchmark-sync.ts @@ -0,0 +1,199 @@ +import fs from 'node:fs/promises' +import path from 'node:path' + +import type { ManifestBenchmarkTracking } from '../../../src/types/manifests' + +const SWE_BENCH_SOURCE_URL = + 'https://raw.githubusercontent.com/SWE-bench/swe-bench.github.io/master/data/leaderboards.json' + +interface ModelManifest { + id: string + benchmarks: Record + benchmarkTracking?: ManifestBenchmarkTracking[] +} + +interface JsonResponse { + ok: boolean + status: number + statusText: string + json(): Promise +} + +export type BenchmarkFetch = (input: string | URL) => Promise + +interface SweBenchResult { + folder: string + name: string + resolved: number +} + +interface SweBenchLeaderboard { + name: string + results: SweBenchResult[] +} + +export interface BenchmarkChange { + modelId: string + filePath: string + benchmark: ManifestBenchmarkTracking['benchmark'] + previousScore: number | null + nextScore: number + modelLabel: string + sourceUrl: string +} + +export interface BenchmarkSyncResult { + checked: number + changes: BenchmarkChange[] +} + +function isRecord(value: unknown): value is Record { + return Boolean(value) && typeof value === 'object' && !Array.isArray(value) +} + +function escapeRegularExpression(value: string): string { + return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') +} + +function parseSweBenchLeaderboards(value: unknown): SweBenchLeaderboard[] { + if (!isRecord(value) || !Array.isArray(value.leaderboards)) { + throw new Error('SWE-bench returned no leaderboards array') + } + + return value.leaderboards.map((leaderboard, leaderboardIndex) => { + if (!isRecord(leaderboard) || typeof leaderboard.name !== 'string') { + throw new Error(`SWE-bench leaderboard ${leaderboardIndex} has no usable name`) + } + if (!Array.isArray(leaderboard.results)) { + throw new Error(`SWE-bench leaderboard ${leaderboard.name} has no results array`) + } + + return { + name: leaderboard.name, + results: leaderboard.results.map((result, resultIndex) => { + if ( + !isRecord(result) || + typeof result.folder !== 'string' || + typeof result.name !== 'string' || + typeof result.resolved !== 'number' + ) { + throw new Error( + `SWE-bench ${leaderboard.name} result ${resultIndex} is missing folder, name, or resolved` + ) + } + return { + folder: result.folder, + name: result.name, + resolved: result.resolved, + } + }), + } + }) +} + +async function fetchSweBenchLeaderboards( + fetchImpl: BenchmarkFetch +): Promise { + const response = await fetchImpl(SWE_BENCH_SOURCE_URL) + if (!response.ok) { + throw new Error(`${SWE_BENCH_SOURCE_URL} returned ${response.status} ${response.statusText}`) + } + return parseSweBenchLeaderboards(await response.json()) +} + +async function loadTrackedModels(rootDir: string): Promise< + Array<{ + filePath: string + manifest: ModelManifest + }> +> { + const directory = path.join(rootDir, 'manifests', 'models') + const models = [] + for (const fileName of (await fs.readdir(directory)) + .filter(file => file.endsWith('.json')) + .sort()) { + const filePath = path.join(directory, fileName) + const manifest = JSON.parse(await fs.readFile(filePath, 'utf8')) as ModelManifest + if (manifest.benchmarkTracking?.length) { + models.push({ filePath, manifest }) + } + } + return models +} + +export async function syncBenchmarks(options: { + rootDir: string + write: boolean + fetchImpl?: BenchmarkFetch +}): Promise { + const trackedModels = await loadTrackedModels(options.rootDir) + const trackingEntries = trackedModels.flatMap(entry => + (entry.manifest.benchmarkTracking ?? []).map(tracking => ({ entry, tracking })) + ) + const fetchImpl = options.fetchImpl ?? (fetch as BenchmarkFetch) + const leaderboards = trackingEntries.length ? await fetchSweBenchLeaderboards(fetchImpl) : [] + + const changes: BenchmarkChange[] = [] + for (const { entry, tracking } of trackingEntries) { + const leaderboard = leaderboards.find(item => item.name === tracking.leaderboard) + if (!leaderboard) { + throw new Error( + `models/${entry.manifest.id}: SWE-bench leaderboard ${tracking.leaderboard} was not found` + ) + } + const matches = leaderboard.results.filter(result => result.folder === tracking.resultId) + if (matches.length !== 1) { + throw new Error( + `models/${entry.manifest.id}: expected exactly one SWE-bench result ${tracking.resultId}, found ${matches.length}` + ) + } + const result = matches[0] + if (!result) { + throw new Error(`models/${entry.manifest.id}: SWE-bench result disappeared after validation`) + } + if (result.name !== tracking.modelLabel) { + throw new Error( + `models/${entry.manifest.id}: SWE-bench label changed from "${tracking.modelLabel}" to "${result.name}"` + ) + } + + const previousScore = entry.manifest.benchmarks[tracking.benchmark] + if (typeof previousScore !== 'number' && previousScore !== null) { + throw new Error(`models/${entry.manifest.id}: ${tracking.benchmark} must be a number or null`) + } + if (previousScore === result.resolved) continue + changes.push({ + modelId: entry.manifest.id, + filePath: entry.filePath, + benchmark: tracking.benchmark, + previousScore, + nextScore: result.resolved, + modelLabel: result.name, + sourceUrl: SWE_BENCH_SOURCE_URL, + }) + } + + if (options.write) { + const changesByFile = Map.groupBy(changes, change => change.filePath) + for (const [filePath, fileChanges] of changesByFile) { + let source = await fs.readFile(filePath, 'utf8') + for (const change of fileChanges) { + const previousValue = escapeRegularExpression(JSON.stringify(change.previousScore)) + const pattern = new RegExp( + `("${escapeRegularExpression(change.benchmark)}"\\s*:\\s*)${previousValue}`, + 'g' + ) + const matches = [...source.matchAll(pattern)] + if (matches.length !== 1) { + throw new Error( + `models/${change.modelId} must contain exactly one matching ${change.benchmark} field` + ) + } + source = source.replace(pattern, `$1${JSON.stringify(change.nextScore)}`) + } + await fs.writeFile(filePath, source, 'utf8') + } + } + + return { checked: trackingEntries.length, changes } +} diff --git a/scripts/fetch/lib/model-source-sync.ts b/scripts/fetch/lib/model-source-sync.ts new file mode 100644 index 00000000..cd65625f --- /dev/null +++ b/scripts/fetch/lib/model-source-sync.ts @@ -0,0 +1,198 @@ +import { createHash } from 'node:crypto' +import fs from 'node:fs/promises' +import path from 'node:path' + +import type { ManifestSource } from '../../../src/types/manifests' + +interface ModelManifest { + id: string + sources?: ManifestSource[] +} + +interface TextResponse { + ok: boolean + status: number + statusText: string + text(): Promise +} + +export type SourceFetch = ( + input: string | URL, + init?: { headers?: Record } +) => Promise + +interface TrackedSource { + modelId: string + filePath: string + source: ManifestSource & { + changeTracking: NonNullable + } +} + +export interface ModelSourceChange { + modelId: string + filePath: string + url: string + fields: string[] + previousDigest: string | null + nextDigest: string + observedAt: string +} + +export interface ModelSourceSyncResult { + checked: number + changes: ModelSourceChange[] +} + +function escapeRegularExpression(value: string): string { + return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') +} + +function decodeCommonEntities(value: string): string { + return value + .replaceAll(' ', ' ') + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"') + .replaceAll(''', "'") +} + +export function normalizeSourceContent(value: string): string { + return decodeCommonEntities( + value + .replace(//g, ' ') + .replace(/<(script|style|noscript|svg)\b[\s\S]*?<\/\1>/gi, ' ') + .replace(/<[^>]+>/g, ' ') + ) + .replace(/\s+/g, ' ') + .trim() +} + +export function digestSourceContent(value: string): string { + return `sha256:${createHash('sha256').update(normalizeSourceContent(value)).digest('hex')}` +} + +async function loadTrackedSources(rootDir: string): Promise { + const directory = path.join(rootDir, 'manifests', 'models') + const tracked: TrackedSource[] = [] + for (const fileName of (await fs.readdir(directory)) + .filter(file => file.endsWith('.json')) + .sort()) { + const filePath = path.join(directory, fileName) + const manifest = JSON.parse(await fs.readFile(filePath, 'utf8')) as ModelManifest + for (const source of manifest.sources ?? []) { + if (source.changeTracking) { + tracked.push({ + modelId: manifest.id, + filePath, + source: { + ...source, + changeTracking: source.changeTracking, + }, + }) + } + } + } + return tracked +} + +async function fetchDigest(url: string, fetchImpl: SourceFetch): Promise { + const response = await fetchImpl(url, { + headers: { + Accept: 'text/html,application/xhtml+xml,text/plain;q=0.9,*/*;q=0.1', + 'Accept-Language': 'en-US,en;q=0.9', + 'User-Agent': 'aicodingstack-model-source-monitor', + }, + }) + if (!response.ok) { + throw new Error(`${url} returned ${response.status} ${response.statusText}`) + } + const content = await response.text() + const normalized = normalizeSourceContent(content) + if (normalized.length < 100) { + throw new Error(`${url} returned too little usable content`) + } + return digestSourceContent(content) +} + +function replaceTrackedSource(source: string, change: ModelSourceChange): string { + const url = escapeRegularExpression(JSON.stringify(change.url)) + const previousDigest = escapeRegularExpression(JSON.stringify(change.previousDigest)) + const trackingPattern = new RegExp( + `("url"\\s*:\\s*${url}[\\s\\S]*?"changeTracking"\\s*:\\s*\\{[\\s\\S]*?"digest"\\s*:\\s*)${previousDigest}([\\s\\S]*?"observedAt"\\s*:\\s*)(?:"[^"]*"|null)`, + 'g' + ) + const matches = [...source.matchAll(trackingPattern)] + if (matches.length !== 1) { + throw new Error( + `models/${change.modelId} must contain exactly one matching tracked source ${change.url}` + ) + } + return source.replace( + trackingPattern, + `$1${JSON.stringify(change.nextDigest)}$2${JSON.stringify(change.observedAt)}` + ) +} + +export async function syncModelSourceDigests(options: { + rootDir: string + write: boolean + observedAt: string + fetchImpl?: SourceFetch +}): Promise { + const tracked = await loadTrackedSources(options.rootDir) + const fetchImpl = options.fetchImpl ?? (fetch as SourceFetch) + const digestByUrl = new Map>() + for (const entry of tracked) { + if (!digestByUrl.has(entry.source.url)) { + digestByUrl.set(entry.source.url, fetchDigest(entry.source.url, fetchImpl)) + } + } + + const observations = await Promise.allSettled( + tracked.map(async entry => ({ + entry, + digest: await digestByUrl.get(entry.source.url), + })) + ) + const failures = observations.flatMap((result, index) => + result.status === 'rejected' + ? [`models/${tracked[index]?.modelId}: ${String(result.reason)}`] + : [] + ) + if (failures.length > 0) { + throw new Error( + `Model source monitoring failed without writing changes:\n${failures.join('\n')}` + ) + } + + const changes: ModelSourceChange[] = [] + for (const result of observations) { + if (result.status !== 'fulfilled') continue + const { entry, digest } = result.value + if (!digest || digest === entry.source.changeTracking.digest) continue + changes.push({ + modelId: entry.modelId, + filePath: entry.filePath, + url: entry.source.url, + fields: entry.source.fields ?? [], + previousDigest: entry.source.changeTracking.digest, + nextDigest: digest, + observedAt: options.observedAt, + }) + } + + if (options.write) { + const changesByFile = Map.groupBy(changes, change => change.filePath) + for (const [filePath, fileChanges] of changesByFile) { + let source = await fs.readFile(filePath, 'utf8') + for (const change of fileChanges) { + source = replaceTrackedSource(source, change) + } + await fs.writeFile(filePath, source, 'utf8') + } + } + + return { checked: tracked.length, changes } +} diff --git a/scripts/fetch/lib/product-version-sync.ts b/scripts/fetch/lib/product-version-sync.ts new file mode 100644 index 00000000..21551526 --- /dev/null +++ b/scripts/fetch/lib/product-version-sync.ts @@ -0,0 +1,336 @@ +import fs from 'node:fs/promises' +import path from 'node:path' + +import type { ManifestReleaseTracking } from '../../../src/types/manifests' + +const PRODUCT_CATEGORIES = ['ides', 'clis', 'desktops', 'extensions'] as const + +interface ProductManifest { + id: string + latestVersion: string + releaseTracking?: ManifestReleaseTracking + [key: string]: unknown +} + +interface JsonResponse { + ok: boolean + status: number + statusText: string + json(): Promise +} + +export type VersionFetch = ( + input: string | URL, + init?: { + method?: string + headers?: Record + body?: string + } +) => Promise + +export interface VersionObservation { + version: string + sourceUrl: string +} + +export interface VersionChange { + category: (typeof PRODUCT_CATEGORIES)[number] + id: string + filePath: string + previousVersion: string + nextVersion: string + sourceUrl: string +} + +export interface VersionSyncResult { + checked: number + changes: VersionChange[] +} + +function isRecord(value: unknown): value is Record { + return Boolean(value) && typeof value === 'object' && !Array.isArray(value) +} + +function escapeRegularExpression(value: string): string { + return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') +} + +function getRequiredString( + value: unknown, + field: string, + provider: ManifestReleaseTracking['provider'] +): string { + if (typeof value !== 'string' || !value.trim()) { + throw new Error(`${provider} returned no usable ${field}`) + } + return value.trim() +} + +async function fetchJson( + fetchImpl: VersionFetch, + url: string, + init: { + method?: string + headers?: Record + body?: string + } = {} +): Promise { + const response = await fetchImpl(url, init) + if (!response.ok) { + throw new Error(`${url} returned ${response.status} ${response.statusText}`) + } + return response.json() +} + +function githubHeaders(): Record { + const headers: Record = { + Accept: 'application/vnd.github+json', + 'User-Agent': 'aicodingstack-version-sync', + 'X-GitHub-Api-Version': '2022-11-28', + } + if (process.env.GITHUB_TOKEN) { + headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}` + } + return headers +} + +export async function fetchTrackedVersion( + tracking: ManifestReleaseTracking, + fetchImpl: VersionFetch = fetch as VersionFetch +): Promise { + switch (tracking.provider) { + case 'npm': { + const url = `https://registry.npmjs.org/${encodeURIComponent(tracking.identifier)}` + const data = await fetchJson(fetchImpl, url) + const distTags = isRecord(data) && isRecord(data['dist-tags']) ? data['dist-tags'] : null + const channel = tracking.channel ?? 'latest' + return { + version: getRequiredString(distTags?.[channel], `dist-tags.${channel}`, tracking.provider), + sourceUrl: `https://www.npmjs.com/package/${tracking.identifier}`, + } + } + case 'homebrew-formula': { + const url = `https://formulae.brew.sh/api/formula/${encodeURIComponent(tracking.identifier)}.json` + const data = await fetchJson(fetchImpl, url) + const versions = isRecord(data) && isRecord(data.versions) ? data.versions : null + return { + version: getRequiredString(versions?.stable, 'versions.stable', tracking.provider), + sourceUrl: `https://formulae.brew.sh/formula/${tracking.identifier}`, + } + } + case 'homebrew-cask': { + const url = `https://formulae.brew.sh/api/cask/${encodeURIComponent(tracking.identifier)}.json` + const data = await fetchJson(fetchImpl, url) + return { + version: getRequiredString( + isRecord(data) ? data.version : null, + 'version', + tracking.provider + ), + sourceUrl: `https://formulae.brew.sh/cask/${tracking.identifier}`, + } + } + case 'crates-io': { + const url = `https://crates.io/api/v1/crates/${encodeURIComponent(tracking.identifier)}` + const data = await fetchJson(fetchImpl, url, { + headers: { + Accept: 'application/json', + 'User-Agent': 'aicodingstack-version-sync', + }, + }) + const crate = isRecord(data) && isRecord(data.crate) ? data.crate : null + const stableVersion = crate?.max_stable_version ?? crate?.max_version + return { + version: getRequiredString(stableVersion, 'max_stable_version', tracking.provider), + sourceUrl: `https://crates.io/crates/${tracking.identifier}`, + } + } + case 'pypi': { + const url = `https://pypi.org/pypi/${encodeURIComponent(tracking.identifier)}/json` + const data = await fetchJson(fetchImpl, url) + const info = isRecord(data) && isRecord(data.info) ? data.info : null + return { + version: getRequiredString(info?.version, 'info.version', tracking.provider), + sourceUrl: `https://pypi.org/project/${tracking.identifier}/`, + } + } + case 'vscode-marketplace': { + const url = + 'https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery?api-version=7.2-preview.1' + const data = await fetchJson(fetchImpl, url, { + method: 'POST', + headers: { + Accept: 'application/json;api-version=7.2-preview.1', + 'Content-Type': 'application/json', + 'User-Agent': 'aicodingstack-version-sync', + }, + body: JSON.stringify({ + filters: [ + { + criteria: [{ filterType: 7, value: tracking.identifier }], + }, + ], + flags: 914, + }), + }) + const results = isRecord(data) && Array.isArray(data.results) ? data.results : [] + const firstResult = isRecord(results[0]) ? results[0] : null + const extensions = + firstResult && Array.isArray(firstResult.extensions) ? firstResult.extensions : [] + const firstExtension = isRecord(extensions[0]) ? extensions[0] : null + const versions = + firstExtension && Array.isArray(firstExtension.versions) ? firstExtension.versions : [] + const firstVersion = isRecord(versions[0]) ? versions[0] : null + return { + version: getRequiredString(firstVersion?.version, 'versions[0].version', tracking.provider), + sourceUrl: `https://marketplace.visualstudio.com/items?itemName=${tracking.identifier}`, + } + } + case 'github-release': { + const url = `https://api.github.com/repos/${tracking.identifier}/releases/latest` + const data = await fetchJson(fetchImpl, url, githubHeaders()) + return { + version: getRequiredString( + isRecord(data) ? data.tag_name : null, + 'tag_name', + tracking.provider + ), + sourceUrl: + isRecord(data) && typeof data.html_url === 'string' + ? data.html_url + : `https://github.com/${tracking.identifier}/releases/latest`, + } + } + } +} + +function parseStableNumericVersion(value: string): number[] | null { + const normalized = value.trim().replace(/^v(?=\d)/, '') + if (!/^\d+(?:\.\d+)*$/.test(normalized)) return null + return normalized.split('.').map(segment => Number(segment)) +} + +function compareNumericVersions(left: number[], right: number[]): number { + const length = Math.max(left.length, right.length) + for (let index = 0; index < length; index++) { + const difference = (left[index] ?? 0) - (right[index] ?? 0) + if (difference !== 0) return difference + } + return 0 +} + +function formatObservedVersion(observed: string, current: string): string { + const normalized = observed.trim() + if (/^v\d/.test(current) && !/^v\d/.test(normalized)) return `v${normalized}` + if (!/^v\d/.test(current) && /^v\d/.test(normalized)) return normalized.slice(1) + return normalized +} + +function assertNotDowngrade( + current: string, + observed: string, + tracking: ManifestReleaseTracking +): void { + if (!['npm', 'crates-io', 'pypi', 'vscode-marketplace'].includes(tracking.provider)) return + const currentVersion = parseStableNumericVersion(current) + const observedVersion = parseStableNumericVersion(observed) + if ( + currentVersion && + observedVersion && + compareNumericVersions(observedVersion, currentVersion) < 0 + ) { + throw new Error( + `${tracking.provider} reported ${observed}, which is older than recorded version ${current}` + ) + } +} + +async function loadTrackedManifests(rootDir: string): Promise< + Array<{ + category: (typeof PRODUCT_CATEGORIES)[number] + filePath: string + manifest: ProductManifest + }> +> { + const manifests: Array<{ + category: (typeof PRODUCT_CATEGORIES)[number] + filePath: string + manifest: ProductManifest + }> = [] + + for (const category of PRODUCT_CATEGORIES) { + const directory = path.join(rootDir, 'manifests', category) + const fileNames = (await fs.readdir(directory)).filter(file => file.endsWith('.json')).sort() + for (const fileName of fileNames) { + const filePath = path.join(directory, fileName) + const manifest = JSON.parse(await fs.readFile(filePath, 'utf8')) as ProductManifest + if (manifest.releaseTracking) { + manifests.push({ category, filePath, manifest }) + } + } + } + + return manifests +} + +export async function syncProductVersions(options: { + rootDir: string + write: boolean + fetchImpl?: VersionFetch +}): Promise { + const tracked = await loadTrackedManifests(options.rootDir) + const observations = await Promise.allSettled( + tracked.map(async entry => { + const tracking = entry.manifest.releaseTracking + if (!tracking) throw new Error(`${entry.manifest.id} has no releaseTracking configuration`) + const observation = await fetchTrackedVersion(tracking, options.fetchImpl) + const nextVersion = formatObservedVersion(observation.version, entry.manifest.latestVersion) + assertNotDowngrade(entry.manifest.latestVersion, nextVersion, tracking) + return { entry, observation, nextVersion } + }) + ) + + const failures = observations.flatMap((result, index) => + result.status === 'rejected' + ? [`${tracked[index]?.category}/${tracked[index]?.manifest.id}: ${String(result.reason)}`] + : [] + ) + if (failures.length > 0) { + throw new Error( + `Version synchronization failed without writing changes:\n${failures.join('\n')}` + ) + } + + const changes: VersionChange[] = [] + for (const result of observations) { + if (result.status !== 'fulfilled') continue + const { entry, observation, nextVersion } = result.value + if (nextVersion === entry.manifest.latestVersion) continue + changes.push({ + category: entry.category, + id: entry.manifest.id, + filePath: entry.filePath, + previousVersion: entry.manifest.latestVersion, + nextVersion, + sourceUrl: observation.sourceUrl, + }) + } + + if (options.write) { + for (const change of changes) { + const source = await fs.readFile(change.filePath, 'utf8') + const previousValue = escapeRegularExpression(JSON.stringify(change.previousVersion)) + const pattern = new RegExp(`("latestVersion"\\s*:\\s*)${previousValue}`, 'g') + const matches = [...source.matchAll(pattern)] + if (matches.length !== 1) { + throw new Error( + `${change.category}/${change.id} must contain exactly one matching latestVersion field` + ) + } + const updated = source.replace(pattern, `$1${JSON.stringify(change.nextVersion)}`) + await fs.writeFile(change.filePath, updated, 'utf8') + } + } + + return { checked: tracked.length, changes } +} diff --git a/scripts/validate/changelog.ts b/scripts/validate/changelog.ts deleted file mode 100644 index 9906fbf6..00000000 --- a/scripts/validate/changelog.ts +++ /dev/null @@ -1,264 +0,0 @@ -#!/usr/bin/env node - -import { execFileSync } from 'node:child_process' -import fs from 'node:fs' -import path from 'node:path' -import { fileURLToPath } from 'node:url' - -const MANIFEST_CATEGORIES = [ - 'ides', - 'clis', - 'desktops', - 'extensions', - 'models', - 'providers', - 'vendors', -] as const - -type ManifestCategory = (typeof MANIFEST_CATEGORIES)[number] -type ChangeType = 'added' | 'updated' | 'removed' - -export interface ManifestChange { - category: ManifestCategory - id: string - change: ChangeType - fields: string[] -} - -interface ChangelogEntry { - id: string - date: string - summary: string - changes: ManifestChange[] -} - -interface ChangelogFile { - version: 1 - entries: ChangelogEntry[] -} - -function comparableFields(record: Record | null): string[] { - return record - ? Object.keys(record) - .filter(key => key !== '$schema') - .sort() - : [] -} - -export function createManifestChange( - category: ManifestCategory, - id: string, - before: Record | null, - after: Record | null -): ManifestChange | null { - if (!before && !after) return null - if (!before) return { category, id, change: 'added', fields: comparableFields(after) } - if (!after) return { category, id, change: 'removed', fields: comparableFields(before) } - - const fields = [...new Set([...comparableFields(before), ...comparableFields(after)])].filter( - key => JSON.stringify(before[key]) !== JSON.stringify(after[key]) - ) - return fields.length > 0 ? { category, id, change: 'updated', fields } : null -} - -function runGit(rootDir: string, args: string[]): string { - return execFileSync('git', args, { cwd: rootDir, encoding: 'utf8' }).trim() -} - -function readBaseManifest( - rootDir: string, - base: string, - filePath: string -): Record | null { - try { - return JSON.parse(runGit(rootDir, ['show', `${base}:${filePath}`])) as Record - } catch { - return null - } -} - -function readWorkingManifest(rootDir: string, filePath: string): Record | null { - const absolutePath = path.join(rootDir, filePath) - return fs.existsSync(absolutePath) - ? (JSON.parse(fs.readFileSync(absolutePath, 'utf8')) as Record) - : null -} - -function parseManifestPath(filePath: string): { category: ManifestCategory; id: string } | null { - const match = /^manifests\/([^/]+)\/([^/]+)\.json$/.exec(filePath) - if (!match || !MANIFEST_CATEGORIES.includes(match[1] as ManifestCategory)) return null - return { category: match[1] as ManifestCategory, id: match[2]! } -} - -export function collectManifestChanges(rootDir: string, base: string): ManifestChange[] { - const manifestPaths = MANIFEST_CATEGORIES.map(category => `manifests/${category}`) - const trackedOutput = runGit(rootDir, [ - 'diff', - '--name-status', - '--find-renames', - base, - '--', - ...manifestPaths, - ]) - const untrackedOutput = runGit(rootDir, [ - 'ls-files', - '--others', - '--exclude-standard', - '--', - ...manifestPaths, - ]) - const lines = [ - ...(trackedOutput ? trackedOutput.split('\n') : []), - ...(untrackedOutput ? untrackedOutput.split('\n').map(filePath => `A\t${filePath}`) : []), - ] - if (lines.length === 0) return [] - - const changes: ManifestChange[] = [] - for (const line of lines) { - const [status = '', firstPath, secondPath] = line.split('\t') - const paths = status.startsWith('R') ? [firstPath, secondPath] : [firstPath] - for (const filePath of paths.filter((value): value is string => Boolean(value))) { - const parsed = parseManifestPath(filePath) - if (!parsed) continue - const before = - status.startsWith('A') || (status.startsWith('R') && filePath === secondPath) - ? null - : readBaseManifest(rootDir, base, filePath) - const after = - status.startsWith('D') || (status.startsWith('R') && filePath === firstPath) - ? null - : readWorkingManifest(rootDir, filePath) - const change = createManifestChange(parsed.category, parsed.id, before, after) - if (change) changes.push(change) - } - } - - return changes.sort( - (a, b) => - a.category.localeCompare(b.category) || - a.id.localeCompare(b.id) || - a.change.localeCompare(b.change) - ) -} - -function parseChangelog(content: string): ChangelogFile { - const parsed = JSON.parse(content) as Partial - if (parsed.version === undefined && Object.keys(parsed).length === 0) { - return { version: 1, entries: [] } - } - if (parsed.version !== 1 || !Array.isArray(parsed.entries)) { - throw new Error('data/changelogs.json must contain version 1 and an entries array') - } - return parsed as ChangelogFile -} - -function readChangelog(filePath: string): ChangelogFile { - return parseChangelog(fs.readFileSync(filePath, 'utf8')) -} - -function readBaseChangelog(rootDir: string, base: string): ChangelogFile { - try { - return parseChangelog(runGit(rootDir, ['show', `${base}:data/changelogs.json`])) - } catch { - return { version: 1, entries: [] } - } -} - -function changesMatch(left: ManifestChange, right: ManifestChange): boolean { - return ( - left.category === right.category && - left.id === right.id && - left.change === right.change && - JSON.stringify(left.fields) === JSON.stringify(right.fields) - ) -} - -function validateChangelog(changelog: ChangelogFile): void { - const entryIds = new Set() - for (const entry of changelog.entries) { - if (!entry.id || !/^\d{4}-\d{2}-\d{2}$/.test(entry.date) || !entry.summary) { - throw new Error(`Invalid changelog entry: ${entry.id || '(missing id)'}`) - } - if (entryIds.has(entry.id)) throw new Error(`Duplicate changelog entry id: ${entry.id}`) - entryIds.add(entry.id) - if (!Array.isArray(entry.changes) || entry.changes.length === 0) { - throw new Error(`Changelog entry has no manifest changes: ${entry.id}`) - } - } -} - -function getArgument(name: string): string | null { - const prefix = `--${name}=` - return process.argv.find(argument => argument.startsWith(prefix))?.slice(prefix.length) ?? null -} - -async function main(): Promise { - const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..') - const changelogPath = path.join(rootDir, 'data', 'changelogs.json') - const base = getArgument('base') ?? process.env.CHANGELOG_BASE ?? 'origin/main' - const date = getArgument('date') ?? new Date().toISOString().slice(0, 10) - const id = getArgument('id') ?? `${date}-manifest-update` - const changes = collectManifestChanges(rootDir, base) - const summary = - getArgument('summary') ?? - `${changes.length} manifest record${changes.length === 1 ? '' : 's'} changed` - const changelog = readChangelog(changelogPath) - - if (process.argv.includes('--write')) { - if (changes.length === 0) throw new Error(`No manifest changes found relative to ${base}`) - const entry: ChangelogEntry = { - id, - date, - summary, - changes, - } - changelog.entries = [...changelog.entries.filter(existing => existing.id !== id), entry].sort( - (a, b) => b.date.localeCompare(a.date) || b.id.localeCompare(a.id) - ) - fs.writeFileSync(changelogPath, `${JSON.stringify(changelog, null, 2)}\n`, 'utf8') - execFileSync('npx', ['biome', 'format', '--write', changelogPath], { - cwd: rootDir, - stdio: 'ignore', - }) - console.log(`Wrote ${changes.length} manifest changes to data/changelogs.json`) - } - - validateChangelog(changelog) - - if (process.argv.includes('--check') && changes.length > 0) { - try { - execFileSync('git', ['diff', '--quiet', base, '--', 'data/changelogs.json'], { cwd: rootDir }) - throw new Error('Manifest changes require an update to data/changelogs.json') - } catch (error) { - if (error instanceof Error && error.message.startsWith('Manifest changes require')) - throw error - } - - const baseChangelog = readBaseChangelog(rootDir, base) - const changedEntries = changelog.entries.filter(entry => { - const previous = baseChangelog.entries.find(candidate => candidate.id === entry.id) - return !previous || JSON.stringify(previous) !== JSON.stringify(entry) - }) - const missing = changes.filter( - change => - !changedEntries.some(entry => entry.changes.some(saved => changesMatch(change, saved))) - ) - if (missing.length > 0) { - throw new Error( - `Changelog is missing manifest changes: ${missing.map(change => `${change.category}/${change.id}`).join(', ')}` - ) - } - } - - console.log( - `Changelog valid: ${changelog.entries.length} entries; ${changes.length} manifest changes relative to ${base}` - ) -} - -const currentFile = fileURLToPath(import.meta.url) -if (process.argv[1] && path.resolve(process.argv[1]) === currentFile) { - main().catch(error => { - console.error(error) - process.exitCode = 1 - }) -} diff --git a/scripts/validate/data-health.ts b/scripts/validate/data-health.ts index e3624a5c..ac13e768 100644 --- a/scripts/validate/data-health.ts +++ b/scripts/validate/data-health.ts @@ -598,6 +598,21 @@ function getArgument(name: string): string | null { return process.argv.find(argument => argument.startsWith(prefix))?.slice(prefix.length) ?? null } +export function shouldFailDataHealth( + report: DataHealthReport, + failOn: string, + failOnCodes: Set = new Set() +): boolean { + if (!['error', 'warning', 'never'].includes(failOn)) { + throw new Error(`Invalid --fail-on value: ${failOn}`) + } + return ( + (failOn === 'error' && report.summary.errors > 0) || + (failOn === 'warning' && report.summary.errors + report.summary.warnings > 0) || + report.issues.some(issue => failOnCodes.has(issue.code)) + ) +} + async function main(): Promise { const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..') const snapshotPath = path.join(rootDir, 'data', 'data-health.json') @@ -631,13 +646,13 @@ async function main(): Promise { } const failOn = getArgument('fail-on') ?? 'never' - if (!['error', 'warning', 'never'].includes(failOn)) { - throw new Error(`Invalid --fail-on value: ${failOn}`) - } - if ( - (failOn === 'error' && report.summary.errors > 0) || - (failOn === 'warning' && report.summary.errors + report.summary.warnings > 0) - ) { + const failOnCodes = new Set( + (getArgument('fail-on-code') ?? '') + .split(',') + .map(code => code.trim()) + .filter(Boolean) + ) + if (shouldFailDataHealth(report, failOn, failOnCodes)) { process.exitCode = 1 } } diff --git a/src/app/[locale]/model-intelligence-index/page.tsx b/src/app/[locale]/model-intelligence-index/page.tsx index 599425ca..0ac936b6 100644 --- a/src/app/[locale]/model-intelligence-index/page.tsx +++ b/src/app/[locale]/model-intelligence-index/page.tsx @@ -5,8 +5,8 @@ import PageHeader from '@/components/PageHeader' import type { Locale } from '@/i18n/config' import { buildTitle, generateStaticPageMetadata } from '@/lib/metadata' import { + allModelIntelligencePoints, modelIntelligenceMeta, - modelIntelligencePoints, modelIntelligenceSeries, } from '@/lib/model-intelligence-index' import { ModelIntelligenceIndexPage } from './page.client' @@ -46,7 +46,7 @@ export default async function Page({ params }: Props) { diff --git a/src/lib/model-intelligence-index.ts b/src/lib/model-intelligence-index.ts index 506d622f..78c2bac5 100644 --- a/src/lib/model-intelligence-index.ts +++ b/src/lib/model-intelligence-index.ts @@ -2,24 +2,12 @@ import { modelsData } from '@/lib/generated/models' import { vendorsData } from '@/lib/generated/vendors' import { findVendorByName } from '@/lib/vendor-identity' import artificialAnalysisData from '../../data/artificial-analysis-index.json' -import modelIntelligenceData from '../../data/model-intelligence-index.json' const FALLBACK_COLOR: ModelIntelligenceThemeColor = { light: '#6b7280', dark: '#9ca3af', } -export const modelIntelligenceHiddenVendors = modelIntelligenceData.hiddenVendorIds.map( - vendorId => { - const vendor = vendorsData.find(candidate => candidate.id === vendorId) - - if (!vendor) { - throw new Error(`Model intelligence configuration has no matching vendor: ${vendorId}`) - } - - return vendor.name - } -) export const modelIntelligenceLegacyMissingModelIds = artificialAnalysisData.legacyMissingModelIds export interface ModelIntelligenceThemeColor { @@ -135,15 +123,9 @@ export const allModelIntelligencePoints: ModelIntelligencePoint[] = } }) -const hiddenVendorSet = new Set(modelIntelligenceHiddenVendors) - -export const modelIntelligencePoints = allModelIntelligencePoints.filter( - point => !hiddenVendorSet.has(point.vendor) -) - const groupedSeries = new Map() -for (const point of modelIntelligencePoints) { +for (const point of allModelIntelligencePoints) { const id = `${point.vendor}:${point.seriesId}` const existing = groupedSeries.get(id) diff --git a/src/lib/model-price-intelligence-index.ts b/src/lib/model-price-intelligence-index.ts index de623829..0e4a2fed 100644 --- a/src/lib/model-price-intelligence-index.ts +++ b/src/lib/model-price-intelligence-index.ts @@ -4,6 +4,7 @@ import { type ModelIntelligenceThemeColor, modelIntelligenceMeta, } from '@/lib/model-intelligence-index' +import type { ManifestModel } from '@/types/manifests' import modelPriceIntelligenceData from '../../data/model-price-intelligence-index.json' const INPUT_SHARE = modelPriceIntelligenceData.inputShare @@ -19,11 +20,6 @@ interface SelectedModel { linearLabelDx?: number linearLabelDy?: number linearLabelAnchor?: LabelAnchor - usdPriceOverride?: { - input: number - output: number - sourceUrl: string - } } const selectedModels = modelPriceIntelligenceData.models as SelectedModel[] @@ -46,11 +42,58 @@ export interface ModelPriceIntelligencePoint { linearLabelDx?: number linearLabelDy?: number linearLabelAnchor?: LabelAnchor - pricingSource: 'catalog' | 'artificial-analysis' + pricingSource: 'official' | 'reference' pricingSourceUrl: string | null } -const modelById = new Map(modelsData.map(model => [model.id, model])) +interface ComparableUsdPricing { + input: number + output: number + source: ModelPriceIntelligencePoint['pricingSource'] + sourceUrl: string | null +} + +function getComparableUsdPricing(model: ManifestModel): ComparableUsdPricing { + const primaryOffer = + model.tokenPricing.status === 'available' + ? model.tokenPricing.offers.find(offer => offer.id === model.tokenPricing.primaryOffer) + : undefined + const primaryRates = primaryOffer?.tiers[0]?.rates + + if ( + primaryOffer?.currency === 'USD' && + primaryRates?.input !== null && + primaryRates?.input !== undefined && + primaryRates.output !== null && + primaryRates.output !== undefined + ) { + return { + input: primaryRates.input, + output: primaryRates.output, + source: 'official', + sourceUrl: null, + } + } + + const referencePricing = model.referenceTokenPricing + + if ( + referencePricing?.currency === 'USD' && + referencePricing.rates.input !== null && + referencePricing.rates.output !== null + ) { + return { + input: referencePricing.rates.input, + output: referencePricing.rates.output, + source: 'reference', + sourceUrl: referencePricing.source.url, + } + } + + throw new Error(`Price-intelligence selection has no comparable USD pricing: ${model.id}`) +} + +const modelById = new Map((modelsData as ManifestModel[]).map(model => [model.id, model] as const)) const intelligenceByModelId = new Map( allModelIntelligencePoints.map(point => [point.modelId, point]) ) @@ -70,31 +113,7 @@ export const modelPriceIntelligencePoints: ModelPriceIntelligencePoint[] = selec ) } - if (!selection.usdPriceOverride && model.tokenPricing.status !== 'available') { - throw new Error( - `Price-intelligence selection has no available token pricing: ${selection.modelId}` - ) - } - - const primaryOffer = - model.tokenPricing.status === 'available' - ? model.tokenPricing.offers.find(offer => offer.id === model.tokenPricing.primaryOffer) - : undefined - const primaryTier = primaryOffer?.tiers[0] - const inputPrice = selection.usdPriceOverride?.input ?? primaryTier?.rates.input - const outputPrice = selection.usdPriceOverride?.output ?? primaryTier?.rates.output - - if ( - (!selection.usdPriceOverride && primaryOffer?.currency !== 'USD') || - inputPrice === null || - inputPrice === undefined || - outputPrice === null || - outputPrice === undefined - ) { - throw new Error( - `Price-intelligence selection requires comparable USD input and output pricing: ${selection.modelId}` - ) - } + const pricing = getComparableUsdPricing(model) return { name: model.name, @@ -102,13 +121,13 @@ export const modelPriceIntelligencePoints: ModelPriceIntelligencePoint[] = selec score: intelligence.score, estimated: intelligence.estimated, configuration: intelligence.configuration, - inputPrice, - outputPrice, - blendedPrice: inputPrice * INPUT_SHARE + outputPrice * OUTPUT_SHARE, + inputPrice: pricing.input, + outputPrice: pricing.output, + blendedPrice: pricing.input * INPUT_SHARE + pricing.output * OUTPUT_SHARE, currency: 'USD', color: intelligence.color, - pricingSource: selection.usdPriceOverride ? 'artificial-analysis' : 'catalog', - pricingSourceUrl: selection.usdPriceOverride?.sourceUrl ?? null, + pricingSource: pricing.source, + pricingSourceUrl: pricing.sourceUrl, ...selection, } } @@ -140,7 +159,7 @@ export const modelPriceIntelligenceMeta = { point ): point is ModelPriceIntelligencePoint & { pricingSourceUrl: string - } => point.pricingSource === 'artificial-analysis' && point.pricingSourceUrl !== null + } => point.pricingSource === 'reference' && point.pricingSourceUrl !== null ) .map(point => ({ modelId: point.modelId, diff --git a/src/types/manifests.ts b/src/types/manifests.ts index 25a39676..2eb78fca 100644 --- a/src/types/manifests.ts +++ b/src/types/manifests.ts @@ -65,6 +65,11 @@ export interface ManifestSource { url: string title?: string fields?: string[] + changeTracking?: { + method: 'normalized-content-sha256' + digest: string | null + observedAt: string | null + } } /** @@ -131,6 +136,29 @@ export interface ManifestRelatedProduct { productId: string } +/** + * Declarative latest-version source + * Based on: /manifests/$schemas/ref/product.schema.json#$defs/releaseTracking + */ +export type ManifestReleaseTracking = + | { + provider: 'npm' + identifier: string + channel?: string + } + | { + provider: 'homebrew-formula' | 'homebrew-cask' | 'crates-io' | 'pypi' + identifier: string + } + | { + provider: 'vscode-marketplace' + identifier: string + } + | { + provider: 'github-release' + identifier: string + } + /** * Platform installation information * Based on: /manifests/$schemas/ref/app.schema.json @@ -151,6 +179,7 @@ export interface ManifestBaseProduct extends ManifestVendorEntity { /** Stable identifier shared by every surface in the same product family */ familyId?: string latestVersion: string + releaseTracking?: ManifestReleaseTracking githubUrl: string | null license: string pricing: ManifestPricingTier[] @@ -274,6 +303,17 @@ export interface ManifestUnavailableTokenPricing { export type ManifestTokenPricing = ManifestAvailableTokenPricing | ManifestUnavailableTokenPricing +export interface ManifestReferenceTokenPricing { + currency: string + basis: 'first-party-api' | 'provider-median' + rates: ManifestTokenPricingRates + source: { + name: string + url: string + observedAt: string + } +} + /** * Benchmark scores * Based on: /manifests/$schemas/model.schema.json @@ -288,6 +328,18 @@ export interface ManifestBenchmarks { liveCodeBench: number | null } +/** + * Exact upstream benchmark leaderboard entry + * Based on: /manifests/$schemas/model.schema.json#$defs/benchmarkTracking + */ +export interface ManifestBenchmarkTracking { + provider: 'swe-bench' + benchmark: 'sweBench' + leaderboard: 'Verified' + resultId: string + modelLabel: string +} + /** * Lifecycle stage of a model */ @@ -303,6 +355,7 @@ export interface ManifestModel extends ManifestVendorEntity { contextWindow: number maxOutput: number | null tokenPricing: ManifestTokenPricing + referenceTokenPricing?: ManifestReferenceTokenPricing releaseDate: string | null lifecycle: ModelLifecycle knowledgeCutoff: string | null @@ -310,6 +363,7 @@ export interface ManifestModel extends ManifestVendorEntity { outputModalities: ModelOutputModality[] capabilities: ModelCapability[] benchmarks: ManifestBenchmarks + benchmarkTracking?: ManifestBenchmarkTracking[] platformUrls: ManifestPlatformUrls } diff --git a/tests/benchmark-sync.test.ts b/tests/benchmark-sync.test.ts new file mode 100644 index 00000000..555af3a5 --- /dev/null +++ b/tests/benchmark-sync.test.ts @@ -0,0 +1,131 @@ +import fs from 'node:fs/promises' +import os from 'node:os' +import path from 'node:path' + +import { afterEach, describe, expect, it } from 'vitest' + +import { type BenchmarkFetch, syncBenchmarks } from '../scripts/fetch/lib/benchmark-sync' + +const temporaryDirectories: string[] = [] + +function leaderboardFetch(results: unknown[]): BenchmarkFetch { + return async () => ({ + ok: true, + status: 200, + statusText: 'OK', + async json() { + return { + leaderboards: [{ name: 'Verified', results }], + } + }, + }) +} + +async function createModelRoot(model: Record): Promise { + const rootDir = await fs.mkdtemp(path.join(os.tmpdir(), 'benchmark-sync-')) + temporaryDirectories.push(rootDir) + await fs.mkdir(path.join(rootDir, 'manifests', 'models'), { recursive: true }) + await fs.writeFile( + path.join(rootDir, 'manifests', 'models', `${String(model.id)}.json`), + `${JSON.stringify(model, null, 2)}\n` + ) + return rootDir +} + +afterEach(async () => { + await Promise.all( + temporaryDirectories + .splice(0) + .map(directory => fs.rm(directory, { force: true, recursive: true })) + ) +}) + +describe('benchmark synchronization', () => { + it('updates an exact SWE-bench result without reformatting the manifest', async () => { + const rootDir = await createModelRoot({ + id: 'example', + benchmarks: { sweBench: 40 }, + benchmarkTracking: [ + { + provider: 'swe-bench', + benchmark: 'sweBench', + leaderboard: 'Verified', + resultId: 'exact-result', + modelLabel: 'Exact model and scaffold', + }, + ], + description: 'Preserve this value.', + }) + const filePath = path.join(rootDir, 'manifests', 'models', 'example.json') + const sourceBeforeSync = await fs.readFile(filePath, 'utf8') + + const result = await syncBenchmarks({ + rootDir, + write: true, + fetchImpl: leaderboardFetch([ + { + folder: 'exact-result', + name: 'Exact model and scaffold', + resolved: 42.5, + }, + ]), + }) + const sourceAfterSync = await fs.readFile(filePath, 'utf8') + + expect(result.changes).toHaveLength(1) + expect(sourceAfterSync).toBe(sourceBeforeSync.replace('"sweBench": 40', '"sweBench": 42.5')) + }) + + it('rejects a changed upstream label instead of fuzzy matching it', async () => { + const rootDir = await createModelRoot({ + id: 'example', + benchmarks: { sweBench: 40 }, + benchmarkTracking: [ + { + provider: 'swe-bench', + benchmark: 'sweBench', + leaderboard: 'Verified', + resultId: 'exact-result', + modelLabel: 'Expected model', + }, + ], + }) + + await expect( + syncBenchmarks({ + rootDir, + write: true, + fetchImpl: leaderboardFetch([ + { folder: 'exact-result', name: 'Different model', resolved: 42.5 }, + ]), + }) + ).rejects.toThrow('label changed') + }) + + it('does not write when an exact result is missing', async () => { + const rootDir = await createModelRoot({ + id: 'example', + benchmarks: { sweBench: 40 }, + benchmarkTracking: [ + { + provider: 'swe-bench', + benchmark: 'sweBench', + leaderboard: 'Verified', + resultId: 'exact-result', + modelLabel: 'Expected model', + }, + ], + }) + const filePath = path.join(rootDir, 'manifests', 'models', 'example.json') + const sourceBeforeSync = await fs.readFile(filePath, 'utf8') + + await expect( + syncBenchmarks({ + rootDir, + write: true, + fetchImpl: leaderboardFetch([]), + }) + ).rejects.toThrow('expected exactly one SWE-bench result') + expect(await fs.readFile(filePath, 'utf8')).toBe(sourceBeforeSync) + }) +}) diff --git a/tests/changelog.test.ts b/tests/changelog.test.ts deleted file mode 100644 index 3f61b7da..00000000 --- a/tests/changelog.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { describe, expect, it } from 'vitest' - -import { createManifestChange } from '../scripts/validate/changelog' - -describe('manifest changelog generation', () => { - it('captures added and removed records', () => { - expect( - createManifestChange('models', 'new-model', null, { id: 'new-model', name: 'New' }) - ).toEqual({ - category: 'models', - id: 'new-model', - change: 'added', - fields: ['id', 'name'], - }) - expect(createManifestChange('providers', 'old', { id: 'old' }, null)).toEqual({ - category: 'providers', - id: 'old', - change: 'removed', - fields: ['id'], - }) - }) - - it('reports only changed top-level fields', () => { - expect( - createManifestChange( - 'models', - 'example', - { $schema: 'old', id: 'example', name: 'Before', verified: false }, - { $schema: 'new', id: 'example', name: 'After', verified: true } - ) - ).toEqual({ - category: 'models', - id: 'example', - change: 'updated', - fields: ['name', 'verified'], - }) - }) - - it('ignores records without material changes', () => { - expect(createManifestChange('vendors', 'same', { id: 'same' }, { id: 'same' })).toBeNull() - }) -}) diff --git a/tests/data-health.test.ts b/tests/data-health.test.ts index 5ec65daf..52dc26f3 100644 --- a/tests/data-health.test.ts +++ b/tests/data-health.test.ts @@ -4,6 +4,7 @@ import { analyzeDataHealth, type ManifestRecord, renderDataHealthMarkdown, + shouldFailDataHealth, } from '../scripts/validate/data-health' function record( @@ -143,4 +144,22 @@ describe('data health reporting', () => { it('rejects a malformed report date', () => { expect(() => analyzeDataHealth([], '2026-02-30')).toThrow('Invalid --as-of date') }) + + it('can fail on selected issue codes without failing on every warning', () => { + const report = analyzeDataHealth( + [ + record('models', 'stale-model', { + verified: true, + sources: [{ url: 'https://example.com' }], + lastVerifiedAt: '2026-01-01', + verifiedBy: 'test', + confidence: 'high', + }), + ], + '2026-07-28' + ) + + expect(shouldFailDataHealth(report, 'error')).toBe(false) + expect(shouldFailDataHealth(report, 'error', new Set(['stale-verification']))).toBe(true) + }) }) diff --git a/tests/model-intelligence-index.test.ts b/tests/model-intelligence-index.test.ts index 19cde46e..d17d75ce 100644 --- a/tests/model-intelligence-index.test.ts +++ b/tests/model-intelligence-index.test.ts @@ -4,10 +4,8 @@ import { vendorsData } from '@/lib/generated/vendors' import { allModelIntelligencePoints, createTimelineTicks, - modelIntelligenceHiddenVendors, modelIntelligenceLegacyMissingModelIds, modelIntelligenceMeta, - modelIntelligencePoints, modelIntelligenceSeries, } from '@/lib/model-intelligence-index' import { findVendorByName } from '@/lib/vendor-identity' @@ -110,14 +108,6 @@ describe('model intelligence index', () => { expect(missingModelIds).toEqual(legacyMissingModelIds) }) - it('keeps hidden vendors in source data but excludes them from the page', () => { - for (const vendor of modelIntelligenceHiddenVendors) { - expect(allModelIntelligencePoints.some(point => point.vendor === vendor)).toBe(true) - expect(modelIntelligencePoints.some(point => point.vendor === vendor)).toBe(false) - expect(modelIntelligenceSeries.some(series => series.vendor === vendor)).toBe(false) - } - }) - it('keeps a single vendor color while separating model series', () => { const vendorColors = new Map>() const vendorStyles = new Map>() diff --git a/tests/model-price-intelligence-index.test.ts b/tests/model-price-intelligence-index.test.ts index a77492a7..0589167e 100644 --- a/tests/model-price-intelligence-index.test.ts +++ b/tests/model-price-intelligence-index.test.ts @@ -21,6 +21,7 @@ describe('model price-intelligence index', () => { 'gpt-5-6-terra', 'claude-haiku-4-5', 'claude-opus-5', + 'claude-fable-5', 'hy3', ]) ) @@ -41,7 +42,7 @@ describe('model price-intelligence index', () => { it('uses reviewed USD API prices when the catalog offer is not directly comparable', () => { const fallbackPoints = modelPriceIntelligencePoints.filter( - point => point.pricingSource === 'artificial-analysis' + point => point.pricingSource === 'reference' ) expect(fallbackPoints.map(point => point.modelId)).toEqual([ diff --git a/tests/model-source-sync.test.ts b/tests/model-source-sync.test.ts new file mode 100644 index 00000000..c2d17357 --- /dev/null +++ b/tests/model-source-sync.test.ts @@ -0,0 +1,126 @@ +import fs from 'node:fs/promises' +import os from 'node:os' +import path from 'node:path' + +import { afterEach, describe, expect, it } from 'vitest' + +import { + digestSourceContent, + normalizeSourceContent, + type SourceFetch, + syncModelSourceDigests, +} from '../scripts/fetch/lib/model-source-sync' + +const temporaryDirectories: string[] = [] + +function textFetch(content: string): SourceFetch { + return async () => ({ + ok: true, + status: 200, + statusText: 'OK', + async text() { + return content + }, + }) +} + +async function createModelRoot(model: Record): Promise { + const rootDir = await fs.mkdtemp(path.join(os.tmpdir(), 'model-source-sync-')) + temporaryDirectories.push(rootDir) + await fs.mkdir(path.join(rootDir, 'manifests', 'models'), { recursive: true }) + await fs.writeFile( + path.join(rootDir, 'manifests', 'models', `${String(model.id)}.json`), + `${JSON.stringify(model, null, 2)}\n` + ) + return rootDir +} + +afterEach(async () => { + await Promise.all( + temporaryDirectories + .splice(0) + .map(directory => fs.rm(directory, { force: true, recursive: true })) + ) +}) + +describe('model source monitoring', () => { + it('normalizes markup and ignores script content', () => { + const first = '
Price: $2 & active
' + const second = '
Price: $2 & active
' + + expect(normalizeSourceContent(first)).toBe('Price: $2 & active') + expect(digestSourceContent(first)).toBe(digestSourceContent(second)) + }) + + it('records only a source digest and observation date', async () => { + const rootDir = await createModelRoot({ + id: 'example', + lifecycle: 'latest', + tokenPricing: { status: 'available' }, + sources: [ + { + url: 'https://example.com/pricing', + fields: ['tokenPricing', 'lifecycle'], + changeTracking: { + method: 'normalized-content-sha256', + digest: null, + observedAt: null, + }, + }, + ], + }) + const filePath = path.join(rootDir, 'manifests', 'models', 'example.json') + + const result = await syncModelSourceDigests({ + rootDir, + write: true, + observedAt: '2026-07-28', + fetchImpl: textFetch(`
${'Official pricing and lifecycle. '.repeat(8)}
`), + }) + const updated = JSON.parse(await fs.readFile(filePath, 'utf8')) as Record + const sources = updated.sources as Array> + const tracking = sources[0]?.changeTracking as Record + + expect(result.changes).toHaveLength(1) + expect(updated.lifecycle).toBe('latest') + expect(updated.tokenPricing).toEqual({ status: 'available' }) + expect(tracking.digest).toMatch(/^sha256:[a-f0-9]{64}$/) + expect(tracking.observedAt).toBe('2026-07-28') + }) + + it('does not write any digest when a monitored source fails', async () => { + const rootDir = await createModelRoot({ + id: 'example', + sources: [ + { + url: 'https://example.com/pricing', + changeTracking: { + method: 'normalized-content-sha256', + digest: null, + observedAt: null, + }, + }, + ], + }) + const filePath = path.join(rootDir, 'manifests', 'models', 'example.json') + const before = await fs.readFile(filePath, 'utf8') + const failingFetch: SourceFetch = async () => ({ + ok: false, + status: 503, + statusText: 'Unavailable', + async text() { + return '' + }, + }) + + await expect( + syncModelSourceDigests({ + rootDir, + write: true, + observedAt: '2026-07-28', + fetchImpl: failingFetch, + }) + ).rejects.toThrow('failed without writing changes') + expect(await fs.readFile(filePath, 'utf8')).toBe(before) + }) +}) diff --git a/tests/product-version-sync.test.ts b/tests/product-version-sync.test.ts new file mode 100644 index 00000000..613b3f2d --- /dev/null +++ b/tests/product-version-sync.test.ts @@ -0,0 +1,223 @@ +import fs from 'node:fs/promises' +import os from 'node:os' +import path from 'node:path' + +import { afterEach, describe, expect, it } from 'vitest' + +import { + fetchTrackedVersion, + syncProductVersions, + type VersionFetch, +} from '../scripts/fetch/lib/product-version-sync' + +const temporaryDirectories: string[] = [] + +function jsonFetch(payload: unknown): VersionFetch { + return async () => ({ + ok: true, + status: 200, + statusText: 'OK', + async json() { + return payload + }, + }) +} + +async function createManifestRoot(manifests: Record[]): Promise { + const rootDir = await fs.mkdtemp(path.join(os.tmpdir(), 'product-version-sync-')) + temporaryDirectories.push(rootDir) + for (const category of ['ides', 'clis', 'desktops', 'extensions']) { + await fs.mkdir(path.join(rootDir, 'manifests', category), { recursive: true }) + } + for (const manifest of manifests) { + await fs.writeFile( + path.join(rootDir, 'manifests', 'clis', `${String(manifest.id)}.json`), + `${JSON.stringify(manifest, null, 2)}\n` + ) + } + return rootDir +} + +afterEach(async () => { + await Promise.all( + temporaryDirectories + .splice(0) + .map(directory => fs.rm(directory, { force: true, recursive: true })) + ) +}) + +describe('product version sources', () => { + it('reads npm dist-tags', async () => { + const observation = await fetchTrackedVersion( + { provider: 'npm', identifier: '@example/tool', channel: 'latest' }, + jsonFetch({ 'dist-tags': { latest: '2.3.4' } }) + ) + + expect(observation).toEqual({ + version: '2.3.4', + sourceUrl: 'https://www.npmjs.com/package/@example/tool', + }) + }) + + it('reads Homebrew formula and cask versions', async () => { + const formula = await fetchTrackedVersion( + { provider: 'homebrew-formula', identifier: 'example' }, + jsonFetch({ versions: { stable: '3.2.1' } }) + ) + const cask = await fetchTrackedVersion( + { provider: 'homebrew-cask', identifier: 'example-app' }, + jsonFetch({ version: '4.5.6' }) + ) + + expect(formula.version).toBe('3.2.1') + expect(cask.version).toBe('4.5.6') + }) + + it('reads crates.io and GitHub stable release versions', async () => { + const crate = await fetchTrackedVersion( + { provider: 'crates-io', identifier: 'example' }, + jsonFetch({ crate: { max_stable_version: '1.9.0', max_version: '2.0.0-beta.1' } }) + ) + const release = await fetchTrackedVersion( + { provider: 'github-release', identifier: 'example/tool' }, + jsonFetch({ + tag_name: 'v5.0.0', + html_url: 'https://github.com/example/tool/releases/tag/v5.0.0', + }) + ) + + expect(crate.version).toBe('1.9.0') + expect(release).toEqual({ + version: 'v5.0.0', + sourceUrl: 'https://github.com/example/tool/releases/tag/v5.0.0', + }) + }) + + it('reads PyPI and Visual Studio Marketplace versions', async () => { + const pypi = await fetchTrackedVersion( + { provider: 'pypi', identifier: 'example-tool' }, + jsonFetch({ info: { version: '1.4.0' } }) + ) + let marketplaceRequest: + | { + input: string + method?: string + body?: string + } + | undefined + const marketplaceFetch: VersionFetch = async (input, init) => { + marketplaceRequest = { + input: String(input), + method: init?.method, + body: init?.body, + } + return jsonFetch({ + results: [ + { + extensions: [{ versions: [{ version: '2.7.1' }] }], + }, + ], + })(input, init) + } + const marketplace = await fetchTrackedVersion( + { provider: 'vscode-marketplace', identifier: 'publisher.extension' }, + marketplaceFetch + ) + + expect(pypi).toEqual({ + version: '1.4.0', + sourceUrl: 'https://pypi.org/project/example-tool/', + }) + expect(marketplace.version).toBe('2.7.1') + expect(marketplaceRequest?.method).toBe('POST') + expect(JSON.parse(marketplaceRequest?.body ?? '{}')).toMatchObject({ + filters: [{ criteria: [{ filterType: 7, value: 'publisher.extension' }] }], + }) + }) +}) + +describe('product version synchronization', () => { + it('writes only latestVersion after every configured source succeeds', async () => { + const rootDir = await createManifestRoot([ + { + id: 'example', + latestVersion: '1.0.0', + releaseTracking: { provider: 'npm', identifier: 'example' }, + lastVerifiedAt: '2026-01-01', + description: 'Preserve this value.', + }, + ]) + const filePath = path.join(rootDir, 'manifests', 'clis', 'example.json') + const sourceBeforeSync = await fs.readFile(filePath, 'utf8') + + const result = await syncProductVersions({ + rootDir, + write: true, + fetchImpl: jsonFetch({ 'dist-tags': { latest: '1.1.0' } }), + }) + const sourceAfterSync = await fs.readFile(filePath, 'utf8') + const manifest = JSON.parse(sourceAfterSync) as Record + + expect(result.changes).toHaveLength(1) + expect(manifest.latestVersion).toBe('1.1.0') + expect(manifest.lastVerifiedAt).toBe('2026-01-01') + expect(manifest.description).toBe('Preserve this value.') + expect(sourceAfterSync).toBe( + sourceBeforeSync.replace('"latestVersion": "1.0.0"', '"latestVersion": "1.1.0"') + ) + }) + + it('does not write partial changes when a source fails', async () => { + const rootDir = await createManifestRoot([ + { + id: 'first', + latestVersion: '1.0.0', + releaseTracking: { provider: 'npm', identifier: 'first' }, + }, + { + id: 'second', + latestVersion: '1.0.0', + releaseTracking: { provider: 'npm', identifier: 'second' }, + }, + ]) + const fetchImpl: VersionFetch = async input => { + if (String(input).endsWith('second')) { + return { + ok: false, + status: 503, + statusText: 'Unavailable', + async json() { + return {} + }, + } + } + return jsonFetch({ 'dist-tags': { latest: '1.1.0' } })(input) + } + + await expect(syncProductVersions({ rootDir, write: true, fetchImpl })).rejects.toThrow( + 'failed without writing changes' + ) + const first = JSON.parse( + await fs.readFile(path.join(rootDir, 'manifests', 'clis', 'first.json'), 'utf8') + ) as Record + expect(first.latestVersion).toBe('1.0.0') + }) + + it('rejects npm version downgrades', async () => { + const rootDir = await createManifestRoot([ + { + id: 'example', + latestVersion: '2.0.0', + releaseTracking: { provider: 'npm', identifier: 'example' }, + }, + ]) + + await expect( + syncProductVersions({ + rootDir, + write: true, + fetchImpl: jsonFetch({ 'dist-tags': { latest: '1.9.0' } }), + }) + ).rejects.toThrow('older than recorded version') + }) +}) diff --git a/tests/validate/manifests.schema.test.ts b/tests/validate/manifests.schema.test.ts index c36aa14b..20f211c4 100644 --- a/tests/validate/manifests.schema.test.ts +++ b/tests/validate/manifests.schema.test.ts @@ -132,6 +132,7 @@ function validateAllManifests(rootDir: string): string[] { const manifestSchemaMap: Record = { clis: 'cli.schema.json', + desktops: 'desktop.schema.json', ides: 'ide.schema.json', extensions: 'extension.schema.json', providers: 'provider.schema.json', diff --git a/tests/validate/ranking-data.schema.test.ts b/tests/validate/ranking-data.schema.test.ts index 1f7ffe9c..32b0d573 100644 --- a/tests/validate/ranking-data.schema.test.ts +++ b/tests/validate/ranking-data.schema.test.ts @@ -5,11 +5,9 @@ import addFormats from 'ajv-formats' import { describe, expect, it } from 'vitest' describe('validate: ranking data schemas', () => { - it.each([ - 'model-intelligence-index', - 'model-price-intelligence-index', - ])('validates the %s configuration', dataName => { + it('validates the model-price-intelligence-index configuration', () => { const rootDir = path.resolve(__dirname, '../..') + const dataName = 'model-price-intelligence-index' const schema = JSON.parse( fs.readFileSync(path.join(rootDir, `data/$schemas/${dataName}.schema.json`), 'utf8') ) diff --git a/tests/validate/typesAlignment.test.ts b/tests/validate/typesAlignment.test.ts index 958370dc..6d30beca 100644 --- a/tests/validate/typesAlignment.test.ts +++ b/tests/validate/typesAlignment.test.ts @@ -144,6 +144,11 @@ function validateTypesAlignment(rootDir: string): string[] { iface: 'ManifestCLI', name: 'CLI', }, + { + schema: path.join(schemasDir, 'desktop.schema.json'), + iface: 'ManifestDesktop', + name: 'Desktop', + }, ] as const for (const check of checks) {