@@ -48,6 +48,21 @@ async function withTempWorkspacePng(
4848 }
4949}
5050
51+ async function withTempAttachmentPng (
52+ cb : ( args : { attachmentRoot : string ; imagePath : string } ) => Promise < void > ,
53+ ) {
54+ const attachmentParent = await fs . mkdtemp ( path . join ( os . tmpdir ( ) , "openclaw-imessage-" ) ) ;
55+ try {
56+ const attachmentRoot = path . join ( attachmentParent , "Library" , "Messages" , "Attachments" ) ;
57+ await fs . mkdir ( attachmentRoot , { recursive : true } ) ;
58+ const imagePath = path . join ( attachmentRoot , "photo.png" ) ;
59+ await fs . writeFile ( imagePath , Buffer . from ( ONE_PIXEL_PNG_B64 , "base64" ) ) ;
60+ await cb ( { attachmentRoot, imagePath } ) ;
61+ } finally {
62+ await fs . rm ( attachmentParent , { recursive : true , force : true } ) ;
63+ }
64+ }
65+
5166function stubMinimaxOkFetch ( ) {
5267 const fetch = vi . fn ( ) . mockResolvedValue ( {
5368 ok : true ,
@@ -495,6 +510,27 @@ describe("image tool implicit imageModel config", () => {
495510 } ) ;
496511 } ) ;
497512
513+ it ( "allows iMessage attachment paths from configured attachment roots" , async ( ) => {
514+ await withTempAttachmentPng ( async ( { attachmentRoot, imagePath } ) => {
515+ const fetch = stubMinimaxOkFetch ( ) ;
516+ await withTempAgentDir ( async ( agentDir ) => {
517+ const cfg : OpenClawConfig = {
518+ ...createMinimaxImageConfig ( ) ,
519+ channels : {
520+ imessage : {
521+ attachmentRoots : [ attachmentRoot ] ,
522+ } ,
523+ } ,
524+ } ;
525+
526+ const tool = createRequiredImageTool ( { config : cfg , agentDir } ) ;
527+
528+ await expectImageToolExecOk ( tool , imagePath ) ;
529+ expect ( fetch ) . toHaveBeenCalledTimes ( 1 ) ;
530+ } ) ;
531+ } ) ;
532+ } ) ;
533+
498534 it ( "respects fsPolicy.workspaceOnly for non-sandbox image paths" , async ( ) => {
499535 await withTempWorkspacePng ( async ( { workspaceDir, imagePath } ) => {
500536 const fetch = stubMinimaxOkFetch ( ) ;
0 commit comments