okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
98d6ff4
main
1"""Quiet sessions unload, watched ones stay, and session reads reuse discovery.""" 2 3import http .client 4import json 5import time 6import unittest 7 8from harness import Albedo ,Provider ,exclusive ,text 9 10# Short enough that the test waits seconds, long enough to outlast a turn. 11UNLOAD_SECONDS = 2 12 13 14def loaded (app ): 15with app .api ("/sessions?scope=all" )as response : 16return { 17row ["id" ]:row ["cursor" ]is not None for row in json .load (response )["items" ] 18 } 19 20 21def wait_for (condition ,message ): 22deadline = time .monotonic ()+ UNLOAD_SECONDS * 5 23while time .monotonic ()< deadline : 24if condition (): 25return 26time .sleep (0.1 ) 27raise AssertionError (message ) 28 29 30# exclusive: shortens the daemon's unload limit 31@exclusive 32class SessionUnloadTests (unittest .TestCase ): 33def setUp (self ): 34self .provider = Provider (lambda _request :text ("ok" )) 35self .addCleanup (self .provider .close ) 36self .app = Albedo ( 37self .provider , 38prepare = lambda app :app .env .update ( 39ALBEDO_UNLOAD_SECONDS = str (UNLOAD_SECONDS ) 40 ), 41 ) 42self .app .__enter__ () 43self .addCleanup (self .app .__exit__ ,None ,None ,None ) 44 45def turn (self ,session ,prompt ): 46self .app .prompt (session ,prompt ).close () 47self .app .idle (session ) 48 49def test_quiet_session_unloads_unless_watched (self ): 50app = self .app 51quiet ,watched = app .session (),app .session () 52self .turn (quiet ,"hello" ) 53self .turn (watched ,"hello" ) 54# A connection of its own, so the requests below never share it. 55stream = http .client .HTTPConnection ("127.0.0.1" ,app .connection ["port" ]) 56self .addCleanup (stream .close ) 57stream .request ( 58"GET" , 59f"/sessions/ { watched } " , 60headers = { 61"Authorization" :"Bearer " + app .connection ["token" ], 62"Accept" :"text/event-stream" , 63 }, 64 ) 65stream .getresponse ().readline () 66 67wait_for (lambda :not loaded (app )[quiet ],"a quiet session stayed loaded" ) 68self .assertTrue (loaded (app )[watched ],"a watched session was unloaded" ) 69 70# Reading stored history, as the session list's preview does, does 71# not load the session again. 72with app .api (f"/sessions/ { quiet } /history?limit=16" )as response : 73self .assertTrue (json .load (response )["items" ]) 74self .assertFalse (loaded (app )[quiet ]) 75 76requests = len (self .provider .requests ) 77self .turn (quiet ,"back again" ) 78self .assertEqual (len (self .provider .requests ),requests + 1 ) 79 80stream .close () 81wait_for (lambda :not loaded (app )[watched ],"a detached session stayed loaded" ) 82 83def test_session_reads_reuse_discovery_until_reload (self ): 84app = self .app 85session = app .session () 86 87def skills (): 88with app .api (f"/sessions/ { session } ?tail=0" )as response : 89return json .load (response )["selection" ]["effective" ]["skills" ] 90 91before = skills () 92late = app .workspace / ".agents/skills/late/SKILL.md" 93late .parent .mkdir (parents = True ) 94late .write_text ("---\nname: late\ndescription: added later\n---\nbody\n" ) 95self .assertEqual (skills (),before ,"a session read walked skill files" ) 96with app .api (f"/sessions/ { session } /reload" , {"target" :"session" })as response : 97json .load (response ) 98self .assertTrue (any ("late" in key for key in skills ()))