okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
5bdc0ee
main
1"""Python agent API: spawn, family identity, refusals, progress, explicit mail, 2agents.get, reading messages across sessions, and listing and searching them.""" 3 4import re 5import time 6import unittest 7 8from harness import Albedo ,Provider ,latest_user ,python ,text 9 10LEAD = """models = await agents.models() 11assert 'beta/fixture-beta' in models, models 12kid = await agents.self.spawn('count to three', name='scout', model=models[0]) 13try: 14await agents.self.spawn('again', name='scout2', model='') 15except TypeError as error: 16print('EMPTY_MODEL', error) 17print('SPAWNED', kid.name, kid.depth, kid.parent.name, 'KID=' + kid.id) 18""" 19CHILD = """me = agents.self 20print('ME', me.name, me.depth, me.parent.name) 21print('PROGRESS', await agents.progress('counting')) 22print('Café Ünïcode') 23try: 24await me.parent.cancel() 25except AgentsError as error: 26print('REFUSED', error) 27page = await me.parent.messages() 28print('PARENT_READ', 'spawn a scout' in page.content) 29up = await agents.get('parent') 30print('GOT', up.id == me.parent.id, up.depth, up.parent, up.closed) 31try: 32await me.parent.delete() 33except AgentsError as error: 34print('ASK', error) 35receipt = await mail.submit('parent', 'three') 36print('SENT', receipt.status, receipt.name) 37""" 38 39READ = """kid = (await agents.self.children())[0] 40page = await kid.messages() 41print('TASK_SEEN', 'count to three' in page.content) 42hits = await kid.search_messages('COUNT TO THREE') 43seq = hits.rows[0]['seq'] 44row = await kid.messages(seq=seq, limit=200) 45print('FOUND', hits.count, row.content.startswith(f'[row #{seq}]'), 'count to three' in row.content) 46""" 47 48PEEK = """async def paged_sessions(query='', cwd=None): 49found = [] 50while True: 51page = await agents.sessions(query, cwd=cwd, offset=len(found)) 52if not page: 53return found 54found.extend(page) 55 56kid = await agents.get({kid!r}) 57print('PEEK', kid.name, kid.depth, kid.closed) 58page = await kid.messages() 59print('PEEK_READ', 'count to three' in page.content) 60try: 61await kid.cancel() 62except AgentsError as error: 63print('PEEK_REFUSED', error) 64listed = await paged_sessions() 65print('LISTED', {kid!r} in [s.id for s in listed], agents.self.id in [s.id for s in listed]) 66child_session = next(s for s in listed if s.id == {kid!r}) 67scouts = await paged_sessions('SCOUT', cwd=child_session.cwd) 68scout = next(s for s in scouts if s.id == {kid!r}) 69print('BY_NAME', scout.name, scout.depth, scout.model, scout.cwd == child_session.cwd) 70print('ELSEWHERE', await paged_sessions(cwd='/nowhere')) 71talked = await paged_sessions('COUNT TO THREE') 72said = next(s for s in talked if s.id == {kid!r}) 73hit = said.matches[0] 74row = await said.messages(seq=hit['seq'], limit=200) 75print('SEARCHED', agents.self.id in [s.id for s in talked], 'count to three' in hit['preview'], 'count to three' in row.content) 76print('UNQUERIED', listed[0].matches) 77print('UNICODE', {kid!r} in [s.id for s in await paged_sessions('CAFÉ ÜNÏCODE')]) 78print('NOTHING', await paged_sessions('never ' + 'said anywhere')) 79try: 80await agents.get('nobody') 81except AgentsError as error: 82print('PEEK_MISSING', error) 83""" 84 85 86def wait_for (predicate ): 87deadline = time .monotonic ()+ 60 88while time .monotonic ()< deadline : 89result = predicate () 90if result : 91return result 92time .sleep (0.1 ) 93raise AssertionError ("agent Python turn never arrived" ) 94 95 96class AgentsPythonTests (unittest .TestCase ): 97def test_python_spawn_identity_refusals_and_explicit_answer (self ): 98def script (request ): 99last = request ["messages" ][- 1 ] 100user = latest_user (request ) 101peek = re .search (r"peek ([0-9a-f]+)" ,user ) 102if last .get ("role" )== "user" and peek : 103return python (PEEK .format (kid = peek .group (1 ))) 104if last .get ("role" )== "user" and user == "spawn a scout" : 105return python (LEAD ) 106if last .get ("role" )== "user" and 'kind="task"' in user : 107return python (CHILD ) 108if last .get ("role" )== "user" and 'kind="message"' in user : 109return python (READ ) 110return text ("ok" ) 111 112provider = Provider (script ) 113providers = { 114name : { 115"baseUrl" :provider .url + f"/ { name } /v1" , 116"apiKey" :"key" , 117"model" :f"fixture- { name } " , 118"protocol" :"chat_completions" , 119 } 120for name in ("alpha" ,"beta" ) 121 } 122try : 123with Albedo (provider ,providers = providers )as app : 124lead = app .session () 125app .prompt (lead ,"spawn a scout" ).close () 126 127def observed (): 128records = [] 129for item in provider .requests : 130messages = item ["request" ]["messages" ] 131last = messages [- 1 ] 132records .append ( 133 { 134"user" :latest_user (item ["request" ]), 135"context" :" " .join ( 136str (m .get ("content" ,"" ))for m in messages 137 ), 138"tool" :str (last .get ("content" ,"" )) 139if last .get ("role" )== "tool" 140else "" , 141 } 142 ) 143return records 144 145spawned = wait_for ( 146lambda :next ( 147 (r ["tool" ]for r in observed ()if "SPAWNED" in r ["tool" ]),None 148 ) 149 ) 150self .assertIn ("SPAWNED scout 1" ,spawned ) 151self .assertIn ("EMPTY_MODEL" ,spawned ) 152child = wait_for ( 153lambda :next ( 154 (r ["tool" ]for r in observed ()if "SENT" in r ["tool" ]),None 155 ) 156 ) 157self .assertIn ("ME scout 1" ,child ) 158self .assertIn ("PROGRESS True" ,child ) 159self .assertIn ("REFUSED" ,child ) 160self .assertIn ("own children" ,child ) 161self .assertIn ("PARENT_READ True" ,child ) 162self .assertIn ("GOT True 0 None False" ,child ) 163self .assertIn ("ASK" ,child ) 164self .assertIn ("only the user deletes" ,child ) 165self .assertTrue ( 166"SENT delivered spawn a scout" in child 167or "SENT queued spawn a scout" in child 168 ) 169task = next (r for r in observed ()if 'kind="task"' in r ["user" ]) 170self .assertIn ('You are child agent "scout"' ,task ["context" ]) 171wait_for ( 172lambda :any ( 173'kind="message"' in r ["user" ]and "three" in r ["user" ] 174for r in observed () 175 ) 176 ) 177read = wait_for ( 178lambda :next ( 179 (r ["tool" ]for r in observed ()if "FOUND" in r ["tool" ]),None 180 ) 181 ) 182self .assertIn ("TASK_SEEN True" ,read ) 183self .assertRegex (read ,r"FOUND [1-9]\d* True True" ) 184match = re .search (r"KID=([0-9a-f]+)" ,spawned ) 185assert match is not None 186kid = match .group (1 ) 187outsider = app .session () 188app .prompt (outsider ,f"peek { kid } " ).close () 189app .idle (outsider ,timeout = 60 ) 190delivered = [record ["tool" ]for record in observed ()if record ["tool" ]] 191peeked = next ( 192 (record for record in delivered if "PEEK_MISSING" in record ),None 193 ) 194assert peeked is not None , ( 195"PEEK turn finished without its final marker; delivered tools: " 196+ repr (delivered ) 197 ) 198self .assertIn ("PEEK scout 1 False" ,peeked ) 199self .assertIn ("PEEK_READ True" ,peeked ) 200self .assertIn ("PEEK_REFUSED you can only cancel or close" ,peeked ) 201self .assertIn ("no agent named 'nobody'" ,peeked ) 202self .assertIn ("LISTED True True" ,peeked ) 203self .assertIn ("BY_NAME scout 1 fixture-alpha True" ,peeked ) 204self .assertIn ("ELSEWHERE []" ,peeked ) 205self .assertIn ("SEARCHED False True True" ,peeked ) 206self .assertIn ("UNQUERIED []" ,peeked ) 207self .assertIn ("UNICODE True" ,peeked ) 208self .assertIn ("NOTHING []" ,peeked ) 209app .idle (lead ) 210time .sleep (1 ) 211self .assertFalse ( 212any ('kind="unreviewed"' in r ["user" ]for r in observed ()) 213 ) 214finally : 215provider .close ()