1- import { describe , expect , it , vi } from "vitest" ;
1+ import { afterEach , describe , expect , it , vi } from "vitest" ;
2+ import { clearRuntimeConfigSnapshot , setRuntimeConfigSnapshot } from "../../config/config.js" ;
23import type { OpenClawConfig } from "../../config/types.openclaw.js" ;
34import { OutboundDeliveryError } from "../../infra/outbound/deliver-types.js" ;
45import type { OutboundPayloadDeliveryOutcome } from "../../infra/outbound/deliver-types.js" ;
@@ -25,6 +26,7 @@ type DeliveryIntentCallbackParams = {
2526
2627type DeliveryRequest = DeliveryIntentCallbackParams & {
2728 abortSignal ?: AbortSignal ;
29+ cfg ?: OpenClawConfig ;
2830 payloads ?: unknown ;
2931 queuePolicy ?: string ;
3032 replyToId ?: string ;
@@ -33,6 +35,10 @@ type DeliveryRequest = DeliveryIntentCallbackParams & {
3335
3436const cfg = { } as OpenClawConfig ;
3537
38+ afterEach ( ( ) => {
39+ clearRuntimeConfigSnapshot ( ) ;
40+ } ) ;
41+
3642function requireMockCall (
3743 mock : { mock : { calls : unknown [ ] [ ] } } ,
3844 callIndex : number ,
@@ -64,6 +70,43 @@ function expectBatchStatus<TStatus extends DurableMessageBatchSendResult["status
6470}
6571
6672describe ( "withDurableMessageSendContext" , ( ) => {
73+ it ( "preserves explicit configs when a runtime snapshot has no source snapshot" , async ( ) => {
74+ const explicitCfg = { channels : { telegram : { enabled : true } } } ;
75+ const runtimeCfg = { channels : { telegram : { enabled : false } } } ;
76+ setRuntimeConfigSnapshot ( runtimeCfg as OpenClawConfig ) ;
77+ deliverOutboundPayloads . mockResolvedValueOnce ( [ { channel : "telegram" , messageId : "msg-1" } ] ) ;
78+
79+ const result = await sendDurableMessageBatch ( {
80+ cfg : explicitCfg as OpenClawConfig ,
81+ channel : "telegram" ,
82+ to : "chat-1" ,
83+ payloads : [ { text : "hello" } ] ,
84+ } ) ;
85+
86+ expectBatchStatus ( result , "sent" ) ;
87+ expect ( latestDeliveryRequest ( ) . cfg ) . toBe ( explicitCfg ) ;
88+ } ) ;
89+
90+ it ( "upgrades source-shaped configs to the active runtime snapshot" , async ( ) => {
91+ const resolvedCredential = "resolved-runtime-credential" ;
92+ const sourceCfg = {
93+ channels : { telegram : { token : { source : "env" , provider : "default" , id : "TG_TOKEN" } } } ,
94+ } ;
95+ const runtimeCfg = { channels : { telegram : { token : resolvedCredential } } } ;
96+ setRuntimeConfigSnapshot ( runtimeCfg as OpenClawConfig , sourceCfg as unknown as OpenClawConfig ) ;
97+ deliverOutboundPayloads . mockResolvedValueOnce ( [ { channel : "telegram" , messageId : "msg-1" } ] ) ;
98+
99+ const result = await sendDurableMessageBatch ( {
100+ cfg : sourceCfg as unknown as OpenClawConfig ,
101+ channel : "telegram" ,
102+ to : "chat-1" ,
103+ payloads : [ { text : "hello" } ] ,
104+ } ) ;
105+
106+ expectBatchStatus ( result , "sent" ) ;
107+ expect ( latestDeliveryRequest ( ) . cfg ) . toBe ( runtimeCfg ) ;
108+ } ) ;
109+
67110 it ( "renders and sends through a durable send context" , async ( ) => {
68111 deliverOutboundPayloads . mockImplementationOnce ( async ( params : DeliveryIntentCallbackParams ) => {
69112 params . onDeliveryIntent ?.( {
0 commit comments