@@ -2072,6 +2072,76 @@ describe("sessions tools", () => {
20722072 expect ( calls . some ( ( call ) => call . method === "send" ) ) . toBe ( false ) ;
20732073 } ) ;
20742074
2075+ it . each ( [
2076+ {
2077+ name : "top-level channel" ,
2078+ entry : { channel : "discord" , lastChannel : "discord" } ,
2079+ expectedChannel : "discord" ,
2080+ } ,
2081+ {
2082+ name : "deliveryContext.channel (top-level channel is webchat)" ,
2083+ entry : { channel : "webchat" , deliveryContext : { channel : "telegram" , to : "group:chat" } } ,
2084+ expectedChannel : "telegram" ,
2085+ } ,
2086+ {
2087+ name : "lastChannel (top-level channel is empty)" ,
2088+ entry : { channel : "" , lastChannel : "slack" , lastTo : "channel:general" } ,
2089+ expectedChannel : "slack" ,
2090+ } ,
2091+ {
2092+ name : "channel in route metadata" ,
2093+ entry : { channel : "webchat" , route : { channel : "discord" , target : { to : "channel:dev" } } } ,
2094+ expectedChannel : "discord" ,
2095+ } ,
2096+ {
2097+ name : "no routable channel falls back to webchat" ,
2098+ entry : { } ,
2099+ expectedChannel : "webchat" ,
2100+ } ,
2101+ ] ) (
2102+ "sessions_send uses deliveryContextFromSession for initial agent call channel — $name" ,
2103+ async ( { entry, expectedChannel } ) => {
2104+ const calls : Array < { method ?: string ; params ?: unknown } > = [ ] ;
2105+ const targetKey = "agent:main:worker" ;
2106+ loadSessionEntryByKeyMock . mockImplementation ( ( sessionKey : string ) =>
2107+ sessionKey === targetKey ? entry : undefined ,
2108+ ) ;
2109+ callGatewayMock . mockImplementation ( async ( opts : unknown ) => {
2110+ const request = opts as { method ?: string ; params ?: unknown } ;
2111+ calls . push ( request ) ;
2112+ if ( request . method === "agent" ) {
2113+ return { runId : "regression-run" , status : "accepted" , acceptedAt : 2000 } ;
2114+ }
2115+ return { } ;
2116+ } ) ;
2117+
2118+ const tool = createOpenClawTools ( {
2119+ agentSessionKey : "discord:group:req" ,
2120+ agentChannel : "discord" ,
2121+ config : {
2122+ ...TEST_CONFIG ,
2123+ session : {
2124+ ...TEST_CONFIG . session ,
2125+ agentToAgent : { maxPingPongTurns : 0 } ,
2126+ } ,
2127+ } ,
2128+ } ) . find ( ( candidate ) => candidate . name === "sessions_send" ) ;
2129+ if ( ! tool ) {
2130+ throw new Error ( "missing sessions_send tool" ) ;
2131+ }
2132+
2133+ await tool . execute ( "regression-delivery-context-channel" , {
2134+ sessionKey : targetKey ,
2135+ message : "verify delivery context channel resolution" ,
2136+ timeoutSeconds : 0 ,
2137+ } ) ;
2138+
2139+ const agentCalls = calls . filter ( ( call ) => call . method === "agent" ) ;
2140+ expect ( agentCalls ) . toHaveLength ( 1 ) ;
2141+ expect ( agentParams ( agentCalls [ 0 ] ?? { } ) . channel ) . toBe ( expectedChannel ) ;
2142+ } ,
2143+ ) ;
2144+
20752145 it ( "sessions_send preserves threadId when announce target is hydrated via sessions.list" , async ( ) => {
20762146 const calls : Array < { method ?: string ; params ?: unknown } > = [ ] ;
20772147 let agentCallCount = 0 ;
0 commit comments