66 lines
1.9 KiB
Python
66 lines
1.9 KiB
Python
"""Provider adapter contracts for OpenClaw, Codex and writer workers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from enum import Enum
|
|
from typing import Protocol, Mapping, Any
|
|
|
|
|
|
class AdapterState(str, Enum):
|
|
CREATED = "CREATED"
|
|
ACTIVE = "ACTIVE"
|
|
CLOSED = "CLOSED"
|
|
FAILED = "FAILED"
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class AdapterSession:
|
|
provider: str
|
|
session_id: str
|
|
provider_session_id: str
|
|
state: AdapterState
|
|
|
|
|
|
class AgentAdapter(Protocol):
|
|
"""Common lifecycle contract for external agent providers."""
|
|
|
|
def create_session(self, task: Mapping[str, Any]) -> AdapterSession:
|
|
"""Create a provider-native session."""
|
|
|
|
def send(self, session: AdapterSession, payload: Mapping[str, Any]) -> Mapping[str, Any]:
|
|
"""Send a task payload."""
|
|
|
|
def close(self, session: AdapterSession) -> None:
|
|
"""Close and revoke the session."""
|
|
|
|
|
|
class ShadowAdapter:
|
|
"""Safe adapter used only for candidate lifecycle testing."""
|
|
|
|
def __init__(self, provider: str) -> None:
|
|
self.provider = provider
|
|
self._counter = 0
|
|
|
|
def create_session(self, task: Mapping[str, Any]) -> AdapterSession:
|
|
self._counter += 1
|
|
return AdapterSession(
|
|
provider=self.provider,
|
|
session_id=f"shadow-{self._counter}",
|
|
provider_session_id=f"provider-{self._counter}",
|
|
state=AdapterState.ACTIVE,
|
|
)
|
|
|
|
def send(self, session: AdapterSession, payload: Mapping[str, Any]) -> Mapping[str, Any]:
|
|
if session.state != AdapterState.ACTIVE:
|
|
raise RuntimeError("session is not active")
|
|
return {
|
|
"provider": self.provider,
|
|
"session_id": session.session_id,
|
|
"result": "shadow-completed",
|
|
"side_effects": False,
|
|
}
|
|
|
|
def close(self, session: AdapterSession) -> None:
|
|
return None
|