Estado atual

Verificado em 10 de outubro de 2026 compilando, testando e rodando cada parte. Onde diz "pendente", é porque ainda não foi feito, não porque está planejado para "em breve".

ComponenteEstado
Choir Code (extensão VS Code)Publicada na Marketplace (0.4.0). Funciona no Linux. Windows e macOS dependem da próxima release de binários.
agichoir-node (runtime)Binários Linux (generic, AVX, AVX2) em github.com/agichoir/models. Zero avisos de compilação. 31 testes no node, 56 no core.
Choir Node (desktop, Tauri)Compila; build local por enquanto. Painel de rede com PeerId, endereços, conectar, peers com latência e desconectar.
Choir AI (mobile, Flutter)APK roda em Android; não publicado. Produto separado: assistente offline, sem rede.
Rede P2PValidada com três nós na mesma máquina (seed + dois clientes, sem mDNS). Travessia de NAT real depende de um seed em IP público.
Consenso verificadoValidado entre duas identidades distintas pela rede: saída idêntica, duas assinaturas válidas.
SiteNo ar, PT/EN/ES.

Instalar

Extensão (VS Code)

Procure "Choir Code" na Marketplace. Na primeira ativação a extensão baixa o runtime certo para a sua CPU e o modelo Canary v1 (0,5B, cerca de 490 MB) de github.com/agichoir/models. Nada sai da máquina além desses downloads. Se já houver um Choir Node rodando na porta 5001, a extensão usa ele.

Runtime pela linha de comando (Linux)

curl -L -o agichoir-node https://github.com/agichoir/models/releases/latest/download/agichoir-node-linux-avx2 chmod +x agichoir-node mkdir -p ~/.agichoir/models curl -L -o ~/.agichoir/models/canary-v1-0.5b-q4.gguf https://github.com/agichoir/models/releases/download/v1/canary-v1-0.5b-q4.gguf ./agichoir-node --worker --port 4001 # API: http://localhost:5001

Variantes: generic roda em qualquer x86-64 desde 2003; avx em Intel 2011+ e AMD Bulldozer+; avx2 em Intel 2013+ e AMD Zen+. Escolher errado dá "illegal instruction" na primeira inferência; a extensão detecta sozinha.

Desktop e mobile

Ainda sem instalador publicado. Veja Build.

Arquitetura

Um core em Rust e três superfícies que falam com ele por HTTP local.

ParteO que éTecnologia
agichoir-coreBiblioteca pura: criptografia, identidade, DAG, reputação, sandbox de execução, gestão de contexto, armazenamentoRust, Ed25519, sled
agichoir-nodeO runtime: inferência nativa, rede P2P, coordenação do consenso, API HTTPllama.cpp (via llama-cpp-2), libp2p 0.54, axum
Choir CodeExtensão: chat, completions inline, ações no editor, controle do nóTypeScript, VS Code API
Choir NodeApp desktop: inicia o runtime, chat, painel de rede, modo EcoTauri v2
Choir AIAssistente offline para Android (produto à parte)Flutter + Rust

Modelo: canary-v1-0.5b-q4.gguf, um Qwen2.5-Coder 0.5B quantizado. A personalidade (lore) fica em ~/.agichoir/lore.json, separada do modelo. Threads de inferência: núcleos físicos por padrão; em CPUs com hyperthreading isso foi a diferença entre 26 segundos e mais de cinco minutos para gerar 150 tokens.

Uma pergunta, passo a passo

Nada disso bloqueia o chat. O desenho anterior esperava 5 segundos pelo consenso e devolvia "local" em qualquer CPU modesta; o atual devolve a resposta e atualiza depois.

Rede P2P

MecanismoPapelEstado
Identidade libp2p persistentePeerId estável entre reinícios (~/.agichoir/p2p_key)Feito
Seeds (AGICHOIR_SEEDS)Ponto de entrada: DHT em modo servidor, relay e AutoNAT. Todo node disca os seeds ao iniciarCódigo feito; nenhum seed público no ar
Reserva de relay + DCUtRNós atrás de NAT ficam alcançáveis por <seed>/p2p-circuit/p2p/<id>; o hole punching tenta promover para conexão diretaValidado localmente
Anúncio com endereçosA cada 30 s (primeiro aos 5 s) cada node publica modelos e endereços discáveis; quem recebe adiciona à DHT e discaFeito
mDNSDescoberta na mesma rede localFeito
DHT pública do IPFSDescoberta global de último recurso; os relays públicos não aceitaram reserva nos testesNão confiável

Como subir um seed: um node com --seed --no-mdns numa máquina com a porta 4001 aberta. O endereço dele (/ip4/<ip>/tcp/4001/p2p/<id>) entra em AGICHOIR_SEEDS dos clientes ou na lista embutida do binário. Uma VPS de 1 GB basta; o seed não carrega modelo.

Consenso

CamadaComparaPode marcar "verificado"
ByteSaídas idênticas após normalizar espaços e quebras de linhaSim
ExecuçãoMesmo stdout rodando o código num sandbox (Linux com namespaces; desligada fora dele)Sim
SemânticaCosseno entre embeddings do próprio modelo (limiar 0,65)Não: aparece como "semelhante na forma"

Por que a semântica não verifica. Na calibração do relatório 025, "2+2 = 4" e "2+2 = 5" pontuaram 0,999. Similaridade reconhece paráfrases e separa assuntos, mas não enxerga contradição. Então "verificado" exige byte ou execução, mais assinaturas válidas em quórum.

