test_smoke_model.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. from __future__ import annotations
  2. import runpy
  3. from pathlib import Path
  4. import pytest
  5. ROOT = Path(__file__).resolve().parents[3]
  6. SMOKE = runpy.run_path(ROOT / "scripts" / "smoke-python-runtime.py")
  7. @pytest.mark.parametrize(
  8. ("prompt_name", "expected"),
  9. [
  10. ("SNAPSHOT_DIRECT_CHILD_PROMPT", "DIRECT_CHILD_OK"),
  11. ("SNAPSHOT_WORKFLOW_CHILD_PROMPT", "WORKFLOW_CHILD_OK"),
  12. ],
  13. )
  14. def test_child_prompt_precedes_runtime_context(prompt_name: str, expected: str) -> None:
  15. chunks = SMOKE["completion_chunks"]({
  16. "messages": [
  17. {"role": "user", "content": SMOKE[prompt_name]},
  18. {"role": "user", "content": "Current runtime context"},
  19. ],
  20. })
  21. assert any(
  22. choice.get("delta", {}).get("content") == expected
  23. for chunk in chunks
  24. for choice in chunk.get("choices", [])
  25. )
  26. def test_mcp_smoke_requests_the_discovered_tool() -> None:
  27. chunks = SMOKE["completion_chunks"]({
  28. "messages": [{"role": "user", "content": SMOKE["MCP_PROMPT"]}],
  29. "tools": [{"type": "function", "function": {"name": "mcp__fixture__add"}}],
  30. })
  31. calls = [
  32. call
  33. for chunk in chunks
  34. for choice in chunk.get("choices", [])
  35. for call in choice.get("delta", {}).get("tool_calls", [])
  36. ]
  37. assert calls[0]["function"] == {
  38. "name": "mcp__fixture__add",
  39. "arguments": '{"a": 19, "b": 23}',
  40. }
  41. def test_mcp_smoke_accepts_the_external_server_result() -> None:
  42. chunks = SMOKE["completion_chunks"]({
  43. "messages": [
  44. {"role": "user", "content": SMOKE["MCP_PROMPT"]},
  45. {
  46. "role": "assistant",
  47. "tool_calls": [{
  48. "id": "mcp-add",
  49. "type": "function",
  50. "function": {"name": "mcp__fixture__add", "arguments": '{}'},
  51. }],
  52. },
  53. {"role": "tool", "tool_call_id": "mcp-add", "content": "42"},
  54. ],
  55. })
  56. assert any(
  57. choice.get("delta", {}).get("content") == SMOKE["MCP_TEXT"]
  58. for chunk in chunks
  59. for choice in chunk.get("choices", [])
  60. )
  61. def test_snapshot_comparison_normalizes_only_session_generation_provenance() -> None:
  62. normalize = SMOKE["normalize_session_format_comparison"]
  63. expected = {
  64. "header": {"type": "session", "version": 0, "otherVersion": 7},
  65. "accepted": {
  66. "type": "session-log-deepseek/delivery-accepted",
  67. "data": {"sessionId": "s", "throughSeq": 4},
  68. },
  69. "source": {
  70. "kind": "session-reference",
  71. "references": [{"sessionId": "other", "capturedThroughSeq": 8}],
  72. },
  73. }
  74. actual = {
  75. "header": {"type": "session", "version": 1, "otherVersion": 7},
  76. "accepted": {
  77. "type": "session-log-deepseek/delivery-accepted",
  78. "data": {"sessionId": "s", "sessionFormatVersion": 1, "throughSeq": 4},
  79. },
  80. "source": {
  81. "kind": "session-reference",
  82. "references": [{
  83. "sessionId": "other",
  84. "capturedFormatVersion": 1,
  85. "capturedThroughSeq": 8,
  86. }],
  87. },
  88. }
  89. assert normalize(expected) == normalize(actual)
  90. assert normalize(expected)["header"]["otherVersion"] == 7
  91. def test_snapshot_value_normalizes_embedded_assistant_stream_timing() -> None:
  92. normalize = SMOKE["normalize_snapshot_value"]
  93. event = {
  94. "type": "assistant/message",
  95. "seq": 4,
  96. "time": 100,
  97. "data": {
  98. "stream": [
  99. {"type": "chunk", "time": 101, "chunk": {"type": "finish"}},
  100. {"type": "text-chunks", "time0": 102, "dt": [1, 2], "texts": ["a", "b", "c"]},
  101. ],
  102. },
  103. }
  104. normalized = normalize(event, [])
  105. assert normalized["time"] == 0
  106. assert normalized["data"]["stream"] == [
  107. {"type": "chunk", "time": 0, "chunk": {"type": "finish"}},
  108. {"type": "text-chunks", "time0": 0, "dt": [0, 0], "texts": ["a", "b", "c"]},
  109. ]
  110. def test_snapshot_comparison_expands_embedded_assistant_streams() -> None:
  111. normalize = SMOKE["normalize_session_format_comparison"]
  112. expected = [
  113. {
  114. "type": "assistant/chunk",
  115. "seq": 4,
  116. "time": 0,
  117. "data": {"turn": 1, "step": 1, "chunk": {
  118. "type": "text-delta", "index": 0, "text": "done",
  119. }},
  120. },
  121. {
  122. "type": "assistant/message",
  123. "seq": 5,
  124. "time": 0,
  125. "data": {"turn": 1, "step": 1, "message": {"role": "assistant"}},
  126. "sourceEventSeqs": [4],
  127. "surfaceOp": "append",
  128. },
  129. ]
  130. actual = [{
  131. "type": "assistant/message",
  132. "seq": 4,
  133. "time": 0,
  134. "data": {
  135. "turn": 1,
  136. "step": 1,
  137. "message": {"role": "assistant"},
  138. "stream": [{
  139. "type": "text-chunks", "time0": 0, "index": 0, "dt": [], "texts": ["done"],
  140. }],
  141. },
  142. "surfaceOp": "append",
  143. }]
  144. assert normalize(actual) == normalize(expected)
  145. def test_snapshot_comparison_expands_sdk_wrapped_attempts() -> None:
  146. normalize = SMOKE["normalize_session_format_comparison"]
  147. actual = [{
  148. "method": "session.event",
  149. "payload": {
  150. "sessionId": "s",
  151. "event": {
  152. "type": "assistant/attempt",
  153. "seq": 7,
  154. "time": 0,
  155. "data": {
  156. "turn": 1,
  157. "step": 1,
  158. "stream": [{"type": "chunk", "time": 0, "chunk": {"type": "finish"}}],
  159. },
  160. },
  161. },
  162. }]
  163. assert normalize(actual) == [{
  164. "method": "session.event",
  165. "payload": {
  166. "sessionId": "s",
  167. "event": {
  168. "type": "assistant/chunk",
  169. "data": {"turn": 1, "step": 1, "chunk": {"type": "finish"}},
  170. },
  171. },
  172. }]
  173. def test_snapshot_generation_names_select_highest_role_without_double_counting(
  174. tmp_path: Path,
  175. ) -> None:
  176. render = SMOKE["snapshot_session_filename"]
  177. select = SMOKE["selected_snapshot_session_files"]
  178. assert render(0, 0) == "session.jsonl"
  179. assert render(0, 2) == "session.v2.jsonl"
  180. assert render(3, 0) == "session.3.jsonl"
  181. assert render(3, 2) == "session.3.v2.jsonl"
  182. (tmp_path / "session.jsonl").write_text(
  183. '{"type":"session","version":0}\n', encoding="utf-8",
  184. )
  185. (tmp_path / "session.v1.jsonl").write_text(
  186. '{"type":"session","version":1}\n', encoding="utf-8",
  187. )
  188. (tmp_path / "session.1.jsonl").write_text(
  189. '{"type":"session","version":0}\n', encoding="utf-8",
  190. )
  191. assert {index: path.name for index, path in select(tmp_path).items()} == {
  192. 0: "session.v1.jsonl",
  193. 1: "session.1.jsonl",
  194. }
  195. def test_snapshot_generation_filename_must_match_header(tmp_path: Path) -> None:
  196. (tmp_path / "session.v1.jsonl").write_text(
  197. '{"type":"session","version":0}\n', encoding="utf-8",
  198. )
  199. with pytest.raises(AssertionError, match="filename declares Session format v1"):
  200. SMOKE["selected_snapshot_session_files"](tmp_path)