Support Matrix
How far each model row and protocol that 2.3 added is verified — documented, fixture-tested, live-verified — kept apart, and what the 2.4 stores and runners were tested against.
文档正文为英文。导航、搜索和界面会跟随你选择的语言。
A model in the registry, or a protocol in a module, is not a promise that it works against the provider's live API. This page says, for every model row and every protocol 2.3 added, which of three levels of verification it has reached. The levels are kept apart on purpose: a documented rule that is tested offline is still not live-verified.
| Level | What it means |
|---|---|
| Documented | The behaviour follows the provider's official documentation as of the date given, or the type definitions of the provider's official npm package at the version given. It records what the provider states, not that the provider accepts what Deuz sends. |
| Fixture-tested | Offline tests in packages/core/test, run by every npm test with no API key and no network beyond 127.0.0.1. They pin what Deuz sends and how it reads a scripted answer. Where the table below says so, the other side is the official MCP or A2A SDK, installed as a devDependency; elsewhere it is a stand-in written from the provider's documentation and SDK types. |
| Live-verified | Checked against the provider's real API with a real key. |
Nothing in 2.3 is live-verified
No model row and no protocol 2.3 added was run against a live provider, so the live column below is "no" everywhere, and resolveModelProfile(model).liveVerified is always false. The repository's opt-in live smoke tests (packages/core/test/live, npm run test:live -w @deuz-sdk/core, keys in .env.smoke) date from before 2.3: they call DeepSeek deepseek-v4-flash, Gemini gemini-3.6-flash and xAI grok-4.5. 2.3 added ten real-model eval tasks to the same command, and defines an eleventh, the batch twin, that no runner submits; they are defined but have never run. None of these ran for 2.3.
The test files below are named without their .test.ts suffix and live in packages/core/test.
Models
Every row here is new in 2.3 or got new rules in 2.3. The request rules each row applies are on Model profiles; prices are on Pricing. A model without a bundled price still runs: under a USD budget it reports an unpriced-model warning, or is refused with unknownPrice: 'reject' (Models without a price).
| Models | Wire | Documented | Fixture-tested | Bundled price | Live |
|---|---|---|---|---|---|
claude-fable-5-1, claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5, claude-opus-5 | Anthropic Messages | Anthropic's Claude API reference and model overview, cached 2026-10-06. The beta request shapes Deuz sends (thinking block binding, mid-conversation tool changes), and the thinking display modes it reads ('omitted', beta 'updates'), follow @anthropic-ai/sdk 0.133.0's types. | model-requests, model-profile, registry, anthropic, anthropic-block-binding, reasoning-replay, reasoning-blocks, ui-display, stable-prefix, stable-prefix-resume, system-placement, compaction-simple, pricing, batch-pricing | Yes, with a batch rate card | No |
Any other claude-{fable,opus,sonnet,haiku}-N, N ≥ 5 | Anthropic Messages | Nothing about the id itself: it gets the strictest of the documented 5.x rules above. | registry, model-profile, anthropic | No | No |
gpt-6.1-sol | OpenAI Responses; Chat Completions without tools | OpenAI's model page, research-dated 2026-10-09. | model-requests, model-profile, openai, pricing | Yes (research-dated rates) | No |
gpt-6-astra, gpt-6-luna | OpenAI Responses | OpenAI's model catalog, research-dated 2026-10-09; output limits undocumented. | model-requests, model-profile, openai, output-cap | gpt-6-astra only | No |
gemini-3.8-flash | Gemini native | Google's latest-model guide, research-dated 2026-10-09; output limit undocumented. | model-requests, model-profile, google-native, output-cap | No | No |
gemini-3.1-pro-preview (a profile of its own) | Gemini native, OpenAI-compatible | Google's model page, research-dated 2026-10-09. | model-requests, model-profile, google-native, reasoning-replay, ui-text-signature | Yes | No |
deepseek-flash, deepseek-v4-pro, deepseek-v4-flash | Chat Completions | DeepSeek's models and pricing page, research-dated 2026-10-09. | model-requests, model-profile, providers-compat, reasoning-replay | No | No in 2.3 (see below) |
kimi-k3, kimi-k2.7-code | Chat Completions | Kimi's K3 and K2.7 Code quickstarts, research-dated 2026-10-09. | model-requests, model-profile, providers-compat, reasoning-replay | No | No |
glm-5.3 | Chat Completions | Z.ai's GLM-5.3 guide, research-dated 2026-10-09. | model-requests, model-profile, providers-compat | No | No |
Qwen/Qwen3-Coder-Next (any host) | Chat Completions | The official model card, research-dated 2026-10-09. | model-requests, model-profile, providers-compat | No | No |
gpt-5.5, gpt-5.5-pro as reasoning rows | Chat Completions | No dated source in the profile. | openai, output-cap, registry | Yes | No |
Priced models that ran on the fallback row before 2.3: claude-opus-4-5, claude-sonnet-4-5, the GPT-5.6 rows, gpt-5, gpt-5-mini, gpt-5-nano, gpt-5.1, gpt-5.2, gpt-5-pro, gpt-5.2-pro, gpt-5.4-pro, gpt-5.2-codex, and gemini-3.1-pro on Gemini native | Anthropic, OpenAI Responses, Gemini native | No dated source in the profile, apart from the GPT-5 snapshots' effort levels, research-dated 2026-10-10. | pricing-registry; for the GPT-5 snapshots also model-requests, model-profile | Yes | No |
"Research-dated" means the facts come from the dated research behind the 2.3 plan and were not checked against the source again at release. Every profile names its sourceUrl and checkedAt where it has them. gemini-3-pro, shut down on 2026-03-09, keeps its row; its profile reports it deprecated, resolving to gemini-3.1-pro-preview, with no dated source.
DeepSeek V4's always-on reasoning, and its refusal of response_format: json_schema and of a forced tool choice, were observed by the opt-in DeepSeek live test when it was added (August 2026, before 2.3). 2.3 states the forced tool choice in the row and sends it as auto; it did not run the live test again.
Protocols
| Protocol | Deuz surface | Documented | Fixture-tested | Live |
|---|---|---|---|---|
| MCP 2026-07-28, client (dual-stack with 2025-11-25) | createMcpClient, createStdioMcpClient and the loops' mcp option, with sdk and versionNegotiation (MCP) | @modelcontextprotocol/client 2.3.1, the only SDK that ships 2026-07-28, and @modelcontextprotocol/sdk 1.29.0 for the 2025-11-25 line | Against the official v1 (2025-11-25) and v2 (2026-07-28) SDK servers, in-process, on local ports or through the server's handler as an injected fetch, over Streamable HTTP and the legacy SSE transport: mcp-v2-client, mcp-dual-stack, mcp-interop, mcp-http, mcp-sse, mcp-oauth, mcp-sampling, mcp-roots. Over a real stdio child process that runs a minimal JSON-RPC server written for the test: mcp-stdio | No: not against third-party MCP servers |
| MCP server | createMcpServer, serveMcpStdio (MCP server) | @modelcontextprotocol/server 2.3.1, which answers 2026-07-28 clients and, through its stateless fallback, 2025-11-25 ones | Against the official v1 and v2 SDK clients, over HTTP and over in-process stdio streams: mcp-server, mcp-server-stdio, mcp-interop | No: not against third-party MCP hosts |
| A2A v1.0.0, JSON-RPC and HTTP+JSON | fetchAgentCard, createA2AClient, createA2AHandler, createA2AAgentExecutor (A2A) | @a2a-js/sdk 1.3.0, which implements A2A v1.0.0 | In both directions against @a2a-js/sdk 1.3.0 (a2a-interop): its client against the handler over both bindings, in-process; the Deuz client against its server, over JSON-RPC through the SDK's request handler in-process and over HTTP+JSON through its express restHandler on 127.0.0.1. The same SDK client against createA2AAgentExecutor over both bindings, in-process: an approval answered in a data part and the typed output as a data artifact, a streamed turn, a cancel (a2a-agent-interop). Against scripted wire payloads and each other: a2a-client, a2a-handler, a2a-roundtrip, a2a-task-store, and for the executor a2a-agent | No: not against third-party agents |
| OpenAI Realtime, WebSocket | createRealtimeSession with createOpenAIRealtime; createOpenAIClientSecret (Realtime) | openai 7.32's type definitions | A scripted socket, a scripted token endpoint, and a local RFC 6455 server reached through Node's own global WebSocket: realtime-openai, realtime-session, realtime-node-socket, realtime-tokens, realtime-encoding | No |
| Gemini Live, WebSocket | createRealtimeSession with createGeminiLive; createGeminiAuthToken (Realtime) | @google/genai 2.28's type definitions | The same harness: realtime-gemini, realtime-session, realtime-node-socket, realtime-tokens, realtime-encoding | No |
OpenAI Batch (Files API, then /v1/responses or /v1/chat/completions) | createBatchClient (Batch) | openai 7.32's types and the Batch guide they link to | In-memory stand-ins of each provider's batch API: batch-openai, batch-client, batch-parse, batch-prepare, batch-budget, batch-pricing | No |
| Anthropic Message Batches | createBatchClient | @anthropic-ai/sdk 0.133's types; the 50% batch rates from the Claude API reference, cached 2026-10-06 | batch-anthropic, and the shared batch tests above | No |
Gemini batch mode (batchGenerateContent, Developer API) | createBatchClient | @google/genai 2.28's REST converters | batch-gemini, and the shared batch tests above | No |
| Stop details and refusals, Anthropic | stopDetails on the results of generateText, streamChat, generateObject, streamObject, native runs and batch requests, on finish and step-finish parts, on NoObjectGeneratedError and on the UI wire | stop_reason: 'refusal' with stop_details, from the Claude API reference, cached 2026-10-06 | stop-details, stop-details-wiring, finish-gate, no-object-stop-details, ui-display, ui-agent, batch-parse | No |
| Stop details and refusals, OpenAI | A refusal ends the turn with finishReason: 'content_filter' and stopDetails: { type: 'refusal', explanation }, the model's refusal text, wherever the Anthropic row reports stopDetails; the text also stays on the finish part as providerMetadata.openai.refusal. A turn the content filter stopped ends with content_filter, without stopDetails | openai 7.32's types: Chat Completions delta.refusal, message.refusal and finish_reason; the Responses refusal content part, its response.refusal.delta and response.refusal.done events, and incomplete_details.reason | openai-refusal, openai, finish-gate-providers, batch-parse | No |
| Stop details and refusals, Gemini | finishReason: 'content_filter' without stopDetails. The finish part and a batch result keep Gemini's own finishReason as providerMetadata.google.finishReason | @google/genai 2.28's FinishReason and promptFeedback.blockReason | google-native, finish-gate-providers, batch-parse | No |
Deuz reads a stop explanation from Anthropic (stop_details, with a refusal's category) and from OpenAI (the refusal text, without a category). It reads none from Gemini: a Gemini candidate's finishMessage is not read, so a Gemini stop has no stopDetails.
- Streams, Gemini. The streaming adapter behind
generateText,streamChat, the object calls and native runs maps everyFinishReasonvalue of@google/genai2.28, each with a fixture (2.3). The filtersSAFETY,RECITATION,BLOCKLIST,PROHIBITED_CONTENT,SPII,IMAGE_SAFETY,IMAGE_PROHIBITED_CONTENTandIMAGE_RECITATION, and a blocked prompt, end a turn withcontent_filter; before 2.3,SPIIand the last two ended it with'stop'.MAX_TOKENSandCONTINUATIONend it withlength(Deuz sends no continuation token;CONTINUATIONended it with'stop'before 2.3),STOPandFINISH_REASON_UNSPECIFIEDwithstop, and so do the stops that leave no usable answer (LANGUAGE,OTHER,MALFORMED_FUNCTION_CALL,UNEXPECTED_TOOL_CALL,TOO_MANY_TOOL_CALLS,NO_IMAGE,IMAGE_OTHER), as before 2.3. A value 2.28 does not list ends it withstop. Thefinishpart keeps Gemini's own value asproviderMetadata.google.finishReason(2.3), which tells those stops fromSTOP. A turn that streamed a call ends withtool_callsunless a filter or a limit stopped it; before 2.3 the call won over every reason. - Streams, OpenAI. Chat Completions'
finish_reasonmaps one to one, with the deprecatedfunction_callastool_calls. A Responses turn ends withlengthwhenincomplete_details.reasonismax_output_tokensand withcontent_filterwhen it iscontent_filter; before 2.3 the latter ended with'stop', or'tool_calls'when the turn streamed a call.max_messagesandsteered, whichopenai7.32 does not document beyond the name, end it as a complete response does. A refusal on either wire ends the turn withcontent_filterunless the provider reportedlengthorcontent_filteritself, also when the stream closed before its last event (Chat Completions without afinish_reason, Responses withoutresponse.completedorresponse.incomplete). Before 2.3 the refusal was dropped, so a refused turn ended with'stop'(or'tool_calls') like an empty answer. The refusal never becomes answer text. - Batch results. The batch parsers share the streaming adapters' mapping, so a batch result ends as the same reply does when streamed: the same finish reason, for an OpenAI refusal the same
stopDetailsandproviderMetadata.openai.refusal, and for Gemini the sameproviderMetadata.google.finishReason. - Tool calls. Whatever the provider, a turn that ends with
content_filterorlengthdispatches none of its tool calls (2.3;finish-gatereplays the Anthropic wire,finish-gate-providersthe Gemini, Responses and Chat Completions wires). That covers a Gemini filter or limit after a call, an OpenAI turn its content filter stopped, and an OpenAI refusal. A turn that ends with any other reason is not held back: a Gemini stop without a usable answer after a call ends withtool_calls, and its call runs, as before 2.3.
2.4
2.4 adds no model row and no provider protocol, and nothing in it was run against a live provider: every model call its features make (memory LLM and embedder callbacks, native runs under the goal supervisor, verifiers, skill proposals) is tested against scripted models. What 2.4 adds is verified against the backends it runs on.
| Surface | In every check run (offline) | Against a real backend |
|---|---|---|
| SQLite stores: versioned memory, goal runtime, V3 runs, conditional chats with their transcript index, durable streams, process operations | Real node:sqlite databases | The same |
| PostgreSQL stores: versioned memory, goal runtime, V3 runs, conditional chats with their transcript index, durable streams | PGlite | Postgres 16 in the CI integration job (DEUZ_TEST_POSTGRES_URL). The pgvector path of the versioned memory store only against an emulated vector type in PGlite |
| Redis durable stream store | ioredis-mock, which runs the same Lua scripts | Redis 7 in the CI integration job (DEUZ_TEST_REDIS_URL) |
| Docker sandbox and process runner (preview) | A scripted Docker CLI | A Docker Engine with Linux containers (DEUZ_TEST_DOCKER=1): GitHub's ubuntu runner in the CI Docker job, and Docker Desktop on Windows 11 locally |
| Webhook handler | GitHub, Slack and HMAC signatures computed in the tests with node:crypto | Not against deliveries from GitHub or Slack |
| Time zone schedules | The host's Intl time zone data, across DST gaps and overlaps | Not applicable |
Golden fixtures recorded with 2.3.0 (179 scenarios across the provider factories) check in every run that, with the 2.4 features off, the provider requests (method, URL, headers and body bytes) are the ones 2.3.0 sent. See What is new in 2.4 for the release's known limits.
Related
- Model profiles: what
resolveModelProfilereports for each model, with its source and check date. - Provider conformance: the contract every adapter's stream, usage, finish and errors must satisfy.
- Compatibility: runtimes, subpaths and optional peers.