Pular para o conteúdo principal

Visão Geral da Arquitetura

O AISCouncil é uma plataforma de gerenciamento de bots sem hospedagem que roda inteiramente no navegador. A saída de produção é um único arquivo index.html (~980 KB) montado a partir de 80 arquivos fonte modulares. Não há dependências de tempo de execução externas — apenas JavaScript e WASM são enviados ao navegador.

Arquitetura de Arquivo Único

O aplicativo é um único arquivo HTML autocontido. Durante o desenvolvimento, ele é dividido em partes em src/ para janelas de contexto menores e edição focada. O script build.sh concatena todas as 80 partes de volta em index.html em uma ordem estrita.

src/shell-head.html        \
src/shell-style.html |
src/shell-body.html |
src/core-boot.js |
src/core-auth-main.js | build.sh
... | ---------> index.html (~980 KB)
src/settings-main.js |
src/miniprograms.js |
src/pwa.js |
src/shell-bottom.js /
aviso

Nunca edite index.html diretamente. Sempre edite o arquivo correspondente em src/, depois execute ./build.sh para remontar.

Namespace Global

Todos os módulos são registrados no namespace global window.AIS. O namespace é inicializado em src/core-boot.js:

window.AIS = { version: "2.0.0", type: "aiscouncil" };
AIS.PLATFORM_VERSION = "1.0.0";
AIS.ABI_VERSION = 1;

A comunicação entre módulos usa um barramento de eventos leve:

AIS.on("event", handler); // subscribe
AIS.off("event", handler); // unsubscribe
AIS.emit("event", data); // publish

Sistema de Módulos: AIS.lazy()

Os módulos usam um padrão de hidratação preguiçosa no estilo Qwik. A função de fábrica é adiada até que o módulo seja acessado pela primeira vez via um getter de propriedade em AIS:

if (!AIS.Council)
AIS.lazy("Council", function () {
"use strict";
// código do módulo aqui
return { run, renderCouncilMessage, estimateCost };
});

No primeiro acesso (ex: AIS.Council.run()), o getter dispara, executa a fábrica, substitui a si mesmo pelo objeto de módulo retornado e o retorna. Acessos subsequentes atingem o valor simples sem sobrecarga.

Módulos de kernel WASM ainda podem substituir um módulo JS definindo AIS.Council = wasmModule antes do primeiro acesso, porque a propriedade é definida como configurable: true.

Categorias de Módulos

Módulos Principais (sempre carregados)

Os módulos principais são definidos dentro de um único bloco <script> (core-boot.js até core-end.js). Eles executam avidamente no carregamento da página e formam a base do aplicativo.

MóduloArquivoPropósito
AIS.Authcore-auth-main.js, core-auth-local.js, core-auth-init.jsLogin WebAuthn/Passkey + OAuth, gerenciamento de sessão, cookie de autenticação
AIS.Billingcore-billing.jsNível de assinatura, trial, plano gerenciado
AIS.Codeccore-codec.jsCodificação Base80, versionamento VLQ, compressão deflate
AIS.Storagecore-storage.jsIndexedDB + SQLite WASM opcional, offline-first
AIS.Providerscore-providers.js, core-providers-builtin.jsRegistro de provedores LLM, fábrica de streaming SSE
AIS.UIcore-ui.jsUtilitários DOM, renderizador markdown, notificações toast
AIS.Sessioncore-session.jsCRUD de sessão de bot (backed por IndexedDB)
AIS.Chatcore-chat.jsHistórico de chat, envio/recebimento de mensagens em streaming
AIS.Configcore-config.jsBindings do painel de configuração do bot, sincronização URL
AIS.Appcore-app-botlist.js, core-app-switch.js, core-app-events.js, core-app-search.js, core-app-init.jsControlador da aplicação, init, roteamento, gerenciamento de bots

Módulos Substituíveis por WASM (carregados preguiçosamente)

Cada módulo substituível por WASM reside em seu próprio bloco <script> e usa o padrão AIS.lazy(). Eles só executam quando acessados pela primeira vez.

