|
1 | | -import { BusEvent } from "@/bus/bus-event" |
2 | | -import { Bus } from "@/bus" |
3 | 1 | import { Log } from "../util/log" |
4 | 2 | import { describeRoute, generateSpecs, validator, resolver, openAPIRouteHandler } from "hono-openapi" |
5 | 3 | import { Hono } from "hono" |
6 | 4 | import { cors } from "hono/cors" |
7 | | -import { streamSSE } from "hono/streaming" |
8 | 5 | import { proxy } from "hono/proxy" |
9 | 6 | import { basicAuth } from "hono/basic-auth" |
10 | 7 | import z from "zod" |
@@ -34,6 +31,7 @@ import { FileRoutes } from "./routes/file" |
34 | 31 | import { ConfigRoutes } from "./routes/config" |
35 | 32 | import { ExperimentalRoutes } from "./routes/experimental" |
36 | 33 | import { ProviderRoutes } from "./routes/provider" |
| 34 | +import { EventRoutes } from "./routes/event" |
37 | 35 | import { InstanceBootstrap } from "../project/bootstrap" |
38 | 36 | import { NotFoundError } from "../storage/db" |
39 | 37 | import type { ContentfulStatusCode } from "hono/utils/http-status" |
@@ -251,6 +249,7 @@ export namespace Server { |
251 | 249 | .route("/question", QuestionRoutes()) |
252 | 250 | .route("/provider", ProviderRoutes()) |
253 | 251 | .route("/", FileRoutes()) |
| 252 | + .route("/", EventRoutes()) |
254 | 253 | .route("/mcp", McpRoutes()) |
255 | 254 | .route("/tui", TuiRoutes()) |
256 | 255 | .post( |
@@ -498,64 +497,6 @@ export namespace Server { |
498 | 497 | return c.json(await Format.status()) |
499 | 498 | }, |
500 | 499 | ) |
501 | | - .get( |
502 | | - "/event", |
503 | | - describeRoute({ |
504 | | - summary: "Subscribe to events", |
505 | | - description: "Get events", |
506 | | - operationId: "event.subscribe", |
507 | | - responses: { |
508 | | - 200: { |
509 | | - description: "Event stream", |
510 | | - content: { |
511 | | - "text/event-stream": { |
512 | | - schema: resolver(BusEvent.payloads()), |
513 | | - }, |
514 | | - }, |
515 | | - }, |
516 | | - }, |
517 | | - }), |
518 | | - async (c) => { |
519 | | - log.info("event connected") |
520 | | - c.header("X-Accel-Buffering", "no") |
521 | | - c.header("X-Content-Type-Options", "nosniff") |
522 | | - return streamSSE(c, async (stream) => { |
523 | | - stream.writeSSE({ |
524 | | - data: JSON.stringify({ |
525 | | - type: "server.connected", |
526 | | - properties: {}, |
527 | | - }), |
528 | | - }) |
529 | | - const unsub = Bus.subscribeAll(async (event) => { |
530 | | - await stream.writeSSE({ |
531 | | - data: JSON.stringify(event), |
532 | | - }) |
533 | | - if (event.type === Bus.InstanceDisposed.type) { |
534 | | - stream.close() |
535 | | - } |
536 | | - }) |
537 | | - |
538 | | - // Send heartbeat every 10s to prevent stalled proxy streams. |
539 | | - const heartbeat = setInterval(() => { |
540 | | - stream.writeSSE({ |
541 | | - data: JSON.stringify({ |
542 | | - type: "server.heartbeat", |
543 | | - properties: {}, |
544 | | - }), |
545 | | - }) |
546 | | - }, 10_000) |
547 | | - |
548 | | - await new Promise<void>((resolve) => { |
549 | | - stream.onAbort(() => { |
550 | | - clearInterval(heartbeat) |
551 | | - unsub() |
552 | | - resolve() |
553 | | - log.info("event disconnected") |
554 | | - }) |
555 | | - }) |
556 | | - }) |
557 | | - }, |
558 | | - ) |
559 | 500 | .all("/*", async (c) => { |
560 | 501 | const path = c.req.path |
561 | 502 |
|
|
0 commit comments