aboutsummaryrefslogtreecommitdiff
path: root/agent/orchestrator/models/base.py
blob: 4ca198873ad1e783e237959994b686a7d40eda50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
"""Backend-agnostic model interface.

Concrete backends (Claude Code, Ollama, Anthropic API direct, OpenCode, etc.)
implement `ModelBackend.call`. The orchestration code only ever talks to this
interface, never to a specific backend.

Persona is NOT carried in ModelRequest; that's a backend-level configuration
concern (some backends autodiscover persona from a workspace, others need to
be told). What flows through here is per-turn DYNAMIC context only.
"""

from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import Literal


Role = Literal["system", "user", "assistant", "tool"]


@dataclass
class Message:
    role: Role
    content: str


@dataclass
class ModelRequest:
    """Everything a backend needs to produce one response."""
    messages: list[Message]
    turn_context: str | None = None
    extras: dict = field(default_factory=dict)


@dataclass
class ModelResponse:
    """What a backend returns. Kept narrow now, extended later."""
    content: str
    extras: dict = field(default_factory=dict)


class ModelBackend(ABC):
    @abstractmethod
    def call(self, request: ModelRequest) -> ModelResponse:
        ...