@@ -26,8 +26,10 @@ import { issueToken } from "../auth/token";
2626import v1Sessions from "../routes/v1/sessions" ;
2727import v1Environments from "../routes/v1/environments" ;
2828import v1EnvironmentsWork from "../routes/v1/environments.work" ;
29+ import v1SessionIngress from "../routes/v1/session-ingress" ;
2930import v2CodeSessions from "../routes/v2/code-sessions" ;
3031import v2Worker from "../routes/v2/worker" ;
32+ import v2WorkerEvents from "../routes/v2/worker-events" ;
3133import webAuth from "../routes/web/auth" ;
3234import webSessions from "../routes/web/sessions" ;
3335import webControl from "../routes/web/control" ;
@@ -38,8 +40,10 @@ function createApp() {
3840 app . route ( "/v1/sessions" , v1Sessions ) ;
3941 app . route ( "/v1/environments" , v1Environments ) ;
4042 app . route ( "/v1/environments" , v1EnvironmentsWork ) ;
43+ app . route ( "/v2/session_ingress" , v1SessionIngress ) ;
4144 app . route ( "/v1/code/sessions" , v2CodeSessions ) ;
4245 app . route ( "/v1/code/sessions" , v2Worker ) ;
46+ app . route ( "/v1/code/sessions" , v2WorkerEvents ) ;
4347 app . route ( "/web" , webAuth ) ;
4448 app . route ( "/web" , webSessions ) ;
4549 app . route ( "/web" , webControl ) ;
@@ -627,3 +631,134 @@ describe("Web Environment Routes", () => {
627631 expect ( res . status ) . toBe ( 401 ) ;
628632 } ) ;
629633} ) ;
634+
635+ describe ( "V1 Session Ingress Routes (HTTP)" , ( ) => {
636+ let app : Hono ;
637+
638+ beforeEach ( ( ) => {
639+ storeReset ( ) ;
640+ for ( const [ key ] of getAllEventBuses ( ) ) {
641+ removeEventBus ( key ) ;
642+ }
643+ process . env . RCS_API_KEYS = "test-api-key" ;
644+ app = createApp ( ) ;
645+ } ) ;
646+
647+ test ( "POST /v2/session_ingress/session/:sessionId/events — ingests events with API key" , async ( ) => {
648+ // Create session first
649+ const sessRes = await app . request ( "/v1/sessions" , {
650+ method : "POST" ,
651+ headers : { ...AUTH_HEADERS , "Content-Type" : "application/json" } ,
652+ body : JSON . stringify ( { } ) ,
653+ } ) ;
654+ const { id } = await sessRes . json ( ) ;
655+
656+ const res = await app . request ( `/v2/session_ingress/session/${ id } /events` , {
657+ method : "POST" ,
658+ headers : { ...AUTH_HEADERS , "Content-Type" : "application/json" } ,
659+ body : JSON . stringify ( { events : [ { type : "assistant" , content : "response" } ] } ) ,
660+ } ) ;
661+ expect ( res . status ) . toBe ( 200 ) ;
662+ const body = await res . json ( ) ;
663+ expect ( body . status ) . toBe ( "ok" ) ;
664+ } ) ;
665+
666+ test ( "POST /v2/session_ingress/session/:sessionId/events — rejects without auth" , async ( ) => {
667+ const res = await app . request ( "/v2/session_ingress/session/nope/events" , {
668+ method : "POST" ,
669+ headers : { "Content-Type" : "application/json" } ,
670+ body : JSON . stringify ( { events : [ ] } ) ,
671+ } ) ;
672+ expect ( res . status ) . toBe ( 401 ) ;
673+ } ) ;
674+
675+ test ( "POST /v2/session_ingress/session/:sessionId/events — 404 for unknown session" , async ( ) => {
676+ const res = await app . request ( "/v2/session_ingress/session/nope/events" , {
677+ method : "POST" ,
678+ headers : { ...AUTH_HEADERS , "Content-Type" : "application/json" } ,
679+ body : JSON . stringify ( { events : [ { type : "user" , content : "hi" } ] } ) ,
680+ } ) ;
681+ expect ( res . status ) . toBe ( 404 ) ;
682+ } ) ;
683+ } ) ;
684+
685+ describe ( "V2 Worker Events Routes" , ( ) => {
686+ let app : Hono ;
687+
688+ beforeEach ( ( ) => {
689+ storeReset ( ) ;
690+ for ( const [ key ] of getAllEventBuses ( ) ) {
691+ removeEventBus ( key ) ;
692+ }
693+ process . env . RCS_API_KEYS = "test-api-key" ;
694+ app = createApp ( ) ;
695+ } ) ;
696+
697+ test ( "POST /v1/code/sessions/:id/worker/events — publishes worker events" , async ( ) => {
698+ // Create session
699+ const sessRes = await app . request ( "/v1/sessions" , {
700+ method : "POST" ,
701+ headers : { ...AUTH_HEADERS , "Content-Type" : "application/json" } ,
702+ body : JSON . stringify ( { } ) ,
703+ } ) ;
704+ const { id } = await sessRes . json ( ) ;
705+
706+ const res = await app . request ( `/v1/code/sessions/${ id } /worker/events` , {
707+ method : "POST" ,
708+ headers : { ...AUTH_HEADERS , "Content-Type" : "application/json" } ,
709+ body : JSON . stringify ( [ { type : "assistant" , content : "response" } ] ) ,
710+ } ) ;
711+ expect ( res . status ) . toBe ( 200 ) ;
712+ const body = await res . json ( ) ;
713+ expect ( body . status ) . toBe ( "ok" ) ;
714+ expect ( body . count ) . toBe ( 1 ) ;
715+ } ) ;
716+
717+ test ( "PUT /v1/code/sessions/:id/worker/state — updates session status" , async ( ) => {
718+ const sessRes = await app . request ( "/v1/sessions" , {
719+ method : "POST" ,
720+ headers : { ...AUTH_HEADERS , "Content-Type" : "application/json" } ,
721+ body : JSON . stringify ( { } ) ,
722+ } ) ;
723+ const { id } = await sessRes . json ( ) ;
724+
725+ const res = await app . request ( `/v1/code/sessions/${ id } /worker/state` , {
726+ method : "PUT" ,
727+ headers : { ...AUTH_HEADERS , "Content-Type" : "application/json" } ,
728+ body : JSON . stringify ( { status : "running" } ) ,
729+ } ) ;
730+ expect ( res . status ) . toBe ( 200 ) ;
731+ } ) ;
732+
733+ test ( "PUT /v1/code/sessions/:id/worker/external_metadata — no-op" , async ( ) => {
734+ const sessRes = await app . request ( "/v1/sessions" , {
735+ method : "POST" ,
736+ headers : { ...AUTH_HEADERS , "Content-Type" : "application/json" } ,
737+ body : JSON . stringify ( { } ) ,
738+ } ) ;
739+ const { id } = await sessRes . json ( ) ;
740+
741+ const res = await app . request ( `/v1/code/sessions/${ id } /worker/external_metadata` , {
742+ method : "PUT" ,
743+ headers : { ...AUTH_HEADERS , "Content-Type" : "application/json" } ,
744+ body : JSON . stringify ( { meta : "data" } ) ,
745+ } ) ;
746+ expect ( res . status ) . toBe ( 200 ) ;
747+ } ) ;
748+
749+ test ( "POST /v1/code/sessions/:id/worker/events/:eventId/delivery — no-op" , async ( ) => {
750+ const sessRes = await app . request ( "/v1/sessions" , {
751+ method : "POST" ,
752+ headers : { ...AUTH_HEADERS , "Content-Type" : "application/json" } ,
753+ body : JSON . stringify ( { } ) ,
754+ } ) ;
755+ const { id } = await sessRes . json ( ) ;
756+
757+ const res = await app . request ( `/v1/code/sessions/${ id } /worker/events/evt123/delivery` , {
758+ method : "POST" ,
759+ headers : { ...AUTH_HEADERS , "Content-Type" : "application/json" } ,
760+ body : JSON . stringify ( { status : "received" } ) ,
761+ } ) ;
762+ expect ( res . status ) . toBe ( 200 ) ;
763+ } ) ;
764+ } ) ;
0 commit comments