-
Notifications
You must be signed in to change notification settings - Fork 90
Expand file tree
/
Copy pathengine_output.py
More file actions
79 lines (57 loc) · 2.76 KB
/
Copy pathengine_output.py
File metadata and controls
79 lines (57 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
from __future__ import annotations
from typing import TypeAlias
from pydantic import BaseModel, ConfigDict
from engine.models.messages import AgentMessage
class AgentOutputItem(BaseModel):
"""Public, lineage-rich wrapper around one durable AgentMessage emitted by an agent.
Tool calls and tool results live inside ``item`` (an AgentMessage), not as separate
payload types — that keeps interleaved parallel-child output trivially groupable
by lineage fields while preserving messages-array compatibility. ``final=True``
marks the root agent's terminating assistant message.
"""
model_config = ConfigDict(extra="forbid")
sequence: int
agent_id: str
parent_agent_id: str | None
parent_tool_call_id: str | None
agent_name: str
depth: int
item: AgentMessage
final: bool = False
class AgentTextDelta(BaseModel):
"""Incremental token-level delta emitted between durable AgentOutputItems while assistant text streams."""
model_config = ConfigDict(extra="forbid")
sequence: int
agent_id: str
parent_agent_id: str | None
parent_tool_call_id: str | None
depth: int
item_id: str
text_delta: str
class RunCheckpoint(BaseModel):
"""The root agent's full conversation state at a resumable boundary.
A HALO run that dies at turn 40 of 50 currently restarts from turn zero and
re-pays for all 40, because nothing about its conversation survives the
process — ``EngineRunState`` is in-memory only. The engine can already
*resume* from a message array (``AgentContext.from_input_messages`` passes a
caller-supplied system message through unchanged, expressly to support
continuations); what was missing is anything that durably emits one.
``messages`` is exactly what ``from_input_messages`` accepts, so a host can
persist the latest checkpoint and hand it straight back to restart mid-run.
Root only. Subagent state is transient — a resumed run re-derives it — and
checkpointing every agent would multiply payload size for state nothing
reads.
Emitted only when ``EngineConfig.emit_run_checkpoints`` is set. It is off by
default because this widens ``EngineStreamEvent``, and a host pinned to an
older engine must not receive a variant it cannot parse.
"""
model_config = ConfigDict(extra="forbid")
sequence: int
agent_id: str
#: Turns the root agent has consumed at this boundary — lets a host tell
#: checkpoint order without depending on bus sequence numbers.
turns_used: int
messages: list[AgentMessage]
EngineStreamEvent: TypeAlias = AgentOutputItem | AgentTextDelta | RunCheckpoint
"""Anything the EngineOutputBus can yield: a durable item, a streaming text
delta, or a resumable checkpoint of root conversation state."""