Skip to content

Latest commit

 

History

History
292 lines (260 loc) · 8.47 KB

File metadata and controls

292 lines (260 loc) · 8.47 KB

Слой Controller — Управление агентами

Обзор модуля

Модуль openhands/controller/ — центральный оркестратор. Управляет жизненным циклом агентов, состоянием, лимитами, делегированием, обнаружением зацикливания и воспроизведением.

Иерархия классов

classDiagram
    class Agent {
        <<abstract>>
        -AgentConfig config
        -LLMRegistry llm_registry
        -dict _registry$
        +prompt_manager PromptManager
        +complete bool
        +name str
        +step(state: State)* Action
        +get_system_message() SystemMessageAction
        +reset()
        +set_mcp_tools(mcp_tools: list)
        +register(name, agent_cls)$
        +get_cls(name)$ type
        +list_agents()$ list~str~
    }

    class AgentController {
        -Agent agent
        -EventStream event_stream
        -StateTracker state_tracker
        -StuckDetector stuck_detector
        -ReplayManager replay_manager
        -SecurityAnalyzer security_analyzer
        +close(set_stop_state: bool)
        +step()
        +should_step(event: Event) bool
        +on_event(event: Event)
        +set_agent_state_to(new_state: AgentState)
        +get_agent_state() AgentState
        +start_delegate(action: AgentDelegateAction)
        +end_delegate()
        +get_state() State
        +set_initial_state(state, conversation_stats, ...)
        +get_trajectory(include_screenshots) list~dict~
        +attempt_loop_recovery() bool
        +save_state()
        +_step()
        +_handle_action(action: Action)
        +_handle_observation(observation: Observation)
        +_handle_message_action(action: MessageAction)
        +_handle_loop_recovery_action(action: LoopRecoveryAction)
        +_is_stuck() bool
        +_perform_loop_recovery(stuck_analysis)
        +_truncate_memory_to_point(recovery_point)
        +_restart_with_last_user_message(stuck_analysis)
        +_handle_security_analyzer(action: Action)
        +_add_system_message()
        +_pending_action Action
    }

    class ResponseParser {
        <<abstract>>
        +parse(response)* Action
        +parse_response(response)* str
        +parse_action(action_str)* Action
    }

    class ActionParser {
        <<abstract>>
        +check_condition(action_str)* bool
        +parse(action_str)* Action
    }

    class ReplayManager {
        -list~Event~ events
        +should_replay() bool
        +step() Action
        +get_replay_events(trajectory)$ list~Event~
    }

    class StuckDetector {
        -State state
        +is_stuck(headless_mode) bool
        +_is_stuck_repeating_action_observation(...)  bool
        +_is_stuck_repeating_action_error(...) bool
        +_is_stuck_monologue(...) bool
        +_is_stuck_action_observation_pattern(...) bool
        +_is_stuck_context_window_error(...) bool
        +_eq_no_pid(obj1: Event, obj2: Event) bool
    }

    class StuckAnalysis {
        <<dataclass>>
        +str loop_type
        +int loop_repeat_times
        +int loop_start_idx
    }

    AgentController --> Agent : manages
    AgentController --> StuckDetector : uses
    AgentController --> ReplayManager : uses
    AgentController --> StateTracker : uses
    StuckDetector --> StuckAnalysis : produces
    ResponseParser <|-- ActionParser
Loading

Управление состоянием

