Capabilities & Protocol-Versionierung
Übersicht
GET /capabilities ist der Preflight-Endpunkt des Daemons. Jeder SDK-Client sollte ihn vor dem Aufruf einer anderen Route lesen, um zu erfahren, welche Protokollversion der Daemon spricht, welche Feature-Tags aktiviert sind und welche Workspace-Runtimes der Daemon akzeptiert. Die Vereinbarung:
- Es gibt nur eine Protokollversion:
v1.SERVE_PROTOCOL_VERSION = 'v1'undSUPPORTED_SERVE_PROTOCOL_VERSIONS = ['v1']. v1 ist intern additiv; brechende Änderungen an der Frame-Form sind für v2 vorbehalten. - Jedes Tag hat eine
since-Version. Zukünftige v2-Daemons können sowohl v1- als auch v2-Tags bewerben. - Einige Tags sind konditional. Tags in
CONDITIONAL_SERVE_FEATURESwerden nur beworben, wenn der entsprechende Deployment-Toggle aktiviert ist. Das Vorhandensein eines Tags bedeutet, dass das Verhalten existiert. - Capability-Tag = Verhaltensvertrag. Das Hinzufügen von neuem Verhalten unter einem bestehenden Tag kann bei Clients, die das alte Tag im Preflight geprüft haben, zu stillschweigenden Brüchen führen. Neues Verhalten benötigt ein neues Tag.
Die vollständige Registry befindet sich in packages/cli/src/serve/capabilities.ts.
Verantwortlichkeiten
- Jedes Feature deklarieren, das der Daemon bewerben könnte.
- Beworbene Features nach Protokollversion und Deployment-Toggles filtern.
getRegisteredServeFeatures()(alle Keys, ungefiltert),getAdvertisedServeFeatures(version, toggles)(gefiltert) undgetServeProtocolVersions()(Envelope{ current, supported }) bereitstellen.- Die Invariante “Tag vorhanden bedeutet Verhalten vorhanden” wahren.
server.test.tsenthält einen Test, der prüft, dass jedes konditionale Tag beworben wird, wenn sein Toggle aktiviert ist; das Hinzufügen eines konditionalen Tags ohne Prädikat schlägt in diesem Test fehl.
Architektur
Capability-Envelope
/capabilities gibt Folgendes zurück:
{
v: 1, // CAPABILITIES_SCHEMA_VERSION
mode: 'http-bridge',
features: ServeFeature[],
workspaceCwd: string,
workspaces?: Array<{ id: string, cwd: string, primary: boolean, trusted: boolean }>,
protocol?: { current: 'v1', supported: ['v1'] },
policy?: { permission: PermissionPolicy },
}workspaceCwd ist der kanonische primäre Workspace-Pfad (siehe 02-serve-runtime.md). Aktuelle Daemons verwenden workspaces[] als registrierten Runtime-Katalog; multi_workspace_sessions zeigt an, dass mehr als eine Runtime aktiv ist. policy.permission ist die aktive Mediator-Richtlinie.
ServeCapabilityDescriptor
interface ServeCapabilityDescriptor {
since: ServeProtocolVersion; // current = 'v1'
modes?: readonly string[]; // lists operation modes when a feature has modes
}Vier v1-Tags verwenden modes:
mcp_guardrails: { since: 'v1', modes: ['warn', 'enforce'] }- Clients sollten'enforce'preflighten, bevor sie sich auf das Ablehnungsverhalten verlassen.permission_mediation: { since: 'v1', modes: ['first-responder', 'designated', 'consensus', 'local-only'] }- dies ist die zur Build-Zeit unterstützte Menge; die aktive Richtlinie befindet sich inpolicy.permission.workspace_voice_transcription: { since: 'v1', modes: ['batch'] }- der Transkriptionspfad, den der Daemon anbietet.voice_transcribe: { since: 'v1', modes: ['streaming', 'batch'] }- die beiden Transkriptionspfade, die auf dem/voice/stream-WebSocket verfügbar sind.
Konditionale Tags
export const CONDITIONAL_SERVE_FEATURES: ReadonlyMap<
ServeFeature,
(toggles: AdvertiseFeatureToggles) => boolean
> = new Map([
['require_auth', (t) => t.requireAuth === true],
['mcp_workspace_pool', (t) => t.mcpPoolActive === true],
['mcp_pool_restart', (t) => t.mcpPoolActive === true],
['allow_origin', (t) => t.allowOriginActive === true],
[
'prompt_absolute_deadline',
(t) => typeof t.promptDeadlineMs === 'number' && t.promptDeadlineMs > 0,
],
[
'writer_idle_timeout',
(t) =>
typeof t.writerIdleTimeoutMs === 'number' && t.writerIdleTimeoutMs > 0,
],
['workspace_settings', (t) => t.persistSettingAvailable === true],
['user_language_sync', (t) => t.persistSettingAvailable === true],
['workspace_voice', (t) => t.persistSettingAvailable === true],
[
'workspace_voice_transcription',
(t) => t.voiceTranscriptionAvailable === true,
],
['session_shell_command', (t) => t.sessionShellCommandEnabled === true],
[
'multi_workspace_session_rewind',
(t) => t.multiWorkspaceSessionsEnabled === true,
],
[
'multi_workspace_session_shell',
(t) =>
t.multiWorkspaceSessionsEnabled === true &&
t.sessionShellCommandEnabled === true,
],
['rate_limit', (t) => t.rateLimit === true],
['workspace_reload', (t) => t.reloadAvailable === true],
['voice_transcribe', (t) => t.voiceWsAvailable !== false],
]);Die Map speichert Mitgliedschaft und Prädikat zusammen. Das Hinzufügen eines neuen konditionalen Tags erfordert zwei koordinierte Änderungen:
- Registriere das Tag und seine
since-Version inSERVE_CAPABILITY_REGISTRY. - Füge sein Prädikat zu
CONDITIONAL_SERVE_FEATUREShinzu.
Baseline-Tags sind nicht in der Map vorhanden und werden bedingungslos beworben. Dies wird absichtlich durch Abwesenheit dargestellt und nicht durch ein separates Set.
v1-Tags nach Domänen gruppiert
Grundlagen: health, daemon_status, capabilities.
Sessions: session_create, session_id_override, session_scope_override, session_load, session_resume, unstable_session_resume, session_list, session_info, session_prompt, session_mid_turn_message_mutation, session_cancel, session_events, session_set_model, session_close, session_metadata, session_archive, session_storage_conflict_repair, session_export, session_transcript, session_context, session_context_usage, session_supported_commands, session_tasks, session_monitor_tool_correlation, session_stats, session_lsp, session_resources, session_status, session_approval_mode_control, session_recap, session_btw, session_shell_command (konditional), session_language, user_language_sync (konditional), session_rewind, session_hooks, session_branch.
Streaming: slow_client_warning, typed_event_schema.
Identität und Heartbeat: client_identity, client_heartbeat.
Berechtigungen: session_permission_vote, permission_vote, permission_mediation (modes: ['first-responder', 'designated', 'consensus', 'local-only']).
Workspace-Read-Only-Snapshots: workspace_mcp, workspace_skills, workspace_providers, workspace_acp_status, workspace_env, workspace_preflight, workspace_hooks, workspace_extensions.
Extension-Management: extension_management_v2 fügt den globalen /extensions/* Katalog-/Mutations-/Operations-Vertrag und die Workspace-Aktivierungsprojektion hinzu. Es ist getrennt von der veröffentlichten workspace_extensions-Kompatibilitätsoberfläche und von workspace_qualified_rest_core.
Lokale Extension-Installation: extension_local_path_install erlaubt einen absoluten Pfad auf dem Daemon-Host im bestehenden source-Feld beider Extension-Install-Routen. Es ist getrennt von extension_management_v2, da die Primary-Workspace-Kompatibilitätsroute es ebenfalls unterstützt, und Clients dürfen keine lokalen Pfade an ältere Daemons senden.
V2-Extension-Batch-Aktivierung: extension_batch_activation_v2 fügt extension_management_v2 queuete globale Standardaktivierungs- und ausgewählte-Workspace-Override-Batches hinzu. Clients müssen dafür unabhängig einen Preflight durchführen, da ältere V2-Daemons nur einzelne Aktivierungsrouten bereitstellen.
Explizite Extension-Aktivierungsaktualisierung: extension_activation_explicit_refresh bedeutet, dass einzelne und Batch-Aktivierungsoperationen am dauerhaften Policy-Commit abschließen, ohne aktive Sessions direkt zu aktualisieren. Clients, die sofortige Anwendung benötigen, sollten auf den Aktivierungserfolg warten und die Workspace-Runtime-Aktualisierungsoperation für jeden Workspace einreichen, dessen Sessions die Änderung sofort übernehmen müssen; ein globaler Standard-Batch ändert die Standardaktivierung, die jeder Workspace erbt, außer dieser Workspace hat ein exaktes Override für den Namen (oder erfüllt eine Legacy-Pfad-Regel), und es gibt keine einzelne Aktualisierung, die jede Runtime abdeckt, daher konvergieren Workspaces, die der Aufrufer nicht aktualisiert, erst beim nächsten 30-Sekunden-Generation-Reconciler-Durchlauf. Daemons ohne dieses Tag schließen die Aktualisierung bereits in die Aktivierungsoperation ein, daher dürfen Caller dort keine Kompatibilitäts-Aktualisierung einreichen.
Workspace-qualifizierte Session-Lesezugriffe: workspace_persisted_transcript, workspace_session_export, workspace_archived_session_export, workspace_session_live_state. Die aktiven und archivierten Export-Tags sind unabhängig voneinander und von session_export sowie workspace_qualified_rest_core, daher müssen Clients den exakten Speicherzustand, den sie exportieren möchten, vorab per Preflight prüfen. Das Paging für persistierte Transkripte erlaubt einen nicht vertrauenswürdigen sekundären Client im Rahmen seiner begrenzten Lese-Richtlinie; beide vollständigen Export-Pfade bleiben nur für vertrauenswürdige Clients zugänglich. workspace_session_live_state ist ebenfalls unabhängig von workspace_qualified_rest_core und nur für vertrauenswürdige Clients: Es liefert den ausschließlich im Speicher gehaltenen Live-Session-Snapshot und die Katalogversion der ausgewählten Runtime und erweitert nicht die Lese-Richtlinie für nicht vertrauenswürdige Secondaries auf den Live-Bridge-State.
Workspace-Mutation (Wave 4+): workspace_memory, workspace_agents, workspace_agent_generate, workspace_acp_preheat, workspace_tool_toggle, workspace_skill_settings_toggle, workspace_skill_settings_batch_toggle, workspace_settings (konditional), workspace_permissions, workspace_init, workspace_github_setup, workspace_trust, workspace_mcp_restart, workspace_mcp_manage, workspace_file_read, workspace_file_bytes, workspace_file_read_cursor, workspace_file_write, workspace_file_upload, workspace_reload (konditional). Die beiden Skill-Einstellungs-Tags ersetzen die eingestellten katalogvalidierten Tags workspace_skill_toggle und workspace_skill_batch_toggle.
MCP-Guardrails: mcp_guardrails (modes: ['warn', 'enforce']), mcp_guardrail_events, mcp_server_runtime_mutation, mcp_workspace_pool (konditional), mcp_pool_restart (konditional).
Prompt-Steuerung: prompt_absolute_deadline (konditional), writer_idle_timeout (konditional), non_blocking_prompt.
Auth: auth_provider_install, auth_device_flow, require_auth (konditional), allow_origin (konditional).
Voice: workspace_voice (konditional), workspace_voice_transcription (konditional, modes: ['batch']), voice_transcribe (konditional, modes: ['streaming', 'batch']).
Rate-Limiting: rate_limit (konditional).
Multi-Workspace-Session-Routing: multi_workspace_sessions (konditional),
multi_workspace_session_rewind (konditional) und
multi_workspace_session_shell (konditional). Ein Client kann Rewind für
eine primäre Session mit session_rewind verwenden; eine sekundäre Live-Session
erfordert zusätzlich multi_workspace_session_rewind. Shell verwendet das
äquivalente session_shell_command plus multi_workspace_session_shell-Paarung
für eine sekundäre Session. ACP-native Clients verwenden weiterhin die von
initialize zurückgegebenen _qwen.methods; es wird keine ACP-Rewind-Vendor-Methode
beworben.
Fettgedruckte Tags haben modes oder sind konditional.
Ablauf
Daemon-Seite: Envelope zusammenstellen
Client-Seite: Feature-Preflight
Status und Lebenszyklus
CAPABILITIES_SCHEMA_VERSIONist die Version der Wire-Envelope-Form, derzeit1. Erhöhe sie nur bei einem Envelope-Bruch.SERVE_PROTOCOL_VERSION = 'v1'ist die Protokoll-Feature-Version. Das Hinzufügen von Features innerhalb von v1 ist additiv; alte Clients sehen kein neues Verhalten, es sei denn, sie preflighten das neue Tag. Korrigiertes Verhalten kann eine Capability innerhalb von v1 ersetzen: Das ersetzende Tag löst das alte Tag ab, das alte Tag wird nicht mehr beworben, und Clients müssen das ersetzende Tag per Preflight prüfen. Das Entfernen eines Features ohne Ersatz ist ein v2-Bruch.EVENT_SCHEMA_VERSION = 1ist das SSE-Frame-v-Feld (siehe09-event-schema.md). Es ist eine unabhängige Versionsachse; das Erhöhen des Event-Schemas impliziert nicht das Erhöhen der Protokollversion und umgekehrt.session_resumeist die stabile Daemon-Capability fürPOST /session/:id/resume.unstable_session_resumewird weiterhin als veralteter Alias beworben, da die zugrunde liegende ACP-Methode immer nochconnection.unstable_resumeSessionheißt; neue Clients solltensession_resumeper Feature-Detection erkennen.
Abhängigkeiten
- Wird von
packages/cli/src/serve/server.tsbeim Erstellen von/capabilities-Antworten gelesen. - Die Toggle-Eingabe stammt von
runQwenServe/createServeApp, einschließlich Authentifizierung, MCP, Origin, Prompt, Einstellungen, Shell, Rate-Limit, Reload und Live-Workspace-Runtime-Count-Status. - Die aktive
permission-Richtlinie im Envelope stammt vonBridgeOptions.permissionPolicy, welches seinerseitssettings.jsonpolicy.permissionStrategyliest.
Konfiguration
| Quelle | Einstellung | Auswirkung auf Capabilities |
|---|---|---|
| CLI-Flag | --require-auth | Bewirbt require_auth. |
| Env | QWEN_SERVE_NO_MCP_POOL=1 | Stoppt das Bewerben von mcp_workspace_pool und mcp_pool_restart; MCP-Events stempeln nicht mehr scope: 'workspace'. |
| CLI-Flag | --mcp-client-budget=N, --mcp-budget-mode={off,warn,enforce} | Ändert nicht das Tag-Set (mcp_guardrails wird immer beworben), ändert aber die serverbezogene Reservierung und das Ablehnungsverhalten. |
| CLI-Flag / Env | --rate-limit / QWEN_SERVE_RATE_LIMIT=1 | Bewirbt rate_limit. |
| Eingebettete Option | persistSettingAvailable | Bewirbt workspace_settings, user_language_sync und workspace_voice. |
| Eingebettete Option | voiceTranscriptionAvailable | Bewirbt workspace_voice_transcription. |
| CLI-Flag / Eingebettete Option | --enable-session-shell / sessionShellCommandEnabled | Bewirbt session_shell_command. |
| Runtime-Status | Mehr als eine registrierte Workspace-Runtime | Bewirbt multi_workspace_sessions und multi_workspace_session_rewind; bewirbt auch multi_workspace_session_shell, wenn Session-Shell effektiv aktiviert ist. |
| Eingebettete Option | reloadAvailable | Bewirbt workspace_reload. |
| Eingebettete Option | voiceWsAvailable | Bewirbt voice_transcribe. |
settings.json | policy.permissionStrategy | Setzt Envelope-policy.permission. |
Einschränkungen und bekannte Grenzen
--require-authversteckt den Preflight. Mit--require-autherfordern alle Routen, einschließlich/capabilities, eine Bearer-Authentifizierung. Ein nicht authentifizierter Client kanncaps.features.require_authnicht preflighten; der 401-Antwort-Body ist die Discovery-Oberfläche. Dasrequire_auth-Tag ist eine authentifizierte Bestätigung für Audit-UIs in abgesicherten Deployments.- Das Vorhandensein eines Tags bedeutet, dass das Verhalten existiert. Wenn ein zukünftiger Contributor Verhalten unter einem bestehenden Tag hinzufügt, ohne
sincezu erhöhen, können Clients, die das alte Tag gepreflightet haben, stillschweigend neues Verhalten erhalten. Die Konvention lautet: Neues Verhalten bekommt ein neues Tag. unstable_*-Tags können ihre Form zwischen Versionen ändern, ohne dass die Protokollversion erhöht wird. Pinne eine SDK-Version, wenn du dich darauf verlässt.- Der Routen-Katalog befindet sich in
../qwen-serve-protocol.md; diese Seite dupliziert ihn absichtlich nicht.
Referenzen
packages/cli/src/serve/capabilities.tspackages/cli/src/serve/types.ts(ServeOptions,CapabilitiesEnvelope)packages/cli/src/serve/server.ts(Envelope-Zusammenstellung)packages/acp-bridge/src/eventBus.ts(EVENT_SCHEMA_VERSION)- Wire-Referenz:
../qwen-serve-protocol.md - Auth- und Deployment-Guardrails:
12-auth-security.md