Skip to Content
Guia do DesenvolvedorModo Daemon (Aprofundamento para Desenvolvedores)Capacidades e Versionamento de Protocolo

Capacidades e Versionamento de Protocolo

Visão Geral

GET /capabilities é o endpoint de preflight do daemon. Todo cliente SDK deve lê-lo antes de chamar qualquer outra rota para descobrir qual versão de protocolo o daemon fala, quais tags de recurso estão habilitadas e quais workspace runtimes o daemon aceita. O contrato:

  • Há apenas uma versão de protocolo: v1. SERVE_PROTOCOL_VERSION = 'v1' e SUPPORTED_SERVE_PROTOCOL_VERSIONS = ['v1']. A v1 é aditiva internamente; mudanças que quebram o formato do frame são reservadas para a v2.
  • Cada tag tem uma versão since. Daemons v2 futuros podem anunciar tanto tags v1 quanto v2.
  • Algumas tags são condicionais. As tags listadas em CONDITIONAL_SERVE_FEATURES são anunciadas apenas quando o toggle de deployment correspondente está habilitado. A presença da tag significa que o comportamento existe.
  • Tag de capability = contrato de comportamento. Adicionar um novo comportamento sob uma tag existente pode quebrar silenciosamente clientes que fizeram preflight da tag antiga. Um novo comportamento precisa de uma nova tag.

O registro completo fica em packages/cli/src/serve/capabilities.ts.

Responsabilidades

  • Declarar cada recurso que o daemon pode anunciar.
  • Filtrar recursos anunciados por versão de protocolo e toggles de deployment.
  • Expor getRegisteredServeFeatures() (todas as chaves, sem filtro), getAdvertisedServeFeatures(version, toggles) (filtrado) e getServeProtocolVersions() (envelope { current, supported }).
  • Preservar o invariante “tag presente significa comportamento presente”. O server.test.ts inclui um teste que garante que toda tag condicional é anunciada quando seu toggle está ativo; adicionar uma tag condicional sem um predicado falha nesse teste.

Arquitetura

Envelope de capacidades

/capabilities retorna:

{ 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 é o caminho canônico do workspace primário (veja 02-serve-runtime.md). Os daemons atuais usam workspaces[] como o catálogo de runtimes registrados; multi_workspace_sessions indica que mais de um runtime está ativo. policy.permission é a política ativa do mediador.

ServeCapabilityDescriptor

interface ServeCapabilityDescriptor { since: ServeProtocolVersion; // current = 'v1' modes?: readonly string[]; // lists operation modes when a feature has modes }

Quatro tags v1 usam modes:

  • mcp_guardrails: { since: 'v1', modes: ['warn', 'enforce'] } - os clientes devem fazer preflight de 'enforce' antes de depender do comportamento de recusa.
  • permission_mediation: { since: 'v1', modes: ['first-responder', 'designated', 'consensus', 'local-only'] } - este é o conjunto suportado em tempo de build; a política ativa está em policy.permission.
  • workspace_voice_transcription: { since: 'v1', modes: ['batch'] } - o caminho de transcrição que o daemon oferece.
  • voice_transcribe: { since: 'v1', modes: ['streaming', 'batch'] } - os dois caminhos de transcrição disponíveis no WebSocket /voice/stream.

Tags condicionais

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], ]);

O Map armazena a associação e o predicado juntos. Adicionar uma nova tag condicional requer duas mudanças coordenadas:

  1. Registrar a tag e sua versão since em SERVE_CAPABILITY_REGISTRY.
  2. Adicionar seu predicado a CONDITIONAL_SERVE_FEATURES.

As tags base não estão presentes no Map e são anunciadas incondicionalmente. Isso é representado intencionalmente pela ausência, em vez de por um Set separado.

Tags v1 agrupadas por domínio

Fundação: health, daemon_status, capabilities.

Sessões: 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 (condicional), session_language, user_language_sync (condicional), session_rewind, session_hooks, session_branch.

Streaming: slow_client_warning, typed_event_schema.

Identidade e heartbeat: client_identity, client_heartbeat.

Permissões: session_permission_vote, permission_vote, permission_mediation (modes: ['first-responder', 'designated', 'consensus', 'local-only']).

Snapshots read-only do workspace: workspace_mcp, workspace_skills, workspace_providers, workspace_acp_status, workspace_env, workspace_preflight, workspace_hooks, workspace_extensions.