classDiagram
    class State {
        <<dataclass>>
        +str session_id
        +str user_id
        +IterationControlFlag iteration_flag
        +BudgetControlFlag budget_flag
        +ConversationStats conversation_stats
        +bool confirmation_mode
        +list~Event~ history
        +dict inputs
        +dict outputs
        +AgentState agent_state
        +AgentState resume_state
        +int delegate_level
        +int start_id
        +int end_id
        +Metrics metrics
        +str last_error
        +View view
        +save_to_session(sid, file_store, user_id)
        +restore_from_session(sid, file_store, user_id)$
        +get_current_user_intent() tuple
        +get_last_agent_message() MessageAction
        +get_last_user_message() MessageAction
        +to_llm_metadata(model_name, agent_name) dict
        +get_local_step() int
        +get_local_metrics() Metrics
    }

    class StateTracker {
        -str sid
        -FileStore file_store
        -State state
        +set_initial_state(id, state, conversation_stats, ...)
        +close(event_stream: EventStream)
        +add_history(event: Event)
        +get_trajectory(include_screenshots) list~dict~
        +maybe_increase_control_flags_limits(headless_mode)
        +get_metrics_snapshot() Metrics
        +save_state()
        +run_control_flags()
        +sync_budget_flag_with_metrics()
    }

    class ControlFlag~T~ {
        <<abstract>>
        +T limit_increase_amount
        +T current_value
        +T max_value
        +bool headless_mode
        +reached_limit()* bool
        +increase_limit(headless_mode)* 
        +step()* 
    }

    class IterationControlFlag {
        +reached_limit() bool
        +increase_limit(headless_mode)
        +step()
    }

    class BudgetControlFlag {
        +reached_limit() bool
        +increase_limit(headless_mode)
        +step()
    }

    ControlFlag <|-- IterationControlFlag
    ControlFlag <|-- BudgetControlFlag
    State *-- IterationControlFlag
    State *-- BudgetControlFlag
    StateTracker --> State : manages
    AgentController --> StateTracker : uses
Loading

Цикл работы контроллера

stateDiagram-v2
    [*] --> LOADING
    LOADING --> RUNNING : agent initialized
    RUNNING --> RUNNING : step() loop
    RUNNING --> AWAITING_USER_INPUT : agent requests input
    AWAITING_USER_INPUT --> RUNNING : user provides input
    RUNNING --> AWAITING_USER_CONFIRMATION : security check
    AWAITING_USER_CONFIRMATION --> RUNNING : USER_CONFIRMED
    AWAITING_USER_CONFIRMATION --> STOPPED : USER_REJECTED
    RUNNING --> FINISHED : AgentFinishAction
    RUNNING --> REJECTED : AgentRejectAction
    RUNNING --> ERROR : exception
    RUNNING --> PAUSED : PAUSE action
    PAUSED --> RUNNING : RESUME action
    RUNNING --> RATE_LIMITED : LLM rate limit
    RATE_LIMITED --> RUNNING : retry success
    RUNNING --> STOPPED : max iterations/budget

    state RUNNING {
        [*] --> check_replay
        check_replay --> replay_step : has replay events
        check_replay --> agent_step : no replay
        replay_step --> handle_action
        agent_step --> handle_action
        handle_action --> run_in_runtime
        run_in_runtime --> handle_observation
        handle_observation --> check_stuck
        check_stuck --> loop_recovery : stuck detected
        check_stuck --> [*] : not stuck
        loop_recovery --> [*]
    }
Loading

Детальный flow обработки одного шага

sequenceDiagram
    participant C as AgentController
    participant RM as ReplayManager
    participant A as Agent
    participant L as LLM
    participant R as Runtime
    participant ES as EventStream
    participant SD as StuckDetector
    participant SEC as SecurityAnalyzer
    participant MEM as Memory

    C->>C: _step()
    C->>RM: has_replay_events()?
    alt Есть replay-события
        RM-->>C: Action из replay
    else Нет replay
        C->>MEM: get_state()
        MEM-->>C: State с condensed history
        C->>A: step(state)
        A->>L: completion(messages, tools)
        L-->>A: ModelResponse
        A->>A: parse response → Action
        A-->>C: Action
    end

    C->>SEC: analyze(action)?
    SEC-->>C: SecurityResult

    alt Action = AgentFinishAction
        C->>ES: add_event(finish)
        C->>C: set_agent_state(FINISHED)
    else Action = CmdRunAction / FileEditAction / etc
        C->>ES: add_event(action)
        C->>R: run_action(action)
        R-->>C: Observation
        C->>ES: add_event(observation)
    end

    C->>SD: check_stuck(state)
    alt Stuck detected
        SD-->>C: StuckAnalysis
        C->>C: attempt recovery
    end
Loading

Budget & Iteration Control

classDiagram
    class IterationControlFlag {
        +int max_iterations
        +check(state: State) bool
    }

    class BudgetControlFlag {
        +float max_budget_per_task
        +check(state: State) bool
    }

    class ControlFlag {
        <<abstract>>
        +check(state: State)* bool
    }

    ControlFlag <|-- IterationControlFlag
    ControlFlag <|-- BudgetControlFlag
Loading