Pular para o conteúdo principal

Ponte Cordis

A ponte Cordis incorpora o mecanismo DeepSeek Harness (DSH) ao backend do Libre WebUI. O DSH executa como uma árvore de plugins em um runtime Cordis hospedado pelo Libre WebUI. Suas capacidades chegam como serviços Cordis, em vez de módulos importados diretamente.

A ponte vem desativada por padrão. Nada descrito nesta página acontece até um operador ativá-la. Consulte Configuração do Cordis.

Por que usar uma ponte em vez de integração direta

Importar os pacotes DSH diretamente nos serviços do Libre WebUI exigiria menos código, mas tornaria o mecanismo uma dependência de compilação. Trocar um adaptador de modelos ou o ciclo do agente, ou remover o mecanismo, passaria a exigir alterações e uma nova implantação do Libre WebUI.

A ponte inverte essa relação. O Libre WebUI depende de um único contrato abstrato, e um documento de composição Cordis decide como atendê-lo:

  • Mudar o destino sem recompilar. A composição é um arquivo YAML; apontar o mecanismo para outro provedor é uma alteração de configuração.
  • Configurar capacidades. Cada capacidade corresponde a uma entrada do Loader. Alterações na composição mantida pelo operador entram em vigor na próxima inicialização do host.
  • Remover sem resíduos. Todo serviço, listener e efeito instalado pelo mecanismo pertence à fibra raiz. Descartá-la reverte tudo, permitindo parar o mecanismo sem reiniciar o Libre WebUI.

Camadas

As dependências concretas do DSH ficam em backend/src/cordis/dsh/. Rotas e serviços da aplicação consomem os contratos da ponte. O driver do Work tem uma composição separada em memória e nunca monta os plugins de sistema de arquivos do host.

Contratos

O contrato fica em backend/src/cordis/contracts.ts. Seu escopo é intencionalmente restrito aos dados necessários à API do Libre WebUI, expressos sem o vocabulário do mecanismo.

ContratoFinalidade
DshEngine.status()Estado do ciclo de vida de cada serviço (pending / ready / failed)
DshEngine.modelConfiguration()Padrões de modelo e provedor da composição em execução
DshEngine.listSessions()Resumos de sessões, começando pelas mais recentes
DshEngine.getSession(id)Uma sessão com suas mensagens projetadas
DshEngine.createSession(opts)Reservar um ID de sessão e um diretório de trabalho
DshEngine.updateSessionSettings(id, settings)Persistir a seleção do modelo real e o modo de permissão nativo quando ocioso
DshEngine.decideApproval(id, approvalId, decision)Resolver uma aprovação pendente de ferramenta nativa da sessão correspondente
DshEngine.deleteSession(id)Encerrar uma sessão e descartar seu agente
DshEngine.listAgents()Agentes ativos, identificados como raiz ou filhos
DshEngine.listTools()Ferramentas registradas pelo mecanismo para os modelos
DshEngine.sendMessage(id, txt)Iniciar um turno e retornar um identificador de stream
DshEngine.cancel(id)Cancelar o turno em andamento de uma sessão

O contrato é publicado como o serviço Cordis libreDshEngine. O consumidor o acessa com ctx.get('libreDshEngine'), sem importar o módulo da ponte.

EngineStreamChunk transporta text, reasoning, tool-call, tool-result, approval-request, approval-decision, error e done. Os quadros ao vivo são encaminhados pelo agente e pela sessão aos quais pertencem; a mensagem durável correspondente do assistente não é emitida novamente. O identificador retornado por sendMessage tem um subscribe que reproduz tudo que já foi emitido. Assim, um primeiro token rápido não se perde entre o início do turno e a conexão do listener pelo handler HTTP.

Sequência: um turno de chat

O turno é uma única sequência do servidor para o cliente após a solicitação, por isso utiliza NDJSON. Mantê-lo no POST evita outro handshake, ticket e protocolo de reconexão e mantém todo o turno em uma única solicitação autenticada.

DONE e PENDING

O Cordis ativa um plugin quando os serviços declarados estão disponíveis, portanto uma entrada pode permanecer em estados anteriores à execução. É importante distinguir os dois conceitos abaixo; confundi-los é uma causa comum de um mecanismo que não responde.

