feat(irc-ws): add irc-ws-receive-line raw transport for Enclave
irc-ws-receive-line returns the WebSocket payload for one IRC command per frame directly, instead of routing opaque Enclave stream tickets through the parsed IRC queue. It unwraps a ws-message (text) or accepts a raw string, and latches the session dead only on a genuine close.
The ws-message unwrap is required because (sigil websocket) ws-receive is on the MESSAGE path (binary frames must flow for the terminal stream relay); imports (sigil websocket connection) for ws-message? / ws-message-type.
Provenance: the irc-ws-receive-line function is prior-session work from the 2026-08-06..08-10 Slate/Enclave remote-terminal investigation; committed during cleanup, not authored here. The ws-message-unwrap branch was added by this session's terminal-stream work.
packages/sigil-irc-websocket/src/sigil/irc/websocket.sgl | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)packages/sigil-irc-websocket/src/sigil/irc/websocket.sglmodified
(sigil math) (sigil string) (sigil struct) (sigil websocket) (sigil websocket connection) (sigil irc message)) (export irc-ws-part irc-ws-quit irc-ws-receive) irc-ws-receive irc-ws-receive-line) (begin (irc-ws-command session "QUIT"))) (irc-ws-close session)) (define (irc-ws-receive-line session) (: irc-ws-session? -> any?) ;; Enclave sends one IRC command per WebSocket text message. Return that ;; transport payload directly: routing it through the parsed IRC queue is ;; both unnecessary and unsafe for opaque stream tickets in native builds. (let ((websocket (irc-ws-session-websocket session))) (if (not websocket) 'closed (let ((message (ws-receive websocket))) (cond ;; This is the raw transport API. Preserve the WebSocket text ;; payload exactly; callers that consume IRC lines already own ;; CRLF splitting. Besides avoiding duplicate work, this keeps ;; opaque Enclave stream tickets out of the generic line helper. ;; ws-receive is back on the MESSAGE path (binary frames must ;; flow for the terminal stream relay), so unwrap text here. ((and (ws-message? message) (eq? (ws-message-type message) 'text)) (ws-message-data message)) ((string? message) message) ;; Latch the session dead ONLY on a genuine close. This relies ;; on ws-receive returning #f while an async socket is opening. ((eq? message 'closed) (set-irc-ws-session-state! session 'disconnected) 'closed) (else message)))))) (define (irc-ws-receive session) (: irc-ws-session? -> any?) (let ((queued (pop-message! session)))