Status: Developer preview — the SDK (@nexislabs/ai-platform) is source-available in the Praxa repo and contract-stable; npm publication follows the public API launch and its security review.
AiPlatformClient.streamChat() returns AsyncGenerator<AiPlatformEventV1>. Every event shares an envelope on top of its own fields:
The event union
AiPlatformEventV1 is a Zod discriminated union on type. These are the only 19 values that exist in v1 — an unrecognized type fails schema validation rather than passing through as an unknown event (see typescript.md):
response.final, request.cancelled, and request.failed are the only terminal types. streamChat() enforces that exactly one of them ends the stream, and that nothing follows it (typescript.md).
Consuming with a switch
AiPlatformEventV1 is a discriminated union, TypeScript narrows event inside each case to that variant’s exact shape, and the switch is exhaustively checkable: adding default: { const exhaustive: never = event; throw new Error("unhandled event"); } will fail to compile if a future SDK version adds a case you haven’t handled yet (only after you deliberately upgrade — see the versioning note in errors-and-retries.md).
Handling approval.required
approval.required is not a terminal event — nothing in the schema or the client stops more events from following it. What happens to the underlying connection while a person is deciding (held open vs. closed by the server) isn’t specified by this package; design for either. If the approval window lapses before a decision is made, the run ends with a request.failed event whose problem.code is "approval_timed_out".
Resuming is a new streamChat() call — not a call back into the same generator. Once your application has a decision and a server-issued receipt for it (obtaining that receipt happens outside this package, through whatever endpoint your platform exposes for submitting approval decisions), attach it to a fresh request on the same conversation:
approvals[].receipt is an opaque string (16–4096 characters) — treat it as a single-use bearer credential for that one approval decision, not as something you construct or inspect. conversationId/sessionId carry the thread forward from original; requestId is per-call and must be fresh.
Reconnect with Last-Event-ID (task mode)
Planned — not implemented in this package version. The Praxa Execution Fabric design (docs/superpowers/specs/2026-07-30-maas-execution-fabric-design.md§3.1) adds a second, durable execution shape —mode: "task"— withGET /v1/runs/:id/eventsstreamingtask_run_eventsand supportingLast-Event-ID-based resume after a disconnect, plusPOST /v1/runs/:id/cancel. The design spec itself lists “external SSE fortask_run_events” and the public run/event projections as unbuilt gaps, not shipped capability.
AiPlatformClient has no run_id concept, no GET /v1/runs/:id/events method, and no reconnect/resume helper today — it only speaks the synchronous turn-mode POST /v1/chat call documented above and in typescript.md. The SSE parser in this package (parseAiPlatformEventStream) also only reads data: lines off the wire; it does not read or emit an id: framing line, so there is nothing today that a browser-native EventSource’s automatic Last-Event-ID reconnection could latch onto even if this client used EventSource instead of fetch (it doesn’t — it reads the response body as a raw ReadableStream). sequence is presently a payload field you can compare yourself, not a resumable stream cursor.
Once task mode ships, the design doc’s shape is: track the highest sequence you’ve successfully processed for a run, and send it back as the Last-Event-ID request header when reopening GET /v1/runs/:id/events after a disconnect, so the server resumes from task_run_events.sequence instead of replaying the whole run. Until then, track sequence defensively in turn mode too — it’s your signal that events arrived in order and without gaps, per the invariants typescript.md documents.
Continue with errors-and-retries.md for how request.failed, thrown errors, and cancellation fit together, or back to typescript.md for the client and request contract.