A declarative, hermetic harness for Nix-defined agents.
0

Configure Feed

Select the types of activity you want to include in your feed.

models: add provider-neutral turn types

+78
+78
tartarus/models.py
··· 1 + """Provider-neutral data types shared by the AgentLoop, Provider, and Broker. 2 + 3 + These shapes are deliberately independent of any vendor wire format. Each concrete 4 + Provider translates between these and its backend's request/response JSON, so the 5 + AgentLoop and Broker never branch on which backend is configured (PLAN.md §6.3). 6 + """ 7 + 8 + from dataclasses import dataclass 9 + from typing import Any 10 + 11 + 12 + @dataclass 13 + class ToolCall: 14 + """A model's request to invoke one tool, normalized across providers.""" 15 + 16 + id: str 17 + name: str 18 + arguments: dict 19 + # Set when the provider could not parse the model's raw arguments as a JSON 20 + # object. The broker turns this into an error result so the model can retry, 21 + # rather than the harness crashing on malformed output. 22 + argument_error: str | None = None 23 + 24 + 25 + @dataclass 26 + class AssistantTurn: 27 + """One assistant response, normalized across providers.""" 28 + 29 + text: str | None 30 + tool_calls: list[ToolCall] 31 + raw: dict[str, Any] # provider-native message, appended to the transcript verbatim 32 + stop_reason: str # "tool_calls" | "end" | "length" | "error" 33 + 34 + 35 + @dataclass 36 + class ToolResult: 37 + """The outcome of brokering one tool call. 38 + 39 + The provider renders this into its backend's native tool-result message. 40 + """ 41 + 42 + call_id: str 43 + output: str 44 + is_error: bool 45 + 46 + 47 + # --- Streaming events --------------------------------------------------------- 48 + # 49 + # A provider's stream() yields these as a turn is generated. The AgentLoop 50 + # forwards TextDelta to the UI as text arrives and uses the terminal 51 + # TurnComplete to broker any tool calls and extend the transcript. Keeping 52 + # these provider-neutral means the loop never branches on the backend. 53 + 54 + 55 + @dataclass 56 + class TextDelta: 57 + """A chunk of assistant text produced mid-turn.""" 58 + 59 + text: str 60 + 61 + 62 + @dataclass 63 + class ToolOutputDelta: 64 + """A chunk of command output produced while a tool is still running.""" 65 + 66 + call: ToolCall 67 + text: str 68 + 69 + 70 + @dataclass 71 + class TurnComplete: 72 + """Terminal stream event carrying the fully assembled turn.""" 73 + 74 + turn: AssistantTurn 75 + 76 + 77 + # What a provider's stream() yields. 78 + StreamEvent = TextDelta | TurnComplete