Assinaturas. Cada resposta vem com a chave pública do respondente e uma assinatura Ed25519 sobre hash(saída | task_id). O requester verifica cada uma; resposta sem assinatura válida é descartada. "Provado" significa assinado por N nós distintos.

Reputação. Cada respondente é creditado pelo seu node_id conforme concordou ou não com a camada vencedora. O próprio nó não alimenta a própria tabela. Tudo fica em ~/.agichoir/reputation.json e cada rodada vai para audit/consensus_log.jsonl.

API HTTP

O node escuta em 0.0.0.0:<porta P2P + 1000>, normalmente 5001. Conexões vindas do loopback não precisam de chave. Qualquer outra origem precisa de Authorization: Bearer <conteúdo de ~/.agichoir/api_key>. A decisão é pelo endereço real do socket; o cabeçalho Host não conta.

RotaO que faz
POST /api/chatChat (formato Ollama: model, messages, stream). Resposta em NDJSON; a linha final traz consensus com method, agreed, total, verified, task_id.
POST /api/generateGeração crua (prompt, raw para FIM). Consenso síncrono quando há peers.
GET /api/consensus/:task_idstatus: done com o resultado, pending ou unknown.
GET /api/statuspeer_id, addrs discáveis, peers, inference_peers, relays, last_consensus, consensus_pending, modelo e contexto.
GET /api/peersPeers conectados: peer_id, rtt_ms, relayed, has_model, addr.
POST /api/connect{"addr": "/ip4/…/tcp/4001/p2p/…"}: disca um peer e o guarda em known_peers.
POST /api/disconnect{"peer_id": "…"}: derruba a conexão.
GET/POST /api/node-configModo Standard/Eco, max_threads (aplicado ao engine na hora e no boot), limites.
GET /api/tagsLista de modelos no formato Ollama (compatibilidade).
GET /api/binary, POST /api/publish-manifestDistribuição de binários entre peers com manifests assinados.

Flags e variáveis

Flag / variávelEfeito
--worker --port NModo normal: P2P na porta N, API em N+1000.
--seedSeed público: relay server, DHT em modo servidor, sem modelo.
--seeds a,b / AGICHOIR_SEEDSSeeds extras (multiaddr com /p2p/<id>).
--no-mdnsSem descoberta de LAN (vários nós na mesma máquina, VPS).
--endpoint URLDelegar inferência a outro node por HTTP (modo legado).
AGICHOIR_P2P_KEYCaminho da chave libp2p (padrão ~/.agichoir/p2p_key).
AGICHOIR_THREADSThreads de inferência (padrão: núcleos físicos, máximo 16).
AGICHOIR_GPU_LAYERSCamadas na GPU; só tem efeito em binários compilados com --features vulkan ou metal.
AGICHOIR_TARGET_FEATURESNa compilação: instruções SIMD do llama.cpp (ver ADR-007).
HOMETudo fica em $HOME/.agichoir: modelos, identidade, chave P2P, peers conhecidos, configuração, reputação.

Build

Rust 1.90, CMake e um compilador C++. O primeiro build compila o llama.cpp e leva cerca de 10 minutos.

# core cd src/agichoir-core && cargo test # runtime (CPU, igual ao que a CI publica) cd src/agichoir-node && cargo build --release # GPU: --features vulkan (Linux/Windows, exige Vulkan SDK) ou --features metal (macOS) # CPUs sem AVX2: aplicar o patch de SIMD antes do primeiro build (ADR-007) bash patches/fix-llama-simd.sh && cargo clean --release -p llama-cpp-sys-2 AGICHOIR_TARGET_FEATURES="fxsr,sse,sse2,sse3,sse4.1,sse4.2,ssse3,avx" cargo build --release # desktop cd src/agichoir-desktop/src-tauri && cargo tauri dev # extensão cd src/agichoir-coder && npm install && npm run compile # scripts de integração (não são testes): P2P, DHT, NAT, DAG, calibração de embeddings cargo run --release --example embed_calibration

Três nós na mesma máquina para testar a rede: um HOME por processo, chaves separadas, --no-mdns, portas 4010 a 4012, o primeiro com --seed e os outros com AGICHOIR_SEEDS apontando para ele.

Decisões registradas

Cada mudança de rumo tem um ADR. Os relatórios de pesquisa, com números, estão na página Pesquisa.

ADRDecisão
001Terminologia: Choir Code, Choir Node, Canary.
002Modelo dual-token. Substituído pelo 008.
003Choir Node como runtime desktop autocontido.
004Nó mobile como edge, não como nó inferior.
005Consenso visível na interface.
006Página inicial e comunicação visual.
007Build do llama.cpp com SIMD controlado: sem isso, SIGILL em CPUs sem AVX2.
008Open Access: sem créditos, sem tokens, sem escassez artificial.
009"Verificado" exige byte ou execução; semântica é "semelhante na forma".
010Consenso pela rede P2P, assíncrono, com assinaturas verificadas; autenticação pelo socket.

Relatórios de pesquisa mais recentes: 020 runtime multi-binário, 021 Canário v1 e consenso entre sub-redes, 022 desempenho de inferência, 023 build Windows, 024 open access, 025 consenso semântico com embeddings reais e seus limites.

Limites conhecidos