MóduloArquivoPropósito
AIS.Registryregistry.jsRegistro de modelos da comunidade, cache 24h, fallback GitHub
AIS.Gridgrid.jsRenderizador de tabela/card de modelos (compilado de TypeScript)
AIS.Councilcouncil.jsMotor de deliberação multi-modelo (7 estilos)
AIS.Wizardwizard.jsWizard de configuração inicial de modo duplo
AIS.Visionvision.jsEntrada de imagem para modelos de visão (colar/upload)
AIS.Memorymemory.jsMemória chave-valor persistente por bot
AIS.ImageGenimagegen.jsGeração de imagens (DALL-E, Grok Imagine, OpenRouter)
AIS.Toolstools.jsNormalização de formato de chamada de ferramenta/função
AIS.Remindersreminders.jsMensagens agendadas via comando /remind
AIS.Themesthemes.jsSistema de temas visuais
AIS.Templatestemplates-registry.jsTemplates de prompt de sistema, telas de boas-vindas
AIS.ModelPickermodel-picker.jsNavegador de modelos ordenável

Módulos de Infraestrutura (carregados preguiçosamente)

MóduloArquivoPropósito
AIS.ModuleLoadermoduleloader.jsCiclo de vida de módulo hot-swap, cache OPFS
AIS.Pluginsplugins.jsSistema de plugins: validação de manifest, hooks
AIS.MCPmcp.jsModel Context Protocol (ferramentas + recursos)
AIS.Channelschannels-core.js, channels-whatsapp.js, channels-adapters.js, channels-stubs.jsAdaptadores de canal (Telegram, Discord, Matrix, Slack, WhatsApp)
AIS.Sandboxsandbox.jsSandbox de ferramentas WASM (Pyodide, QuickJS, SQLite)
AIS.Publishpublish.jsPublicação SEO + HTML estático
AIS.Perfperf.jsMonitoramento de performance
AIS.P2Pp2p.jsColaboração P2P via WebRTC + CRDTs

Módulos de Plataforma

MóduloArquivoPropósito
AIS.Settingssettings-main.jsDiálogo de configurações globais (todas as seções)
AIS.I18ni18n.jsInternacionalização
AIS.MiniProgramsminiprograms.jsRuntime de mini-programas (iframes sandboxed)
AIS.Docsdocs.jsVisualizador de docs inline
AIS.Profilesprofiles.jsTemplates de perfil/council multi-modelo
AIS.Croncron.jsAgendador baseado em navegador

Arquitetura CSS

O aplicativo usa uma abordagem CSS sem classes. Os estilos targetizam elementos HTML semânticos e IDs em vez de classes.

Tipo de SeletorExemploCaso de Uso
ID#header, #sidebar-left, #config-bodyContainers de layout únicos
Elemento semântico#messages > article, article menu buttonMensagens, ações, navegação
Atributo de dados[data-from="user"], [data-variant="primary"]Variantes (role da mensagem, tipo de botão)
Classe de estado.active, .collapsed, .mobile-openEstados alternados por JS
Classe de componente.council-member-row, .status-dotComponentes JS dinâmicos
Classe utilitária.f1, .sc, .dimSubstituição de estilo inline ocasional

Elementos HTML semânticos usados: <header>, <main>, <aside>, <section>, <footer>, <nav>, <article>, <menu>, <details>, <dialog>, <output>.

informação

Classes são usadas apenas para três casos: alternância de estados (.active, .collapsed), componentes JS dinâmicos (.council-member-row), e atalhos utilitários (.f1, .sc). Se você pode targetizar um elemento com um seletor semântico ou atributo de dados, faça isso em vez de adicionar uma classe.

Arquitetura de Armazenamento

O armazenamento é dividido entre stores síncronos e assíncronos:

