Жизненный цикл хода

Полный путь одного хода (turn) агента: от TurnStart до TurnEnd.

Издатель: Agent (Run, loop.go:69)

Подписчики:

  • TUI → handleTurnStartTurnActive = true, сброс stream buffers
  • Manager → StartStatusListenerSetState(SessionRunning)

Издатель: Agent (finishTurn, loop.go:244)

Подписчики:

  • TUI → handleTurnEndTurnActive = false, finalize assistant message
  • Manager → StartStatusListenerSetState(SessionIdle)

Издатель: LLM provider (через makeStreamCallback)

Подписчик: TUI → handleStreamingToken → накапливает в StreamBuf

kind: "" / "text" — обычный вывод, "thinking" — reasoning (dim/italic)

Издатель: Agent при стрим-ошибке без возможности autorcompact

Подписчик: TUI → handleError → сообщение об ошибке в чате

Издатель: LLM retry layer (retry.go)

Подписчик: TUI → handleRetry → показывает countdown до retry

Издатель: Agent при auto-compact (tryAutoCompact)

Подписчик: TUI → handleCompaction → индикатор компактизации

Издатель: TUI (onAbort), сабагент (при отмене родительского контекста)

Подписчик: Agent → слушает в начале Run, вызывает cancelTurn()

Издатель: ask_user tool

Подписчик: TUI → handleAskUser → интерактивный picker

Издатель: Agent (StatsTracker) после каждой итерации

Подписчик: TUI → handleStats → обновление сайдбара

Издатель: Agent после каждого LLM ответа

Подписчик: TUI → handleMessageStats → токены на сообщении

sequenceDiagram
    participant TUI
    participant A as Agent.Run
    participant LLM
    participant T as Tool

    A->>TUI: TurnStart
    Note over TUI: TurnActive=true

    loop Итерации (stream → tools → repeat)
        A->>LLM: Stream(request)
        loop Токены
            LLM-->>A: delta
            A->>TUI: StreamingToken(delta)
        end

        A->>TUI: MessageStats(tokens)

        alt Есть tool calls
            A->>TUI: ToolCall
            alt Требует approval
                A->>TUI: ToolApprovalRequest
                TUI->>A: ToolApprovalResponse
            end
            A->>T: Execute
            T-->>A: Result
            A->>TUI: ToolResult
        else Без tools
            A->>A: drainPending (новые сообщения?)
        end
    end

    A->>TUI: TurnEnd{stopReason, usage}
    Note over TUI: TurnActive=false, finalize
sequenceDiagram
    participant TUI
    participant A as Agent.Run
    participant LLM

    Note over A: Стрим идёт...
    TUI->>A: AbortRequest{sessionID}
    Note over A: abortCh ← signal
    A->>A: cancelTurn()
    Note over A: turnCtx cancelled
    LLM-->>A: stream error (ctx cancelled)
    A->>A: persistPartial
    A->>TUI: TurnEnd{stopReason: aborted}