Mercurial
comparison mrjunejune/inference/copilot_sidecar_test.py @ 280:49e9e591c9bb
Add persistent dictation, prewarmed WebRTC speech input, Copilot SDK routing, animated conversation lifecycle controls, parking, and architecture coverage.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Tue, 18 Aug 2026 19:14:53 -0700 |
| parents | 056790c4fb0d |
| children | c57149ad216e |
comparison
equal
deleted
inserted
replaced
| 279:b3b547563ec7 | 280:49e9e591c9bb |
|---|---|
| 8 from mrjunejune.inference.copilot_sidecar import ( | 8 from mrjunejune.inference.copilot_sidecar import ( |
| 9 CompiledProfile, | 9 CompiledProfile, |
| 10 Sidecar, | 10 Sidecar, |
| 11 SidecarConfig, | 11 SidecarConfig, |
| 12 _derive_sdk_session_id, | 12 _derive_sdk_session_id, |
| 13 _CANVAS_ORCHESTRATOR_PROMPT, | |
| 13 _SDK_SESSION_NAMESPACE, | 14 _SDK_SESSION_NAMESPACE, |
| 14 _validate_history, | 15 _validate_history, |
| 15 _HISTORY_MAX_ENTRIES, | 16 _HISTORY_MAX_ENTRIES, |
| 16 _HISTORY_MAX_BYTES, | 17 _HISTORY_MAX_BYTES, |
| 17 ) | 18 ) |
| 48 return _FAKE_PROFILES[profile] | 49 return _FAKE_PROFILES[profile] |
| 49 | 50 |
| 50 | 51 |
| 51 def _fake_sdk_id(conversation_id: str, profile: str) -> str: | 52 def _fake_sdk_id(conversation_id: str, profile: str) -> str: |
| 52 """Compute the deterministic SDK session ID for use in test assertions.""" | 53 """Compute the deterministic SDK session ID for use in test assertions.""" |
| 53 p = _FAKE_PROFILES[profile] | 54 if profile == "canvas_orchestrator": |
| 55 content = _CANVAS_ORCHESTRATOR_PROMPT.strip() | |
| 56 p = { | |
| 57 "content": content, | |
| 58 "version": 1, | |
| 59 "hash": hashlib.sha256(content.encode()).hexdigest(), | |
| 60 } | |
| 61 else: | |
| 62 p = _FAKE_PROFILES[profile] | |
| 54 compiled = CompiledProfile( | 63 compiled = CompiledProfile( |
| 55 profile=profile, | 64 profile=profile, |
| 56 content=p["content"], | 65 content=p["content"], |
| 57 prompt_version=1, | 66 prompt_version=1, |
| 58 knowledge_version=p["version"], | 67 knowledge_version=p["version"], |
| 208 self.assertEqual( | 217 self.assertEqual( |
| 209 [item["type"] for item in self.output[-2:]], | 218 [item["type"] for item in self.output[-2:]], |
| 210 ["turn.error", "turn.done"], | 219 ["turn.error", "turn.done"], |
| 211 ) | 220 ) |
| 212 | 221 |
| 222 async def test_warm_creates_session_without_sending_prompt(self): | |
| 223 sidecar, client = await self.make_sidecar() | |
| 224 await sidecar.dispatch( | |
| 225 { | |
| 226 "command": "conversation.warm", | |
| 227 "request_id": "warm-1", | |
| 228 "conversation_id": "canvas-worker-1", | |
| 229 "prompt_profile": "canvas_orchestrator", | |
| 230 "prompt_version": 1, | |
| 231 "knowledge_version": 1, | |
| 232 "resume_existing": False, | |
| 233 } | |
| 234 ) | |
| 235 | |
| 236 self.assertEqual(len(client.create_calls), 1) | |
| 237 self.assertEqual(len(client.resume_calls), 0) | |
| 238 session = next(iter(client.sessions.values())) | |
| 239 self.assertEqual(session.prompts, []) | |
| 240 self.assertEqual( | |
| 241 [item["type"] for item in self.output[-2:]], | |
| 242 ["session.warmed", "turn.done"], | |
| 243 ) | |
| 244 | |
| 245 async def test_warm_rejects_non_boolean_resume_existing(self): | |
| 246 sidecar, client = await self.make_sidecar() | |
| 247 await sidecar.dispatch( | |
| 248 { | |
| 249 "command": "conversation.warm", | |
| 250 "request_id": "warm-invalid", | |
| 251 "conversation_id": "canvas-worker-1", | |
| 252 "prompt_profile": "canvas_orchestrator", | |
| 253 "prompt_version": 1, | |
| 254 "knowledge_version": 1, | |
| 255 "resume_existing": "false", | |
| 256 } | |
| 257 ) | |
| 258 | |
| 259 self.assertEqual(len(client.create_calls), 0) | |
| 260 self.assertEqual(len(client.resume_calls), 0) | |
| 261 self.assertEqual( | |
| 262 [item["type"] for item in self.output[-2:]], | |
| 263 ["turn.error", "turn.done"], | |
| 264 ) | |
| 265 self.assertEqual( | |
| 266 self.output[-2]["error"]["message"], | |
| 267 "resume_existing must be a boolean", | |
| 268 ) | |
| 269 | |
| 213 async def test_multi_turn_reuses_one_session_and_configures_sdk(self): | 270 async def test_multi_turn_reuses_one_session_and_configures_sdk(self): |
| 214 sidecar, client = await self.make_sidecar() | 271 sidecar, client = await self.make_sidecar() |
| 215 for request_id, prompt in (("r1", "first"), ("r2", "second")): | 272 for request_id, prompt in (("r1", "first"), ("r2", "second")): |
| 216 await sidecar.dispatch( | 273 await sidecar.dispatch( |
| 217 { | 274 { |
| 409 set(client.delete_calls), | 466 set(client.delete_calls), |
| 410 { | 467 { |
| 411 _fake_sdk_id("delete-me", "public_visitor"), | 468 _fake_sdk_id("delete-me", "public_visitor"), |
| 412 _fake_sdk_id("delete-me", "invited_friend"), | 469 _fake_sdk_id("delete-me", "invited_friend"), |
| 413 _fake_sdk_id("delete-me", "june_admin"), | 470 _fake_sdk_id("delete-me", "june_admin"), |
| 471 _fake_sdk_id("delete-me", "canvas_orchestrator"), | |
| 414 }, | 472 }, |
| 415 ) | 473 ) |
| 416 self.assertTrue(client.stopped) | 474 self.assertTrue(client.stopped) |
| 417 self.assertTrue(sidecar.shutting_down) | 475 self.assertTrue(sidecar.shutting_down) |
| 418 shutdown = [ | 476 shutdown = [ |
| 956 set(client.delete_calls), | 1014 set(client.delete_calls), |
| 957 { | 1015 { |
| 958 _fake_sdk_id("conv-del-check", "public_visitor"), | 1016 _fake_sdk_id("conv-del-check", "public_visitor"), |
| 959 _fake_sdk_id("conv-del-check", "invited_friend"), | 1017 _fake_sdk_id("conv-del-check", "invited_friend"), |
| 960 _fake_sdk_id("conv-del-check", "june_admin"), | 1018 _fake_sdk_id("conv-del-check", "june_admin"), |
| 1019 _fake_sdk_id("conv-del-check", "canvas_orchestrator"), | |
| 961 }, | 1020 }, |
| 962 ) | 1021 ) |
| 963 self.assertNotIn("conv-del-check", client.delete_calls) | 1022 self.assertNotIn("conv-del-check", client.delete_calls) |
| 964 | 1023 |
| 965 async def test_delete_nonexistent_conversation_cleans_known_profile_ids(self): | 1024 async def test_delete_nonexistent_conversation_cleans_known_profile_ids(self): |
| 975 set(client.delete_calls), | 1034 set(client.delete_calls), |
| 976 { | 1035 { |
| 977 _fake_sdk_id("ghost-conv", "public_visitor"), | 1036 _fake_sdk_id("ghost-conv", "public_visitor"), |
| 978 _fake_sdk_id("ghost-conv", "invited_friend"), | 1037 _fake_sdk_id("ghost-conv", "invited_friend"), |
| 979 _fake_sdk_id("ghost-conv", "june_admin"), | 1038 _fake_sdk_id("ghost-conv", "june_admin"), |
| 1039 _fake_sdk_id("ghost-conv", "canvas_orchestrator"), | |
| 980 }, | 1040 }, |
| 981 ) | 1041 ) |
| 982 self.assertNotIn("ghost-conv", client.delete_calls) | 1042 self.assertNotIn("ghost-conv", client.delete_calls) |
| 983 done = [e for e in self.output if e["type"] == "turn.done" and e["request_id"] == "del-ghost"] | 1043 done = [e for e in self.output if e["type"] == "turn.done" and e["request_id"] == "del-ghost"] |
| 984 self.assertEqual(done[0]["action"], "conversation.delete") | 1044 self.assertEqual(done[0]["action"], "conversation.delete") |