@ai-ecoverse/wasi-slicc
slicc for seven's kernel, built from ai-ecoverse/slicc-cli at the same version.
slicc also runs inside seven's kernel, so that one seven's agent or user can prompt, watch and abort another seven's agent, and see and manage this seven's own tray. That build is slicc.wasm, slicc-cli's client commands compiled with GOOS=wasip1 GOARCH=wasm and CGO_ENABLED=0, and it ships as the npm package @ai-ecoverse/wasi-slicc, at slicc-cli's own version. seven's page holds the WebRTC link; slicc only reaches the page's link facade.
slicc <join-url> prompt [--allsettled <quiet>] [--steer | --reject] [--thinking] [--json] [--plain] <text>|@file|-
slicc <join-url> watch [--thinking] [--json] [--plain] [--since <entry-id>]
slicc <join-url> wait [--allsettled <quiet>] [--timeout <limit>] [--json]
slicc <join-url> abort
slicc tray [--json]
slicc tray url
slicc tray rotate
slicc tray unlink <device>
slicc tray retry
slicc --version
slicc --help
- Commands:
prompt,watch,waitandabortwith a join URL behave as in Remote control: the same flags, output, styling,--jsonevents, resuming and exit codes, from the same code. The differences:- Ctrl-C ends slicc with 130 (the kernel's default for
SIGINT),watchincluded, and a running prompt goes on in the other seven.--abort-on-interruptisn't offered. - Exit 3 covers the facade's own refusals too. When the facade gives a message (
unlock the vault to continue, or the other seven's refusal), slicc prints it instead of the Linked devices hint. - A terminal is a standard stream that is a character device. Styling then follows
TERM,NO_COLORand--plainas usual.
- Ctrl-C ends slicc with 130 (the kernel's default for
slicc tray: this seven's tray, the leader's view (SLICC six'shost). It asks the facade with thetraykind (§5.16), so it takes no join URL.slicc trayprints the tray's state (off,connecting,ready,reconnectingorfailed) and its hub origin, the current exit when it is a device or a tailnet node, and one line per device:DEVICE(its fingerprint, as3fa9…c210),NAME,HOST(<label>.slicc.internal),MODE,STATE(connecting,connectedoroffline) andOFFERS(exitwhen the device offers to be the exit).--jsonprints seven's answer as one line of JSON.slicc tray urlprints the join URL and nothing else, soslicc tray url > /dev/clipboardcopies it. It is the one deliberate exception to "the join URL is never printed": nothing else prints it,slicc trayand--jsonincluded, so it reaches a transcript only when asked for. It prints only an answer that is a valid join URL without control characters, and exits 1 otherwise.- Whatever seven answers, slicc doesn't trust it to keep the rule.
slicc tray,--jsonand the error messages replace any join URL in the answer with<join-url>, and strip control characters and terminal escapes from names and messages.--jsonalso dropsurl,join,joinUrl,joinCommand,followUrlandwebhookUrlkeys, wherever they are, and prints one line. slicc tray rotatemakes a new join URL; the old one stops working (SLICC six'shost reset). It prints nothing on stdout, andmade a new join URL; …on stderr.unlinkandretryalso confirm on stderr.slicc tray unlink <device>drops one device, as Linked devices' Unlink does.<device>is a fingerprint, a unique prefix of one (colons and case ignored), or exactly the short formslicc trayshows (3fa9…c210, or3fa9...c210). slicc asks for the status first and matches there, then sends the full id. No match or more than one exits 1.slicc tray retryreconnects the tray's links, as the Reconnect button does.- Not here: choosing the exit (that's routing, not tray state), and SLICC six's
host joinandhost leave: a seven follower runs no kernel or agent of its own, so following stays with#follow=and the UI's Leave. - Exit status: 0, 1 on failure (
ENOTCONNwhen the tray isn't connected, a facade that doesn't answer within 1 minute, or 5 minutes forrotateandunlink, which seven may ask you to approve), 2 for bad usage, 3 when seven refuses (EACCES).
- Everything else exits 2 with
slicc: <command> isn't available inside seven:follow,attach,open,browsers, the default flow,update,install, andprompt,watch,waitorabortwithout a join URL.--helplists only what works there. - What the build leaves out (build constraints): pion and the link, CDP, SSH, mounts, the kernel listener, the policy, browser discovery, telemetry and updates.
The link facade. slicc reads its address from SLICC_LINK_URL only, as tcp://127.0.0.1:<port> on the kernel's loopback (any 127.x address, or localhost). Without it, or with another shape, slicc exits 1. Each agent stream (see agent) is one connection, carrying records of a u8 type, a u32 big-endian length and the payload, both ways:
1, control: JSON, at most 64 KiB.- slicc's first record is
{ "v": 1, "join": "<join-url>", "open": { "kind": "agent", "op": … } }, whereopenis the stream's OPEN,lengthfor long prompts included. The join URL goes only there, never in an address, a log or an error. - For
slicc tray, it is{ "v": 1, "open": { "kind": "tray", "op": … } }, withoutjoin. The page answers with one control record,{ "opened": <result> }or areset, and slicc closes the connection (see §5.16). - The page answers
{ "opened": { … } }(the OPENED) or{ "reset": "ERRNO: message" }. Aresetmay also come later, as the stream's RESET. - Without an answer within 1 minute, slicc gives up:
seven's link facade didn't answer within 1m0s, exit 1 (watchreconnects).slicc tray rotateandunlinkwait 5 minutes, since seven may ask for approval first.
- slicc's first record is
2, data: the stream's DATA: a long prompt's bytes up, and NDJSON events down. slicc sends records of at most 64 KiB, and takes records of up to 16 MiB; record boundaries carry no meaning.3, end: that side's END. slicc closes the connection after both ends or a reset.- Errors: an unknown type, a control record over 64 KiB, any record over 16 MiB, a control record that isn't JSON, or a later control record that isn't a
resetmakes slicc send{ "reset": "EPROTO" }and fail the stream.ENOTCONN(the tray can't be reached) failspromptandabortwith exit 1;watchsayslost the link to seven; reconnectingand retries with its usual backoff, as it does when a connection drops.
The host module. Go on wasip1 can't open sockets, so the package's host/slicc-host.mjs gives slicc.wasm the slicc_host imports, on the kernel's loopback, through the imports-module API's ctx.net.connect and ctx.net.ready and the fd-read, fd-write, fd-select and fd-close calls (slicc-kernel 1.92.0 or later, the package's engines.slicc-kernel): probe, connect(host, port) (loopback only, non-blocking; localhost is connected as 127.0.0.1, never by name, so /etc/hosts can't point it elsewhere), connected(fd, timeout), read(fd, buffer, timeout), write(fd, buffer, timeout) (non-blocking) and close(fd). Connects, reads and writes wait at most 100 ms at a time, so signals, timeouts and a reset that arrives while a long prompt uploads get through. Without the module, slicc exits 1 with this runtime has no slicc_host module. On a kernel older than 1.92.0, which has no ctx.net, connect answers ENOSYS, so slicc exits 1 with can't reach seven's link facade.
The package. @ai-ecoverse/wasi-slicc holds bin/slicc.wasm, host/slicc-host.mjs, this section as its README, and the LICENSE. Its package.json has "slicc": { "abi": "wasi", "commands": { "slicc": { "wasm": "bin/slicc.wasm", "imports": "host/slicc-host.mjs" } } } and engines.slicc-kernel. The release attaches slicc.wasm as slicc-wasip1-wasm.wasm, in SHA256SUMS and its attestation (see Releases).
Tests. test/integration/wasi_test.go builds slicc.wasm, stages the package with npm-stage.mjs --wasi-only, and runs it in @ai-ecoverse/slicc-kernel's Node kernel (an exact-pinned devDependency, so npm ci first) against a fake facade, a kernel JS program in testdata/wasi/fakefacade/. One case writes /etc/hosts as root to map localhost to 203.0.113.5 and connects to tcp://localhost:<port>; testdata/wasi/hostmodule.mjs also loads the staged host/slicc-host.mjs with a ctx.net that records the host it is asked for. wasi_realfacade_test.go runs it against the kernel's own link facade (createNodeKernel({ facades: { link } })), served by a test page hook, testdata/wasi/page.mjs, that implements §5.16: it checks the stamp the hook receives (root and a cone in sudo pass, a scoop gets EACCES) and that the kernel sets SLICC_LINK_URL. wasi_tray_test.go runs slicc tray against both, and checks that its openings carry no join URL. cmd/slicc builds for both: a file there that needs a native-only package carries //go:build !wasip1, and wasi_test.go fails when the wasip1 build breaks or links one of the left-out packages.