feat(backend): wire terminal manager into the daemon at /mux
Construct the tmux runtime and a terminal.Manager fed by the CDC broadcaster, and hand it to httpd.New so the /mux WebSocket surface goes live. httpd.New now runs after the CDC substrate so the broadcaster exists when the manager subscribes; the listener still binds before running.json is written, preserving fail-fast on port conflict. The manager is closed on shutdown alongside the CDC pipeline and lifecycle stack.
This commit is contained in:
parent
edcc631037
commit
4d90d59bf0
|
|
@ -284,9 +284,9 @@ func (c *connState) handleSubscribe() {
|
|||
Type: msgSnapshot,
|
||||
Session: &sessionUpdate{
|
||||
Seq: e.Seq,
|
||||
ProjectID: e.ProjectID,
|
||||
SessionID: e.SessionID,
|
||||
EventType: e.EventType,
|
||||
Revision: e.Revision,
|
||||
EventType: string(e.Type),
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ func TestServeForwardsSessionChannelFromCDC(t *testing.T) {
|
|||
conn.in <- clientMsg{Ch: chSubscribe, Type: msgSubscribe}
|
||||
// Give the subscription time to register before publishing.
|
||||
eventually(t, time.Second, func() bool {
|
||||
bc.Publish(cdc.Event{Seq: 9, SessionID: "s1", EventType: "session_updated", Revision: 4})
|
||||
bc.Publish(cdc.Event{Seq: 9, ProjectID: "p1", SessionID: "s1", Type: cdc.EventSessionUpdated})
|
||||
select {
|
||||
case m := <-conn.out:
|
||||
return m.Ch == chSessions && m.Session != nil && m.Session.Seq == 9
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ type serverMsg struct {
|
|||
// change_log payload blob; the client refetches detail over the REST surface.
|
||||
type sessionUpdate struct {
|
||||
Seq int64 `json:"seq"`
|
||||
SessionID string `json:"sessionId"`
|
||||
ProjectID string `json:"projectId"`
|
||||
SessionID string `json:"sessionId,omitempty"`
|
||||
EventType string `json:"eventType"`
|
||||
Revision int64 `json:"revision"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ func TestServerMsgSessionFrameWireShape(t *testing.T) {
|
|||
Ch: chSessions,
|
||||
Type: msgSnapshot,
|
||||
Session: &sessionUpdate{
|
||||
Seq: 7, SessionID: "s1", EventType: "session_updated", Revision: 3,
|
||||
Seq: 7, ProjectID: "p1", SessionID: "s1", EventType: "session_updated",
|
||||
},
|
||||
}
|
||||
raw, err := json.Marshal(msg)
|
||||
|
|
@ -41,7 +41,7 @@ func TestServerMsgSessionFrameWireShape(t *testing.T) {
|
|||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
// Golden wire shape the client depends on.
|
||||
want := `{"ch":"sessions","type":"snapshot","session":{"seq":7,"sessionId":"s1","eventType":"session_updated","revision":3}}`
|
||||
want := `{"ch":"sessions","type":"snapshot","session":{"seq":7,"projectId":"p1","sessionId":"s1","eventType":"session_updated"}}`
|
||||
if string(raw) != want {
|
||||
t.Fatalf("wire shape:\n got %s\nwant %s", raw, want)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,10 +12,12 @@ import (
|
|||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/aoagents/agent-orchestrator/backend/internal/adapters/runtime/tmux"
|
||||
"github.com/aoagents/agent-orchestrator/backend/internal/config"
|
||||
"github.com/aoagents/agent-orchestrator/backend/internal/httpd"
|
||||
"github.com/aoagents/agent-orchestrator/backend/internal/runfile"
|
||||
"github.com/aoagents/agent-orchestrator/backend/internal/storage/sqlite"
|
||||
"github.com/aoagents/agent-orchestrator/backend/internal/terminal"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
@ -42,11 +44,6 @@ func run() error {
|
|||
return fmt.Errorf("daemon already running (pid %d, port %d); refusing to start", live.PID, live.Port)
|
||||
}
|
||||
|
||||
srv, err := httpd.New(cfg, log, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Open the durable store and bring up the CDC substrate: the DB triggers
|
||||
// capture changes into change_log, the poller tails it, and the broadcaster
|
||||
// fans events out to the SSE transport. The LCM/Session Manager and the HTTP
|
||||
|
|
@ -70,6 +67,19 @@ func run() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Terminal streaming: the tmux runtime supplies the PTY-attach command and
|
||||
// liveness; the CDC broadcaster feeds the session-state channel. The manager
|
||||
// is handed to httpd, which mounts it at /mux. Raw PTY bytes never flow
|
||||
// through the CDC change_log — only session-state events do.
|
||||
runtimeAdapter := tmux.New(tmux.Options{})
|
||||
termMgr := terminal.NewManager(runtimeAdapter, cdcPipe.Broadcaster, log)
|
||||
defer termMgr.Close()
|
||||
|
||||
srv, err := httpd.New(cfg, log, termMgr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Bring up the Lifecycle Manager (sole store writer) and the reaper (OBSERVE
|
||||
// timer). This makes the write path live end-to-end: LCM write -> store -> DB
|
||||
// trigger -> change_log -> poller -> broadcaster. The collaborators it needs
|
||||
|
|
|
|||
Loading…
Reference in New Issue