okami.mom/albedo

git clone https://git.nkp.pet/okami.mom/albedo

Aly Raffauffeat(api)!: migrate daemon and clients to protocol 361c43ca

main
6.3 KiB150 linesraw
1"""Retrieval keeps exact counts, scoped pages, and Unicode text offsets through the daemon."""
2
3import json
4import unittest
5
6from harness import Albedo, Provider, Reply, python, text
7
8
9class RetrievalTests(unittest.TestCase):
10    def setUp(self):
11        self.code = None
12        self.tool = None
13        self.arguments = None
14
15        def script(request):
16            last = request["input"][-1]
17            if last.get("type") == "function_call_output":
18                return text("done")
19            if "<newly-evicted-history>" in str(last.get("content", "")):
20                return text("fold-only Café")
21            if self.code is not None:
22                return python(self.code)
23            if self.tool is not None:
24                return Reply(
25                    "python", tool_name=self.tool, tool_arguments=self.arguments
26                )
27            return text("done")
28
29        self.provider = Provider(script)
30        self.addCleanup(self.provider.close)
31        self.app = Albedo(self.provider, protocol="responses")
32        self.app.__enter__()
33        self.addCleanup(self.app.__exit__, None, None, None)
34        self.session = self.app.session()
35
36    def turn(self, session, prompt):
37        before = len(self.provider.requests)
38        self.app.prompt(session, prompt).close()
39        self.app.idle(session)
40        return [entry["request"] for entry in self.provider.requests[before:]]
41
42    def retrieve(self, name, arguments):
43        self.tool, self.arguments = name, arguments
44        requests = self.turn(self.session, "retrieve fixture")
45        output = next(
46            item["output"]
47            for item in reversed(requests[-1]["input"])
48            if item.get("type") == "function_call_output"
49        )
50        return json.loads(output)
51
52    def test_transcript_pages_count_matches_and_preserve_grapheme_offsets(self):
53        target = self.app.session()
54        for prompt in ["é👩‍💻tail Café\r", "second Café", "third Café"]:
55            self.turn(target, prompt)
56        self.code = f"""
57agent = await agents.get({target!r})
58found = await agent.search_messages('CAFÉ', limit=1)
59assert found.count == 3, found
60assert len(found.rows) == 1 and found.next_offset == 1, found
61seq = found.rows[0]['seq']
62second = await agent.search_messages('CAFÉ', offset=1, limit=1)
63assert second.count == 3 and second.rows[0]['seq'] > seq, second
64end = await agent.search_messages('CAFÉ', offset=3, limit=1)
65assert end.count == 3 and end.rows == [] and end.next_offset is None, end
66prefix = len(f'[row #{{seq}}]\\n[user]\\n')
67accent = await agent.messages(seq=seq, offset=prefix, limit=1)
68assert accent.content == 'é', accent
69emoji = await agent.messages(seq=seq, offset=prefix+1, limit=1)
70assert emoji.content == '👩‍💻', emoji
71boundary = await agent.messages(seq=seq, offset=prefix+11, limit=1)
72assert boundary.content == '\\r\\n', boundary
73separator = await agent.messages(seq=seq, offset=prefix+12, limit=1)
74assert separator.content == '\\n', separator
75beyond = await agent.messages(seq=seq, offset=100000, limit=1)
76assert beyond.content == '' and beyond.next_offset is None, beyond
77try:
78    await agent.messages(seq=seq, offset=-1)
79    assert False, 'negative offset was accepted'
80except AgentsError as error:
81    assert 'nonnegative' in str(error), error
82print('RETRIEVAL_PAGES_OK')
83"""
84        requests = self.turn(self.session, "verify source retrieval")
85        output = next(
86            item["output"]
87            for item in reversed(requests[-1]["input"])
88            if item.get("type") == "function_call_output"
89        )
90        self.assertIn("RETRIEVAL_PAGES_OK", output)
91
92    def test_lcm_search_pages_sources_and_nodes_independently_inside_selected_range(
93        self,
94    ):
95        for prompt in ["first Café", "second Café", "third Café", "fourth Café"]:
96            self.turn(self.session, prompt)
97        with self.app.api(
98            f"/sessions/{self.session}/compaction",
99            {"strategy": "lcm"},
100        ) as response:
101            result = json.load(response)
102        self.assertEqual(result["state"], "compacted")
103        self.app.idle(self.session)
104        listed = self.retrieve("lcm_list", {"limit": 1})
105        self.assertGreater(listed["total"], 0)
106        self.assertEqual(len(listed["folds"]), 1)
107        node = listed["folds"][0]
108        self.assertTrue(node["frontier"])
109        scoped = self.retrieve(
110            "lcm_grep", {"pattern": "CAFÉ", "summary_id": node["id"], "limit": 1}
111        )
112        self.assertGreater(scoped["source_count"], 1)
113        self.assertEqual(scoped["node_count"], 1)
114        self.assertEqual(len(scoped["sources"]), 1)
115        self.assertEqual(len(scoped["nodes"]), 1)
116        self.assertEqual(scoped["next_offset"], 1)
117        source = scoped["sources"][0]
118        self.assertEqual(source["node_id"], node["id"])
119        self.assertGreaterEqual(source["seq"], node["first_seq"])
120        self.assertLessEqual(source["seq"], node["last_seq"])
121        second = self.retrieve(
122            "lcm_grep",
123            {"pattern": "CAFÉ", "summary_id": node["id"], "limit": 1, "offset": 1},
124        )
125        self.assertEqual(second["source_count"], scoped["source_count"])
126        self.assertEqual(second["node_count"], 1)
127        self.assertEqual(len(second["sources"]), 1)
128        self.assertEqual(second["nodes"], [])
129        self.assertEqual(second["next_offset"], 2)
130        summary_only = self.retrieve(
131            "lcm_grep", {"pattern": "fold-only", "summary_id": node["id"], "limit": 1}
132        )
133        self.assertEqual(summary_only["source_count"], 0)
134        self.assertEqual(summary_only["node_count"], 1)
135        self.assertEqual(summary_only["sources"], [])
136        self.assertEqual(len(summary_only["nodes"]), 1)
137        self.assertIsNone(summary_only["next_offset"])
138        page = self.retrieve("lcm_expand", {"id": node["id"], "limit": 1})
139        self.assertEqual(page["content"], "[")
140        self.assertEqual(page["next_offset"], 1)
141        continued = self.retrieve(
142            "lcm_expand", {"id": node["id"], "limit": 1, "offset": 1}
143        )
144        self.assertEqual(continued["content"], "s")
145        outside = self.retrieve(
146            "lcm_grep", {"pattern": "CAFÉ", "summary_id": node["id"], "offset": 1000}
147        )
148        self.assertEqual(outside["source_count"], scoped["source_count"])
149        self.assertEqual(outside["sources"], [])
150        self.assertIsNone(outside["next_offset"])