@@ -107,6 +107,11 @@ let resolveTelegramTransport: typeof import("./fetch.js").resolveTelegramTranspo
107107type TelegramDispatcherPolicy = NonNullable <
108108 ReturnType < typeof resolveTelegramTransport > [ "dispatcherAttempts" ]
109109> [ number ] [ "dispatcherPolicy" ] ;
110+ type DirectTelegramDispatcherPolicy = Extract < TelegramDispatcherPolicy , { mode : "direct" } > ;
111+ type ExplicitProxyTelegramDispatcherPolicy = Extract <
112+ TelegramDispatcherPolicy ,
113+ { mode : "explicit-proxy" }
114+ > ;
110115
111116beforeAll ( async ( ) => {
112117 ( { resolveTelegramApiBase, resolveTelegramFetch, resolveTelegramTransport } =
@@ -221,12 +226,9 @@ function expectStickyAutoSelectDispatcher(
221226 | undefined ,
222227 field : "connect" | "proxyTls" | "requestTls" = "connect" ,
223228) : void {
224- expect ( dispatcher ?. options ?. [ field ] ) . toEqual (
225- expect . objectContaining ( {
226- autoSelectFamily : true ,
227- autoSelectFamilyAttemptTimeout : 300 ,
228- } ) ,
229- ) ;
229+ const options = dispatcher ?. options ?. [ field ] ;
230+ expect ( options ?. autoSelectFamily ) . toBe ( true ) ;
231+ expect ( options ?. autoSelectFamilyAttemptTimeout ) . toBe ( 300 ) ;
230232}
231233
232234function expectHttp1OnlyDispatcher (
@@ -238,11 +240,7 @@ function expectHttp1OnlyDispatcher(
238240 }
239241 | undefined ,
240242) : void {
241- expect ( dispatcher ?. options ) . toEqual (
242- expect . objectContaining ( {
243- allowH2 : false ,
244- } ) ,
245- ) ;
243+ expect ( dispatcher ?. options ?. allowH2 ) . toBe ( false ) ;
246244}
247245
248246function expectPinnedIpv4ConnectDispatcher ( args : {
@@ -251,12 +249,8 @@ function expectPinnedIpv4ConnectDispatcher(args: {
251249 followupCall ?: number ;
252250} ) : void {
253251 const pinnedDispatcher = getDispatcherFromUndiciCall ( args . pinnedCall ) ;
254- expect ( pinnedDispatcher ?. options ?. connect ) . toEqual (
255- expect . objectContaining ( {
256- family : 4 ,
257- autoSelectFamily : false ,
258- } ) ,
259- ) ;
252+ expect ( pinnedDispatcher ?. options ?. connect ?. family ) . toBe ( 4 ) ;
253+ expect ( pinnedDispatcher ?. options ?. connect ?. autoSelectFamily ) . toBe ( false ) ;
260254 if ( args . firstCall ) {
261255 expect ( getDispatcherFromUndiciCall ( args . firstCall ) ) . not . toBe ( pinnedDispatcher ) ;
262256 }
@@ -267,13 +261,9 @@ function expectPinnedIpv4ConnectDispatcher(args: {
267261
268262function expectPinnedFallbackIpDispatcher ( callIndex : number ) {
269263 const dispatcher = getDispatcherFromUndiciCall ( callIndex ) ;
270- expect ( dispatcher ?. options ?. connect ) . toEqual (
271- expect . objectContaining ( {
272- family : 4 ,
273- autoSelectFamily : false ,
274- lookup : expect . any ( Function ) ,
275- } ) ,
276- ) ;
264+ expect ( dispatcher ?. options ?. connect ?. family ) . toBe ( 4 ) ;
265+ expect ( dispatcher ?. options ?. connect ?. autoSelectFamily ) . toBe ( false ) ;
266+ expect ( typeof dispatcher ?. options ?. connect ?. lookup ) . toBe ( "function" ) ;
277267 const callback = vi . fn ( ) ;
278268 (
279269 dispatcher ?. options ?. connect ?. lookup as
@@ -368,13 +358,9 @@ describe("resolveTelegramFetch", () => {
368358
369359 const dispatcher = getDispatcherFromUndiciCall ( 1 ) ;
370360 expectHttp1OnlyDispatcher ( dispatcher ) ;
371- expect ( dispatcher ?. options ?. connect ) . toEqual (
372- expect . objectContaining ( {
373- autoSelectFamily : true ,
374- autoSelectFamilyAttemptTimeout : 300 ,
375- lookup : expect . any ( Function ) ,
376- } ) ,
377- ) ;
361+ expect ( dispatcher ?. options ?. connect ?. autoSelectFamily ) . toBe ( true ) ;
362+ expect ( dispatcher ?. options ?. connect ?. autoSelectFamilyAttemptTimeout ) . toBe ( 300 ) ;
363+ expect ( typeof dispatcher ?. options ?. connect ?. lookup ) . toBe ( "function" ) ;
378364 } ) ;
379365
380366 it ( "emits default transport decisions at debug level" , ( ) => {
@@ -400,27 +386,15 @@ describe("resolveTelegramFetch", () => {
400386 await resolved ( "https://api.telegram.org/botx/getMe" ) ;
401387
402388 expect ( EnvHttpProxyAgentCtor ) . toHaveBeenCalledTimes ( 1 ) ;
403- expect ( EnvHttpProxyAgentCtor ) . toHaveBeenCalledWith (
404- expect . objectContaining ( {
405- httpsProxy : "http://127.0.0.1:7890" ,
406- } ) ,
407- ) ;
389+ expect ( EnvHttpProxyAgentCtor . mock . calls [ 0 ] ?. [ 0 ] ?. httpsProxy ) . toBe ( "http://127.0.0.1:7890" ) ;
408390 expect ( AgentCtor ) . not . toHaveBeenCalled ( ) ;
409391
410392 const dispatcher = getDispatcherFromUndiciCall ( 1 ) ;
411393 expectHttp1OnlyDispatcher ( dispatcher ) ;
412- expect ( dispatcher ?. options ?. connect ) . toEqual (
413- expect . objectContaining ( {
414- autoSelectFamily : false ,
415- autoSelectFamilyAttemptTimeout : 300 ,
416- } ) ,
417- ) ;
418- expect ( dispatcher ?. options ?. proxyTls ) . toEqual (
419- expect . objectContaining ( {
420- autoSelectFamily : false ,
421- autoSelectFamilyAttemptTimeout : 300 ,
422- } ) ,
423- ) ;
394+ expect ( dispatcher ?. options ?. connect ?. autoSelectFamily ) . toBe ( false ) ;
395+ expect ( dispatcher ?. options ?. connect ?. autoSelectFamilyAttemptTimeout ) . toBe ( 300 ) ;
396+ expect ( dispatcher ?. options ?. proxyTls ?. autoSelectFamily ) . toBe ( false ) ;
397+ expect ( dispatcher ?. options ?. proxyTls ?. autoSelectFamilyAttemptTimeout ) . toBe ( 300 ) ;
424398 } ) ;
425399
426400 it ( "uses the OpenClaw debug proxy URL when no explicit proxy fetch is provided" , async ( ) => {
@@ -432,12 +406,11 @@ describe("resolveTelegramFetch", () => {
432406 await resolved ( "https://api.telegram.org/botTOKEN/getMe" ) ;
433407
434408 expect ( ProxyAgentCtor ) . toHaveBeenCalledTimes ( 1 ) ;
435- expect ( ProxyAgentCtor ) . toHaveBeenCalledWith (
436- expect . objectContaining ( {
437- allowH2 : false ,
438- uri : "http://127.0.0.1:7777" ,
439- } ) ,
440- ) ;
409+ const proxyOptions = ProxyAgentCtor . mock . calls [ 0 ] ?. [ 0 ] as
410+ | { allowH2 ?: boolean ; uri ?: string }
411+ | undefined ;
412+ expect ( proxyOptions ?. allowH2 ) . toBe ( false ) ;
413+ expect ( proxyOptions ?. uri ) . toBe ( "http://127.0.0.1:7777" ) ;
441414 } ) ;
442415
443416 it ( "uses OPENCLAW_PROXY_URL as a Telegram explicit proxy when proxy env is absent" , async ( ) => {
@@ -454,23 +427,19 @@ describe("resolveTelegramFetch", () => {
454427 await transport . fetch ( "https://api.telegram.org/botTOKEN/getMe" ) ;
455428
456429 expect ( ProxyAgentCtor ) . toHaveBeenCalledTimes ( 1 ) ;
457- expect ( ProxyAgentCtor ) . toHaveBeenCalledWith (
458- expect . objectContaining ( {
459- allowH2 : false ,
460- uri : "http://127.0.0.1:7788" ,
461- requestTls : expect . objectContaining ( {
462- autoSelectFamily : false ,
463- } ) ,
464- } ) ,
465- ) ;
430+ const proxyOptions = ProxyAgentCtor . mock . calls [ 0 ] ?. [ 0 ] as
431+ | { allowH2 ?: boolean ; uri ?: string ; requestTls ?: { autoSelectFamily ?: boolean } }
432+ | undefined ;
433+ expect ( proxyOptions ?. allowH2 ) . toBe ( false ) ;
434+ expect ( proxyOptions ?. uri ) . toBe ( "http://127.0.0.1:7788" ) ;
435+ expect ( proxyOptions ?. requestTls ?. autoSelectFamily ) . toBe ( false ) ;
466436 expect ( EnvHttpProxyAgentCtor ) . not . toHaveBeenCalled ( ) ;
467437 expect ( AgentCtor ) . not . toHaveBeenCalled ( ) ;
468- expect ( transport . dispatcherAttempts ?. [ 0 ] ?. dispatcherPolicy ) . toEqual (
469- expect . objectContaining ( {
470- mode : "explicit-proxy" ,
471- proxyUrl : "http://127.0.0.1:7788" ,
472- } ) ,
473- ) ;
438+ const dispatcherPolicy = transport . dispatcherAttempts ?. [ 0 ] ?. dispatcherPolicy as
439+ | ExplicitProxyTelegramDispatcherPolicy
440+ | undefined ;
441+ expect ( dispatcherPolicy ?. mode ) . toBe ( "explicit-proxy" ) ;
442+ expect ( dispatcherPolicy ?. proxyUrl ) . toBe ( "http://127.0.0.1:7788" ) ;
474443 } ) ;
475444
476445 it ( "preserves caller-provided custom fetch when OPENCLAW_PROXY_URL is present" , async ( ) => {
@@ -529,18 +498,10 @@ describe("resolveTelegramFetch", () => {
529498
530499 const dispatcher = getDispatcherFromUndiciCall ( 1 ) ;
531500 expectHttp1OnlyDispatcher ( dispatcher ) ;
532- expect ( dispatcher ?. options ?. connect ) . toEqual (
533- expect . objectContaining ( {
534- autoSelectFamily : true ,
535- autoSelectFamilyAttemptTimeout : 300 ,
536- } ) ,
537- ) ;
538- expect ( dispatcher ?. options ?. proxyTls ) . toEqual (
539- expect . objectContaining ( {
540- autoSelectFamily : true ,
541- autoSelectFamilyAttemptTimeout : 300 ,
542- } ) ,
543- ) ;
501+ expect ( dispatcher ?. options ?. connect ?. autoSelectFamily ) . toBe ( true ) ;
502+ expect ( dispatcher ?. options ?. connect ?. autoSelectFamilyAttemptTimeout ) . toBe ( 300 ) ;
503+ expect ( dispatcher ?. options ?. proxyTls ?. autoSelectFamily ) . toBe ( true ) ;
504+ expect ( dispatcher ?. options ?. proxyTls ?. autoSelectFamilyAttemptTimeout ) . toBe ( 300 ) ;
544505 } ) ;
545506
546507 it ( "keeps resolver-scoped transport policy for OpenClaw proxy fetches" , async ( ) => {
@@ -563,16 +524,10 @@ describe("resolveTelegramFetch", () => {
563524 expect ( AgentCtor ) . not . toHaveBeenCalled ( ) ;
564525 const dispatcher = getDispatcherFromUndiciCall ( 1 ) ;
565526 expectHttp1OnlyDispatcher ( dispatcher ) ;
566- expect ( dispatcher ?. options ) . toEqual (
567- expect . objectContaining ( {
568- uri : "http://127.0.0.1:7890" ,
569- } ) ,
570- ) ;
571- expect ( dispatcher ?. options ?. requestTls ) . toEqual (
572- expect . objectContaining ( {
573- autoSelectFamily : false ,
574- } ) ,
527+ expect ( ( dispatcher ?. options as { uri ?: string } | undefined ) ?. uri ) . toBe (
528+ "http://127.0.0.1:7890" ,
575529 ) ;
530+ expect ( dispatcher ?. options ?. requestTls ?. autoSelectFamily ) . toBe ( false ) ;
576531 } ) ;
577532
578533 it ( "exports fallback dispatcher attempts for Telegram media downloads" , async ( ) => {
@@ -595,43 +550,28 @@ describe("resolveTelegramFetch", () => {
595550 expect ( transport . dispatcherAttempts ) . toHaveLength ( 3 ) ;
596551
597552 const [ defaultAttempt , ipv4Attempt , pinnedAttempt ] = transport . dispatcherAttempts as Array < {
598- dispatcherPolicy ?: TelegramDispatcherPolicy ;
553+ dispatcherPolicy ?: DirectTelegramDispatcherPolicy ;
599554 } > ;
600555
601- expect ( defaultAttempt . dispatcherPolicy ) . toEqual (
602- expect . objectContaining ( {
603- mode : "direct" ,
604- connect : expect . objectContaining ( {
605- autoSelectFamily : true ,
606- autoSelectFamilyAttemptTimeout : 300 ,
607- lookup : expect . any ( Function ) ,
608- } ) ,
609- } ) ,
610- ) ;
611- expect ( ipv4Attempt . dispatcherPolicy ) . toEqual (
612- expect . objectContaining ( {
613- mode : "direct" ,
614- connect : expect . objectContaining ( {
615- family : 4 ,
616- autoSelectFamily : false ,
617- lookup : expect . any ( Function ) ,
618- } ) ,
619- } ) ,
620- ) ;
621- expect ( pinnedAttempt . dispatcherPolicy ) . toEqual (
622- expect . objectContaining ( {
623- mode : "direct" ,
624- pinnedHostname : {
625- hostname : "api.telegram.org" ,
626- addresses : [ "149.154.167.220" ] ,
627- } ,
628- connect : expect . objectContaining ( {
629- family : 4 ,
630- autoSelectFamily : false ,
631- lookup : expect . any ( Function ) ,
632- } ) ,
633- } ) ,
634- ) ;
556+ const defaultPolicy = defaultAttempt . dispatcherPolicy ;
557+ const ipv4Policy = ipv4Attempt . dispatcherPolicy ;
558+ const pinnedPolicy = pinnedAttempt . dispatcherPolicy ;
559+ expect ( defaultPolicy ?. mode ) . toBe ( "direct" ) ;
560+ expect ( defaultPolicy ?. connect ?. autoSelectFamily ) . toBe ( true ) ;
561+ expect ( defaultPolicy ?. connect ?. autoSelectFamilyAttemptTimeout ) . toBe ( 300 ) ;
562+ expect ( typeof defaultPolicy ?. connect ?. lookup ) . toBe ( "function" ) ;
563+ expect ( ipv4Policy ?. mode ) . toBe ( "direct" ) ;
564+ expect ( ipv4Policy ?. connect ?. family ) . toBe ( 4 ) ;
565+ expect ( ipv4Policy ?. connect ?. autoSelectFamily ) . toBe ( false ) ;
566+ expect ( typeof ipv4Policy ?. connect ?. lookup ) . toBe ( "function" ) ;
567+ expect ( pinnedPolicy ?. mode ) . toBe ( "direct" ) ;
568+ expect ( pinnedPolicy ?. pinnedHostname ) . toEqual ( {
569+ hostname : "api.telegram.org" ,
570+ addresses : [ "149.154.167.220" ] ,
571+ } ) ;
572+ expect ( pinnedPolicy ?. connect ?. family ) . toBe ( 4 ) ;
573+ expect ( pinnedPolicy ?. connect ?. autoSelectFamily ) . toBe ( false ) ;
574+ expect ( typeof pinnedPolicy ?. connect ?. lookup ) . toBe ( "function" ) ;
635575 } ) ;
636576
637577 it ( "does not blind-retry when sticky IPv4 fallback is disallowed for explicit proxy paths" , async ( ) => {
@@ -688,20 +628,13 @@ describe("resolveTelegramFetch", () => {
688628 await resolved ( "https://api.telegram.org/botx/sendMessage" ) ;
689629
690630 expect ( EnvHttpProxyAgentCtor ) . toHaveBeenCalledTimes ( 1 ) ;
691- expect ( EnvHttpProxyAgentCtor ) . toHaveBeenCalledWith (
692- expect . objectContaining ( {
693- allowH2 : false ,
694- httpProxy : "http://127.0.0.1:7891" ,
695- httpsProxy : "http://127.0.0.1:7891" ,
696- } ) ,
697- ) ;
631+ const proxyOptions = EnvHttpProxyAgentCtor . mock . calls [ 0 ] ?. [ 0 ] ;
632+ expect ( proxyOptions ?. allowH2 ) . toBe ( false ) ;
633+ expect ( proxyOptions ?. httpProxy ) . toBe ( "http://127.0.0.1:7891" ) ;
634+ expect ( proxyOptions ?. httpsProxy ) . toBe ( "http://127.0.0.1:7891" ) ;
698635 expect ( AgentCtor ) . not . toHaveBeenCalled ( ) ;
699636
700- expect ( transport . dispatcherAttempts ?. [ 0 ] ?. dispatcherPolicy ) . toEqual (
701- expect . objectContaining ( {
702- mode : "env-proxy" ,
703- } ) ,
704- ) ;
637+ expect ( transport . dispatcherAttempts ?. [ 0 ] ?. dispatcherPolicy ?. mode ) . toBe ( "env-proxy" ) ;
705638 } ) ;
706639
707640 it ( "arms sticky IPv4 fallback when env proxy init falls back to direct Agent" , async ( ) => {
@@ -794,11 +727,7 @@ describe("resolveTelegramFetch", () => {
794727 expect ( AgentCtor ) . toHaveBeenCalledTimes ( 1 ) ;
795728
796729 const dispatcher = getDispatcherFromUndiciCall ( 1 ) ;
797- expect ( dispatcher ?. options ?. connect ) . toEqual (
798- expect . objectContaining ( {
799- autoSelectFamily : false ,
800- } ) ,
801- ) ;
730+ expect ( dispatcher ?. options ?. connect ?. autoSelectFamily ) . toBe ( false ) ;
802731 } ) ;
803732
804733 it ( "retries once, keeps sticky IPv4, then recovers to primary dispatcher" , async ( ) => {
@@ -834,12 +763,8 @@ describe("resolveTelegramFetch", () => {
834763 expect ( eighthDispatcher ) . toBe ( firstDispatcher ) ;
835764
836765 expectStickyAutoSelectDispatcher ( firstDispatcher ) ;
837- expect ( secondDispatcher ?. options ?. connect ) . toEqual (
838- expect . objectContaining ( {
839- family : 4 ,
840- autoSelectFamily : false ,
841- } ) ,
842- ) ;
766+ expect ( secondDispatcher ?. options ?. connect ?. family ) . toBe ( 4 ) ;
767+ expect ( secondDispatcher ?. options ?. connect ?. autoSelectFamily ) . toBe ( false ) ;
843768 expect ( loggerDebug ) . toHaveBeenCalledWith (
844769 expect . stringContaining ( "fetch fallback: enabling sticky IPv4-only dispatcher" ) ,
845770 ) ;
@@ -1101,16 +1026,8 @@ describe("resolveTelegramFetch", () => {
11011026
11021027 expect ( dispatcherA ) . not . toBe ( dispatcherB ) ;
11031028
1104- expect ( dispatcherA ?. options ?. connect ) . toEqual (
1105- expect . objectContaining ( {
1106- autoSelectFamily : false ,
1107- } ) ,
1108- ) ;
1109- expect ( dispatcherB ?. options ?. connect ) . toEqual (
1110- expect . objectContaining ( {
1111- autoSelectFamily : true ,
1112- } ) ,
1113- ) ;
1029+ expect ( dispatcherA ?. options ?. connect ?. autoSelectFamily ) . toBe ( false ) ;
1030+ expect ( dispatcherB ?. options ?. connect ?. autoSelectFamily ) . toBe ( true ) ;
11141031
11151032 // Core guarantee: Telegram transport no longer mutates process-global defaults.
11161033 expect ( setGlobalDispatcher ) . not . toHaveBeenCalled ( ) ;
@@ -1130,15 +1047,16 @@ describe("resolveTelegramFetch", () => {
11301047 // One direct Agent for the default dispatcher plus two lazy fallbacks not yet touched.
11311048 expect ( AgentCtor ) . toHaveBeenCalledTimes ( 1 ) ;
11321049 const defaultAgent = AgentCtor . mock . instances [ 0 ] ?. options ;
1133- expect ( defaultAgent ) . toEqual (
1134- expect . objectContaining ( {
1135- allowH2 : false ,
1136- keepAliveTimeout : expect . any ( Number ) ,
1137- keepAliveMaxTimeout : expect . any ( Number ) ,
1138- connections : expect . any ( Number ) ,
1139- pipelining : expect . any ( Number ) ,
1140- } ) ,
1050+ expect ( typeof defaultAgent ) . toBe ( "object" ) ;
1051+ expect ( ( defaultAgent as { allowH2 ?: boolean } | undefined ) ?. allowH2 ) . toBe ( false ) ;
1052+ expect ( typeof ( defaultAgent as { keepAliveTimeout ?: unknown } ) . keepAliveTimeout ) . toBe (
1053+ "number" ,
1054+ ) ;
1055+ expect ( typeof ( defaultAgent as { keepAliveMaxTimeout ?: unknown } ) . keepAliveMaxTimeout ) . toBe (
1056+ "number" ,
11411057 ) ;
1058+ expect ( typeof ( defaultAgent as { connections ?: unknown } ) . connections ) . toBe ( "number" ) ;
1059+ expect ( typeof ( defaultAgent as { pipelining ?: unknown } ) . pipelining ) . toBe ( "number" ) ;
11421060 const connections = ( defaultAgent as { connections ?: number } ) . connections ;
11431061 expect ( connections ) . toBeGreaterThan ( 0 ) ;
11441062 expect ( connections ) . toBeLessThan ( 100 ) ;
0 commit comments