Pular para o conteúdo
miblo

SDK

Sessões, avisos e status: a API de status do Miblo

Cada método da API de status do Miblo: session, needsYou, done, say, focus, timer e snapshot, com parâmetros, respostas, erros e um exemplo completo.

O cliente

Tudo começa com um MibloStatus. Ele guarda o token e a porta e assina cada pedido; não abre conexão até o primeiro uso.

import { MibloStatus } from '@miblo/status';

const miblo = new MibloStatus({ token, port, timeoutMs });   // todos opcionais
ParâmetroPadrãoO que é
tokenMIBLO_TOKENO token de miblo sdk token. Sem ele, o construtor já lança no_token.
portMIBLO_PORT, senão 47821A porta da ponte. O endereço é sempre 127.0.0.1.
timeoutMs / timeout3000 ms / 3.0 sQuanto esperar cada resposta.

hello()

Confere o token e a versão do Miblo, sem mudar nada: { api, version } (por exemplo { api: 1, version: "1.25.0" }). Útil para checar a instalação no início do programa.

const { api, version } = await miblo.hello();

Como cada pedido é assinado

Você não precisa fazer nada disso, os pacotes fazem: antes de cada pedido o cliente pede um desafio (GET /sdk/v1/hello com um nonce aleatório), confere que a ponte provou conhecer o token, assina o pedido com HMAC-SHA256 (método, caminho e o SHA-256 do corpo) e, na volta, confere a assinatura da resposta. Um programa que ocupe a porta do Miblo enquanto ele está fora não consegue provar o token, e o cliente não manda nada a ele. O passo a passo está na referência.

Sessões

Uma sessão é o seu programa na lista do Miblo, ao lado das sessões das ferramentas de IA.

session()

const job = await miblo.session({ tool, title, cwd, state, detail, pid });
CampoObrigatórioRegras
toolsimO nome do seu programa, 1 a 20 caracteres, uma linha. Não pode ser o nome de uma ferramenta do Claude Code (Bash, Edit, Read, Task, Agent...) nem começar com _.
titlenãoO nome da sessão no aparelho (até 64 caracteres; o aparelho mostra cerca de 20). Sem ele, vale a pasta de cwd; sem os dois, o tool. Nomes repetidos ganham " 2", " 3".
cwdnãoUma pasta; o nome dela vira o título quando não há title.
statenãoworking (padrão), needs_you, idle ou done.
detailnãoUma linha curta (até 64 caracteres; o que passar é cortado). É a atividade enquanto trabalha e o motivo quando precisa de você.
pidnãoO processo cujo fim encerra a sessão. Padrão: o próprio programa. null (TS) ou None (Python): nenhum, e a sessão expira após 12 h sem atualização (2 h quando parada ou concluída).

Devolve um objeto Session com id (sdk- + 32 hexadecimais, criado pela ponte) e state. Só ids sdk- são aceitos depois, então um programa nunca consegue mudar ou encerrar a sessão de uma ferramenta de IA.

Mudar o estado

TypeScriptPythonEstadoNo aparelho
job.working(detail?)job.working(detail=None)workingA linha mostra tool · detail.
job.needsYou(reason?)job.needs_you(reason=None)needs_youAviso de pergunta, uma vez por mudança; conta em "precisa de você".
job.idle(detail?)job.idle(detail=None)idleParada, sem aviso.
job.done(detail?)job.done(detail=None)doneAviso de fim, uma vez por mudança.
job.set(state, detail?)job.set(state, detail=None)qualquer umO mesmo, escolhendo o estado.
job.end()job.end()(sai)Tira a sessão do Miblo: { id, ended: true }.

Cada chamada devolve { id, state }. Os modos reunião e discreto escondem o detail, como fazem com toda sessão. As sessões sobrevivem a uma atualização da ponte, mas não a um reinício do computador.

Mensagens, foco e timer

As mesmas ações de miblo say, miblo focus e miblo timer, com os mesmos limites do aparelho.