Gerenciamento de extensões: extension_management_v2 adiciona o contrato global de catálogo/mutação/operação /extensions/* e a projeção de ativação do workspace. É separado da superfície de compatibilidade publicada workspace_extensions e de workspace_qualified_rest_core.

Instalação local de Extensões: extension_local_path_install permite um caminho absoluto no host do daemon no campo source existente de ambas as rotas de instalação de Extensões. É separado de extension_management_v2 porque a rota de compatibilidade do workspace primário também o suporta, e clientes não devem enviar caminhos locais para daemons mais antigos.

Ativação em lote de Extensões V2: extension_batch_activation_v2 adiciona lotes enfileirados de ativação padrão global e substituição de workspace selecionado ao extension_management_v2. Os clientes devem fazer pre-flight dela independentemente porque daemons V2 mais antigos expõem apenas rotas de ativação singular.

Atualização explícita de ativação de Extensão: extension_activation_explicit_refresh significa que operações de ativação singular e em lote terminam no commit de política durável sem atualizar diretamente as sessões ativas. Clientes que precisam de aplicação imediata devem aguardar o sucesso da ativação e submeter a operação de atualização de runtime do workspace para cada workspace cujas sessões devem aplicar a mudança imediatamente; um lote padrão global altera a ativação padrão que cada workspace herda, a menos que esse workspace tenha uma substituição exata para o nome (ou corresponda a uma regra de caminho legada), e não há uma única atualização que cubra cada runtime, então workspaces que o chamador não atualizar convergem apenas na próxima passagem do reconciliador de geração a cada 30 segundos. Daemons sem essa tag já incluem atualização na operação de ativação, então os chamadores não devem submeter uma atualização de compatibilidade lá.

Leituras de sessão qualificadas por workspace: workspace_persisted_transcript, workspace_session_export, workspace_archived_session_export, workspace_session_live_state. As tags de exportação ativa e arquivada são independentes entre si e de session_export e workspace_qualified_rest_core, então os clientes devem fazer pre-flight do estado exato de armazenamento que pretendem exportar. A paginação de transcrição persistida permite um secundário não confiável sob sua política de leitura limitada; ambos os caminhos de exportação completa permanecem apenas para confiáveis. workspace_session_live_state também é independente de workspace_qualified_rest_core e é apenas para confiáveis: serve o snapshot de sessão ao vivo em memória e a versão do catálogo do runtime selecionado e não estende a política de leitura persistida do secundário não confiável ao estado ao vivo da bridge.

Mutação do workspace (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 (condicional), 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 (condicional). As duas tags de configuração de Skill substituem as tags aposentadas e validadas pelo catálogo workspace_skill_toggle e workspace_skill_batch_toggle.

Guardrails do MCP: mcp_guardrails (modes: ['warn', 'enforce']), mcp_guardrail_events, mcp_server_runtime_mutation, mcp_workspace_pool (condicional), mcp_pool_restart (condicional).

Controle de prompt: prompt_absolute_deadline (condicional), writer_idle_timeout (condicional), non_blocking_prompt.

Autenticação: auth_provider_install, auth_device_flow, require_auth (condicional), allow_origin (condicional).

Voz: workspace_voice (condicional), workspace_voice_transcription (condicional, modes: ['batch']), voice_transcribe (condicional, modes: ['streaming', 'batch']).

Limite de taxa: rate_limit (condicional).

Roteamento de sessão multi-workspace: multi_workspace_sessions (condicional), multi_workspace_session_rewind (condicional) e multi_workspace_session_shell (condicional). Um cliente pode usar rewind para uma sessão primária com session_rewind; uma sessão secundária ativa adicionalmente requer multi_workspace_session_rewind. Shell usa o pareamento equivalente session_shell_command mais multi_workspace_session_shell para uma sessão secundária. Clientes nativos ACP continuam usando os _qwen.methods retornados pelo initialize; nenhum método vendor de rewind ACP é anunciado.

Tags em negrito têm modes ou são condicionais.

Fluxo

Lado do daemon: montar o envelope

Lado do cliente: preflight de recursos

Estado e ciclo de vida

  • CAPABILITIES_SCHEMA_VERSION é a versão do formato do envelope na rede, atualmente 1. Incremente apenas em caso de quebra no envelope.
  • SERVE_PROTOCOL_VERSION = 'v1' é a versão de protocolo-recurso. Adicionar recursos dentro da v1 é aditivo; clientes antigos não veem o novo comportamento a menos que façam preflight da nova tag. Comportamentos corrigidos podem substituir uma capability dentro da v1: a tag de substituição sobrescreve a tag antiga, a tag antiga deixa de ser anunciada, e os clientes devem fazer preflight da substituição. Remover um recurso sem substituição é uma quebra na v2.
  • EVENT_SCHEMA_VERSION = 1 é o campo v do frame SSE (veja 09-event-schema.md). É um eixo de versão independente; incrementar o schema de eventos não implica incrementar a versão do protocolo, e vice-versa.
  • session_resume é a capability estável do daemon para POST /session/:id/resume. unstable_session_resume continua sendo anunciado como um alias depreciado porque o método ACP subjacente ainda se chama connection.unstable_resumeSession; novos clientes devem detectar o recurso session_resume.

Dependências

  • Lido por packages/cli/src/serve/server.ts ao construir respostas de /capabilities.
  • A entrada de toggles vem de runQwenServe / createServeApp, incluindo autenticação, MCP, origin, prompt, configurações, shell, rate-limit, reload e estado dinâmico de contagem de workspace runtime.
  • A política permission ativa no envelope vem de BridgeOptions.permissionPolicy, que por sua vez lê policy.permissionStrategy em settings.json.

Configuração

OrigemOpçãoEfeito nas capacidades
Flag da CLI--require-authAnuncia require_auth.
EnvQWEN_SERVE_NO_MCP_POOL=1Para de anunciar mcp_workspace_pool e mcp_pool_restart; eventos do MCP não estampam mais scope: 'workspace'.
Flag da CLI--mcp-client-budget=N, --mcp-budget-mode={off,warn,enforce}Não altera o conjunto de tags (mcp_guardrails é sempre anunciado), mas altera a reserva por servidor e o comportamento de recusa.
Flag da CLI / env--rate-limit / QWEN_SERVE_RATE_LIMIT=1Anuncia rate_limit.
Opção embutidapersistSettingAvailableAnuncia workspace_settings, user_language_sync e workspace_voice.
Opção embutidavoiceTranscriptionAvailableAnuncia workspace_voice_transcription.
Flag da CLI / opção embutida--enable-session-shell / sessionShellCommandEnabledAnuncia session_shell_command.
Estado de runtimeMais de um workspace runtime registradoAnuncia multi_workspace_sessions e multi_workspace_session_rewind; também anuncia multi_workspace_session_shell quando o shell de sessão está efetivamente habilitado.
Opção embutidareloadAvailableAnuncia workspace_reload.
Opção embutidavoiceWsAvailableAnuncia voice_transcribe.
settings.jsonpolicy.permissionStrategyDefine policy.permission no envelope.

Ressalvas e limitações conhecidas

  • --require-auth oculta o preflight. Com --require-auth, todas as rotas, incluindo /capabilities, exigem bearer auth. Um cliente não autenticado não pode fazer preflight de caps.features.require_auth; o corpo da resposta 401 é a superfície de descoberta. A tag require_auth é uma confirmação autenticada para UIs de auditoria de deployments com segurança reforçada.
  • A presença da tag significa que o comportamento existe. Se um futuro contribuidor adicionar um comportamento sob uma tag existente sem incrementar since, clientes que fizeram preflight da tag antiga podem receber silenciosamente o novo comportamento. A convenção é: novo comportamento recebe uma nova tag.
  • Tags unstable_* podem mudar de formato entre versões sem um incremento de protocolo. Fixe uma versão do SDK ao depender delas.
  • O catálogo de rotas fica em ../qwen-serve-protocol.md; esta página intencionalmente não o duplica.

Referências

  • packages/cli/src/serve/capabilities.ts
  • packages/cli/src/serve/types.ts (ServeOptions, CapabilitiesEnvelope)
  • packages/cli/src/serve/server.ts (montagem do envelope)
  • packages/acp-bridge/src/eventBus.ts (EVENT_SCHEMA_VERSION)
  • Referência de wire: ../qwen-serve-protocol.md
  • Guardrails de autenticação e de deployment: 12-auth-security.md
Last updated on