- AgentOrchestrator actor: turn-lifecycle state machine; LLMProvider protocol-driven; injection via providerFactory closure for testability - submit(_:) returns .ran or .rejected(.turnInFlight) - cancelAndSubmit(_:) returns .superseded(priorId, .bargedIn); critical AGENT-06 actor-reentrancy guard: priorTask.cancel() THEN `_ = await priorTask.value` BEFORE assigning new currentTurn (prevents late .messageStop from cancelled stream from clobbering currentTurn) - ReplayLog wired: turnNonce persisted via startTurn(turnNonce:); full blob via .toolResultFull (AGENT-08); SEC-06 invariant (nonce never appears in OrchestratorEvent emitted to bus) - ToolResultPacker integration: 8 KB cap on model-facing string (AGENT-08); full bytes preserved for replay via separate channel - Tool-use loop: append assistant tool_use msg, dispatch via ToolDispatcher, append wrapped tool_result msg, re-invoke provider - Architectural deviation (Rule 3 — blocking dep cycle): Replay already depends on AgentCore for TurnID; the plan's literal layout would have introduced AgentCore→Replay cycle. Resolved by carving a new target `AgentOrchestrator` in the AgentCore package, depending on both AgentCore and Replay. Plan files_modified paths shifted from `Sources/AgentCore/` to `Sources/AgentOrchestrator/` accordingly - 11 new tests (OrchestratorSubmitTests + OrchestratorCancelTests) plus MockLLMProvider scriptable test double; 105 total AgentCore tests green
18 lines
567 B
Swift
18 lines
567 B
Swift
import Foundation
|
|
import AgentCore
|
|
|
|
/// Tracks the AGENT-09 stream_truncated retry budget for one logical turn.
|
|
///
|
|
/// **Bounded at 1.** A second back-to-back truncation in the same logical
|
|
/// turn is terminal: orchestrator emits `.error(... .streamTruncatedFinal)`
|
|
/// and ends the turn. No exponential backoff, no rolling window — one shot.
|
|
struct RetryState: Sendable {
|
|
var budget: Int = 1
|
|
var originalTurnId: TurnID
|
|
|
|
init(originalTurnId: TurnID, budget: Int = 1) {
|
|
self.originalTurnId = originalTurnId
|
|
self.budget = budget
|
|
}
|
|
}
|