Documentation
¶
Overview ¶
Package event defines the core event types for the LoopKit event-sourced loop kernel. Events are append-only, immutable records of everything that happened in a loop. The chain hash provides tamper evidence and enables strict replay verification.
Index ¶
- func ComputeHash(prev [32]byte, e Envelope) [32]byte
- func Marshal(v any) ([]byte, error)
- func Unmarshal(data []byte, v any) error
- type ActionRequestedPayload
- type BudgetChargedPayload
- type CompactionAppliedPayload
- type ConvergenceWarningPayload
- type Envelope
- type ForkedFromPayload
- type HumanRequestedPayload
- type HumanRespondedPayload
- type InterruptedPayload
- type IterationStartedPayload
- type Kind
- type LoopFinishedPayload
- type LoopID
- type LoopStartedPayload
- type ModelCalledPayload
- type ModelUsage
- type PolicyDecidedPayload
- type ResumedPayload
- type Snapshot
- type SnapshotTakenPayload
- type StreamChunk
- type SubAgentCompletedPayload
- type SubAgentSpawnedPayload
- type ToolCalledPayload
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ComputeHash ¶
ComputeHash computes the chain hash for an envelope. Formula: SHA-256(prevHash ‖ []byte(LoopID) ‖ Seq_as_8_big_endian_bytes ‖ []byte(Time.RFC3339Nano) ‖ []byte(Kind) ‖ Payload)
Types ¶
type ActionRequestedPayload ¶
type ActionRequestedPayload struct {
ActionID string `json:"action_id"`
ActionType string `json:"action_type"`
ActionPayload json.RawMessage `json:"action_payload"`
}
ActionRequestedPayload is the intent record appended before an action executes. This implements the durability protocol: intent before effect.
type BudgetChargedPayload ¶
type BudgetChargedPayload struct {
// Tokens charged in this event.
Tokens int64 `json:"tokens,omitempty"`
// USD charged in this event.
USD float64 `json:"usd,omitempty"`
// WallClockMs charged in this event (milliseconds).
WallClockMs int64 `json:"wall_clock_ms,omitempty"`
// Iterations charged in this event.
Iterations int `json:"iterations,omitempty"`
// ActionType is the kind of action that generated this charge ("model" | "tool" | "iteration").
ActionType string `json:"action_type"`
}
BudgetChargedPayload records an actual spend charge against the budget ledger.
type CompactionAppliedPayload ¶
type CompactionAppliedPayload struct {
Strategy string `json:"strategy"`
// PlanJSON is the serialised ctxmgr.Plan. Replay reads this instead of re-deciding.
PlanJSON json.RawMessage `json:"plan_json"`
// Legacy fields kept for backward compat with SP3 stub (DroppedFrom/To/SummaryRef).
DroppedFrom uint64 `json:"dropped_from,omitempty"`
DroppedTo uint64 `json:"dropped_to,omitempty"`
SummaryRef string `json:"summary_ref,omitempty"`
}
CompactionAppliedPayload records a context-management compaction that occurred before a ModelCall. The Plan is stored verbatim so replay can re-apply it deterministically without re-running the Strategy.
type ConvergenceWarningPayload ¶
type ConvergenceWarningPayload struct {
// Detector is the name of the detector that fired ("oscillation" | "zero-progress" | "depth").
Detector string `json:"detector"`
// Reason is a human-readable explanation.
Reason string `json:"reason"`
// Count is how many times the condition has been observed.
Count int `json:"count"`
}
ConvergenceWarningPayload is injected when the convergence monitor fires in Redirect mode. The transition can inspect this event and change strategy.
type Envelope ¶
type Envelope struct {
// LoopID identifies which loop this event belongs to.
LoopID LoopID
// Seq is 1-based and contiguous within a loop. No gaps are permitted.
Seq uint64
// Time is injected by the runtime Clock. Transitions must NOT read the system clock;
// they must use ctx.Now which comes from the last event's Time field.
Time time.Time
// Kind identifies the event type. See Kind constants in kinds.go.
Kind Kind
// Payload is canonical JSON (sorted keys, no insignificant whitespace).
// Always produced via event.Marshal.
Payload []byte
// Hash is SHA-256(prevHash ‖ LoopID ‖ Seq ‖ Time(RFC3339Nano) ‖ Kind ‖ Payload).
// The zero value of prevHash is used for the first event in a loop.
Hash [32]byte
}
Envelope is the immutable record wrapper for every event stored in the log. The Hash field chains each envelope to its predecessor, enabling tamper detection.
type ForkedFromPayload ¶
type ForkedFromPayload struct {
// SourceLoopID is the loop ID that was forked from.
SourceLoopID LoopID `json:"source_loop_id"`
// AtSeq is the sequence number at which the fork diverged.
// Events 1..AtSeq are replayed from the source; events after are live.
AtSeq uint64 `json:"at_seq"`
}
ForkedFromPayload records that a forked loop branched off from a source trajectory. The forked loop's first event is ForkedFrom; the source log is immutable.
type HumanRequestedPayload ¶
type HumanRequestedPayload struct {
ActionID string `json:"action_id"`
Prompt string `json:"prompt"`
}
HumanRequestedPayload records a pause for human input.
type HumanRespondedPayload ¶
type HumanRespondedPayload struct {
ActionID string `json:"action_id"`
Response string `json:"response"`
}
HumanRespondedPayload records the human's response.
type InterruptedPayload ¶
type InterruptedPayload struct {
Reason string `json:"reason"`
}
InterruptedPayload records why a loop was interrupted.
type IterationStartedPayload ¶
type IterationStartedPayload struct {
Iteration int `json:"iteration"`
}
IterationStartedPayload marks the beginning of iteration n.
type Kind ¶
type Kind string
Kind is the string identifier for an event type.
const ( KindLoopStarted Kind = "LoopStarted" KindIterationStarted Kind = "IterationStarted" KindActionRequested Kind = "ActionRequested" KindModelCalled Kind = "ModelCalled" KindToolCalled Kind = "ToolCalled" KindHumanRequested Kind = "HumanRequested" KindHumanResponded Kind = "HumanResponded" KindSubAgentSpawned Kind = "SubAgentSpawned" // reserved: SP5 KindSubAgentCompleted Kind = "SubAgentCompleted" // reserved: SP5 KindBudgetCharged Kind = "BudgetCharged" // SP3: governance KindPolicyDecided Kind = "PolicyDecided" // SP3: governance KindConvergenceWarning Kind = "ConvergenceWarning" // SP3: convergence monitor KindCompactionApplied Kind = "CompactionApplied" // SP3: context management KindSnapshotTaken Kind = "SnapshotTaken" KindInterrupted Kind = "Interrupted" KindResumed Kind = "Resumed" KindLoopFinished Kind = "LoopFinished" KindForkedFrom Kind = "ForkedFrom" // SP4: fork replay )
Event kind constants. All kinds listed here (including reserved ones for future sub-projects).
type LoopFinishedPayload ¶
type LoopFinishedPayload struct {
OutcomeKind string `json:"outcome_kind"`
Result json.RawMessage `json:"result,omitempty"`
Error string `json:"error,omitempty"`
TotalSpend json.RawMessage `json:"total_spend,omitempty"`
}
LoopFinishedPayload records the terminal outcome of a loop.
type LoopID ¶
type LoopID string
LoopID is a ULID string identifying a loop instance. Generated by the runtime and recorded in the LoopStarted event.
type LoopStartedPayload ¶
type LoopStartedPayload struct {
Name string `json:"name"`
InitialState json.RawMessage `json:"initial_state"`
Seed int64 `json:"seed"`
ConfigHash string `json:"config_hash"`
// SP5: multi-agent fields (zero value = top-level loop)
ParentID LoopID `json:"parent_id,omitempty"` // empty for root loops
Depth int `json:"depth,omitempty"` // 0 = root; parent+1 for children
}
LoopStartedPayload carries the initial configuration of a loop.
type ModelCalledPayload ¶
type ModelCalledPayload struct {
ActionID string `json:"action_id"`
Request json.RawMessage `json:"request"`
Response json.RawMessage `json:"response"`
Usage ModelUsage `json:"usage"`
Provider string `json:"provider"`
Model string `json:"model"`
DurationMs int64 `json:"duration_ms"`
}
ModelCalledPayload records the result of a model completion call.
type ModelUsage ¶
type ModelUsage struct {
In int `json:"in"`
Out int `json:"out"`
CostUSD float64 `json:"cost_usd"`
}
ModelUsage tracks token and cost consumption for a single model call.
type PolicyDecidedPayload ¶
type PolicyDecidedPayload struct {
// ActionID links back to the ActionRequested event.
ActionID string `json:"action_id"`
// Decision is "allow" | "deny" | "ask-human".
Decision string `json:"decision"`
// Capability is the capability string that was evaluated.
Capability string `json:"capability"`
// Tool is the tool name that triggered the check.
Tool string `json:"tool"`
// Reason is the human-readable explanation from the policy engine.
Reason string `json:"reason"`
}
PolicyDecidedPayload records a policy engine decision for a tool call.
type ResumedPayload ¶
type ResumedPayload struct{}
ResumedPayload has no fields — resumption is its own record.
type Snapshot ¶
type Snapshot struct {
// LoopID identifies the loop this snapshot belongs to.
LoopID LoopID
// Seq is the sequence number of the last event included in this snapshot.
Seq uint64
// State is the canonical JSON-encoded state at this point.
State []byte
// StateHash is SHA-256 of the State bytes, for integrity verification.
StateHash [32]byte
// TakenAt is when the snapshot was recorded (wall clock of the runner).
TakenAt time.Time
}
Snapshot captures a materialized state at a given sequence number. Snapshots are used to bound replay time: instead of replaying from the beginning, resume starts from the latest snapshot and replays only the tail events.
type SnapshotTakenPayload ¶
type SnapshotTakenPayload struct {
Seq uint64 `json:"seq"`
StateHash string `json:"state_hash"` // hex-encoded SHA-256 of state
}
SnapshotTakenPayload records when a snapshot was written.
type StreamChunk ¶
type StreamChunk struct {
// Delta contains the incremental content update (e.g., a text delta or tool-use chunk).
// See core/model.Chunk for the wire format definition.
Delta json.RawMessage `json:"delta"`
// Usage is set only in the final chunk; nil for intermediate chunks.
Usage *ModelUsage `json:"usage,omitempty"`
}
StreamChunk represents a chunk of streamed model response data. It is used by StreamReader.Recv() and StreamObserver callbacks.
type SubAgentCompletedPayload ¶
type SubAgentCompletedPayload struct {
ChildLoopID string `json:"child_loop_id"`
Definition string `json:"definition"`
// OutcomeKind is "Completed" | "BudgetExceeded" | "Stuck" | "Failed" | "Interrupted" | "PolicyDenied".
OutcomeKind string `json:"outcome_kind"`
// RespJSON is the marshalled child result (only set when OutcomeKind == "Completed").
RespJSON json.RawMessage `json:"resp_json,omitempty"`
// Error is a human-readable error string for non-Completed outcomes.
Error string `json:"error,omitempty"`
// ChildSpend is the actual spend charged to the parent ledger for this child.
ChildSpend json.RawMessage `json:"child_spend,omitempty"`
}
SubAgentCompletedPayload records the result of a child loop. It is delivered to the parent transition after the child reaches a terminal outcome.
type SubAgentSpawnedPayload ¶
type SubAgentSpawnedPayload struct {
ChildLoopID string `json:"child_loop_id"`
Definition string `json:"definition"`
Request json.RawMessage `json:"request"`
}
SubAgentSpawnedPayload records that a child loop was launched by the parent.
type ToolCalledPayload ¶
type ToolCalledPayload struct {
ActionID string `json:"action_id"`
Tool string `json:"tool"`
Args json.RawMessage `json:"args"`
Result json.RawMessage `json:"result"`
IsError bool `json:"is_error"`
DurationMs int64 `json:"duration_ms"`
IdempotencyKey string `json:"idempotency_key"`
}
ToolCalledPayload records the result of a tool execution.