Documentation
¶
Overview ¶
Package view builds read models over a store for operator surfaces: what runs exist, what a run did, and which approval is waiting. Everything here reads; nothing decides. The summaries are the shape cmd/agentrt prints and both consumers' own commands report.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrNotPending = errors.New("approval is not pending") ErrNoPendingApproval = errors.New("no pending approval") ErrAmbiguousApproval = errors.New("more than one pending approval") )
Errors PendingApproval wraps, so a front end can match them and word its own message; the text carries the ids.
Functions ¶
func PendingApproval ¶
func PendingApproval(ctx context.Context, store *agentrt.Store, runID, approvalID string) (agentrt.Approval, error)
PendingApproval selects the approval an operator means. With an id it fetches that approval and requires it to be pending; without one the run must have exactly one pending approval, and the error names the candidates when it does not, because guessing which one to grant is not the runtime's decision to make.
Example ¶
PendingApproval is the rule for choosing the approval an operator means: without an id the run must have exactly one pending approval, and a named approval must still be pending. Guessing is not the runtime's decision.
ctx := context.Background()
store, err := agentrt.OpenStore(":memory:")
if err != nil {
panic(err)
}
defer store.Close()
push := tool{spec: agentrt.ToolSpec{
Name: "push", Description: "push", SideEffect: agentrt.RemoteMutation, Timeout: time.Second,
InputSchema: []byte(`{"type":"object","properties":{"n":{"type":"integer"}},"additionalProperties":false}`),
}}
agent := &scripted.Agent{Decisions: []agentrt.Decision{scripted.ToolCall("push", `{"n":7}`, "publish")}}
d, err := agentrt.NewDriver(agentrt.Config{
Store: store, Agent: agent, Policy: agentrt.DefaultPolicy(),
Tools: []agentrt.Tool{push},
NewID: func() func() string {
n := 0
return func() string { n++; return fmt.Sprintf("id-%d", n) }
}(),
})
if err != nil {
panic(err)
}
run, err := d.Start(ctx, "publish the counter", agentrt.DefaultLimits())
if err != nil {
panic(err)
}
// One pending approval, so the operator need not name it.
a, err := view.PendingApproval(ctx, store, run.ID, "")
fmt.Println(a.ID, a.Kind, a.Status, err)
if err := d.Approve(ctx, run.ID, a.ID, "joey", ""); err != nil {
panic(err)
}
// Once decided it is no longer a candidate, by id or without one.
_, err = view.PendingApproval(ctx, store, run.ID, a.ID)
fmt.Println(errors.Is(err, view.ErrNotPending))
_, err = view.PendingApproval(ctx, store, run.ID, "")
fmt.Println(errors.Is(err, view.ErrNoPendingApproval))
Output: id-3 remote_mutation pending <nil> true true
Types ¶
type RunSummary ¶
type RunSummary struct {
ID string `json:"id"`
Goal string `json:"goal"`
Status agentrt.RunStatus `json:"status"`
Reason agentrt.TerminalReason `json:"reason,omitempty"`
ReasonDetail string `json:"reason_detail,omitempty"`
Steps int `json:"steps"`
CreatedAt time.Time `json:"created_at"`
FinishedAt time.Time `json:"finished_at,omitempty"`
// PendingApprovalID is set only for a run waiting for approval, which is
// the only state in which an approval can still be decided.
PendingApprovalID string `json:"pending_approval_id,omitempty"`
ModelCalls int `json:"model_calls,omitempty"`
Usage agentrt.Usage `json:"usage,omitzero"`
EstimatedCost agentrt.Micros `json:"estimated_cost_micros,omitempty"`
}
RunSummary is one run as an operator needs to see it. The model totals come from the run row itself, so a summary costs no extra query.
type StepSummary ¶
type StepSummary struct {
Index int `json:"index"`
ID string `json:"id"`
Tool string `json:"tool,omitempty"`
Decision agentrt.DecisionKind `json:"decision,omitempty"`
Status agentrt.StepStatus `json:"status"`
Policy agentrt.PolicyOutcome `json:"policy,omitempty"`
Observation agentrt.ObservationKind `json:"observation,omitempty"`
Summary string `json:"summary,omitempty"`
}
StepSummary is one step: what the agent asked for, what the policy said, and what came back.