feat(sdk): expose live event stream (#34098)

This commit is contained in:
Kit Langton 2026-06-26 21:16:33 +02:00 committed by GitHub
commit 42e6b7db32
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 395 additions and 56 deletions

View file

@ -1,16 +1,19 @@
import { EventV2 } from "@opencode-ai/core/event"
import { Effect, Stream } from "effect"
import { OpenCodeEvent } from "@opencode-ai/protocol/groups/event"
import { Effect, Schema, Stream } from "effect"
import { HttpServerResponse } from "effect/unstable/http"
import { HttpApiBuilder } from "effect/unstable/httpapi"
import * as Sse from "effect/unstable/encoding/Sse"
import { Api } from "../api"
const subscriberCapacity = 256
function eventData(data: unknown): Sse.Event {
return {
_tag: "Event",
event: "message",
id: undefined,
data: JSON.stringify(data),
data: JSON.stringify(Schema.encodeUnknownSync(OpenCodeEvent)(data)),
}
}
@ -24,13 +27,16 @@ export const EventHandler = HttpApiBuilder.group(Api, "server.event", (handlers)
type: "server.connected",
data: {},
}
const output = Stream.unwrap(
Effect.gen(function* () {
// Acquiring the bounded stream installs its listener before readiness is observable.
const live = yield* EventV2.allBounded(events, subscriberCapacity)
return Stream.make(connected).pipe(Stream.concat(live))
}),
).pipe(Stream.map(eventData), Stream.pipeThroughChannel(Sse.encode()))
const heartbeat = Stream.tick("15 seconds").pipe(Stream.map(() => ": heartbeat\n\n"))
return HttpServerResponse.stream(
Stream.make(connected).pipe(
Stream.concat(events.all()),
Stream.map(eventData),
Stream.pipeThroughChannel(Sse.encode()),
Stream.encodeText,
),
output.pipe(Stream.merge(heartbeat, { haltStrategy: "left" }), Stream.encodeText),
{
contentType: "text/event-stream",
headers: {