Estado da entrada do Loader. O Loader acompanha cada entrada em PENDING → LOADING → ACTIVE ou FAILED. Uma entrada com serviços declarados ausentes permanece pendente indefinidamente, em vez de falhar. Por isso, uma composição incompleta pode iniciar o mecanismo sem que ele ofereça qualquer serviço.

Disponibilidade do serviço. O host informa cada serviço esperado como:

EstadoSignificadoCausa
pendingNão registrado no contextoA entrada provedora não foi ativada ou está desabilitada
readyRegistrado e utilizávelA entrada provedora foi ativada
failedDeclarado, mas inutilizávelMotivo informado em uma string detail

host.status() lista todos os serviços esperados com sua disponibilidade e identifica os obrigatórios que faltam. GET /api/cordis/health expõe as mesmas informações. Se faltar um serviço obrigatório, a inicialização lança um erro, em vez de publicar um mecanismo que responde com listas vazias.

Duas cadeias de dependências merecem atenção:

  • dsh-tools não inicia sem systemPrompt.
  • dsh-agent-loop só inicia quando agents, sessions, llm, tools, systemPrompt e sessionProjections existem.

Sem qualquer um deles, a composição pode ter um armazenamento de sessões funcional, mas um mecanismo que nunca responde a mensagens.

Configuração de provedores

A entrada incluída libre-webui-llm-adapter atende aos provedores de modelos configurados no Libre WebUI. O seletor da página do mecanismo escolhe um modelo de provedor para a sessão sem substituir essa entrada.

Alterações nas entradas de plugins da composição entram em vigor na próxima inicialização do host. Reinicie o backend ou desative e reative o Cordis quando o controle administrativo estiver desbloqueado. As sessões persistidas permanecem no armazenamento configurado e são retomadas pela composição atual.

Código de integração confiável pode usar diretamente as APIs de ciclo de vida do Cordis Loader. A ponte não expõe um endpoint para trocar adaptadores nem restaura automaticamente o anterior quando uma substituição falha.

Reversão

Descartar a fibra raiz do host remove tudo que o mecanismo instalou. Essa relação única de responsabilidade sustenta a garantia:

  • Serviços são registrados por plugins e retirados junto com sua fibra.
  • As assinaturas de session/event são registradas no próprio construtor da ponte e pertencem à fibra da entrada da ponte.
  • A ponte acompanha os identificadores dos agentes e os descarta em seu efeito de encerramento.
  • O host descarta o contexto raiz, que possui todas as entradas.

stopCordisHost() é idempotente e participa da sequência de desligamento do backend. Os temporizadores e identificadores de arquivo do mecanismo são liberados explicitamente, sem depender do encerramento do processo.

Identidade e persistência das sessões

A página do mecanismo reserva um ID opaco ao criar a sessão. Com persistência ativada, o cabeçalho é salvo imediatamente; até uma sessão vazia sobrevive a reinicializações. A ponte lista sessões armazenadas e ativas, lê os logs pela API de persistência validada do DSH e retoma o agente com o mesmo ID em turnos posteriores. Novas mensagens de usuário usam o construtor de mensagens identificadas do DSH.

Excluir uma sessão cancela e descarta seu agente antes de remover o artefato. O adaptador local de exclusão JSONL valida os caminhos do armazenamento e da sessão e rejeita links simbólicos. Backends personalizados sem suporte a exclusão retornam um erro, em vez de afirmar que removeram os dados.

O cancelamento chega ao agente nativo, à solicitação do modelo e às ferramentas. Desconectar o cliente cancela seu turno, mas as mensagens concluídas continuam legíveis. O buffer de reprodução tem limite e preserva respostas rápidas emitidas antes da conexão do leitor.

O mecanismo do host é um recurso solo de réplica única. Implantações team não podem montar seu runtime JSONL local. O Work em sandbox usa os repositórios SQL existentes de tarefas, execuções, mensagens, aprovações e eventos.

Interface HTTP

MétodoCaminhoFinalidade
GET/api/cordis/healthEstado da ponte, sem autenticação
GET/api/cordis/sessionsListar sessões
POST/api/cordis/sessionsCriar uma sessão
GET/api/cordis/sessions/:idLer uma sessão com suas mensagens
DELETE/api/cordis/sessions/:idEncerrar uma sessão
POST/api/cordis/sessions/:id/messagesEnviar mensagem e receber NDJSON em streaming
POST/api/cordis/sessions/:id/cancelCancelar o turno em andamento
GET/api/cordis/agentsListar agentes ativos
GET/api/cordis/toolsListar ferramentas registradas

