import { Hono } from 'hono' import { sessionIngressAuth, acceptCliHeaders } from '../../auth/middleware' import { publishSessionEvent } from '../../services/transport' import { getSession, touchSession, updateSessionStatus, } from '../../services/session' const app = new Hono() function extractWorkerEvents(body: unknown): Array> { if (!body || typeof body !== 'object') { return [] } const payload = body as Record const rawEvents = Array.isArray(payload.events) ? payload.events : Array.isArray(body) ? body : [body] return rawEvents .filter( (evt): evt is Record => !!evt && typeof evt === 'object', ) .map(evt => { const wrappedPayload = evt.payload if ( wrappedPayload && typeof wrappedPayload === 'object' && !Array.isArray(wrappedPayload) ) { return wrappedPayload as Record } return evt }) } /** POST /v1/code/sessions/:id/worker/events — Write events */ app.post( '/:id/worker/events', acceptCliHeaders, sessionIngressAuth, async c => { const sessionId = c.req.param('id')! if (!getSession(sessionId)) { return c.json( { error: { type: 'not_found', message: 'Session not found' } }, 404, ) } const body = await c.req.json() const events = extractWorkerEvents(body) const published = [] for (const evt of events) { const eventType = typeof evt.type === 'string' ? evt.type : 'message' const result = publishSessionEvent(sessionId, eventType, evt, 'inbound') published.push(result) } touchSession(sessionId) return c.json({ status: 'ok', count: published.length }, 200) }, ) /** PUT /v1/code/sessions/:id/worker/state — Report worker state */ app.put('/:id/worker/state', acceptCliHeaders, sessionIngressAuth, async c => { const sessionId = c.req.param('id')! if (!getSession(sessionId)) { return c.json( { error: { type: 'not_found', message: 'Session not found' } }, 404, ) } const body = await c.req.json() if (body.status) { updateSessionStatus(sessionId, body.status) } else { touchSession(sessionId) } return c.json({ status: 'ok' }, 200) }) /** PUT /v1/code/sessions/:id/worker/external_metadata — Report worker metadata (no-op) */ app.put( '/:id/worker/external_metadata', acceptCliHeaders, sessionIngressAuth, async c => { const sessionId = c.req.param('id')! if (!getSession(sessionId)) { return c.json( { error: { type: 'not_found', message: 'Session not found' } }, 404, ) } // TUI's CCRClient calls this for metadata reporting. Accept and discard. return c.json({ status: 'ok' }, 200) }, ) /** POST /v1/code/sessions/:id/worker/events/delivery — Batch delivery tracking (no-op) */ app.post( '/:id/worker/events/delivery', acceptCliHeaders, sessionIngressAuth, async c => { const sessionId = c.req.param('id')! if (!getSession(sessionId)) { return c.json( { error: { type: 'not_found', message: 'Session not found' } }, 404, ) } return c.json({ status: 'ok' }, 200) }, ) /** POST /v1/code/sessions/:id/worker/events/:eventId/delivery — Delivery tracking (no-op) */ app.post( '/:id/worker/events/:eventId/delivery', acceptCliHeaders, sessionIngressAuth, async c => { const sessionId = c.req.param('id')! if (!getSession(sessionId)) { return c.json( { error: { type: 'not_found', message: 'Session not found' } }, 404, ) } // TUI's CCRClient reports event delivery status (received/processing/processed). // Accept and discard — event bus doesn't track per-event delivery. return c.json({ status: 'ok' }, 200) }, ) export default app