From bfa6d76d048c949eecfcb0aa2ca1484dc52bead9 Mon Sep 17 00:00:00 2001 From: nb213 Date: Sat, 10 Oct 2026 10:01:49 +0800 Subject: [PATCH 1/9] Merge pull request #2421 from binyangzhu000-sudo/feat/atlas-cloud-provider feat: add Atlas Cloud as an LLM provider --- src/main/provider/defaults.ts | 14 ++++++++++++++ src/main/provider/providerRegistry.ts | 8 ++++++++ src/renderer/src/assets/llm-icons/atlascloud.svg | 1 + .../src/components/icons/modelIconRegistry.ts | 3 +++ 4 files changed, 26 insertions(+) create mode 100644 src/renderer/src/assets/llm-icons/atlascloud.svg diff --git a/src/main/provider/defaults.ts b/src/main/provider/defaults.ts index f13773993..92589dc0c 100644 --- a/src/main/provider/defaults.ts +++ b/src/main/provider/defaults.ts @@ -566,6 +566,20 @@ const PROVIDER_DEFAULTS: LLM_PROVIDER_BASE[] = [ models: 'https://openrouter.ai/docs/models' } }, + { + id: 'atlascloud', + name: 'Atlas Cloud', + apiType: 'openai-completions', + apiKey: '', + baseUrl: 'https://api.atlascloud.ai/v1', + enable: false, + websites: { + official: 'https://atlascloud.ai/', + apiKey: 'https://console.atlascloud.ai/api-keys', + docs: 'https://docs.atlascloud.ai/', + models: 'https://console.atlascloud.ai/models' + } + }, { id: 'requesty', name: 'Requesty', diff --git a/src/main/provider/providerRegistry.ts b/src/main/provider/providerRegistry.ts index 2ad76a69d..053f35a90 100644 --- a/src/main/provider/providerRegistry.ts +++ b/src/main/provider/providerRegistry.ts @@ -168,6 +168,14 @@ const PROVIDER_ID_REGISTRY = new Map([ embeddingStrategy: 'none' }) ], + [ + 'atlascloud', + createDefinition({ + ...OPENAI_BASE, + credentialStrategy: 'api-key', + embeddingStrategy: 'none' + }) + ], [ 'amd-developer', createDefinition({ diff --git a/src/renderer/src/assets/llm-icons/atlascloud.svg b/src/renderer/src/assets/llm-icons/atlascloud.svg new file mode 100644 index 000000000..d9e7da2f8 --- /dev/null +++ b/src/renderer/src/assets/llm-icons/atlascloud.svg @@ -0,0 +1 @@ +Atlas Cloud diff --git a/src/renderer/src/components/icons/modelIconRegistry.ts b/src/renderer/src/components/icons/modelIconRegistry.ts index 92ab979bc..747ee8366 100644 --- a/src/renderer/src/components/icons/modelIconRegistry.ts +++ b/src/renderer/src/components/icons/modelIconRegistry.ts @@ -49,6 +49,7 @@ import daoxeColorIcon from '@/assets/llm-icons/daoxe.png?url' import kimiColorIcon from '@/assets/llm-icons/kimi-color.svg?url' import moonshotColorIcon from '@/assets/llm-icons/moonshot.svg?url' import openrouterColorIcon from '@/assets/llm-icons/openrouter.svg?url' +import atlascloudIcon from '@/assets/llm-icons/atlascloud.svg?url' import requestyColorIcon from '@/assets/llm-icons/requesty.png?url' import opperColorIcon from '@/assets/llm-icons/opper.svg?url' import demonrouteColorIcon from '@/assets/llm-icons/demonroute.svg?url' @@ -188,6 +189,7 @@ export const modelIcons = { qwen: qwenColorIcon, moonshot: moonshotColorIcon, openrouter: openrouterColorIcon, + atlascloud: atlascloudIcon, requesty: requestyColorIcon, opper: opperColorIcon, demonroute: demonrouteColorIcon, @@ -269,6 +271,7 @@ const monoIconUrls = new Set([ rwkvColorIcon, moonshotColorIcon, openrouterColorIcon, + atlascloudIcon, opperColorIcon, demonrouteColorIcon, githubColorIcon, From bdd924801c55c69579d387006037b2d42d2ec1d8 Mon Sep 17 00:00:00 2001 From: zerob13 Date: Sat, 10 Oct 2026 16:32:56 +0800 Subject: [PATCH 2/9] docs(readme): reorder sections, fix stale claims - Move Quick Start above Main Features so install steps are not buried - Remove the Ask DeepWiki badge from all three READMEs - Keep sponsor position and order unchanged - Fix stale Skills list, JP Node runtime claim, Bocha naming, and dead links --- README.jp.md | 99 ++++++++++++++++++++++++++------------------------ README.md | 101 +++++++++++++++++++++++++-------------------------- README.zh.md | 101 ++++++++++++++++++++++++++------------------------- 3 files changed, 152 insertions(+), 149 deletions(-) diff --git a/README.jp.md b/README.jp.md index 2c9342926..4d9d14700 100644 --- a/README.jp.md +++ b/README.jp.md @@ -13,7 +13,6 @@ Issues Badge License Badge Downloads - Ask DeepWiki

@@ -65,6 +64,10 @@ - [📑 目次](#-目次) - [🚀 プロジェクト紹介](#-プロジェクト紹介) - [💡 なぜDeepChatを選ぶのか](#-なぜdeepchatを選ぶのか) +- [📦 クイックスタート](#-クイックスタート) + - [ダウンロードとインストール](#ダウンロードとインストール) + - [モデルの設定](#モデルの設定) + - [会話を開始](#会話を開始) - [🔥 主な機能](#-主な機能) - [📼 Tape と Trace](#-tape-と-trace) - [🧠 Skills サポート](#-skills-サポート) @@ -73,10 +76,6 @@ - [🤖 サポートされているモデルプロバイダー](#-サポートされているモデルプロバイダー) - [OpenAI/Gemini/Anthropic API形式の任意のモデルプロバイダーと互換性あり](#openaigeminianthropic-api形式の任意のモデルプロバイダーと互換性あり) - [🔍 ユースケース](#-ユースケース) -- [📦 クイックスタート](#-クイックスタート) - - [ダウンロードとインストール](#ダウンロードとインストール) - - [モデルの設定](#モデルの設定) - - [会話を開始](#会話を開始) - [💻 開発ガイド](#-開発ガイド) - [依存関係のインストール](#依存関係のインストール) - [開発を開始](#開発を開始) @@ -119,6 +118,45 @@ DeepChatのセッションとAgentプロセスはTape.systemsの哲学に基づ - **プライバシー重視**: ローカルデータストレージとネットワークプロキシのサポートにより、情報漏洩のリスクを軽減します - **ビジネスフレンドリー**: Apache License 2.0の下でオープンソース化され、商用・個人利用の両方に適しています +## 📦 クイックスタート + +### ダウンロードとインストール + +以下のいずれかの方法で DeepChat をインストールできます: + +**方法1:GitHub Releases** + +[GitHub Releases](https://github.com/ThinkInAIXYZ/deepchat/releases)ページからお使いのシステム用の最新バージョンをダウンロードしてください: + +- Windows: `.exe`インストールファイル +- macOS: `.dmg`インストールファイル +- Linux: `.AppImage`または`.deb`インストールファイル + +**方法2:公式ウェブサイト** + +[公式ウェブサイト](https://deepchatai.cn/#/download)からダウンロードできます。 + +**方法3:Homebrew(macOS のみ)** + +macOS ユーザーは Homebrew を使用してインストールできます: + +```bash +brew install --cask deepchat +``` + +### モデルの設定 + +1. DeepChatアプリケーションを起動 +2. 設定アイコンをクリック +3. "モデルプロバイダー"タブを選択 +4. APIキーを追加するか、ローカルOllamaを設定 + +### 会話を開始 + +1. "+"ボタンをクリックして新しい会話を作成 +2. 使用したいモデルを選択 +3. AIアシスタントとの対話を開始 + ## 🔥 主な機能 - 🤖 **ローカルファーストAgentデスクトップクライアント** @@ -149,13 +187,13 @@ DeepChatのセッションとAgentプロセスはTape.systemsの哲学に基づ - 画像、Mermaidダイアグラム、その他のマルチモーダルコンテンツのレンダリングをサポート。GPT-4o、Gemini、Grokのテキストから画像生成機能をサポート - 検索結果などの外部情報ソースをコンテンツ内でハイライト表示 - 🔍 **強力な検索強化機能** - - 博查搜索、Brave Searchなどの主要な検索APIを組み込み、モデルが検索のタイミングを賢く判断 + - Bocha Search、Brave Searchなどの主要な検索APIを統合し、モデルが検索のタイミングを賢く判断 - ユーザーのウェブブラウジングをシミュレートすることで、Google、Bing、Baidu、Sogou公式アカウント検索などの主要検索エンジンをサポート - あらゆる検索エンジンの読み取りをサポート。検索アシスタントモデルを設定するだけで、内部ネットワーク、APIなしのエンジン、垂直ドメイン検索エンジンなど、様々な情報ソースをモデルに接続可能 - 🔧 **優れたMCP(Model Context Protocol)サポート** - Resources / Prompts / Tools の三大コア機能をサポート - StreamableHTTP、SSE、StdioなどのTransportに対応 - - 組み込みNode.jsランタイムにより、npx/node系サービスがすぐに利用可能 + - npx/node系サービス向けの公式Node.jsツールチェーンを、必要なときに設定からインストール可能 - コード実行、Web情報取得、ファイル操作などのinMemoryサービスに対応 - ツール呼び出し、パラメータ、戻り値を見やすくデバッグ可能 - DeepLinkによるMCPサービスのワンクリックインストールに対応 @@ -180,7 +218,7 @@ DeepChat Skills は標準の Agent Skills 仕様と互換性のある設計で Skillsはフォルダー、ZIPファイル、URLからインストールできます。Claude Code、Codex、Cursor、Windsurf、GitHub Copilot、Kiro、Antigravity、OpenCode、Goose、Kilo Code などの互換ツールとのインポート/エクスポートにも対応します。 -組み込みSkillsは、生成アート、コードレビュー、DeepChat設定、ドキュメント共同作成、DOCX、フロントエンド設計、git commitメッセージ、インフォグラフィック構文、MCP構築、PDF、PPTX、Skill作成、Web Artifacts、XLSXワークフローをカバーします。 +組み込みSkillsは、アルゴリズムアート、コードレビュー、DeepChat CLI、DeepChat設定、ドキュメント共同作成、DOCX、フロントエンド設計、git commitメッセージ、インフォグラフィック構文、MCP構築、メモリ管理、PDF、PPTX、Skill作成、XLSXワークフローをカバーします。 クイックスタート: @@ -424,6 +462,8 @@ DeepChatはメッセージアプリからリモート操作できるため、デ ### OpenAI/Gemini/Anthropic API形式の任意のモデルプロバイダーと互換性あり +上記の組み込みプロバイダーに加えて、OpenAI、Gemini、Anthropic API形式と互換性のある任意のサービスをカスタムプロバイダーとして追加できます。 + ## 🔍 ユースケース DeepChatは様々なAIアプリケーションシナリオに適しています: @@ -434,45 +474,6 @@ DeepChatは様々なAIアプリケーションシナリオに適しています - **コンテンツ作成**: コピーライティング、クリエイティブなインスピレーション、コンテンツの最適化 - **データ分析**: データの解釈、チャート生成、レポート作成 -## 📦 クイックスタート - -### ダウンロードとインストール - -以下のいずれかの方法で DeepChat をインストールできます: - -**方法1:GitHub Releases** - -[GitHub Releases](https://github.com/ThinkInAIXYZ/deepchat/releases)ページからお使いのシステム用の最新バージョンをダウンロードしてください: - -- Windows: `.exe`インストールファイル -- macOS: `.dmg`インストールファイル -- Linux: `.AppImage`または`.deb`インストールファイル - -**方法2:公式ウェブサイト** - -[公式ウェブサイト](https://deepchatai.cn/#/download)からダウンロードできます。 - -**方法3:Homebrew(macOS のみ)** - -macOS ユーザーは Homebrew を使用してインストールできます: - -```bash -brew install --cask deepchat -``` - -### モデルの設定 - -1. DeepChatアプリケーションを起動 -2. 設定アイコンをクリック -3. "モデルプロバイダー"タブを選択 -4. APIキーを追加するか、ローカルOllamaを設定 - -### 会話を開始 - -1. "+"ボタンをクリックして新しい会話を作成 -2. 使用したいモデルを選択 -3. AIアシスタントとの対話を開始 - ## 💻 開発ガイド [貢献ガイドライン](./CONTRIBUTING.md)をお読みください。 @@ -518,6 +519,8 @@ $ pnpm run build:linux:x64 $ pnpm run build:linux:arm64 ``` +開発環境、プロジェクト構成、アーキテクチャの詳細は[開発者ガイド](./docs/guides/getting-started.md)と[ドキュメント索引](./docs/README.md)を参照してください。 + ## 👥 コミュニティと貢献 DeepChatはアクティブなオープンソースコミュニティプロジェクトであり、様々な形での貢献を歓迎します: @@ -526,7 +529,7 @@ DeepChatはアクティブなオープンソースコミュニティプロジェ - 💡 [機能の提案を提出する](https://github.com/ThinkInAIXYZ/deepchat/issues) - 🔧 [コードの改善を提出する](https://github.com/ThinkInAIXYZ/deepchat/pulls) - 📚 [ドキュメントを改善する](https://github.com/ThinkInAIXYZ/deepchat/wiki) -- 🌍 [翻訳を手伝う](https://github.com/ThinkInAIXYZ/deepchat/tree/main/locales) +- 🌍 [翻訳を手伝う](https://github.com/ThinkInAIXYZ/deepchat/tree/main/src/renderer/src/i18n) プロジェクトへの参加方法について詳しく知るには、[貢献ガイドライン](./CONTRIBUTING.md)をご確認ください。 diff --git a/README.md b/README.md index b914017f6..04dcde419 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,6 @@ Issues Badge License Badge Downloads - Ask DeepWiki

@@ -64,6 +63,10 @@ - [📑 Table of Contents](#-table-of-contents) - [🚀 Project Introduction](#-project-introduction) - [💡 Why Choose DeepChat](#-why-choose-deepchat) +- [📦 Quick Start](#-quick-start) + - [Download and Install](#download-and-install) + - [Configure Models](#configure-models) + - [Start Conversations](#start-conversations) - [🔥 Main Features](#-main-features) - [📼 Tape & Trace](#-tape--trace) - [🧠 Skills Support](#-skills-support) @@ -72,10 +75,6 @@ - [🤖 Supported Model Providers](#-supported-model-providers) - [Compatible with any model provider in OpenAI/Gemini/Anthropic API format](#compatible-with-any-model-provider-in-openaigeminianthropic-api-format) - [🔍 Use Cases](#-use-cases) -- [📦 Quick Start](#-quick-start) - - [Download and Install](#download-and-install) - - [Configure Models](#configure-models) - - [Start Conversations](#start-conversations) - [💻 Development Guide](#-development-guide) - [Install Dependencies](#install-dependencies) - [Start Development](#start-development) @@ -118,6 +117,45 @@ Compared to other AI tools, DeepChat offers the following unique advantages: - **Privacy-Focused**: Local data storage and network proxy support reduce the risk of information leakage - **Business-Friendly**: Embraces open source under the Apache License 2.0, suitable for both commercial and personal use +## 📦 Quick Start + +### Download and Install + +You can install DeepChat using one of the following methods: + +**Option 1: GitHub Releases** + +Download the latest version for your system from the [GitHub Releases](https://github.com/ThinkInAIXYZ/deepchat/releases) page: + +- Windows: `.exe` installation file +- macOS: `.dmg` installation file +- Linux: `.AppImage` or `.deb` installation file + +**Option 2: Official Website** + +Download from the [official website](https://deepchatai.cn/#/download). + +**Option 3: Homebrew (macOS only)** + +For macOS users, you can install DeepChat using Homebrew: + +```bash +brew install --cask deepchat +``` + +### Configure Models + +1. Launch the DeepChat application +2. Click the settings icon +3. Select the "Model Providers" tab +4. Add your API keys or configure local Ollama + +### Start Conversations + +1. Click the "+" button to create a new conversation +2. Select the model you want to use +3. Start communicating with your AI assistant + ## 🔥 Main Features - 🤖 **Local-First Agent Desktop Client** @@ -148,7 +186,7 @@ Compared to other AI tools, DeepChat offers the following unique advantages: - Supports rendering images, Mermaid diagrams, and other multi-modal content; supports GPT-4o, Gemini, Grok text-to-image capabilities - Supports highlighting external information sources like search results within the content - 🔍 **Robust Search Extension Capabilities** - - Built-in integration with leading search APIs like BoSearch and Brave Search, allowing the model to intelligently decide when to search + - Built-in integration with leading search APIs like Bocha Search and Brave Search, allowing the model to intelligently decide when to search - Supports mainstream search engines like Google, Bing, Baidu, and Sogou Official Accounts search by simulating user web browsing, enabling the LLM to read search engines like a human - Supports reading any search engine; simply configure a search assistant model to connect various search sources, whether internal networks, API-less engines, or vertical domain search engines, as information sources for the model - 🔧 **Strong MCP (Model Context Protocol) Support** @@ -169,8 +207,6 @@ Compared to other AI tools, DeepChat offers the following unique advantages: - Clear code structure, both model providers and MCP services are highly decoupled, can be freely customized with minimal cost - Reasonable architecture, data interaction and UI behavior separation, fully utilizing Electron's capabilities, rejecting simple web wrappers, excellent performance -For more details on how to use these features, see the [documentation index](./docs/README.md). - ## 📼 Tape & Trace DeepChat's session Tape follows the Tape.systems philosophy and keeps agent work recoverable and inspectable. Trace previews expose request sequences, provider/model metadata, Tape view manifests, included or excluded entries, and token budgets, making long-running agent sessions easier to debug and resume. @@ -181,7 +217,7 @@ DeepChat Skills are designed to be compatible with the standard Agent Skills spe You can install Skills from folders, ZIP files, or URLs, and import/export them with Claude Code, Codex, Cursor, Windsurf, GitHub Copilot, Kiro, Antigravity, OpenCode, Goose, Kilo Code, and other compatible tools. -Built-in Skills cover generative art, code review, DeepChat settings, document collaboration, DOCX, frontend design, git commit messages, infographic syntax, MCP building, PDF, PPTX, Skill creation, Web Artifacts, and XLSX workflows. +Built-in Skills cover algorithmic art, code review, DeepChat CLI, DeepChat settings, document collaboration, DOCX, frontend design, git commit messages, infographic syntax, MCP building, memory management, PDF, PPTX, Skill creation, and XLSX workflows. Quick start: @@ -425,6 +461,8 @@ Common commands include `/start`, `/help`, `/pair`, `/new`, `/sessions`, `/use`, ### Compatible with any model provider in OpenAI/Gemini/Anthropic API format +Any service that speaks the OpenAI, Gemini, or Anthropic API format can be added as a custom provider next to the built-in ones. + ## 🔍 Use Cases DeepChat is suitable for various AI application scenarios: @@ -435,47 +473,6 @@ DeepChat is suitable for various AI application scenarios: - **Content Creation**: Copywriting, creative inspiration, content optimization - **Data Analysis**: Data interpretation, chart generation, report writing -## 📦 Quick Start - -### Download and Install - -You can install DeepChat using one of the following methods: - -**Option 1: GitHub Releases** - -Download the latest version for your system from the [GitHub Releases](https://github.com/ThinkInAIXYZ/deepchat/releases) page: - -- Windows: `.exe` installation file -- macOS: `.dmg` installation file -- Linux: `.AppImage` or `.deb` installation file - -**Option 2: Official Website** - -Download from the [official website](https://deepchatai.cn/#/download). - -**Option 3: Homebrew (macOS only)** - -For macOS users, you can install DeepChat using Homebrew: - -```bash -brew install --cask deepchat -``` - -### Configure Models - -1. Launch the DeepChat application -2. Click the settings icon -3. Select the "Model Providers" tab -4. Add your API keys or configure local Ollama - -### Start Conversations - -1. Click the "+" button to create a new conversation -2. Select the model you want to use -3. Start communicating with your AI assistant - -For a comprehensive guide on getting started and using all features, please refer to the [documentation index](./docs/README.md). - ## 💻 Development Guide Please read the [Contribution Guidelines](./CONTRIBUTING.md) @@ -521,7 +518,7 @@ $ pnpm run build:linux:x64 $ pnpm run build:linux:arm64 ``` -For a more detailed guide on development, project structure, and architecture, please see the [Developer Guide](./docs/guides/getting-started.md). +For a more detailed guide on development, project structure, and architecture, please see the [Developer Guide](./docs/guides/getting-started.md) and the maintained [documentation index](./docs/README.md). ## 👥 Community & Contribution @@ -531,7 +528,7 @@ DeepChat is an active open-source community project, and we welcome various form - 💡 [Submit feature suggestions](https://github.com/ThinkInAIXYZ/deepchat/issues) - 🔧 [Submit code improvements](https://github.com/ThinkInAIXYZ/deepchat/pulls) - 📚 [Improve documentation](https://github.com/ThinkInAIXYZ/deepchat/wiki) -- 🌍 [Help with translation](https://github.com/ThinkInAIXYZ/deepchat/tree/main/locales) +- 🌍 [Help with translation](https://github.com/ThinkInAIXYZ/deepchat/tree/main/src/renderer/src/i18n) Check the [Contribution Guidelines](./CONTRIBUTING.md) to learn more about ways to participate in the project. diff --git a/README.zh.md b/README.zh.md index 76cfcc9f5..fa2325d72 100644 --- a/README.zh.md +++ b/README.zh.md @@ -13,7 +13,6 @@ Issues Badge License Badge Downloads - Ask DeepWiki

@@ -62,6 +61,10 @@ - [📑 目录](#-目录) - [🚀 项目简介](#-项目简介) - [💡 为什么选择DeepChat](#-为什么选择deepchat) +- [📦 快速开始](#-快速开始) + - [下载安装](#下载安装) + - [配置模型](#配置模型) + - [开始对话](#开始对话) - [🔥 主要功能](#-主要功能) - [📼 Tape 与 Trace](#-tape-与-trace) - [🧠 Skills 支持](#-skills-支持) @@ -70,10 +73,6 @@ - [🤖 支持的模型提供商](#-支持的模型提供商) - [兼容任何OpenAI/Gemini/Anthropic API格式的模型提供商](#兼容任何openaigeminianthropic-api格式的模型提供商) - [🔍 使用场景](#-使用场景) -- [📦 快速开始](#-快速开始) - - [下载安装](#下载安装) - - [配置模型](#配置模型) - - [开始对话](#开始对话) - [💻 开发指南](#-开发指南) - [安装依赖](#安装依赖) - [开始开发](#开始开发) @@ -116,6 +115,45 @@ DeepChat 的会话与 Agent 过程基于 Tape.systems 的哲学设计:把过 - **注重隐私保护**:本地数据存储,支持网络代理,减少信息泄露风险 - **开源友好**:基于 Apache License 2.0 协议,适合商业和个人使用 +## 📦 快速开始 + +### 下载安装 + +您可以通过以下任一方式安装 DeepChat: + +**方式一:GitHub Releases** + +从[GitHub Releases](https://github.com/ThinkInAIXYZ/deepchat/releases)页面下载适合您系统的最新版本: + +- Windows: `.exe`安装文件 +- macOS: `.dmg`安装文件 +- Linux: `.AppImage`或`.deb`安装文件 + +**方式二:官网下载** + +从[官网下载页面](https://deepchatai.cn/#/download)获取安装包。 + +**方式三:Homebrew(仅 macOS)** + +macOS 用户可以使用 Homebrew 安装: + +```bash +brew install --cask deepchat +``` + +### 配置模型 + +1. 启动DeepChat应用 +2. 点击设置图标 +3. 选择"模型提供商"选项卡 +4. 添加您的API密钥或配置本地Ollama + +### 开始对话 + +1. 点击"+"按钮创建新对话 +2. 选择您想使用的模型 +3. 开始与AI助手交流 + ## 🔥 主要功能 - 🤖 **本地优先 Agent 桌面客户端** @@ -177,7 +215,7 @@ DeepChat Skills 是兼容标准 Agent Skills 规范的设计。一个 Skill 可 你可以从文件夹、ZIP 文件或 URL 安装 Skills,也可以与 Claude Code、Codex、Cursor、Windsurf、GitHub Copilot、Kiro、Antigravity、OpenCode、Goose、Kilo Code 等兼容工具导入/导出。 -内置 Skills 覆盖算法艺术、代码审查、DeepChat 设置、文档协作、DOCX、前端设计、git commit 信息、信息图语法、MCP 构建、PDF、PPTX、Skill 创建、Web Artifacts 和 XLSX 工作流。 +内置 Skills 覆盖算法艺术、代码审查、DeepChat CLI、DeepChat 设置、文档协作、DOCX、前端设计、git commit 信息、信息图语法、MCP 构建、记忆管理、PDF、PPTX、Skill 创建和 XLSX 工作流。 快速上手: @@ -421,6 +459,8 @@ DeepChat 可以通过聊天软件远程控制,让你离开桌面后也能继 ### 兼容任何OpenAI/Gemini/Anthropic API格式的模型提供商 +除了上方的内置提供商,任何兼容 OpenAI、Gemini 或 Anthropic API 格式的服务都可以作为自定义提供商接入。 + ## 🔍 使用场景 DeepChat适用于多种AI应用场景: @@ -431,48 +471,9 @@ DeepChat适用于多种AI应用场景: - **内容创作**:文案撰写、创意激发、内容优化 - **数据分析**:数据解读、图表生成、报告撰写 -## 📦 快速开始 - -### 下载安装 - -您可以通过以下任一方式安装 DeepChat: - -**方式一:GitHub Releases** - -从[GitHub Releases](https://github.com/ThinkInAIXYZ/deepchat/releases)页面下载适合您系统的最新版本: - -- Windows: `.exe`安装文件 -- macOS: `.dmg`安装文件 -- Linux: `.AppImage`或`.deb`安装文件 - -**方式二:官网下载** - -从[官网下载页面](https://deepchatai.cn/#/download)获取安装包。 - -**方式三:Homebrew(仅 macOS)** - -macOS 用户可以使用 Homebrew 安装: - -```bash -brew install --cask deepchat -``` - -### 配置模型 - -1. 启动DeepChat应用 -2. 点击设置图标 -3. 选择"模型提供商"选项卡 -4. 添加您的API密钥或配置本地Ollama - -### 开始对话 - -1. 点击"+"按钮创建新对话 -2. 选择您想使用的模型 -3. 开始与AI助手交流 - ## 💻 开发指南 -请阅读[贡献指南](./CONTRIBUTING.md) +请阅读[贡献指南](./CONTRIBUTING.zh.md) Windows和Linux通过GitHub Action打包。 对于Mac相关的签名和打包,请参考[Mac发布指南](https://github.com/ThinkInAIXYZ/deepchat/wiki/Mac-Release-Guide)。 @@ -515,6 +516,8 @@ $ pnpm run build:linux:x64 $ pnpm run build:linux:arm64 ``` +开发环境、项目结构与架构说明请见[开发者指南](./docs/guides/getting-started.md)和[文档索引](./docs/README.md)。 + ## 👥 社区与贡献 DeepChat是一个活跃的开源社区项目,我们欢迎各种形式的贡献: @@ -523,9 +526,9 @@ DeepChat是一个活跃的开源社区项目,我们欢迎各种形式的贡献 - 💡 [提交功能建议](https://github.com/ThinkInAIXYZ/deepchat/issues) - 🔧 [提交代码改进](https://github.com/ThinkInAIXYZ/deepchat/pulls) - 📚 [完善文档](https://github.com/ThinkInAIXYZ/deepchat/wiki) -- 🌍 [帮助翻译](https://github.com/ThinkInAIXYZ/deepchat/tree/main/locales) +- 🌍 [帮助翻译](https://github.com/ThinkInAIXYZ/deepchat/tree/main/src/renderer/src/i18n) -查看[贡献指南](./CONTRIBUTING.md)了解更多参与项目的方式。 +查看[贡献指南](./CONTRIBUTING.zh.md)了解更多参与项目的方式。 ## ⭐ Star历史 @@ -533,7 +536,7 @@ DeepChat是一个活跃的开源社区项目,我们欢迎各种形式的贡献 ## 👨‍💻 贡献者 -感谢您考虑为deepchat做出贡献!贡献指南可以在[贡献指南](./CONTRIBUTING.md)中找到。 +感谢您考虑为deepchat做出贡献!贡献指南可以在[贡献指南](./CONTRIBUTING.zh.md)中找到。 Contribution Leaderboard From dbe81944060792dcb547bba4ddf0b1f338658e3d Mon Sep 17 00:00:00 2001 From: George Pickett Date: Sun, 11 Oct 2026 04:40:40 -0700 Subject: [PATCH 3/9] Merge pull request #2425 from georgeatparallel/parallel-search-984a7d0f-8a65-4bd1-b22e-ec1e52be5470 Add a Parallel Search MCP user-plugin example --- docs/features/user-plugins/authoring.md | 5 + .../parallel-search/.codex-plugin/plugin.json | 10 + .../user-plugins/parallel-search/.mcp.json | 9 + examples/user-plugins/parallel-search/LICENSE | 202 ++++++++++++++++++ .../user-plugins/parallel-search/README.md | 73 +++++++ test/main/plugin/userPluginLifecycle.test.ts | 64 ++++++ 6 files changed, 363 insertions(+) create mode 100644 examples/user-plugins/parallel-search/.codex-plugin/plugin.json create mode 100644 examples/user-plugins/parallel-search/.mcp.json create mode 100644 examples/user-plugins/parallel-search/LICENSE create mode 100644 examples/user-plugins/parallel-search/README.md diff --git a/docs/features/user-plugins/authoring.md b/docs/features/user-plugins/authoring.md index d2a35a960..1c928d308 100644 --- a/docs/features/user-plugins/authoring.md +++ b/docs/features/user-plugins/authoring.md @@ -17,6 +17,11 @@ password field for a user-supplied Bearer key and includes ZIP packaging instruc rotation and removal guidance. The hosted service requires a separate account and may charge for usage; the example is optional and is not bundled or auto-enabled. +For anonymous web search and page fetching, see +[Parallel Search](../../../examples/user-plugins/parallel-search/README.md). This MCP-only example +uses Streamable HTTP with no account or API key required. Package it as a small ZIP and explicitly +enable it after installation; anonymous service rate limits apply. + ## A complete skills-and-hooks package ```text diff --git a/examples/user-plugins/parallel-search/.codex-plugin/plugin.json b/examples/user-plugins/parallel-search/.codex-plugin/plugin.json new file mode 100644 index 000000000..daf322771 --- /dev/null +++ b/examples/user-plugins/parallel-search/.codex-plugin/plugin.json @@ -0,0 +1,10 @@ +{ + "name": "parallel-search", + "version": "0.1.0", + "description": "Free web search and page fetching through Parallel Search MCP. No account or API key required.", + "author": { + "name": "Parallel" + }, + "license": "Apache-2.0", + "mcpServers": "./.mcp.json" +} diff --git a/examples/user-plugins/parallel-search/.mcp.json b/examples/user-plugins/parallel-search/.mcp.json new file mode 100644 index 000000000..67b98ed0b --- /dev/null +++ b/examples/user-plugins/parallel-search/.mcp.json @@ -0,0 +1,9 @@ +{ + "parallel-search": { + "type": "http", + "url": "https://search.parallel.ai/mcp", + "headers": { + "User-Agent": "DeepChat-Parallel-Search/0.1.0 (https://github.com/ThinkInAIXYZ/deepchat)" + } + } +} diff --git a/examples/user-plugins/parallel-search/LICENSE b/examples/user-plugins/parallel-search/LICENSE new file mode 100644 index 000000000..4d226b6b6 --- /dev/null +++ b/examples/user-plugins/parallel-search/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2025] [ThinkInAIXYZ] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/examples/user-plugins/parallel-search/README.md b/examples/user-plugins/parallel-search/README.md new file mode 100644 index 000000000..bac077866 --- /dev/null +++ b/examples/user-plugins/parallel-search/README.md @@ -0,0 +1,73 @@ +# Parallel Search for DeepChat + +An optional MCP-only user plugin for free web search and page fetching with +[Parallel Search MCP](https://docs.parallel.ai/integrations/mcp/search-mcp). +No account or API key is required. Anonymous searches use Fast mode; the free endpoint has +rate limits and is intended for exploration and light use. + +The package contains a manifest and remote MCP configuration, with no local commands, hooks, +Skills or dependencies to install. Installation leaves the plugin disabled and preserves your +existing model and MCP settings. It connects directly to `https://search.parallel.ai/mcp` using +Streamable HTTP. Search queries and requested URLs are sent to Parallel when tools are called. + +## Install + +Use a DeepChat version with **Plugins → Install from ZIP**. The user-plugin installation flow +is available in `v1.1.2-beta.5` and later; `v1.1.1` does not include it. + +1. Obtain a source checkout containing this example. For a pending PR, use its exact commit; + the example will only be available in upstream `dev` after merge. +2. Package only this directory, including its hidden files. With Python 3, run from the + repository root: + + ```sh + cd examples/user-plugins/parallel-search + python3 -m zipfile -c /tmp/parallel-search.zip .codex-plugin .mcp.json README.md LICENSE + ``` + + Choose another output path on Windows. Do not include the entire repository, `.git`, + credentials or `node_modules`. **Install from Git** on the whole DeepChat repository exceeds + the current plugin file-count limit; use the small ZIP instead. +3. Open **Plugins → Install from ZIP**, select the archive and review the package. It should + contain only the `parallel-search` HTTP MCP server at the endpoint above, with no credential + variables, Skills or hooks. Select **MCP** and confirm installation. +4. Explicitly enable the installed **parallel-search** plugin. No password or OAuth sign-in is + needed. Check its MCP status card for a running connection and discovered tools. Plugin-owned + servers do not appear in the ordinary MCP settings list. + +## Tools and controls + +The endpoint exposes `web_search` for finding pages and `web_fetch` for reading URLs. Under the +discovered tool schemas, `web_search` accepts arguments such as: + +```json +{ + "objective": "Find the Python documentation for virtual environments", + "search_queries": ["Python virtual environment documentation"] +} +``` + +Then call `web_fetch` with a URL from the result: + +```json +{ + "urls": ["https://docs.python.org/3/library/venv.html"], + "objective": "Explain how to create a virtual environment" +} +``` + +Inspect the returned content. Discovery alone does not prove a tool call succeeded. This package +uses DeepChat's existing tool and permission controls and does not configure external ACP agents. + +Disable the plugin to stop its integration, or uninstall it to remove its local configuration. +Use **Review update** to import changes; editing your source checkout does not update an installed +snapshot. Uninstalling does not remove previous conversation records. + +If a call is rate limited, wait for the service's retry time before trying again. For connection +errors, check access to the endpoint and the plugin's diagnostic. Do not add an Authorization +header to this anonymous example. For service limits and support, see the +[Parallel Search MCP guide](https://docs.parallel.ai/integrations/mcp/search-mcp); for installation +behavior, see DeepChat's [user-plugin guide](../../../docs/features/user-plugins/authoring.md). + +These example files use DeepChat's [Apache-2.0 license](./LICENSE). Parallel operates the hosted +service separately. I work at Parallel. diff --git a/test/main/plugin/userPluginLifecycle.test.ts b/test/main/plugin/userPluginLifecycle.test.ts index 8b7c65c51..259366f92 100644 --- a/test/main/plugin/userPluginLifecycle.test.ts +++ b/test/main/plugin/userPluginLifecycle.test.ts @@ -506,3 +506,67 @@ it('clears interrupted-update state even when restoring MCP settings fails', asy await new UserPlugins(f.deps).initialize() expect(f.store.pending()).toBeNull() }) + +it('installs the anonymous Parallel ZIP without changing existing MCP settings', async () => { + const f = fixture() + const source = path.resolve('examples/user-plugins/parallel-search') + const archive = path.join(f.root, 'parallel-search.zip') + fs.writeFileSync( + archive, + zipSync( + Object.fromEntries( + fs + .readdirSync(source, { recursive: true, encoding: 'utf8' }) + .filter((relative) => fs.statSync(path.join(source, relative)).isFile()) + .map((relative) => [ + relative.split(path.sep).join('/'), + fs.readFileSync(path.join(source, relative)) + ]) + ) + ) + ) + const existing = await f.mcpSettings.getMcpServers() + const inspected = await f.service.inspect({ kind: 'zip', path: archive }, randomUUID()) + expect(inspected.package).toMatchObject({ + name: 'parallel-search', + skills: [], + hooks: [], + findings: [], + mcpServers: [ + { + name: 'parallel-search', + type: 'http', + url: 'https://search.parallel.ai/mcp', + headers: { + 'User-Agent': 'DeepChat-Parallel-Search/0.1.0 (https://github.com/ThinkInAIXYZ/deepchat)' + }, + requiredVariables: [] + } + ] + }) + const installed = await f.service.install({ + operationId: inspected.operationId, + selection: { skills: false, hooks: false, mcp: true } + }) + expect(installed.ok).toBe(true) + expect(installed.status).toMatchObject({ enabled: false }) + expect(await f.mcpSettings.getMcpServers()).toEqual(existing) + const id = installed.status!.id + expect((await f.service.enable(id)).ok).toBe(true) + const key = `${id}.parallel-search` + const enabled = await f.mcpSettings.getMcpServers() + expect(enabled[key]).toMatchObject({ + type: 'http', + baseUrl: 'https://search.parallel.ai/mcp', + customHeaders: { + 'User-Agent': 'DeepChat-Parallel-Search/0.1.0 (https://github.com/ThinkInAIXYZ/deepchat)' + }, + environmentVariables: [] + }) + expect(f.mcpSettings.getMcpVariableBindings(enabled[key])).toEqual({}) + for (const [name, config] of Object.entries(existing)) expect(enabled[name]).toEqual(config) + expect((await f.service.disable(id)).ok).toBe(true) + expect((await f.mcpSettings.getMcpServers())[key].enabled).toBe(false) + expect((await f.service.uninstall(id)).ok).toBe(true) + expect(await f.mcpSettings.getMcpServers()).toEqual(existing) +}) From 159f93231614965412900da25de81ec0d3ddb080 Mon Sep 17 00:00:00 2001 From: Rohan Sharma <114828377+rs545837@users.noreply.github.com> Date: Sun, 11 Oct 2026 21:50:32 -0700 Subject: [PATCH 4/9] docs(plugin): add optional Sem example (#2426) --- docs/features/user-plugins/authoring.md | 4 ++ .../sem/.codex-plugin/plugin.json | 8 +++ examples/user-plugins/sem/.mcp.json | 11 ++++ examples/user-plugins/sem/README.md | 64 +++++++++++++++++++ test/main/plugin/userPluginLifecycle.test.ts | 43 +++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 examples/user-plugins/sem/.codex-plugin/plugin.json create mode 100644 examples/user-plugins/sem/.mcp.json create mode 100644 examples/user-plugins/sem/README.md diff --git a/docs/features/user-plugins/authoring.md b/docs/features/user-plugins/authoring.md index 1c928d308..fa9711802 100644 --- a/docs/features/user-plugins/authoring.md +++ b/docs/features/user-plugins/authoring.md @@ -22,6 +22,10 @@ For anonymous web search and page fetching, see uses Streamable HTTP with no account or API key required. Package it as a small ZIP and explicitly enable it after installation; anonymous service rate limits apply. +For local code-entity search and structural diffs, see +[Sem](../../../examples/user-plugins/sem/README.md). This optional stdio example asks for an explicit +Git repository path and keeps normal tool approvals; its validation tools can execute repository commands. + ## A complete skills-and-hooks package ```text diff --git a/examples/user-plugins/sem/.codex-plugin/plugin.json b/examples/user-plugins/sem/.codex-plugin/plugin.json new file mode 100644 index 000000000..df7964a6a --- /dev/null +++ b/examples/user-plugins/sem/.codex-plugin/plugin.json @@ -0,0 +1,8 @@ +{ + "name": "sem-code-review", + "version": "0.1.0", + "description": "Local code-entity search, caller inspection and structural diffs with Sem.", + "author": { "name": "Ataraxy Labs" }, + "license": "Apache-2.0", + "mcpServers": "./.mcp.json" +} diff --git a/examples/user-plugins/sem/.mcp.json b/examples/user-plugins/sem/.mcp.json new file mode 100644 index 000000000..75f22861d --- /dev/null +++ b/examples/user-plugins/sem/.mcp.json @@ -0,0 +1,11 @@ +{ + "sem": { + "command": "npx", + "args": ["-y", "@ataraxy-labs/sem@0.27.0", "mcp"], + "env": { + "SEM_REPO": "${SEM_REPO}", + "SEM_NO_NETWORK": "1", + "SEM_NO_TELEMETRY": "1" + } + } +} diff --git a/examples/user-plugins/sem/README.md b/examples/user-plugins/sem/README.md new file mode 100644 index 000000000..4339104f3 --- /dev/null +++ b/examples/user-plugins/sem/README.md @@ -0,0 +1,64 @@ +# Sem local code review for DeepChat + +An optional MCP-only plugin for [Sem](https://github.com/Ataraxy-Labs/sem): inspect +code entities, callers, dependencies and structural diffs in a local Git repository. +No Sem account or API key is required. This example adds no hooks, Skills or bundled binaries. +It leaves existing model settings and MCP servers unchanged. + +## Install + +Use a DeepChat version with user plugins (v1.1.2-beta.5 or later), Git, and Node.js/npm +available through DeepChat's Toolchains settings. This example targets macOS/Linux on ARM64/x64. +Enabling the server invokes npx; first installation downloads the pinned npm package and native +Sem binary. Only connect a repository whose build/test scripts you trust. + +1. Obtain a checkout containing this example. Until its PR merges, use the PR's exact commit. +2. From this directory, package the hidden files as well as the README: + + ```sh + python3 -m zipfile -c /tmp/sem-code-review.zip .codex-plugin .mcp.json README.md + ``` + + Choose a suitable output path on your platform. Do not package the whole repository, + credentials, `.git` or `node_modules`. +3. Open **Plugins → Install from ZIP** and inspect the archive. Expect one stdio server, + the pinned command above, and one required variable, `SEM_REPO`. Select MCP and install. + Installation leaves the plugin disabled. +4. Explicitly enable the plugin and use its MCP setup form to supply `SEM_REPO`: an absolute + path to an existing local Git repository. The generic setup form masks variable values; + this value is a directory path, not an API key. It is not inherited from your shell. +5. Check the plugin's MCP connection status and discovered tool schemas. Plugin-owned servers + are separate from the ordinary MCP settings list. Discovery is not proof that a tool call works. + +## Try it + +Substitute a symbol that exists in the selected repository: + +> Use Sem to locate `parse_config`, inspect its callers and explain the code. Do not edit files or run tests. + +For a checkout with tracked local changes: + +> Inspect the structural diff with Sem and explain the changes. Do not execute validation commands. + +The graph's coverage depends on the language and source constructs. Missing results do not prove +there are no references. Retain ordinary file tools for configuration and unresolved code. +This plugin does not configure external ACP agents or provide Weave editing/merging tools. + +## Permissions and privacy + +- `sem_check` can run repository build/test commands. Keep normal tool approvals and only + authorize execution intentionally; this is not a read-only server. +- `SEM_REPO` selects a repository; it is not an operating-system sandbox. +- The preset disables Sem cloud access and telemetry recording. npm/native-binary installation + still uses the network. Those flags do not sandbox commands run by repository checks. +- Returned source code enters the conversation and may reach the configured model provider. +- Sem builds a local index. Structural results are not proof that code compiles or passes tests. + +If setup fails, check Node/npm in Toolchains, Git availability, install-script permissions and the +absolute repository path. Change the path through MCP setup, not your shell environment. +Use **Review update** to change an installed package; editing the source checkout does not update +its installed snapshot. Disable or uninstall the plugin to remove its active integration. +Uninstalling does not erase earlier conversations, npm downloads or Sem's local cache. + +The example files use DeepChat's Apache-2.0 license; Sem is distributed separately under its own +license. This example is contributed by Sem's maintainer at Ataraxy Labs. diff --git a/test/main/plugin/userPluginLifecycle.test.ts b/test/main/plugin/userPluginLifecycle.test.ts index 259366f92..5c225935e 100644 --- a/test/main/plugin/userPluginLifecycle.test.ts +++ b/test/main/plugin/userPluginLifecycle.test.ts @@ -507,6 +507,49 @@ it('clears interrupted-update state even when restoring MCP settings fails', asy expect(f.store.pending()).toBeNull() }) +it('installs Sem disabled and retains its explicit repository binding through enable and removal', async () => { + const f = fixture() + const existing = await f.mcpSettings.getMcpServers() + const inspected = await f.service.inspect( + { kind: 'directory', path: path.resolve('examples/user-plugins/sem') }, + randomUUID() + ) + expect(inspected.package).toMatchObject({ + name: 'sem-code-review', + skills: [], + hooks: [], + findings: [], + mcpServers: [{ name: 'sem', type: 'stdio', requiredVariables: ['SEM_REPO'] }] + }) + const installed = await f.service.install({ + operationId: inspected.operationId, + selection: { skills: false, hooks: false, mcp: true } + }) + expect(installed.ok).toBe(true) + expect(installed.status).toMatchObject({ enabled: false }) + expect(await f.mcpSettings.getMcpServers()).toEqual(existing) + const id = installed.status!.id + const key = `${id}.sem` + expect((await f.service.enable(id)).ok).toBe(true) + expect((await f.service.get(id)).userPlugin?.setup[key]).toEqual(['SEM_REPO']) + expect((await f.service.configureMcp(id, key, { SEM_REPO: '' })).ok).toBe(false) + const repository = path.join(f.root, 'repository with spaces') + expect((await f.service.configureMcp(id, key, { SEM_REPO: repository })).ok).toBe(true) + const config = (await f.mcpSettings.getMcpServers())[key] + expect(config).toMatchObject({ + type: 'stdio', + command: 'npx', + args: ['-y', '@ataraxy-labs/sem@0.27.0', 'mcp'], + env: { SEM_REPO: '${SEM_REPO}', SEM_NO_NETWORK: '1', SEM_NO_TELEMETRY: '1' }, + environmentVariables: ['SEM_REPO'] + }) + expect(f.mcpSettings.getMcpVariableBindings(config)).toEqual({ SEM_REPO: repository }) + expect((await f.service.disable(id)).ok).toBe(true) + expect((await f.mcpSettings.getMcpServers())[key].enabled).toBe(false) + expect((await f.service.uninstall(id)).ok).toBe(true) + expect(await f.mcpSettings.getMcpServers()).toEqual(existing) +}) + it('installs the anonymous Parallel ZIP without changing existing MCP settings', async () => { const f = fixture() const source = path.resolve('examples/user-plugins/parallel-search') From b296496d9d7271cde38bc35e4b89fcbf3a59af7f Mon Sep 17 00:00:00 2001 From: zerob13 Date: Mon, 12 Oct 2026 13:45:46 +0800 Subject: [PATCH 5/9] fix(copilot): validate session authentication --- .env.example | 4 +- .../provider/auth/githubCopilotDeviceFlow.ts | 187 +++++++++-------- src/main/provider/auth/githubCopilotOAuth.ts | 19 -- src/main/provider/auth/index.ts | 84 ++------ .../providers/githubCopilotProvider.ts | 198 ++---------------- .../provider/githubCopilotDeviceFlow.test.ts | 144 ++++++++++++- .../githubCopilotOAuthService.test.ts | 93 ++++++++ .../provider/githubCopilotProvider.test.ts | 186 ++++++++++------ .../components/GitHubCopilotOAuth.test.ts | 20 ++ 9 files changed, 491 insertions(+), 444 deletions(-) create mode 100644 test/main/provider/githubCopilotOAuthService.test.ts diff --git a/.env.example b/.env.example index 52d6ef8c0..5dea5c23a 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ # GitHub OAuth Configuration for GitHub Copilot -# Copy this file to .env and fill in the actual values -# Both Client ID and Client Secret are required +# Device Flow uses a built-in public Client ID and does not require a Client Secret. +# For traditional OAuth, configure a matching Client ID, Client Secret, and redirect URI. VITE_GITHUB_CLIENT_ID=Iv1.b507a08c87ecfe98 VITE_GITHUB_CLIENT_SECRET=your_github_client_secret_here VITE_GITHUB_REDIRECT_URI=https://deepchatai.cn/auth/github/callback diff --git a/src/main/provider/auth/githubCopilotDeviceFlow.ts b/src/main/provider/auth/githubCopilotDeviceFlow.ts index 9926a6a87..30f41ae21 100644 --- a/src/main/provider/auth/githubCopilotDeviceFlow.ts +++ b/src/main/provider/auth/githubCopilotDeviceFlow.ts @@ -1,8 +1,12 @@ import { BrowserWindow, clipboard, shell } from 'electron' import { exec } from 'child_process' import logger from '@shared/logger' +import { z } from 'zod' +import { createProviderHttpErrorFromResponse, type ProviderHttpError } from '../providerFailure' const GITHUB_DEVICE_URL = 'https://github.com/login/device' +const GITHUB_COPILOT_DEVICE_FLOW_CLIENT_ID = 'Iv1.b507a08c87ecfe98' +const GITHUB_TOKEN_PATTERN = /^[\x21-\x7e]+$/ export interface DeviceFlowConfig { clientId: string @@ -31,20 +35,96 @@ export interface CopilotTokenResponse { refresh_in?: number } -export interface ApiToken { - apiKey: string - expiresAt: Date +// Copilot chat uses VS Code integration metadata independently of the DeepChat app version. +export const GITHUB_COPILOT_CHAT_HEADERS = { + 'User-Agent': 'GitHubCopilotChat/0.44.0', + 'Editor-Version': 'vscode/1.115.0', + 'Editor-Plugin-Version': 'copilot-chat/0.44.0', + 'Copilot-Integration-Id': 'vscode-chat', + 'X-GitHub-Api-Version': '2026-08-01' } -export interface CopilotConfig { - oauthToken?: string - apiToken?: ApiToken +const CopilotTokenSchema = z.object({ + token: z.string().regex(GITHUB_TOKEN_PATTERN), + expires_at: z.number().positive().finite(), + refresh_in: z.number().nonnegative().finite().optional() +}) + +export async function createGitHubCopilotHttpError( + response: Response, + phase: 'token' | 'chat', + secrets: string[] +): Promise { + const body = await response.json().catch(() => null) + const sanitize = (value: unknown): string => { + if (typeof value !== 'string') return '' + let text = value + for (const secret of secrets) { + if (secret) text = text.replaceAll(secret, '[redacted]') + } + return text + .replace(/(?:gh[opusr]_|github_pat_)[A-Za-z0-9_]+/g, '[redacted]') + .replace(/Bearer\s+[^\s"',}]+/gi, 'Bearer [redacted]') + .replace(/(?:access_token|refresh_token|api_key)["\s:=]+[^"'\s,}]+/gi, '[redacted]') + .replace(/[\r\n\0]/g, ' ') + .slice(0, 500) + } + const serverMessage = sanitize( + body?.error?.message ?? body?.error_details?.message ?? body?.message + ) + const serverCode = sanitize(body?.error?.code ?? body?.error_details?.code ?? body?.code) + const requestId = sanitize( + response.headers.get('x-github-request-id') ?? response.headers.get('x-request-id') + ) + const details = [ + serverMessage, + /^[A-Za-z0-9._:-]{1,128}$/.test(serverCode) ? `code=${serverCode}` : '', + /^[A-Za-z0-9._:-]{1,128}$/.test(requestId) ? `request_id=${requestId}` : '' + ].filter(Boolean) + const description = phase === 'token' ? 'token exchange failed' : 'API error' + return createProviderHttpErrorFromResponse( + `GitHub Copilot ${description}: ${response.status} ${sanitize(response.statusText)}` + + (details.length ? ` - ${details.join('; ')}` : ''), + response, + `github_copilot_${phase}_http_error` + ) +} + +export async function getGitHubCopilotToken( + oauthToken: string, + signal?: AbortSignal +): Promise { + signal?.throwIfAborted() + if (typeof oauthToken !== 'string' || !GITHUB_TOKEN_PATTERN.test(oauthToken)) { + throw new Error('No GitHub OAuth token available. Please sign in to GitHub Copilot.') + } + try { + const response = await fetch('https://api.github.com/copilot_internal/v2/token', { + headers: { + Authorization: `token ${oauthToken}`, + Accept: 'application/json', + 'User-Agent': GITHUB_COPILOT_CHAT_HEADERS['User-Agent'], + 'X-GitHub-Api-Version': '2025-04-01' + }, + ...(signal ? { signal } : {}) + }) + if (!response.ok) { + throw await createGitHubCopilotHttpError(response, 'token', [oauthToken]) + } + const result = CopilotTokenSchema.safeParse(await response.json().catch(() => null)) + if (!result.success) { + throw new Error('Invalid GitHub Copilot token response') + } + return result.data + } catch (error) { + signal?.throwIfAborted() + throw error + } } export class GitHubCopilotDeviceFlow { private config: DeviceFlowConfig private pollingInterval: NodeJS.Timeout | null = null - private oauthToken: string | null = null constructor(config: DeviceFlowConfig) { this.config = config @@ -73,83 +153,6 @@ export class GitHubCopilotDeviceFlow { } } - /** - * 获取 Copilot API token - * 使用OAuth token交换Copilot API token - */ - public async getCopilotToken(signal?: AbortSignal): Promise { - signal?.throwIfAborted() - if (!this.oauthToken) { - throw new Error('No OAuth token available') - } - - // 使用OAuth token从GitHub API获取Copilot token - const tokenUrl = 'https://api.github.com/copilot_internal/v2/token' - - try { - const response = await fetch(tokenUrl, { - method: 'GET', - headers: { - Authorization: `Bearer ${this.oauthToken}`, - Accept: 'application/json', - 'User-Agent': 'DeepChat/1.0.0' - }, - ...(signal ? { signal } : {}) - }) - - if (!response.ok) { - const errorText = await response.text().catch(() => '') - throw new Error( - `Failed to get Copilot token: ${response.status} ${response.statusText} - ${errorText}` - ) - } - - const data = (await response.json()) as { token: string; expires_at: number } - return data.token - } catch (error) { - signal?.throwIfAborted() - console.error('[GitHub Copilot][DeviceFlow] Failed to get Copilot token:', error) - throw error - } - } - - /** - * 检查是否已经有有效的认证状态 - */ - public async checkExistingAuth(externalToken?: string): Promise { - try { - // 如果提供了外部 token,使用它 - if (externalToken) { - this.oauthToken = externalToken - - // 尝试获取 API token 来验证认证状态 - try { - await this.getCopilotToken() - return this.oauthToken - } catch { - this.oauthToken = null - return null - } - } - - // 检查内部存储的 token - if (this.oauthToken) { - // 尝试获取 API token 来验证认证状态 - try { - await this.getCopilotToken() - return this.oauthToken! - } catch { - this.oauthToken = null - } - } - - return null - } catch (error) { - console.warn('[GitHub Copilot][DeviceFlow] Error checking existing auth:', error) - return null - } - } - /** * Step 1: Request device code */ @@ -594,13 +597,10 @@ export class GitHubCopilotDeviceFlow { // GitHub Copilot Device Flow configuration export function createGitHubCopilotDeviceFlow(clientIdOverride?: string): GitHubCopilotDeviceFlow { - const clientId = clientIdOverride?.trim() || import.meta.env.VITE_GITHUB_CLIENT_ID - - if (!clientId) { - throw new Error( - 'GitHub Client ID is required. Please enter it in the Copilot settings input or set VITE_GITHUB_CLIENT_ID in .env.' - ) - } + const clientId = + clientIdOverride?.trim() || + import.meta.env.VITE_GITHUB_CLIENT_ID?.trim() || + GITHUB_COPILOT_DEVICE_FLOW_CLIENT_ID const config: DeviceFlowConfig = { clientId, @@ -624,7 +624,10 @@ let globalDeviceFlowClientId: string | null = null export function getGlobalGitHubCopilotDeviceFlow( clientIdOverride?: string ): GitHubCopilotDeviceFlow { - const effectiveClientId = clientIdOverride?.trim() || import.meta.env.VITE_GITHUB_CLIENT_ID + const effectiveClientId = + clientIdOverride?.trim() || + import.meta.env.VITE_GITHUB_CLIENT_ID?.trim() || + GITHUB_COPILOT_DEVICE_FLOW_CLIENT_ID if (!globalDeviceFlowInstance || globalDeviceFlowClientId !== effectiveClientId) { globalDeviceFlowInstance?.dispose() diff --git a/src/main/provider/auth/githubCopilotOAuth.ts b/src/main/provider/auth/githubCopilotOAuth.ts index 5660ade5c..957fa59fa 100644 --- a/src/main/provider/auth/githubCopilotOAuth.ts +++ b/src/main/provider/auth/githubCopilotOAuth.ts @@ -191,25 +191,6 @@ export class GitHubCopilotOAuth { } } - /** - * Validate access token - */ - async validateToken(token: string): Promise { - try { - const response = await fetch('https://api.github.com/user', { - headers: { - Authorization: `Bearer ${token}`, - 'User-Agent': 'DeepChat/1.0.0' - } - }) - - return response.ok - } catch (error) { - console.error('Token validation failed:', error) - return false - } - } - /** * Close authorization window */ diff --git a/src/main/provider/auth/index.ts b/src/main/provider/auth/index.ts index c87db9099..a485d8fca 100644 --- a/src/main/provider/auth/index.ts +++ b/src/main/provider/auth/index.ts @@ -4,7 +4,7 @@ import { BrowserWindow } from 'electron' import * as http from 'http' import { URL } from 'url' import { createGitHubCopilotOAuth } from './githubCopilotOAuth' -import { getGlobalGitHubCopilotDeviceFlow } from './githubCopilotDeviceFlow' +import { getGitHubCopilotToken, getGlobalGitHubCopilotDeviceFlow } from './githubCopilotDeviceFlow' import { getGlobalOpenAICodexAuth, initializeGlobalOpenAICodexAuth } from './openaiCodex' import { getGlobalXaiGrokAuth, initializeGlobalXaiGrokAuth } from './xaiGrok' import type { OpenAICodexAuthStatus } from '@shared/types/openai-codex' @@ -29,64 +29,26 @@ export class OAuthService implements OAuthServicePort { initializeGlobalXaiGrokAuth(publishEvent) } - /** - * Validate GitHub access token - */ - private async validateGitHubAccessToken(token: string): Promise { - try { - const response = await fetch('https://api.github.com/user', { - headers: { - Authorization: `Bearer ${token}`, - 'User-Agent': 'DeepChat/1.0.0' - } - }) - - return response.ok - } catch (error) { - console.error('Token validation failed:', error) - return false - } - } - /** * Start GitHub Copilot Device Flow login process (recommended) */ async startGitHubCopilotDeviceFlowLogin(providerId: string): Promise { try { const provider = this.providerSettings.getProviderById(providerId) - const githubDeviceFlow = getGlobalGitHubCopilotDeviceFlow(provider?.copilotClientId) - - // 首先检查现有认证状态 - if (provider && provider.apiKey) { - const existingToken = await githubDeviceFlow.checkExistingAuth(provider.apiKey) - if (existingToken) { - return true - } - } + if (!provider) throw new Error(`Provider ${providerId} not found`) + const githubDeviceFlow = getGlobalGitHubCopilotDeviceFlow(provider.copilotClientId) // 开始Device Flow登录 const accessToken = await githubDeviceFlow.startDeviceFlow() - // Validate token - logger.info('Validating access token...') - const isValid = await this.validateGitHubAccessToken(accessToken) - if (!isValid) { - throw new Error('Obtained access token is invalid') - } - - // 保存访问令牌到provider配置 - if (provider) { - provider.apiKey = accessToken - this.providerSettings.setProviderById(providerId, provider) - logger.info('[GitHub Copilot] Device Flow login completed successfully') - } else { - throw new Error(`Provider ${providerId} not found`) - } + await getGitHubCopilotToken(accessToken) + this.providerSettings.setProviderById(providerId, { ...provider, apiKey: accessToken }) + logger.info('[GitHub Copilot] Device Flow login completed successfully') return true } catch (error) { console.error('[GitHub Copilot] Device Flow login failed:', error) - return false + throw error } } @@ -141,7 +103,8 @@ export class OAuthService implements OAuthServicePort { // 使用专门的GitHub Copilot OAuth实现 logger.info('[GitHub Copilot][OAuth] Creating GitHub OAuth instance...') const provider = this.providerSettings.getProviderById(providerId) - const githubOAuth = createGitHubCopilotOAuth(provider?.copilotClientId) + if (!provider) throw new Error(`Provider ${providerId} not found`) + const githubOAuth = createGitHubCopilotOAuth(provider.copilotClientId) // 开始OAuth登录 logger.info('[GitHub Copilot][OAuth] Starting OAuth login flow...') @@ -169,30 +132,9 @@ export class OAuthService implements OAuthServicePort { logger.info('[GitHub Copilot][OAuth] Access token received successfully') } - // Validate token - logger.info('[GitHub Copilot][OAuth] Validating access token...') - const isValid = await githubOAuth.validateToken(accessToken) - logger.info('[GitHub Copilot][OAuth] Token validation result:', isValid) - - if (!isValid) { - console.error('[GitHub Copilot][OAuth] Token validation failed - token is invalid') - throw new Error('获取的访问令牌无效') - } - - // 保存访问令牌到provider配置 - logger.info('[GitHub Copilot][OAuth] Saving access token to provider configuration...') - if (provider) { - provider.apiKey = accessToken - this.providerSettings.setProviderById(providerId, provider) - logger.info( - '[GitHub Copilot][OAuth] Access token saved successfully to provider:', - providerId - ) - logger.info('[GitHub Copilot][OAuth] Traditional OAuth login completed successfully') - } else { - console.error('[GitHub Copilot][OAuth] Provider not found:', providerId) - throw new Error(`Provider ${providerId} not found`) - } + await getGitHubCopilotToken(accessToken) + this.providerSettings.setProviderById(providerId, { ...provider, apiKey: accessToken }) + logger.info('[GitHub Copilot][OAuth] Traditional OAuth login completed successfully') return true } catch (error) { @@ -208,7 +150,7 @@ export class OAuthService implements OAuthServicePort { if (error instanceof Error && error.stack) { console.error('[GitHub Copilot][OAuth][ERROR] Stack trace:', error.stack) } - return false + throw error } } diff --git a/src/main/provider/providers/githubCopilotProvider.ts b/src/main/provider/providers/githubCopilotProvider.ts index ca7220a6b..8432d8cff 100644 --- a/src/main/provider/providers/githubCopilotProvider.ts +++ b/src/main/provider/providers/githubCopilotProvider.ts @@ -17,31 +17,16 @@ import { } from '../baseProvider' import { normalizeToolInputSchema } from '../aiSdk/toolMapper' import type { ProviderLocalePort } from '../ports' -import { HttpsProxyAgent } from 'https-proxy-agent' import { - getGlobalGitHubCopilotDeviceFlow, - GitHubCopilotDeviceFlow + createGitHubCopilotHttpError, + getGitHubCopilotToken, + GITHUB_COPILOT_CHAT_HEADERS } from '../../provider/auth/githubCopilotDeviceFlow' -import { createProviderHttpErrorFromResponse, ProviderHttpError } from '../providerFailure' - -// 扩展RequestInit类型以支持agent属性 -interface RequestInitWithAgent extends RequestInit { - agent?: HttpsProxyAgent -} -import { proxyConfig } from '../../platform/proxy' - -interface CopilotTokenResponse { - token: string - expires_at: number - refresh_in?: number -} export class GithubCopilotProvider extends BaseLLMProvider { private copilotToken: string | null = null private tokenExpiresAt: number = 0 private baseApiUrl = 'https://api.githubcopilot.com' - private tokenUrl = 'https://api.github.com/copilot_internal/v2/token' - private deviceFlow: GitHubCopilotDeviceFlow | null = null constructor( provider: LLM_PROVIDER, @@ -56,15 +41,6 @@ export class GithubCopilotProvider extends BaseLLMProvider { if (this.provider.enable) { try { this.isInitialized = true - this.deviceFlow = getGlobalGitHubCopilotDeviceFlow(this.provider.copilotClientId) - - // 检查现有认证状态 - if (this.provider.apiKey) { - const existingToken = await this.deviceFlow.checkExistingAuth(this.provider.apiKey) - if (!existingToken) { - this.provider.apiKey = '' - } - } await this.fetchModels() await this.autoEnableModelsIfNeeded() @@ -85,124 +61,26 @@ export class GithubCopilotProvider extends BaseLLMProvider { } public override updateConfig(provider: LLM_PROVIDER): void { - const newDeviceFlow = getGlobalGitHubCopilotDeviceFlow(provider.copilotClientId) - super.updateConfig(provider) this.copilotToken = null this.tokenExpiresAt = 0 - this.deviceFlow = newDeviceFlow - } - - private createChatHttpError(response: Response): ProviderHttpError { - const code = 'github_copilot_chat_http_error' - if (response.status !== 403) { - return createProviderHttpErrorFromResponse( - `GitHub Copilot API error: ${response.status} ${response.statusText}`, - response, - code - ) - } - - return createProviderHttpErrorFromResponse( - `GitHub Copilot 访问被拒绝 (403)。\n\n可能的原因:\n` + - `1. GitHub Copilot 订阅已过期或未激活\n` + - `2. 需要重新认证以获取正确的访问权限\n` + - `3. API访问策略已更新,需要使用最新的认证方式\n` + - `4. 您的账户可能没有访问此API的权限\n\n` + - `建议解决方案:\n` + - `- 访问 https://github.com/settings/copilot 检查订阅状态\n` + - `- 在DeepChat设置中重新进行 GitHub Copilot 登录\n` + - `- 确保您的 GitHub 账户有有效的 Copilot 订阅\n` + - `- 如果是企业账户,请联系管理员确认访问权限`, - response, - code - ) } private async getCopilotToken(signal?: AbortSignal): Promise { signal?.throwIfAborted() - // 优先使用设备流获取 token - if (this.deviceFlow) { - try { - return await this.deviceFlow.getCopilotToken(signal) - } catch (error) { - signal?.throwIfAborted() - console.warn( - '[GitHub Copilot] Device flow failed, falling back to provider API key:', - error - ) - } - } - - // 检查token是否过期 if (this.copilotToken && Date.now() < this.tokenExpiresAt) { return this.copilotToken } - if (!this.provider.apiKey) { - throw new Error('No GitHub OAuth token available. Please use device flow authentication.') - } - - // 获取新的token - const headers: Record = { - Authorization: `Bearer ${this.provider.apiKey}`, - Accept: 'application/json', - 'User-Agent': 'DeepChat/1.0.0' - } - - const requestOptions: RequestInitWithAgent = { - method: 'GET', - headers, - ...(signal ? { signal } : {}) - } - - // 添加代理支持 - const proxyUrl = proxyConfig.getProxyUrl() - if (proxyUrl) { - const agent = new HttpsProxyAgent(proxyUrl) - requestOptions.agent = agent - } - - try { - const response = await fetch(this.tokenUrl, requestOptions) - - if (!response.ok) { - let errorMessage = `Failed to get Copilot token: ${response.status} ${response.statusText}` - - // 提供更具体的错误信息和解决建议 - if (response.status === 404) { - errorMessage = `GitHub Copilot 访问被拒绝 (404)。请检查: -1. 您的 GitHub 账户是否有有效的 GitHub Copilot 订阅 -2. OAuth token 权限不足 - 需要 'read:org' 权限访问 Copilot API -3. 请重新进行 OAuth 登录以获取正确的权限范围 -4. 访问 https://github.com/features/copilot 检查订阅状态` - } else if (response.status === 401) { - errorMessage = `GitHub OAuth token 无效或已过期 (401)。请重新登录授权并确保获取了正确的权限范围。` - } else if (response.status === 403) { - errorMessage = `GitHub Copilot 访问被禁止 (403)。请检查: -1. 您的 GitHub Copilot 订阅是否有效且处于活跃状态 -2. 是否达到了 API 使用限制 -3. OAuth token 是否包含 'read:org' 权限范围 -4. 如果是组织账户,请确保组织已启用 Copilot 并且您有访问权限` - } - - throw createProviderHttpErrorFromResponse( - errorMessage, - response, - 'github_copilot_token_http_error' - ) - } - - const data: CopilotTokenResponse = await response.json() + const provider = this.provider + const data = await getGitHubCopilotToken(provider.apiKey, signal) + signal?.throwIfAborted() + // An exchange started before an account change must not populate the new account's cache. + if (this.provider === provider) { this.copilotToken = data.token - this.tokenExpiresAt = data.expires_at * 1000 // 转换为毫秒 - - return this.copilotToken - } catch (error) { - signal?.throwIfAborted() - console.error('[GitHub Copilot] Error getting Copilot token:', error) - throw error + this.tokenExpiresAt = data.expires_at * 1000 } + return data.token } protected async fetchProviderModels(): Promise { @@ -485,9 +363,7 @@ export class GithubCopilotProvider extends BaseLLMProvider { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', Accept: 'text/event-stream', - 'User-Agent': 'DeepChat/1.0.0', - 'Editor-Version': 'DeepChat/1.0.0', - 'Copilot-Integration-Id': 'vscode-chat' + ...GITHUB_COPILOT_CHAT_HEADERS } // 添加详细的请求日志 @@ -499,7 +375,7 @@ export class GithubCopilotProvider extends BaseLLMProvider { ` Request Body: { messages: ${formattedMessages.length}, model: "${modelId}", temperature: ${temperature}, max_tokens: ${_maxTokens} }` ) - const requestOptions: RequestInitWithAgent = { + const requestOptions: RequestInit = { method: 'POST', headers, body: JSON.stringify(requestBody), @@ -512,13 +388,6 @@ export class GithubCopilotProvider extends BaseLLMProvider { body: requestBody }) - // 添加代理支持 - const proxyUrl = proxyConfig.getProxyUrl() - if (proxyUrl) { - const agent = new HttpsProxyAgent(proxyUrl) - requestOptions.agent = agent - } - const response = await this.fetchProvider( `${this.baseApiUrl}/chat/completions`, requestOptions @@ -529,7 +398,7 @@ export class GithubCopilotProvider extends BaseLLMProvider { logger.info(` OK: ${response.ok}`) if (!response.ok) { - throw this.createChatHttpError(response) + throw await createGitHubCopilotHttpError(response, 'chat', [token, this.provider.apiKey]) } if (!response.body) { @@ -644,9 +513,7 @@ export class GithubCopilotProvider extends BaseLLMProvider { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', Accept: 'application/json', - 'User-Agent': 'DeepChat/1.0.0', - 'Editor-Version': 'DeepChat/1.0.0', - 'Copilot-Integration-Id': 'vscode-chat' + ...GITHUB_COPILOT_CHAT_HEADERS } // 添加详细的请求日志 @@ -658,20 +525,13 @@ export class GithubCopilotProvider extends BaseLLMProvider { ` Request Body: { messages: ${formattedMessages.length}, model: "${modelId}", temperature: ${temperature}, max_tokens: ${_maxTokens} }` ) - const requestOptions: RequestInitWithAgent = { + const requestOptions: RequestInit = { method: 'POST', headers, body: JSON.stringify(requestBody), ...(signal ? { signal } : {}) } - // 添加代理支持 - const proxyUrl = proxyConfig.getProxyUrl() - if (proxyUrl) { - const agent = new HttpsProxyAgent(proxyUrl) - requestOptions.agent = agent - } - const response = await this.fetchProvider( `${this.baseApiUrl}/chat/completions`, requestOptions @@ -682,7 +542,7 @@ export class GithubCopilotProvider extends BaseLLMProvider { logger.info(` OK: ${response.ok}`) if (!response.ok) { - throw this.createChatHttpError(response) + throw await createGitHubCopilotHttpError(response, 'chat', [token, this.provider.apiKey]) } const data = await response.json() @@ -754,36 +614,12 @@ export class GithubCopilotProvider extends BaseLLMProvider { async check(): Promise<{ isOk: boolean; errorMsg: string | null }> { try { - // Device flow may be active without apiKey; proceed to token retrieval await this.getCopilotToken() return { isOk: true, errorMsg: null } } catch (error) { - let errorMsg = error instanceof Error ? error.message : 'Unknown error' - - // 分析错误类型并提供更具体的建议 - if (errorMsg.includes('404')) { - errorMsg = `GitHub Copilot 访问被拒绝 (404)。请检查: -1. 您的 GitHub 账户是否有有效的 GitHub Copilot 订阅 -2. 访问 https://github.com/features/copilot 检查订阅状态 -3. 如果是组织账户,请确保组织已启用 Copilot 并且您有访问权限` - } else if (errorMsg.includes('401')) { - errorMsg = `GitHub OAuth token 无效或已过期 (401)。请重新登录授权并确保获取了正确的权限范围。` - } else if (errorMsg.includes('403')) { - errorMsg = `GitHub Copilot 访问被禁止 (403)。请检查: -1. 您的 GitHub Copilot 订阅是否有效且处于活跃状态 -2. 是否达到了 API 使用限制 -3. OAuth token 是否包含 'read:org' 权限范围 -4. 如果是组织账户,请确保组织已启用 Copilot 并且您有访问权限` - } else if (errorMsg.includes('fetch failed') || errorMsg.includes('network')) { - errorMsg = `网络连接失败。请检查: -1. 网络连接是否正常 -2. 代理设置是否正确 -3. 防火墙是否阻止了 GitHub API 访问` - } - return { isOk: false, - errorMsg + errorMsg: error instanceof Error ? error.message : 'Unknown error' } } } diff --git a/test/main/provider/githubCopilotDeviceFlow.test.ts b/test/main/provider/githubCopilotDeviceFlow.test.ts index ed82ff024..35e194af5 100644 --- a/test/main/provider/githubCopilotDeviceFlow.test.ts +++ b/test/main/provider/githubCopilotDeviceFlow.test.ts @@ -1,6 +1,11 @@ import { afterEach, describe, expect, it, vi } from 'vitest' -import { GitHubCopilotDeviceFlow } from '@/provider/auth/githubCopilotDeviceFlow' +import { + disposeGlobalGitHubCopilotDeviceFlow, + getGitHubCopilotToken, + getGlobalGitHubCopilotDeviceFlow +} from '@/provider/auth/githubCopilotDeviceFlow' +import { extractProviderFailureMetadata } from '@/provider/providerFailure' vi.mock('electron', () => ({ BrowserWindow: vi.fn(function BrowserWindow() {}), @@ -8,16 +13,47 @@ vi.mock('electron', () => ({ shell: { openExternal: vi.fn() } })) -describe('GitHubCopilotDeviceFlow cancellation', () => { +describe('GitHub Copilot token exchange', () => { afterEach(() => { vi.unstubAllGlobals() + vi.unstubAllEnvs() + disposeGlobalGitHubCopilotDeviceFlow() + vi.restoreAllMocks() }) - const createAuthenticatedFlow = () => { - const flow = new GitHubCopilotDeviceFlow({ clientId: 'client', scope: 'read:user' }) - ;(flow as unknown as { oauthToken: string }).oauthToken = 'oauth-token' - return flow - } + it.each([ + [undefined, undefined, 'Iv1.b507a08c87ecfe98'], + [' ', ' ', 'Iv1.b507a08c87ecfe98'], + [undefined, ' env-client ', 'env-client'], + [' custom-client ', 'env-client', 'custom-client'] + ])( + 'requests a device code with the resolved client (%s, %s)', + async (override, environment, expected) => { + vi.stubEnv('VITE_GITHUB_CLIENT_ID', environment) + const fetchMock = vi.fn().mockResolvedValue( + Response.json({ + device_code: 'device-code', + user_code: 'ABCD-EFGH', + verification_uri: 'https://github.com/login/device', + expires_in: 900, + interval: 5 + }) + ) + vi.stubGlobal('fetch', fetchMock) + const flow = getGlobalGitHubCopilotDeviceFlow(override) + vi.spyOn(flow as any, 'showUserCodeAndOpenBrowser').mockResolvedValue(undefined) + vi.spyOn(flow as any, 'pollForAccessToken').mockResolvedValue('oauth-token') + + await expect(flow.startDeviceFlow()).resolves.toBe('oauth-token') + + expect(fetchMock).toHaveBeenCalledWith( + 'https://github.com/login/device/code', + expect.objectContaining({ + body: JSON.stringify({ client_id: expected, scope: 'read:user read:org' }) + }) + ) + } + ) it('forwards the exact caller signal to the Copilot token exchange', async () => { const fetchMock = vi.fn().mockImplementation((_url: string, options?: RequestInit) => { @@ -29,11 +65,10 @@ describe('GitHubCopilotDeviceFlow cancellation', () => { }) }) vi.stubGlobal('fetch', fetchMock) - const flow = createAuthenticatedFlow() const controller = new AbortController() const reason = { source: 'memory-caller' } - const token = flow.getCopilotToken(controller.signal) + const token = getGitHubCopilotToken('oauth-token', controller.signal) await vi.waitFor(() => expect(fetchMock).toHaveBeenCalledOnce()) controller.abort(reason) @@ -47,12 +82,99 @@ describe('GitHubCopilotDeviceFlow cancellation', () => { it('does not start a token exchange for a pre-aborted request', async () => { const fetchMock = vi.fn() vi.stubGlobal('fetch', fetchMock) - const flow = createAuthenticatedFlow() const controller = new AbortController() const reason = new DOMException('Already cancelled', 'AbortError') controller.abort(reason) - await expect(flow.getCopilotToken(controller.signal)).rejects.toBe(reason) + await expect(getGitHubCopilotToken('oauth-token', controller.signal)).rejects.toBe(reason) + expect(fetchMock).not.toHaveBeenCalled() + }) + + it('exchanges the current OAuth credential using the GitHub token protocol', async () => { + const fetchMock = vi + .fn() + .mockResolvedValue(Response.json({ token: 'session-token', expires_at: 2_000_000_000 })) + vi.stubGlobal('fetch', fetchMock) + + await expect(getGitHubCopilotToken('oauth-token')).resolves.toEqual({ + token: 'session-token', + expires_at: 2_000_000_000 + }) + expect(fetchMock).toHaveBeenCalledWith( + 'https://api.github.com/copilot_internal/v2/token', + expect.objectContaining({ + headers: expect.objectContaining({ + Authorization: 'token oauth-token', + 'X-GitHub-Api-Version': '2025-04-01' + }) + }) + ) + }) + + it.each([ + {}, + { token: ' ', expires_at: 2_000_000_000 }, + { token: 'session\r\nsecret', expires_at: 2_000_000_000 }, + { token: 'session-token', expires_at: '2000000000' } + ])('rejects malformed successful token responses: %j', async (body) => { + vi.stubGlobal('fetch', vi.fn().mockResolvedValue(Response.json(body))) + + await expect(getGitHubCopilotToken('oauth-token')).rejects.toThrow( + 'Invalid GitHub Copilot token response' + ) + }) + + it('rejects invalid OAuth credentials before they can reach HTTP errors or logs', async () => { + const fetchMock = vi.fn() + vi.stubGlobal('fetch', fetchMock) + + await expect(getGitHubCopilotToken('oauth\r\nsecret')).rejects.toThrow( + 'No GitHub OAuth token available' + ) expect(fetchMock).not.toHaveBeenCalled() }) + + it('preserves token failure details and retry headers without exposing credentials', async () => { + vi.stubGlobal( + 'fetch', + vi.fn().mockResolvedValue( + Response.json( + { + error_details: { + code: 'not_authorized', + message: 'Denied oauth-token; Bearer session-secret; access_token="another-secret"' + }, + token: 'private-response-field' + }, + { + status: 403, + statusText: 'Forbidden', + headers: { 'x-github-request-id': 'ABCD:1234', 'retry-after': '3' } + } + ) + ) + ) + let failure: unknown + try { + await getGitHubCopilotToken('oauth-token') + } catch (error) { + failure = error + } + + expect(String(failure)).toContain('token exchange failed: 403 Forbidden') + expect(String(failure)).toContain('code=not_authorized; request_id=ABCD:1234') + for (const secret of [ + 'oauth-token', + 'session-secret', + 'another-secret', + 'private-response-field' + ]) { + expect(String(failure)).not.toContain(secret) + } + expect(extractProviderFailureMetadata(failure)).toEqual({ + statusCode: 403, + code: 'github_copilot_token_http_error', + retryHeaders: { 'retry-after': '3' } + }) + }) }) diff --git a/test/main/provider/githubCopilotOAuthService.test.ts b/test/main/provider/githubCopilotOAuthService.test.ts new file mode 100644 index 000000000..7b73d2e60 --- /dev/null +++ b/test/main/provider/githubCopilotOAuthService.test.ts @@ -0,0 +1,93 @@ +import { afterEach, describe, expect, it, vi } from 'vitest' +import { OAuthService } from '@/provider/auth' +import type { LLM_PROVIDER } from '@shared/types/provider' + +const mocks = vi.hoisted(() => ({ + startDeviceFlow: vi.fn(), + startLogin: vi.fn(), + exchangeCodeForToken: vi.fn() +})) + +vi.mock('@/provider/auth/githubCopilotDeviceFlow', async (importOriginal) => ({ + ...(await importOriginal()), + getGlobalGitHubCopilotDeviceFlow: () => ({ startDeviceFlow: mocks.startDeviceFlow }) +})) +vi.mock('@/provider/auth/githubCopilotOAuth', () => ({ + createGitHubCopilotOAuth: () => ({ + startLogin: mocks.startLogin, + exchangeCodeForToken: mocks.exchangeCodeForToken + }) +})) +vi.mock('@/provider/auth/openaiCodex', () => ({ + initializeGlobalOpenAICodexAuth: vi.fn() +})) +vi.mock('@/provider/auth/xaiGrok', () => ({ + initializeGlobalXaiGrokAuth: vi.fn() +})) + +describe('GitHub Copilot login validation', () => { + afterEach(() => { + vi.unstubAllGlobals() + vi.resetAllMocks() + }) + + const setup = () => { + const provider: LLM_PROVIDER = { + id: 'github-copilot', + name: 'GitHub Copilot', + apiType: 'github-copilot', + apiKey: 'saved-oauth-token', + baseUrl: 'https://api.githubcopilot.com', + enable: true + } + mocks.startDeviceFlow.mockResolvedValue('new-oauth-token') + mocks.startLogin.mockResolvedValue('auth-code') + mocks.exchangeCodeForToken.mockResolvedValue('new-oauth-token') + const setProviderById = vi.fn() + const service = new OAuthService({ getProviderById: () => provider, setProviderById }, vi.fn()) + return { provider, service, setProviderById } + } + + for (const method of ['startGitHubCopilotDeviceFlowLogin', 'startGitHubCopilotLogin'] as const) { + it(`${method} saves credentials only after Copilot accepts them`, async () => { + const { provider, service, setProviderById } = setup() + const fetchMock = vi.fn(async (_url: string) => { + expect(setProviderById).not.toHaveBeenCalled() + return Response.json({ token: 'copilot-session', expires_at: 2_000_000_000 }) + }) + vi.stubGlobal('fetch', fetchMock) + + await expect(service[method](provider.id)).resolves.toBe(true) + + expect(fetchMock).toHaveBeenCalledOnce() + expect(fetchMock.mock.calls[0][0]).toBe('https://api.github.com/copilot_internal/v2/token') + expect(setProviderById).toHaveBeenCalledWith(provider.id, { + ...provider, + apiKey: 'new-oauth-token' + }) + expect(provider.apiKey).toBe('saved-oauth-token') + }) + + it(`${method} surfaces Copilot rejection without replacing saved credentials`, async () => { + const { provider, service, setProviderById } = setup() + const fetchMock = vi.fn().mockResolvedValue( + Response.json( + { error_details: { message: 'Copilot access denied', code: 'not_authorized' } }, + { + status: 403, + statusText: 'Forbidden', + headers: { 'x-github-request-id': 'ABCD:1234' } + } + ) + ) + vi.stubGlobal('fetch', fetchMock) + + await expect(service[method](provider.id)).rejects.toThrow( + 'GitHub Copilot token exchange failed: 403 Forbidden - Copilot access denied; code=not_authorized; request_id=ABCD:1234' + ) + expect(fetchMock).toHaveBeenCalledOnce() + expect(setProviderById).not.toHaveBeenCalled() + expect(provider.apiKey).toBe('saved-oauth-token') + }) + } +}) diff --git a/test/main/provider/githubCopilotProvider.test.ts b/test/main/provider/githubCopilotProvider.test.ts index d073dae89..f9ac0fb4c 100644 --- a/test/main/provider/githubCopilotProvider.test.ts +++ b/test/main/provider/githubCopilotProvider.test.ts @@ -3,26 +3,20 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { GithubCopilotProvider } from '../../../src/main/provider/providers/githubCopilotProvider' import { extractProviderFailureMetadata } from '@/provider/providerFailure' -import { getGlobalGitHubCopilotDeviceFlow } from '../../../src/main/provider/auth/githubCopilotDeviceFlow' +import { getGitHubCopilotToken } from '../../../src/main/provider/auth/githubCopilotDeviceFlow' -vi.mock('../../../src/main/platform/proxy', () => ({ - proxyConfig: { - getProxyUrl: vi.fn().mockReturnValue(null) - } -})) - -vi.mock('../../../src/main/provider/auth/githubCopilotDeviceFlow', () => ({ - getGlobalGitHubCopilotDeviceFlow: vi.fn(() => ({ - getCopilotToken: vi.fn(), - checkExistingAuth: vi.fn() - })), - GitHubCopilotDeviceFlow: vi.fn() +vi.mock('../../../src/main/provider/auth/githubCopilotDeviceFlow', async (importOriginal) => ({ + ...(await importOriginal< + typeof import('../../../src/main/provider/auth/githubCopilotDeviceFlow') + >()), + getGitHubCopilotToken: vi.fn() })) describe('GithubCopilotProvider request timeout', () => { afterEach(() => { vi.useRealTimers() vi.unstubAllGlobals() + vi.resetAllMocks() }) it('does not promote catalog capabilities into provider facts', async () => { @@ -143,35 +137,32 @@ describe('GithubCopilotProvider request timeout', () => { ) }) - it('does not fall back to the provider API key after Device Flow is aborted', async () => { + it('does not retry a cancelled token exchange', async () => { const fetchMock = vi.fn() vi.stubGlobal('fetch', fetchMock) - const deviceFlow = { - getCopilotToken: vi.fn( - (signal?: AbortSignal) => - new Promise((_resolve, reject) => { - signal?.addEventListener('abort', () => reject(signal.reason), { once: true }) - }) - ) - } + vi.mocked(getGitHubCopilotToken).mockImplementationOnce( + (_oauthToken, signal) => + new Promise((_resolve, reject) => { + signal?.addEventListener('abort', () => reject(signal.reason), { once: true }) + }) + ) const provider = Object.create(GithubCopilotProvider.prototype) as any provider.provider = { id: 'github-copilot', name: 'GitHub Copilot', apiKey: 'fallback-oauth-token' } - provider.deviceFlow = deviceFlow provider.copilotToken = null provider.tokenExpiresAt = 0 const controller = new AbortController() const reason = new DOMException('Memory request aborted', 'AbortError') const token = provider.getCopilotToken(controller.signal) - await vi.waitFor(() => expect(deviceFlow.getCopilotToken).toHaveBeenCalledOnce()) + await vi.waitFor(() => expect(getGitHubCopilotToken).toHaveBeenCalledOnce()) controller.abort(reason) await expect(token).rejects.toBe(reason) - expect(deviceFlow.getCopilotToken).toHaveBeenCalledWith(controller.signal) + expect(getGitHubCopilotToken).toHaveBeenCalledWith('fallback-oauth-token', controller.signal) expect(fetchMock).not.toHaveBeenCalled() }) @@ -321,6 +312,60 @@ describe('GithubCopilotProvider request timeout', () => { ]) }) + it.each([true, false])( + 'uses the session token and Copilot client metadata (stream=%s)', + async (stream) => { + const fetchMock = vi + .fn() + .mockResolvedValue( + stream + ? new Response('data: [DONE]\n\n') + : Response.json({ choices: [{ message: { content: 'hello' } }] }) + ) + vi.stubGlobal('fetch', fetchMock) + vi.mocked(getGitHubCopilotToken).mockResolvedValueOnce({ + token: 'session-token', + expires_at: Date.now() / 1000 + 3600 + }) + const provider = Object.create(GithubCopilotProvider.prototype) as any + provider.provider = { + id: 'github-copilot', + apiKey: 'oauth-token', + baseUrl: 'https://api.githubcopilot.com' + } + provider.baseApiUrl = 'https://api.githubcopilot.com' + provider.providerSettings = { getModelConfig: vi.fn().mockReturnValue({}) } + + if (stream) { + for await (const _event of provider.coreStream( + [{ role: 'user', content: 'hello' }], + 'gpt-4o', + {}, + 0.7, + 1024, + [] + )) { + // Consume the stream to exercise the complete request lifecycle. + } + } else { + await provider.completions([{ role: 'user', content: 'hello' }], 'gpt-4o') + } + + expect(getGitHubCopilotToken).toHaveBeenCalledWith('oauth-token', undefined) + expect(fetchMock).toHaveBeenCalledWith( + 'https://api.githubcopilot.com/chat/completions', + expect.objectContaining({ + headers: expect.objectContaining({ + Authorization: 'Bearer session-token', + 'Editor-Version': 'vscode/1.115.0', + 'Editor-Plugin-Version': 'copilot-chat/0.44.0', + 'Copilot-Integration-Id': 'vscode-chat' + }) + }) + ) + } + ) + it('refreshes cached auth state when provider config changes', () => { const provider = Object.create(GithubCopilotProvider.prototype) as GithubCopilotProvider & { provider: Record @@ -329,7 +374,6 @@ describe('GithubCopilotProvider request timeout', () => { customModels: unknown[] copilotToken: string | null tokenExpiresAt: number - deviceFlow: unknown } provider.provider = { @@ -345,10 +389,6 @@ describe('GithubCopilotProvider request timeout', () => { provider.customModels = [] provider.copilotToken = 'cached-token' provider.tokenExpiresAt = 123 - provider.deviceFlow = { id: 'old-flow' } - - vi.mocked(getGlobalGitHubCopilotDeviceFlow).mockReturnValueOnce({ id: 'new-flow' } as any) - provider.updateConfig({ id: 'github-copilot', name: 'GitHub Copilot', @@ -358,9 +398,7 @@ describe('GithubCopilotProvider request timeout', () => { expect(provider.copilotToken).toBeNull() expect(provider.tokenExpiresAt).toBe(0) - expect(provider.deviceFlow).toEqual({ id: 'new-flow' }) expect(provider.provider.copilotClientId).toBe('new-client') - expect(getGlobalGitHubCopilotDeviceFlow).toHaveBeenCalledWith('new-client') }) it('preserves assistant tool calls and empty reasoning_content when formatting messages', () => { @@ -397,48 +435,60 @@ describe('GithubCopilotProvider request timeout', () => { ]) }) - it('preserves cached auth state when acquiring a new device flow fails', () => { - const provider = Object.create(GithubCopilotProvider.prototype) as GithubCopilotProvider & { - provider: Record - providerSettings: Pick - models: unknown[] - customModels: unknown[] - copilotToken: string | null - tokenExpiresAt: number - deviceFlow: unknown - } + it('reuses a valid session and refreshes it after expiry', async () => { + vi.useFakeTimers() + const provider = Object.create(GithubCopilotProvider.prototype) as any + provider.provider = { id: 'github-copilot', apiKey: 'oauth-token' } + vi.mocked(getGitHubCopilotToken) + .mockResolvedValueOnce({ token: 'first-session', expires_at: Date.now() / 1000 + 60 }) + .mockResolvedValueOnce({ token: 'second-session', expires_at: Date.now() / 1000 + 120 }) + + await expect(provider.check()).resolves.toEqual({ isOk: true, errorMsg: null }) + await expect(provider.check()).resolves.toEqual({ isOk: true, errorMsg: null }) + expect(getGitHubCopilotToken).toHaveBeenCalledOnce() + + await vi.advanceTimersByTimeAsync(60_000) + await expect(provider.check()).resolves.toEqual({ isOk: true, errorMsg: null }) + expect(getGitHubCopilotToken).toHaveBeenCalledTimes(2) + }) - provider.provider = { - id: 'github-copilot', - name: 'GitHub Copilot', - copilotClientId: 'old-client' - } + it('preserves saved credentials and the original error when token exchange fails', async () => { + const provider = Object.create(GithubCopilotProvider.prototype) as any + provider.provider = { id: 'github-copilot', apiKey: 'oauth-token', enable: true } + provider.fetchModels = vi.fn().mockResolvedValue([]) + provider.autoEnableModelsIfNeeded = vi.fn().mockResolvedValue(undefined) + const message = 'GitHub Copilot token exchange failed: 403 Forbidden - request_id=ABCD:1234' + vi.mocked(getGitHubCopilotToken).mockRejectedValueOnce(new Error(message)) + + await provider.init() + await expect(provider.check()).resolves.toEqual({ isOk: false, errorMsg: message }) + expect(provider.provider.apiKey).toBe('oauth-token') + expect(getGitHubCopilotToken).toHaveBeenCalledOnce() + }) + + it('does not cache an old account session after configuration changes during exchange', async () => { + const provider = Object.create(GithubCopilotProvider.prototype) as any + provider.provider = { id: 'github-copilot', apiKey: 'old-account' } provider.providerSettings = { getProviderModels: vi.fn(() => []), getCustomModels: vi.fn(() => []) } - provider.models = [] - provider.customModels = [] - provider.copilotToken = 'cached-token' - provider.tokenExpiresAt = 123 - provider.deviceFlow = { id: 'old-flow' } - - vi.mocked(getGlobalGitHubCopilotDeviceFlow).mockImplementationOnce(() => { - throw new Error('device flow init failed') + let finishExchange!: (value: { token: string; expires_at: number }) => void + vi.mocked(getGitHubCopilotToken).mockImplementationOnce(() => { + return new Promise((resolve) => { + finishExchange = resolve + }) + }) + const oldCheck = provider.check() + provider.updateConfig({ id: 'github-copilot', apiKey: 'new-account' }) + finishExchange({ token: 'old-session', expires_at: Date.now() / 1000 + 3600 }) + await oldCheck + vi.mocked(getGitHubCopilotToken).mockResolvedValueOnce({ + token: 'new-session', + expires_at: Date.now() / 1000 + 3600 }) - expect(() => - provider.updateConfig({ - id: 'github-copilot', - name: 'GitHub Copilot', - copilotClientId: 'new-client', - enable: true - } as any) - ).toThrow('device flow init failed') - - expect(provider.copilotToken).toBe('cached-token') - expect(provider.tokenExpiresAt).toBe(123) - expect(provider.deviceFlow).toEqual({ id: 'old-flow' }) - expect(provider.provider.copilotClientId).toBe('old-client') + await expect(provider.check()).resolves.toEqual({ isOk: true, errorMsg: null }) + expect(getGitHubCopilotToken).toHaveBeenLastCalledWith('new-account', undefined) }) }) diff --git a/test/renderer/components/GitHubCopilotOAuth.test.ts b/test/renderer/components/GitHubCopilotOAuth.test.ts index f07dac1ab..2a195887f 100644 --- a/test/renderer/components/GitHubCopilotOAuth.test.ts +++ b/test/renderer/components/GitHubCopilotOAuth.test.ts @@ -116,4 +116,24 @@ describe('GitHubCopilotOAuth', () => { expect(oauthClient.startGitHubCopilotLogin).toHaveBeenCalledWith('github-copilot') expect(wrapper.emitted('auth-success')).toHaveLength(2) }) + + it.each([ + ['startGitHubCopilotDeviceFlowLogin', 0], + ['startGitHubCopilotLogin', 1] + ] as const)( + 'shows a Copilot rejection from %s without emitting login success', + async (method, buttonIndex) => { + const { wrapper, oauthClient } = await setup() + const message = 'GitHub Copilot token exchange failed: 403 Forbidden - request_id=ABCD:1234' + oauthClient[method].mockRejectedValueOnce(new Error(message)) + + await wrapper.findAll('button')[buttonIndex].trigger('click') + await flushPromises() + + expect(wrapper.text()).toContain(message) + expect(wrapper.emitted('auth-error')).toEqual([[message]]) + expect(wrapper.emitted('auth-success')).toBeUndefined() + wrapper.unmount() + } + ) }) From 47851642547496fc03fb725c35c835fee134c8e6 Mon Sep 17 00:00:00 2001 From: zerob13 Date: Mon, 12 Oct 2026 15:10:15 +0800 Subject: [PATCH 6/9] fix(provider): update Codex media support --- docs/features/provider-runtime/spec.md | 15 +- resources/acp-registry/registry.json | 154 +- resources/model-db/providers.json | 9181 +++++++++-------- src/main/cli/computeService.ts | 20 +- src/main/provider/auth/openaiCodex/index.ts | 33 +- src/main/provider/index.ts | 6 +- src/main/provider/modelConfig.ts | 9 +- src/main/provider/providers/aiSdkProvider.ts | 24 +- test/main/cli/computeService.test.ts | 81 + .../provider/aiSdkProviderFactory.test.ts | 113 +- test/main/provider/auth/openaiCodex.test.ts | 28 + .../main/provider/openaiCodexProvider.test.ts | 28 +- .../provider/providerDbModelConfig.test.ts | 30 + test/main/provider/providerRuntime.test.ts | 15 + 14 files changed, 5127 insertions(+), 4610 deletions(-) diff --git a/docs/features/provider-runtime/spec.md b/docs/features/provider-runtime/spec.md index c56e1fc8c..6f58b0018 100644 --- a/docs/features/provider-runtime/spec.md +++ b/docs/features/provider-runtime/spec.md @@ -99,12 +99,19 @@ and [GPT OSS 120B model ID](https://fireworks.ai/models/fireworks/gpt-oss-120b). ## OpenAI Codex `openai-codex` is separate from standard `openai`: distinct provider ID, runtime kind, credential store, -routes and request adapter. Current recommended catalog includes `gpt-5.5`, `gpt-5.6-sol`, -`gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.3-codex-spark` and `gpt-image-2` -when provider-db metadata contains them; connection check uses `gpt-5.6-luna`. +routes and request adapter. Current recommended catalog includes `gpt-6.1-sol`, `gpt-6-astra`, +`gpt-6-sol`, `gpt-6-luna`, `gpt-5.5`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, +`gpt-image-2.5-sunburst`, `gpt-image-2.5-flare` and `gpt-image-2`. Chat models require provider-db +metadata. Curated image models remain listed when metadata is missing and use the OpenAI image-route +compatibility fallback; explicit user model settings retain precedence. Connection check uses +`gpt-5.6-luna`. GPT-5.4, GPT-5.4 mini and Codex Spark are omitted following their +[Codex retirement](https://learn.chatgpt.com/docs/models#deprecated-codex-models). Codex requests include required instructions and backend routing headers, preserve streaming/tool/reasoning -behavior, and surface entitlement failure without logging token or account identifiers. Image generation +behavior, and surface entitlement failure without logging token or account identifiers. Rejected refresh +tokens retain their HTTP failure metadata and require sign-in again; media CLI calls return +`authentication_failed` with `retriable: false`. Other media provider failures expose only normalized +HTTP status and retryability. Image generation uses the same OAuth credential path with `/images/generations`; Responses-only body normalization does not apply to image requests. The image-generation projection preserves shared OpenAI image settings but disables vision input because the standalone route accepts only text prompts. Background provider-db refresh skips diff --git a/resources/acp-registry/registry.json b/resources/acp-registry/registry.json index 17ff4cdf4..fe3f56108 100644 --- a/resources/acp-registry/registry.json +++ b/resources/acp-registry/registry.json @@ -159,7 +159,7 @@ { "id": "claude-acp", "name": "Claude Agent", - "version": "0.88.0", + "version": "0.89.1", "description": "ACP wrapper for Anthropic's Claude", "repository": "https://github.com/agentclientprotocol/claude-agent-acp", "authors": [ @@ -171,7 +171,7 @@ "license_url": "https://github.com/agentclientprotocol/claude-agent-acp/blob/main/LICENSE", "distribution": { "npx": { - "package": "@agentclientprotocol/claude-agent-acp@0.88.0" + "package": "@agentclientprotocol/claude-agent-acp@0.89.1" } }, "icon": "https://cdn.agentclientprotocol.com/registry/v1/latest/claude-acp.svg" @@ -201,7 +201,7 @@ { "id": "codebuddy-code", "name": "Codebuddy Code", - "version": "2.163.0", + "version": "2.164.0", "description": "Tencent Cloud's official intelligent coding tool", "website": "https://www.codebuddy.cn/cli/", "authors": [ @@ -211,7 +211,7 @@ "license_url": "https://www.codebuddy.cn/agreement/", "distribution": { "npx": { - "package": "@tencent-ai/codebuddy-code@2.163.0", + "package": "@tencent-ai/codebuddy-code@2.164.0", "args": [ "--acp" ] @@ -222,7 +222,7 @@ { "id": "codex-acp", "name": "Codex", - "version": "2.1.1", + "version": "2.2.2", "description": "ACP adapter for OpenAI's coding assistant", "repository": "https://github.com/agentclientprotocol/codex-acp", "authors": [ @@ -234,7 +234,7 @@ "license_url": "https://github.com/agentclientprotocol/codex-acp/blob/main/LICENSE", "distribution": { "npx": { - "package": "@agentclientprotocol/codex-acp@2.1.1" + "package": "@agentclientprotocol/codex-acp@2.2.2" } }, "icon": "https://cdn.agentclientprotocol.com/registry/v1/latest/codex-acp.svg" @@ -554,7 +554,7 @@ { "id": "dirac", "name": "Dirac", - "version": "0.5.18", + "version": "0.5.19", "description": "Reduces API costs by more than 50%, produces better and faster work. Uses Hash anchored parallel edits, AST manipulation and a whole lot of neat optimizations. Fully Open Source.", "repository": "https://github.com/dirac-run/dirac", "website": "https://dirac.run", @@ -566,7 +566,7 @@ "icon": "https://cdn.agentclientprotocol.com/registry/v1/latest/dirac.svg", "distribution": { "npx": { - "package": "dirac-cli@0.5.18", + "package": "dirac-cli@0.5.19", "args": [ "--acp" ] @@ -576,7 +576,7 @@ { "id": "factory-droid", "name": "Factory Droid", - "version": "0.237.0", + "version": "0.238.0", "description": "Factory Droid - AI coding agent powered by Factory AI", "website": "https://factory.ai/product/cli", "authors": [ @@ -586,7 +586,7 @@ "license_url": "https://factory.ai/legal/terms", "distribution": { "npx": { - "package": "droid@0.237.0", + "package": "droid@0.238.0", "args": [ "exec", "--output-format", @@ -649,8 +649,8 @@ }, { "id": "github-copilot-cli", - "name": "GitHub Copilot", - "version": "1.0.94", + "name": "Copilot", + "version": "1.0.95", "description": "GitHub's AI pair programmer", "repository": "https://github.com/github/copilot-cli", "website": "https://github.com/features/copilot/cli/", @@ -661,7 +661,7 @@ "license_url": "https://github.com/github/copilot-cli/blob/main/LICENSE.md", "distribution": { "npx": { - "package": "@github/copilot@1.0.94", + "package": "@github/copilot@1.0.95", "args": [ "--acp" ] @@ -748,7 +748,7 @@ { "id": "grok-build", "name": "Grok Build", - "version": "1.0.50", + "version": "1.0.52", "description": "xAI's coding agent and CLI", "website": "https://x.ai/cli", "authors": [ @@ -758,7 +758,7 @@ "license_url": "https://x.ai/legal/terms-of-service", "distribution": { "npx": { - "package": "@xai-official/grok@1.0.50", + "package": "@xai-official/grok@1.0.52", "args": [ "agent", "stdio" @@ -770,7 +770,7 @@ { "id": "harn", "name": "Harn", - "version": "0.10.157", + "version": "0.10.163", "description": "Harn runs .harn agent pipelines as a native ACP coding agent over stdio.", "repository": "https://github.com/burin-labs/harn", "website": "https://harnlang.com", @@ -782,49 +782,49 @@ "distribution": { "binary": { "darwin-aarch64": { - "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.157/harn-aarch64-apple-darwin.tar.gz", + "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.163/harn-aarch64-apple-darwin.tar.gz", "cmd": "./harn", "args": [ "serve", "acp" ], - "sha256": "c1a7d8e0a6f4e4b83d2e03f3455140cd7eaeff8848566a75a6371f7f834659a4" + "sha256": "659693a735cf8bd1dceb04dc660433ebe49a5974f4be0dbf322ac95fa92ff884" }, "darwin-x86_64": { - "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.157/harn-x86_64-apple-darwin.tar.gz", + "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.163/harn-x86_64-apple-darwin.tar.gz", "cmd": "./harn", "args": [ "serve", "acp" ], - "sha256": "1fd8b4723ba94ef6de3ff61b39e33c283b6827fa658c40f1de9777ee4090b9ad" + "sha256": "406b1416f80764fad8497074078593cbf26577531684d3d62fd59008db6a8ffc" }, "linux-aarch64": { - "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.157/harn-aarch64-unknown-linux-gnu.tar.gz", + "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.163/harn-aarch64-unknown-linux-gnu.tar.gz", "cmd": "./harn", "args": [ "serve", "acp" ], - "sha256": "f2aba480171f4bf98bdac5d0843e24ba90f018fb590f024f6969246be4d8ee64" + "sha256": "89126de50317ad5fda5893c13862f0683f1f81c7b57f682033bc3e19c75e8c56" }, "linux-x86_64": { - "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.157/harn-x86_64-unknown-linux-gnu.tar.gz", + "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.163/harn-x86_64-unknown-linux-gnu.tar.gz", "cmd": "./harn", "args": [ "serve", "acp" ], - "sha256": "56d0053277f44b88e0969d06d4f2a419add3a342bb0c1ee958775645d280a7c5" + "sha256": "e778c31058464c46ab7e9d5d6d9f6cab87a14cb106781817d74ef2eb7f2f15ea" }, "windows-x86_64": { - "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.157/harn-x86_64-pc-windows-msvc.zip", + "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.163/harn-x86_64-pc-windows-msvc.zip", "cmd": "harn.exe", "args": [ "serve", "acp" ], - "sha256": "e4e202f862d8f141bd559ca56cc6ab1b31fedb32d49dfabc0da92e3016542263" + "sha256": "da2cbf6838b417337be8eefb74d44f0bbcd2e1a99958aa0f02037c8339582b8e" } } }, @@ -957,7 +957,7 @@ { "id": "kimchi", "name": "Kimchi", - "version": "1.7.2", + "version": "1.9.1", "description": "Coding agent powered by multi-model orchestration", "repository": "https://github.com/getkimchi/kimchi", "website": "https://kimchi.dev", @@ -969,8 +969,8 @@ "distribution": { "binary": { "darwin-aarch64": { - "archive": "https://github.com/getkimchi/kimchi/releases/download/v1.7.2/kimchi_darwin_arm64.tar.gz", - "sha256": "2c33ed15c215c5bec5ee3fa598e8a370278a6ecdac6dd3fdb6651ee1ef362eb1", + "archive": "https://github.com/getkimchi/kimchi/releases/download/v1.9.1/kimchi_darwin_arm64.tar.gz", + "sha256": "989f30c77701a2a8497d6ac0a71335a6d035a9b1345ff7ec63e5796ada04dbd8", "cmd": "./bin/kimchi", "args": [ "--mode", @@ -978,8 +978,8 @@ ] }, "darwin-x86_64": { - "archive": "https://github.com/getkimchi/kimchi/releases/download/v1.7.2/kimchi_darwin_amd64.tar.gz", - "sha256": "79c737b9bdcd973cb7809f27badbe9bbf0ac862c96023a70a79966cfbfa6d28d", + "archive": "https://github.com/getkimchi/kimchi/releases/download/v1.9.1/kimchi_darwin_amd64.tar.gz", + "sha256": "f459a29a237c690f4444913c72643cc5c3092788fef86077335f7bafcf027eef", "cmd": "./bin/kimchi", "args": [ "--mode", @@ -987,8 +987,8 @@ ] }, "linux-aarch64": { - "archive": "https://github.com/getkimchi/kimchi/releases/download/v1.7.2/kimchi_linux_arm64.tar.gz", - "sha256": "ddcce90ef9be5692d34cc36a86c014cad78294c9dae96433a6c27fd619ce5613", + "archive": "https://github.com/getkimchi/kimchi/releases/download/v1.9.1/kimchi_linux_arm64.tar.gz", + "sha256": "32e190f5de1b27b0377f39ba35ed3290b43b6dae0688d39a983702b06163b01d", "cmd": "./bin/kimchi", "args": [ "--mode", @@ -996,8 +996,8 @@ ] }, "linux-x86_64": { - "archive": "https://github.com/getkimchi/kimchi/releases/download/v1.7.2/kimchi_linux_amd64.tar.gz", - "sha256": "8de9162966343551e7d77b2131db222cb15c263e803dbea7c59397d297ed23e7", + "archive": "https://github.com/getkimchi/kimchi/releases/download/v1.9.1/kimchi_linux_amd64.tar.gz", + "sha256": "75698947892c1cb03d91dd0362eff739d9a4135eb11b2fbd6a71193cce7d16a6", "cmd": "./bin/kimchi", "args": [ "--mode", @@ -1005,8 +1005,8 @@ ] }, "windows-x86_64": { - "archive": "https://github.com/getkimchi/kimchi/releases/download/v1.7.2/kimchi_windows_amd64.zip", - "sha256": "f6cfd6f768b3841a06a3235728ac6d91e653f219bcebbf0296b24edc93602ebe", + "archive": "https://github.com/getkimchi/kimchi/releases/download/v1.9.1/kimchi_windows_amd64.zip", + "sha256": "619141eec481700654651b5157f547fb57092f0079d6aef4841e142bb28703c2", "cmd": "./bin/kimchi.exe", "args": [ "--mode", @@ -1120,7 +1120,7 @@ { "id": "mistral-vibe", "name": "Mistral Vibe", - "version": "2.26.0", + "version": "2.26.1", "description": "Mistral's open-source coding assistant", "repository": "https://github.com/mistralai/mistral-vibe", "website": "https://mistral.ai/products/vibe", @@ -1133,29 +1133,29 @@ "distribution": { "binary": { "darwin-aarch64": { - "archive": "https://github.com/mistralai/mistral-vibe/releases/download/v2.26.0/vibe-acp-darwin-aarch64-2.26.0.tar.gz", + "archive": "https://github.com/mistralai/mistral-vibe/releases/download/v2.26.1/vibe-acp-darwin-aarch64-2.26.1.tar.gz", "cmd": "./vibe-acp", - "sha256": "a7830f89519b8744b059a8ef6538f08b7d04dfab4a208f605b4cc7adde974e9b" + "sha256": "4035a97f3bf99d91589ae4b5399438fb417f6b72511a995c7c363ec4b468f10a" }, "darwin-x86_64": { - "archive": "https://github.com/mistralai/mistral-vibe/releases/download/v2.26.0/vibe-acp-darwin-x86_64-2.26.0.tar.gz", + "archive": "https://github.com/mistralai/mistral-vibe/releases/download/v2.26.1/vibe-acp-darwin-x86_64-2.26.1.tar.gz", "cmd": "./vibe-acp", - "sha256": "f80393f1fa8032770e53e7ccb96c2695bff303c3f6515b0d136ca77d0d5eec86" + "sha256": "3acfc454ffc248826a05333e1cb2467c465308639bbba6725b47384dc9e8f757" }, "linux-aarch64": { - "archive": "https://github.com/mistralai/mistral-vibe/releases/download/v2.26.0/vibe-acp-linux-aarch64-2.26.0.tar.gz", + "archive": "https://github.com/mistralai/mistral-vibe/releases/download/v2.26.1/vibe-acp-linux-aarch64-2.26.1.tar.gz", "cmd": "./vibe-acp", - "sha256": "1453148ed6b6bcf33cda02bec01db8b5cae4b567230c632bcdc627f7e82e2ff0" + "sha256": "147ce53d0d185148ac269e23ff285eb087167077ba00d7c9ff41492c647ad2c6" }, "linux-x86_64": { - "archive": "https://github.com/mistralai/mistral-vibe/releases/download/v2.26.0/vibe-acp-linux-x86_64-2.26.0.tar.gz", + "archive": "https://github.com/mistralai/mistral-vibe/releases/download/v2.26.1/vibe-acp-linux-x86_64-2.26.1.tar.gz", "cmd": "./vibe-acp", - "sha256": "a429760edc3bd51d0acf4a8171f767a5d3a6989074e09303c748214883e55d04" + "sha256": "c8a018ca7d02eed5cebf291f6bcce1744e44323ff774b1c3fceac13794a95634" }, "windows-x86_64": { - "archive": "https://github.com/mistralai/mistral-vibe/releases/download/v2.26.0/vibe-acp-windows-x86_64-2.26.0.zip", + "archive": "https://github.com/mistralai/mistral-vibe/releases/download/v2.26.1/vibe-acp-windows-x86_64-2.26.1.zip", "cmd": "./vibe-acp.exe", - "sha256": "7111916a2d7085f922286823fcfe03a837f3e9989af5fb507f4e7c74273edbd2" + "sha256": "fd192698e396470f478adda5ce57cd8fd58927a2cd5e35ec1055c7c55089d370" } } } @@ -1185,7 +1185,7 @@ { "id": "opencode", "name": "OpenCode", - "version": "1.18.35", + "version": "1.19.0", "description": "The open source coding agent", "repository": "https://github.com/anomalyco/opencode", "website": "https://opencode.ai", @@ -1198,52 +1198,52 @@ "distribution": { "binary": { "darwin-aarch64": { - "archive": "https://github.com/anomalyco/opencode/releases/download/v1.18.35/opencode-darwin-arm64.zip", + "archive": "https://github.com/anomalyco/opencode/releases/download/v1.19.0/opencode-darwin-arm64.zip", "cmd": "./opencode", "args": [ "acp" ], - "sha256": "80b05124357a77cd57945bfde36082a028e829c198d222d5e146617f49a2c4b7" + "sha256": "0d5f511948d6fbfedf9bb16753c0ac42613dcc8de75d9deb7e8d0cf584c8fba6" }, "darwin-x86_64": { - "archive": "https://github.com/anomalyco/opencode/releases/download/v1.18.35/opencode-darwin-x64.zip", + "archive": "https://github.com/anomalyco/opencode/releases/download/v1.19.0/opencode-darwin-x64.zip", "cmd": "./opencode", "args": [ "acp" ], - "sha256": "8127d69e8e94d7adc496e910435f2f73856d87d456e988d3a947f250c95c1be2" + "sha256": "515380b03f3410f2178c8c1c7ba6d1e9556a3bdee2a01d114e7b1681952131a0" }, "linux-aarch64": { - "archive": "https://github.com/anomalyco/opencode/releases/download/v1.18.35/opencode-linux-arm64.tar.gz", + "archive": "https://github.com/anomalyco/opencode/releases/download/v1.19.0/opencode-linux-arm64.tar.gz", "cmd": "./opencode", "args": [ "acp" ], - "sha256": "f7f2ba59ee8aa94d388f9696575a32d20e71c2ee48def9f80fc693a60fec6c72" + "sha256": "e9841d43d3e1a8f36ed2691592d3b8b4fb097e606c8b559a277a1b845840e26b" }, "linux-x86_64": { - "archive": "https://github.com/anomalyco/opencode/releases/download/v1.18.35/opencode-linux-x64.tar.gz", + "archive": "https://github.com/anomalyco/opencode/releases/download/v1.19.0/opencode-linux-x64.tar.gz", "cmd": "./opencode", "args": [ "acp" ], - "sha256": "c8f888b451f5494a18f858fffb0e0b68f4e4baa9c241761c5f206884f0fa640d" + "sha256": "7bb9e61ad6feacf2e89c10a6a2c1840e3de4220bb50ba1fc7110f31806076aec" }, "windows-aarch64": { - "archive": "https://github.com/anomalyco/opencode/releases/download/v1.18.35/opencode-windows-arm64.zip", + "archive": "https://github.com/anomalyco/opencode/releases/download/v1.19.0/opencode-windows-arm64.zip", "cmd": "./opencode", "args": [ "acp" ], - "sha256": "3c144f54fea5d56afb00174fd3134709803a7bb6ce990963044831b671bd9882" + "sha256": "cfb6f1d40c4596613d2d40e34c48500da7b873f98f7458d3d4ea11136bf174f6" }, "windows-x86_64": { - "archive": "https://github.com/anomalyco/opencode/releases/download/v1.18.35/opencode-windows-x64.zip", + "archive": "https://github.com/anomalyco/opencode/releases/download/v1.19.0/opencode-windows-x64.zip", "cmd": "./opencode.exe", "args": [ "acp" ], - "sha256": "c90d248cca75e42fd15422a29b5f83a1b30c441af83565635d6b2682adc58dd1" + "sha256": "17108e9448c4fdad48eb8714c4ed6f5dfc9cf86c2eb8f2ce5d02043fef806eb5" } } } @@ -1356,7 +1356,7 @@ { "id": "qwen-code", "name": "Qwen Code", - "version": "0.25.0", + "version": "0.25.1", "description": "Alibaba's Qwen coding assistant", "repository": "https://github.com/QwenLM/qwen-code", "website": "https://qwenlm.github.io/qwen-code-docs/en/users/overview", @@ -1367,7 +1367,7 @@ "license_url": "https://github.com/QwenLM/qwen-code/blob/main/LICENSE", "distribution": { "npx": { - "package": "@qwen-code/qwen-code@0.25.0", + "package": "@qwen-code/qwen-code@0.25.1", "args": [ "--acp", "--experimental-skills" @@ -1379,7 +1379,7 @@ { "id": "sigit", "name": "siGit Code", - "version": "1.6.5", + "version": "1.6.7", "description": "Local-first coding agent. Runs entirely on your machine with optional on-device LLM inference via Onde.", "repository": "https://github.com/getsigit/sigit", "website": "https://github.com/getsigit/sigit", @@ -1391,38 +1391,38 @@ "distribution": { "binary": { "darwin-aarch64": { - "archive": "https://github.com/getsigit/sigit/releases/download/v1.6.5/sigit-macos-arm64.tar.gz", + "archive": "https://github.com/getsigit/sigit/releases/download/v1.6.7/sigit-macos-arm64.tar.gz", "cmd": "./sigit", - "sha256": "af766810f6f7ed6e410c9bb77323127681fd76b8f0e25b98aa3cba3a3f235b17" + "sha256": "cd78cb6e603241181d80be58ed5ebb20703d18799eea00fb65a7f73c2f3b346f" }, "darwin-x86_64": { - "archive": "https://github.com/getsigit/sigit/releases/download/v1.6.5/sigit-macos-amd64.tar.gz", + "archive": "https://github.com/getsigit/sigit/releases/download/v1.6.7/sigit-macos-amd64.tar.gz", "cmd": "./sigit", - "sha256": "4014a8e4898e7d61038fcd154e72069c06d657e82a201c8ad966485a24279fdb" + "sha256": "5d3bab7c52c77db769dbcf0669c29c9fd3a9d13178d19dde6f60556a018ef90f" }, "linux-aarch64": { - "archive": "https://github.com/getsigit/sigit/releases/download/v1.6.5/sigit-linux-arm64", + "archive": "https://github.com/getsigit/sigit/releases/download/v1.6.7/sigit-linux-arm64", "cmd": "./sigit-linux-arm64", - "sha256": "e2dbe4405fe80a297deae84f9ce2a6f861a3b4090259f32fc641fdcb394a8b0c" + "sha256": "66b01b0984fb3879a2a0eed7a04ee8801001f442226ef4473ca1d266691af398" }, "linux-x86_64": { - "archive": "https://github.com/getsigit/sigit/releases/download/v1.6.5/sigit-linux-amd64", + "archive": "https://github.com/getsigit/sigit/releases/download/v1.6.7/sigit-linux-amd64", "cmd": "./sigit-linux-amd64", - "sha256": "122e06e27573ce630fb644c73f925d1c77282567d798ff13c7fc91a247923991" + "sha256": "096275cb02ab2270a2a02e8248163e58f53ec91831a17ffbf675b72aac5dc845" }, "windows-aarch64": { - "archive": "https://github.com/getsigit/sigit/releases/download/v1.6.5/sigit-win-arm64.exe", + "archive": "https://github.com/getsigit/sigit/releases/download/v1.6.7/sigit-win-arm64.exe", "cmd": "./sigit-win-arm64.exe", - "sha256": "e89f6fe4b3af7105d22ebaa0c49b5e8715cdf074c343b68d5d61d5fbf96f20fa" + "sha256": "34a0f1b31167f94f27260923347e564c9d6d4f20a94b6542daddc4625565d39e" }, "windows-x86_64": { - "archive": "https://github.com/getsigit/sigit/releases/download/v1.6.5/sigit-win-amd64.exe", + "archive": "https://github.com/getsigit/sigit/releases/download/v1.6.7/sigit-win-amd64.exe", "cmd": "./sigit-win-amd64.exe", - "sha256": "e659b8b178dd3063c7ca30dae8e62e7db0f60f3017e767f517cf2768bfb0a536" + "sha256": "d5791e31fd4e76bb44aec8ce03c91a536e4d694f045abb14399b14fbe9f32361" } }, "npx": { - "package": "@smbcloud/sigit@1.6.5" + "package": "@smbcloud/sigit@1.6.7" } }, "icon": "https://cdn.agentclientprotocol.com/registry/v1/latest/sigit.svg" diff --git a/resources/model-db/providers.json b/resources/model-db/providers.json index 6a99e25c4..4144b5361 100644 --- a/resources/model-db/providers.json +++ b/resources/model-db/providers.json @@ -666,6 +666,34 @@ "last_updated": "2026-05-21", "type": "chat" }, + { + "id": "Qwen/Qwen3-VL-30B-A3B-Instruct", + "name": "Qwen3 VL 30B A3B Instruct", + "display_name": "Qwen3 VL 30B A3B Instruct", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 32768 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": true, + "release_date": "2025-10-04", + "last_updated": "2025-10-04", + "type": "chat" + }, { "id": "Qwen/Qwen3.8-Max", "name": "Qwen3.8 Max", @@ -10586,46 +10614,6 @@ "last_updated": "2026-08-03", "type": "chat" }, - { - "id": "deepseek-v3-2", - "name": "DeepSeek V3.2", - "display_name": "DeepSeek V3.2", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 128000, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "effort_options": [ - "none", - "low", - "medium", - "high", - "max" - ] - } - }, - "attachment": false, - "open_weights": true, - "knowledge": "2024-07", - "release_date": "2025-12-01", - "last_updated": "2025-12-01", - "type": "chat" - }, { "id": "minimax-m2-7-highspeed", "name": "MiniMax M2.7 Highspeed", @@ -10683,46 +10671,6 @@ "last_updated": "2026-04-22", "type": "chat" }, - { - "id": "qwen3-max", - "name": "Qwen3 Max", - "display_name": "Qwen3 Max", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 256000, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-09-23", - "last_updated": "2025-09-23", - "type": "chat" - }, { "id": "seed-2-0-pro", "name": "Seed 2.0 Pro", @@ -12243,46 +12191,6 @@ "last_updated": "2026-07-09", "type": "chat" }, - { - "id": "qwen3-6-max-preview", - "name": "Qwen3.6 Max Preview", - "display_name": "Qwen3.6 Max Preview", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 256000, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "effort_options": [ - "none", - "low", - "medium", - "high", - "max" - ] - } - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2026-04-20", - "last_updated": "2026-04-20", - "type": "chat" - }, { "id": "step-3-7-flash", "name": "Step 3.7 Flash", @@ -12433,57 +12341,6 @@ "release_date": "2026-04-02", "last_updated": "2026-06-12", "type": "chat" - }, - { - "id": "deepseek-v4-flash", - "name": "DeepSeek V4 Flash", - "display_name": "DeepSeek V4 Flash", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 393216 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": true, - "mode": "effort", - "effort": "high", - "effort_options": [ - "low", - "high", - "max" - ], - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "notes": [ - "The DeepSeek API maps medium and xhigh to high for V4 models; effort_options lists distinct model-effective levels." - ] - } - }, - "attachment": false, - "open_weights": true, - "knowledge": "2025-05", - "release_date": "2026-04-24", - "last_updated": "2026-06-12", - "type": "chat" } ] }, @@ -26726,14 +26583,15 @@ "context": 4096, "output": 3686 }, + "temperature": true, "tool_call": false, "reasoning": { "supported": false }, "attachment": false, "open_weights": true, - "release_date": "2025-08-08", - "last_updated": "2025-08-08", + "release_date": "2023-08-10", + "last_updated": "2023-08-10", "type": "chat" }, { @@ -28082,6 +27940,7 @@ "context": 262144, "output": 32768 }, + "temperature": true, "tool_call": true, "reasoning": { "supported": true @@ -28092,7 +27951,7 @@ } }, "attachment": false, - "open_weights": false, + "open_weights": true, "release_date": "2026-07-23", "last_updated": "2026-07-23", "type": "chat" @@ -28152,6 +28011,7 @@ "context": 262144, "output": 32768 }, + "temperature": true, "tool_call": true, "reasoning": { "supported": true, @@ -28169,8 +28029,8 @@ }, "attachment": true, "open_weights": true, - "release_date": "2026-09-09", - "last_updated": "2026-09-09", + "release_date": "2026-09-10", + "last_updated": "2026-09-10", "type": "chat" }, { @@ -28189,6 +28049,7 @@ "context": 262144, "output": 32768 }, + "temperature": true, "tool_call": true, "reasoning": { "supported": true, @@ -28207,7 +28068,7 @@ } }, "attachment": false, - "open_weights": false, + "open_weights": true, "release_date": "2026-07-23", "last_updated": "2026-07-23", "type": "chat" @@ -28447,14 +28308,15 @@ "context": 256000, "output": 8192 }, + "temperature": true, "tool_call": true, "reasoning": { "supported": false }, "attachment": false, "open_weights": true, - "release_date": "2024-01-01", - "last_updated": "2025-07-01", + "release_date": "2025-07-11", + "last_updated": "2025-07-11", "type": "chat" }, { @@ -35479,14 +35341,15 @@ "context": 65536, "output": 8192 }, + "temperature": true, "tool_call": false, "reasoning": { "supported": false }, "attachment": true, "open_weights": true, - "release_date": "2025-04-15", - "last_updated": "2025-04-15", + "release_date": "2024-04-15", + "last_updated": "2024-04-15", "type": "chat" }, { @@ -37894,46 +37757,6 @@ "last_updated": "2025-10-29", "type": "chat" }, - { - "id": "glm-5-3-flash", - "name": "GLM-5.3-Flash", - "display_name": "GLM-5.3-Flash", - "modalities": { - "input": [ - "text", - "image", - "video", - "pdf" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1048576, - "output": 131072 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "effort_options": [ - "low", - "high", - "max" - ] - } - }, - "attachment": true, - "open_weights": true, - "release_date": "2026-08-26", - "last_updated": "2026-08-26", - "type": "chat" - }, { "id": "kimi-k3", "name": "Kimi K3", @@ -40771,6 +40594,286 @@ "last_updated": "2025-09-29", "type": "chat" }, + { + "id": "anthropic/claude-opus-5-5", + "name": "Claude Opus 5.5", + "display_name": "Claude Opus 5.5", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-06", + "release_date": "2026-09-22", + "last_updated": "2026-09-22", + "type": "chat" + }, + { + "id": "anthropic/claude-fable-5-1", + "name": "Claude Fable 5.1", + "display_name": "Claude Fable 5.1", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "default_enabled": true, + "mode": "effort", + "effort": "high", + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "interleaved": true, + "summaries": true, + "visibility": "omitted", + "continuation": [ + "thinking_blocks" + ], + "notes": [ + "Adaptive thinking is always on for Claude Fable 5 and Claude Mythos 5; thinking.type = \"disabled\" is rejected.", + "Manual budget_tokens requests return 400 on Claude Fable 5 and Claude Mythos 5.", + "thinking.display defaults to omitted; set display to summarized to receive readable thinking summaries." + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-06", + "release_date": "2026-09-01", + "last_updated": "2026-09-01", + "type": "chat" + }, + { + "id": "anthropic/claude-opus-5", + "name": "Claude Opus 5", + "display_name": "Claude Opus 5", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "type": "chat" + }, + { + "id": "anthropic/claude-fable-5", + "name": "Claude Fable 5", + "display_name": "Claude Fable 5", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "default_enabled": true, + "mode": "effort", + "effort": "high", + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "interleaved": true, + "summaries": true, + "visibility": "omitted", + "continuation": [ + "thinking_blocks" + ], + "notes": [ + "Adaptive thinking is always on for Claude Fable 5 and Claude Mythos 5; thinking.type = \"disabled\" is rejected.", + "Manual budget_tokens requests return 400 on Claude Fable 5 and Claude Mythos 5.", + "thinking.display defaults to omitted; set display to summarized to receive readable thinking summaries." + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-01-31", + "release_date": "2026-06-09", + "last_updated": "2026-06-09", + "type": "chat" + }, + { + "id": "anthropic/claude-opus-4-8", + "name": "Claude Opus 4.8", + "display_name": "Claude Opus 4.8", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": false + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "default_enabled": false, + "mode": "effort", + "effort": "high", + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "interleaved": true, + "summaries": true, + "visibility": "omitted", + "continuation": [ + "thinking_blocks" + ], + "notes": [ + "Claude Opus 4.7 and newer Opus models require thinking.type = \"adaptive\" to enable thinking explicitly.", + "Manual budget_tokens requests return 400 on Claude Opus 4.7 and newer adaptive-only Opus models.", + "task_budget is separate from thinking control and should not be treated as a thinking budget." + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-01", + "release_date": "2026-05-28", + "last_updated": "2026-05-28", + "type": "chat" + }, + { + "id": "anthropic/claude-sonnet-5", + "name": "Claude Sonnet 5", + "display_name": "Claude Sonnet 5", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-01-31", + "release_date": "2026-06-30", + "last_updated": "2026-06-30", + "type": "chat" + }, { "id": "anthropic/claude-opus-4-6", "name": "Claude Opus 4.6", @@ -40830,6 +40933,47 @@ "last_updated": "2026-03-13", "type": "chat" }, + { + "id": "anthropic/claude-haiku-5-5", + "name": "Claude Haiku 5.5", + "display_name": "Claude Haiku 5.5", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-06", + "release_date": "2026-10-07", + "last_updated": "2026-10-07", + "type": "chat" + }, { "id": "anthropic/claude-sonnet-4-6", "name": "Claude Sonnet 4.6", @@ -40889,6 +41033,48 @@ "last_updated": "2026-03-13", "type": "chat" }, + { + "id": "anthropic/claude-sonnet-5-5", + "name": "Claude Sonnet 5.5", + "display_name": "Claude Sonnet 5.5", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-06", + "release_date": "2026-09-28", + "last_updated": "2026-09-28", + "type": "chat" + }, { "id": "anthropic/claude-opus-4-7", "name": "Claude Opus 4.7", @@ -40946,6 +41132,137 @@ "last_updated": "2026-04-16", "type": "chat" }, + { + "id": "deepseek/deepseek-v4.1-flash", + "name": "DeepSeek V4.1 Flash", + "display_name": "DeepSeek V4.1 Flash", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 384000 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "effort_options": [ + "low", + "high", + "max" + ] + } + }, + "attachment": true, + "open_weights": true, + "knowledge": "2025-05", + "release_date": "2026-09-10", + "last_updated": "2026-09-10", + "type": "chat" + }, + { + "id": "deepseek/deepseek-v3.2", + "name": "DeepSeek V3.2", + "display_name": "DeepSeek V3.2", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 128000, + "output": 64000 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": false, + "open_weights": true, + "knowledge": "2024-07", + "release_date": "2025-12-01", + "last_updated": "2025-12-01", + "type": "chat" + }, + { + "id": "z-ai/glm-5.3-flash", + "name": "GLM-5.3-Flash", + "display_name": "GLM-5.3-Flash", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 131072 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "effort_options": [ + "low", + "high", + "max" + ] + } + }, + "attachment": true, + "open_weights": true, + "release_date": "2026-08-26", + "last_updated": "2026-08-26", + "type": "chat" + }, { "id": "black-forest-labs/FLUX.2-klein-4B", "name": "FLUX.2 Klein 4B", @@ -40973,6 +41290,87 @@ "last_updated": "2026-01-14", "type": "chat" }, + { + "id": "x-ai/grok-4.7", + "name": "Grok 4.7", + "display_name": "Grok 4.7", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 500000, + "output": 500000 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "low", + "medium", + "high", + "xhigh" + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-05", + "release_date": "2026-09-21", + "last_updated": "2026-09-21", + "type": "chat" + }, + { + "id": "x-ai/grok-4.6", + "name": "Grok 4.6", + "display_name": "Grok 4.6", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 500000, + "output": 500000 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "effort_options": [ + "low", + "medium", + "high", + "xhigh" + ] + } + }, + "attachment": false, + "open_weights": false, + "knowledge": "2026-02-01", + "release_date": "2026-08-12", + "last_updated": "2026-08-12", + "type": "chat" + }, { "id": "google/gemini-3.5-flash", "name": "Gemini 3.5 Flash", @@ -41130,6 +41528,54 @@ "last_updated": "2025-06-17", "type": "chat" }, + { + "id": "google/gemini-3.8-flash", + "name": "Gemini 3.8 Flash", + "display_name": "Gemini 3.8 Flash", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1048576, + "output": 65536 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "default_enabled": true, + "mode": "level", + "level": "high", + "level_options": [ + "minimal", + "low", + "medium", + "high" + ], + "summaries": true, + "visibility": "summary", + "continuation": [ + "thought_signatures" + ] + } + }, + "attachment": true, + "open_weights": false, + "release_date": "2026-09-02", + "last_updated": "2026-09-02", + "type": "chat" + }, { "id": "google/gemini-2.5-flash-lite", "name": "Gemini 2.5 Flash-Lite", @@ -41247,6 +41693,46 @@ "last_updated": "2025-06-03", "type": "rerank" }, + { + "id": "Qwen/Qwen3.8-27B", + "name": "Qwen3.8 27B", + "display_name": "Qwen3.8 27B", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 32768 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": true, + "open_weights": true, + "release_date": "2026-08-14", + "last_updated": "2026-08-14", + "type": "chat" + }, { "id": "Qwen/Qwen3-VL-30B-A3B-Instruct", "name": "Qwen3-VL 30B-A3B Instruct", @@ -41342,9 +41828,9 @@ "type": "chat" }, { - "id": "zai-org/GLM-5.1-FP8", - "name": "GLM-5.1 FP8", - "display_name": "GLM-5.1 FP8", + "id": "moonshotai/kimi-k3", + "name": "Kimi K3", + "display_name": "Kimi K3", "modalities": { "input": [ "text" @@ -41354,8 +41840,52 @@ ] }, "limit": { - "context": 202752, - "output": 16384 + "context": 1048576, + "output": 131072 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "effort_options": [ + "low", + "high", + "max" + ] + } + }, + "attachment": false, + "open_weights": true, + "release_date": "2026-07-16", + "last_updated": "2026-07-16", + "type": "chat" + }, + { + "id": "moonshotai/kimi-k2.6", + "name": "Kimi K2.6", + "display_name": "Kimi K2.6", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 262144 }, "temperature": true, "tool_call": true, @@ -41376,8 +41906,82 @@ }, "attachment": false, "open_weights": true, - "release_date": "2026-03-27", - "last_updated": "2026-03-27", + "knowledge": "2025-01", + "release_date": "2026-04-21", + "last_updated": "2026-04-21", + "type": "chat" + }, + { + "id": "qwen/qwen3.7-max", + "name": "Qwen3.7 Max", + "display_name": "Qwen3.7 Max", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 65536 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true + } + }, + "attachment": false, + "open_weights": false, + "release_date": "2026-05-21", + "last_updated": "2026-05-21", + "type": "chat" + }, + { + "id": "qwen/qwen3.5-397b-a17b", + "name": "Qwen3.5 397B-A17B", + "display_name": "Qwen3.5 397B-A17B", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 65536 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": true, + "open_weights": true, + "release_date": "2026-02-15", + "last_updated": "2026-02-15", "type": "chat" }, { @@ -41730,6 +42334,89 @@ "last_updated": "2025-08-07", "type": "chat" }, + { + "id": "openai/gpt-6.1-sol", + "name": "GPT-6.1 Sol", + "display_name": "GPT-6.1 Sol", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1050000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-04-30", + "release_date": "2026-09-29", + "last_updated": "2026-09-29", + "type": "chat" + }, + { + "id": "openai/gpt-6-astra", + "name": "GPT-6 Astra", + "display_name": "GPT-6 Astra", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1050000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-04-30", + "release_date": "2026-09-04", + "last_updated": "2026-09-04", + "type": "chat" + }, { "id": "openai/gpt-5.1", "name": "GPT-5.1", @@ -41833,6 +42520,59 @@ "last_updated": "2026-03-17", "type": "chat" }, + { + "id": "openai/gpt-5.6-luna", + "name": "GPT-5.6 Luna", + "display_name": "GPT-5.6 Luna", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1050000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "default_enabled": true, + "mode": "effort", + "effort": "medium", + "effort_options": [ + "none", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "verbosity": "medium", + "verbosity_options": [ + "low", + "medium", + "high" + ], + "visibility": "hidden" + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-02-16", + "release_date": "2026-07-09", + "last_updated": "2026-07-09", + "type": "chat" + }, { "id": "openai/gpt-5.2", "name": "GPT-5.2", @@ -41968,33 +42708,75 @@ "type": "chat" }, { - "id": "openai/gpt-4.1-mini", - "name": "GPT-4.1 mini", - "display_name": "GPT-4.1 mini", + "id": "openai/gpt-4.1-mini", + "name": "GPT-4.1 mini", + "display_name": "GPT-4.1 mini", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1047576, + "output": 32768 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": false, + "knowledge": "2024-04", + "release_date": "2025-04-14", + "last_updated": "2025-04-14", + "type": "chat" + }, + { + "id": "openai/gpt-6-luna", + "name": "GPT-6 Luna", + "display_name": "GPT-6 Luna", "modalities": { "input": [ "text", - "image", - "pdf" + "image" ], "output": [ "text" ] }, "limit": { - "context": 1047576, - "output": 32768 + "context": 1050000, + "output": 128000 }, - "temperature": true, + "temperature": false, "tool_call": true, "reasoning": { - "supported": false + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "none", + "low", + "medium", + "high", + "xhigh", + "max" + ] + } }, "attachment": true, "open_weights": false, - "knowledge": "2024-04", - "release_date": "2025-04-14", - "last_updated": "2025-04-14", + "knowledge": "2026-05-18", + "release_date": "2026-09-22", + "last_updated": "2026-09-22", "type": "chat" }, { @@ -42092,6 +42874,101 @@ "release_date": "2025-08-07", "last_updated": "2025-08-07", "type": "chat" + }, + { + "id": "openai/gpt-5.6-sol", + "name": "GPT-5.6 Sol", + "display_name": "GPT-5.6 Sol", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1050000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "default_enabled": true, + "mode": "effort", + "effort": "medium", + "effort_options": [ + "none", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "verbosity": "medium", + "verbosity_options": [ + "low", + "medium", + "high" + ], + "visibility": "hidden" + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-02-16", + "release_date": "2026-07-09", + "last_updated": "2026-07-09", + "type": "chat" + }, + { + "id": "openai/gpt-6-sol", + "name": "GPT-6 Sol", + "display_name": "GPT-6 Sol", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1050000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "none", + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-04-20", + "release_date": "2026-09-22", + "last_updated": "2026-09-22", + "type": "chat" } ] }, @@ -49475,47 +50352,6 @@ "last_updated": "2025-09-23", "type": "chat" }, - { - "id": "deepinfra/qwen3.8-2.4t-a95b", - "name": "Qwen3.8 2.4T A95B (DeepInfra)", - "display_name": "Qwen3.8 2.4T A95B (DeepInfra)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 131072 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "effort_options": [ - "minimal", - "low", - "medium", - "high", - "xhigh", - "max" - ] - } - }, - "attachment": false, - "open_weights": true, - "release_date": "2026-08-12", - "last_updated": "2026-08-12", - "type": "chat" - }, { "id": "deepinfra/muse-glimmer-30b", "name": "Muse Glimmer 30B (DeepInfra)", @@ -49802,7 +50638,9 @@ "display_name": "Qwen3.5 9B (DeepInfra)", "modalities": { "input": [ - "text" + "text", + "image", + "video" ], "output": [ "text" @@ -49829,7 +50667,7 @@ ] } }, - "attachment": false, + "attachment": true, "open_weights": true, "release_date": "2026-02-23", "last_updated": "2026-02-23", @@ -59013,33 +59851,6 @@ "last_updated": "2026-05-21", "type": "chat" }, - { - "id": "alibaba/qwen-coder-plus", - "name": "Qwen Coder Plus (Alibaba Cloud)", - "display_name": "Qwen Coder Plus (Alibaba Cloud)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 8192 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": false, - "release_date": "2024-09-18", - "last_updated": "2024-09-18", - "type": "chat" - }, { "id": "alibaba/qwen3-vl-plus", "name": "Qwen3 VL Plus (Alibaba Cloud)", @@ -59418,85 +60229,6 @@ "last_updated": "2026-07-15", "type": "chat" }, - { - "id": "alibaba/qwen3-max", - "name": "Qwen3 Max (Alibaba Cloud)", - "display_name": "Qwen3 Max (Alibaba Cloud)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 256000, - "output": 32800 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": true, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-09-23", - "last_updated": "2025-09-23", - "type": "chat" - }, - { - "id": "alibaba/qwen3-vl-flash", - "name": "Qwen3 VL Flash (Alibaba Cloud)", - "display_name": "Qwen3 VL Flash (Alibaba Cloud)", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": true, - "open_weights": false, - "release_date": "2025-10-15", - "last_updated": "2025-10-15", - "type": "chat" - }, { "id": "alibaba/qwen3.5-122b-a10b", "name": "Qwen3.5 122B A10B (Alibaba Cloud)", @@ -59728,34 +60460,6 @@ "last_updated": "2025-07-28", "type": "chat" }, - { - "id": "alibaba/qwen3-coder-plus", - "name": "Qwen3 Coder Plus (Alibaba Cloud)", - "display_name": "Qwen3 Coder Plus (Alibaba Cloud)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 66000 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-07-23", - "last_updated": "2025-07-23", - "type": "chat" - }, { "id": "alibaba/qwen3.8-flash", "name": "Qwen3.8 Flash (Alibaba Cloud)", @@ -59892,46 +60596,6 @@ "last_updated": "2026-02-23", "type": "chat" }, - { - "id": "alibaba/qwen3.6-max-preview", - "name": "Qwen3.6 Max Preview (Alibaba Cloud)", - "display_name": "Qwen3.6 Max Preview (Alibaba Cloud)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2026-04-20", - "last_updated": "2026-04-20", - "type": "chat" - }, { "id": "alibaba/glm-5.2", "name": "GLM-5.2 (Alibaba Cloud)", @@ -59980,38 +60644,6 @@ "last_updated": "2026-06-13", "type": "chat" }, - { - "id": "alibaba/qwen-omni-turbo", - "name": "Qwen Omni Turbo (Alibaba Cloud)", - "display_name": "Qwen Omni Turbo (Alibaba Cloud)", - "modalities": { - "input": [ - "text", - "image", - "audio", - "video" - ], - "output": [ - "text", - "audio" - ] - }, - "limit": { - "context": 32768, - "output": 8192 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false - }, - "attachment": true, - "open_weights": false, - "knowledge": "2024-04", - "release_date": "2025-01-19", - "last_updated": "2025-03-26", - "type": "chat" - }, { "id": "alibaba/deepseek-v4-pro", "name": "DeepSeek V4 Pro (Alibaba Cloud)", @@ -60577,47 +61209,404 @@ "type": "chat" }, { - "id": "baidu/glm-5.3", - "name": "GLM-5.3 (Baidu)", - "display_name": "GLM-5.3 (Baidu)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1048576, - "output": 131072 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "effort_options": [ - "low", - "high", - "max" - ] - } - }, - "attachment": false, - "open_weights": true, - "release_date": "2026-08-14", - "last_updated": "2026-08-14", - "type": "chat" - }, - { - "id": "baidu/deepseek-v4-flash", - "name": "DeepSeek V4 Flash (Baidu)", - "display_name": "DeepSeek V4 Flash (Baidu)", + "id": "baidu/glm-5.3", + "name": "GLM-5.3 (Baidu)", + "display_name": "GLM-5.3 (Baidu)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1048576, + "output": 131072 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "effort_options": [ + "low", + "high", + "max" + ] + } + }, + "attachment": false, + "open_weights": true, + "release_date": "2026-08-14", + "last_updated": "2026-08-14", + "type": "chat" + }, + { + "id": "baidu/deepseek-v4-flash", + "name": "DeepSeek V4 Flash (Baidu)", + "display_name": "DeepSeek V4 Flash (Baidu)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1048576, + "output": 131072 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "default_enabled": true, + "mode": "effort", + "effort": "high", + "effort_options": [ + "low", + "high", + "max" + ], + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "notes": [ + "The DeepSeek API maps medium and xhigh to high for V4 models; effort_options lists distinct model-effective levels." + ] + } + }, + "attachment": false, + "open_weights": true, + "knowledge": "2025-05", + "release_date": "2026-04-24", + "last_updated": "2026-04-24", + "type": "chat" + }, + { + "id": "gonka24/glm-5.3-flash", + "name": "GLM-5.3 Flash (Gonka24)", + "display_name": "GLM-5.3 Flash (Gonka24)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 200000, + "output": 16384 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "effort_options": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": false, + "open_weights": true, + "release_date": "2026-08-26", + "last_updated": "2026-08-26", + "type": "chat" + }, + { + "id": "gonka24/minimax-m2.7", + "name": "MiniMax M2.7 (Gonka24)", + "display_name": "MiniMax M2.7 (Gonka24)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 204800, + "output": 131100 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": false, + "open_weights": true, + "release_date": "2026-03-18", + "last_updated": "2026-03-18", + "type": "chat" + }, + { + "id": "gonka24/deepseek-v4-flash", + "name": "DeepSeek V4 Flash (Gonka24)", + "display_name": "DeepSeek V4 Flash (Gonka24)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 390000, + "output": 16384 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "default_enabled": true, + "mode": "effort", + "effort": "high", + "effort_options": [ + "low", + "high", + "max" + ], + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "notes": [ + "The DeepSeek API maps medium and xhigh to high for V4 models; effort_options lists distinct model-effective levels." + ] + } + }, + "attachment": false, + "open_weights": true, + "knowledge": "2025-05", + "release_date": "2026-04-24", + "last_updated": "2026-04-24", + "type": "chat" + }, + { + "id": "reka-ai/reka-edge-2603", + "name": "Reka Edge 2603 (reka-ai)", + "display_name": "Reka Edge 2603 (reka-ai)", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 16384, + "output": 16384 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": false, + "release_date": "2026-10-09", + "last_updated": "2026-10-09", + "type": "chat" + }, + { + "id": "reka-ai/qwen3.8-27b", + "name": "Qwen3.8 27B (reka-ai)", + "display_name": "Qwen3.8 27B (reka-ai)", + "modalities": { + "input": [ + "text", + "image", + "video" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 262144 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": true, + "release_date": "2026-08-14", + "last_updated": "2026-08-14", + "type": "chat" + }, + { + "id": "reka-ai/glm-5.3-flash", + "name": "GLM-5.3 Flash (reka-ai)", + "display_name": "GLM-5.3 Flash (reka-ai)", + "modalities": { + "input": [ + "text", + "image", + "video", + "pdf" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 262144 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "effort_options": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": true, + "release_date": "2026-08-26", + "last_updated": "2026-08-26", + "type": "chat" + }, + { + "id": "reka-ai/deepseek-v4-pro", + "name": "DeepSeek V4 Pro (reka-ai)", + "display_name": "DeepSeek V4 Pro (reka-ai)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1048576, + "output": 393216 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "default_enabled": true, + "mode": "effort", + "effort": "high", + "effort_options": [ + "low", + "high", + "max" + ], + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "notes": [ + "The DeepSeek API maps medium and xhigh to high for V4 models; effort_options lists distinct model-effective levels." + ] + } + }, + "attachment": false, + "open_weights": true, + "knowledge": "2025-05", + "release_date": "2026-04-24", + "last_updated": "2026-04-24", + "type": "chat" + }, + { + "id": "reka-ai/glm-5.3", + "name": "GLM-5.3 (reka-ai)", + "display_name": "GLM-5.3 (reka-ai)", "modalities": { "input": [ "text" @@ -60628,58 +61617,7 @@ }, "limit": { "context": 1048576, - "output": 131072 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": true, - "mode": "effort", - "effort": "high", - "effort_options": [ - "low", - "high", - "max" - ], - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "notes": [ - "The DeepSeek API maps medium and xhigh to high for V4 models; effort_options lists distinct model-effective levels." - ] - } - }, - "attachment": false, - "open_weights": true, - "knowledge": "2025-05", - "release_date": "2026-04-24", - "last_updated": "2026-04-24", - "type": "chat" - }, - { - "id": "gonka24/glm-5.3-flash", - "name": "GLM-5.3 Flash (Gonka24)", - "display_name": "GLM-5.3 Flash (Gonka24)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 200000, - "output": 16384 + "output": 262144 }, "temperature": true, "tool_call": true, @@ -60703,60 +61641,14 @@ }, "attachment": false, "open_weights": true, - "release_date": "2026-08-26", - "last_updated": "2026-08-26", - "type": "chat" - }, - { - "id": "gonka24/minimax-m2.7", - "name": "MiniMax M2.7 (Gonka24)", - "display_name": "MiniMax M2.7 (Gonka24)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 204800, - "output": 131100 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "effort_options": [ - "low", - "medium", - "high", - "xhigh", - "max" - ] - } - }, - "attachment": false, - "open_weights": true, - "release_date": "2026-03-18", - "last_updated": "2026-03-18", + "release_date": "2026-08-14", + "last_updated": "2026-08-14", "type": "chat" }, { - "id": "gonka24/deepseek-v4-flash", - "name": "DeepSeek V4 Flash (Gonka24)", - "display_name": "DeepSeek V4 Flash (Gonka24)", + "id": "reka-ai/deepseek-v4-flash", + "name": "DeepSeek V4 Flash (reka-ai)", + "display_name": "DeepSeek V4 Flash (reka-ai)", "modalities": { "input": [ "text" @@ -60766,8 +61658,8 @@ ] }, "limit": { - "context": 390000, - "output": 16384 + "context": 262144, + "output": 131072 }, "temperature": true, "tool_call": true, @@ -68742,8 +69634,8 @@ }, { "id": "bytedance-seed/seed-1.6-flash", - "name": "ByteDance Seed: Seed 1.6 Flash", - "display_name": "ByteDance Seed: Seed 1.6 Flash", + "name": "ByteDance Seed: Seed 1.6 Flash (retires Nov 11)", + "display_name": "ByteDance Seed: Seed 1.6 Flash (retires Nov 11)", "modalities": { "input": [ "image", @@ -68940,8 +69832,8 @@ }, { "id": "bytedance-seed/seed-1.6", - "name": "ByteDance Seed: Seed 1.6", - "display_name": "ByteDance Seed: Seed 1.6", + "name": "ByteDance Seed: Seed 1.6 (retires Nov 11)", + "display_name": "ByteDance Seed: Seed 1.6 (retires Nov 11)", "modalities": { "input": [ "image", @@ -70463,8 +71355,8 @@ ] }, "limit": { - "context": 128000, - "output": 16000 + "context": 163840, + "output": 16384 }, "temperature": true, "tool_call": true, @@ -70676,8 +71568,8 @@ }, { "id": "deepseek/deepseek-r1-0528", - "name": "DeepSeek: R1 0528", - "display_name": "DeepSeek: R1 0528", + "name": "DeepSeek R1 0528", + "display_name": "DeepSeek R1 0528", "modalities": { "input": [ "text" @@ -70711,7 +71603,7 @@ } }, "attachment": false, - "open_weights": false, + "open_weights": true, "release_date": "2025-05-28", "last_updated": "2025-05-28", "type": "chat" @@ -71261,8 +72153,8 @@ }, { "id": "meta-llama/llama-3.2-1b-instruct", - "name": "Meta: Llama 3.2 1B Instruct", - "display_name": "Meta: Llama 3.2 1B Instruct", + "name": "Llama 3.2 1B Instruct", + "display_name": "Llama 3.2 1B Instruct", "modalities": { "input": [ "text" @@ -71281,7 +72173,7 @@ "supported": false }, "attachment": false, - "open_weights": false, + "open_weights": true, "release_date": "2024-09-25", "last_updated": "2024-09-25", "type": "chat" @@ -71625,8 +72517,8 @@ ] }, "limit": { - "context": 198000, - "output": 16384 + "context": 202752, + "output": 131072 }, "temperature": true, "tool_call": true, @@ -75653,8 +76545,8 @@ }, { "id": "inclusionai/ling-3.1-flash", - "name": "inclusionAI: Ling 3.1 Flash (new)", - "display_name": "inclusionAI: Ling 3.1 Flash (new)", + "name": "inclusionAI: Ling 3.1 Flash", + "display_name": "inclusionAI: Ling 3.1 Flash", "modalities": { "input": [ "text" @@ -75890,7 +76782,7 @@ }, "limit": { "context": 262144, - "output": 235929 + "output": 98304 }, "temperature": true, "tool_call": true, @@ -75966,8 +76858,8 @@ }, { "id": "moonshotai/kimi-k2-0905", - "name": "MoonshotAI: Kimi K2 0905", - "display_name": "MoonshotAI: Kimi K2 0905", + "name": "Kimi K2 Instruct 0905", + "display_name": "Kimi K2 Instruct 0905", "modalities": { "input": [ "text" @@ -75986,9 +76878,9 @@ "supported": false }, "attachment": false, - "open_weights": false, - "release_date": "2025-09-04", - "last_updated": "2025-09-04", + "open_weights": true, + "release_date": "2025-09-05", + "last_updated": "2025-09-05", "type": "chat" }, { @@ -76298,80 +77190,80 @@ }, "attachment": false, "open_weights": true, - "release_date": "2025-12-15", - "last_updated": "2025-12-15", - "type": "chat" - }, - { - "id": "nvidia/nemotron-3.5-content-safety:free", - "name": "NVIDIA: Nemotron 3.5 Content Safety (free)", - "display_name": "NVIDIA: Nemotron 3.5 Content Safety (free)", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 128000, - "output": 8192 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "effort_options": [ - "none", - "high" - ] - } - }, - "attachment": true, - "open_weights": true, - "release_date": "2026-06-04", - "last_updated": "2026-06-04", - "type": "chat" - }, - { - "id": "nvidia/nemotron-3.5-lightning", - "name": "Nemotron 3.5 Lightning 30B A3B", - "display_name": "Nemotron 3.5 Lightning 30B A3B", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 131072 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "effort_options": [ - "none", - "high" - ] - } - }, - "attachment": false, - "open_weights": true, + "release_date": "2025-12-15", + "last_updated": "2025-12-15", + "type": "chat" + }, + { + "id": "nvidia/nemotron-3.5-content-safety:free", + "name": "NVIDIA: Nemotron 3.5 Content Safety (free)", + "display_name": "NVIDIA: Nemotron 3.5 Content Safety (free)", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 128000, + "output": 8192 + }, + "temperature": true, + "tool_call": false, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "none", + "high" + ] + } + }, + "attachment": true, + "open_weights": true, + "release_date": "2026-06-04", + "last_updated": "2026-06-04", + "type": "chat" + }, + { + "id": "nvidia/nemotron-3.5-lightning", + "name": "Nemotron 3.5 Lightning 30B A3B", + "display_name": "Nemotron 3.5 Lightning 30B A3B", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 235929 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "effort_options": [ + "none", + "high" + ] + } + }, + "attachment": false, + "open_weights": true, "release_date": "2026-08-11", "last_updated": "2026-08-11", "type": "chat" @@ -76503,8 +77395,8 @@ ] }, "limit": { - "context": 262144, - "output": 16384 + "context": 202800, + "output": 182520 }, "temperature": true, "tool_call": true, @@ -77991,8 +78883,8 @@ ] }, "limit": { - "context": 1000000, - "output": 131072 + "context": 262144, + "output": 235929 }, "temperature": true, "tool_call": true, @@ -78016,50 +78908,6 @@ "last_updated": "2026-08-14", "type": "chat" }, - { - "id": "qwen/qwen3-vl-235b-a22b-thinking", - "name": "Qwen3 VL 235B A22B Thinking", - "display_name": "Qwen3 VL 235B A22B Thinking", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "effort_options": [ - "high" - ] - } - }, - "attachment": true, - "open_weights": true, - "knowledge": "2025-03-31", - "release_date": "2025-09-23", - "last_updated": "2025-09-23", - "type": "chat" - }, { "id": "qwen/qwen3.8-2.4t-a95b", "name": "Qwen3.8 2.4T A95B", @@ -78156,8 +79004,8 @@ ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 262144, + "output": 235929 }, "temperature": true, "tool_call": true, @@ -78363,45 +79211,6 @@ "last_updated": "2026-07-15", "type": "chat" }, - { - "id": "qwen/qwen3-max", - "name": "Qwen3 Max", - "display_name": "Qwen3 Max", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-09-23", - "last_updated": "2025-09-23", - "type": "chat" - }, { "id": "qwen/qwen3-coder-30b-a3b-instruct", "name": "Qwen3-Coder 30B-A3B Instruct", @@ -78471,8 +79280,8 @@ }, { "id": "qwen/qwen3-vl-30b-a3b-instruct", - "name": "Qwen: Qwen3 VL 30B A3B Instruct", - "display_name": "Qwen: Qwen3 VL 30B A3B Instruct", + "name": "Qwen3 VL 30B A3B Instruct", + "display_name": "Qwen3 VL 30B A3B Instruct", "modalities": { "input": [ "text", @@ -78492,15 +79301,15 @@ "supported": false }, "attachment": true, - "open_weights": false, - "release_date": "2025-10-06", - "last_updated": "2025-10-06", + "open_weights": true, + "release_date": "2025-10-04", + "last_updated": "2025-10-04", "type": "chat" }, { "id": "qwen/qwen3-235b-a22b-thinking-2507", - "name": "Qwen: Qwen3 235B A22B Thinking 2507 (retires Oct 9)", - "display_name": "Qwen: Qwen3 235B A22B Thinking 2507 (retires Oct 9)", + "name": "Qwen: Qwen3 235B A22B Thinking 2507", + "display_name": "Qwen: Qwen3 235B A22B Thinking 2507", "modalities": { "input": [ "text" @@ -78510,8 +79319,8 @@ ] }, "limit": { - "context": 131072, - "output": 117964 + "context": 128000, + "output": 16384 }, "temperature": true, "tool_call": true, @@ -78539,50 +79348,6 @@ "last_updated": "2025-07-25", "type": "chat" }, - { - "id": "qwen/qwen3-235b-a22b", - "name": "Qwen3 235B-A22B", - "display_name": "Qwen3 235B-A22B", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 8192 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "effort_options": [ - "none", - "high" - ] - } - }, - "attachment": false, - "open_weights": true, - "knowledge": "2025-04", - "release_date": "2025-04", - "last_updated": "2025-04", - "type": "chat" - }, { "id": "qwen/qwen3.5-122b-a10b", "name": "Qwen3.5 122B-A10B", @@ -78628,44 +79393,6 @@ "last_updated": "2026-02-23", "type": "chat" }, - { - "id": "qwen/qwen-plus-2025-07-28", - "name": "Qwen: Qwen Plus 0728 (retires Oct 9)", - "display_name": "Qwen: Qwen Plus 0728 (retires Oct 9)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": false, - "release_date": "2025-09-08", - "last_updated": "2025-09-08", - "type": "chat" - }, { "id": "qwen/qwen3.6-35b-a3b", "name": "Qwen3.6 35B-A3B", @@ -78682,7 +79409,7 @@ }, "limit": { "context": 262144, - "output": 235929 + "output": 65536 }, "temperature": true, "tool_call": true, @@ -78725,7 +79452,7 @@ }, "limit": { "context": 262144, - "output": 16384 + "output": 235929 }, "temperature": true, "tool_call": true, @@ -78741,8 +79468,8 @@ }, { "id": "qwen/qwen3-vl-30b-a3b-thinking", - "name": "Qwen: Qwen3 VL 30B A3B Thinking (retires Oct 9)", - "display_name": "Qwen: Qwen3 VL 30B A3B Thinking (retires Oct 9)", + "name": "Qwen: Qwen3 VL 30B A3B Thinking", + "display_name": "Qwen: Qwen3 VL 30B A3B Thinking", "modalities": { "input": [ "text", @@ -78753,8 +79480,8 @@ ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 262144, + "output": 235929 }, "temperature": true, "tool_call": true, @@ -78927,77 +79654,6 @@ "last_updated": "2026-02-25", "type": "chat" }, - { - "id": "qwen/qwen3-max-thinking", - "name": "Qwen: Qwen3 Max Thinking (retires Oct 9)", - "display_name": "Qwen: Qwen3 Max Thinking (retires Oct 9)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "effort_options": [ - "none", - "high" - ] - } - }, - "attachment": false, - "open_weights": false, - "release_date": "2026-02-09", - "last_updated": "2026-02-09", - "type": "chat" - }, - { - "id": "qwen/qwen3-coder-plus", - "name": "Qwen3 Coder Plus", - "display_name": "Qwen3 Coder Plus", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-07-23", - "last_updated": "2025-07-23", - "type": "chat" - }, { "id": "qwen/qwen3.5-9b", "name": "Qwen3.5 9B", @@ -79184,7 +79840,7 @@ }, "limit": { "context": 262144, - "output": 65536 + "output": 32768 }, "temperature": true, "tool_call": true, @@ -79213,50 +79869,6 @@ "last_updated": "2026-02-23", "type": "chat" }, - { - "id": "qwen/qwen3.6-max-preview", - "name": "Qwen3.6 Max Preview", - "display_name": "Qwen3.6 Max Preview", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "effort_options": [ - "none", - "high" - ] - } - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2026-04-20", - "last_updated": "2026-04-20", - "type": "chat" - }, { "id": "qwen/qwen3-30b-a3b", "name": "Qwen3 30B A3B", @@ -79345,81 +79957,10 @@ "last_updated": "2026-02-15", "type": "chat" }, - { - "id": "qwen/qwen3-8b", - "name": "Qwen: Qwen3 8B (retires Oct 9)", - "display_name": "Qwen: Qwen3 8B (retires Oct 9)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 8192 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "effort_options": [ - "none", - "high" - ] - } - }, - "attachment": false, - "open_weights": false, - "release_date": "2025-04-28", - "last_updated": "2025-04-28", - "type": "chat" - }, - { - "id": "qwen/qwen3-vl-32b-instruct", - "name": "Qwen: Qwen3 VL 32B Instruct (retires Oct 9)", - "display_name": "Qwen: Qwen3 VL 32B Instruct (retires Oct 9)", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": true, - "open_weights": false, - "release_date": "2025-10-23", - "last_updated": "2025-10-23", - "type": "chat" - }, { "id": "qwen/qwen3-vl-8b-instruct", - "name": "Qwen: Qwen3 VL 8B Instruct (retires Oct 9)", - "display_name": "Qwen: Qwen3 VL 8B Instruct (retires Oct 9)", + "name": "Qwen: Qwen3 VL 8B Instruct", + "display_name": "Qwen: Qwen3 VL 8B Instruct", "modalities": { "input": [ "image", @@ -79430,8 +79971,8 @@ ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 262144, + "output": 235929 }, "temperature": true, "tool_call": true, @@ -79598,48 +80139,6 @@ "last_updated": "2024-09-19", "type": "chat" }, - { - "id": "qwen/qwen3-30b-a3b-thinking-2507", - "name": "Qwen: Qwen3 30B A3B Thinking 2507 (retires Oct 9)", - "display_name": "Qwen: Qwen3 30B A3B Thinking 2507 (retires Oct 9)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 81920, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "effort_options": [ - "high" - ] - } - }, - "attachment": false, - "open_weights": false, - "release_date": "2025-08-28", - "last_updated": "2025-08-28", - "type": "chat" - }, { "id": "qwen/qwen3.6-27b", "name": "Qwen3.6 27B", @@ -79774,49 +80273,6 @@ "last_updated": "2025-04-28", "type": "chat" }, - { - "id": "qwen/qwen3-vl-8b-thinking", - "name": "Qwen: Qwen3 VL 8B Thinking (retires Oct 9)", - "display_name": "Qwen: Qwen3 VL 8B Thinking (retires Oct 9)", - "modalities": { - "input": [ - "image", - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "effort_options": [ - "high" - ] - } - }, - "attachment": true, - "open_weights": false, - "release_date": "2025-10-14", - "last_updated": "2025-10-14", - "type": "chat" - }, { "id": "qwen/qwen3.7-plus", "name": "Qwen3.7 Plus", @@ -84383,6 +84839,45 @@ "last_updated": "2026-06-11", "type": "chat" }, + { + "id": "openai-gpt-61-sol-ultrafast", + "name": "GPT-6.1 Sol Ultrafast", + "display_name": "GPT-6.1 Sol Ultrafast", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1050000, + "output": 128000 + }, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": false, + "release_date": "2026-10-08", + "last_updated": "2026-10-10", + "type": "chat" + }, { "id": "claude-opus-5", "name": "Claude Opus 5", @@ -88365,6 +88860,267 @@ } ] }, + "lowrouter": { + "id": "lowrouter", + "name": "LowRouter", + "display_name": "LowRouter", + "api": "https://api.lowrouter.ai/v1", + "doc": "https://lowrouter.ai/docs/models/available", + "models": [ + { + "id": "auto/mistralai/ministral-8b-2512", + "name": "Ministral 3 8B", + "display_name": "Ministral 3 8B", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 262144 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": true, + "release_date": "2025-12-02", + "last_updated": "2025-12-02", + "type": "chat" + }, + { + "id": "auto/mistralai/mistral-large-4", + "name": "Mistral Large 4", + "display_name": "Mistral Large 4", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 524288, + "output": 262144 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "none", + "high" + ] + } + }, + "attachment": true, + "open_weights": false, + "release_date": "2026-10-06", + "last_updated": "2026-10-06", + "type": "chat" + }, + { + "id": "auto/mistralai/mistral-medium-3.5", + "name": "Mistral Medium 3.5", + "display_name": "Mistral Medium 3.5", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 262144 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "none", + "high" + ] + } + }, + "attachment": true, + "open_weights": true, + "release_date": "2026-04-29", + "last_updated": "2026-04-29", + "type": "chat" + }, + { + "id": "auto/mistralai/mistral-small-2603", + "name": "Mistral Small 4", + "display_name": "Mistral Small 4", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 256000, + "output": 256000 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "none", + "high" + ] + } + }, + "attachment": true, + "open_weights": true, + "knowledge": "2025-06", + "release_date": "2026-03-16", + "last_updated": "2026-03-16", + "type": "chat" + }, + { + "id": "auto/mistralai/mistral-large-2512", + "name": "Mistral Large 3", + "display_name": "Mistral Large 3", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 262144 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": true, + "knowledge": "2024-11", + "release_date": "2025-12-02", + "last_updated": "2025-12-02", + "type": "chat" + }, + { + "id": "auto/mistralai/ministral-14b-2512", + "name": "Ministral 3 14B", + "display_name": "Ministral 3 14B", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 262144 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": true, + "release_date": "2025-12-02", + "last_updated": "2025-12-02", + "type": "chat" + }, + { + "id": "auto/mistralai/ministral-3b-2512", + "name": "Ministral 3 3B", + "display_name": "Ministral 3 3B", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 262144 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": true, + "release_date": "2025-12-02", + "last_updated": "2025-12-02", + "type": "chat" + }, + { + "id": "auto/mistralai/codestral-2508", + "name": "Codestral 25.08", + "display_name": "Codestral 25.08", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 128000, + "output": 8192 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": false, + "release_date": "2025-07-30", + "last_updated": "2025-07-30", + "type": "chat" + } + ] + }, "inference": { "id": "inference", "name": "Inference", @@ -96135,42 +96891,15 @@ }, "novita-ai": { "id": "novita-ai", - "name": "NovitaAI", - "display_name": "NovitaAI", + "name": "Novita AI", + "display_name": "Novita AI", "api": "https://api.novita.ai/openai", "doc": "https://novita.ai/docs/guides/introduction", "models": [ { - "id": "kwaipilot/kat-coder-pro", - "name": "Kat Coder Pro", - "display_name": "Kat Coder Pro", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 256000, - "output": 128000 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "release_date": "2026-01-05", - "last_updated": "2026-01-05", - "type": "chat" - }, - { - "id": "deepseek/deepseek-prover-v2-671b", - "name": "Deepseek Prover V2 671B", - "display_name": "Deepseek Prover V2 671B", + "id": "baai/bge-m3", + "name": "BGE M3", + "display_name": "BGE M3", "modalities": { "input": [ "text" @@ -96180,24 +96909,24 @@ ] }, "limit": { - "context": 160000, - "output": 160000 + "context": 8192, + "output": 8192 }, - "temperature": true, + "temperature": false, "tool_call": false, "reasoning": { "supported": false }, "attachment": false, "open_weights": true, - "release_date": "2025-04-30", - "last_updated": "2025-04-30", - "type": "chat" + "release_date": "2024-01-30", + "last_updated": "2024-01-30", + "type": "embedding" }, { - "id": "deepseek/deepseek-r1-distill-qwen-14b", - "name": "DeepSeek R1 Distill Qwen 14B", - "display_name": "DeepSeek R1 Distill Qwen 14B", + "id": "baai/bge-reranker-v2-m3", + "name": "BGE Reranker V2 M3", + "display_name": "BGE Reranker V2 M3", "modalities": { "input": [ "text" @@ -96207,24 +96936,24 @@ ] }, "limit": { - "context": 32768, - "output": 16384 + "context": 8000, + "output": 8192 }, - "temperature": true, + "temperature": false, "tool_call": false, "reasoning": { "supported": false }, "attachment": false, "open_weights": true, - "release_date": "2025-01-20", - "last_updated": "2025-01-20", - "type": "chat" + "release_date": "2024-03-15", + "last_updated": "2024-03-15", + "type": "rerank" }, { - "id": "deepseek/deepseek-v3-0324", - "name": "DeepSeek V3 0324", - "display_name": "DeepSeek V3 0324", + "id": "deepseek/deepseek-v4-flash-0731", + "name": "DeepSeek V4 Flash 0731", + "display_name": "DeepSeek V4 Flash 0731", "modalities": { "input": [ "text" @@ -96234,79 +96963,82 @@ ] }, "limit": { - "context": 163840, - "output": 163840 + "context": 1048576, + "output": 393216 }, "temperature": true, "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "knowledge": "2024-07", - "release_date": "2025-03-25", - "last_updated": "2025-03-25", - "type": "chat" - }, - { - "id": "deepseek/deepseek-r1-distill-llama-70b", - "name": "DeepSeek R1 Distill LLama 70B", - "display_name": "DeepSeek R1 Distill LLama 70B", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 8192, - "output": 8192 - }, - "temperature": true, - "tool_call": false, "reasoning": { "supported": true, "default": true }, "extra_capabilities": { "reasoning": { - "supported": true + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "effort_options": [ + "low", + "high", + "max" + ] } }, "attachment": false, "open_weights": true, - "release_date": "2025-01-27", - "last_updated": "2025-01-27", + "knowledge": "2025-05", + "release_date": "2026-07-31", + "last_updated": "2026-07-31", "type": "chat" }, { - "id": "deepseek/deepseek-v3-turbo", - "name": "DeepSeek V3 (Turbo)\t", - "display_name": "DeepSeek V3 (Turbo)\t", + "id": "deepseek/deepseek-v4.1-flash", + "name": "DeepSeek V4.1 Flash", + "display_name": "DeepSeek V4.1 Flash", "modalities": { "input": [ - "text" + "text", + "image" ], "output": [ "text" ] }, "limit": { - "context": 64000, - "output": 16000 + "context": 1048576, + "output": 393216 }, "temperature": true, "tool_call": true, "reasoning": { - "supported": false + "supported": true, + "default": true }, - "attachment": false, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "effort_options": [ + "low", + "high", + "max" + ] + } + }, + "attachment": true, "open_weights": true, - "release_date": "2025-03-05", - "last_updated": "2025-03-05", + "knowledge": "2025-05", + "release_date": "2026-09-10", + "last_updated": "2026-09-10", "type": "chat" }, { @@ -96337,38 +97069,10 @@ "last_updated": "2025-05-29", "type": "chat" }, - { - "id": "deepseek/deepseek-v3.1-terminus", - "name": "Deepseek V3.1 Terminus", - "display_name": "Deepseek V3.1 Terminus", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "attachment": false, - "open_weights": true, - "release_date": "2025-09-22", - "last_updated": "2025-09-22", - "type": "chat" - }, { "id": "deepseek/deepseek-ocr-2", - "name": "deepseek/deepseek-ocr-2", - "display_name": "deepseek/deepseek-ocr-2", + "name": "DeepSeek OCR 2", + "display_name": "DeepSeek OCR 2", "modalities": { "input": [ "text", @@ -96392,38 +97096,10 @@ "last_updated": "2026-01-27", "type": "chat" }, - { - "id": "deepseek/deepseek-ocr", - "name": "DeepSeek-OCR", - "display_name": "DeepSeek-OCR", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 8192, - "output": 8192 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false - }, - "attachment": true, - "open_weights": true, - "release_date": "2025-10-24", - "last_updated": "2025-10-24", - "type": "chat" - }, { "id": "deepseek/deepseek-r1-turbo", - "name": "DeepSeek R1 (Turbo)\t", - "display_name": "DeepSeek R1 (Turbo)\t", + "name": "DeepSeek R1 (Turbo)", + "display_name": "DeepSeek R1 (Turbo)", "modalities": { "input": [ "text" @@ -96444,14 +97120,15 @@ }, "attachment": false, "open_weights": true, - "release_date": "2025-03-05", - "last_updated": "2025-03-05", + "knowledge": "2024-07", + "release_date": "2025-01-20", + "last_updated": "2025-05-29", "type": "chat" }, { - "id": "deepseek/deepseek-v3.2-exp", - "name": "Deepseek V3.2 Exp", - "display_name": "Deepseek V3.2 Exp", + "id": "deepseek/deepseek-v4-pro-0813", + "name": "DeepSeek V4 Pro 0813", + "display_name": "DeepSeek V4 Pro 0813", "modalities": { "input": [ "text" @@ -96461,8 +97138,8 @@ ] }, "limit": { - "context": 163840, - "output": 65536 + "context": 1048576, + "output": 393216 }, "temperature": true, "tool_call": true, @@ -96470,43 +97147,32 @@ "supported": true, "default": true }, - "attachment": false, - "open_weights": true, - "release_date": "2025-09-29", - "last_updated": "2025-09-29", - "type": "chat" - }, - { - "id": "deepseek/deepseek-r1-distill-qwen-32b", - "name": "DeepSeek R1 Distill Qwen 32B", - "display_name": "DeepSeek R1 Distill Qwen 32B", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 64000, - "output": 32000 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "effort_options": [ + "low", + "high", + "max" + ] + } }, "attachment": false, "open_weights": true, - "release_date": "2025-01-20", - "last_updated": "2025-01-20", + "release_date": "2026-08-12", + "last_updated": "2026-08-22", "type": "chat" }, { - "id": "deepseek/deepseek-v3.1", - "name": "DeepSeek V3.1", - "display_name": "DeepSeek V3.1", + "id": "deepseek/deepseek_v3", + "name": "DeepSeek-V3", + "display_name": "DeepSeek-V3", "modalities": { "input": [ "text" @@ -96516,19 +97182,18 @@ ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 64000, + "output": 16000 }, "temperature": true, "tool_call": true, "reasoning": { - "supported": true, - "default": true + "supported": false }, "attachment": false, "open_weights": true, - "release_date": "2025-08-21", - "last_updated": "2025-08-21", + "release_date": "2024-12-26", + "last_updated": "2024-12-26", "type": "chat" }, { @@ -96617,15 +97282,14 @@ }, "attachment": false, "open_weights": true, - "knowledge": "2024-07", "release_date": "2025-05-28", "last_updated": "2025-05-28", "type": "chat" }, { - "id": "deepseek/deepseek-v3.2", - "name": "Deepseek V3.2", - "display_name": "Deepseek V3.2", + "id": "tencent/hy3", + "name": "Hy3", + "display_name": "Hy3", "modalities": { "input": [ "text" @@ -96635,8 +97299,8 @@ ] }, "limit": { - "context": 163840, - "output": 65536 + "context": 262144, + "output": 262144 }, "temperature": true, "tool_call": true, @@ -96652,19 +97316,23 @@ "visibility": "summary", "continuation": [ "thinking_blocks" + ], + "effort_options": [ + "none", + "high" ] } }, "attachment": false, "open_weights": true, - "release_date": "2025-12-01", - "last_updated": "2025-12-01", + "release_date": "2026-07-06", + "last_updated": "2026-07-06", "type": "chat" }, { - "id": "deepseek/deepseek-v4-flash", - "name": "DeepSeek V4 Flash", - "display_name": "DeepSeek V4 Flash", + "id": "tencent/hy4-preview", + "name": "Hy4 preview", + "display_name": "Hy4 preview", "modalities": { "input": [ "text" @@ -96674,8 +97342,8 @@ ] }, "limit": { - "context": 1048576, - "output": 393216 + "context": 1000000, + "output": 64000 }, "temperature": true, "tool_call": true, @@ -96686,36 +97354,28 @@ "extra_capabilities": { "reasoning": { "supported": true, - "default_enabled": true, - "mode": "effort", - "effort": "high", - "effort_options": [ - "low", - "high", - "max" - ], "interleaved": true, "summaries": true, "visibility": "summary", "continuation": [ "thinking_blocks" ], - "notes": [ - "The DeepSeek API maps medium and xhigh to high for V4 models; effort_options lists distinct model-effective levels." + "effort_options": [ + "none", + "high" ] } }, "attachment": false, "open_weights": true, - "knowledge": "2025-05", - "release_date": "2026-04-24", - "last_updated": "2026-04-24", + "release_date": "2026-08-28", + "last_updated": "2026-08-28", "type": "chat" }, { "id": "meta-llama/llama-4-maverick-17b-128e-instruct-fp8", - "name": "Llama 4 Maverick Instruct", - "display_name": "Llama 4 Maverick Instruct", + "name": "Llama 4 Maverick 17B Instruct", + "display_name": "Llama 4 Maverick 17B Instruct", "modalities": { "input": [ "text", @@ -96730,20 +97390,21 @@ "output": 8192 }, "temperature": true, - "tool_call": false, + "tool_call": true, "reasoning": { "supported": false }, "attachment": true, "open_weights": true, - "release_date": "2025-04-06", - "last_updated": "2025-04-06", + "knowledge": "2024-08", + "release_date": "2025-04-05", + "last_updated": "2025-04-05", "type": "chat" }, { - "id": "meta-llama/llama-3-70b-instruct", - "name": "Llama3 70B Instruct", - "display_name": "Llama3 70B Instruct", + "id": "meta-llama/llama-3.3-70b-instruct", + "name": "Llama-3.3-70B-Instruct", + "display_name": "Llama-3.3-70B-Instruct", "modalities": { "input": [ "text" @@ -96753,24 +97414,25 @@ ] }, "limit": { - "context": 8192, - "output": 8000 + "context": 12288, + "output": 12288 }, "temperature": true, - "tool_call": false, + "tool_call": true, "reasoning": { "supported": false }, "attachment": false, "open_weights": true, - "release_date": "2024-04-25", - "last_updated": "2024-04-25", + "knowledge": "2023-12", + "release_date": "2024-12-06", + "last_updated": "2024-12-06", "type": "chat" }, { - "id": "meta-llama/llama-3.3-70b-instruct", - "name": "Llama 3.3 70B Instruct", - "display_name": "Llama 3.3 70B Instruct", + "id": "meta-llama/llama-3.1-8b-instruct", + "name": "Llama-3.1-8B-Instruct", + "display_name": "Llama-3.1-8B-Instruct", "modalities": { "input": [ "text" @@ -96780,8 +97442,8 @@ ] }, "limit": { - "context": 131072, - "output": 120000 + "context": 16384, + "output": 16384 }, "temperature": true, "tool_call": true, @@ -96791,14 +97453,14 @@ "attachment": false, "open_weights": true, "knowledge": "2023-12", - "release_date": "2024-12-07", - "last_updated": "2024-12-07", + "release_date": "2024-07-23", + "last_updated": "2024-07-23", "type": "chat" }, { - "id": "meta-llama/llama-3.1-8b-instruct", - "name": "Llama 3.1 8B Instruct", - "display_name": "Llama 3.1 8B Instruct", + "id": "meta-llama/llama-3.2-1b-instruct", + "name": "Llama 3.2 1B Instruct", + "display_name": "Llama 3.2 1B Instruct", "modalities": { "input": [ "text" @@ -96808,24 +97470,24 @@ ] }, "limit": { - "context": 16384, - "output": 16384 + "context": 131000, + "output": 32000 }, "temperature": true, - "tool_call": false, + "tool_call": true, "reasoning": { "supported": false }, "attachment": false, "open_weights": true, - "release_date": "2024-07-24", - "last_updated": "2024-07-24", + "release_date": "2024-09-25", + "last_updated": "2024-09-25", "type": "chat" }, { "id": "meta-llama/llama-4-scout-17b-16e-instruct", - "name": "Llama 4 Scout Instruct", - "display_name": "Llama 4 Scout Instruct", + "name": "Llama 4 Scout 17B Instruct", + "display_name": "Llama 4 Scout 17B Instruct", "modalities": { "input": [ "text", @@ -96840,68 +97502,15 @@ "output": 131072 }, "temperature": true, - "tool_call": false, + "tool_call": true, "reasoning": { "supported": false }, "attachment": true, "open_weights": true, - "release_date": "2025-04-06", - "last_updated": "2025-04-06", - "type": "chat" - }, - { - "id": "meta-llama/llama-3.2-3b-instruct", - "name": "Llama 3.2 3B Instruct", - "display_name": "Llama 3.2 3B Instruct", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 32768, - "output": 32000 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "release_date": "2024-09-18", - "last_updated": "2024-09-18", - "type": "chat" - }, - { - "id": "meta-llama/llama-3-8b-instruct", - "name": "Llama 3 8B Instruct", - "display_name": "Llama 3 8B Instruct", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 8192, - "output": 8192 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "release_date": "2024-04-25", - "last_updated": "2024-04-25", + "knowledge": "2024-08", + "release_date": "2025-04-05", + "last_updated": "2025-04-05", "type": "chat" }, { @@ -96921,31 +97530,34 @@ "output": 8192 }, "temperature": true, - "tool_call": false, + "tool_call": true, "reasoning": { "supported": false }, "attachment": false, "open_weights": true, - "release_date": "2024-06-27", - "last_updated": "2024-06-27", + "release_date": "2024-04-30", + "last_updated": "2024-04-30", "type": "chat" }, { - "id": "xiaomimimo/mimo-v2-flash", - "name": "XiaomiMiMo/MiMo-V2-Flash", - "display_name": "XiaomiMiMo/MiMo-V2-Flash", + "id": "xiaomimimo/mimo-v2.6-pro", + "name": "MiMo-V2.6-Pro", + "display_name": "MiMo-V2.6-Pro", "modalities": { "input": [ - "text" + "text", + "image", + "audio", + "video" ], "output": [ "text" ] }, "limit": { - "context": 262144, - "output": 32000 + "context": 1048576, + "output": 131072 }, "temperature": true, "tool_call": true, @@ -96953,20 +97565,32 @@ "supported": true, "default": true }, - "attachment": false, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": true, "open_weights": true, - "knowledge": "2024-12", - "release_date": "2025-12-19", - "last_updated": "2025-12-19", + "release_date": "2026-09-22", + "last_updated": "2026-09-22", "type": "chat" }, { - "id": "xiaomimimo/mimo-v2-pro", - "name": "MiMo-V2-Pro", - "display_name": "MiMo-V2-Pro", + "id": "xiaomimimo/mimo-v2.5", + "name": "MiMo-V2.5", + "display_name": "MiMo-V2.5", "modalities": { "input": [ - "text" + "text", + "image", + "video" ], "output": [ "text" @@ -96993,11 +97617,11 @@ ] } }, - "attachment": false, - "open_weights": false, + "attachment": true, + "open_weights": true, "knowledge": "2024-12", - "release_date": "2026-03-18", - "last_updated": "2026-05-27", + "release_date": "2026-04-22", + "last_updated": "2026-04-22", "type": "chat" }, { @@ -97037,46 +97661,18 @@ "open_weights": true, "knowledge": "2024-12", "release_date": "2026-04-22", - "last_updated": "2026-05-27", - "type": "chat" - }, - { - "id": "baidu/ernie-4.5-vl-28b-a3b", - "name": "ERNIE 4.5 VL 28B A3B", - "display_name": "ERNIE 4.5 VL 28B A3B", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 30000, - "output": 8000 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "attachment": true, - "open_weights": true, - "release_date": "2025-06-30", - "last_updated": "2026-06-14", + "last_updated": "2026-04-22", "type": "chat" }, { - "id": "baidu/ernie-4.5-vl-28b-a3b-thinking", - "name": "ERNIE-4.5-VL-28B-A3B-Thinking", - "display_name": "ERNIE-4.5-VL-28B-A3B-Thinking", + "id": "xiaomimimo/mimo-v2.6-flash", + "name": "MiMo-V2.6-Flash", + "display_name": "MiMo-V2.6-Flash", "modalities": { "input": [ "text", "image", + "audio", "video" ], "output": [ @@ -97084,8 +97680,8 @@ ] }, "limit": { - "context": 131072, - "output": 65536 + "context": 1048576, + "output": 131072 }, "temperature": true, "tool_call": true, @@ -97093,39 +97689,21 @@ "supported": true, "default": true }, - "attachment": true, - "open_weights": true, - "release_date": "2025-11-26", - "last_updated": "2025-11-26", - "type": "chat" - }, - { - "id": "baidu/ernie-4.5-21B-a3b-thinking", - "name": "ERNIE-4.5-21B-A3B-Thinking", - "display_name": "ERNIE-4.5-21B-A3B-Thinking", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 65536 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": true, - "default": true + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } }, - "attachment": false, + "attachment": true, "open_weights": true, - "knowledge": "2025-03", - "release_date": "2025-09-19", - "last_updated": "2025-09-19", + "release_date": "2026-09-22", + "last_updated": "2026-09-22", "type": "chat" }, { @@ -97151,71 +97729,53 @@ }, "attachment": false, "open_weights": true, - "knowledge": "2025-03", "release_date": "2025-06-30", "last_updated": "2025-06-30", "type": "chat" }, { - "id": "baidu/ernie-4.5-vl-424b-a47b", - "name": "ERNIE 4.5 VL 424B A47B", - "display_name": "ERNIE 4.5 VL 424B A47B", + "id": "baidu/cobuddy", + "name": "CoBuddy", + "display_name": "CoBuddy", "modalities": { "input": [ - "text", - "image" + "text" ], "output": [ "text" ] }, "limit": { - "context": 123000, - "output": 16000 + "context": 131072, + "output": 65536 }, "temperature": true, - "tool_call": false, + "tool_call": true, "reasoning": { "supported": true, "default": true }, - "attachment": true, - "open_weights": true, - "release_date": "2025-06-30", - "last_updated": "2025-06-30", - "type": "chat" - }, - { - "id": "baidu/ernie-4.5-300b-a47b-paddle", - "name": "ERNIE 4.5 300B A47B", - "display_name": "ERNIE 4.5 300B A47B", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 123000, - "output": 12000 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } }, "attachment": false, - "open_weights": true, - "release_date": "2025-06-30", - "last_updated": "2025-06-30", + "open_weights": false, + "release_date": "2026-05-06", + "last_updated": "2026-05-06", "type": "chat" }, { "id": "google/gemma-4-31b-it", - "name": "Gemma 4 31B", - "display_name": "Gemma 4 31B", + "name": "Gemma 4 31B IT", + "display_name": "Gemma 4 31B IT", "modalities": { "input": [ "text", @@ -97235,6 +97795,17 @@ "supported": true, "default": true }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, "attachment": true, "open_weights": true, "release_date": "2026-04-02", @@ -97243,8 +97814,8 @@ }, { "id": "google/gemma-3-27b-it", - "name": "Gemma 3 27B", - "display_name": "Gemma 3 27B", + "name": "Gemma 3 27B IT", + "display_name": "Gemma 3 27B IT", "modalities": { "input": [ "text", @@ -97259,20 +97830,21 @@ "output": 16384 }, "temperature": true, - "tool_call": false, + "tool_call": true, "reasoning": { "supported": false }, "attachment": true, "open_weights": true, - "release_date": "2025-03-25", - "last_updated": "2025-03-25", + "knowledge": "2024-08", + "release_date": "2025-03-12", + "last_updated": "2025-03-12", "type": "chat" }, { "id": "google/gemma-4-26b-a4b-it", - "name": "Gemma 4 26B A4B", - "display_name": "Gemma 4 26B A4B", + "name": "Gemma 4 26B A4B IT", + "display_name": "Gemma 4 26B A4B IT", "modalities": { "input": [ "text", @@ -97292,6 +97864,17 @@ "supported": true, "default": true }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, "attachment": true, "open_weights": true, "release_date": "2026-04-02", @@ -97300,8 +97883,8 @@ }, { "id": "google/gemma-3-12b-it", - "name": "Gemma 3 12B", - "display_name": "Gemma 3 12B", + "name": "Gemma 3 12B IT", + "display_name": "Gemma 3 12B IT", "modalities": { "input": [ "text", @@ -97316,20 +97899,21 @@ "output": 8192 }, "temperature": true, - "tool_call": false, + "tool_call": true, "reasoning": { "supported": false }, "attachment": true, "open_weights": true, - "release_date": "2025-03-13", - "last_updated": "2025-03-13", + "knowledge": "2024-08", + "release_date": "2025-03-12", + "last_updated": "2025-03-12", "type": "chat" }, { "id": "minimaxai/minimax-m1-80k", - "name": "MiniMax M1", - "display_name": "MiniMax M1", + "name": "MiniMax M1 80K", + "display_name": "MiniMax M1 80K", "modalities": { "input": [ "text" @@ -97355,9 +97939,9 @@ "type": "chat" }, { - "id": "mistralai/mistral-nemo", - "name": "Mistral Nemo", - "display_name": "Mistral Nemo", + "id": "inclusionai/ling-3.0-flash", + "name": "Ling 3.0 Flash", + "display_name": "Ling 3.0 Flash", "modalities": { "input": [ "text" @@ -97367,24 +97951,36 @@ ] }, "limit": { - "context": 60288, - "output": 16000 + "context": 262144, + "output": 32768 }, "temperature": true, - "tool_call": false, + "tool_call": true, "reasoning": { - "supported": false + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } }, "attachment": false, "open_weights": true, - "release_date": "2024-07-30", - "last_updated": "2024-07-30", + "release_date": "2026-07-23", + "last_updated": "2026-07-23", "type": "chat" }, { - "id": "inclusionai/ring-2.6-1t", - "name": "Ring-2.6-1T", - "display_name": "Ring-2.6-1T", + "id": "inclusionai/ling-3.1-flash", + "name": "Ling 3.1 Flash", + "display_name": "Ling 3.1 Flash", "modalities": { "input": [ "text" @@ -97395,24 +97991,34 @@ }, "limit": { "context": 262144, - "output": 65536 + "output": 32768 }, - "temperature": true, "tool_call": true, "reasoning": { "supported": true, "default": true }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, "attachment": false, "open_weights": false, - "release_date": "2026-05-08", - "last_updated": "2026-05-27", + "release_date": "2026-09-29", + "last_updated": "2026-09-29", "type": "chat" }, { - "id": "inclusionai/ling-2.6-1t", - "name": "Ling-2.6-1T", - "display_name": "Ling-2.6-1T", + "id": "inclusionai/ling-3.0-flash-sante", + "name": "Ling 3.0 Flash Sante", + "display_name": "Ling 3.0 Flash Sante", "modalities": { "input": [ "text" @@ -97428,18 +98034,71 @@ "temperature": true, "tool_call": true, "reasoning": { - "supported": false + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } }, "attachment": false, + "open_weights": false, + "release_date": "2026-09-04", + "last_updated": "2026-09-04", + "type": "chat" + }, + { + "id": "inclusionai/ling-3.0-flash-vl", + "name": "Ling 3.0 Flash VL", + "display_name": "Ling 3.0 Flash VL", + "modalities": { + "input": [ + "text", + "image", + "video" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 32768 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": true, "open_weights": true, - "release_date": "2026-04-23", - "last_updated": "2026-06-29", + "release_date": "2026-09-10", + "last_updated": "2026-09-10", "type": "chat" }, { - "id": "inclusionai/ling-2.6-flash", - "name": "Ling-2.6-flash", - "display_name": "Ling-2.6-flash", + "id": "inclusionai/ling-3.0-flash-fin", + "name": "Ling 3.0 Flash Fin", + "display_name": "Ling 3.0 Flash Fin", "modalities": { "input": [ "text" @@ -97452,15 +98111,26 @@ "context": 262144, "output": 32768 }, - "temperature": true, "tool_call": true, "reasoning": { - "supported": false + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } }, "attachment": false, "open_weights": true, - "release_date": "2026-04-24", - "last_updated": "2026-04-24", + "release_date": "2026-08-27", + "last_updated": "2026-09-03", "type": "chat" }, { @@ -97490,7 +98160,14 @@ "extra_capabilities": { "reasoning": { "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], "effort_options": [ + "none", "low", "high", "max" @@ -97580,8 +98257,9 @@ }, "attachment": false, "open_weights": true, - "release_date": "2025-11-07", - "last_updated": "2026-06-29", + "knowledge": "2024-08", + "release_date": "2025-11-06", + "last_updated": "2025-11-06", "type": "chat" }, { @@ -97602,7 +98280,7 @@ "context": 262144, "output": 262144 }, - "temperature": true, + "temperature": false, "tool_call": true, "reasoning": { "supported": true, @@ -97622,8 +98300,8 @@ "attachment": true, "open_weights": true, "knowledge": "2025-01", - "release_date": "2026-01-27", - "last_updated": "2026-01-27", + "release_date": "2026-01", + "last_updated": "2026-01", "type": "chat" }, { @@ -97640,7 +98318,7 @@ }, "limit": { "context": 131072, - "output": 32768 + "output": 98304 }, "temperature": true, "tool_call": true, @@ -97655,8 +98333,8 @@ }, { "id": "moonshotai/kimi-k2-0905", - "name": "Kimi K2 0905", - "display_name": "Kimi K2 0905", + "name": "Kimi K2 Instruct 0905", + "display_name": "Kimi K2 Instruct 0905", "modalities": { "input": [ "text" @@ -97676,7 +98354,6 @@ }, "attachment": false, "open_weights": true, - "knowledge": "2024-10", "release_date": "2025-09-05", "last_updated": "2025-09-05", "type": "chat" @@ -97707,7 +98384,13 @@ }, "extra_capabilities": { "reasoning": { - "supported": true + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] } }, "attachment": true, @@ -97719,13 +98402,13 @@ }, { "id": "zai-org/glm-4.6v", - "name": "GLM 4.6V", - "display_name": "GLM 4.6V", + "name": "GLM-4.6V", + "display_name": "GLM-4.6V", "modalities": { "input": [ "text", - "video", - "image" + "image", + "video" ], "output": [ "text" @@ -97741,6 +98424,17 @@ "supported": true, "default": true }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, "attachment": true, "open_weights": true, "knowledge": "2025-04", @@ -97749,20 +98443,22 @@ "type": "chat" }, { - "id": "zai-org/glm-4.5", - "name": "GLM-4.5", - "display_name": "GLM-4.5", + "id": "zai-org/glm-5.3-flash", + "name": "GLM-5.3-Flash", + "display_name": "GLM-5.3-Flash", "modalities": { "input": [ - "text" + "text", + "image", + "video" ], "output": [ "text" ] }, "limit": { - "context": 131072, - "output": 98304 + "context": 1048576, + "output": 131072 }, "temperature": true, "tool_call": true, @@ -97778,19 +98474,24 @@ "visibility": "summary", "continuation": [ "thinking_blocks" + ], + "effort_options": [ + "low", + "high", + "max" ] } }, - "attachment": false, + "attachment": true, "open_weights": true, - "release_date": "2025-07-28", - "last_updated": "2025-07-28", + "release_date": "2026-08-26", + "last_updated": "2026-08-26", "type": "chat" }, { "id": "zai-org/glm-4.6", - "name": "GLM 4.6", - "display_name": "GLM 4.6", + "name": "GLM-4.6", + "display_name": "GLM-4.6", "modalities": { "input": [ "text" @@ -97822,6 +98523,7 @@ }, "attachment": false, "open_weights": true, + "knowledge": "2025-04", "release_date": "2025-09-30", "last_updated": "2025-09-30", "type": "chat" @@ -97861,19 +98563,19 @@ }, "attachment": false, "open_weights": true, - "release_date": "2026-02-11", + "release_date": "2026-02-12", "last_updated": "2026-02-12", "type": "chat" }, { "id": "zai-org/glm-4.5v", - "name": "GLM 4.5V", - "display_name": "GLM 4.5V", + "name": "GLM-4.5V", + "display_name": "GLM-4.5V", "modalities": { "input": [ "text", - "video", - "image" + "image", + "video" ], "output": [ "text" @@ -97889,6 +98591,17 @@ "supported": true, "default": true }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, "attachment": true, "open_weights": true, "knowledge": "2025-04", @@ -97920,7 +98633,13 @@ }, "extra_capabilities": { "reasoning": { - "supported": true + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] } }, "attachment": false, @@ -97965,6 +98684,7 @@ }, "attachment": false, "open_weights": true, + "knowledge": "2025-04", "release_date": "2025-12-22", "last_updated": "2025-12-22", "type": "chat" @@ -98048,14 +98768,14 @@ }, "attachment": false, "open_weights": true, - "release_date": "2026-03-27", - "last_updated": "2026-03-27", + "release_date": "2026-04-07", + "last_updated": "2026-04-07", "type": "chat" }, { "id": "zai-org/autoglm-phone-9b-multilingual", - "name": "AutoGLM-Phone-9B-Multilingual", - "display_name": "AutoGLM-Phone-9B-Multilingual", + "name": "AutoGLM Phone 9B Multilingual", + "display_name": "AutoGLM Phone 9B Multilingual", "modalities": { "input": [ "text", @@ -98082,8 +98802,8 @@ }, { "id": "zai-org/glm-4.5-air", - "name": "GLM 4.5 Air", - "display_name": "GLM 4.5 Air", + "name": "GLM-4.5-Air", + "display_name": "GLM-4.5-Air", "modalities": { "input": [ "text" @@ -98102,17 +98822,28 @@ "supported": true, "default": true }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, "attachment": false, "open_weights": true, "knowledge": "2025-04", - "release_date": "2025-10-13", - "last_updated": "2025-10-13", + "release_date": "2025-07-28", + "last_updated": "2025-07-28", "type": "chat" }, { - "id": "gryphe/mythomax-l2-13b", - "name": "Mythomax L2 13B", - "display_name": "Mythomax L2 13B", + "id": "zai-org/glm-5.3", + "name": "GLM-5.3", + "display_name": "GLM-5.3", "modalities": { "input": [ "text" @@ -98122,24 +98853,42 @@ ] }, "limit": { - "context": 4096, - "output": 3200 + "context": 1048576, + "output": 131072 }, "temperature": true, - "tool_call": false, + "tool_call": true, "reasoning": { - "supported": false + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "effort_options": [ + "none", + "low", + "high", + "max" + ] + } }, "attachment": false, "open_weights": true, - "release_date": "2024-04-25", - "last_updated": "2024-04-25", + "release_date": "2026-08-14", + "last_updated": "2026-08-14", "type": "chat" }, { - "id": "minimax/minimax-m2.5", - "name": "MiniMax M2.5", - "display_name": "MiniMax M2.5", + "id": "apodex/apodex-1.1-mini", + "name": "Apodex 1.1 Mini", + "display_name": "Apodex 1.1 Mini", "modalities": { "input": [ "text" @@ -98149,8 +98898,8 @@ ] }, "limit": { - "context": 204800, - "output": 131072 + "context": 262144, + "output": 262144 }, "temperature": true, "tool_call": true, @@ -98170,15 +98919,15 @@ } }, "attachment": false, - "open_weights": false, - "release_date": "2026-02-12", - "last_updated": "2026-02-12", + "open_weights": true, + "release_date": "2026-08-24", + "last_updated": "2026-08-24", "type": "chat" }, { - "id": "minimax/minimax-m2.7", - "name": "MiniMax M2.7", - "display_name": "MiniMax M2.7", + "id": "nvidia/nemotron-3-nano-30b-a3b", + "name": "Nemotron 3 Nano 30B A3B", + "display_name": "Nemotron 3 Nano 30B A3B", "modalities": { "input": [ "text" @@ -98188,8 +98937,8 @@ ] }, "limit": { - "context": 204800, - "output": 131072 + "context": 262144, + "output": 32768 }, "temperature": true, "tool_call": true, @@ -98210,14 +98959,41 @@ }, "attachment": false, "open_weights": true, - "release_date": "2026-03-18", - "last_updated": "2026-03-18", + "release_date": "2025-12-15", + "last_updated": "2025-12-15", "type": "chat" }, { - "id": "minimax/minimax-m2.7-highspeed", - "name": "MiniMax-M2.7-highspeed", - "display_name": "MiniMax-M2.7-highspeed", + "id": "gryphe/mythomax-l2-13b", + "name": "MythoMax L2 13B", + "display_name": "MythoMax L2 13B", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 4096, + "output": 3200 + }, + "temperature": true, + "tool_call": false, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "release_date": "2023-08-10", + "last_updated": "2023-08-10", + "type": "chat" + }, + { + "id": "minimax/minimax-m2.5", + "name": "MiniMax-M2.5", + "display_name": "MiniMax-M2.5", "modalities": { "input": [ "text" @@ -98228,7 +99004,7 @@ }, "limit": { "context": 204800, - "output": 131072 + "output": 131100 }, "temperature": true, "tool_call": true, @@ -98249,14 +99025,14 @@ }, "attachment": false, "open_weights": true, - "release_date": "2026-03-18", - "last_updated": "2026-05-27", + "release_date": "2026-02-12", + "last_updated": "2026-02-12", "type": "chat" }, { - "id": "minimax/minimax-m2.5-highspeed", - "name": "MiniMax M2.5 Highspeed", - "display_name": "MiniMax M2.5 Highspeed", + "id": "minimax/minimax-m2.7", + "name": "MiniMax-M2.7", + "display_name": "MiniMax-M2.7", "modalities": { "input": [ "text" @@ -98287,31 +99063,34 @@ } }, "attachment": false, - "open_weights": false, - "release_date": "2026-02-12", - "last_updated": "2026-02-12", + "open_weights": true, + "release_date": "2026-03-18", + "last_updated": "2026-03-18", "type": "chat" }, { - "id": "minimax/minimax-m2.1", - "name": "Minimax M2.1", - "display_name": "Minimax M2.1", + "id": "minimax/minimax-m3", + "name": "MiniMax-M3", + "display_name": "MiniMax-M3", "modalities": { "input": [ - "text" + "text", + "image", + "video" ], "output": [ "text" ] }, "limit": { - "context": 204800, + "context": 1000000, "output": 131072 }, "temperature": true, "tool_call": true, "reasoning": { - "supported": true + "supported": true, + "default": true }, "extra_capabilities": { "reasoning": { @@ -98324,16 +99103,16 @@ ] } }, - "attachment": false, + "attachment": true, "open_weights": true, - "release_date": "2025-12-23", - "last_updated": "2025-12-23", + "release_date": "2026-06-01", + "last_updated": "2026-06-01", "type": "chat" }, { - "id": "minimax/minimax-m2", - "name": "MiniMax-M2", - "display_name": "MiniMax-M2", + "id": "minimax/minimax-m2.7-highspeed", + "name": "MiniMax-M2.7-highspeed", + "display_name": "MiniMax-M2.7-highspeed", "modalities": { "input": [ "text" @@ -98365,14 +99144,14 @@ }, "attachment": false, "open_weights": true, - "release_date": "2025-10-27", - "last_updated": "2025-10-27", + "release_date": "2026-03-18", + "last_updated": "2026-03-18", "type": "chat" }, { "id": "paddlepaddle/paddleocr-vl", - "name": "PaddleOCR-VL", - "display_name": "PaddleOCR-VL", + "name": "PaddleOCR VL", + "display_name": "PaddleOCR VL", "modalities": { "input": [ "text", @@ -98393,14 +99172,14 @@ }, "attachment": true, "open_weights": true, - "release_date": "2025-10-22", - "last_updated": "2025-10-22", + "release_date": "2025-10-16", + "last_updated": "2025-10-16", "type": "chat" }, { - "id": "qwen/qwen3-vl-235b-a22b-instruct", - "name": "Qwen3 VL 235B A22B Instruct", - "display_name": "Qwen3 VL 235B A22B Instruct", + "id": "stepfun/step-3.7-flash", + "name": "Step 3.7 Flash", + "display_name": "Step 3.7 Flash", "modalities": { "input": [ "text", @@ -98412,24 +99191,42 @@ ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 262144, + "output": 256000 }, "temperature": true, "tool_call": true, "reasoning": { - "supported": false + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "effort_options": [ + "low", + "medium", + "high" + ] + } }, "attachment": true, "open_weights": true, - "release_date": "2025-09-24", - "last_updated": "2025-09-24", + "knowledge": "2026-03-01", + "release_date": "2026-05-29", + "last_updated": "2026-05-29", "type": "chat" }, { - "id": "qwen/qwen3.7-max", - "name": "Qwen3.7-Max", - "display_name": "Qwen3.7-Max", + "id": "mindai/macaron-v1-tall", + "name": "Macaron V1 Tall", + "display_name": "Macaron V1 Tall", "modalities": { "input": [ "text" @@ -98439,8 +99236,8 @@ ] }, "limit": { - "context": 1000000, - "output": 65536 + "context": 262144, + "output": 32768 }, "temperature": true, "tool_call": true, @@ -98450,35 +99247,43 @@ }, "extra_capabilities": { "reasoning": { - "supported": true + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "effort_options": [ + "none", + "high" + ] } }, "attachment": false, - "open_weights": false, - "release_date": "2026-05-21", - "last_updated": "2026-05-27", + "open_weights": true, + "release_date": "2026-07-21", + "last_updated": "2026-07-21", "type": "chat" }, { - "id": "qwen/qwen3-vl-235b-a22b-thinking", - "name": "Qwen3 VL 235B A22B Thinking", - "display_name": "Qwen3 VL 235B A22B Thinking", + "id": "mindai/macaron-v1-venti", + "name": "Macaron V1 Venti", + "display_name": "Macaron V1 Venti", "modalities": { "input": [ - "text", - "image", - "video" + "text" ], "output": [ "text" ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 1048576, + "output": 131072 }, "temperature": true, - "tool_call": false, + "tool_call": true, "reasoning": { "supported": true, "default": true @@ -98491,31 +99296,34 @@ "visibility": "summary", "continuation": [ "thinking_blocks" + ], + "effort_options": [ + "none", + "high", + "max" ] } }, - "attachment": true, + "attachment": false, "open_weights": true, - "release_date": "2025-09-24", - "last_updated": "2025-09-24", + "release_date": "2026-07-21", + "last_updated": "2026-07-21", "type": "chat" }, { - "id": "qwen/qwen3.5-27b", - "name": "Qwen3.5-27B", - "display_name": "Qwen3.5-27B", + "id": "qwen/qwen3.7-max", + "name": "Qwen3.7 Max", + "display_name": "Qwen3.7 Max", "modalities": { "input": [ - "text", - "image", - "video" + "text" ], "output": [ "text" ] }, "limit": { - "context": 262144, + "context": 1000000, "output": 65536 }, "temperature": true, @@ -98535,55 +99343,29 @@ ] } }, - "attachment": true, - "open_weights": true, - "release_date": "2026-02-26", - "last_updated": "2026-02-26", - "type": "chat" - }, - { - "id": "qwen/qwen3-235b-a22b-instruct-2507", - "name": "Qwen3 235B A22B Instruct 2507", - "display_name": "Qwen3 235B A22B Instruct 2507", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 16384 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, "attachment": false, - "open_weights": true, - "knowledge": "2025-04", - "release_date": "2025-07-22", - "last_updated": "2025-07-22", + "open_weights": false, + "release_date": "2026-05-21", + "last_updated": "2026-05-21", "type": "chat" }, { - "id": "qwen/qwen3-next-80b-a3b-thinking", - "name": "Qwen3 Next 80B A3B Thinking", - "display_name": "Qwen3 Next 80B A3B Thinking", + "id": "qwen/qwen3.8-27b", + "name": "Qwen3.8 27B", + "display_name": "Qwen3.8 27B", "modalities": { "input": [ - "text" + "text", + "image", + "video" ], "output": [ "text" ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 1000000, + "output": 131072 }, "temperature": true, "tool_call": true, @@ -98599,19 +99381,24 @@ "visibility": "summary", "continuation": [ "thinking_blocks" + ], + "effort_options": [ + "low", + "medium", + "xhigh" ] } }, - "attachment": false, + "attachment": true, "open_weights": true, - "release_date": "2025-09-10", - "last_updated": "2025-09-10", + "release_date": "2026-08-14", + "last_updated": "2026-08-14", "type": "chat" }, { - "id": "qwen/qwen3-coder-next", - "name": "Qwen3 Coder Next", - "display_name": "Qwen3 Coder Next", + "id": "qwen/qwen3.8-2.4t-a95b", + "name": "Qwen3.8 2.4T A95B", + "display_name": "Qwen3.8 2.4T A95B", "modalities": { "input": [ "text" @@ -98621,70 +99408,54 @@ ] }, "limit": { - "context": 262144, - "output": 65536 + "context": 1000000, + "output": 131072 }, "temperature": true, "tool_call": true, "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "release_date": "2026-02-03", - "last_updated": "2026-02-03", - "type": "chat" - }, - { - "id": "qwen/qwen3-omni-30b-a3b-instruct", - "name": "Qwen3 Omni 30B A3B Instruct", - "display_name": "Qwen3 Omni 30B A3B Instruct", - "modalities": { - "input": [ - "text", - "video", - "audio", - "image" - ], - "output": [ - "text", - "audio" - ] - }, - "limit": { - "context": 65536, - "output": 16384 + "supported": true, + "default": true }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "effort_options": [ + "low", + "medium", + "xhigh" + ] + } }, - "attachment": true, + "attachment": false, "open_weights": true, - "knowledge": "2024-04", - "release_date": "2025-09-24", - "last_updated": "2025-09-24", + "release_date": "2026-08-12", + "last_updated": "2026-08-12", "type": "chat" }, { - "id": "qwen/qwen3-omni-30b-a3b-thinking", - "name": "Qwen3 Omni 30B A3B Thinking", - "display_name": "Qwen3 Omni 30B A3B Thinking", + "id": "qwen/qwen3.5-27b", + "name": "Qwen3.5 27B", + "display_name": "Qwen3.5 27B", "modalities": { "input": [ "text", - "audio", - "video", - "image" + "image", + "video" ], "output": [ "text" ] }, "limit": { - "context": 65536, - "output": 16384 + "context": 262144, + "output": 65536 }, "temperature": true, "tool_call": true, @@ -98705,30 +99476,33 @@ }, "attachment": true, "open_weights": true, - "release_date": "2025-09-24", - "last_updated": "2025-09-24", + "release_date": "2026-02-23", + "last_updated": "2026-02-23", "type": "chat" }, { - "id": "qwen/qwen3-max", - "name": "Qwen3 Max", - "display_name": "Qwen3 Max", + "id": "qwen/qwen3.8-max", + "name": "Qwen3.8 Max", + "display_name": "Qwen3.8 Max", "modalities": { "input": [ - "text" + "text", + "image", + "video" ], "output": [ "text" ] }, "limit": { - "context": 262144, - "output": 65536 + "context": 1000000, + "output": 131072 }, "temperature": true, "tool_call": true, "reasoning": { - "supported": true + "supported": true, + "default": true }, "extra_capabilities": { "reasoning": { @@ -98738,76 +99512,66 @@ "visibility": "summary", "continuation": [ "thinking_blocks" + ], + "effort_options": [ + "low", + "medium", + "xhigh" ] } }, - "attachment": false, + "attachment": true, "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-09-24", - "last_updated": "2025-09-24", + "release_date": "2026-08-03", + "last_updated": "2026-08-03", "type": "chat" }, { - "id": "qwen/qwen3-235b-a22b-fp8", - "name": "Qwen3 235B A22B", - "display_name": "Qwen3 235B A22B", + "id": "qwen/qwen3-omni-30b-a3b-thinking", + "name": "Qwen3 Omni 30B A3B Thinking", + "display_name": "Qwen3 Omni 30B A3B Thinking", "modalities": { "input": [ - "text" + "text", + "image", + "video", + "audio" ], "output": [ "text" ] }, "limit": { - "context": 40960, - "output": 20000 + "context": 65536, + "output": 16384 }, "temperature": true, - "tool_call": false, + "tool_call": true, "reasoning": { "supported": true, "default": true }, - "attachment": false, - "open_weights": true, - "release_date": "2025-04-29", - "last_updated": "2025-04-29", - "type": "chat" - }, - { - "id": "qwen/qwen3-coder-480b-a35b-instruct", - "name": "Qwen3 Coder 480B A35B Instruct", - "display_name": "Qwen3 Coder 480B A35B Instruct", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } }, - "attachment": false, + "attachment": true, "open_weights": true, - "knowledge": "2025-04", - "release_date": "2025-07-23", - "last_updated": "2025-07-23", + "release_date": "2025-09-22", + "last_updated": "2025-09-22", "type": "chat" }, { - "id": "qwen/qwen3-coder-30b-a3b-instruct", - "name": "Qwen3 Coder 30b A3B Instruct", - "display_name": "Qwen3 Coder 30b A3B Instruct", + "id": "qwen/qwen3-reranker-8b", + "name": "Qwen3 Reranker 8B", + "display_name": "Qwen3 Reranker 8B", "modalities": { "input": [ "text" @@ -98817,29 +99581,29 @@ ] }, "limit": { - "context": 160000, - "output": 32768 + "context": 32768, + "output": 8192 }, - "temperature": true, - "tool_call": true, + "temperature": false, + "tool_call": false, "reasoning": { "supported": false }, "attachment": false, "open_weights": true, - "release_date": "2025-10-09", - "last_updated": "2025-10-09", - "type": "chat" + "release_date": "2025-06-05", + "last_updated": "2025-06-05", + "type": "rerank" }, { "id": "qwen/qwen3-vl-30b-a3b-instruct", - "name": "qwen/qwen3-vl-30b-a3b-instruct", - "display_name": "qwen/qwen3-vl-30b-a3b-instruct", + "name": "Qwen3 VL 30B A3B Instruct", + "display_name": "Qwen3 VL 30B A3B Instruct", "modalities": { "input": [ "text", - "video", - "image" + "image", + "video" ], "output": [ "text" @@ -98856,25 +99620,27 @@ }, "attachment": true, "open_weights": true, - "release_date": "2025-10-11", - "last_updated": "2025-10-11", + "release_date": "2025-10-04", + "last_updated": "2025-10-04", "type": "chat" }, { - "id": "qwen/qwen3-235b-a22b-thinking-2507", - "name": "Qwen3 235B A22b Thinking 2507", - "display_name": "Qwen3 235B A22b Thinking 2507", + "id": "qwen/qwen3.5-122b-a10b", + "name": "Qwen3.5 122B-A10B", + "display_name": "Qwen3.5 122B-A10B", "modalities": { "input": [ - "text" + "text", + "image", + "video" ], "output": [ "text" ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 262144, + "output": 65536 }, "temperature": true, "tool_call": true, @@ -98893,44 +99659,16 @@ ] } }, - "attachment": false, - "open_weights": true, - "knowledge": "2025-04", - "release_date": "2025-07-25", - "last_updated": "2025-07-25", - "type": "chat" - }, - { - "id": "qwen/qwen2.5-7b-instruct", - "name": "Qwen2.5 7B Instruct", - "display_name": "Qwen2.5 7B Instruct", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 32000, - "output": 32000 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, + "attachment": true, "open_weights": true, - "release_date": "2025-04-16", - "last_updated": "2025-04-16", + "release_date": "2026-02-23", + "last_updated": "2026-02-23", "type": "chat" }, { - "id": "qwen/qwen3.5-122b-a10b", - "name": "Qwen3.5-122B-A10B", - "display_name": "Qwen3.5-122B-A10B", + "id": "qwen/qwen3.6-35b-a3b", + "name": "Qwen3.6 35B-A3B", + "display_name": "Qwen3.6 35B-A3B", "modalities": { "input": [ "text", @@ -98964,14 +99702,14 @@ }, "attachment": true, "open_weights": true, - "release_date": "2026-02-26", - "last_updated": "2026-02-26", + "release_date": "2026-04-17", + "last_updated": "2026-04-17", "type": "chat" }, { - "id": "qwen/qwen3-30b-a3b-fp8", - "name": "Qwen3 30B A3B", - "display_name": "Qwen3 30B A3B", + "id": "qwen/qwen-mt-plus", + "name": "Qwen MT Plus", + "display_name": "Qwen MT Plus", "modalities": { "input": [ "text" @@ -98981,52 +99719,24 @@ ] }, "limit": { - "context": 40960, - "output": 20000 + "context": 16384, + "output": 8192 }, "temperature": true, "tool_call": false, - "reasoning": { - "supported": true, - "default": true - }, - "attachment": false, - "open_weights": true, - "release_date": "2025-04-29", - "last_updated": "2025-04-29", - "type": "chat" - }, - { - "id": "qwen/qwen3-next-80b-a3b-instruct", - "name": "Qwen3 Next 80B A3B Instruct", - "display_name": "Qwen3 Next 80B A3B Instruct", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, "reasoning": { "supported": false }, "attachment": false, - "open_weights": true, - "release_date": "2025-09-10", - "last_updated": "2025-09-10", + "open_weights": false, + "release_date": "2025-07-24", + "last_updated": "2025-07-24", "type": "chat" }, { - "id": "qwen/qwen3-vl-30b-a3b-thinking", - "name": "qwen/qwen3-vl-30b-a3b-thinking", - "display_name": "qwen/qwen3-vl-30b-a3b-thinking", + "id": "qwen/qwen3.8-flash", + "name": "Qwen3.8 Flash", + "display_name": "Qwen3.8 Flash", "modalities": { "input": [ "text", @@ -99038,13 +99748,13 @@ ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 1000000, + "output": 131072 }, - "temperature": true, "tool_call": true, "reasoning": { - "supported": true + "supported": true, + "default": true }, "extra_capabilities": { "reasoning": { @@ -99054,19 +99764,24 @@ "visibility": "summary", "continuation": [ "thinking_blocks" + ], + "effort_options": [ + "low", + "medium", + "xhigh" ] } }, "attachment": true, - "open_weights": true, - "release_date": "2025-10-11", - "last_updated": "2025-10-11", + "open_weights": false, + "release_date": "2026-08-26", + "last_updated": "2026-08-26", "type": "chat" }, { - "id": "qwen/qwen-mt-plus", - "name": "Qwen MT Plus", - "display_name": "Qwen MT Plus", + "id": "qwen/qwen3-embedding-8b", + "name": "Qwen3 Embedding 8B", + "display_name": "Qwen3 Embedding 8B", "modalities": { "input": [ "text" @@ -99076,80 +99791,24 @@ ] }, "limit": { - "context": 16384, + "context": 32768, "output": 8192 }, - "temperature": true, + "temperature": false, "tool_call": false, "reasoning": { "supported": false }, "attachment": false, "open_weights": true, - "release_date": "2025-09-03", - "last_updated": "2025-09-03", - "type": "chat" - }, - { - "id": "qwen/qwen3-32b-fp8", - "name": "Qwen3 32B", - "display_name": "Qwen3 32B", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 40960, - "output": 20000 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": true, - "default": true - }, - "attachment": false, - "open_weights": true, - "release_date": "2025-04-29", - "last_updated": "2025-04-29", - "type": "chat" - }, - { - "id": "qwen/qwen3-8b-fp8", - "name": "Qwen3 8B", - "display_name": "Qwen3 8B", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 128000, - "output": 20000 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": true, - "default": true - }, - "attachment": false, - "open_weights": true, - "release_date": "2025-04-29", - "last_updated": "2025-04-29", - "type": "chat" + "release_date": "2025-06-05", + "last_updated": "2025-06-05", + "type": "embedding" }, { "id": "qwen/qwen3.5-35b-a3b", - "name": "Qwen3.5-35B-A3B", - "display_name": "Qwen3.5-35B-A3B", + "name": "Qwen3.5 35B-A3B", + "display_name": "Qwen3.5 35B-A3B", "modalities": { "input": [ "text", @@ -99183,14 +99842,14 @@ }, "attachment": true, "open_weights": true, - "release_date": "2026-02-26", - "last_updated": "2026-02-26", + "release_date": "2026-02-23", + "last_updated": "2026-02-23", "type": "chat" }, { "id": "qwen/qwen3.5-397b-a17b", - "name": "Qwen3.5-397B-A17B", - "display_name": "Qwen3.5-397B-A17B", + "name": "Qwen3.5 397B-A17B", + "display_name": "Qwen3.5 397B-A17B", "modalities": { "input": [ "text", @@ -99203,7 +99862,7 @@ }, "limit": { "context": 262144, - "output": 64000 + "output": 65536 }, "temperature": true, "tool_call": true, @@ -99224,43 +99883,14 @@ }, "attachment": true, "open_weights": true, - "release_date": "2026-02-17", - "last_updated": "2026-02-17", - "type": "chat" - }, - { - "id": "qwen/qwen3-vl-8b-instruct", - "name": "qwen/qwen3-vl-8b-instruct", - "display_name": "qwen/qwen3-vl-8b-instruct", - "modalities": { - "input": [ - "text", - "image", - "video" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": true, - "open_weights": true, - "release_date": "2025-10-17", - "last_updated": "2025-10-17", + "release_date": "2026-02-15", + "last_updated": "2026-02-15", "type": "chat" }, { - "id": "qwen/qwen2.5-vl-72b-instruct", - "name": "Qwen2.5 VL 72B Instruct", - "display_name": "Qwen2.5 VL 72B Instruct", + "id": "qwen/qwen3.6-27b", + "name": "Qwen3.6 27B", + "display_name": "Qwen3.6 27B", "modalities": { "input": [ "text", @@ -99272,80 +99902,36 @@ ] }, "limit": { - "context": 32768, - "output": 32768 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false - }, - "attachment": true, - "open_weights": true, - "release_date": "2025-03-25", - "last_updated": "2025-03-25", - "type": "chat" - }, - { - "id": "qwen/qwen-2.5-72b-instruct", - "name": "Qwen 2.5 72B Instruct", - "display_name": "Qwen 2.5 72B Instruct", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 32000, - "output": 8192 + "context": 262144, + "output": 65536 }, "temperature": true, "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "knowledge": "2024-04", - "release_date": "2024-10-15", - "last_updated": "2024-10-15", - "type": "chat" - }, - { - "id": "qwen/qwen3-4b-fp8", - "name": "Qwen3 4B", - "display_name": "Qwen3 4B", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 128000, - "output": 20000 - }, - "temperature": true, - "tool_call": false, "reasoning": { "supported": true, "default": true }, - "attachment": false, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": true, "open_weights": true, - "release_date": "2025-04-29", - "last_updated": "2025-04-29", + "release_date": "2026-04-22", + "last_updated": "2026-04-22", "type": "chat" }, { "id": "baichuan/baichuan-m2-32b", - "name": "baichuan-m2-32b", - "display_name": "baichuan-m2-32b", + "name": "Baichuan M2 32B", + "display_name": "Baichuan M2 32B", "modalities": { "input": [ "text" @@ -99361,62 +99947,22 @@ "temperature": true, "tool_call": false, "reasoning": { - "supported": false + "supported": true, + "default": true }, "attachment": false, "open_weights": true, - "knowledge": "2024-12", "release_date": "2025-08-13", "last_updated": "2025-08-13", "type": "chat" }, - { - "id": "openai/gpt-oss-20b", - "name": "OpenAI: GPT OSS 20B", - "display_name": "OpenAI: GPT OSS 20B", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "effort_options": [ - "low", - "medium", - "high" - ] - } - }, - "attachment": true, - "open_weights": true, - "release_date": "2025-08-06", - "last_updated": "2025-08-06", - "type": "chat" - }, { "id": "openai/gpt-oss-120b", - "name": "OpenAI GPT OSS 120B", - "display_name": "OpenAI GPT OSS 120B", + "name": "GPT OSS 120B", + "display_name": "GPT OSS 120B", "modalities": { "input": [ - "text", - "image" + "text" ], "output": [ "text" @@ -99435,6 +99981,12 @@ "extra_capabilities": { "reasoning": { "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], "effort_options": [ "low", "medium", @@ -99442,16 +99994,16 @@ ] } }, - "attachment": true, + "attachment": false, "open_weights": true, - "release_date": "2025-08-06", - "last_updated": "2025-08-06", + "release_date": "2025-08-05", + "last_updated": "2025-08-05", "type": "chat" }, { "id": "microsoft/wizardlm-2-8x22b", - "name": "Wizardlm 2 8x22B", - "display_name": "Wizardlm 2 8x22B", + "name": "WizardLM 2 8x22B", + "display_name": "WizardLM 2 8x22B", "modalities": { "input": [ "text" @@ -99471,116 +100023,8 @@ }, "attachment": false, "open_weights": true, - "release_date": "2024-04-24", - "last_updated": "2024-04-24", - "type": "chat" - }, - { - "id": "sao10K/l3-70b-euryale-v2.1", - "name": "L3 70B Euryale V2.1\t", - "display_name": "L3 70B Euryale V2.1\t", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 8192, - "output": 8192 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "release_date": "2024-06-18", - "last_updated": "2024-06-18", - "type": "chat" - }, - { - "id": "sao10K/L3-8B-stheno-v3.2", - "name": "L3 8B Stheno V3.2", - "display_name": "L3 8B Stheno V3.2", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 8192, - "output": 32000 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "release_date": "2024-11-29", - "last_updated": "2024-11-29", - "type": "chat" - }, - { - "id": "sao10K/l3-8b-lunaris", - "name": "Sao10k L3 8B Lunaris\t", - "display_name": "Sao10k L3 8B Lunaris\t", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 8192, - "output": 8192 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "release_date": "2024-11-28", - "last_updated": "2024-11-28", - "type": "chat" - }, - { - "id": "sao10K/l31-70b-euryale-v2.2", - "name": "L31 70B Euryale V2.2", - "display_name": "L31 70B Euryale V2.2", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 8192, - "output": 8192 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "release_date": "2024-09-19", - "last_updated": "2024-09-19", + "release_date": "2024-04-15", + "last_updated": "2024-04-15", "type": "chat" } ] @@ -101464,6 +101908,48 @@ "last_updated": "2025-10-08", "type": "chat" }, + { + "id": "gpt-6.1-sol", + "name": "GPT-6.1 Sol", + "display_name": "GPT-6.1 Sol", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1050000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-04-30", + "release_date": "2026-09-29", + "last_updated": "2026-09-29", + "type": "chat" + }, { "id": "claude-opus-4-5-20251101", "name": "claude-opus-4-5-20251101", @@ -103672,6 +104158,48 @@ "last_updated": "2026-07-09", "type": "chat" }, + { + "id": "claude-haiku-5-5", + "name": "Claude Haiku 5.5", + "display_name": "Claude Haiku 5.5", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-06", + "release_date": "2026-10-07", + "last_updated": "2026-10-07", + "type": "chat" + }, { "id": "gemini-3.8-flash", "name": "Gemini 3.8 Flash", @@ -118594,6 +119122,111 @@ "api": "https://moark.com/v1", "doc": "https://moark.com/docs/openapi/v1#tag/%E6%96%87%E6%9C%AC%E7%94%9F%E6%88%90", "models": [ + { + "id": "Kimi-K2.6", + "name": "Kimi K2.6", + "display_name": "Kimi K2.6", + "modalities": { + "input": [ + "text", + "image", + "video" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 262144 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true + } + }, + "attachment": true, + "open_weights": true, + "knowledge": "2025-01", + "release_date": "2026-04-21", + "last_updated": "2026-04-21", + "type": "chat" + }, + { + "id": "deepseek-v4-flash-0731", + "name": "DeepSeek V4 Flash 0731", + "display_name": "DeepSeek V4 Flash 0731", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 384000 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true + } + }, + "attachment": false, + "open_weights": true, + "knowledge": "2025-05", + "release_date": "2026-07-31", + "last_updated": "2026-07-31", + "type": "chat" + }, + { + "id": "kimi-k3", + "name": "Kimi K3", + "display_name": "Kimi K3", + "modalities": { + "input": [ + "text", + "image", + "video" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1048576, + "output": 131072 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true + } + }, + "attachment": true, + "open_weights": true, + "release_date": "2026-07-16", + "last_updated": "2026-07-16", + "type": "chat" + }, { "id": "GLM-4.7", "name": "GLM-4.7", @@ -118666,6 +119299,221 @@ "release_date": "2025-12-23", "last_updated": "2025-12-23", "type": "chat" + }, + { + "id": "DeepSeek-V4-Flash", + "name": "DeepSeek V4 Flash", + "display_name": "DeepSeek V4 Flash", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 384000 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "default_enabled": true, + "mode": "effort", + "effort": "high", + "effort_options": [ + "low", + "high", + "max" + ], + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "notes": [ + "The DeepSeek API maps medium and xhigh to high for V4 models; effort_options lists distinct model-effective levels." + ] + } + }, + "attachment": false, + "open_weights": true, + "knowledge": "2025-05", + "release_date": "2026-04-24", + "last_updated": "2026-04-24", + "type": "chat" + }, + { + "id": "DeepSeek-V4-Pro", + "name": "DeepSeek V4 Pro", + "display_name": "DeepSeek V4 Pro", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 384000 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "default_enabled": true, + "mode": "effort", + "effort": "high", + "effort_options": [ + "low", + "high", + "max" + ], + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ], + "notes": [ + "The DeepSeek API maps medium and xhigh to high for V4 models; effort_options lists distinct model-effective levels." + ] + } + }, + "attachment": false, + "open_weights": true, + "knowledge": "2025-05", + "release_date": "2026-04-24", + "last_updated": "2026-04-24", + "type": "chat" + }, + { + "id": "MiniMax-M2.7", + "name": "MiniMax-M2.7", + "display_name": "MiniMax-M2.7", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 204800, + "output": 131072 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": false, + "open_weights": true, + "release_date": "2026-03-18", + "last_updated": "2026-03-18", + "type": "chat" + }, + { + "id": "Qwen3.6-Flash", + "name": "Qwen3.6 Flash", + "display_name": "Qwen3.6 Flash", + "modalities": { + "input": [ + "text", + "image", + "video" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 65536 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": true, + "open_weights": false, + "release_date": "2026-04-27", + "last_updated": "2026-04-27", + "type": "chat" + }, + { + "id": "GLM-5.3", + "name": "GLM-5.3", + "display_name": "GLM-5.3", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 131072 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true + } + }, + "attachment": false, + "open_weights": true, + "release_date": "2026-08-14", + "last_updated": "2026-08-14", + "type": "chat" } ] }, @@ -131851,6 +132699,34 @@ "last_updated": "2026-02-03", "type": "chat" }, + { + "id": "Qwen/Qwen3-VL-30B-A3B-Instruct", + "name": "Qwen3 VL 30B A3B Instruct", + "display_name": "Qwen3 VL 30B A3B Instruct", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 131072, + "output": 32768 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": true, + "release_date": "2025-10-04", + "last_updated": "2025-10-04", + "type": "chat" + }, { "id": "Qwen/Qwen3-VL-235B-A22B-Thinking", "name": "Qwen3 VL 235B A22B Thinking", @@ -133135,6 +134011,34 @@ "last_updated": "2026-06-01", "type": "chat" }, + { + "id": "MiniMaxAI/MiniMax-M1-80k", + "name": "MiniMax M1 80K", + "display_name": "MiniMax M1 80K", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 80000 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "attachment": false, + "open_weights": true, + "release_date": "2025-06-17", + "last_updated": "2025-06-17", + "type": "chat" + }, { "id": "MiniMaxAI/MiniMax-M2.1", "name": "MiniMax-M2.1", @@ -133847,6 +134751,34 @@ "last_updated": "2025-09-30", "type": "chat" }, + { + "id": "zai-org/AutoGLM-Phone-9B-Multilingual", + "name": "AutoGLM Phone 9B Multilingual", + "display_name": "AutoGLM Phone 9B Multilingual", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 65536, + "output": 65536 + }, + "temperature": true, + "tool_call": false, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": true, + "release_date": "2025-12-10", + "last_updated": "2025-12-10", + "type": "chat" + }, { "id": "zai-org/GLM-4.7-Flash", "name": "GLM-4.7-Flash", @@ -153478,14 +154410,79 @@ "last_updated": "2026-08-14", "type": "chat" }, + { + "id": "qwen/qwen3.6-35b-a3b", + "name": "Qwen3.6 35B-A3B", + "display_name": "Qwen3.6 35B-A3B", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 262144 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": false, + "open_weights": true, + "release_date": "2026-04-17", + "last_updated": "2026-04-17", + "type": "chat" + }, + { + "id": "qwen/qwen3-30b-a3b-instruct-2507", + "name": "Qwen3 30B A3B Instruct 2507", + "display_name": "Qwen3 30B A3B Instruct 2507", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 131072, + "output": 32768 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "release_date": "2026-10-09", + "last_updated": "2026-10-09", + "type": "chat" + }, { "id": "qwen/qwen3.6-27b", "name": "Qwen3.6 27B", "display_name": "Qwen3.6 27B", "modalities": { "input": [ - "text", - "image" + "text" ], "output": [ "text" @@ -153512,7 +154509,7 @@ ] } }, - "attachment": true, + "attachment": false, "open_weights": true, "release_date": "2026-04-22", "last_updated": "2026-04-22", @@ -160852,6 +161849,33 @@ "last_updated": "2026-08-28", "type": "chat" }, + { + "id": "heygen/heygen-video-1", + "name": "HeyGen Video", + "display_name": "HeyGen Video", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "video" + ] + }, + "limit": { + "context": 8192, + "output": 8192 + }, + "tool_call": false, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": false, + "release_date": "2026-10-09", + "last_updated": "2026-10-09", + "type": "chat" + }, { "id": "inference-net/schematron-v2-small", "name": "Schematron V2 Small", @@ -161658,35 +162682,6 @@ "last_updated": "2025-12-16", "type": "chat" }, - { - "id": "alibaba/qwen3-vl-235b-a22b-instruct", - "name": "Qwen3 VL 235B A22B Instruct", - "display_name": "Qwen3 VL 235B A22B Instruct", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 129024 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false - }, - "attachment": true, - "open_weights": true, - "knowledge": "2025-03-31", - "release_date": "2025-09-23", - "last_updated": "2025-09-23", - "type": "chat" - }, { "id": "alibaba/qwen3.7-max", "name": "Qwen 3.7 Max", @@ -161769,48 +162764,6 @@ "last_updated": "2026-08-14", "type": "chat" }, - { - "id": "alibaba/qwen3-vl-thinking", - "name": "Qwen3 VL Thinking", - "display_name": "Qwen3 VL Thinking", - "modalities": { - "input": [ - "text", - "image", - "pdf" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": true, - "open_weights": true, - "knowledge": "2025-09", - "release_date": "2025-09-23", - "last_updated": "2025-09-24", - "type": "chat" - }, { "id": "alibaba/qwen3.8-2.4t-a95b", "name": "Qwen3.8 2.4T A95B", @@ -161972,8 +162925,8 @@ ] }, "limit": { - "context": 131072, - "output": 129024 + "context": 262144, + "output": 262144 }, "temperature": true, "tool_call": true, @@ -162001,7 +162954,7 @@ }, "limit": { "context": 262144, - "output": 65536 + "output": 32768 }, "temperature": true, "tool_call": true, @@ -162067,34 +163020,6 @@ "last_updated": "2026-02-16", "type": "chat" }, - { - "id": "alibaba/qwen-3.6-max-preview", - "name": "Qwen 3.6 Max Preview", - "display_name": "Qwen 3.6 Max Preview", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 240000, - "output": 64000 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "attachment": true, - "open_weights": true, - "release_date": "2026-04-20", - "last_updated": "2026-04-24", - "type": "chat" - }, { "id": "alibaba/wan-v2.6-i2v-flash", "name": "Wan v2.6 Image-to-Video Flash", @@ -162222,45 +163147,6 @@ "last_updated": "2026-07-15", "type": "chat" }, - { - "id": "alibaba/qwen3-max", - "name": "Qwen3 Max", - "display_name": "Qwen3 Max", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-09-23", - "last_updated": "2025-09-23", - "type": "chat" - }, { "id": "alibaba/qwen3-embedding-0.6b", "name": "Qwen3 Embedding 0.6B", @@ -162411,45 +163297,6 @@ "last_updated": "2025-06-05", "type": "embedding" }, - { - "id": "alibaba/qwen3-max-preview", - "name": "Qwen3 Max Preview", - "display_name": "Qwen3 Max Preview", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-09-05", - "last_updated": "2025-09-23", - "type": "chat" - }, { "id": "alibaba/wan-v2.6-i2v", "name": "Wan v2.6 Image-to-Video", @@ -162572,34 +163419,6 @@ "last_updated": "2025-01", "type": "chat" }, - { - "id": "alibaba/qwen3-coder-plus", - "name": "Qwen3 Coder Plus", - "display_name": "Qwen3 Coder Plus", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-07-23", - "last_updated": "2025-07-23", - "type": "chat" - }, { "id": "alibaba/qwen3.8-max-prime", "name": "Qwen 3.8 Max Prime", @@ -162638,48 +163457,6 @@ "last_updated": "2026-09-23", "type": "chat" }, - { - "id": "alibaba/qwen3-235b-a22b-thinking", - "name": "Qwen3 235B A22B Thinking 2507", - "display_name": "Qwen3 235B A22B Thinking 2507", - "modalities": { - "input": [ - "text", - "image", - "pdf" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": true, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-09-23", - "last_updated": "2025-04", - "type": "chat" - }, { "id": "alibaba/qwen3.8-flash", "name": "Qwen 3.8 Flash", @@ -162741,7 +163518,7 @@ "supported": false }, "attachment": false, - "open_weights": false, + "open_weights": true, "release_date": "2025-06-05", "last_updated": "2025-06-05", "type": "embedding" @@ -165044,7 +165821,7 @@ "none", "low", "medium", - "high" + "xhigh" ] } }, @@ -165432,9 +166209,9 @@ "default": true }, "attachment": false, - "open_weights": false, + "open_weights": true, "release_date": "2026-08-27", - "last_updated": "2026-08-27", + "last_updated": "2026-09-03", "type": "chat" }, { @@ -166866,8 +167643,8 @@ ] }, "limit": { - "context": 60288, - "output": 16000 + "context": 131072, + "output": 131072 }, "temperature": true, "tool_call": true, @@ -166907,8 +167684,6 @@ "reasoning": { "effort_options": [ "none", - "low", - "medium", "high" ] } @@ -186602,6 +187377,48 @@ "last_updated": "2026-04-16", "type": "chat" }, + { + "id": "anthropic/claude-haiku-5.5", + "name": "Claude Haiku 5.5", + "display_name": "Claude Haiku 5.5", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-06", + "release_date": "2026-10-07", + "last_updated": "2026-10-07", + "type": "chat" + }, { "id": "anthropic/claude-opus-4.8", "name": "Claude Opus 4.8", @@ -195654,6 +196471,45 @@ "last_updated": "2026-04-24", "type": "chat" }, + { + "id": "deepseek/deepseek-r1-0528", + "name": "DeepSeek R1 (0528)", + "display_name": "DeepSeek R1 (0528)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 65536, + "output": 32768 + }, + "temperature": true, + "tool_call": false, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": false, + "open_weights": true, + "release_date": "2025-05-28", + "last_updated": "2025-05-28", + "type": "chat" + }, { "id": "deepseek/deepseek-v3.2", "name": "DeepSeek V3.2", @@ -198872,6 +199728,34 @@ "last_updated": "2025-04", "type": "chat" }, + { + "id": "qwen/qwen3-vl-30b-a3b-instruct", + "name": "Qwen3-VL 30B-A3B Instruct", + "display_name": "Qwen3-VL 30B-A3B Instruct", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 131072, + "output": 32768 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": true, + "release_date": "2025-10-04", + "last_updated": "2025-10-04", + "type": "chat" + }, { "id": "qwen/qwen3-235b-a22b", "name": "Qwen3 235B A22B", @@ -219447,9 +220331,94 @@ "type": "chat" }, { - "id": "deepinfra/google/gemma-3-12b-it", - "name": "Gemma 3 12B IT (Deep Infra)", - "display_name": "Gemma 3 12B IT (Deep Infra)", + "id": "deepinfra/google/gemma-3-12b-it", + "name": "Gemma 3 12B IT (Deep Infra)", + "display_name": "Gemma 3 12B IT (Deep Infra)", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 131072, + "output": 131072 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": true, + "knowledge": "2024-08", + "release_date": "2025-03-12", + "last_updated": "2025-03-12", + "type": "chat" + }, + { + "id": "deepinfra/google/gemma-3-4b-it", + "name": "Gemma 3 4B IT (Deep Infra)", + "display_name": "Gemma 3 4B IT (Deep Infra)", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 131072, + "output": 131072 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": true, + "knowledge": "2024-08", + "release_date": "2025-03-12", + "last_updated": "2025-03-12", + "type": "chat" + }, + { + "id": "deepinfra/Gryphe/MythoMax-L2-13b", + "name": "MythoMax L2 13B (Deep Infra)", + "display_name": "MythoMax L2 13B (Deep Infra)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 4096, + "output": 3200 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "release_date": "2023-08-10", + "last_updated": "2023-08-10", + "type": "chat" + }, + { + "id": "deepinfra/Qwen/Qwen3-VL-235B-A22B-Instruct", + "name": "Qwen3 VL 235B A22B Instruct (Deep Infra)", + "display_name": "Qwen3 VL 235B A22B Instruct (Deep Infra)", "modalities": { "input": [ "text", @@ -219460,8 +220429,8 @@ ] }, "limit": { - "context": 131072, - "output": 131072 + "context": 262144, + "output": 32768 }, "temperature": true, "tool_call": true, @@ -219470,15 +220439,43 @@ }, "attachment": true, "open_weights": true, - "knowledge": "2024-08", - "release_date": "2025-03-12", - "last_updated": "2025-03-12", + "knowledge": "2025-03-31", + "release_date": "2025-09-23", + "last_updated": "2025-09-23", "type": "chat" }, { - "id": "deepinfra/google/gemma-3-4b-it", - "name": "Gemma 3 4B IT (Deep Infra)", - "display_name": "Gemma 3 4B IT (Deep Infra)", + "id": "deepinfra/Qwen/Qwen3-Next-80B-A3B-Instruct", + "name": "Qwen3-Next 80B-A3B Instruct (Deep Infra)", + "display_name": "Qwen3-Next 80B-A3B Instruct (Deep Infra)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 32768 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "knowledge": "2025-04", + "release_date": "2025-09", + "last_updated": "2025-09", + "type": "chat" + }, + { + "id": "deepinfra/Qwen/Qwen3-VL-30B-A3B-Instruct", + "name": "Qwen3 VL 30B A3B Instruct (Deep Infra)", + "display_name": "Qwen3 VL 30B A3B Instruct (Deep Infra)", "modalities": { "input": [ "text", @@ -219489,8 +220486,8 @@ ] }, "limit": { - "context": 131072, - "output": 131072 + "context": 262144, + "output": 32768 }, "temperature": true, "tool_call": true, @@ -219499,9 +220496,102 @@ }, "attachment": true, "open_weights": true, - "knowledge": "2024-08", - "release_date": "2025-03-12", - "last_updated": "2025-03-12", + "release_date": "2025-10-04", + "last_updated": "2025-10-04", + "type": "chat" + }, + { + "id": "deepinfra/Qwen/Qwen3-Max", + "name": "Qwen3 Max (Deep Infra)", + "display_name": "Qwen3 Max (Deep Infra)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 256000, + "output": 65536 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": false, + "open_weights": false, + "knowledge": "2025-04", + "release_date": "2025-09-23", + "last_updated": "2025-09-23", + "type": "chat" + }, + { + "id": "deepinfra/Qwen/Qwen3-235B-A22B-Instruct-2507", + "name": "Qwen3 235B-A22B Instruct 2507 (Deep Infra)", + "display_name": "Qwen3 235B-A22B Instruct 2507 (Deep Infra)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 16384 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "release_date": "2025-07-21", + "last_updated": "2025-07-21", + "type": "chat" + }, + { + "id": "deepinfra/Qwen/Qwen3-Coder-480B-A35B-Instruct", + "name": "Qwen3-Coder 480B-A35B Instruct (Deep Infra)", + "display_name": "Qwen3-Coder 480B-A35B Instruct (Deep Infra)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 65536 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "knowledge": "2025-04", + "release_date": "2025-04", + "last_updated": "2025-04", "type": "chat" }, { @@ -219664,6 +220754,45 @@ "last_updated": "2026-09-10", "type": "chat" }, + { + "id": "deepinfra/deepseek-ai/DeepSeek-R1-0528", + "name": "DeepSeek R1 0528 (Deep Infra)", + "display_name": "DeepSeek R1 0528 (Deep Infra)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 163840, + "output": 32768 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": false, + "open_weights": true, + "release_date": "2025-05-28", + "last_updated": "2025-05-28", + "type": "chat" + }, { "id": "deepinfra/deepseek-ai/DeepSeek-V3", "name": "DeepSeek-V3 (Deep Infra)", @@ -219795,6 +220924,33 @@ "last_updated": "2026-02-13", "type": "chat" }, + { + "id": "deepinfra/moonshotai/Kimi-K2-Instruct", + "name": "Kimi K2 Instruct (Deep Infra)", + "display_name": "Kimi K2 Instruct (Deep Infra)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 131072, + "output": 32768 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "release_date": "2025-07-11", + "last_updated": "2025-07-11", + "type": "chat" + }, { "id": "deepinfra/moonshotai/Kimi-K2.5", "name": "Kimi K2.5 (Deep Infra)", @@ -220085,6 +221241,33 @@ "last_updated": "2025-08-05", "type": "chat" }, + { + "id": "deepinfra/microsoft/WizardLM-2-8x22B", + "name": "WizardLM 2 8x22B (Deep Infra)", + "display_name": "WizardLM 2 8x22B (Deep Infra)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 65536, + "output": 8000 + }, + "temperature": true, + "tool_call": false, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "release_date": "2024-04-15", + "last_updated": "2024-04-15", + "type": "chat" + }, { "id": "cerebras/gpt-oss-120b", "name": "GPT OSS 120B (Cerebras)", @@ -221841,90 +223024,15 @@ }, "attachment": false, "open_weights": true, - "knowledge": "2025-05", - "release_date": "2026-07-31", - "last_updated": "2026-07-31", - "type": "chat" - }, - { - "id": "databricks/databricks-gpt-oss-120b", - "name": "GPT OSS 120B (Databricks)", - "display_name": "GPT OSS 120B (Databricks)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "effort_options": [ - "low", - "medium", - "high" - ] - } - }, - "attachment": false, - "open_weights": true, - "release_date": "2025-08-05", - "last_updated": "2025-08-05", - "type": "chat" - }, - { - "id": "databricks/databricks-deepseek-v4-pro-0813", - "name": "DeepSeek V4 Pro 0813 (Databricks)", - "display_name": "DeepSeek V4 Pro 0813 (Databricks)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 384000 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "effort_options": [ - "none", - "low", - "high", - "max" - ] - } - }, - "attachment": false, - "open_weights": true, - "release_date": "2026-08-12", - "last_updated": "2026-08-22", + "knowledge": "2025-05", + "release_date": "2026-07-31", + "last_updated": "2026-07-31", "type": "chat" }, { - "id": "tencent/step-5-preview", - "name": "Step 5 Preview (Tencent)", - "display_name": "Step 5 Preview (Tencent)", + "id": "databricks/databricks-gpt-oss-120b", + "name": "GPT OSS 120B (Databricks)", + "display_name": "GPT OSS 120B (Databricks)", "modalities": { "input": [ "text" @@ -221934,10 +223042,11 @@ ] }, "limit": { - "context": 1000000, - "output": 1000000 + "context": 131072, + "output": 32768 }, - "tool_call": false, + "temperature": true, + "tool_call": true, "reasoning": { "supported": true, "default": true @@ -221952,9 +223061,75 @@ } }, "attachment": false, - "open_weights": false, - "release_date": "2026-09-16", - "last_updated": "2026-09-20", + "open_weights": true, + "release_date": "2025-08-05", + "last_updated": "2025-08-05", + "type": "chat" + }, + { + "id": "databricks/databricks-deepseek-v4-pro-0813", + "name": "DeepSeek V4 Pro 0813 (Databricks)", + "display_name": "DeepSeek V4 Pro 0813 (Databricks)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 384000 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "none", + "low", + "high", + "max" + ] + } + }, + "attachment": false, + "open_weights": true, + "release_date": "2026-08-12", + "last_updated": "2026-08-22", + "type": "chat" + }, + { + "id": "databricks/databricks-qwen3-next-80b-a3b-instruct", + "name": "Qwen3-Next 80B-A3B Instruct (Databricks)", + "display_name": "Qwen3-Next 80B-A3B Instruct (Databricks)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 131072, + "output": 32768 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "knowledge": "2025-04", + "release_date": "2025-09", + "last_updated": "2025-09", "type": "chat" }, { @@ -222599,6 +223774,46 @@ "last_updated": "2026-07-31", "type": "chat" }, + { + "id": "flexai/Muse-Glimmer-30B", + "name": "Muse Glimmer 30B (FlexAI)", + "display_name": "Muse Glimmer 30B (FlexAI)", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 131072, + "output": 131072 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "low", + "medium", + "high", + "xhigh" + ] + } + }, + "attachment": true, + "open_weights": true, + "knowledge": "2026-01-04", + "release_date": "2026-08-10", + "last_updated": "2026-08-10", + "type": "chat" + }, { "id": "flexai/DeepSeek-V4.1-Flash", "name": "DeepSeek V4.1 Flash (FlexAI)", @@ -223963,6 +225178,33 @@ "last_updated": "2025-03-12", "type": "chat" }, + { + "id": "nebius/Qwen/Qwen3-235B-A22B-Instruct-2507", + "name": "Qwen3 235B-A22B Instruct 2507 (Nebius)", + "display_name": "Qwen3 235B-A22B Instruct 2507 (Nebius)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 16384 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "release_date": "2025-07-21", + "last_updated": "2025-07-21", + "type": "chat" + }, { "id": "nebius/deepseek-ai/DeepSeek-V4-Flash-0731", "name": "DeepSeek V4 Flash 0731 (Nebius)", @@ -224266,6 +225508,61 @@ "last_updated": "2026-07-31", "type": "chat" }, + { + "id": "scaleway/qwen3-235b-a22b-instruct-2507", + "name": "Qwen3 235B-A22B Instruct 2507 (Scaleway)", + "display_name": "Qwen3 235B-A22B Instruct 2507 (Scaleway)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 250000, + "output": 16384 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "release_date": "2025-07-21", + "last_updated": "2025-07-21", + "type": "chat" + }, + { + "id": "scaleway/qwen3-coder-30b-a3b-instruct", + "name": "Qwen3-Coder 30B-A3B Instruct (Scaleway)", + "display_name": "Qwen3-Coder 30B-A3B Instruct (Scaleway)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 128000, + "output": 65536 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "knowledge": "2025-04", + "release_date": "2025-04", + "last_updated": "2025-04", + "type": "chat" + }, { "id": "scaleway/llama-3.3-70b-instruct", "name": "Llama-3.3-70B-Instruct (Scaleway)", @@ -224360,6 +225657,34 @@ "last_updated": "2024-12-06", "type": "chat" }, + { + "id": "ionos/Qwen/Qwen3-Coder-Next", + "name": "Qwen3 Coder Next (IONOS)", + "display_name": "Qwen3 Coder Next (IONOS)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 65536 + }, + "temperature": true, + "tool_call": false, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "knowledge": "2025-09", + "release_date": "2026-02-03", + "last_updated": "2026-02-03", + "type": "chat" + }, { "id": "ionos/openai/gpt-oss-120b", "name": "GPT OSS 120B (IONOS)", @@ -225531,17 +226856,56 @@ ] } }, - "attachment": true, + "attachment": true, + "open_weights": true, + "knowledge": "2025-05", + "release_date": "2026-09-10", + "last_updated": "2026-09-10", + "type": "chat" + }, + { + "id": "tensorx/deepseek/deepseek-v4-pro-0813", + "name": "DeepSeek V4 Pro 0813 (TensorX)", + "display_name": "DeepSeek V4 Pro 0813 (TensorX)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1048576, + "output": 384000 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "effort_options": [ + "none", + "low", + "high", + "max" + ] + } + }, + "attachment": false, "open_weights": true, - "knowledge": "2025-05", - "release_date": "2026-09-10", - "last_updated": "2026-09-10", + "release_date": "2026-08-12", + "last_updated": "2026-08-22", "type": "chat" }, { - "id": "tensorx/deepseek/deepseek-v4-pro-0813", - "name": "DeepSeek V4 Pro 0813 (TensorX)", - "display_name": "DeepSeek V4 Pro 0813 (TensorX)", + "id": "tensorx/deepseek/deepseek-r1-0528", + "name": "DeepSeek R1 0528 (TensorX)", + "display_name": "DeepSeek R1 0528 (TensorX)", "modalities": { "input": [ "text" @@ -225551,8 +226915,8 @@ ] }, "limit": { - "context": 1048576, - "output": 384000 + "context": 164000, + "output": 32768 }, "temperature": true, "tool_call": true, @@ -225563,18 +226927,18 @@ "extra_capabilities": { "reasoning": { "supported": true, - "effort_options": [ - "none", - "low", - "high", - "max" + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" ] } }, "attachment": false, "open_weights": true, - "release_date": "2026-08-12", - "last_updated": "2026-08-22", + "release_date": "2025-05-28", + "last_updated": "2025-05-28", "type": "chat" }, { @@ -225885,6 +227249,34 @@ "last_updated": "2025-04-08", "type": "chat" }, + { + "id": "amazon/qwen.qwen3-coder-next", + "name": "Qwen3 Coder Next (Amazon Bedrock)", + "display_name": "Qwen3 Coder Next (Amazon Bedrock)", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 262144, + "output": 65536 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": true, + "knowledge": "2025-09", + "release_date": "2026-02-03", + "last_updated": "2026-02-03", + "type": "chat" + }, { "id": "amazon/moonshotai.kimi-k2.5", "name": "Kimi K2.5 (Amazon Bedrock)", @@ -226612,76 +228004,6 @@ "last_updated": "2026-04-29", "type": "chat" }, - { - "id": "qwen/qwen3-vl-235b-a22b-instruct", - "name": "Qwen3 VL 235B A22B Instruct", - "display_name": "Qwen3 VL 235B A22B Instruct", - "modalities": { - "input": [ - "text", - "image", - "video" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": true, - "open_weights": true, - "knowledge": "2025-03-31", - "release_date": "2025-09-23", - "last_updated": "2025-09-23", - "type": "chat" - }, - { - "id": "qwen/qwq-plus", - "name": "QwQ Plus", - "display_name": "QwQ Plus", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 8192 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": false, - "knowledge": "2024-04", - "release_date": "2025-03-05", - "last_updated": "2025-03-05", - "type": "chat" - }, { "id": "qwen/qwen3.8-27b", "name": "Qwen3.8 27B", @@ -226722,48 +228044,6 @@ "last_updated": "2026-08-14", "type": "chat" }, - { - "id": "qwen/qwen3-vl-235b-a22b-thinking", - "name": "Qwen3 VL 235B A22B Thinking", - "display_name": "Qwen3 VL 235B A22B Thinking", - "modalities": { - "input": [ - "text", - "image", - "video" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": true, - "open_weights": true, - "knowledge": "2025-03-31", - "release_date": "2025-09-23", - "last_updated": "2025-09-23", - "type": "chat" - }, { "id": "qwen/qwen3.8-2.4t-a95b", "name": "Qwen3.8 2.4T A95B", @@ -226842,33 +228122,6 @@ "last_updated": "2026-07-31", "type": "chat" }, - { - "id": "qwen/qwen3-235b-a22b-instruct-2507", - "name": "Qwen3 235B-A22B Instruct 2507", - "display_name": "Qwen3 235B-A22B Instruct 2507", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 16384 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "release_date": "2025-07-21", - "last_updated": "2025-07-21", - "type": "chat" - }, { "id": "qwen/qwen-max", "name": "Qwen Max", @@ -226897,46 +228150,6 @@ "last_updated": "2025-01-25", "type": "chat" }, - { - "id": "qwen/qwen3-next-80b-a3b-thinking", - "name": "Qwen3-Next 80B-A3B (Thinking)", - "display_name": "Qwen3-Next 80B-A3B (Thinking)", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": true, - "knowledge": "2025-04", - "release_date": "2025-09", - "last_updated": "2025-09", - "type": "chat" - }, { "id": "qwen/qwen3.8-max", "name": "Qwen3.8 Max", @@ -226978,34 +228191,6 @@ "last_updated": "2026-08-03", "type": "chat" }, - { - "id": "qwen/qwen3-coder-next", - "name": "Qwen3 Coder Next", - "display_name": "Qwen3 Coder Next", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "knowledge": "2025-09", - "release_date": "2026-02-03", - "last_updated": "2026-02-03", - "type": "chat" - }, { "id": "qwen/deepseek-v4.1-flash", "name": "DeepSeek V4.1 Flash (Alibaba)", @@ -227047,101 +228232,6 @@ "last_updated": "2026-09-10", "type": "chat" }, - { - "id": "qwen/qwen3-max", - "name": "Qwen3 Max", - "display_name": "Qwen3 Max", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-09-23", - "last_updated": "2025-09-23", - "type": "chat" - }, - { - "id": "qwen/qwen3-coder-480b-a35b-instruct", - "name": "Qwen3-Coder 480B-A35B Instruct", - "display_name": "Qwen3-Coder 480B-A35B Instruct", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "knowledge": "2025-04", - "release_date": "2025-04", - "last_updated": "2025-04", - "type": "chat" - }, - { - "id": "qwen/qwen3-coder-30b-a3b-instruct", - "name": "Qwen3-Coder 30B-A3B Instruct", - "display_name": "Qwen3-Coder 30B-A3B Instruct", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": true, - "knowledge": "2025-04", - "release_date": "2025-04", - "last_updated": "2025-04", - "type": "chat" - }, { "id": "qwen/qwen3.8-omni-flash", "name": "Qwen3.8 Omni Flash", @@ -227183,39 +228273,9 @@ "type": "chat" }, { - "id": "qwen/qwen-vl-max", - "name": "Qwen-VL Max", - "display_name": "Qwen-VL Max", - "modalities": { - "input": [ - "text", - "image", - "video" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 8192 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false - }, - "attachment": true, - "open_weights": false, - "knowledge": "2024-04", - "release_date": "2024-04-08", - "last_updated": "2025-08-13", - "type": "chat" - }, - { - "id": "qwen/qwen3-next-80b-a3b-instruct", - "name": "Qwen3-Next 80B-A3B Instruct", - "display_name": "Qwen3-Next 80B-A3B Instruct", + "id": "qwen/qwen3-coder-flash", + "name": "Qwen3 Coder Flash", + "display_name": "Qwen3 Coder Flash", "modalities": { "input": [ "text" @@ -227225,8 +228285,8 @@ ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 1000000, + "output": 65536 }, "temperature": true, "tool_call": true, @@ -227234,28 +228294,26 @@ "supported": false }, "attachment": false, - "open_weights": true, + "open_weights": false, "knowledge": "2025-04", - "release_date": "2025-09", - "last_updated": "2025-09", + "release_date": "2025-07-28", + "last_updated": "2025-07-28", "type": "chat" }, { - "id": "qwen/qwen-vl-plus", - "name": "Qwen-VL Plus", - "display_name": "Qwen-VL Plus", + "id": "qwen/qwen-mt-plus", + "name": "Qwen MT Plus", + "display_name": "Qwen MT Plus", "modalities": { "input": [ - "text", - "image", - "video" + "text" ], "output": [ "text" ] }, "limit": { - "context": 131072, + "context": 4096, "output": 8192 }, "temperature": true, @@ -227263,39 +228321,10 @@ "reasoning": { "supported": false }, - "attachment": true, - "open_weights": false, - "knowledge": "2024-04", - "release_date": "2024-01-25", - "last_updated": "2025-08-15", - "type": "chat" - }, - { - "id": "qwen/qwen3-coder-flash", - "name": "Qwen3 Coder Flash", - "display_name": "Qwen3 Coder Flash", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, "attachment": false, "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-07-28", - "last_updated": "2025-07-28", + "release_date": "2025-07-24", + "last_updated": "2025-07-24", "type": "chat" }, { @@ -227337,34 +228366,6 @@ "last_updated": "2026-08-22", "type": "chat" }, - { - "id": "qwen/qwen3-coder-plus", - "name": "Qwen3 Coder Plus", - "display_name": "Qwen3 Coder Plus", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-07-23", - "last_updated": "2025-07-23", - "type": "chat" - }, { "id": "qwen/qwen3.8-flash", "name": "Qwen3.8 Flash", @@ -234256,9 +235257,9 @@ "default": true }, "attachment": false, - "open_weights": false, + "open_weights": true, "release_date": "2026-08-27", - "last_updated": "2026-08-27", + "last_updated": "2026-09-03", "type": "chat" }, { @@ -259203,6 +260204,34 @@ "last_updated": "2026-04-02", "type": "chat" }, + { + "id": "reka-edge-2603", + "name": "Reka Edge 2603", + "display_name": "Reka Edge 2603", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 16384, + "output": 16384 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": false, + "release_date": "2026-10-09", + "last_updated": "2026-10-09", + "type": "chat" + }, { "id": "grok-4-5", "name": "Grok 4.5", @@ -259913,33 +260942,6 @@ "last_updated": "2025-11-13", "type": "chat" }, - { - "id": "qwen-coder-plus", - "name": "Qwen Coder Plus", - "display_name": "Qwen Coder Plus", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 8192 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": false, - "release_date": "2024-09-18", - "last_updated": "2024-09-18", - "type": "chat" - }, { "id": "glm-5v-turbo", "name": "GLM-5V-Turbo", @@ -262612,45 +263614,6 @@ "last_updated": "2024-04-18", "type": "chat" }, - { - "id": "qwen3-vl-flash", - "name": "Qwen3 VL Flash", - "display_name": "Qwen3 VL Flash", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 32000 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": true, - "open_weights": false, - "release_date": "2025-10-09", - "last_updated": "2025-10-09", - "type": "chat" - }, { "id": "seed-2-0-pro-260328", "name": "Seed 2.0 Pro (260328)", @@ -263834,34 +264797,6 @@ "last_updated": "2026-04-22", "type": "chat" }, - { - "id": "qwen3-coder-plus", - "name": "Qwen3 Coder Plus", - "display_name": "Qwen3 Coder Plus", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-07-23", - "last_updated": "2025-07-23", - "type": "chat" - }, { "id": "glm-4.7-flash", "name": "GLM-4.7-Flash", @@ -264789,46 +265724,6 @@ "last_updated": "2026-02-23", "type": "chat" }, - { - "id": "qwen3.6-max-preview", - "name": "Qwen3.6 Max Preview", - "display_name": "Qwen3.6 Max Preview", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2026-04-20", - "last_updated": "2026-04-20", - "type": "chat" - }, { "id": "claude-opus-4-6", "name": "Claude Opus 4.6", @@ -265124,38 +266019,6 @@ "last_updated": "2025-07-11", "type": "chat" }, - { - "id": "qwen-omni-turbo", - "name": "Qwen-Omni Turbo", - "display_name": "Qwen-Omni Turbo", - "modalities": { - "input": [ - "text", - "image", - "audio", - "video" - ], - "output": [ - "text", - "audio" - ] - }, - "limit": { - "context": 32768, - "output": 2048 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": false, - "knowledge": "2024-04", - "release_date": "2025-01-19", - "last_updated": "2025-03-26", - "type": "chat" - }, { "id": "hy-mt2-plus", "name": "Hy-MT2 Plus", @@ -266929,7 +267792,9 @@ "supported": true, "effort_options": [ "none", + "minimal", "low", + "medium", "high", "xhigh", "max" @@ -271572,6 +272437,33 @@ "last_updated": "2026-05-28", "type": "imageGeneration" }, + { + "id": "codestral-2", + "name": "Codestral 2", + "display_name": "Codestral 2", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 128000, + "output": 8192 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": false, + "open_weights": false, + "release_date": "2025-07-30", + "last_updated": "2025-07-30", + "type": "chat" + }, { "id": "gemini-3.1-pro-preview", "name": "Gemini 3.1 Pro Preview", @@ -271868,6 +272760,64 @@ "last_updated": "2026-06-30", "type": "imageGeneration" }, + { + "id": "mistral-medium-3", + "name": "Mistral Medium 3", + "display_name": "Mistral Medium 3", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 131072, + "output": 131072 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": false, + "knowledge": "2025-05", + "release_date": "2025-05-07", + "last_updated": "2025-05-07", + "type": "chat" + }, + { + "id": "mistral-small-2503", + "name": "Mistral Small 3.1 24B", + "display_name": "Mistral Small 3.1 24B", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 128000, + "output": 16384 + }, + "temperature": true, + "tool_call": true, + "reasoning": { + "supported": false + }, + "attachment": true, + "open_weights": true, + "knowledge": "2024-06", + "release_date": "2025-03-17", + "last_updated": "2025-03-17", + "type": "chat" + }, { "id": "gemini-3.7-flash", "name": "Gemini 3.7 Flash", @@ -292581,6 +293531,47 @@ "last_updated": "2024-05-22", "type": "chat" }, + { + "id": "anthropic-claude-5.5-haiku", + "name": "Anthropic Claude 5.5 Haiku", + "display_name": "Anthropic Claude 5.5 Haiku", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 1000000, + "output": 128000 + }, + "temperature": false, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "effort_options": [ + "low", + "medium", + "high", + "xhigh", + "max" + ] + } + }, + "attachment": true, + "open_weights": false, + "knowledge": "2026-06", + "release_date": "2026-10-07", + "last_updated": "2026-10-07", + "type": "chat" + }, { "id": "qwen-2.5-14b-instruct", "name": "Qwen 2.5 14B Instruct", @@ -318956,7 +319947,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -318981,7 +319972,7 @@ "default": true }, "attachment": false, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319006,7 +319997,7 @@ "default": true }, "attachment": false, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319031,7 +320022,7 @@ "default": true }, "attachment": false, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319056,7 +320047,7 @@ "supported": false }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "embedding" }, { @@ -319081,7 +320072,7 @@ "supported": false }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "embedding" }, { @@ -319107,7 +320098,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319133,7 +320124,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319159,7 +320150,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319185,7 +320176,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319211,7 +320202,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319237,7 +320228,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319263,7 +320254,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319289,7 +320280,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319315,7 +320306,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319341,7 +320332,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319365,7 +320356,7 @@ "supported": false }, "attachment": false, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319391,7 +320382,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319417,7 +320408,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319441,7 +320432,7 @@ "supported": false }, "attachment": false, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319461,7 +320452,7 @@ "supported": false }, "attachment": false, - "last_updated": "2026-09-28T03:59:13Z" + "last_updated": "2026-10-09T09:49:07Z" }, { "id": "doubao-seedance-1-0-pro-fast-251015", @@ -319480,7 +320471,7 @@ "supported": false }, "attachment": false, - "last_updated": "2026-09-28T03:59:13Z" + "last_updated": "2026-10-09T09:49:07Z" }, { "id": "doubao-seedance-2-0-260128", @@ -319500,7 +320491,7 @@ "supported": false }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z" + "last_updated": "2026-10-09T09:49:07Z" }, { "id": "doubao-seedance-2-0-fast-260128", @@ -319520,7 +320511,7 @@ "supported": false }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z" + "last_updated": "2026-10-09T09:49:07Z" }, { "id": "doubao-seedance-2-0-mini-260615", @@ -319540,7 +320531,7 @@ "supported": false }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z" + "last_updated": "2026-10-09T09:49:07Z" }, { "id": "doubao-seedance-2-5-260628", @@ -319560,7 +320551,7 @@ "supported": false }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z" + "last_updated": "2026-10-09T09:49:07Z" }, { "id": "doubao-seedream-4-0-250828", @@ -319580,7 +320571,7 @@ "supported": false }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "imageGeneration" }, { @@ -319601,7 +320592,7 @@ "supported": false }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "imageGeneration" }, { @@ -319622,7 +320613,7 @@ "supported": false }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "imageGeneration" }, { @@ -319643,7 +320634,7 @@ "supported": false }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "imageGeneration" }, { @@ -319664,7 +320655,7 @@ "supported": false }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "imageGeneration" }, { @@ -319689,7 +320680,7 @@ "default": true }, "attachment": false, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" }, { @@ -319715,7 +320706,7 @@ "default": true }, "attachment": true, - "last_updated": "2026-09-28T03:59:13Z", + "last_updated": "2026-10-09T09:49:07Z", "type": "chat" } ] @@ -319765,6 +320756,26 @@ }, "type": "chat" }, + { + "id": "tencent/hy4-preview", + "name": "Hy4 Preview", + "display_name": "Hy4 Preview", + "limit": { + "context": 1000000, + "output": 64000 + }, + "tool_call": true, + "reasoning": { + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true + } + }, + "type": "chat" + }, { "id": "deepseek/deepseek-v4-flash-0731-p", "name": "deepseek/deepseek-v4-flash-0731-p", @@ -320037,43 +321048,6 @@ }, "type": "chat" }, - { - "id": "deepseek/deepseek-v4-flash", - "name": "DeepSeek V4 Flash", - "display_name": "DeepSeek V4 Flash", - "limit": { - "context": 1048576, - "output": 393216 - }, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": true, - "mode": "effort", - "effort": "high", - "effort_options": [ - "low", - "high", - "max" - ], - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "notes": [ - "The DeepSeek API maps medium and xhigh to high for V4 models; effort_options lists distinct model-effective levels." - ] - } - }, - "type": "chat" - }, { "id": "deepseek/deepseek-v4-pro", "name": "DeepSeek V4 Pro", @@ -323473,6 +324447,46 @@ }, "type": "imageGeneration" }, + { + "id": "qwen-image-2.1-pro", + "name": "qwen-image-2.1-pro", + "display_name": "qwen-image-2.1-pro", + "modalities": { + "input": [ + "text", + "image" + ] + }, + "limit": { + "context": 8192, + "output": 8192 + }, + "tool_call": false, + "reasoning": { + "supported": false + }, + "type": "imageGeneration" + }, + { + "id": "qwen-image-2.1-turbo", + "name": "qwen-image-2.1-turbo", + "display_name": "qwen-image-2.1-turbo", + "modalities": { + "input": [ + "text", + "image" + ] + }, + "limit": { + "context": 8192, + "output": 8192 + }, + "tool_call": false, + "reasoning": { + "supported": false + }, + "type": "imageGeneration" + }, { "id": "claude-haiku-5-5", "name": "claude-haiku-5-5", @@ -323740,9 +324754,9 @@ "type": "chat" }, { - "id": "decision-model-preview", - "name": "decision-model-preview", - "display_name": "decision-model-preview", + "id": "jev-1.13", + "name": "jev-1.13", + "display_name": "jev-1.13", "modalities": { "input": [ "text" @@ -323759,9 +324773,9 @@ "type": "chat" }, { - "id": "jev-1.13", - "name": "jev-1.13", - "display_name": "jev-1.13", + "id": "jev-latest", + "name": "jev-latest", + "display_name": "jev-latest", "modalities": { "input": [ "text" @@ -323778,9 +324792,9 @@ "type": "chat" }, { - "id": "jev-latest", - "name": "jev-latest", - "display_name": "jev-latest", + "id": "decision-model-preview", + "name": "decision-model-preview", + "display_name": "decision-model-preview", "modalities": { "input": [ "text" @@ -323999,26 +325013,6 @@ }, "type": "chat" }, - { - "id": "gpt-live-transcribe", - "name": "gpt-live-transcribe", - "display_name": "gpt-live-transcribe", - "modalities": { - "input": [ - "audio", - "text" - ] - }, - "limit": { - "context": 8192, - "output": 8192 - }, - "tool_call": false, - "reasoning": { - "supported": false - }, - "type": "chat" - }, { "id": "xiaomi-mimo-v2.6-pro-free", "name": "xiaomi-mimo-v2.6-pro-free", @@ -324089,6 +325083,26 @@ }, "type": "chat" }, + { + "id": "gpt-live-transcribe", + "name": "gpt-live-transcribe", + "display_name": "gpt-live-transcribe", + "modalities": { + "input": [ + "audio", + "text" + ] + }, + "limit": { + "context": 8192, + "output": 8192 + }, + "tool_call": false, + "reasoning": { + "supported": false + }, + "type": "chat" + }, { "id": "gpt-realtime-2.1", "name": "gpt-realtime-2.1", @@ -324249,9 +325263,9 @@ "type": "chat" }, { - "id": "coding-glm-5.3", - "name": "coding-glm-5.3", - "display_name": "coding-glm-5.3", + "id": "hy4-preview", + "name": "hy4-preview", + "display_name": "hy4-preview", "modalities": { "input": [ "text" @@ -324274,19 +325288,17 @@ "type": "chat" }, { - "id": "coding-glm-5.3-flash-free", - "name": "coding-glm-5.3-flash-free", - "display_name": "coding-glm-5.3-flash-free", + "id": "coding-glm-5.3", + "name": "coding-glm-5.3", + "display_name": "coding-glm-5.3", "modalities": { "input": [ - "text", - "image", - "video" + "text" ] }, "limit": { - "context": 1000000, - "output": 1000000 + "context": 1048576, + "output": 1048576 }, "tool_call": true, "reasoning": { @@ -324301,17 +325313,19 @@ "type": "chat" }, { - "id": "hy4-preview", - "name": "hy4-preview", - "display_name": "hy4-preview", + "id": "coding-glm-5.3-flash-free", + "name": "coding-glm-5.3-flash-free", + "display_name": "coding-glm-5.3-flash-free", "modalities": { "input": [ - "text" + "text", + "image", + "video" ] }, "limit": { - "context": 1048576, - "output": 1048576 + "context": 1000000, + "output": 1000000 }, "tool_call": true, "reasoning": { @@ -324326,21 +325340,19 @@ "type": "chat" }, { - "id": "muse-spark-1.3", - "name": "muse-spark-1.3", - "display_name": "muse-spark-1.3", + "id": "coding-glm-5.3-flash", + "name": "coding-glm-5.3-flash", + "display_name": "coding-glm-5.3-flash", "modalities": { "input": [ "text", "image", - "video", - "audio", - "pdf" + "video" ] }, "limit": { - "context": 1048576, - "output": 1048576 + "context": 1000000, + "output": 1000000 }, "tool_call": true, "reasoning": { @@ -324355,19 +325367,17 @@ "type": "chat" }, { - "id": "coding-glm-5.3-flash", - "name": "coding-glm-5.3-flash", - "display_name": "coding-glm-5.3-flash", + "id": "coding-glm-5.3-free", + "name": "coding-glm-5.3-free", + "display_name": "coding-glm-5.3-free", "modalities": { "input": [ - "text", - "image", - "video" + "text" ] }, "limit": { - "context": 1000000, - "output": 1000000 + "context": 1048576, + "output": 1048576 }, "tool_call": true, "reasoning": { @@ -324382,12 +325392,16 @@ "type": "chat" }, { - "id": "coding-glm-5.3-free", - "name": "coding-glm-5.3-free", - "display_name": "coding-glm-5.3-free", + "id": "muse-spark-1.3", + "name": "muse-spark-1.3", + "display_name": "muse-spark-1.3", "modalities": { "input": [ - "text" + "text", + "image", + "video", + "audio", + "pdf" ] }, "limit": { @@ -324455,6 +325469,46 @@ }, "type": "chat" }, + { + "id": "mai-image-2.6", + "name": "mai-image-2.6", + "display_name": "mai-image-2.6", + "modalities": { + "input": [ + "text", + "image" + ] + }, + "limit": { + "context": 32000, + "output": 32000 + }, + "tool_call": false, + "reasoning": { + "supported": false + }, + "type": "imageGeneration" + }, + { + "id": "mai-image-2.6-flash", + "name": "mai-image-2.6-flash", + "display_name": "mai-image-2.6-flash", + "modalities": { + "input": [ + "text", + "image" + ] + }, + "limit": { + "context": 32000, + "output": 32000 + }, + "tool_call": false, + "reasoning": { + "supported": false + }, + "type": "imageGeneration" + }, { "id": "gemini-3.7-flash", "name": "gemini-3.7-flash", @@ -324498,46 +325552,6 @@ }, "type": "chat" }, - { - "id": "mai-image-2.6", - "name": "mai-image-2.6", - "display_name": "mai-image-2.6", - "modalities": { - "input": [ - "text", - "image" - ] - }, - "limit": { - "context": 32000, - "output": 32000 - }, - "tool_call": false, - "reasoning": { - "supported": false - }, - "type": "imageGeneration" - }, - { - "id": "mai-image-2.6-flash", - "name": "mai-image-2.6-flash", - "display_name": "mai-image-2.6-flash", - "modalities": { - "input": [ - "text", - "image" - ] - }, - "limit": { - "context": 32000, - "output": 32000 - }, - "tool_call": false, - "reasoning": { - "supported": false - }, - "type": "imageGeneration" - }, { "id": "minimax-h3-max", "name": "minimax-h3-max", @@ -324605,22 +325619,27 @@ "type": "chat" }, { - "id": "intern-s2-free", - "name": "intern-s2-free", - "display_name": "intern-s2-free", + "id": "glm-5.2", + "name": "glm-5.2", + "display_name": "glm-5.2", "modalities": { "input": [ - "text", - "image" + "text" ] }, "limit": { - "context": 262144, - "output": 262144 + "context": 1000000, + "output": 1000000 }, - "tool_call": false, + "tool_call": true, "reasoning": { - "supported": false + "supported": true, + "default": true + }, + "extra_capabilities": { + "reasoning": { + "supported": true + } }, "type": "chat" }, @@ -324645,27 +325664,22 @@ "type": "chat" }, { - "id": "glm-5.2", - "name": "glm-5.2", - "display_name": "glm-5.2", + "id": "intern-s2-free", + "name": "intern-s2-free", + "display_name": "intern-s2-free", "modalities": { "input": [ - "text" + "text", + "image" ] }, "limit": { - "context": 1000000, - "output": 1000000 + "context": 262144, + "output": 262144 }, - "tool_call": true, + "tool_call": false, "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true - } + "supported": false }, "type": "chat" }, @@ -327807,26 +328821,6 @@ }, "type": "rerank" }, - { - "id": "qwen-image-2.0", - "name": "qwen-image-2.0", - "display_name": "qwen-image-2.0", - "modalities": { - "input": [ - "text", - "image" - ] - }, - "limit": { - "context": 8192, - "output": 8192 - }, - "tool_call": false, - "reasoning": { - "supported": false - }, - "type": "imageGeneration" - }, { "id": "qwen-image-2.0-pro", "name": "qwen-image-2.0-pro", @@ -327899,6 +328893,26 @@ }, "type": "chat" }, + { + "id": "qwen-image-2.0", + "name": "qwen-image-2.0", + "display_name": "qwen-image-2.0", + "modalities": { + "input": [ + "text", + "image" + ] + }, + "limit": { + "context": 8192, + "output": 8192 + }, + "tool_call": false, + "reasoning": { + "supported": false + }, + "type": "imageGeneration" + }, { "id": "qwen3.6-plus", "name": "qwen3.6-plus", @@ -329571,34 +330585,6 @@ }, "type": "chat" }, - { - "id": "doubao-seed-2-0-mini", - "name": "doubao-seed-2-0-mini", - "display_name": "doubao-seed-2-0-mini", - "modalities": { - "input": [ - "text", - "image", - "video", - "document" - ] - }, - "limit": { - "context": 256000, - "output": 256000 - }, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true - } - }, - "type": "chat" - }, { "id": "gemini-3-flash-preview", "name": "gemini-3-flash-preview", @@ -344698,8 +345684,8 @@ ] }, "limit": { - "context": 128000, - "output": 16000 + "context": 163840, + "output": 16384 }, "tool_call": true, "reasoning": { @@ -346864,8 +347850,8 @@ ] }, "limit": { - "context": 262144, - "output": 235929 + "context": 131072, + "output": 32768 }, "temperature": true, "tool_call": true, @@ -348920,7 +349906,7 @@ }, "limit": { "context": 262144, - "output": 235929 + "output": 98304 }, "tool_call": true, "reasoning": { @@ -349461,8 +350447,8 @@ ] }, "limit": { - "context": 262144, - "output": 16384 + "context": 202800, + "output": 182520 }, "temperature": true, "tool_call": true, @@ -349596,7 +350582,7 @@ }, "limit": { "context": 262144, - "output": 131072 + "output": 235929 }, "tool_call": true, "reasoning": { @@ -354148,39 +355134,6 @@ }, "type": "chat" }, - { - "id": "qwen/qwen-plus-2025-07-28", - "name": "Qwen: Qwen Plus 0728", - "display_name": "Qwen: Qwen Plus 0728", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 32768 - }, - "tool_call": true, - "reasoning": { - "supported": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "type": "chat" - }, { "id": "qwen/qwen2.5-vl-72b-instruct", "name": "Qwen: Qwen2.5 VL 72B Instruct", @@ -354239,41 +355192,6 @@ }, "type": "chat" }, - { - "id": "qwen/qwen3-235b-a22b", - "name": "Qwen: Qwen3 235B A22B", - "display_name": "Qwen: Qwen3 235B A22B", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 8192 - }, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "type": "chat" - }, { "id": "qwen/qwen3-235b-a22b-2507", "name": "Qwen: Qwen3 235B A22B Instruct 2507", @@ -354309,8 +355227,8 @@ ] }, "limit": { - "context": 131072, - "output": 117964 + "context": 128000, + "output": 16384 }, "tool_call": true, "reasoning": { @@ -354368,102 +355286,9 @@ "type": "chat" }, { - "id": "qwen/qwen3-30b-a3b-instruct-2507", - "name": "Qwen: Qwen3 30B A3B Instruct 2507", - "display_name": "Qwen: Qwen3 30B A3B Instruct 2507", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 235929 - }, - "tool_call": true, - "reasoning": { - "supported": false - }, - "type": "chat" - }, - { - "id": "qwen/qwen3-30b-a3b-thinking-2507", - "name": "Qwen: Qwen3 30B A3B Thinking 2507", - "display_name": "Qwen: Qwen3 30B A3B Thinking 2507", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 81920, - "output": 32768 - }, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": true, - "mode": "fixed", - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "type": "chat" - }, - { - "id": "qwen/qwen3-32b", - "name": "Qwen: Qwen3 32B", - "display_name": "Qwen: Qwen3 32B", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 40960, - "output": 16384 - }, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "type": "chat" - }, - { - "id": "qwen/qwen3-8b", - "name": "Qwen: Qwen3 8B", - "display_name": "Qwen: Qwen3 8B", + "id": "qwen/qwen3-30b-a3b-instruct-2507", + "name": "Qwen: Qwen3 30B A3B Instruct 2507", + "display_name": "Qwen: Qwen3 30B A3B Instruct 2507", "modalities": { "input": [ "text" @@ -354473,10 +355298,31 @@ ] }, "limit": { - "context": 131072, - "output": 8192 + "context": 262144, + "output": 235929 + }, + "tool_call": true, + "reasoning": { + "supported": false + }, + "type": "chat" + }, + { + "id": "qwen/qwen3-32b", + "name": "Qwen: Qwen3 32B", + "display_name": "Qwen: Qwen3 32B", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "limit": { + "context": 40960, + "output": 16384 }, - "temperature": true, "tool_call": true, "reasoning": { "supported": true, @@ -354585,97 +355431,6 @@ }, "type": "chat" }, - { - "id": "qwen/qwen3-coder-plus", - "name": "Qwen: Qwen3 Coder Plus", - "display_name": "Qwen: Qwen3 Coder Plus", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 65536 - }, - "tool_call": true, - "reasoning": { - "supported": false - }, - "type": "chat" - }, - { - "id": "qwen/qwen3-max", - "name": "Qwen: Qwen3 Max", - "display_name": "Qwen: Qwen3 Max", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "type": "chat" - }, - { - "id": "qwen/qwen3-max-thinking", - "name": "Qwen: Qwen3 Max Thinking", - "display_name": "Qwen: Qwen3 Max Thinking", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "type": "chat" - }, { "id": "qwen/qwen3-next-80b-a3b-instruct", "name": "Qwen: Qwen3 Next 80B A3B Instruct", @@ -354690,7 +355445,7 @@ }, "limit": { "context": 262144, - "output": 16384 + "output": 235929 }, "tool_call": true, "reasoning": { @@ -354711,8 +355466,8 @@ ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 262144, + "output": 235929 }, "tool_call": true, "reasoning": { @@ -354758,44 +355513,6 @@ }, "type": "chat" }, - { - "id": "qwen/qwen3-vl-235b-a22b-thinking", - "name": "Qwen: Qwen3 VL 235B A22B Thinking", - "display_name": "Qwen: Qwen3 VL 235B A22B Thinking", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": true, - "mode": "fixed", - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "type": "chat" - }, { "id": "qwen/qwen3-vl-30b-a3b-instruct", "name": "Qwen: Qwen3 VL 30B A3B Instruct", @@ -354834,8 +355551,8 @@ ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 262144, + "output": 235929 }, "temperature": true, "tool_call": true, @@ -354858,30 +355575,6 @@ }, "type": "chat" }, - { - "id": "qwen/qwen3-vl-32b-instruct", - "name": "Qwen: Qwen3 VL 32B Instruct", - "display_name": "Qwen: Qwen3 VL 32B Instruct", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": false - }, - "type": "chat" - }, { "id": "qwen/qwen3-vl-8b-instruct", "name": "Qwen: Qwen3 VL 8B Instruct", @@ -354896,8 +355589,8 @@ ] }, "limit": { - "context": 131072, - "output": 32768 + "context": 262144, + "output": 235929 }, "temperature": true, "tool_call": true, @@ -354906,44 +355599,6 @@ }, "type": "chat" }, - { - "id": "qwen/qwen3-vl-8b-thinking", - "name": "Qwen: Qwen3 VL 8B Thinking", - "display_name": "Qwen: Qwen3 VL 8B Thinking", - "modalities": { - "input": [ - "image", - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 131072, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": true, - "mode": "fixed", - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "type": "chat" - }, { "id": "qwen/qwen3.5-122b-a10b", "name": "Qwen: Qwen3.5-122B-A10B", @@ -355036,7 +355691,7 @@ }, "limit": { "context": 262144, - "output": 65536 + "output": 32768 }, "temperature": true, "tool_call": true, @@ -355245,46 +355900,9 @@ "type": "chat" }, { - "id": "qwen/qwen3.6-27b", - "name": "Qwen: Qwen3.6 27B", - "display_name": "Qwen: Qwen3.6 27B", - "modalities": { - "input": [ - "text", - "image", - "video" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 262144, - "output": 65536 - }, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "type": "chat" - }, - { - "id": "qwen/qwen3.6-35b-a3b", - "name": "Qwen: Qwen3.6 35B A3B", - "display_name": "Qwen: Qwen3.6 35B A3B", + "id": "qwen/qwen3.6-27b", + "name": "Qwen: Qwen3.6 27B", + "display_name": "Qwen: Qwen3.6 27B", "modalities": { "input": [ "text", @@ -355297,9 +355915,8 @@ }, "limit": { "context": 262144, - "output": 235929 + "output": 81920 }, - "temperature": true, "tool_call": true, "reasoning": { "supported": true, @@ -355320,9 +355937,9 @@ "type": "chat" }, { - "id": "qwen/qwen3.6-flash", - "name": "Qwen: Qwen3.6 Flash", - "display_name": "Qwen: Qwen3.6 Flash", + "id": "qwen/qwen3.6-35b-a3b", + "name": "Qwen: Qwen3.6 35B A3B", + "display_name": "Qwen: Qwen3.6 35B A3B", "modalities": { "input": [ "text", @@ -355334,9 +355951,10 @@ ] }, "limit": { - "context": 1000000, + "context": 262144, "output": 65536 }, + "temperature": true, "tool_call": true, "reasoning": { "supported": true, @@ -355357,19 +355975,21 @@ "type": "chat" }, { - "id": "qwen/qwen3.6-max-preview", - "name": "Qwen: Qwen3.6 Max Preview", - "display_name": "Qwen: Qwen3.6 Max Preview", + "id": "qwen/qwen3.6-flash", + "name": "Qwen: Qwen3.6 Flash", + "display_name": "Qwen: Qwen3.6 Flash", "modalities": { "input": [ - "text" + "text", + "image", + "video" ], "output": [ "text" ] }, "limit": { - "context": 262144, + "context": 1000000, "output": 65536 }, "tool_call": true, @@ -355571,8 +356191,8 @@ ] }, "limit": { - "context": 1000000, - "output": 131072 + "context": 262144, + "output": 235929 }, "temperature": true, "tool_call": true, @@ -357416,8 +358036,8 @@ ] }, "limit": { - "context": 198000, - "output": 16384 + "context": 202752, + "output": 131072 }, "temperature": true, "tool_call": true, @@ -359717,58 +360337,6 @@ }, "type": "chat" }, - { - "id": "claude-opus-4-6-dd", - "name": "claude-opus-4-6-dd", - "display_name": "claude-opus-4-6-dd", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 128000 - }, - "tool_call": true, - "reasoning": { - "supported": true, - "default": false - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": false, - "mode": "mixed", - "budget": { - "min": 1024, - "unit": "tokens" - }, - "effort": "high", - "effort_options": [ - "low", - "medium", - "high", - "max" - ], - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "notes": [ - "Anthropic recommends adaptive thinking with effort for Claude 4.6; budget_tokens remains a deprecated compatibility path.", - "Anthropic API defaults effort to high; lower effort levels should be chosen per workload." - ] - } - }, - "type": "chat" - }, { "id": "claude-opus-4-6", "name": "claude-opus-4-6", @@ -359925,58 +360493,6 @@ }, "type": "chat" }, - { - "id": "claude-sonnet-4-6-dd", - "name": "claude-sonnet-4-6-dd", - "display_name": "claude-sonnet-4-6-dd", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 1000000, - "output": 128000 - }, - "tool_call": true, - "reasoning": { - "supported": true, - "default": false - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": false, - "mode": "mixed", - "budget": { - "min": 1024, - "unit": "tokens" - }, - "effort": "high", - "effort_options": [ - "low", - "medium", - "high", - "max" - ], - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "notes": [ - "Anthropic recommends adaptive thinking with effort for Claude 4.6; budget_tokens remains a deprecated compatibility path.", - "Anthropic API defaults effort to high; lower effort levels should be chosen per workload." - ] - } - }, - "type": "chat" - }, { "id": "claude-sonnet-4-6-r", "name": "claude-sonnet-4-6-r", @@ -360080,57 +360596,6 @@ }, "type": "chat" }, - { - "id": "claude-opus-4-5-20251101-dd", - "name": "claude-opus-4-5-20251101-dd", - "display_name": "claude-opus-4-5-20251101-dd", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 200000, - "output": 65536 - }, - "tool_call": true, - "reasoning": { - "supported": true, - "default": false - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": false, - "mode": "mixed", - "budget": { - "min": 1024, - "unit": "tokens" - }, - "effort": "high", - "effort_options": [ - "low", - "medium", - "high" - ], - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "notes": [ - "Claude Opus 4.5 uses manual thinking.type = \"enabled\" with budget_tokens; effort can be used alongside the thinking budget.", - "Interleaved thinking requires the interleaved-thinking-2025-05-14 beta header." - ] - } - }, - "type": "chat" - }, { "id": "claude-sonnet-4-5-20250929", "name": "claude-sonnet-4-5-20250929", @@ -360176,51 +360641,6 @@ }, "type": "chat" }, - { - "id": "claude-sonnet-4-5-20250929-dd", - "name": "claude-sonnet-4-5-20250929-dd", - "display_name": "claude-sonnet-4-5-20250929-dd", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 200000, - "output": 64000 - }, - "tool_call": true, - "reasoning": { - "supported": true, - "default": false - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": false, - "mode": "budget", - "budget": { - "min": 1024, - "unit": "tokens" - }, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "notes": [ - "Claude 4 manual thinking uses thinking.type = \"enabled\" with budget_tokens.", - "Interleaved thinking requires the interleaved-thinking-2025-05-14 beta header for this model family." - ] - } - }, - "type": "chat" - }, { "id": "claude-haiku-4-5-20251001", "name": "claude-haiku-4-5-20251001", @@ -360266,51 +360686,6 @@ }, "type": "chat" }, - { - "id": "claude-haiku-4-5-20251001-dd", - "name": "claude-haiku-4-5-20251001-dd", - "display_name": "claude-haiku-4-5-20251001-dd", - "modalities": { - "input": [ - "text", - "image" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 200000, - "output": 64000 - }, - "tool_call": true, - "reasoning": { - "supported": true, - "default": false - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "default_enabled": false, - "mode": "budget", - "budget": { - "min": 1024, - "unit": "tokens" - }, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ], - "notes": [ - "Claude 4 manual thinking uses thinking.type = \"enabled\" with budget_tokens.", - "Interleaved thinking requires the interleaved-thinking-2025-05-14 beta header for this model family." - ] - } - }, - "type": "chat" - }, { "id": "claude-haiku-4-5-20251001-r", "name": "claude-haiku-4-5-20251001-r", @@ -363055,6 +363430,62 @@ }, "type": "chat" }, + { + "id": "gemini-nano-banana-2.1-as", + "name": "gemini-nano-banana-2.1-as", + "display_name": "gemini-nano-banana-2.1-as", + "modalities": { + "input": [ + "text", + "image", + "video", + "audio" + ], + "output": [ + "text", + "image", + "video", + "audio" + ] + }, + "limit": { + "context": 8192, + "output": 8192 + }, + "tool_call": false, + "reasoning": { + "supported": false + }, + "type": "chat" + }, + { + "id": "gemini-nano-banana-2.1", + "name": "gemini nano banana 2.1", + "display_name": "gemini nano banana 2.1", + "modalities": { + "input": [ + "text", + "image", + "video", + "audio" + ], + "output": [ + "text", + "image", + "video", + "audio" + ] + }, + "limit": { + "context": 8192, + "output": 8192 + }, + "tool_call": false, + "reasoning": { + "supported": false + }, + "type": "chat" + }, { "id": "claude-haiku-5-5", "name": "claude-haiku-5-5", @@ -365492,73 +365923,6 @@ }, "type": "imageGeneration" }, - { - "id": "deepseek/deepseek-r1-0528", - "name": "DeepSeek: DeepSeek R1 0528", - "display_name": "DeepSeek: DeepSeek R1 0528", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 163840, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": false, - "release_date": "2025-05-28", - "last_updated": "2025-05-28", - "type": "chat" - }, - { - "id": "deepseek/deepseek-chat-v3.1", - "name": "DeepSeek: DeepSeek V3.1", - "display_name": "DeepSeek: DeepSeek V3.1", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 163840, - "output": 32768 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true, - "default": true - }, - "attachment": false, - "open_weights": false, - "release_date": "2025-08-21", - "last_updated": "2025-08-21", - "type": "chat" - }, { "id": "deepseek/deepseek-v3.2", "name": "DeepSeek: DeepSeek V3.2", @@ -366449,17 +366813,16 @@ }, "limit": { "context": 262144, - "output": 32768 + "output": 262144 }, - "temperature": true, "tool_call": true, "reasoning": { "supported": false }, "attachment": false, - "open_weights": true, + "open_weights": false, "release_date": "2026-04-23", - "last_updated": "2026-06-29", + "last_updated": "2026-04-23", "type": "chat" }, { @@ -366476,17 +366839,16 @@ }, "limit": { "context": 262144, - "output": 32768 + "output": 262144 }, - "temperature": true, "tool_call": true, "reasoning": { "supported": false }, "attachment": false, - "open_weights": true, - "release_date": "2026-04-24", - "last_updated": "2026-04-24", + "open_weights": false, + "release_date": "2026-04-21", + "last_updated": "2026-04-21", "type": "chat" }, { @@ -366505,6 +366867,7 @@ "context": 262144, "output": 32768 }, + "temperature": true, "tool_call": true, "reasoning": { "supported": true @@ -366515,7 +366878,7 @@ } }, "attachment": false, - "open_weights": false, + "open_weights": true, "release_date": "2026-07-23", "last_updated": "2026-07-23", "type": "chat" @@ -366594,6 +366957,7 @@ "context": 262144, "output": 32768 }, + "temperature": true, "tool_call": true, "reasoning": { "supported": true, @@ -366601,8 +366965,8 @@ }, "attachment": true, "open_weights": true, - "release_date": "2026-09-09", - "last_updated": "2026-09-09", + "release_date": "2026-09-10", + "last_updated": "2026-09-10", "type": "chat" }, { @@ -366767,8 +367131,8 @@ ] }, "limit": { - "context": 262144, - "output": 65536 + "context": 262000, + "output": 65000 }, "temperature": true, "tool_call": true, @@ -366776,10 +367140,11 @@ "supported": true, "default": true }, - "attachment": false, - "open_weights": false, - "release_date": "2026-05-08", - "last_updated": "2026-05-27", + "attachment": true, + "open_weights": true, + "knowledge": "2025-12-31", + "release_date": "2026-05-07", + "last_updated": "2026-05-14", "type": "chat" }, { @@ -367151,14 +367516,30 @@ ] }, "limit": { - "context": 256000, - "output": 256000 + "context": 262144, + "output": 32768 }, - "tool_call": false, + "temperature": true, + "tool_call": true, "reasoning": { "supported": true, "default": true }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": false, + "open_weights": true, + "release_date": "2026-07-21", + "last_updated": "2026-07-21", "type": "chat" }, { @@ -367174,14 +367555,30 @@ ] }, "limit": { - "context": 1000000, - "output": 1000000 + "context": 1048576, + "output": 131072 }, - "tool_call": false, + "temperature": true, + "tool_call": true, "reasoning": { "supported": true, "default": true }, + "extra_capabilities": { + "reasoning": { + "supported": true, + "interleaved": true, + "summaries": true, + "visibility": "summary", + "continuation": [ + "thinking_blocks" + ] + } + }, + "attachment": false, + "open_weights": true, + "release_date": "2026-07-21", + "last_updated": "2026-07-21", "type": "chat" }, { @@ -369486,73 +369883,6 @@ }, "type": "rerank" }, - { - "id": "qwen/qwen3-coder-plus", - "name": "Qwen: Qwen3-Coder-Plus", - "display_name": "Qwen: Qwen3-Coder-Plus", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 128000, - "output": 65536 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": false - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-07-23", - "last_updated": "2025-07-23", - "type": "chat" - }, - { - "id": "qwen/qwen3-max", - "name": "Qwen: Qwen3-Max-Thinking", - "display_name": "Qwen: Qwen3-Max-Thinking", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 256000, - "output": 65536 - }, - "temperature": true, - "tool_call": true, - "reasoning": { - "supported": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2025-09-23", - "last_updated": "2025-09-23", - "type": "chat" - }, { "id": "qwen/qwen3-vl-plus", "name": "Qwen: Qwen3-VL-Plus", @@ -369715,45 +370045,6 @@ "last_updated": "2026-04-27", "type": "chat" }, - { - "id": "qwen/qwen3.6-max-preview", - "name": "Qwen: Qwen3.6 Max Preview", - "display_name": "Qwen: Qwen3.6 Max Preview", - "modalities": { - "input": [ - "text" - ], - "output": [ - "text" - ] - }, - "limit": { - "context": 245760, - "output": 65536 - }, - "temperature": true, - "tool_call": false, - "reasoning": { - "supported": true - }, - "extra_capabilities": { - "reasoning": { - "supported": true, - "interleaved": true, - "summaries": true, - "visibility": "summary", - "continuation": [ - "thinking_blocks" - ] - } - }, - "attachment": false, - "open_weights": false, - "knowledge": "2025-04", - "release_date": "2026-04-20", - "last_updated": "2026-04-20", - "type": "chat" - }, { "id": "qwen/qwen3.6-plus", "name": "Qwen: Qwen3.6-Plus", diff --git a/src/main/cli/computeService.ts b/src/main/cli/computeService.ts index 659055704..d2b46de9b 100644 --- a/src/main/cli/computeService.ts +++ b/src/main/cli/computeService.ts @@ -702,12 +702,28 @@ export class CliComputeService { retriable: true }) } + const metadata = extractProviderFailureMetadata(error) + const failure = ModelInvokeProviderFailureSchema.parse({ + ...(metadata?.statusCode !== undefined ? { statusCode: metadata.statusCode } : {}), + retryable: providerFailureIsRetryable(metadata?.statusCode, metadata?.retryable) + }) + if (metadata?.code === 'openai_codex_sign_in_required') { + return new CliRequestError( + 'authentication_failed', + 'OpenAI Codex sign-in is required. Sign in again.', + { httpStatus: 401, details: { providerFailure: failure } } + ) + } this.log.warn('[CLI] Media generation failed', { providerId: input.providerId, modelId: input.modelId, - failure: { name: error instanceof Error ? error.name : typeof error } + failure + }) + return new CliRequestError('unavailable', message, { + httpStatus: 503, + retriable: failure.retryable, + details: { providerFailure: failure } }) - return new CliRequestError('unavailable', message, { httpStatus: 503, retriable: true }) } } diff --git a/src/main/provider/auth/openaiCodex/index.ts b/src/main/provider/auth/openaiCodex/index.ts index 1d2b9f75e..b8e5b3db2 100644 --- a/src/main/provider/auth/openaiCodex/index.ts +++ b/src/main/provider/auth/openaiCodex/index.ts @@ -25,6 +25,7 @@ import { import { OpenAICodexCredentialStore, type OpenAICodexTokenSet } from './credentialStore' import { createOpenAICodexPkcePair, createOpenAICodexState } from './pkce' import type { OpenAICodexAuthStatus } from '@shared/types/openai-codex' +import { ProviderHttpError } from '../../providerFailure' export type OpenAICodexBackendAuth = { accessToken: string @@ -306,7 +307,11 @@ export class OpenAICodexAuth { const tokens = this.store.load() if (!tokens) { - throw new Error(this.store.getLoadError() ?? 'OpenAI Codex sign-in is required') + throw new ProviderHttpError(this.store.getLoadError() ?? 'OpenAI Codex sign-in is required', { + statusCode: 401, + code: 'openai_codex_sign_in_required', + retryable: false + }) } const current = @@ -323,7 +328,10 @@ export class OpenAICodexAuth { this.assertEnabled() const tokens = this.store.load() if (!tokens?.refreshToken) { - throw new Error(this.store.getLoadError() ?? 'OpenAI Codex refresh token is unavailable') + throw new ProviderHttpError( + this.store.getLoadError() ?? 'OpenAI Codex refresh token is unavailable', + { statusCode: 401, code: 'openai_codex_sign_in_required', retryable: false } + ) } const refreshed = await this.refreshAccessToken(tokens, true) @@ -427,7 +435,11 @@ export class OpenAICodexAuth { currentTokens: OpenAICodexTokenSet ): Promise { if (!currentTokens.refreshToken) { - throw new Error('OpenAI Codex refresh token is unavailable') + throw new ProviderHttpError('OpenAI Codex refresh token is unavailable', { + statusCode: 401, + code: 'openai_codex_sign_in_required', + retryable: false + }) } const payload = await this.postForm(OPENAI_CODEX_TOKEN_URL, { @@ -498,7 +510,20 @@ export class OpenAICodexAuth { }) if (!response.ok) { - throw new Error(await readErrorBody(response)) + const errorBody = await readErrorBody(response) + let requiresSignIn = false + if (params.grant_type === 'refresh_token') { + try { + requiresSignIn = JSON.parse(errorBody)?.error?.code === 'invalid_refresh_token' + } catch {} + } + throw new ProviderHttpError( + requiresSignIn ? 'OpenAI Codex sign-in has expired. Sign in again.' : errorBody, + { + statusCode: response.status, + ...(requiresSignIn ? { code: 'openai_codex_sign_in_required', retryable: false } : {}) + } + ) } return (await response.json()) as TokenResponse diff --git a/src/main/provider/index.ts b/src/main/provider/index.ts index 7bfb6ab5f..07143b9dd 100644 --- a/src/main/provider/index.ts +++ b/src/main/provider/index.ts @@ -685,7 +685,7 @@ export class ProviderRuntime }) } if (event.type === 'error') { - throw new Error(event.error_message) + throw Object.assign(new Error(event.error_message), { failure: event.failure }) } } } @@ -769,7 +769,7 @@ export class ProviderRuntime }) } if (event.type === 'error') { - throw new Error(event.error_message) + throw Object.assign(new Error(event.error_message), { failure: event.failure }) } } } @@ -856,7 +856,7 @@ export class ProviderRuntime } } if (event.type === 'error') { - throw new Error(event.error_message) + throw Object.assign(new Error(event.error_message), { failure: event.failure }) } } } diff --git a/src/main/provider/modelConfig.ts b/src/main/provider/modelConfig.ts index 89d7e4b11..d257e0647 100644 --- a/src/main/provider/modelConfig.ts +++ b/src/main/provider/modelConfig.ts @@ -1,4 +1,4 @@ -import { ApiEndpointType, ModelType } from '@shared/model' +import { ApiEndpointType, ModelType, isOpenAIImageGenerationModelId } from '@shared/model' import type { IModelConfig, MODEL_META, @@ -499,6 +499,8 @@ export class ModelConfigHelper { } if (!finalConfig) { + const isCodexImage = + normProviderId === 'openai-codex' && isOpenAIImageGenerationModelId(normModelId) finalConfig = { ...this.resolveCapabilityFallbacks( normProviderId, @@ -506,11 +508,12 @@ export class ModelConfigHelper { capabilityIdentity, providerApiType ), + ...(isCodexImage ? { functionCall: false } : {}), timeout: DEFAULT_MODEL_TIMEOUT, temperature: 0.6, topP: undefined, - type: ModelType.Chat, - apiEndpoint: ApiEndpointType.Chat, + type: isCodexImage ? ModelType.ImageGeneration : ModelType.Chat, + apiEndpoint: isCodexImage ? ApiEndpointType.Image : ApiEndpointType.Chat, endpointType: undefined, thinkingBudget: undefined, forceInterleavedThinkingCompat: undefined, diff --git a/src/main/provider/providers/aiSdkProvider.ts b/src/main/provider/providers/aiSdkProvider.ts index b94c789b8..e384d6007 100644 --- a/src/main/provider/providers/aiSdkProvider.ts +++ b/src/main/provider/providers/aiSdkProvider.ts @@ -74,13 +74,16 @@ import { } from '../deepseekResponsesAdapter' const OPENAI_CODEX_RECOMMENDED_MODEL_IDS = [ + 'gpt-6.1-sol', + 'gpt-6-astra', + 'gpt-6-sol', + 'gpt-6-luna', 'gpt-5.5', 'gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna', - 'gpt-5.4', - 'gpt-5.4-mini', - 'gpt-5.3-codex-spark', + 'gpt-image-2.5-sunburst', + 'gpt-image-2.5-flare', 'gpt-image-2' ] const GREENPT_RECOMMENDED_MODEL_IDS = [ @@ -1605,19 +1608,12 @@ export class AiSdkProvider extends BaseLLMProvider { private mapOpenAICodexModels(): MODEL_META[] { const models = this.mapProviderDbModels(this.definition.providerDbGroup || 'Codex') const modelsById = new Map(models.map((model) => [model.id, model])) - const recommended = OPENAI_CODEX_RECOMMENDED_MODEL_IDS.flatMap((id) => { + return OPENAI_CODEX_RECOMMENDED_MODEL_IDS.flatMap((id) => { const model = modelsById.get(id) - return model ? [model] : [] + if (model) return [model] + if (!isOpenAIImageGenerationModelId(id)) return [] + return [{ id, name: id, group: 'Codex', providerId: this.provider.id, isCustom: false }] }) - - if (recommended.length > 0) { - return recommended - } - - return models.filter( - (model) => - model.id.toLowerCase().includes('codex') || model.name.toLowerCase().includes('codex') - ) } private mapKimiForCodingModels(): MODEL_META[] { diff --git a/test/main/cli/computeService.test.ts b/test/main/cli/computeService.test.ts index 9696598fa..ff3fea79f 100644 --- a/test/main/cli/computeService.test.ts +++ b/test/main/cli/computeService.test.ts @@ -16,6 +16,7 @@ import type { MODEL_META, ModelConfig } from '@shared/types/provider' import { CliComputeService, type CliComputeServiceOptions } from '@/cli/computeService' import { ArtifactSpool } from '@/cli/artifactSpool' import type { CliRouteCaller } from '@/routes/routeRegistry' +import { ProviderHttpError } from '@/provider/providerFailure' const mediaSpools: ArtifactSpool[] = [] const temporaryDirectories: string[] = [] @@ -635,6 +636,86 @@ describe('CLI compute service', () => { expect(await readdir(media.artifactDirectory)).toEqual([]) }) + it.each([ + [400, false], + [401, false], + [403, false], + [429, true], + [500, true], + [200, false] + ] as const)( + 'preserves media provider status %i and retryability %s without private data', + async (statusCode, retryable) => { + const error = Object.assign(new Error('private upstream response'), { + statusCode, + ...(statusCode === 200 ? { isRetryable: false } : {}), + code: 'SECRET_PROVIDER_CODE', + responseHeaders: { 'retry-after': 'secret-header-value' } + }) + const media = await createMediaService(ModelType.ImageGeneration, { + generateImageStandalone: vi.fn(async () => { + throw error + }) + }) + await expect( + media.service.dispatchStream( + imagesGenerateRoute.name, + { providerId: provider.id, modelId: media.mediaModel.id, prompt: 'hello' }, + caller, + 'request-error', + new AbortController().signal, + async () => undefined + ) + ).rejects.toMatchObject({ + code: 'unavailable', + retriable: retryable, + options: { details: { providerFailure: { statusCode, retryable } } } + }) + expect(JSON.stringify(media.log.warn.mock.calls)).not.toMatch( + /private upstream response|SECRET_PROVIDER_CODE|secret-header-value/ + ) + } + ) + + it.each([ + [ModelType.ImageGeneration, imagesGenerateRoute.name, 'generateImageStandalone'], + [ModelType.VideoGeneration, videosGenerateRoute.name, 'generateVideoStandalone'], + [ModelType.TTS, speechGenerateRoute.name, 'generateSpeechStandalone'] + ] as const)( + 'reports expired Codex sign-in for %s without requesting retries', + async (type, route, method) => { + const media = await createMediaService(type, { + [method]: vi.fn(async () => { + throw new ProviderHttpError('private OAuth response', { + statusCode: 400, + code: 'openai_codex_sign_in_required', + retryable: false + }) + }) + }) + await expect( + media.service.dispatchStream( + route, + { + providerId: provider.id, + modelId: media.mediaModel.id, + ...(type === ModelType.TTS ? { text: 'hello' } : { prompt: 'hello' }) + }, + caller, + 'request-auth-error', + new AbortController().signal, + async () => undefined + ) + ).rejects.toMatchObject({ + code: 'authentication_failed', + message: 'OpenAI Codex sign-in is required. Sign in again.', + retriable: false, + options: { details: { providerFailure: { statusCode: 400, retryable: false } } } + }) + expect(media.log.warn).not.toHaveBeenCalled() + } + ) + it('normalizes media failures without logging provider response text', async () => { const media = await createMediaService(ModelType.TTS, { generateSpeechStandalone: vi.fn(async () => { diff --git a/test/main/provider/aiSdkProviderFactory.test.ts b/test/main/provider/aiSdkProviderFactory.test.ts index 76302eb9d..9459188f6 100644 --- a/test/main/provider/aiSdkProviderFactory.test.ts +++ b/test/main/provider/aiSdkProviderFactory.test.ts @@ -250,66 +250,69 @@ describe('AI SDK provider factory', () => { expect(context.resolvedModelId).toBe('my-gpt-4.1-deployment') }) - it('generates images through the OpenAI Codex image endpoint', async () => { - const imageBase64 = - 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=' - const fetchMock = vi.fn().mockResolvedValue( - new Response( - JSON.stringify({ - created: 1, - data: [{ b64_json: imageBase64 }] - }), - { - status: 200, - headers: { 'Content-Type': 'application/json' } - } + it.each(['gpt-image-2', 'gpt-image-2.5-sunburst', 'gpt-image-2.5-flare'])( + 'generates %s through the OpenAI Codex image endpoint', + async (modelId) => { + const imageBase64 = + 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=' + const fetchMock = vi.fn().mockResolvedValue( + new Response( + JSON.stringify({ + created: 1, + data: [{ b64_json: imageBase64 }] + }), + { + status: 200, + headers: { 'Content-Type': 'application/json' } + } + ) ) - ) - vi.stubGlobal('fetch', fetchMock) - codexAuthState.getBackendAuth.mockResolvedValueOnce({ - accessToken: 'codex-token', - accountId: 'acct-1' - }) + vi.stubGlobal('fetch', fetchMock) + codexAuthState.getBackendAuth.mockResolvedValueOnce({ + accessToken: 'codex-token', + accountId: 'acct-1' + }) - const context = createAiSdkProviderContext({ - providerKind: 'openai-codex', - provider: { - id: 'openai-codex', - name: 'OpenAI Codex', - apiType: 'openai-codex', - apiKey: '', - baseUrl: 'https://chatgpt.com/backend-api/codex', - customHeaders: { 'X-Tenant-ID': 'team-a' }, - enable: true - } as any, - providerSettings: {} as any, - defaultHeaders: {}, - modelId: 'gpt-image-2', - wrapThinkReasoning: false - }) + const context = createAiSdkProviderContext({ + providerKind: 'openai-codex', + provider: { + id: 'openai-codex', + name: 'OpenAI Codex', + apiType: 'openai-codex', + apiKey: '', + baseUrl: 'https://chatgpt.com/backend-api/codex', + customHeaders: { 'X-Tenant-ID': 'team-a' }, + enable: true + } as any, + providerSettings: {} as any, + defaultHeaders: {}, + modelId, + wrapThinkReasoning: false + }) - expect(context.imageModel).toBeDefined() - expect(context.endpoint).toBe('https://chatgpt.com/backend-api/codex/responses') - expect(context.imageEndpoint).toBe('https://chatgpt.com/backend-api/codex/images/generations') + expect(context.imageModel).toBeDefined() + expect(context.endpoint).toBe('https://chatgpt.com/backend-api/codex/responses') + expect(context.imageEndpoint).toBe('https://chatgpt.com/backend-api/codex/images/generations') - const result = await generateImage({ - model: context.imageModel, - prompt: 'A red fox in a field', - size: '1024x1024' - }) + const result = await generateImage({ + model: context.imageModel, + prompt: 'A red fox in a field', + size: '1024x1024' + }) - expect(result.image.base64).toBe(imageBase64) - expect(fetchMock).toHaveBeenCalledTimes(1) - const [requestUrl, requestInit] = fetchMock.mock.calls[0] as [string, RequestInit] - expect(requestUrl).toBe('https://chatgpt.com/backend-api/codex/images/generations') - expect(new Headers(requestInit.headers).get('x-tenant-id')).toBe('team-a') - expect(JSON.parse(String(requestInit.body))).toEqual({ - model: 'gpt-image-2', - prompt: 'A red fox in a field', - n: 1, - size: '1024x1024' - }) - }) + expect(result.image.base64).toBe(imageBase64) + expect(fetchMock).toHaveBeenCalledTimes(1) + const [requestUrl, requestInit] = fetchMock.mock.calls[0] as [string, RequestInit] + expect(requestUrl).toBe('https://chatgpt.com/backend-api/codex/images/generations') + expect(new Headers(requestInit.headers).get('x-tenant-id')).toBe('team-a') + expect(JSON.parse(String(requestInit.body))).toEqual({ + model: modelId, + prompt: 'A red fox in a field', + n: 1, + size: '1024x1024' + }) + } + ) it('uses deployment ids from azure deployment-scoped urls', () => { const context = createAiSdkProviderContext({ diff --git a/test/main/provider/auth/openaiCodex.test.ts b/test/main/provider/auth/openaiCodex.test.ts index 51680ac74..da5526c55 100644 --- a/test/main/provider/auth/openaiCodex.test.ts +++ b/test/main/provider/auth/openaiCodex.test.ts @@ -193,6 +193,34 @@ describe('OpenAI Codex auth', () => { expect(store.load()?.refreshToken).toBe('new-refresh-token') }) + it('requires sign-in after a rejected refresh token without deleting credentials', async () => { + const store = new OpenAICodexCredentialStore(path.join(tempDir, 'credentials.json')) + store.save({ + accessToken: 'expired-token', + refreshToken: 'rejected-refresh-token', + tokenType: 'Bearer', + expiresAt: Date.now() - 1000, + updatedAt: Date.now() + }) + const fetchMock = vi.fn().mockResolvedValue( + new Response( + JSON.stringify({ + error: { code: 'invalid_refresh_token', message: 'private upstream response' } + }), + { status: 400 } + ) + ) + vi.stubGlobal('fetch', fetchMock) + const auth = new OpenAICodexAuth(store, vi.fn()) + + await expect(auth.getBackendAuth()).rejects.toMatchObject({ + message: 'OpenAI Codex sign-in has expired. Sign in again.', + failure: { statusCode: 400, code: 'openai_codex_sign_in_required', retryable: false } + }) + expect(fetchMock).toHaveBeenCalledOnce() + expect(store.load()?.refreshToken).toBe('rejected-refresh-token') + }) + it('opens browser login externally and completes from a pasted callback URL', async () => { startOAuthLoopbackCallbackSessionMock.mockImplementationOnce( async (options: { expectedState: string; path: string }) => { diff --git a/test/main/provider/openaiCodexProvider.test.ts b/test/main/provider/openaiCodexProvider.test.ts index 7b92216ec..f525b8a59 100644 --- a/test/main/provider/openaiCodexProvider.test.ts +++ b/test/main/provider/openaiCodexProvider.test.ts @@ -10,6 +10,10 @@ import type { LLM_PROVIDER } from '@shared/types/provider' import { checkRequiresRebuild } from '@shared/provider-operations' const CODEX_RESOURCE_MODEL_IDS = [ + 'gpt-6.1-sol', + 'gpt-6-astra', + 'gpt-6-sol', + 'gpt-6-luna', 'gpt-5.6', 'gpt-5.6-sol', 'gpt-5.6-luna', @@ -113,6 +117,14 @@ describe('OpenAI Codex provider registration', () => { id: 'openai', name: 'OpenAI', models: [ + ...['gpt-6.1-sol', 'gpt-6-astra', 'gpt-6-sol', 'gpt-6-luna'].map((id) => ({ + id, + display_name: id, + modalities: { input: ['text', 'image'], output: ['text'] }, + limit: { context: 1050000, output: 128000 }, + tool_call: true, + reasoning: { supported: true } + })), { id: 'gpt-5-codex', display_name: 'GPT-5-Codex', @@ -202,18 +214,28 @@ describe('OpenAI Codex provider registration', () => { providerDbSpy.mockRestore() expect(models.map((model) => model.id)).toEqual([ + 'gpt-6.1-sol', + 'gpt-6-astra', + 'gpt-6-sol', + 'gpt-6-luna', 'gpt-5.5', 'gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna', - 'gpt-5.4', - 'gpt-5.4-mini', - 'gpt-5.3-codex-spark', + 'gpt-image-2.5-sunburst', + 'gpt-image-2.5-flare', 'gpt-image-2' ]) expect(models.some((model) => model.id === 'gpt-5.6')).toBe(false) expect(models.every((model) => model.group === 'Codex')).toBe(true) expect(models.every((model) => model.providerId === 'openai-codex')).toBe(true) + expect(models.find((model) => model.id === 'gpt-image-2.5-sunburst')).toEqual({ + id: 'gpt-image-2.5-sunburst', + name: 'gpt-image-2.5-sunburst', + group: 'Codex', + providerId: 'openai-codex', + isCustom: false + }) const luna = models.find((model) => model.id === 'gpt-5.6-luna') expect(luna).not.toHaveProperty('reasoning') expect(luna).not.toHaveProperty('contextLength') diff --git a/test/main/provider/providerDbModelConfig.test.ts b/test/main/provider/providerDbModelConfig.test.ts index e65d0e94b..4ac32c5f7 100644 --- a/test/main/provider/providerDbModelConfig.test.ts +++ b/test/main/provider/providerDbModelConfig.test.ts @@ -372,6 +372,36 @@ describe('Provider DB strict matching and user overrides', () => { expect(helper.getModelConfig('gpt-image-2', 'openai').vision).toBe(true) }) + it.each(['gpt-image-2.5-sunburst', 'gpt-image-2.5-flare'])( + 'routes Codex image model %s without catalog metadata and preserves user settings', + (modelId) => { + const helper = new ModelConfigHelper() + expect(helper.getModelConfig(modelId, 'openai-codex')).toMatchObject({ + type: ModelType.ImageGeneration, + apiEndpoint: ApiEndpointType.Image, + vision: false, + functionCall: false, + reasoning: false, + isUserDefined: false + }) + expect(helper.getModelConfig(modelId, 'openai')).toMatchObject({ + type: ModelType.Chat, + apiEndpoint: ApiEndpointType.Chat + }) + + helper.setModelConfig(modelId, 'openai-codex', { + ...helper.getModelConfig(modelId, 'openai-codex'), + type: ModelType.Chat, + apiEndpoint: ApiEndpointType.Chat + }) + expect(helper.getModelConfig(modelId, 'openai-codex')).toMatchObject({ + type: ModelType.Chat, + apiEndpoint: ApiEndpointType.Chat, + isUserDefined: true + }) + } + ) + it('applies partial fallbacks when limit fields are missing', () => { const helper = new ModelConfigHelper() const cfg1 = helper.getModelConfig('partial-limit', 'test-provider') diff --git a/test/main/provider/providerRuntime.test.ts b/test/main/provider/providerRuntime.test.ts index cef4c3b8d..c651737dc 100644 --- a/test/main/provider/providerRuntime.test.ts +++ b/test/main/provider/providerRuntime.test.ts @@ -729,6 +729,21 @@ describe('ProviderRuntime Integration Tests', () => { expect(call?.[6]).toEqual([]) }, 15000) + it.each([ + 'generateImageStandalone', + 'generateVideoStandalone', + 'generateSpeechStandalone' + ] as const)('preserves provider failure metadata from %s error events', async (method) => { + const failure = { statusCode: 401, retryable: false } + mockRunAiSdkCoreStream.mockImplementationOnce(async function* () { + yield { type: 'error', error_message: 'provider rejected request', failure } + }) + + await expect( + providerRuntime[method]('mock-openai-api', 'hello', 'mock-gpt-thinking') + ).rejects.toMatchObject({ message: 'provider rejected request', failure }) + }) + it('should summarize titles', async () => { const messages = [ { role: 'user' as const, content: 'Hello, I want to learn about artificial intelligence' }, From 7c56ce9170074d3ec3d4b9831b8629b1d8f2b4bb Mon Sep 17 00:00:00 2001 From: zerob13 Date: Mon, 12 Oct 2026 15:28:41 +0800 Subject: [PATCH 7/9] fix(copilot): guard account changes --- src/main/provider/auth/index.ts | 18 +++- .../providers/githubCopilotProvider.ts | 4 +- .../githubCopilotOAuthService.test.ts | 48 ++++++++++- .../provider/githubCopilotProvider.test.ts | 83 +++++++++++++++---- 4 files changed, 130 insertions(+), 23 deletions(-) diff --git a/src/main/provider/auth/index.ts b/src/main/provider/auth/index.ts index a485d8fca..99ba15a01 100644 --- a/src/main/provider/auth/index.ts +++ b/src/main/provider/auth/index.ts @@ -10,6 +10,7 @@ import { getGlobalXaiGrokAuth, initializeGlobalXaiGrokAuth } from './xaiGrok' import type { OpenAICodexAuthStatus } from '@shared/types/openai-codex' import type { XaiGrokAuthStatus } from '@shared/types/xai-grok' import type { DeepchatEventPublisher } from '@shared/contracts/events' +import type { LLM_PROVIDER } from '@shared/types/provider' import type { OAuthConfig, OAuthServicePort } from '@shared/types/oauth' @@ -29,6 +30,19 @@ export class OAuthService implements OAuthServicePort { initializeGlobalXaiGrokAuth(publishEvent) } + private saveGitHubCopilotCredential(provider: LLM_PROVIDER, apiKey: string): void { + const current = this.providerSettings.getProviderById(provider.id) + if ( + !current || + current.apiType !== provider.apiType || + current.apiKey !== provider.apiKey || + (current.copilotClientId?.trim() || '') !== (provider.copilotClientId?.trim() || '') + ) { + throw new Error('GitHub Copilot configuration changed during sign-in. Please try again.') + } + this.providerSettings.setProviderById(provider.id, { ...current, apiKey }) + } + /** * Start GitHub Copilot Device Flow login process (recommended) */ @@ -42,7 +56,7 @@ export class OAuthService implements OAuthServicePort { const accessToken = await githubDeviceFlow.startDeviceFlow() await getGitHubCopilotToken(accessToken) - this.providerSettings.setProviderById(providerId, { ...provider, apiKey: accessToken }) + this.saveGitHubCopilotCredential(provider, accessToken) logger.info('[GitHub Copilot] Device Flow login completed successfully') return true @@ -133,7 +147,7 @@ export class OAuthService implements OAuthServicePort { } await getGitHubCopilotToken(accessToken) - this.providerSettings.setProviderById(providerId, { ...provider, apiKey: accessToken }) + this.saveGitHubCopilotCredential(provider, accessToken) logger.info('[GitHub Copilot][OAuth] Traditional OAuth login completed successfully') return true diff --git a/src/main/provider/providers/githubCopilotProvider.ts b/src/main/provider/providers/githubCopilotProvider.ts index 8432d8cff..137a716da 100644 --- a/src/main/provider/providers/githubCopilotProvider.ts +++ b/src/main/provider/providers/githubCopilotProvider.ts @@ -75,7 +75,9 @@ export class GithubCopilotProvider extends BaseLLMProvider { const provider = this.provider const data = await getGitHubCopilotToken(provider.apiKey, signal) signal?.throwIfAborted() - // An exchange started before an account change must not populate the new account's cache. + if (this.provider.apiKey !== provider.apiKey) { + throw new Error('GitHub Copilot configuration changed during token exchange. Please retry.') + } if (this.provider === provider) { this.copilotToken = data.token this.tokenExpiresAt = data.expires_at * 1000 diff --git a/test/main/provider/githubCopilotOAuthService.test.ts b/test/main/provider/githubCopilotOAuthService.test.ts index 7b73d2e60..de0d55168 100644 --- a/test/main/provider/githubCopilotOAuthService.test.ts +++ b/test/main/provider/githubCopilotOAuthService.test.ts @@ -44,8 +44,11 @@ describe('GitHub Copilot login validation', () => { mocks.startLogin.mockResolvedValue('auth-code') mocks.exchangeCodeForToken.mockResolvedValue('new-oauth-token') const setProviderById = vi.fn() - const service = new OAuthService({ getProviderById: () => provider, setProviderById }, vi.fn()) - return { provider, service, setProviderById } + const getProviderById = vi.fn((_providerId: string): LLM_PROVIDER | undefined => ({ + ...provider + })) + const service = new OAuthService({ getProviderById, setProviderById }, vi.fn()) + return { provider, service, setProviderById, getProviderById } } for (const method of ['startGitHubCopilotDeviceFlowLogin', 'startGitHubCopilotLogin'] as const) { @@ -89,5 +92,46 @@ describe('GitHub Copilot login validation', () => { expect(setProviderById).not.toHaveBeenCalled() expect(provider.apiKey).toBe('saved-oauth-token') }) + + it.each(['credentials', 'client', 'protocol', 'removal'] as const)( + `${method} rejects stale authentication after a provider change: %s`, + async (change) => { + const { provider, service, setProviderById, getProviderById } = setup() + vi.stubGlobal( + 'fetch', + vi.fn(async () => { + if (change === 'credentials') provider.apiKey = 'newer-oauth-token' + if (change === 'client') provider.copilotClientId = 'new-client' + if (change === 'protocol') provider.apiType = 'openai' + if (change === 'removal') getProviderById.mockReturnValue(undefined) + return Response.json({ token: 'copilot-session', expires_at: 2_000_000_000 }) + }) + ) + + await expect(service[method](provider.id)).rejects.toThrow( + 'GitHub Copilot configuration changed during sign-in' + ) + expect(setProviderById).not.toHaveBeenCalled() + } + ) + + it(`${method} preserves unrelated settings changed during authentication`, async () => { + const { provider, service, setProviderById } = setup() + vi.stubGlobal( + 'fetch', + vi.fn(async () => { + provider.name = 'Renamed Copilot' + provider.enable = false + provider.customHeaders = { 'X-Custom': 'current' } + return Response.json({ token: 'copilot-session', expires_at: 2_000_000_000 }) + }) + ) + + await expect(service[method](provider.id)).resolves.toBe(true) + expect(setProviderById).toHaveBeenCalledWith(provider.id, { + ...provider, + apiKey: 'new-oauth-token' + }) + }) } }) diff --git a/test/main/provider/githubCopilotProvider.test.ts b/test/main/provider/githubCopilotProvider.test.ts index f9ac0fb4c..8b575b285 100644 --- a/test/main/provider/githubCopilotProvider.test.ts +++ b/test/main/provider/githubCopilotProvider.test.ts @@ -466,29 +466,76 @@ describe('GithubCopilotProvider request timeout', () => { expect(getGitHubCopilotToken).toHaveBeenCalledOnce() }) - it('does not cache an old account session after configuration changes during exchange', async () => { + it('keeps the request valid when unrelated provider settings change during exchange', async () => { + const fetchMock = vi + .fn() + .mockResolvedValue(Response.json({ choices: [{ message: { content: 'hello' } }] })) + vi.stubGlobal('fetch', fetchMock) const provider = Object.create(GithubCopilotProvider.prototype) as any - provider.provider = { id: 'github-copilot', apiKey: 'old-account' } + provider.provider = { id: 'github-copilot', apiKey: 'same-account', name: 'Copilot' } + provider.baseApiUrl = 'https://api.githubcopilot.com' provider.providerSettings = { getProviderModels: vi.fn(() => []), - getCustomModels: vi.fn(() => []) + getCustomModels: vi.fn(() => []), + getModelConfig: vi.fn(() => ({})) } - let finishExchange!: (value: { token: string; expires_at: number }) => void - vi.mocked(getGitHubCopilotToken).mockImplementationOnce(() => { - return new Promise((resolve) => { - finishExchange = resolve - }) - }) - const oldCheck = provider.check() - provider.updateConfig({ id: 'github-copilot', apiKey: 'new-account' }) - finishExchange({ token: 'old-session', expires_at: Date.now() / 1000 + 3600 }) - await oldCheck - vi.mocked(getGitHubCopilotToken).mockResolvedValueOnce({ - token: 'new-session', - expires_at: Date.now() / 1000 + 3600 + vi.mocked(getGitHubCopilotToken).mockImplementationOnce(async () => { + provider.updateConfig({ ...provider.provider, name: 'Renamed Copilot' }) + return { token: 'same-account-session', expires_at: Date.now() / 1000 + 3600 } }) - await expect(provider.check()).resolves.toEqual({ isOk: true, errorMsg: null }) - expect(getGitHubCopilotToken).toHaveBeenLastCalledWith('new-account', undefined) + await expect( + provider.completions([{ role: 'user', content: 'hello' }], 'gpt-4o') + ).resolves.toEqual({ + content: 'hello' + }) + expect(fetchMock).toHaveBeenCalledWith( + 'https://api.githubcopilot.com/chat/completions', + expect.objectContaining({ + headers: expect.objectContaining({ Authorization: 'Bearer same-account-session' }) + }) + ) }) + + it.each([true, false])( + 'rejects the original request when accounts change during exchange (stream=%s)', + async (stream) => { + const fetchMock = vi.fn() + vi.stubGlobal('fetch', fetchMock) + const provider = Object.create(GithubCopilotProvider.prototype) as any + provider.provider = { id: 'github-copilot', apiKey: 'old-account' } + provider.baseApiUrl = 'https://api.githubcopilot.com' + provider.providerSettings = { + getProviderModels: vi.fn(() => []), + getCustomModels: vi.fn(() => []), + getModelConfig: vi.fn(() => ({})) + } + let finishExchange!: (value: { token: string; expires_at: number }) => void + vi.mocked(getGitHubCopilotToken).mockImplementationOnce(() => { + return new Promise((resolve) => { + finishExchange = resolve + }) + }) + const oldRequest = stream + ? provider + .coreStream([{ role: 'user', content: 'hello' }], 'gpt-4o', {}, 0.7, 1024, []) + .next() + : provider.completions([{ role: 'user', content: 'hello' }], 'gpt-4o') + const rejection = expect(oldRequest).rejects.toThrow( + 'GitHub Copilot configuration changed during token exchange' + ) + provider.updateConfig({ id: 'github-copilot', apiKey: 'new-account' }) + finishExchange({ token: 'old-session', expires_at: Date.now() / 1000 + 3600 }) + await rejection + expect(fetchMock).not.toHaveBeenCalled() + expect(getGitHubCopilotToken).toHaveBeenCalledOnce() + vi.mocked(getGitHubCopilotToken).mockResolvedValueOnce({ + token: 'new-session', + expires_at: Date.now() / 1000 + 3600 + }) + + await expect(provider.check()).resolves.toEqual({ isOk: true, errorMsg: null }) + expect(getGitHubCopilotToken).toHaveBeenLastCalledWith('new-account', undefined) + } + ) }) From 0a8a2d3f154fced32774f6c3a3156a5b8f2ddd1e Mon Sep 17 00:00:00 2001 From: zerob13 Date: Mon, 12 Oct 2026 15:37:13 +0800 Subject: [PATCH 8/9] fix(auth): preserve Codex error semantics --- docs/features/provider-runtime/spec.md | 3 +- resources/acp-registry/registry.json | 26 +++--- src/main/provider/auth/openaiCodex/index.ts | 21 +++-- test/main/provider/auth/openaiCodex.test.ts | 90 ++++++++++++++------- 4 files changed, 92 insertions(+), 48 deletions(-) diff --git a/docs/features/provider-runtime/spec.md b/docs/features/provider-runtime/spec.md index 6f58b0018..9d921dc1a 100644 --- a/docs/features/provider-runtime/spec.md +++ b/docs/features/provider-runtime/spec.md @@ -111,7 +111,8 @@ Codex requests include required instructions and backend routing headers, preser behavior, and surface entitlement failure without logging token or account identifiers. Rejected refresh tokens retain their HTTP failure metadata and require sign-in again; media CLI calls return `authentication_failed` with `retriable: false`. Other media provider failures expose only normalized -HTTP status and retryability. Image generation +HTTP status and retryability. Unreadable credential files remain storage failures. OAuth error bodies +are parsed before diagnostic messages are limited to 1,000 characters. Image generation uses the same OAuth credential path with `/images/generations`; Responses-only body normalization does not apply to image requests. The image-generation projection preserves shared OpenAI image settings but disables vision input because the standalone route accepts only text prompts. Background provider-db refresh skips diff --git a/resources/acp-registry/registry.json b/resources/acp-registry/registry.json index fe3f56108..7fccc8018 100644 --- a/resources/acp-registry/registry.json +++ b/resources/acp-registry/registry.json @@ -770,7 +770,7 @@ { "id": "harn", "name": "Harn", - "version": "0.10.163", + "version": "0.10.165", "description": "Harn runs .harn agent pipelines as a native ACP coding agent over stdio.", "repository": "https://github.com/burin-labs/harn", "website": "https://harnlang.com", @@ -782,49 +782,49 @@ "distribution": { "binary": { "darwin-aarch64": { - "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.163/harn-aarch64-apple-darwin.tar.gz", + "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.165/harn-aarch64-apple-darwin.tar.gz", "cmd": "./harn", "args": [ "serve", "acp" ], - "sha256": "659693a735cf8bd1dceb04dc660433ebe49a5974f4be0dbf322ac95fa92ff884" + "sha256": "29d9a1eb6024e462f22db26652684b8b10e5ac9c1a9c1fb83916e71f2025de08" }, "darwin-x86_64": { - "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.163/harn-x86_64-apple-darwin.tar.gz", + "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.165/harn-x86_64-apple-darwin.tar.gz", "cmd": "./harn", "args": [ "serve", "acp" ], - "sha256": "406b1416f80764fad8497074078593cbf26577531684d3d62fd59008db6a8ffc" + "sha256": "0f3ca86f1f3f78ba50c23a93c03c4974c2d52ae81e9e01ff52cdc5f967de9e53" }, "linux-aarch64": { - "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.163/harn-aarch64-unknown-linux-gnu.tar.gz", + "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.165/harn-aarch64-unknown-linux-gnu.tar.gz", "cmd": "./harn", "args": [ "serve", "acp" ], - "sha256": "89126de50317ad5fda5893c13862f0683f1f81c7b57f682033bc3e19c75e8c56" + "sha256": "e312f48a8bf7aa02defafc6e820a752eb0e6d170b2f3b9b81b3832aa8850ce14" }, "linux-x86_64": { - "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.163/harn-x86_64-unknown-linux-gnu.tar.gz", + "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.165/harn-x86_64-unknown-linux-gnu.tar.gz", "cmd": "./harn", "args": [ "serve", "acp" ], - "sha256": "e778c31058464c46ab7e9d5d6d9f6cab87a14cb106781817d74ef2eb7f2f15ea" + "sha256": "68f368f0163c07587ce3360781f72bbc44d744db2c16a57b4fd708b1c872d639" }, "windows-x86_64": { - "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.163/harn-x86_64-pc-windows-msvc.zip", + "archive": "https://github.com/burin-labs/harn/releases/download/v0.10.165/harn-x86_64-pc-windows-msvc.zip", "cmd": "harn.exe", "args": [ "serve", "acp" ], - "sha256": "da2cbf6838b417337be8eefb74d44f0bbcd2e1a99958aa0f02037c8339582b8e" + "sha256": "da62c98d007dabf6d6f426d05d19866a8425b3903bfbf18c6dd5ca6788c50541" } } }, @@ -1163,7 +1163,7 @@ { "id": "nova", "name": "Nova", - "version": "1.1.51", + "version": "1.1.52", "description": "Nova by Compass AI - a fully-fledged software engineer at your command", "repository": "https://github.com/Compass-Agentic-Platform/nova", "website": "https://www.compassap.ai/portfolio/nova.html", @@ -1175,7 +1175,7 @@ "icon": "https://cdn.agentclientprotocol.com/registry/v1/latest/nova.svg", "distribution": { "npx": { - "package": "@compass-ai/nova@1.1.51", + "package": "@compass-ai/nova@1.1.52", "args": [ "acp" ] diff --git a/src/main/provider/auth/openaiCodex/index.ts b/src/main/provider/auth/openaiCodex/index.ts index b8e5b3db2..c14ba4973 100644 --- a/src/main/provider/auth/openaiCodex/index.ts +++ b/src/main/provider/auth/openaiCodex/index.ts @@ -102,7 +102,7 @@ async function readErrorBody(response: Response): Promise { if (!text.trim()) { return `${response.status} ${response.statusText}` } - return text.slice(0, 1000) + return text } catch { return `${response.status} ${response.statusText}` } @@ -307,7 +307,9 @@ export class OpenAICodexAuth { const tokens = this.store.load() if (!tokens) { - throw new ProviderHttpError(this.store.getLoadError() ?? 'OpenAI Codex sign-in is required', { + const loadError = this.store.getLoadError() + if (loadError) throw new Error(loadError) + throw new ProviderHttpError('OpenAI Codex sign-in is required', { statusCode: 401, code: 'openai_codex_sign_in_required', retryable: false @@ -328,10 +330,13 @@ export class OpenAICodexAuth { this.assertEnabled() const tokens = this.store.load() if (!tokens?.refreshToken) { - throw new ProviderHttpError( - this.store.getLoadError() ?? 'OpenAI Codex refresh token is unavailable', - { statusCode: 401, code: 'openai_codex_sign_in_required', retryable: false } - ) + const loadError = this.store.getLoadError() + if (loadError) throw new Error(loadError) + throw new ProviderHttpError('OpenAI Codex refresh token is unavailable', { + statusCode: 401, + code: 'openai_codex_sign_in_required', + retryable: false + }) } const refreshed = await this.refreshAccessToken(tokens, true) @@ -518,7 +523,9 @@ export class OpenAICodexAuth { } catch {} } throw new ProviderHttpError( - requiresSignIn ? 'OpenAI Codex sign-in has expired. Sign in again.' : errorBody, + requiresSignIn + ? 'OpenAI Codex sign-in has expired. Sign in again.' + : errorBody.slice(0, 1000), { statusCode: response.status, ...(requiresSignIn ? { code: 'openai_codex_sign_in_required', retryable: false } : {}) diff --git a/test/main/provider/auth/openaiCodex.test.ts b/test/main/provider/auth/openaiCodex.test.ts index da5526c55..788e019c3 100644 --- a/test/main/provider/auth/openaiCodex.test.ts +++ b/test/main/provider/auth/openaiCodex.test.ts @@ -5,6 +5,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { OpenAICodexAuth } from '@/provider/auth/openaiCodex' import { OpenAICodexCredentialStore } from '@/provider/auth/openaiCodex/credentialStore' import { createOpenAICodexPkcePair } from '@/provider/auth/openaiCodex/pkce' +import { extractProviderFailureMetadata } from '@/provider/providerFailure' const { startOAuthLoopbackCallbackSessionMock } = vi.hoisted(() => ({ startOAuthLoopbackCallbackSessionMock: vi.fn() @@ -193,32 +194,59 @@ describe('OpenAI Codex auth', () => { expect(store.load()?.refreshToken).toBe('new-refresh-token') }) - it('requires sign-in after a rejected refresh token without deleting credentials', async () => { + it.each([1, 100])( + 'requires sign-in after a rejected refresh token with %i message repeats', + async (messageRepeats) => { + const store = new OpenAICodexCredentialStore(path.join(tempDir, 'credentials.json')) + store.save({ + accessToken: 'expired-token', + refreshToken: 'rejected-refresh-token', + tokenType: 'Bearer', + expiresAt: Date.now() - 1000, + updatedAt: Date.now() + }) + const fetchMock = vi.fn().mockResolvedValue( + new Response( + JSON.stringify({ + error: { + code: 'invalid_refresh_token', + message: 'private upstream response'.repeat(messageRepeats) + } + }), + { status: 400 } + ) + ) + vi.stubGlobal('fetch', fetchMock) + const auth = new OpenAICodexAuth(store, vi.fn()) + + await expect(auth.getBackendAuth()).rejects.toMatchObject({ + message: 'OpenAI Codex sign-in has expired. Sign in again.', + failure: { statusCode: 400, code: 'openai_codex_sign_in_required', retryable: false } + }) + expect(fetchMock).toHaveBeenCalledOnce() + expect(store.load()?.refreshToken).toBe('rejected-refresh-token') + } + ) + + it('limits OAuth diagnostic messages after parsing the complete error response', async () => { const store = new OpenAICodexCredentialStore(path.join(tempDir, 'credentials.json')) store.save({ accessToken: 'expired-token', - refreshToken: 'rejected-refresh-token', + refreshToken: 'refresh-token', tokenType: 'Bearer', expiresAt: Date.now() - 1000, updatedAt: Date.now() }) - const fetchMock = vi.fn().mockResolvedValue( - new Response( - JSON.stringify({ - error: { code: 'invalid_refresh_token', message: 'private upstream response' } - }), - { status: 400 } - ) + vi.stubGlobal( + 'fetch', + vi.fn().mockResolvedValue(new Response('x'.repeat(2000), { status: 500 })) ) - vi.stubGlobal('fetch', fetchMock) const auth = new OpenAICodexAuth(store, vi.fn()) - await expect(auth.getBackendAuth()).rejects.toMatchObject({ - message: 'OpenAI Codex sign-in has expired. Sign in again.', - failure: { statusCode: 400, code: 'openai_codex_sign_in_required', retryable: false } - }) - expect(fetchMock).toHaveBeenCalledOnce() - expect(store.load()?.refreshToken).toBe('rejected-refresh-token') + const failure = await auth.getBackendAuth().catch((error) => error) + expect(failure).toBeInstanceOf(Error) + expect(failure.message).toHaveLength(1000) + expect(failure.failure).toEqual({ statusCode: 500 }) }) it('opens browser login externally and completes from a pasted callback URL', async () => { @@ -326,15 +354,23 @@ describe('OpenAI Codex auth', () => { expect(status.error).toContain('not valid JSON') }) - it('rejects backend auth requests with the credential-store load error', async () => { - vi.spyOn(console, 'warn').mockImplementation(() => {}) - const credentialPath = path.join(tempDir, 'credentials.json') - const store = new OpenAICodexCredentialStore(credentialPath) - const auth = new OpenAICodexAuth(store, vi.fn()) - - files.set(credentialPath, '{broken') - - await expect(auth.getBackendAuth()).rejects.toThrow(/not valid JSON/) - await expect(auth.forceRefreshBackendAuth()).rejects.toThrow(/not valid JSON/) - }) + it.each(['getBackendAuth', 'forceRefreshBackendAuth'] as const)( + 'keeps credential-store load errors separate from sign-in errors in %s', + async (method) => { + vi.spyOn(console, 'warn').mockImplementation(() => {}) + const credentialPath = path.join(tempDir, 'credentials.json') + const store = new OpenAICodexCredentialStore(credentialPath) + const auth = new OpenAICodexAuth(store, vi.fn()) + + files.set(credentialPath, '{broken') + + const failure = await auth[method]().catch((error) => error) + expect(failure).toBeInstanceOf(Error) + expect(failure.message).toMatch(/not valid JSON/) + expect(extractProviderFailureMetadata(failure)?.code).not.toBe( + 'openai_codex_sign_in_required' + ) + expect(files.get(credentialPath)).toBe('{broken') + } + ) }) From 5e659db57e269511c8ba69f8e39feb259b3ead75 Mon Sep 17 00:00:00 2001 From: zerob13 Date: Mon, 12 Oct 2026 17:42:09 +0800 Subject: [PATCH 9/9] chore(release): prepare v1.1.4-beta.1 --- CHANGELOG.md | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13aa2553b..c0ccbb739 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## v1.1.4-beta.1 (2026-10-12) +- Added the Atlas Cloud model provider +- Fixed GitHub Copilot session authentication, validated access before saving login credentials, and prevented requests from using another account after an account switch +- Updated the Codex model list with GPT-6 and GPT Image 2.5 models, keeping supported image models available when catalog metadata is missing +- Codex media generation now preserves provider failure details and requests sign-in again when credentials expire instead of retrying authentication failures +- Added optional Parallel Search and Sem MCP user-plugin examples +- Refreshed the built-in model and ACP catalogs +- 新增 Atlas Cloud 模型服务商 +- 修复 GitHub Copilot 会话认证,保存登录凭据前验证访问权限,并防止切换账号后请求使用另一账号 +- 更新 Codex 模型列表,新增 GPT-6 与 GPT Image 2.5 模型,目录元数据缺失时仍保留支持的图像模型 +- Codex 媒体生成保留服务商错误信息,凭据失效时提示重新登录,不再重试认证失败 +- 新增可选的 Parallel Search 与 Sem MCP 用户插件示例 +- 刷新内置模型与 ACP 目录 + ## v1.1.3 (2026-10-09) - Added automatic two-way device sync, Codex-compatible Nowledge Mem integration, and a bundled optional Memcode memory plugin - Reference past conversations in native chats with @ or by dragging from the sidebar, so the agent can look up their content when needed diff --git a/package.json b/package.json index f07b27385..d7733d977 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "DeepChat", - "version": "1.1.3", + "version": "1.1.4-beta.1", "description": "DeepChat,一个简单易用的 Agent 客户端", "main": "./out/main/index.js", "author": "ThinkInAIXYZ",