Todas as rotas, exceto /health, exigem uma sessão autenticada de administrador. Quando a ponte não pode atender às solicitações, retornam 503 com code igual a CORDIS_DISABLED, CORDIS_STARTING ou CORDIS_UNAVAILABLE.

Página do Motor Cordis no Libre WebUI com a lista de sessões, ferramentas registradas e uma conversa transmitida em streaming.

A página é frontend/src/pages/CordisPage.tsx, acessível em /cordis pela barra lateral. Ela lista sessões e ferramentas registradas, cria sessões e transmite cada turno para a conversa. Quando a ponte está desligada ou não pode iniciar, mostra o motivo em vez de uma lista vazia, distinguindo a ausência de sessões da ausência do mecanismo.

O cliente do navegador fica em frontend/src/utils/api/cordisApi.ts. Ele usa apenas essa interface, sem importar tipos do backend ou pacotes @deepseek-ai/*, permitindo trocar o mecanismo sem alterar o frontend. O turno é consumido com sendMessage(sessionId, text, { onChunk }); o cliente analisa o JSON delimitado por novas linhas e aceita chunks divididos entre leituras de rede.

Controles de chat do mecanismo

A página do mecanismo renderiza Markdown, tabelas e blocos de código com realce de sintaxe, com controles para copiar respostas e código. Prompts de sistema e contexto de runtime injetado ficam na seção recolhida Contexto da sessão, sem aparecer como mensagens escritas pelo usuário. Raciocínio exposto e atividade das ferramentas têm seções próprias, e os resultados continuam associados à operação correta após recarregar.

Escolha um modelo real de provedor no compositor. O seletor usa os modelos locais e de plugins disponíveis ao administrador conectado, incluindo a identidade do provedor. Seleções de personas e agentes do Chat não são IDs de modelo e não injetam suas instruções na conversa do mecanismo. Cabeçalhos antigos de modelos de persona que falharam são ignorados como sugestões de modelo padrão, sem alterar o log salvo.

Cada sessão tem uma configuração própria de Apenas leitura ou Escrita no espaço de trabalho, aplicada pela política de arquivos do DSH e pelo limite canônico do espaço de trabalho da ponte. O compositor mostra esse escopo. As configurações são salvas como eventos nativos da sessão e sobrevivem a reinicializações; alterações são recusadas enquanto um turno está ativo.

Uma solicitação nativa de elevação aparece em um cartão Permitir uma vez / Recusar associado à operação. A aprovação vale apenas para essa solicitação e não altera o modo de permissão permanente. Solicitações expiradas ou canceladas não podem ser aprovadas, e chamadas de Chat sem interface rejeitam perguntas que não conseguem exibir. A ponte não oferece acesso irrestrito ao host.

Os endpoints administrativos adicionais são:

MétodoCaminhoFinalidade
GET/api/cordis/modelsModelos de provedor disponíveis e o modelo real padrão atual
PATCH/api/cordis/sessions/:id/settingsDefinir o modelo e/ou modo de permissão desta sessão
POST/api/cordis/sessions/:id/approvals/:approvalIdDecidir uma solicitação pendente com allowed-once ou rejected

Uso do mecanismo no Chat

Ative Acesso e políticas → Modelos de agentes CLI e Motor Cordis. Administradores poderão selecionar DeepSeek Harness no Chat. Cada solicitação recebe uma nova sessão transitória do mecanismo com o histórico fornecido por aquela solicitação. O banco normal do Chat continua sendo a fonte autoritativa; conversas distintas, ramificações e novas tentativas não compartilham um histórico invisível do mecanismo. O log transitório é removido após a conclusão ou o cancelamento e não aparece na página do mecanismo.

A composição padrão também lista opções DeepSeek Harness · modelo (provedor) no grupo Agentes. Seus IDs salvos encapsulam a mesma rota qualificada usada pela página do mecanismo: dsh:lwui:ollama:<model> ou dsh:lwui:plugin:<plugin>:<model>, com cada componente do provedor codificado por porcentagem. A conexão local opcional com DSH nativo acrescenta opções dsh:native:<provider>:<model> do catálogo ao vivo dessa instância, reutilizando as configurações e credenciais do provedor nativo. Instale o pacote independente Apache-2.0 de libre-webui/dsh-native-provider ou prepare um bundle pela distribuição do Libre WebUI. Ambos usam o nome @libre-webui/dsh-native-provider e mantêm as chaves no DSH nativo. A conexão usa um socket Unix privado no mesmo host e na mesma conta do sistema; não isola aplicações que compartilham essa conta. Ela oferece apenas inferência, sem sessões de agentes ou execução de ferramentas nativas. Consulte o guia de configuração para instalação, reinicialização do perfil, atualização e remoção. A ausência da conexão ou do modelo selecionado causa falha sem mudar de provedor. Chamadas nativas também aparecem em Uso de Fornecedores, com modelo selecionado, tokens informados, latência e resultado. O perfil básico dsh mantém o modelo padrão da composição em execução. Composições com adaptadores personalizados expõem esse perfil básico sem anunciar substituições de provedor do Libre WebUI que não suportam.

Títulos e resumos de raciocínio resolvem a seleção DSH para seu provedor subjacente e fazem uma solicitação direta de texto, sem ferramentas ou sessão de agente. Uma solicitação ao perfil básico lê os padrões do mecanismo em execução, incluindo substituições da entrada da ponte, em vez de deduzi-los do catálogo atual. Adaptadores personalizados precisam de um modelo de tarefa Ollama ou de plugin configurado explicitamente para essas funções. Um provedor selecionado indisponível causa a falha normal ou a prévia local do título, sem enviar a solicitação a outro provedor.

A solicitação usa as configurações e credenciais do administrador autenticado. Nenhuma credencial de outro administrador é escolhida implicitamente. O espaço Cordis configurado continua sendo o padrão; o Chat não o substitui pelo diretório pessoal do usuário do servidor.

Work em sandbox

Com o Cordis ativado, o Work oferece um controle separado Motor, com opções Libre WebUI e DeepSeek Harness. O seletor mantém os nomes habituais dos modelos e as identidades dos provedores. Para provedores do LWUI, a seleção DSH é armazenada internamente como dsh:<model>. As escolhas nativas guardam providerType: dsh, o ID exato do provedor nativo e o ID original do modelo. As verificações normais de capacidade de ferramentas e acesso continuam valendo; credenciais nativas também exigem um administrador ativo.

Cada execução cria um ciclo de agente DSH isolado em memória. Seu adaptador recebe o histórico atual do Work, metadados do provedor, imagens e esquemas das ferramentas. Os corpos das ferramentas apenas aguardam os resultados devolvidos pelo Work; não podem ler arquivos nem iniciar processos no host.

O Work continua responsável por validar argumentos, solicitar aprovações, executar ferramentas no runtime do espaço de trabalho, registrar resultados e estado de reprodução do provedor em SQL, aplicar orçamentos e publicar eventos. Uma ferramenta recusada produz o resultado normal de recusa. O cancelamento descarta o DSH e segue a limpeza de contêineres já existente no Work. Após recuperar um worker, um novo driver DSH recebe o contexto restaurado do Work sem repetir efeitos de ferramentas já concluídos.

A integração Work não precisa da composição do mecanismo do host nem do armazenamento de sessões JSONL. Segue as regras atuais de runtime e implantação Docker/Kubernetes do Work, incluindo a persistência compartilhada exigida no modo team.

Limite de segurança

A página do mecanismo e o agente Chat no host são exclusivos de administradores. As sessões do mecanismo, incluindo seus prompts de sistema, formam um console administrativo compartilhado, não um espaço por usuário. Contas comuns não podem ler, criar, modificar ou cancelar essas sessões pela API.

As ferramentas de arquivos do host incluídas restringem leituras e gravações ao espaço configurado usando destinos canônicos, inclusive a resolução de links simbólicos. Substituições do diretório de trabalho da sessão devem permanecer dentro desse espaço. As políticas nativas de alteração do DSH e as aprovações únicas do mecanismo continuam valendo. Plugins de composição instalados pelo operador são código confiável do servidor e podem conceder capacidades adicionais. As aprovações do mecanismo são separadas do fluxo de aprovação e execução em contêiner do Work.

O driver DSH do Work é separado: não monta plugins de sistema de arquivos, shell ou persistência do host e só executa por meio da autorização e do sandbox existentes no Work. Provedores remotos continuam sendo opcionais e usam a rota de provedor configurada para a conta selecionada.