2026-04-03 13:14:59 +08:00
|
|
|
from dataclasses import dataclass
|
2026-03-21 10:13:29 +08:00
|
|
|
from enum import Enum
|
2026-04-03 13:14:59 +08:00
|
|
|
from typing import Annotated, Any, TypedDict
|
2026-03-21 10:13:29 +08:00
|
|
|
|
2026-03-29 20:31:13 +08:00
|
|
|
from langchain_core.messages import BaseMessage
|
|
|
|
|
from langgraph.graph.message import add_messages
|
2026-03-25 21:42:26 +08:00
|
|
|
|
2026-03-21 10:13:29 +08:00
|
|
|
|
|
|
|
|
class AgentRole(str, Enum):
|
|
|
|
|
MASTER = "master"
|
2026-03-29 20:31:13 +08:00
|
|
|
SCHEDULE_PLANNER = "schedule_planner"
|
2026-03-21 10:13:29 +08:00
|
|
|
EXECUTOR = "executor"
|
|
|
|
|
LIBRARIAN = "librarian"
|
|
|
|
|
ANALYST = "analyst"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
|
class ConversationTurn:
|
|
|
|
|
role: str # "user" | "assistant"
|
|
|
|
|
content: str
|
|
|
|
|
agent: AgentRole | None = None
|
|
|
|
|
model: str | None = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AgentState(TypedDict):
|
2026-03-29 20:31:13 +08:00
|
|
|
messages: Annotated[list[BaseMessage], add_messages]
|
2026-03-21 10:13:29 +08:00
|
|
|
user_id: str
|
|
|
|
|
conversation_id: str
|
|
|
|
|
|
2026-03-29 20:31:13 +08:00
|
|
|
current_agent: str | None
|
2026-04-03 13:14:59 +08:00
|
|
|
next_step: str | None
|
|
|
|
|
active_agents: list[AgentRole]
|
|
|
|
|
current_sub_commander: str | None
|
|
|
|
|
active_sub_commanders: list[str]
|
|
|
|
|
sub_commander_trace: list[dict[str, Any]]
|
2026-03-29 20:31:13 +08:00
|
|
|
agent_trace: list[str]
|
2026-03-21 10:13:29 +08:00
|
|
|
|
2026-04-03 13:14:59 +08:00
|
|
|
pending_tasks: list[dict[str, Any]]
|
|
|
|
|
completed_tasks: list[dict[str, Any]]
|
|
|
|
|
tool_calls: list[dict[str, Any]]
|
|
|
|
|
last_tool_result: str | None
|
|
|
|
|
action_results: list[dict[str, Any]]
|
|
|
|
|
created_entities: list[dict[str, Any]]
|
|
|
|
|
tool_outcomes: list[dict[str, Any]]
|
|
|
|
|
|
|
|
|
|
tool_strategy_used: str | None
|
|
|
|
|
tool_round_count: int
|
|
|
|
|
max_tool_rounds: int
|
|
|
|
|
retry_count: int
|
|
|
|
|
max_retries: int
|
|
|
|
|
iteration_count: int
|
|
|
|
|
max_iterations: int
|
|
|
|
|
routing_hops: int
|
|
|
|
|
max_routing_hops: int
|
|
|
|
|
terminated_due_to_loop_guard: bool
|
|
|
|
|
retrieval_trace: list[dict[str, Any]]
|
|
|
|
|
stop_reason: str | None
|
|
|
|
|
|
|
|
|
|
clarification_needed: bool
|
|
|
|
|
clarification_question: str | None
|
|
|
|
|
fallback_parse_error: str | None
|
|
|
|
|
should_respond: bool
|
|
|
|
|
|
2026-03-21 10:13:29 +08:00
|
|
|
knowledge_context: str | None
|
2026-04-03 13:14:59 +08:00
|
|
|
graph_context: str | None
|
2026-03-29 20:31:13 +08:00
|
|
|
schedule_context_summary: str | None
|
2026-04-03 13:14:59 +08:00
|
|
|
plan: str | None
|
|
|
|
|
plan_steps: list[dict[str, Any]]
|
2026-03-21 10:13:29 +08:00
|
|
|
analysis_report: str | None
|
|
|
|
|
final_response: str | None
|
2026-04-03 13:14:59 +08:00
|
|
|
|
2026-03-21 10:13:29 +08:00
|
|
|
memory_context: str | None
|
2026-03-29 20:31:13 +08:00
|
|
|
current_datetime_context: str | None
|
2026-04-03 13:14:59 +08:00
|
|
|
current_datetime_reference: dict[str, str] | None
|
|
|
|
|
|
|
|
|
|
turn_context: dict[str, Any] | None
|
|
|
|
|
routing_decision: dict[str, Any] | None
|
|
|
|
|
continuity_state: dict[str, Any] | None
|
|
|
|
|
pending_action: dict[str, Any] | None
|
|
|
|
|
last_completed_action: dict[str, Any] | None
|
|
|
|
|
clarification_context: dict[str, Any] | None
|
|
|
|
|
|
|
|
|
|
user_llm_config: dict[str, Any] | None
|
|
|
|
|
provider_capabilities: dict[str, Any] | None
|
2026-03-22 13:50:01 +08:00
|
|
|
|
2026-03-21 10:13:29 +08:00
|
|
|
|
|
|
|
|
def initial_state(user_id: str, conversation_id: str) -> AgentState:
|
|
|
|
|
return AgentState(
|
|
|
|
|
messages=[],
|
|
|
|
|
user_id=user_id,
|
|
|
|
|
conversation_id=conversation_id,
|
2026-03-29 20:31:13 +08:00
|
|
|
current_agent=AgentRole.MASTER.value,
|
|
|
|
|
next_step=None,
|
2026-04-03 13:14:59 +08:00
|
|
|
active_agents=[AgentRole.MASTER],
|
|
|
|
|
current_sub_commander=None,
|
|
|
|
|
active_sub_commanders=[],
|
|
|
|
|
sub_commander_trace=[],
|
2026-03-29 20:31:13 +08:00
|
|
|
agent_trace=[AgentRole.MASTER.value],
|
2026-03-21 10:13:29 +08:00
|
|
|
pending_tasks=[],
|
|
|
|
|
completed_tasks=[],
|
2026-04-03 13:14:59 +08:00
|
|
|
tool_calls=[],
|
|
|
|
|
last_tool_result=None,
|
|
|
|
|
action_results=[],
|
2026-03-29 20:31:13 +08:00
|
|
|
created_entities=[],
|
2026-04-03 13:14:59 +08:00
|
|
|
tool_outcomes=[],
|
|
|
|
|
tool_strategy_used=None,
|
|
|
|
|
tool_round_count=0,
|
|
|
|
|
max_tool_rounds=2,
|
|
|
|
|
retry_count=0,
|
|
|
|
|
max_retries=1,
|
|
|
|
|
iteration_count=0,
|
|
|
|
|
max_iterations=3,
|
|
|
|
|
routing_hops=0,
|
|
|
|
|
max_routing_hops=2,
|
|
|
|
|
terminated_due_to_loop_guard=False,
|
|
|
|
|
retrieval_trace=[],
|
|
|
|
|
stop_reason=None,
|
|
|
|
|
clarification_needed=False,
|
|
|
|
|
clarification_question=None,
|
|
|
|
|
fallback_parse_error=None,
|
|
|
|
|
should_respond=True,
|
2026-03-21 10:13:29 +08:00
|
|
|
knowledge_context=None,
|
2026-04-03 13:14:59 +08:00
|
|
|
graph_context=None,
|
2026-03-29 20:31:13 +08:00
|
|
|
schedule_context_summary=None,
|
2026-04-03 13:14:59 +08:00
|
|
|
plan=None,
|
|
|
|
|
plan_steps=[],
|
2026-03-21 10:13:29 +08:00
|
|
|
analysis_report=None,
|
|
|
|
|
final_response=None,
|
|
|
|
|
memory_context=None,
|
2026-03-29 20:31:13 +08:00
|
|
|
current_datetime_context=None,
|
2026-04-03 13:14:59 +08:00
|
|
|
current_datetime_reference=None,
|
|
|
|
|
turn_context=None,
|
|
|
|
|
routing_decision=None,
|
|
|
|
|
continuity_state=None,
|
|
|
|
|
pending_action=None,
|
|
|
|
|
last_completed_action=None,
|
|
|
|
|
clarification_context=None,
|
2026-03-22 13:50:01 +08:00
|
|
|
user_llm_config=None,
|
2026-03-29 20:31:13 +08:00
|
|
|
provider_capabilities=None,
|
2026-03-21 10:13:29 +08:00
|
|
|
)
|