add global.event.subscribe() to sdk

This commit is contained in:
Dax Raad
2025-11-14 12:32:43 -05:00
parent c1cf9cda6a
commit 5fc26c958a
5 changed files with 717 additions and 623 deletions

View File

@@ -0,0 +1,10 @@
import { EventEmitter } from "events"
export const GlobalBus = new EventEmitter<{
event: [
{
directory: string
payload: any
},
]
}>()

View File

@@ -2,6 +2,7 @@ import z from "zod"
import type { ZodType } from "zod"
import { Log } from "../util/log"
import { Instance } from "../project/instance"
import { GlobalBus } from "./global"
export namespace Bus {
const log = Log.create({ service: "bus" })
@@ -65,6 +66,10 @@ export namespace Bus {
pending.push(sub(payload))
}
}
GlobalBus.emit("event", {
directory: Instance.directory,
payload,
})
return Promise.all(pending)
}

View File

@@ -40,6 +40,7 @@ import type { ContentfulStatusCode } from "hono/utils/http-status"
import { TuiEvent } from "@/cli/cmd/tui/event"
import { Snapshot } from "@/snapshot"
import { SessionSummary } from "@/session/summary"
import { GlobalBus } from "@/bus/global"
const ERRORS = {
400: {
@@ -117,6 +118,51 @@ export namespace Server {
timer.stop()
}
})
.get(
"/global/event",
describeRoute({
description: "Get events",
operationId: "global.event.subscribe",
responses: {
200: {
description: "Event stream",
content: {
"text/event-stream": {
schema: resolver(
Bus.payloads().meta({
ref: "Event",
}),
),
},
},
},
},
}),
async (c) => {
log.info("global event connected")
return streamSSE(c, async (stream) => {
stream.writeSSE({
data: JSON.stringify({
type: "server.connected",
properties: {},
}),
})
async function handler(event: any) {
await stream.writeSSE({
data: JSON.stringify(event),
})
}
GlobalBus.on("event", handler)
await new Promise<void>((resolve) => {
stream.onAbort(() => {
GlobalBus.off("event", handler)
resolve()
log.info("global event disconnected")
})
})
})
},
)
.use(async (c, next) => {
const directory = c.req.query("directory") ?? process.cwd()
return Instance.provide({

View File

@@ -2,6 +2,8 @@
import type { Options as ClientOptions, TDataShape, Client } from "./client/index.js"
import type {
GlobalEventButtData,
GlobalEventButtResponses,
ProjectListData,
ProjectListResponses,
ProjectCurrentData,
@@ -175,6 +177,32 @@ class _HeyApiClient {
}
}
class Event extends _HeyApiClient {
/**
* Get events
*/
public butt<ThrowOnError extends boolean = false>(options?: Options<GlobalEventButtData, ThrowOnError>) {
return (options?.client ?? this._client).get.sse<GlobalEventButtResponses, unknown, ThrowOnError>({
url: "/global/event",
...options,
})
}
/**
* Get events
*/
public subscribe<ThrowOnError extends boolean = false>(options?: Options<EventSubscribeData, ThrowOnError>) {
return (options?.client ?? this._client).get.sse<EventSubscribeResponses, unknown, ThrowOnError>({
url: "/event",
...options,
})
}
}
class Global extends _HeyApiClient {
event = new Event({ client: this._client })
}
class Project extends _HeyApiClient {
/**
* List all projects
@@ -828,18 +856,6 @@ class Auth extends _HeyApiClient {
}
}
class Event extends _HeyApiClient {
/**
* Get events
*/
public subscribe<ThrowOnError extends boolean = false>(options?: Options<EventSubscribeData, ThrowOnError>) {
return (options?.client ?? this._client).get.sse<EventSubscribeResponses, unknown, ThrowOnError>({
url: "/event",
...options,
})
}
}
export class OpencodeClient extends _HeyApiClient {
/**
* Respond to a permission request
@@ -860,6 +876,7 @@ export class OpencodeClient extends _HeyApiClient {
},
})
}
global = new Global({ client: this._client })
project = new Project({ client: this._client })
config = new Config({ client: this._client })
tool = new Tool({ client: this._client })

File diff suppressed because it is too large Load Diff