Files
anomalyco_opencode/packages/protocol/src/groups/event.ts
T
2026-07-06 13:01:36 -04:00

59 lines
2.4 KiB
TypeScript

import { Event } from "@opencode-ai/schema/event"
import { EventManifest } from "@opencode-ai/schema/event-manifest"
import { Location } from "@opencode-ai/schema/location"
import type { Definition } from "@opencode-ai/schema/event"
import { Schema } from "effect"
import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi"
const fields = {
id: Event.ID,
metadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
location: Schema.optional(Location.Ref),
}
const schema = <const Definitions extends ReadonlyArray<Definition>>(definitions: Definitions) =>
Schema.Union([
...definitions,
...(definitions.some((definition) => definition.type === "server.connected")
? []
: [
Schema.Struct({
...fields,
type: Schema.Literal("server.connected"),
data: Schema.Struct({}),
}).annotate({ identifier: "V2Event.server.connected" }),
]),
]).annotate({ identifier: "V2Event" })
const make = <const Definitions extends ReadonlyArray<Definition>>(definitions: Definitions) => {
const EventSchema = schema(definitions)
return {
schema: EventSchema,
group: HttpApiGroup.make("server.event")
.add(
HttpApiEndpoint.get("event.subscribe", "/api/event", {
success: HttpApiSchema.StreamSse({ data: EventSchema }),
}).annotateMerge(
OpenApi.annotations({
identifier: "v2.event.subscribe",
summary: "Subscribe to events",
description:
"Subscribe to native event payloads for the server. Volatile by contract: a slow consumer overflows and fails the stream, and events during disconnection are missed.",
}),
),
)
.annotateMerge(OpenApi.annotations({ title: "event", description: "Experimental event stream routes." })),
}
}
export const makeEventGroup = <const Definitions extends ReadonlyArray<Definition>>(definitions: Definitions) =>
make(definitions).group
const event = make(EventManifest.ServerDefinitions)
export const EventGroup = event.group
export const OpenCodeEvent = event.schema
export type OpenCodeEvent = typeof OpenCodeEvent.Type
export type OpenCodeEventEncoded = typeof OpenCodeEvent.Encoded
export const isOpenCodeEvent = (event: { readonly type: string }): event is OpenCodeEvent =>
event.type === "server.connected" || EventManifest.isServer(event)