@@ -367,6 +367,46 @@ func (s *bridgeSessionStoreStub) UpdateSessionState(ctx context.Context, input a
367367 return nil
368368}
369369
370+ type boundaryRuntimeStub struct {
371+ * runtimeStub
372+ deletedSessionID string
373+ renamedSessionID string
374+ renamedTitle string
375+ modelSessionID string
376+ modelProviderID string
377+ modelID string
378+ syncProviderID string
379+ syncModelID string
380+ }
381+
382+ func (s * boundaryRuntimeStub ) SupportsSessionMutationBoundary () bool {
383+ return true
384+ }
385+
386+ func (s * boundaryRuntimeStub ) DeleteSession (_ context.Context , sessionID string ) error {
387+ s .deletedSessionID = sessionID
388+ return nil
389+ }
390+
391+ func (s * boundaryRuntimeStub ) RenameSession (_ context.Context , sessionID string , title string ) error {
392+ s .renamedSessionID = sessionID
393+ s .renamedTitle = title
394+ return nil
395+ }
396+
397+ func (s * boundaryRuntimeStub ) UpdateSessionModel (_ context.Context , sessionID string , providerID string , modelID string ) error {
398+ s .modelSessionID = sessionID
399+ s .modelProviderID = providerID
400+ s .modelID = modelID
401+ return nil
402+ }
403+
404+ func (s * boundaryRuntimeStub ) SyncSessionsProviderModel (_ context.Context , providerID string , modelID string ) error {
405+ s .syncProviderID = providerID
406+ s .syncModelID = modelID
407+ return nil
408+ }
409+
370410func TestGatewayRuntimePortBridgeCheckpointOperations (t * testing.T ) {
371411 stub := & runtimeStub {
372412 listCheckpointsResult : []agentsession.CheckpointRecord {
@@ -1496,6 +1536,32 @@ func TestGatewayRuntimePortBridgeDeleteSession(t *testing.T) {
14961536 })
14971537}
14981538
1539+ func TestGatewayRuntimePortBridgeDeleteSessionUsesRuntimeBoundary (t * testing.T ) {
1540+ store := & bridgeSessionStoreStub {
1541+ deleteFn : func (_ context.Context , _ string ) error {
1542+ t .Fatalf ("DeleteSession should use runtime boundary instead of direct store write" )
1543+ return nil
1544+ },
1545+ }
1546+ stub := & boundaryRuntimeStub {runtimeStub : & runtimeStub {eventsCh : make (chan agentruntime.RuntimeEvent , 1 )}}
1547+ bridge , err := newGatewayRuntimePortBridge (context .Background (), stub , store )
1548+ if err != nil {
1549+ t .Fatalf ("new bridge: %v" , err )
1550+ }
1551+ defer bridge .Close ()
1552+
1553+ deleted , err := bridge .DeleteSession (context .Background (), gateway.DeleteSessionInput {
1554+ SubjectID : testBridgeSubjectID ,
1555+ SessionID : " session-1 " ,
1556+ })
1557+ if err != nil {
1558+ t .Fatalf ("DeleteSession() error = %v" , err )
1559+ }
1560+ if ! deleted || stub .deletedSessionID != "session-1" {
1561+ t .Fatalf ("deleted=%v runtimeID=%q" , deleted , stub .deletedSessionID )
1562+ }
1563+ }
1564+
14991565func TestGatewayRuntimePortBridgeRenameSession (t * testing.T ) {
15001566 t .Run ("success" , func (t * testing.T ) {
15011567 store := & bridgeSessionStoreStub {
@@ -1564,6 +1630,32 @@ func TestGatewayRuntimePortBridgeRenameSession(t *testing.T) {
15641630 })
15651631}
15661632
1633+ func TestGatewayRuntimePortBridgeRenameSessionUsesRuntimeBoundary (t * testing.T ) {
1634+ store := & bridgeSessionStoreStub {
1635+ updateFn : func (_ context.Context , _ agentsession.UpdateSessionStateInput ) error {
1636+ t .Fatalf ("RenameSession should use runtime boundary instead of direct store write" )
1637+ return nil
1638+ },
1639+ }
1640+ stub := & boundaryRuntimeStub {runtimeStub : & runtimeStub {eventsCh : make (chan agentruntime.RuntimeEvent , 1 )}}
1641+ bridge , err := newGatewayRuntimePortBridge (context .Background (), stub , store )
1642+ if err != nil {
1643+ t .Fatalf ("new bridge: %v" , err )
1644+ }
1645+ defer bridge .Close ()
1646+
1647+ if err := bridge .RenameSession (context .Background (), gateway.RenameSessionInput {
1648+ SubjectID : testBridgeSubjectID ,
1649+ SessionID : " session-1 " ,
1650+ Title : " New Title " ,
1651+ }); err != nil {
1652+ t .Fatalf ("RenameSession() error = %v" , err )
1653+ }
1654+ if stub .renamedSessionID != "session-1" || stub .renamedTitle != "New Title" {
1655+ t .Fatalf ("runtime rename = (%q, %q)" , stub .renamedSessionID , stub .renamedTitle )
1656+ }
1657+ }
1658+
15671659// ---- providerSelection stub ----
15681660
15691661type providerSelectionStub struct {
@@ -2099,6 +2191,58 @@ func TestGatewayRuntimePortBridgeSetSessionModelProviderInference(t *testing.T)
20992191 }
21002192}
21012193
2194+ func TestGatewayRuntimePortBridgeSetSessionModelUsesRuntimeBoundary (t * testing.T ) {
2195+ store := & bridgeSessionStoreWithLoader {
2196+ bridgeSessionStoreStub : bridgeSessionStoreStub {
2197+ updateFn : func (_ context.Context , _ agentsession.UpdateSessionStateInput ) error {
2198+ t .Fatalf ("SetSessionModel should use runtime boundary instead of direct store write" )
2199+ return nil
2200+ },
2201+ },
2202+ session : agentsession.Session {ID : "s-1" , Provider : "" , Model : "" },
2203+ }
2204+ ps := & providerSelectionStub {
2205+ listOptions : []configstate.ProviderOption {
2206+ {ID : "openai" , Models : []providertypes.ModelDescriptor {{ID : "gpt-4" , Name : "GPT-4" }}},
2207+ },
2208+ }
2209+ stub := & boundaryRuntimeStub {runtimeStub : & runtimeStub {eventsCh : make (chan agentruntime.RuntimeEvent , 1 )}}
2210+ bridge , _ := newGatewayRuntimePortBridge (context .Background (), stub , store , nil , ps )
2211+ defer bridge .Close ()
2212+
2213+ if err := bridge .SetSessionModel (context .Background (), gateway.SetSessionModelInput {
2214+ SubjectID : testBridgeSubjectID ,
2215+ SessionID : "s-1" ,
2216+ ModelID : "gpt-4" ,
2217+ }); err != nil {
2218+ t .Fatalf ("SetSessionModel() error = %v" , err )
2219+ }
2220+ if stub .modelSessionID != "s-1" || stub .modelProviderID != "openai" || stub .modelID != "gpt-4" {
2221+ t .Fatalf ("runtime model update = (%q, %q, %q)" , stub .modelSessionID , stub .modelProviderID , stub .modelID )
2222+ }
2223+ }
2224+
2225+ func TestGatewayRuntimePortBridgeSyncSessionsProviderModelUsesRuntimeBoundary (t * testing.T ) {
2226+ store := & bridgeSessionStoreWithLoader {
2227+ bridgeSessionStoreStub : bridgeSessionStoreStub {
2228+ updateFn : func (_ context.Context , _ agentsession.UpdateSessionStateInput ) error {
2229+ t .Fatalf ("SyncSessionsProviderModel should use runtime boundary instead of direct store write" )
2230+ return nil
2231+ },
2232+ },
2233+ }
2234+ stub := & boundaryRuntimeStub {runtimeStub : & runtimeStub {eventsCh : make (chan agentruntime.RuntimeEvent , 1 )}}
2235+ bridge , _ := newGatewayRuntimePortBridge (context .Background (), stub , store )
2236+ defer bridge .Close ()
2237+
2238+ if err := bridge .SyncSessionsProviderModel (context .Background (), " openai " , " gpt-4 " ); err != nil {
2239+ t .Fatalf ("SyncSessionsProviderModel() error = %v" , err )
2240+ }
2241+ if stub .syncProviderID != "openai" || stub .syncModelID != "gpt-4" {
2242+ t .Fatalf ("runtime sync = (%q, %q)" , stub .syncProviderID , stub .syncModelID )
2243+ }
2244+ }
2245+
21022246func TestGatewayRuntimePortBridgeSetSessionModelNotFound (t * testing.T ) {
21032247 store := & bridgeSessionStoreWithLoader {
21042248 session : agentsession.Session {ID : "s-1" , Provider : "openai" , Model : "" },
0 commit comments