"""Dify attachment compatibility and per-outlet fault isolation regressions.""" import asyncio import base64 import json from unittest import TestCase import httpx import model_gateway as gw from test_model_gateway import _client, _outlet PNG = base64.b64encode(b'\x89PNG\r\n\x1a\nsynthetic').decode() class DifyMediaAudit(TestCase): def exercise(self, *, status=200, legacy=False, extra=None): requests=[] async def run(): def handler(request): requests.append(request) if request.url.path.endswith('/files/upload'): return httpx.Response(status,json={'id':'synthetic-file'}) return httpx.Response(200,json={'answer':'synthetic-ok'}) messages=[{'role':'system','content':'系统测试'}, {'role':'user','content':[ {'type':'text','text':'图上写了什么?'}, {'type':'image_url','image_url':{'url':'data:image/png;base64,'+PNG}}]}] if extra:messages[-1]['content'].append(extra) async with _client(handler) as client: outlet=_outlet(kind='dify') result=await gw.call_outlet(client,outlet,messages,image_b64=PNG if legacy else '') return result,outlet result,outlet=asyncio.run(run()) return result,outlet,requests def test_inline_image_uploaded_and_referenced_with_matching_user(self): result,_,requests=self.exercise() self.assertEqual(result['text'],'synthetic-ok') self.assertEqual(len(requests),2) self.assertTrue(requests[0].url.path.endswith('/files/upload')) body=json.loads(requests[1].content) self.assertEqual(body['files'][0]['upload_file_id'],'synthetic-file') self.assertIn(('\r\n\r\n'+body['user']+'\r\n').encode(), requests[0].content) self.assertNotIn(PNG,body['query']) def test_legacy_and_inline_same_image_uploads_once(self): _,_,requests=self.exercise(legacy=True) self.assertEqual(sum(r.url.path.endswith('/files/upload') for r in requests),1) def test_failed_upload_is_outlet_failure_not_uncaught_gateway_exception(self): result,outlet,requests=self.exercise(status=400,legacy=True) self.assertFalse(result['text']) self.assertIn('400',result['error']) self.assertEqual(outlet.breaker.failures,1) self.assertEqual(len(requests),1) def test_remote_image_url_is_forwarded_as_attachment_not_downloaded(self): _,_,requests=self.exercise(extra={'type':'image_url','image_url':{'url':'https://images.example/test.jpg'}}) body=json.loads(requests[-1].content) self.assertEqual(body['files'][1],{'type':'image','transfer_method':'remote_url','url':'https://images.example/test.jpg'}) def test_jpeg_attachment_keeps_mime_type(self): _,_,requests=self.exercise(extra={'type':'image_url','image_url':{'url':'data:image/jpeg;base64,'+PNG}}) upload=[r for r in requests if r.url.path.endswith('/files/upload')] self.assertEqual(len(upload),2) self.assertIn(b'Content-Type: image/jpeg',upload[1].content)