TypeScriptPythonRegras
say(text, { minutes })say(text, minutes=None)Uma linha, até 40 caracteres (47 bytes UTF-8), por 1 a 480 minutos (padrão 30). Não pode começar como os avisos do próprio Miblo ("Approved:", "Phone:", "Miblo:", "Allow?"... em inglês e português).
sayOff()say_off()Tira a mensagem.
focus({ focusMin, breakMin, rounds })focus(focus_min=None, break_min=None, rounds=None)Foco de 5 a 120 min, pausa de 1 a 60, 1 a 12 rodadas.
focusStop()focus_stop()Para o foco.
timer(minutes)timer(minutes)1 a 180 minutos.
timerStop()timer_stop()Para o timer.

Cada uma devolve { ok, delivered, gadgets }: delivered conta os aparelhos que aceitaram, e gadgets traz cada aparelho pareado com { id, name, ok, error? }, onde error é offline, unpaired, unsupported, rejected ou busy. Sem Miblo pareado, delivered é 0 e não é erro. Nada disso vira notificação no computador.

Snapshot

snapshot() lê quem está trabalhando e quem precisa de você, sem mudar nada.

const { sessions, gadgets } = await miblo.snapshot();
const waiting = sessions.filter((s) => s.state === 'needs_you');
  • sessions: [{ id, name, state, tool, sdk, since }]. Uma sessão de ferramenta de IA aparece com um id de 8 caracteres e o nome da ferramenta em tool ("Claude Code", "Codex"...); sdk é true nas sessões de programas; since é o momento (epoch, em segundos) em que entrou no estado.

  • gadgets: [{ id, name, online }].

  • Nunca traz um comando, um arquivo, um prompt, um custo, um limite ou nada do Miblo+. Leituras: 5 por segundo, em rajadas de 10.

Exemplo completo

Um vigia de build: roda o comando, mostra o andamento, avisa quando falha e põe uma mensagem quando passa.

// MIBLO_TOKEN=$(miblo sdk token) node build-watch.mjs
import { spawn } from 'node:child_process';
import { MibloStatus, MibloError } from '@miblo/status';

const miblo = new MibloStatus();
const job = await miblo.session({ tool: 'build', title: 'Build do site', detail: 'npm run build' });

const code = await new Promise((resolve) => {
  spawn('npm', ['run', 'build'], { stdio: 'inherit' }).on('exit', resolve);
});

try {
  if (code === 0) {
    await job.done('passou');
    await miblo.say('Build verde', { minutes: 10 });
  } else {
    await job.needsYou(`falhou (saída ${code})`);
  }
} catch (e) {
  if (e instanceof MibloError && e.code === 'rate_limited') console.log(`tente em ${e.retryAfter} s`);
  else throw e;
}

Erros

Todo erro é um MibloError com:

  • code: estável, nunca renomeado (lista abaixo);

  • status: o status HTTP, ou 0 quando a ponte não foi alcançada;

  • field (em bad_request): o campo com problema, como tool ou detail;

  • retryAfter (TS) / retry_after (Python) em rate_limited: quantos segundos esperar.

codeStatusQuando
bad_request400Um campo fora da faixa ou do tipo errado (veja field)
bad_json400O corpo não é JSON
sdk_off401Sem token neste computador
not_authorised401Token errado ou trocado
unknown_session404A sessão terminou, expirou ou não é do SDK
too_many_sessions409Já há 8 sessões do SDK
too_large413Corpo acima de 4096 bytes (o cliente recusa antes de mandar)
rate_limited429Acima de um limite; espere retryAfter segundos
internal500Um bug do Miblo: conte para a gente

Do lado do cliente: no_token, bridge_unavailable, timeout e unverified_answer (veja Instalação).

Chamadas de baixo nível

call(method, path, body?, opts?) faz um pedido assinado a qualquer rota /sdk/v1/* e devolve o JSON da resposta (lança MibloError em erro). Um Uint8Array (TS) ou bytes (Python) vai como application/octet-stream. Serve para rotas novas antes de o pacote ter um método para elas.

const screen = await miblo.call('GET', '/sdk/v1/screen', undefined, { tool: 'build' });