ArmazenamentoChavesRazão
localStorage (sync)ais-theme, ais-apikey-*, ais-user, ais-ollama-endpointLeituras síncronas necessárias no boot
IndexedDB (async, ilimitado)ais-bots, ais-chat-*, ais-addon-manifestsDados grandes, sem limite de 5 MB
SQLite WASM (opcional, OPFS)Blobs bináriosCarregado preguiçosamente para acesso concorrente

No primeiro boot, AIS.Storage.init() migra automaticamente dados do localStorage para IndexedDB.

Arquitetura de Provedores

Provedores são registrados via AIS.Providers.register(). A maioria dos provedores usa a fábrica de streaming SSE compartilhada openaiCompatible(), que lida com:

  • Parsing de Server-Sent Events
  • Callbacks de streaming token por token
  • Suporte a sinal AbortController
  • Contagem de tokens dos cabeçalhos de resposta

Seis provedores integrados são registrados em core-providers-builtin.js:

ProvedorEstilo de APIAuthNotas
AnthropicNativo (Messages API)header x-api-keyFormato de streaming customizado
OpenAIOpenAI-compatibleBearer tokenSSE padrão
xAIOpenAI-compatibleBearer tokenModelos Grok
Google GeminiNativo (Gemini API)param query ?key=Evita preflight CORS
OpenRouterOpenAI-compatibleBearer token300+ modelos, nível gratuito
OllamaOpenAI-compatibleNenhumLLMs locais, auto-detecta modelos

Todas as chaves de API são armazenadas localmente (localStorage['ais-apikey-{provider}']). As chaves são enviadas diretamente do navegador para o provedor — nunca passadas por proxy através de nenhum servidor.

Princípios de Design

A base de código segue princípios de design estritos que toda mudança deve satisfazer:

  1. HTML5 nativo primeiro -- Use <dialog>, <output>, atributo hidden, animações CSS antes de equivalentes JS.
  2. Zero polling -- Sem loops requestAnimationFrame, sem setInterval, sem setTimeout para animação. Somente orientado a eventos.
  3. Listeners passivos -- Todos os eventos não canceláveis usam { passive: true }.
  4. Delegação de eventos -- Listener único no container, não listeners por item em listas dinâmicas.
  5. Fonte mínima de 14px -- Todo texto deve ser legível por LLMs de visão. Sem texto abaixo de 14px.
  6. Layout amigável a VLM -- Alvos de clique 48px+, toggles grandes, alto contraste. Configurações e menus exibem todos os itens principais sem scroll em 1920x1080.
  7. Movimento reduzido -- @media (prefers-reduced-motion: reduce) desabilita todas as animações.
  8. Contenção CSS -- contain: strict em sidebars, content-visibility: auto em listas scrolláveis.
dica

Antes de adicionar qualquer funcionalidade, faça as quatro perguntas de portão de decisão:

  1. O navegador pode fazer isso nativamente?
  2. Isso requer um servidor? (Se sim, torne opcional.)
  3. Isso escala para 1 milhão de bots por dispositivo?
  4. Quais são os custos de memória e CPU?

Kernel WASM

O kernel WASM opcional (kernel/) é escrito em Zig e compila para ~5.5 KB. Ele fornece primitivas de baixo nível para o sistema de módulos: gerenciamento de slots, dispatch de hooks, I/O de ring buffer, e write-ahead logging.

O kernel opera em um SharedArrayBuffer de 64 MB com regiões de memória definidas para segmentos de módulo, ring buffers, WAL, e arena scratch. Módulos JS podem ser substituídos por equivalentes WASM em tempo de execução sem quebrar o contrato de carregamento preguiçoso.

Arquitetura de API

A plataforma usa Workers separados para diferentes preocupações:

WorkerDomínioPropósito
aiscouncil-apiapi.aiscouncil.netBilling, uso, distribuição de chaves, geo
aiscouncil-authauth.aiscouncil.netCallbacks OAuth, verificação de token

URLs base da API são definidas no boot a partir de detecção de domínio e podem ser sobrescritas via localStorage['ais-api-base'] para desenvolvimento local.