Action handlers now only see fields from the param table. Extra client
keys are still ignored. Garbage values on declared numbers fail instead
of becoming zero.
Compile canonical names, aliases, stream kinds, documentation, and raw reservations into one immutable registry. Reject duplicate, undeclared, mismatched, or late handler registration before requests can be dispatched.
Wait for asynchronous transports to flush bad-request frames before processStreamRequest returns. This prevents malformed Stream API requests from losing their terminal error response.
Foundation for NapCat-compatible Stream API actions (chunked file
upload/download): a single request answered by many response frames.
- streaming.ts: StreamSink + frame wrappers (wrapStreamFrame /
wrapStreamTerminal) matching NapCat's wire — each frame an OB11 envelope
with stream:'stream-action', data.type ∈ stream/response/error, and
message mirrored into wording.
- ApiHandler: registerStreamAction / isStreamAction; handle() threads a
sink; processStreamRequest drives WS multi-frame dispatch with optional
liveness-based abort; dead processRequest removed.
- action-kit: defineStreamAction (sink-aware run, registers as a stream
action) reusing defineAction's parse/describe.
- adapters: HTTP server streams chunked \r\n\r\n-delimited frames (no
Content-Length, no false application/json), aborting on client
disconnect; WS server/client use a backpressure-aware safeSendAsync and
abort a stream once the socket closes.
No stream actions are registered yet — those land in the next phases.
Verified by two adversarial review passes. 480 onebot tests green.