Русский · English · Español · 中文 · Português
«Espaço Agora» — API do agente
Esta página é para agentes de IA (e para as pessoas que os usam). Ela explica como um agente se conecta a uma página «Espaço Agora» ativa (known.html) no navegador de uma pessoa e o que ele pode fazer ali: tudo o que a interface faz — abrir qualquer objeto, mover a câmera, avançar o tempo, alternar camadas e filtros, modo astronauta, encontrar eclipses e desfiles de planetas, contar um roteiro com voz e legendas, exibir imagens próprias, gravar vídeo, ler erros. A renderização acontece no navegador da pessoa (WebGL na GPU dela); o agente envia comandos e recebe respostas e capturas de tela.
1. Pareamento
- A pessoa abre o site e pressiona o botão redondo 🤖 (canto inferior direito, acima do astronauta) — a barra do agente se abre; «Ligar o agente» mostra um código (20 caracteres, ex.:
r4fxjbjsxdy6ex3pf4hd). O código é a senha: quem o tem controla esta aba. 🤖 apenas oculta/mostra a barra, a conexão permanece; «Desconectar» na barra a desliga. A barra sempre tem 📂 (abrir um arquivo de roteiro ou salvar o exibido — também sem agente) e «MCP ↗» (esta página). - A pessoa entrega o código ao agente. O agente chama
connectcom ele. - Conexão permanente (opcional): na página — 📌 «Lembrar» na barra do agente (o código fica neste navegador, o site se conecta sozinho toda vez que abre); o agente —
connectcomsave: true(código em~/.orbit-agent.json, o MCP conecta ao iniciar). Depois disso, basta abrir o site. Para esquecer: desafixe 📌 e chameforget. - «Desconectar» na página (ou a saída do agente) encerra a sessão; a página então devolve camadas e interface ao estado anterior
ao agente, para a música, a voz, as legendas, as imagens e os cenários, e remove locais de pouso (
sites), desenhos e marcas (draw,mark,flybys), janelas de mídia e corpos próprios (spawn) — independentemente deonstop. A câmera, o tempo e a seleção também voltam (por padrão;onstop {restore: false}— manter o que o agente mostrou). Exceção:play/story runcomdetach: true— a apresentação toca até o fim e só então é revertida.
O som (voz, música) só começa depois que a pessoa clicou na página ao menos uma vez — regra do navegador. A voz vem desligada por padrão: a pessoa a liga com 🔊 na barra do agente (fica lembrado); as legendas são sempre exibidas.
Checklist da apresentação — faça sempre
[
{"cmd":"onstop","args":{"restore":true}}, // primeiro passo: ao terminar, com Esc ou ✕ tudo volta
{"cmd":"reset"},
{"cmd":"view","args":{"on":["oplanets"]}}, // só as camadas necessárias: satélites, naves, órbitas, constelações desligados
{"cmd":"hideUi","args":{"on":true,"labels":false}},
{"cmd":"time","args":{"at":"<moment>","rate":0}}, // defina o tempo você mesmo; rate 0 — a iluminação não se desloca
… voo (fly) …
… a apresentação …
]
- Não confie nos padrões: defina camadas, tempo, câmera e interface explicitamente.
- Uma vista definida com
view(ou o campoonde um roteiro) é mantida porshow(keepView: false— as camadas do evento).fly,camera,sites,timenão mexem nas camadas;galaxy,sceneeambientdefinem a própria vista — chameviewde novo depois deles, se necessário. - Depois da apresentação a cena deve ficar como antes:
onstop {restore: true}mais a remoção das suas próprias coisas —sites {on: false},flybys {on: false},draw {clear: true},image {clear: true},media {close: true}. Quando o agente sai, elas são removidas de qualquer forma. - Confira o quadro com
screenshotantes de dizer à pessoa «olhe». - A
captionfica no canto inferior esquerdo: mantenhatitlecurto, ponha textos longos emsubetext. - Um passo com falha em
playvai paralogs(nível error), paraplaysem argumentos (lastError: {step, cmd, error}) e para o player como «⚠ passo N». Um comando desconhecido nos passos é um erro imediato, antes do início.
2. Transporte
Os dois lados se conectam a uma sala de retransmissão no mesmo site: wss://<site>/agent/<code>?r=agent (a página usa
?r=page). A sala encaminha mensagens entre os dois; nada é armazenado. Mensagens JSON:
agent → page { "id": 1, "cmd": "go", "args": { "search": "?o=Mars" } }
page → agent { "id": 1, "ok": true, "result": … } | { "id": 1, "ok": false, "error": "…" }
room → both { "sys": "peer", "on": true|false } (o outro lado entrou / saiu)
keepalive envie { "sys": "ping" } a cada 30 s, a sala responde { "sys": "pong" }
Uma conexão por papel (um novo agente com o mesmo código substitui o antigo, código de fechamento 4000 — não reconecte nesse caso).
Mensagens de até 4 MB. Sites: https://space.bl2.ru, https://space.bl2.net (o mesmo site, ru/en por padrão).
3. Servidor MCP
Servidor MCP pronto (stdio): scripts/agent-mcp.mjs no repositório orbit-proto (Node ≥ 20, dependência ws).
Cada comando abaixo é uma ferramenta de mesmo nome (hide_ui → comando da página hideUi), além de connect,
disconnect, help (esta página como texto; lang: en). Arquivos: image recebe path, record salva
em path, screenshot retorna uma imagem.
{ "mcpServers": { "orbit-space": { "command": "node", "args": ["scripts/agent-mcp.mjs"] } } }
Env: AGENT_SITE — site padrão, AGENT_CODE — conectar na inicialização.
Conexão sem o servidor MCP (agentes na nuvem)
- Muitos agentes rodam em sandboxes na nuvem cuja rede de saída é limitada a uma lista de permissões, então
wss://space.bl2.rupode ficar inacessível. Solução: abra o WebSocket de qualquer aba do navegador emspace.bl2.ru(esta página de ajuda, por exemplo) e envie os comandos de lá. Teste de conexão:{"sys":"ping"}→{"sys":"pong"}. - O agente sair =
playpara e a cena é revertida. Um agente com sessões curtas (as ferramentas de navegador permitem ~45 s por chamada) envia a apresentação comdetach: true—play {steps, detach: true}oustory {action: 'run', story, detach: true}— e retorna na hora: a página toca a apresentação sozinha e reverte (comonstop) quando ela termina. Semdetach, mantenha o socket aberto até o cenário terminar. - Dê a cada comando seu próprio timeout (digamos, 8 s): caso contrário, um comando sem resposta trava a chamada inteira.
// «iniciar e retornar» — do console de uma aba em space.bl2.ru (ou Node ≥ 22)
const code = '<code>', ws = new WebSocket(`wss://space.bl2.ru/agent/${code}?r=agent`);
let id = 0; const wait = new Map();
const cmd = (name, args = {}, ms = 8000) => new Promise((res, rej) => {
const i = ++id, t = setTimeout(() => (wait.delete(i), rej(new Error('timeout ' + name))), ms);
wait.set(i, (m) => (clearTimeout(t), m.ok ? res(m.result) : rej(new Error(m.error))));
ws.send(JSON.stringify({ id: i, cmd: name, args }));
});
ws.onmessage = (e) => { const m = JSON.parse(e.data); if (!m.sys) wait.get(m.id)?.(m), wait.delete(m.id); };
ws.onopen = async () => {
await cmd('onstop', { restore: true });
await cmd('play', { detach: true, onError: 'skip', steps: [
{ cmd: 'reset' },
{ cmd: 'view', args: { on: ['oplanets'] } },
{ cmd: 'hideUi', args: { on: true, labels: false } },
{ cmd: 'fly', args: { name: 'Saturn', size: 0.5, lit: true }, wait: 6500 },
{ cmd: 'caption', args: { title: 'Saturn', sub: '1,4 bilhão de km do Sol' }, wait: 8000 },
] });
ws.close(); // a apresentação continua sozinha e depois recoloca tudo no lugar
};
4. Comandos
Observação e estado
| cmd | args | o quê |
|---|---|---|
| state | tempo, rate, objeto selecionado, centro da vista, câmera (yaw, pitch, dist km, fov), estrela próxima, chaves das camadas visíveis, tamanho do canvas em px | |
| screenshot | width, quality, full | JPEG da cena 3D. full: true — a aba inteira com a interface (a pessoa autoriza a captura da aba uma vez, pelo «📷» na barra do agente) |
| body | name | para enquadramento: raio km, kind, parent, luas, ângulos da câmera, sunYaw/sunPitch (direção da câmera da qual o corpo fica totalmente iluminado), fov, distForSize {0.25, 0.5, 0.66, 0.8 → km}: distância em que o disco ocupa essa fração da altura da tela (= raio / tan(fov/2) / k) |
| where | name, at | posição em um instante: km e UA a partir do Sol e da Terra, AR/Dec a partir da Terra (J2000) |
| logs | level, last, clear | erros/avisos/informações do console da página (buffer circular de 300) |
| snapshot | estado completo (tempo, rate, câmera, centro, seleção, todas as caixas de camadas, interface oculta, link do astronauta) — guarde-o para reproduzir um bug | |
| restore | state | voltar a um snapshot |
Vista, câmera, tempo, camadas
| cmd | args | o quê |
|---|---|---|
| search | q, limit | busca na base de objetos como o campo de busca: corpos, luas, naves espaciais, nebulosas e galáxias (quando a camada delas está ligada), satélites da Terra (nome ou NORAD), asteroides (nome ou número; o catálogo carrega pela linha load-asteroids). Retorna linhas com n |
| open | n | abrir um resultado da busca: seleção, ficha, voo — como clicar na linha |
| go | search | abrir uma vista como um link de compartilhamento: ?o= corpo (Mars, Марс, ISS…), ?a= asteroide (número ou nome), ?s= satélite NORAD, ?g= galáxia, ?n= nebulosa, ?st= estrela de constelação; extras d= câmera km, v=yaw,pitch, t= tempo ISO |
| fly | name, size, lit, face, seconds | voo suave até um corpo (como um clique na árvore). size — fração da altura da tela para o corpo (0.66 — dois terços), lit: true — pelo lado iluminado; o enquadramento leva ~2,5 s a mais depois do voo (~6 s no total, use wait ≥ 6500). face: "spot" — Júpiter: o tempo retrocede até a Grande Mancha Vermelha estar no lado diurno |
| camera | yaw, pitch, dist, ms | câmera em torno do centro da vista (rad, km). ms > 0 — mover suavemente ao longo de ms. Exemplo «preencher 2/3 da tela, lado iluminado»: body → camera {yaw: sunYaw+0.4, pitch: sunPitch, dist: distForSize[0.66], ms: 3000} |
| time | at, rate, live, from, to | from, to, ms, ease — avanço suave de uma data a outra; at — segundos Unix ou instante ISO (a.C.: -000500-01-01), velocidade (1 real, 3600 = 1 h/s, negativa = para trás, 0 pausa), live: true |
| view | on, set, orbits | view — chaves padrão para cada alternância. Sem args — lista {key, on}; on: [...] — desliga tudo e liga só o listado; set: {key: true|false} — altera só estas; orbits: false — todas as linhas de órbita de uma vez. Chaves (cada grupo também tem <key>:orbits — suas linhas de órbita): oplanets — Sol, planetas e luas; odwarfs — planetas anões e os maiores asteroides; ohelio — heliopausa; oshock — choque de terminação; osandbox — corpos próprios (spawn); oknown-small — pequenos conhecidos (Apophis, Bennu…); ocomets — cometas; ointerstellar — objetos interestelares (1I, 2I, 3I); okuiper — cinturão de Kuiper; ooort — nuvem de Oort; a0…a9 — asteroides por tamanho (a0 — acima de 100 km); ocraft, ocraft-orbit, ocraft-l — naves em voo, em órbita de corpos, em pontos de Lagrange; s0…s30 — grupos de satélites da Terra, sats — todos de uma vez; ogalaxy — modelo da Via Láctea; ouniverse — galáxias; stars — estrelas de constelações com nomes; conlines — linhas das figuras de constelações (com stars; não listado em view {on} — sem linhas); galmarks — rótulos do centro galáctico e do ápice; galsun — «Sol — você está aqui»; scenelabels — rótulos só no que a cena precisa (labels {only}). Um único caminho interestelar: desligue ointerstellar:orbits, select {name: '3I/ATLAS'} — o caminho dele fica brilhante. Também: earth:ph|cities|seas|mountains|volcanoes, weather, aurora (aurora), sw (clima espacial), sk:0…6, sk:neb. Roteiros e slides aceitam um campo on (aplicado antes dos passos): liste só o necessário — novas camadas ligadas por padrão não aparecerão em roteiros antigos |
| layers | todos os grupos de camadas: key, name, visible, orbits, count | |
| layer | key, visible, orbits | alternar uma camada. Chaves: oplanets, odwarfs, ocomets, ocraft*, ogalaxy, ouniverse, a0…a9 asteroides por tamanho, s0… grupos de satélites… |
| galaxy | far | vista da Via Láctea (far — com outras galáxias). Para cenas: dist (0 — modelo no Sol, > 0 — afastar-se), pitch, center: true — orbitar o centro galáctico, off: true; tempo galáctico — galtime {rate} (anos/s) |
| galaxies | count, dwell | sobrevoar N galáxias famosas por distância, dwell segundos em cada |
| clear | desselecionar, fechar a ficha |
Eventos (calculados pela página, sem precisar de fórmulas)
| cmd | args | o quê |
|---|---|---|
| find | kind, from, to, total, count, min | lunar (total: true — «lua de sangue»), solar, parade (min de planetas 3…7) a partir de qualquer data; retorna o instante médio, total?, lat/lon/região onde é visível; lunar — contact (toque da umbra) |
| show | kind, at, keepView | mostrar um evento como em «📅 Eventos»: tempo — meia hora antes do meio, velocidade ×100 (defina time {rate: 0} ou a sua), seleção limpa, centro da vista e câmera na Terra (solar: acima do ponto da sombra) ou na Lua (lunar); um desfile — vista em primeira pessoa a partir da Terra, só planetas. As camadas definidas com view permanecem (keepView: false — as do evento). Depois: hideUi, camera se necessário |
Interface inteira
| cmd | args | o quê |
|---|---|---|
| ui | text, within | todo botão, caixa de seleção, controle deslizante, campo, linha de lista/árvore visível, com ref, texto, id, atributos data, estado. Filtro por texto ou área CSS |
| click | ref | selector | pressionar |
| set | ref | selector, value | caixa de seleção true/false, controle deslizante, campo, select |
| key | code, ms, shift, ctrl | pressionar tecla (KeyW… segure ms para voar, Space pausa, KeyH oculta painéis, Escape…) |
| pointer | action, x, y, to, dy | mouse na cena 3D: click (selecionar), dblclick (voar até), move (hover), drag (girar) até [x,y], wheel (dy zoom) |
| hideUi | on, labels | ocultar tudo: painéis, botões de canto, a barra do agente (labels: false — também os rótulos dos corpos); ficam só a cena, a legenda, as imagens, as janelas de mídia, as marcas (mark) e os desenhos do agente. on: false — volta |
| astro | action, name | astronauta: enter (onde a câmera está), goto name (voar até lá, orbitar), land (ficar de pé no solo), exit, link, state. Andar e olhar — key/pointer |
| eval | code | só no servidor de desenvolvimento (npm run dev): executa uma expressão JS na página; window.__known guarda o estado. Indisponível no site público |
Contar um roteiro
| cmd | args | o quê |
|---|---|---|
| caption | title, sub, text, seconds | legenda no canto inferior esquerdo como na proteção de tela (title vazio — ocultar) |
| say | text, title, sub, audio, keep, caption | mostrar o texto como legenda; audio — uma narração em mp3 (link ou nome de arquivo no computador; sem voz do navegador — gere o mp3 antes, p. ex. com edge-tts); 🔇 — silencioso |
| music | on, theme, volume | música de fundo gerada no navegador: theme 0 «Nebulosa», 1 «Profundeza», 2 «Cristais», null — alternar |
| image | id, src | path, at, x, y, dx, dy, w, label, remove, clear | sua imagem sobre a cena: presa a um corpo (o acompanha) ou em um ponto da tela |
| play | steps | stop | pause | seek | step | um cenário inteiro tocado pela página: [{cmd, args, wait}], wait = ms ou "speech". Como um player: pause, seek: n — pular para o passo n (os passos anteriores executam de imediato, sem esperas nem voz), step: ±1. A pessoa recebe um player embaixo: ⏮ ⏪ ▶/⏸ ⏹ ⏩ ⏭, «slide · passo», 💾 salvar no site (senha), ⬇ baixar, 🗑 excluir, ✕. Para ao desconectar — exceto com detach: true (toca até o fim e depois reverte). onError: 'skip' (padrão — continuar) | 'stop'; um passo com falha vai para logs, para play sem args (lastError) e para o player. Uma apresentação passa ao próximo slide sozinha; ✕ ou Esc — sair (a interface volta) |
| deck | slides, start, go, close | apresentação: [{title, steps}]; a pessoa recebe «◀ n/N ▶» embaixo (e PageUp/PageDown), avançar executa os passos daquele slide. Permanece visível com hideUi |
| buttons | items | seus próprios botões embaixo: [{label, title, steps}], um clique executa os passos; [] remove |
| story | action, story, id, password, name | um roteiro = o que o agente compôs (plano de voo, narração, visualização — p. ex. para o NASA Space Apps): {title, summary, lang, slides:[{title, steps}] | steps}. run — exibir; publish — salvar no site com uma senha de edição (password; sem ela — a página pergunta à pessoa) → link known.html?story=<uuid>, qualquer um o vê sem agente (com «◀ n/N ▶»); até 256 KB, guardado por 30 dias após a última abertura; update — editar (id + a mesma senha); delete — excluir do site (id + a mesma senha); download — um arquivo para a pessoa (qualquer tamanho); open — a pessoa escolhe um arquivo (ou solta um .json na página; menu «📂» na barra do agente); load — por id |
| steps | onde estamos em um roteiro ou apresentação: slide e lista de slides, passo e lista de passos (n, label), playing, paused. Pular — play {seek: n} / {step: ±1}, deck {go: n}. A pessoa tem ☰ no player — a lista de slides e passos, clique para pular | |
| scene | code | uma cena do modo ambiente dentro de um roteiro — seu voo de câmera, legenda e tempo (~20–30 s, aguarda o fim). Códigos — scenes: body:Сатурн, event:<id>, mission:…, astro:…, lapse:…, galaxy, pullback. O próprio modo ambiente («∞») é o mesmo gerador de cenas no player comum: ⏮ ▶/⏸ ⏭, ☰ reproduzidas e todas as cenas, 💾/⬇ — o que foi reproduzido como um roteiro de passos de cena |
| scenes | todas as cenas ambiente por seção, com códigos | |
| record | action, fps, mbps / path | vídeo da cena: start, stop (o MCP salva WebM em path) |
Um ponto de entrada: WS, MCP, console, roteiro
Os comandos e a linguagem são os mesmos, venham de onde vierem: WebSocket de qualquer linguagem, MCP, o console da página (o botão >_ na barra do agente) ou um roteiro. Escreva um cenário inteiro e entregue a story, ou chame os comandos um a um. Novidade: exec {steps} — executa passos da linguagem agora (as variáveis persistem entre chamadas), expr {e} — avalia uma expressão, js {code, timeout} — JavaScript em sandbox (iframe isolado + Web Worker: sem DOM, cookies ou rede; dentro — await cmd(name, args), await expr('…'), log(), sleep(), return).
Console: fly Mars size=0.6 (um comando, a primeira palavra é o nome), um comando JSON, passos {…} / […], uma expressão = …, código js ….
Script base — Node.js:
// node agent.mjs <código> (Node ≥ 22 — WebSocket embutido)
const code = process.argv[2], ws = new WebSocket(`wss://space.bl2.ru/agent/${code}?r=agent`);
let id = 0; const wait = new Map();
const cmd = (name, args = {}) => new Promise((res, rej) => {
const i = ++id; wait.set(i, { res, rej }); ws.send(JSON.stringify({ id: i, cmd: name, args }));
});
ws.onmessage = (e) => {
const m = JSON.parse(e.data);
if (m.sys) return; // peer / pong
const w = wait.get(m.id); wait.delete(m.id);
m.ok ? w.res(m.result) : w.rej(new Error(m.error));
};
setInterval(() => ws.send('{"sys":"ping"}'), 30000);
ws.onopen = async () => {
await cmd('fly', { name: 'Mars', size: 0.6, lit: true });
console.log(await cmd('expr', { e: "round(au(get('Mars','sun')),3)" }));
await cmd('exec', { steps: [{ wait: "dist('camera','Mars') < 1e5 km" }, { cmd: 'caption', args: { title: 'Mars' } }] });
process.exit(0);
};
Python:
# python agent.py <código> (pip install websockets)
import asyncio, json, sys, websockets
async def main(code):
async with websockets.connect(f"wss://space.bl2.ru/agent/{code}?r=agent") as ws:
n = 0
async def cmd(name, **args):
nonlocal n; n += 1
await ws.send(json.dumps({"id": n, "cmd": name, "args": args}))
while True:
m = json.loads(await ws.recv())
if m.get("id") == n:
if not m["ok"]: raise RuntimeError(m["error"])
return m["result"]
await cmd("fly", name="Saturn", size=0.6, lit=True)
print(await cmd("expr", e="get('Saturn','moons')"))
asyncio.run(main(sys.argv[1]))
Linguagem de cenário v2
Versões: um roteiro sem v (ou v: 1) — passos e slides como acima; v: 2 — uma linguagem com condições. Uma nova versão do manipulador nunca altera as antigas.
{ "v": 2, "title": "…", "on": ["oplanets"], "vars": { "n": 0 }, "steps": [
{ "cmd": "fly", "args": { "name": "Mars", "size": 0.5, "lit": true } },
{ "wait": "dist('camera', 'Mars') < 50000 km", "timeout": 20 },
{ "set": { "n": "n + 1" } },
{ "if": "visible('Mars')", "then": [ { "cmd": "caption", "args": { "title": "Mars", "sub": "{round(au(dist('camera','Sun')),3)} UA do Sol" } } ] },
{ "repeat": 2, "do": [ { "wait": 1 } ] }
] }
Passos: {cmd, args, wait} (wait — ms ou uma expressão), {wait: expression | seconds, timeout}, {if, then, else}, {repeat: n | expression, do}, {set: {name: expression}}, {on: [...]}. Expressões — sem eval: números com unidades km au ly m, strings '…', variáveis, + - * / %, < > <= >= == !=, && || !; funções dist(a, b) ('camera' ou um corpo, km), visible(body), elapsed(), time(), camdist(), au(x), ly(x), round(x, d), abs min max. Propriedades na hora: get(body | 'camera', 'prop') — um corpo tem name, kind, radius, parent, moons, x y z, sun (km do Sol), earth, camera (km da câmera), center, visible; a câmera tem dist, yaw, pitch, fov, x y z, sun, center; sem prop — o objeto inteiro. O resultado de um comando em uma variável: {cmd, args, as: 'r'}, um campo — field(r, 'rows.0.text'), tamanho — count(x). Em strings de args — {expression}. Os erros vão para logs. A seguir: gatilhos (when/once/every) e um sandbox (spawn de corpos e modelos 3D). Funções próprias: {def: name, params, e} — em expressões, {def, params, steps} — como um passo {call, args, as}, {local}, {return}; em um roteiro — funcs. Mais funções: angle(a, b) — graus entre as direções a partir da câmera, edge(a, b) — quantos graus a aparece além do limbo de b, sin cos (graus), pow sqrt. wait: true em um comando — até ele terminar. Para cenas: fitdist(r[, margin]) — a distância a partir da qual um círculo de raio r km cabe na tela (lado menor; um corpo também tem day — período de rotação, s); satcount('all' | 'active' | 'debris' | 'rb' | 'dead') — objetos do catálogo ao redor da Terra; mstat(craft, 'launch' | 'km' | 'turns' | 'rmin' | 'rnow' | 'flybys') — números da missão a partir de sua trajetória, até hoje. As trajetórias de naves e os sobrevoos vêm da importação (scripts/fetch-missions.mjs, JPL Horizons, diária): uma nova nave na base recebe seus sobrevoos e números automaticamente; flybys {craft} desenha os pontos de sobrevoo em seu caminho. Mídia em cenas: media {url | file, title, x, y, w, h, volume, loop, start, id} — uma janela com áudio ou vídeo: um link de mp3/vídeo ou YouTube; file — um arquivo do computador da pessoa (o site não guarda arquivos: a pessoa o escolhe na janela e então ele toca offline); close: true fecha as janelas. Estado: remember {name} — salva a câmera, o tempo, a vista e a interface; recall {name} — traz de volta; onstop {restore: true} (em um arquivo de roteiro — o campo "onstop": "restore") — ao terminar, com Esc ou ✕, recoloca tudo como antes do início. Avise a pessoa: roteiros e a proteção de tela podem ser controlados por um controle remoto — um apresentador de slides (PageDown/PageUp, «.» ou B — tela preta), teclas de mídia de teclados, fones e TV boxes (próximo, anterior, pausa), um gamepad (D-pad ←/→, A — pausa, B — tela preta), setas do teclado, Space, Esc. Links diretos: ?ambient — a proteção de tela, ?ambient=<scene code from ☰> — começando por aquela cena (p. ex. ?ambient=landings:Moon:apollo), ?story=<id>&step=N ou &slide=N — um roteiro publicado a partir daquele ponto; o botão 🔗 no player copia um link para o que está tocando. O comando ambient {play: code} faz o mesmo a partir de um agente; reset zera câmera, tempo e vista antes de uma cena.
Câmera e movimento
| cmd | args | o quê |
|---|---|---|
| fly | name, ms, ease, size, alt, lat, lon, rel, lit | Voo em um só movimento direto para o enquadramento: size — fração da altura da tela para o disco, alt — km acima da superfície, lat/lon — acima de um ponto da superfície, rel: {to, deg, elev} — lado em relação a outro objeto (0° — ele fica atrás da câmera, 180° — atrás do corpo no quadro; elev — elevar). Retorna ms. |
| camera | dist, yaw, pitch, rel, ms, ease, target | Câmera em torno do centro da vista; rel como em fly. target: {between: [a, b], k} — olhar para um ponto entre corpos; {sat: 25544} — orbitar um satélite (NORAD); {sat, space: {tilt, spin, from, ms}} — vista do espaço (a Terra atrás do satélite): tilt° da vertical, spin °/s, aproximação de from km até dist ao longo de ms; null — volta ao corpo. |
| media | url | file, kind, title, x, y, w, h, volume, loop, start, id, anchor, dx, dy, header, close, forgetDir | Uma janela com áudio ou vídeo: um link (mp3/vídeo/YouTube) ou file — um arquivo no computador (a pessoa o escolhe). anchor: {sat: NORAD} | {body: name} — a janela acompanha um objeto (dx, dy — deslocamento, px); header: false — sem barra de título (padrão quando ancorada). Retorna ms para wait: true. close: true | id; forgetDir: true — esquecer a pasta de mídia. Antes de um roteiro começar — a janela «Preparando a cena» (arquivos, pré-carregamento de links). |
| ambient | play | Proteção de tela «∞» a partir de uma cena dada: código como em ☰ (hover|Mars, landings:Moon:apollo, event:eclSun, mission:Parker, satellites…); sem play — a lista de códigos. |
| lang | set | Idioma da interface: sem set — o atual e a lista (ru, en, es, zh, pt); set — trocar. Troca na hora, sem recarregar: o agente continua conectado. O protetor de tela reproduz a cena atual de novo no novo idioma; o player, o cartão, a árvore de camadas e as janelas são redesenhados. O endereço da página passa a ser /<idioma>/ (por exemplo /pt/; o idioma do próprio domínio é só /): o idioma é definido apenas pelo endereço, não existe o parâmetro ?lang=; o link do site em um idioma é https://space.bl2.net/<idioma>/ (russo — https://space.bl2.ru/). |
| reset | — | Antes de uma cena: para a órbita, as rampas de olhar e de tempo; Galáxia desligada; marcas, pontos de sobrevoo e janelas de mídia removidos (as cenas da proteção de tela fazem isso sozinhas). |
| remember / recall | name | Salvar o estado (câmera, tempo, vista, interface) / trazê-lo de volta. |
| onstop | restore | Ligado por padrão: ao terminar, com Esc, ✕ ou a saída do agente, recoloca tudo como antes do primeiro comando do agente: camadas e alternâncias de vista, painéis e interface oculta, câmera (ângulo, distância, centro, rastreamento), seleção, tempo e velocidade (ou «ao vivo»); música e voz param. As coisas do próprio agente (sites, draw, mark, flybys, image, media, spawn) são sempre removidas. restore: false (em um arquivo de roteiro — "onstop": "keep") — mantém a câmera, o tempo e a seleção como o agente os deixou. exec reverte ao seu término só com um onstop {restore: true} explícito. |
| console | open | Abrir / fechar o console >_. |
| sites | body | code, group, ids, light, on | Locais de pouso: fichas em pontos da superfície (na cena). body pode ser omitido — o corpo vem do grupo (apollo, luna, rovers, new, farside, first, china — Lua; mars, chryse — Marte; venera — Vênus) ou de ids. Exemplo: sites {group: 'apollo', light: true} → {lat, lon, alt, at, ids}; depois time {at, rate: 0} e fly {name: 'Moon', lat, lon, alt}. Sem voar até lat/lon, a câmera pode ficar de frente para o lado oculto — nenhuma ficha visível. light: true — um instante em que os locais estão sob luz do dia (resposta at). |
| flybys | craft, on | Pontos de assistência gravitacional e de inserção em órbita no caminho de uma nave (da trajetória da missão). |
| orbit | speed (°/s), turns | ms, pitch, dist, end, blend, ease, stop | Orbitar o corpo. end: {to, deg, elev} — terminar exatamente nesse enquadramento (uma direção, sem voltar). Terminando em velocidade — segue por inércia, o próximo fly assume a velocidade. |
| look | to, ms, ease, clear | Olhar para um objeto: o olho fica (ou continua orbitando), a vista gira suavemente e o acompanha. clear: true — volta ao centro. |
| select, shadow, camera target | name; name, by, center, ms, dist; target | Para cenas da proteção de tela: select {name} — destacar o caminho de um corpo ('' — limpar); shadow {name, by, center, ms, dist} — câmera no ponto da sombra do eclipse; camera {target: {between: [a, b], k}, ms} — ponto de mira entre corpos (a órbita o circunda), target: null — volta; look {to: 'galcenter'}; fly {frame: {path, from, to, with}, elev, deg} — enquadrar o caminho inteiro de uma nave. |
| follow | name, ms, dist, ease | Seguir outro objeto: passagem suave mantendo o enquadramento. |
Mostrar um corpo pequeno (um cometa, um objeto interestelar — invisível a dezenas de milhões de km): follow {name} ou fly {name}, depois mark {name, label: true} — um marcador multicolorido piscante no corpo (visível também com hideUi; também color, speed), select {name} — o caminho dele fica brilhante. Remover: mark {remove: name} ou mark {clear: true}, select {name: ''}; a reversão do onstop e a saída do agente removem as marcas sozinhas.
Suavização ease — como uma função de temporização CSS: linear, ease, ease-in, ease-out, ease-in-out, smooth, cubic-bezier(x1,y1,x2,y2) ou uma fórmula de t (0…1): 1-pow(1-t,2), t*t*t*(t*(6*t-15)+10).
Sobreposição: {cmd, args, then: [steps], before_end: ms | after_begin: ms | when: "condition"} — os passos aninhados rodam junto com o comando. Exemplo: orbitar a Terra, voltar-se para Io, voar até ela:
[ {"cmd": "fly", "args": {"name": "Earth", "size": 0.4, "rel": {"to": "sun", "deg": 0, "elev": 10}, "ms": 3000, "ease": "ease-in-out"}, "wait": true},
{"cmd": "orbit", "args": {"speed": 60, "ms": 6000, "ease": "ease-in"},
"when": "edge('Io','Earth') < 15", "then": [{"cmd": "look", "args": {"to": "Io", "ms": 1500}, "wait": true}], "wait": true},
{"cmd": "fly", "args": {"name": "Io", "size": 0.15, "rel": {"to": "Jupiter", "deg": 180, "elev": 15}, "ms": 8000, "ease": "ease-out"}, "wait": true} ]
Sandbox, desenho, astronauta
| cmd | args | o quê |
|---|---|---|
| spawn | id, like, diameter, color, at: {near, dist, dir} | pos, vel | Seu próprio objeto: uma cópia de um corpo ou uma rocha; ele assume uma órbita circular em torno do corpo dominante (física, não linhas retas) |
| move | id, vel | impact: {target, at} | Nova velocidade ou «atingir um corpo em um instante» |
| despawn / objects | id | all | Remover / listar |
| draw | items | clear | remove | Gráficos no espaço para depuração e aulas: arrow (vel, sun, north, {sum}), axes (roll/pitch/yaw), line, dash, path, angle (arco e graus), project (projeção sobre um corpo, altitude), point, text; label — texto ao longo da linha |
| flybys | craft, on | Pontos de assistência gravitacional no caminho de uma nave: «Corpo · data» e o que a assistência deu; on: false — remover |
| sites | body | code, group, ids, light, on | Locais de pouso (Lua, Marte, Vênus, Titã): pontos e fichas na cena — foto, nome, ano, descrição; group — vista combinada (apollo, luna, rovers, new, farside, first, china, mars, chryse, venera; o corpo vem do grupo, body é opcional); light: true — locais no lado diurno; retorna lat, lon, alt para fly; on: false — remover |
| astro | action: goto | view | shield | land | exit, name, tpd, yaw, pitch, on, text | Astronauta: ancorar em qualquer coisa (corpo, ISS, número NORAD, asteroide); view — olhar para a figura; shield — remover/colocar um escudo, mensagem própria |
Console da página — a tecla crase (ё no layout russo).
Como trabalhar
- Leia esta página (
help), façaconnectcom o código. - Peça dados à página:
search/open(objetos),body(tamanhos, lado iluminado),where(posições),find(eventos),layers,state. - Prepare as ações a partir desses dados: um cenário
play, ou umdeckde slides que a pessoa percorre, oubuttons. - Execute; confira com
screenshotelogs; ajuste.
5. Exemplo: «conte-me sobre os planetas»
connect {code}
layers → layer {key, visible:false} for everything except oplanets
music {theme: 0, volume: 0.4}; hide_ui {on: true}
play {steps: [
{cmd:"fly", args:{name:"Mars"}, wait: 3800},
{cmd:"camera", args:{yaw: …, pitch: …, dist: …, ms: 3000}, wait: 3200}, // valores de body {name:"Mars"}
{cmd:"say", args:{title:"Mars", sub:"228 million km · light takes 13 min", text:"…", audio:"mars.mp3"}, wait: "speech"}, // a voz é Piper no navegador (ru ruslan, en amy); audio — um mp3 pronto no lugar dela
…
]}
6. Recursos
- Corpos: Sol, 8 planetas com luas, planetas anões, ~1,4 M de asteroides (por grupos de tamanho), cometas, naves interplanetárias, ~30 000 satélites da Terra (CelesTrak, diário), constelações em 3D, modelo da Via Láctea com nebulosas e aglomerados, 44 000 galáxias (2MRS).
- Os nomes funcionam em russo e inglês (
Марс/Mars); as posições são equatoriais J2000, km. - Intervalo de tempo: qualquer data (as efemérides pioram longe de hoje; satélites só ±90 dias do catálogo).
- Links de compartilhamento (
?o=…&d=…&v=…&t=…) abrem a mesma vista para qualquer pessoa.
Regras: a página aceita somente esses comandos; sem navegação para outros sites, sem dados pessoais. Mantenha a pessoa no controle — ela pode pressionar «Desconectar» a qualquer momento.