5c66161ca7
Build the client-side half of the Session channel extensions that the
sessions PR shipped on the server. Pairs with POST
/api/v1/runs/:runFriendlyId/session-streams/wait and the
append-fires-waitpoints wiring on the session append handler.
Extend SessionHandle with two asymmetric channels mirroring the
run-scoped streams primitives:
- .in (SessionInputChannel) mirrors streams.input. on / once / peek /
wait / waitWithIdleTimeout for the task to consume; send for
external clients to produce. .wait / .waitWithIdleTimeout suspend
the run on a session-stream waitpoint; it resumes when a record
lands on .in, same semantics as streams.input.wait on a run-scoped
input stream.
- .out (SessionOutputChannel) mirrors streams.define. append / pipe /
writer for the task to produce records — all three route through
SessionStreamInstance -> StreamsWriterV2 for uniform parsed-object
serialization on the subscribe side. read returns an SSE subscription
for external consumers.
The two channels are disjoint classes with zero overlapping methods.
SessionHandle is { id, in, out } so directional tags stay at every
call site. No public initialize() — S2 credentials are an internal
detail of pipe / writer.
Core
- StandardSessionStreamManager + sessionStreams global: SSE-backed
tail with once/on/peek buffering, auto-reconnect, lastSeqNum
resume. Keyed on {sessionId, io}. Registered in dev- and managed-
run workers; taskExecutor clears handlers at run end alongside
input streams.
- SessionStreamInstance: S2-only parallel of StreamInstance. Fetches
session S2 creds via initializeSessionStream and pipes through
StreamsWriterV2.
- ApiClient.createSessionStreamWaitpoint — calls the new server route.
Reference
- references/hello-world/src/trigger/sessionsSmoke.ts now exercises
.out.writer alongside .out.append.
- references/hello-world/src/trigger/sessionsWaitSmoke.ts (new) —
end-to-end waitpoint validation. Orchestrator suspends on
.in.waitWithIdleTimeout; a delayed sender task fires the waitpoint
via .in.send; orchestrator resumes with the payload. match: true.