@@ -5,34 +5,146 @@ import type { LineAccountConfig } from "./types.js";
55
66// Avoid pulling in globals/pairing/media dependencies; this suite only asserts
77// allowlist/groupPolicy gating and message-context wiring.
8- vi . mock ( "openclaw/plugin-sdk/runtime-env" , async ( ) => {
9- const actual = await vi . importActual < typeof import ( "openclaw/plugin-sdk/runtime-env" ) > (
10- "openclaw/plugin-sdk/runtime-env" ,
11- ) ;
12- return {
13- ...actual ,
14- danger : ( text : string ) => text ,
15- logVerbose : ( ) => { } ,
16- shouldLogVerbose : ( ) => false ,
17- } ;
18- } ) ;
8+ vi . mock ( "openclaw/plugin-sdk/channel-inbound" , ( ) => ( {
9+ buildMentionRegexes : ( ) => [ ] ,
10+ matchesMentionPatterns : ( ) => false ,
11+ resolveMentionGatingWithBypass : ( {
12+ isGroup,
13+ requireMention,
14+ canDetectMention,
15+ wasMentioned,
16+ hasAnyMention,
17+ allowTextCommands,
18+ hasControlCommand,
19+ commandAuthorized,
20+ } : {
21+ isGroup : boolean ;
22+ requireMention : boolean ;
23+ canDetectMention : boolean ;
24+ wasMentioned : boolean ;
25+ hasAnyMention : boolean ;
26+ allowTextCommands : boolean ;
27+ hasControlCommand : boolean ;
28+ commandAuthorized : boolean ;
29+ } ) => ( {
30+ shouldSkip :
31+ isGroup &&
32+ requireMention &&
33+ canDetectMention &&
34+ ! wasMentioned &&
35+ ! ( allowTextCommands && hasControlCommand && commandAuthorized && ! hasAnyMention ) ,
36+ } ) ,
37+ } ) ) ;
38+ vi . mock ( "openclaw/plugin-sdk/channel-pairing" , ( ) => ( {
39+ createChannelPairingChallengeIssuer :
40+ ( { upsertPairingRequest } : { upsertPairingRequest : ( args : unknown ) => Promise < unknown > } ) =>
41+ async ( { senderId, onCreated } : { senderId : string ; onCreated ?: ( ) => void } ) => {
42+ await upsertPairingRequest ( { id : senderId , meta : { } } ) ;
43+ onCreated ?.( ) ;
44+ } ,
45+ } ) ) ;
46+ vi . mock ( "openclaw/plugin-sdk/command-auth" , ( ) => ( {
47+ hasControlCommand : ( text : string ) => text . trim ( ) . startsWith ( "!" ) ,
48+ resolveControlCommandGate : ( {
49+ hasControlCommand,
50+ authorizers,
51+ } : {
52+ hasControlCommand : boolean ;
53+ authorizers : Array < { configured : boolean ; allowed : boolean } > ;
54+ } ) => ( {
55+ commandAuthorized :
56+ hasControlCommand && authorizers . some ( ( entry ) => entry . allowed || entry . configured === false ) ,
57+ } ) ,
58+ } ) ) ;
59+ vi . mock ( "openclaw/plugin-sdk/config-runtime" , ( ) => ( {
60+ resolveAllowlistProviderRuntimeGroupPolicy : ( {
61+ groupPolicy,
62+ defaultGroupPolicy,
63+ } : {
64+ groupPolicy ?: string ;
65+ defaultGroupPolicy : string ;
66+ } ) => ( {
67+ groupPolicy : groupPolicy ?? defaultGroupPolicy ,
68+ providerMissingFallbackApplied : false ,
69+ } ) ,
70+ resolveDefaultGroupPolicy : ( cfg : { channels ?: { line ?: { groupPolicy ?: string } } } ) =>
71+ cfg . channels ?. line ?. groupPolicy ?? "open" ,
72+ warnMissingProviderGroupPolicyFallbackOnce : ( ) => { } ,
73+ } ) ) ;
74+ vi . mock ( "openclaw/plugin-sdk/runtime-env" , ( ) => ( {
75+ danger : ( text : string ) => text ,
76+ logVerbose : ( ) => { } ,
77+ } ) ) ;
78+ vi . mock ( "openclaw/plugin-sdk/group-access" , ( ) => ( {
79+ evaluateMatchedGroupAccessForPolicy : ( {
80+ groupPolicy,
81+ hasMatchInput,
82+ allowlistConfigured,
83+ allowlistMatched,
84+ } : {
85+ groupPolicy : string ;
86+ hasMatchInput : boolean ;
87+ allowlistConfigured : boolean ;
88+ allowlistMatched : boolean ;
89+ } ) => {
90+ if ( groupPolicy === "disabled" ) {
91+ return { allowed : false , reason : "disabled" } ;
92+ }
93+ if ( groupPolicy !== "allowlist" ) {
94+ return { allowed : true , reason : null } ;
95+ }
96+ if ( ! hasMatchInput ) {
97+ return { allowed : false , reason : "missing_match_input" } ;
98+ }
99+ if ( ! allowlistConfigured ) {
100+ return { allowed : false , reason : "empty_allowlist" } ;
101+ }
102+ if ( ! allowlistMatched ) {
103+ return { allowed : false , reason : "not_allowlisted" } ;
104+ }
105+ return { allowed : true , reason : null } ;
106+ } ,
107+ } ) ) ;
108+ vi . mock ( "openclaw/plugin-sdk/reply-history" , ( ) => ( {
109+ DEFAULT_GROUP_HISTORY_LIMIT : 20 ,
110+ clearHistoryEntriesIfEnabled : ( {
111+ historyMap,
112+ historyKey,
113+ } : {
114+ historyMap : Map < string , HistoryEntry [ ] > ;
115+ historyKey : string ;
116+ } ) => {
117+ historyMap . delete ( historyKey ) ;
118+ } ,
119+ recordPendingHistoryEntryIfEnabled : ( {
120+ historyMap,
121+ historyKey,
122+ limit,
123+ entry,
124+ } : {
125+ historyMap : Map < string , HistoryEntry [ ] > ;
126+ historyKey : string ;
127+ limit : number ;
128+ entry : HistoryEntry ;
129+ } ) => {
130+ const existing = historyMap . get ( historyKey ) ?? [ ] ;
131+ historyMap . set ( historyKey , [ ...existing , entry ] . slice ( - limit ) ) ;
132+ } ,
133+ } ) ) ;
134+ vi . mock ( "openclaw/plugin-sdk/routing" , ( ) => ( {
135+ resolveAgentRoute : ( ) => ( { agentId : "default" } ) ,
136+ } ) ) ;
19137
20138const { readAllowFromStoreMock, upsertPairingRequestMock } = vi . hoisted ( ( ) => ( {
21139 readAllowFromStoreMock : vi . fn ( async ( ) => [ ] as string [ ] ) ,
22140 upsertPairingRequestMock : vi . fn ( async ( ) => ( { code : "CODE" , created : true } ) ) ,
23141} ) ) ;
24142
25- vi . mock ( "openclaw/plugin-sdk/conversation-runtime" , async ( ) => {
26- const actual = await vi . importActual < typeof import ( "openclaw/plugin-sdk/conversation-runtime" ) > (
27- "openclaw/plugin-sdk/conversation-runtime" ,
28- ) ;
29- return {
30- ...actual ,
31- resolvePairingIdLabel : ( ) => "lineUserId" ,
32- readChannelAllowFromStore : readAllowFromStoreMock ,
33- upsertChannelPairingRequest : upsertPairingRequestMock ,
34- } ;
35- } ) ;
143+ vi . mock ( "openclaw/plugin-sdk/conversation-runtime" , ( ) => ( {
144+ resolvePairingIdLabel : ( ) => "lineUserId" ,
145+ readChannelAllowFromStore : readAllowFromStoreMock ,
146+ upsertChannelPairingRequest : upsertPairingRequestMock ,
147+ } ) ) ;
36148
37149vi . mock ( "./download.js" , ( ) => ( {
38150 downloadLineMedia : async ( ) => {
0 commit comments