Expand description
Task 23 — per-turn budgets (spec §8.1).
Every stream session runs under one TurnBudget: provider rounds,
tool calls, elapsed wall-clock, accumulated tool-result bytes, and the
optional context-token / USD-cost dimensions. Budgets differ by role
(foreground, autonomous/watcher, worker) but share ONE enforcement
mechanism — the TurnBudgetMeter consulted by the stream loop.
Composition note: the chat frontend’s reactor auto-turn cap
(events.auto_turn_cap, default engine::reactor::AUTO_TURN_CAP) limits consecutive auto-triggered
turns ACROSS turns; this budget bounds work WITHIN one turn. They
compose — neither replaces nor duplicates the other.
Structs§
- Owner
Steer Budget - Moves an event-started turn onto the session’s budget once the owner’s own message is delivered into it (a steer): from then on someone is watching. Shared by the session actor (which sends the owner’s steer) and the turn’s stream (which drains steering). Sending an owner steer and draining steering hold the same lock, so the stream takes the budget in the very drain that delivers the owner’s message, never before it and never for an event or note steered into the same channel.
- Turn
Budget - Per-turn limits (spec §8.1).
- Turn
Budget Meter - One turn’s running budget meter. NOT thread-shared: owned by the
stream loop; the only cross-task input is the
UsageCounterscell. - Usage
Counters - Shared provider-usage counters, updated at the single authoritative Usage emission sites in the transport and read by the stream loop for the optional token/cost dimensions. Metadata only.
Enums§
- Turn
Role - Execution role a turn runs under.
Constants§
- TOOL_
CALL_ BUDGET_ REFUSAL - The synthetic tool_result for a call refused by the turn’s tool-call allowance.
- TOOL_
CALL_ NOT_ EXECUTED - Start of every synthetic tool_result for a call the engine did not run because a turn budget was used up. Hosts that count executed calls (the watcher agent) skip results that start with it.