package main import ( "context" "git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/model" ) // streamSubject is the bus subject the loop's OnStream closure publishes each // structured stream event to. The gateway hub subscribes to ws.> and carries a // dedicated branch for this subject that maps the model.StreamEvent to the typed // downstream WS event (message.*/thinking.*/tool_call.*) with a seq number. // // It MUST stay in sync with wsStreamSubject in internal/services/gateway/ws_hub.go; // the two packages cannot share a const without pulling the gateway into the // main binary's import graph, so the literal is duplicated and documented. const streamSubject = "ws.stream" // streamChunk is the loop's OnStream callback. It publishes one structured // stream event to the gateway's streaming subject so the hub fans it out to // every client as the matching typed WS event. It is a no-op when no bus is // wired and never blocks the loop: bus.Publish is asynchronous and a full // per-subscription buffer drops the event rather than stalling the model stream. func (a *app) streamChunk(ev model.StreamEvent) { if a.bus == nil { return } if err := a.bus.Publish(context.Background(), streamSubject, ev); err != nil { a.log.Warn("stream event publish", "err", err) } }