3.4 KiB
02 — Lua client (trapos-sandbox)
Sub-plan of trap-sandbox-gateway-spec. Implements the Protocol, Handshake, and os-event contract from the spec — reference them, don't redefine. M2; depends on the protocol contract (not on M1 code existing).
Scope
The Lua side: apis/libsandbox.lua, servers/sandbox.lua, programs/sandbox.lua, and Lua unit
tests. Package/meta changes are 03-packages; integration/e2e is
04-integration-tooling.
Task checklist
apis/libsandbox.lua(template:apis/libmcpcomputer.lua).servers/sandbox.lua(template:servers/mcp-computer-server.lua).programs/sandbox.lua(template:programs/ai.lua).- Lua unit tests (
tests/sandbox.lua). - Gate:
just _craftos-testrunstests/sandbox.luagreen.
apis/libsandbox.lua — template: apis/libmcpcomputer.lua
createSandbox() returns:
traposId(osLike)→id .. ":" .. (label or "").- Envelope builders for the 4 events + hello.
onMessage(content, …): decode (pcall);gateway_request→ built-inping(elseok:false unknown_type) replied ascomputer_responsevia pcall-send;gateway_response→ iftype=="hello"drive the handshake state, elsequeueEvent('trapos_sandbox_reply', messageId, ok, payload, error).startSession(opts)(daemon; injectablehttp/eventloop/encode/decode/os): builds the connect URL from baseopts.url, computestraposId;websocketAsync; onwebsocket_successsend hello; on hellook:trueset state=ready +queueEvent('trapos_sandbox_connected', traposId); on hellook:falseset state=unauthorized (terminal, storelastError, close, no reconnect); onwebsocket_failure/_closedreconnect viael.setTimeout(connect, 5)(unless unauthorized); hello with no ack in ~10s → close + reconnect;trapos_sandbox_sendhandler buildscomputer_request, pcall-send only when ready, else fasttrapos_sandbox_reply(messageId, false, nil, {code:"not_connected"}). Returns{ isReady, lastError }.request(type, payload, opts)(injectablequeueEvent/pullEvent/startTimer): mint messageId, queuetrapos_sandbox_send, wait for matchingtrapos_sandbox_replyvs a timer (default 10s, overridable). Returns(ok, payloadOrError).
servers/sandbox.lua — template: servers/mcp-computer-server.lua
Read sandbox.url (unset/http.websocket missing → "daemon inactive", return) and sandbox.password;
startSession{ eventloop=_G.bootEventLoop, url, password(secret), os }; print version.
programs/sandbox.lua — template: programs/ai.lua
- Reads
sandbox.urlfirst; unset → immediateset sandbox.url first(no 10s wait). health→request('health'); printsandboxOk/opencodeOk(+opencode: <detail>when false); onnot okprintsandbox health failed: <code> <message>(e.g.unauthorized,not_connected,timeout).--version/--help.
Lua unit tests (tests/sandbox.lua, libtest + fakes)
Envelope builders, traposId, onMessage dispatch (ping ok / unknown_type / hello), empty-payload
coercion, startSession wiring (fake eventloop+http: hello sent on open, ready on ack, terminal on
unauthorized, reconnect on drop), request() resolve + timeout via injected event primitives.
Verification gate
just _craftos-test runs the new tests/sandbox.lua green.