Files
openswarm/backend/apps/agents/models.py
T
ciregenz 4778cea80e [eric] multi-model subscription support: connect ChatGPT Plus, Gemini Advanced, and GitHub Copilot subscriptions via 9Router
- Add BUILTIN_MODELS for OpenAI (GPT-5.4/Mini/5.3-Codex), Google (Gemini 3 Pro/Flash, 2.5 Pro/Flash), and GitHub Copilot
  - Add resolve_model_id_for_sdk() and resolve_aux_model() to route prefixed model IDs (cx/, gc/, gh/) through 9Router translator
  - Add GET /agents/models endpoint returning available models based on live 9Router connection state
  - Enable ENABLE_TOOL_SEARCH=auto for all providers so non-Claude models get full tool access (23 built-in + all MCPs)
  - Add thinking block streaming support (ThinkingBlock in stream handler + AssistantMessage) for reasoning models
  - Fix Gemini 3 thought-signature errors: use skip_thought_signature_validator per Google docs
  - Fix WebSearch blocked_domains/allowed_domains empty-list rejection on Anthropic API
  - Fix browser_agent text_parts UnboundLocalError on non-Claude models
  - Fix auxiliary LLM calls (title gen, group meta, dashboard naming, view builder, browser agent) via resolve_aux_model
  - Add Codex OAuth callback listener on port 1455 for ChatGPT Plus subscription connect
  - Route Gemini OAuth through system browser since Google blocks embedded webviews
  - Override Electron popup user-agent for OAuth
  - Fix duplicate OAuth callback with idempotent completed_oauth tracking
  - Fix Settings modal tab routing and stale warning banner
  - Add API key inputs for OpenAI, Google, and OpenRouter
  - Add MCP warning banner when selecting non-Claude model with many tools
  - Force session fork on cross-provider model switch to prevent transcript corruption
  - Disable GitHub Copilot subscription card (9Router poll issue, marked preview)
  - Delete dead CopilotProvider import and unused CopilotAuthButton component
2026-04-12 12:06:36 -07:00

80 lines
3.1 KiB
Python

from pydantic import BaseModel, Field
from typing import Optional, Literal, Any
from datetime import datetime
from uuid import uuid4
class AgentConfig(BaseModel):
name: str = Field(default_factory=lambda: f"Agent-{uuid4().hex[:6]}")
model: str = "sonnet"
mode: str = "agent"
provider: str = "anthropic"
system_prompt: Optional[str] = None
allowed_tools: list[str] = Field(default_factory=lambda: ["Read", "Edit", "Write", "Bash", "Glob", "Grep", "AskUserQuestion"])
max_turns: Optional[int] = None
target_directory: Optional[str] = None # if None, uses repo root
dashboard_id: Optional[str] = None
class ApprovalRequest(BaseModel):
id: str = Field(default_factory=lambda: uuid4().hex)
session_id: str
tool_name: str
tool_input: dict[str, Any]
created_at: datetime = Field(default_factory=datetime.now)
class ApprovalResponse(BaseModel):
request_id: str
behavior: Literal["allow", "deny"]
message: Optional[str] = None
updated_input: Optional[dict[str, Any]] = None
class Message(BaseModel):
id: str = Field(default_factory=lambda: uuid4().hex)
role: Literal["user", "assistant", "tool_call", "tool_result", "system", "thinking"]
content: Any # str or list of content blocks
timestamp: datetime = Field(default_factory=datetime.now)
branch_id: str = "main"
parent_id: Optional[str] = None
context_paths: Optional[list[dict]] = None
attached_skills: Optional[list[dict]] = None
forced_tools: Optional[list[str]] = None
images: Optional[list[dict]] = None
hidden: bool = False
class MessageBranch(BaseModel):
id: str = Field(default_factory=lambda: uuid4().hex)
parent_branch_id: Optional[str] = None
fork_point_message_id: Optional[str] = None
created_at: datetime = Field(default_factory=datetime.now)
class ToolGroupMeta(BaseModel):
id: str
name: str
svg: str = ""
is_refined: bool = False
class AgentSession(BaseModel):
id: str = Field(default_factory=lambda: uuid4().hex)
name: str
status: Literal["running", "waiting_approval", "completed", "error", "stopped"] = "running"
provider: str = "anthropic"
model: str = "sonnet"
mode: str = "agent"
sdk_session_id: Optional[str] = None
system_prompt: Optional[str] = None
allowed_tools: list[str] = Field(default_factory=list)
max_turns: Optional[int] = None
cwd: Optional[str] = None
created_at: datetime = Field(default_factory=datetime.now)
closed_at: Optional[datetime] = None
cost_usd: float = 0.0
tokens: dict[str, int] = Field(default_factory=lambda: {"input": 0, "output": 0})
messages: list[Message] = Field(default_factory=list)
pending_approvals: list[ApprovalRequest] = Field(default_factory=list)
branches: dict[str, "MessageBranch"] = Field(default_factory=lambda: {"main": MessageBranch(id="main")})
active_branch_id: str = "main"
tool_group_meta: dict[str, "ToolGroupMeta"] = Field(default_factory=dict)
dashboard_id: Optional[str] = None
browser_id: Optional[str] = None
parent_session_id: Optional[str] = None
needs_fork: bool = False