Help us shape the future of Go! Take the 2026 Go Developer Survey

sugasdk

package
v0.54.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package sugasdk embeds suga in another program, in process: the host opens an engine, opens sessions in its own workspaces, runs turns and reads the answers and events, and reaches the same session history and memory the suga CLI uses.

Experimental

The package is a first version: the API may change in a minor release until the host that embeds it has settled. Types and methods are documented with the behaviour they promise; the wire-level details of suga (events, trace, store) are not part of this contract.

One engine per process

suga's configuration (config.yaml, .env, the model selection, tools.*) is process global. Therefore a process holds at most one open Engine: a second Open returns ErrEngineOpen, and after Close an Open is possible again. The data root is guarded the same way: Open sets $SUGA_HOME and loads the configuration when the process has none, reuses the configuration of the same root, and returns ErrSugaHomeMismatch when the process already loaded another root. The loaded configuration stays for the life of the process.

Sessions

Every session assembles its own runtime for its workspace (tools, provider, project rules, memory scope), so sessions of different directories can run side by side. A host may set SessionOptions.ProjectMemoryKey to pin a session's project memory to an isolated files scope under <SUGA_HOME>/projects/<key>/memory; this bypasses repository discovery and memory.project.backend for that session. A session runs one turn at a time: a second concurrent Send returns ErrBusy instead of queueing, and Steer inserts text into a turn that is already running (ErrNoRunningTurn when there is none), and Cancel stops the in-flight turn so the session can continue with a later Send. A panic inside a turn is recovered and returned as an error; it never propagates to the host. Entry reads an immutable session record by its "<session>/<seq>" reference with a window of neighboring records; record sequence numbers are append-only.

Idempotent sends

Prompt.RequestID (recommended: a UUID the caller generates, scoped to one session) makes a Send deduplicated instead of always running: with an id this session already finished, Send replays the stored first result with Result.Replayed set and the model is not called again. The replay comes from storage: a small record in the session meta (turn id, state, a summary with the usage numbers and the end time; never the answer text, so the meta does not grow with the length of the answers), and the output rebuilt from the turn's own assistant entry. A turn whose entries are gone from the session log no longer replays: Send reports ErrRequestOutputGone. Each session keeps only the most recent 200 of these records (requestRecordLimit) - the window serves reconnects, so older finished records (but never a running one) drop from the meta as newer claims arrive, and an id trimmed out of the window is an unclaimed request to Send again. An id whose turn is running errors with ErrRequestRunning; a record left running by a process that died mid-turn (delivery unknown) errors with ErrDeliveryUncertain and reads "unknown" from Session.RequestStatus: the host resends the prompt under a NEW request id, nothing replays on its own. The mapping and outcomes survive restarts and a reopened session handle answers the same way. A Prompt without a RequestID keeps the plain behaviour. Missing or blank ids in place of RequestID (a Prompt with a whitespace-only id) are refused.

Sessions opened without SessionOptions.Origin record origin "sdk" (or the EngineOptions.Origin value) and are retained as non-interactive sessions. Hosts that need longer retention should use Engine.Pin.

Engine.Pin keeps a session and its history out of both automatic garbage collection modes until the host clears the marker, regardless of origin.

Tool invocations

The runtime gives every tool call an invocation id and puts it in the context the tool runs with: tools.InvocationID(ctx). It is the same for the hooks around that call (BeforeTool, AfterTool) and different for every call of a session, so a host tool can use it as the idempotency key of its own side-effect ledger. suga keeps the same guarantee on its side: a call with side effects is written down before it runs, and a turn that was interrupted between running the call and storing its result replays it as "state unknown" instead of running it again - the host can answer an id it has seen the same way (see the tool_invocation ledger in the trace).

Thread safety

Open, Close and OpenSession are safe to call from several goroutines, as are the Engine methods (Memory, Search, Sessions): they share the engine's locks. A Session's Send, Steer, Card, Compact and Close may be called from several goroutines too - Send and Steer are meant to be, since a turn is steered while it runs - and Close makes later calls return ErrSessionClosed. The Event callback of Send runs on the goroutine of the turn that emits it; it must not call Send on the same session (that is ErrBusy) but may call Steer.

Scope

The SDK covers suga's programmatic side: one turn with its events and result, steering, the session card, compaction, session search and listing, and the memory store. It does not offer the chat terminal, hooks beyond agentcore.Hook, ACP or the MCP server gate; a host that needs those runs the CLI or the ACP server instead.

Index

Constants

View Source
const (
	DefaultEntriesLimit = 100
	MaxEntriesLimit     = 1000
)

Entries limits for Engine.Entries: a zero or negative limit means the default, anything above the maximum is clamped.

View Source
const (
	// RequestStatusUnknown: no record for the id, or one left running by a
	// process that is not running it any more (it died mid-turn). Delivery is
	// uncertain: the host resends the prompt under a NEW request id.
	RequestStatusUnknown = "unknown"
	// RequestStatusRunning: the id's turn currently runs in this session.
	RequestStatusRunning = "running"
	// RequestStatusDone: the turn finished and its outcome is stored.
	RequestStatusDone = "done"
	// RequestStatusFailed: the finished turn failed (or was cancelled).
	RequestStatusFailed = "failed"
)

Request status values returned by Session.RequestStatus.

View Source
const OriginSDK = store.OriginSDK

OriginSDK is the session origin the SDK records when no origin is configured. Hosts that need longer retention should pin sessions with Engine.Pin.

Variables

View Source
var (
	// ErrEngineOpen reports a second Open in a process that has an engine.
	ErrEngineOpen = errors.New("sugasdk: an engine is already open in this process")
	// ErrEngineClosed reports a use of an engine (or of a session it opened)
	// after Close.
	ErrEngineClosed = errors.New("sugasdk: engine is closed")
	// ErrSugaHomeMismatch reports an Open for a data root other than the one
	// this process already loaded: suga's configuration is process global.
	ErrSugaHomeMismatch = errors.New("sugasdk: this process already loaded suga configuration from another SUGA_HOME")
	// ErrBusy reports Send on a session whose previous turn still runs; the
	// turns of one session never queue.
	ErrBusy = errors.New("sugasdk: a turn is already running in this session")
	// ErrNoRunningTurn reports Steer while no turn of the session runs.
	ErrNoRunningTurn = errors.New("sugasdk: no turn is running in this session")
	// ErrRequestRunning reports Send with a RequestID whose turn is currently
	// running in this session (the caller retries when it finishes).
	ErrRequestRunning = errors.New("sugasdk: this request is already running in this session")
	// ErrDeliveryUncertain reports Send with a RequestID whose record says
	// running but whose turn is not running in any live place (the claiming
	// process died mid-turn): whether the prompt was delivered is unknown.
	// Send the prompt again under a NEW request id; the old one is never
	// replayed on its own.
	ErrDeliveryUncertain = errors.New("sugasdk: the delivery of this request is uncertain (it was interrupted while running); resend with a new request id")
	// ErrRequestOutputGone reports a replayable request whose turn's answer is
	// no longer in the session log (the entries were trimmed after the request
	// aged past what the storage keeps), so its output cannot be rebuilt.
	ErrRequestOutputGone = errors.New("sugasdk: the stored answer of the request is gone from the session log")
	// ErrSessionClosed reports a use of a session after Close.
	ErrSessionClosed = errors.New("sugasdk: session is closed")
	// ErrOutputContract reports a send whose final answer does not satisfy
	// Prompt.OutputSchema, even after the one correction round: the turn itself
	// completed (Result.State stays COMPLETED), the answer's shape did not meet the
	// caller's contract. Result.OutputContract carries the report.
	ErrOutputContract = errors.New("sugasdk: the answer does not satisfy the output schema")
	// ErrInvalidOutputSchema reports a Prompt.OutputSchema that does not compile:
	// the send fails before any turn starts.
	ErrInvalidOutputSchema = errors.New("sugasdk: the output schema is invalid")
)

Errors of the engine and its sessions; test them with errors.Is.

Functions

This section is empty.

Types

type Card

type Card struct {
	SessionID string    `json:"session_id"`
	Title     string    `json:"title,omitempty"`
	State     string    `json:"state"`
	Origin    string    `json:"origin,omitempty"`
	CreatedAt time.Time `json:"created_at"`
	// LastActiveAt is the newest entry of the session (its update time for an
	// empty session).
	LastActiveAt time.Time `json:"last_active_at"`
	// LatestSummary is the newest handoff or compaction summary; SummaryKind
	// says which ("handoff" or "compaction").
	LatestSummary string    `json:"latest_summary,omitempty"`
	SummaryKind   string    `json:"summary_kind,omitempty"`
	SummaryAt     time.Time `json:"summary_at"`
	// OpenSteps are the pending and in_progress steps of the latest plan.
	OpenSteps     []string  `json:"open_steps,omitempty"`
	PlanUpdatedAt time.Time `json:"plan_updated_at"`
	Usage         Usage     `json:"usage"`
	// SegmentCount counts the segment records (1 = never compacted), Turns the
	// turns started in the session.
	SegmentCount int `json:"segment_count"`
	Turns        int `json:"turns"`
}

Card is a read-only snapshot of where a session stands.

type ContractError

type ContractError struct {
	// Path is the JSON path of the offending value, e.g. $ or $.items[0].id.
	Path string `json:"path"`
	// Message is the one-line reason.
	Message string `json:"message"`
}

ContractError is one validation problem of a checked answer.

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine is the embedding host's handle on suga in this process: the loaded configuration, the sessions it opened and the memory and history of the data root. One process holds at most one engine at a time.

func Open

func Open(ctx context.Context, opts EngineOptions) (*Engine, error)

Open loads suga's configuration for opts.SugaHome if this process has not loaded one yet, and returns the engine. A process that already loaded the same root reuses it; another root is an error (suga's settings are process global). A second Open while an engine is open is an error too: Close it first.

func (*Engine) Close

func (e *Engine) Close() error

Close releases the engine: the memory layer, the store behind it and every session this engine opened. Sessions closed by the caller first are skipped. Close it while no turn runs: a session's runtime is closed here, so a Send still in flight fails. The loaded suga configuration stays in the process (it cannot be unloaded); after Close another Open is allowed, for the same root only.

func (*Engine) Entries added in v0.53.0

func (e *Engine) Entries(ctx context.Context, sessionID string, fromSeq int64, limit int) ([]Entry, error)

Entries lists the records of one session in sequence order, starting at the first record whose Seq is >= fromSeq (fromSeq <= 1 starts at the beginning). It returns at most limit records (DefaultEntriesLimit when limit <= 0, clamped to MaxEntriesLimit); page by passing the last Seq + 1. A fromSeq past the end yields an empty slice. An unknown session is an error.

func (*Engine) Entry added in v0.52.0

func (e *Engine) Entry(ctx context.Context, ref string, window int) ([]Entry, error)

Entry reads one session record and its surrounding window. ref is "<session>/<seq>"; window includes that many records on either side. The sequence is assigned by the append-only store and is never rewritten.

func (*Engine) Home

func (e *Engine) Home() string

Home is the data root the engine's configuration came from.

func (*Engine) Memory

func (e *Engine) Memory() *Memory

Memory returns the memory API of this engine's data root and the project scope of the process directory. The memory layer is built on first use.

func (*Engine) Model

func (e *Engine) Model() string

Model is the engine's default model ref ("" = the configured model).

func (*Engine) OpenSession

func (e *Engine) OpenSession(ctx context.Context, id string, opts SessionOptions) (*Session, error)

OpenSession opens a conversation: an existing session id continues it, an empty or unknown one starts a new session (with that id when one is given). The runtime of the session is assembled here, so SessionOptions (workspace, model, extra tools, approver) apply from its first turn.

func (*Engine) Pin added in v0.52.0

func (e *Engine) Pin(ctx context.Context, sessionID string, pinned bool) error

Pin changes the persistent keep marker of a session. A pin protects the session from both age-based and origin-retention garbage collection. Explicit DeleteSession remains a deliberate manual deletion and is not blocked by a pin.

func (*Engine) Search

func (e *Engine) Search(ctx context.Context, query string, limit int) ([]Hit, error)

Search runs the session_search query of the whole store: every term must occur in one entry. limit <= 0 means 20, at most 100.

func (*Engine) Sessions

func (e *Engine) Sessions(ctx context.Context, filter SessionFilter) ([]SessionInfo, error)

Sessions lists the stored sessions (newest first) matching filter. Sub-agent sessions and archived ones stay hidden unless the filter asks for them.

func (*Engine) TraceEvents added in v0.53.0

func (e *Engine) TraceEvents(ctx context.Context, sessionID string, afterID int64, limit int) ([]TraceEvent, error)

TraceEvents lists the trace events of one session (the ones `suga inspect trace` shows) in creation order, those with ID > afterID. limit follows the same default/maximum as Entries; page by passing the last event's ID. An unknown session is an error. Plan records are not included.

type EngineOptions

type EngineOptions struct {
	// SugaHome is the data root (config.yaml, .env, db, sessions). Empty uses
	// $SUGA_HOME, or ~/.suga when that is unset too. suga's configuration is
	// process global: Open sets $SUGA_HOME to this root and loads it when the
	// process has not loaded one yet, reuses a configuration loaded from the
	// same root, and refuses a different one.
	SugaHome string
	// Model is the default model of the sessions this engine opens:
	// "<provider>/<model>" or a bare model id. Empty uses the configured model.
	Model string
	// Logger receives the engine's own diagnostics (nil = slog.Default()).
	Logger *slog.Logger
	// Origin is the session origin recorded by default on sessions this engine
	// creates; empty uses OriginSDK. Hosts that need longer retention should pin
	// sessions with Engine.Pin.
	Origin string
}

EngineOptions configures one engine of this process.

type Entry added in v0.52.0

type Entry struct {
	SessionID string          `json:"session_id"`
	Seq       int64           `json:"seq"`
	TurnID    string          `json:"turn_id,omitempty"`
	Type      string          `json:"type"`
	JSON      json.RawMessage `json:"json"`
	CreatedAt time.Time       `json:"created_at"`
}

Entry is one immutable session record returned by Engine.Entry. JSON is the stored record body; Seq remains stable for the lifetime of the session.

type Event

type Event struct {
	// Kind is the event kind: "text" (answer text), "tool_call" (before a tool
	// runs; Tool and Text name the call, ToolArgs its arguments), "tool_result"
	// (after it; Text is the result summary, IsError a failed or refused call),
	// "usage" (a counted model call), "run_finished" (the turn's total),
	// "retry" (a transient provider failure being retried, Text the reason),
	// "plan", "steer_delivered", "context_update", "session_recovered", ...
	Kind string
	// Text is the event's text: the streamed answer, the argument summary of a
	// tool call, the result summary of a tool result, the reason of a retry.
	Text string
	// Tool is the tool name of a tool_call / tool_result event.
	Tool string
	// ToolArgs are the whole arguments of a tool_call event (nil otherwise).
	ToolArgs map[string]any
	// IsError marks a tool result whose call failed or was refused.
	IsError bool
	// Usage is set on "usage" and "run_finished" events.
	Usage *Usage
	// Error is set on an "error" event.
	Error string
}

Event is one update of a running turn. Only stable fields are carried: the answer text as it streams, the tool name with a summary of its arguments and its result, usage and errors.

type Hit

type Hit struct {
	// Ref locates the entry ("<session>/<seq>", readable with recall).
	Ref       string    `json:"ref"`
	SessionID string    `json:"session_id"`
	Role      string    `json:"role"`
	Snippet   string    `json:"snippet"`
	CreatedAt time.Time `json:"created_at"`
}

Hit is one match of Engine.Search.

type Memory

type Memory struct {
	// contains filtered or unexported fields
}

Memory is the engine's memory API. It reads and writes the user scope and the project scope of the process directory, with the configured write policy (memory.write / memory.write_tainted).

func (*Memory) Add

func (m *Memory) Add(ctx context.Context, scope string, entry MemoryEntry) (MemoryEntry, error)

Add writes a new memory entry (title, body and kind are required; the id is derived from the title) and returns it as stored, including its UUID.

func (*Memory) Get added in v0.52.0

func (m *Memory) Get(ctx context.Context, uuid string) (MemoryEntry, error)

Get returns a live memory entry by its stable UUID. Deleted UUIDs remain in the metadata table as tombstones but cannot be used to resurrect content.

func (*Memory) List

func (m *Memory) List(ctx context.Context, scope string) ([]MemoryEntry, error)

List returns the entries of a scope. Backends that can enumerate hand back the bodies too; the others are asked for their index, so only id, kind, title and summary are filled.

func (*Memory) Remove added in v0.52.0

func (m *Memory) Remove(ctx context.Context, uuid string) error

Remove tombstones the memory addressed by uuid through the governed store.

func (*Memory) Search

func (m *Memory) Search(ctx context.Context, scope, query string, limit int) ([]MemoryEntry, error)

Search finds memory entries of a scope. scope is "user" or "project:<key>"; empty means "user". limit <= 0 uses the backend's default.

func (*Memory) Update added in v0.52.0

func (m *Memory) Update(ctx context.Context, uuid string, entry MemoryEntry) (MemoryEntry, error)

Update replaces the content addressed by uuid. The operation goes through Governed, so taint confirmation, sanitization, budgets and tombstones remain identical to memory-tool writes.

type MemoryConfirmRequest

type MemoryConfirmRequest struct {
	// Scope is "user" or "project:<key>".
	Scope string
	// Action is "add", "replace" or "remove".
	Action  string
	Kind    string
	ID      string
	Title   string
	Body    string
	Summary string
}

MemoryConfirmRequest is what a memory write would do; MemoryConfirm approves or refuses it.

type MemoryEntry

type MemoryEntry struct {
	UUID    string `json:"uuid,omitempty"`
	ID      string `json:"id,omitempty"`
	Title   string `json:"title,omitempty"`
	Body    string `json:"body,omitempty"`
	Kind    string `json:"kind,omitempty"`
	Summary string `json:"summary,omitempty"`
	// Scope is "user" or "project:<key>".
	Scope   string    `json:"scope,omitempty"`
	Updated time.Time `json:"updated"`
}

MemoryEntry is one memory item.

type OutputContract

type OutputContract struct {
	// Checked is false when the turn's end left nothing to judge (a failed,
	// yielded, wrapped-up or truncated turn, or an empty answer).
	Checked bool `json:"checked"`
	// Passed is the final check's outcome (meaningful only when Checked).
	Passed bool `json:"passed"`
	// Rounds counts the checks: 1 when the first answer was fine, 2 when the one
	// correction round was needed.
	Rounds int `json:"rounds"`
	// Source says where the checked JSON came from: whole, fenced, substring or
	// no_json.
	Source string `json:"source,omitempty"`
	// Reason says why the answer was not checked (Checked=false only).
	Reason string `json:"reason,omitempty"`
	// Errors are the last check's validation problems.
	Errors []ContractError `json:"errors,omitempty"`
}

OutputContract is the outcome of judging one send's answer against Prompt.OutputSchema. It is defined here (not taken from an internal package) so a host compiles against public types only.

type Prompt

type Prompt struct {
	// Text is the message a person or the host wants answered.
	Text string
	// Images are picture files attached to the message (same checks, scaling
	// and storage as chat's :image).
	Images []string
	// RequestID makes the turn an idempotent request of this session: the caller
	// generates it (a UUID is recommended) and it is scoped to one session.
	// Empty keeps the plain behaviour of Send. With an id, a Send for an id this
	// session already finished returns the stored first result with Result.Replayed
	// set instead of running the turn again; a Send for an id whose turn currently
	// runs errors with ErrRequestRunning; a record left running by a process that
	// died mid-turn reads as delivery uncertain (ErrDeliveryUncertain, and
	// "unknown" from RequestStatus): resend under a NEW id, nothing is replayed
	// on its own.
	RequestID string
	// OutputSchema is the JSON Schema this turn's final answer must satisfy (a
	// caller parameter of this send, not a session setting: empty means no
	// contract, and the next Send starts without one). A failing answer gets one
	// correction round, then Send returns ErrOutputContract with
	// Result.OutputContract.Passed=false (design 2026-10-22 2.2).
	OutputSchema json.RawMessage
}

Prompt is one turn's input: text plus pictures.

type Result

type Result struct {
	SessionID string `json:"session_id"`
	TurnID    string `json:"turn_id,omitempty"`
	// State is COMPLETED, INPUT_REQUIRED, FAILED or CANCELED.
	State string `json:"state"`
	// Output is the turn's final answer.
	Output string `json:"output"`
	// Usage is this turn's usage, SessionUsage the session's cumulative one.
	Usage        Usage `json:"usage"`
	SessionUsage Usage `json:"session_usage"`
	// DeniedTools lists the tools the approver refused, first refusal first.
	DeniedTools []string `json:"denied_tools,omitempty"`
	// WrapUp names why the answer stopped early ("max_steps", a hook's reason);
	// empty for a normal answer.
	WrapUp string `json:"wrap_up,omitempty"`
	// Truncated marks an answer cut off at the output token limit.
	Truncated bool `json:"truncated,omitempty"`
	// ReturnedSteers are the steering messages the turn did not deliver, as
	// text: the caller runs them as the next turn.
	ReturnedSteers []string `json:"returned_steers,omitempty"`
	// Replayed marks a result returned from the stored record of an earlier
	// Send with the same RequestID (the model was not called again).
	Replayed bool `json:"replayed,omitempty"`
	// OutputValue is the value that satisfied Prompt.OutputSchema: the extracted
	// JSON text, compacted (numbers keep their literal text). Empty without a
	// contract or when the contract failed.
	OutputValue json.RawMessage `json:"output_value,omitempty"`
	// OutputContract reports the output contract check; nil when the send had no
	// Prompt.OutputSchema.
	OutputContract *OutputContract `json:"output_contract,omitempty"`
}

Result is the outcome of one turn.

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session is one conversation: a persisted suga session plus the runtime (tools, provider, rules) assembled for its workspace.

func (*Session) Cancel added in v0.52.0

func (s *Session) Cancel() error

Cancel stops the current turn. It is safe to call concurrently with Send; after cancellation the session slot is released and a later Send can run.

func (*Session) Card

func (s *Session) Card(ctx context.Context) (Card, error)

Card reads where the session stands (latest summary, open plan steps, usage, activity). It writes nothing.

func (*Session) Close

func (s *Session) Close() error

Close releases the session's runtime and forgets it in the engine. It is idempotent. Close it while no turn runs: the runtime the turn uses is closed here, so a Send still in flight fails.

func (*Session) Compact

func (s *Session) Compact(ctx context.Context) error

Compact starts a new segment of the session now. A session with nothing to compact counts as success.

func (*Session) ID

func (s *Session) ID() string

ID is the persisted session id.

func (*Session) RequestStatus

func (s *Session) RequestStatus(ctx context.Context, requestID string) (string, error)

RequestStatus reports where the request requestID of this session stands: RequestStatusRunning while its turn runs here, RequestStatusDone or RequestStatusFailed once its stored outcome is replayable, and RequestStatusUnknown otherwise - including a record left running by a process that died mid-turn (delivery uncertain: resend with a new id).

func (*Session) Send

func (s *Session) Send(ctx context.Context, prompt Prompt, emit func(Event)) (res Result, err error)

Send runs one turn and streams its events to emit (which may be nil). The turn ends when ctx is cancelled; a panic inside the turn is recovered and returned as an error, so it never reaches the caller. A session runs one turn at a time: a second Send while one runs returns ErrBusy instead of queueing. With a RequestID the send is an idempotent request instead: an id already finished replays its stored first result (Result.Replayed), an id whose turn runs errors with ErrRequestRunning, and a record left running by a process that died mid-turn errors with ErrDeliveryUncertain (resend with a new id).

func (*Session) Steer

func (s *Session) Steer(text string) error

Steer inserts text into the running turn of the session (the turn's next model request carries it). ErrNoRunningTurn is returned when no turn of the session runs, so the caller runs the text as its next turn instead.

func (*Session) Workspace

func (s *Session) Workspace() string

Workspace is the directory the session's tools work in.

type SessionFilter

type SessionFilter struct {
	// Origin keeps one origin ("sdk", "chat", ...); "all" or empty keeps
	// every one.
	Origin string
	// Cwd keeps sessions of this directory and its descendants; empty keeps
	// every directory.
	Cwd string
	// IncludeAgents includes sub-agent sessions (hidden by default).
	IncludeAgents bool
	// IncludeArchived includes archived sessions (hidden by default).
	IncludeArchived bool
}

SessionFilter narrows Engine.Sessions.

type SessionInfo

type SessionInfo struct {
	ID        string    `json:"id"`
	Title     string    `json:"title,omitempty"`
	Cwd       string    `json:"cwd,omitempty"`
	Status    string    `json:"status"`
	Origin    string    `json:"origin,omitempty"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

SessionInfo is one row of Engine.Sessions.

type SessionOptions

type SessionOptions struct {
	// Workspace is the tool workspace root (absolute, or relative to the
	// process directory); empty uses the process directory. The session's
	// project rules, memory scope and file tools work in it.
	Workspace string
	// ProjectMemoryKey pins this session's project memory to a host-owned key.
	// A non-empty key ignores repository discovery and memory.project.backend.
	ProjectMemoryKey string
	// Model overrides EngineOptions.Model for this session.
	Model string
	// AllowWrite exposes the workspace write and shell tools.
	AllowWrite bool
	// ExtraTools are the host's own tools: they sit next to the built-in ones
	// (tool table, manifest, tool_search) and tools.disabled can remove them.
	// A name a built-in or MCP tool already has is an error. Execute reads
	// tools.InvocationID(ctx) - an id unique to the call, stable for the whole
	// call - so a host may use it as the idempotency key of its own side-effect
	// ledger (see doc.go, "Tool invocations").
	ExtraTools []api.Tool
	// Hooks observe the turn (agentcore.Hook).
	Hooks []agentcore.Hook
	// HostContext returns the host's context text (persona, topic index,
	// verbatim constraints) and a hash of it. The text is frozen into the
	// segment context; a hash change inside a segment appends an update.
	HostContext func() (content, hash string)
	// Approver decides every tool call. nil denies every call (fail closed).
	Approver tools.Approver
	// MemoryConfirm approves a memory write of a session that has read external
	// content. nil refuses such writes.
	MemoryConfirm func(ctx context.Context, req MemoryConfirmRequest) bool
	// Origin is the session origin recorded on the sessions this engine
	// creates; empty uses the engine origin, then OriginSDK. Hosts that need
	// longer retention should pin sessions with Engine.Pin.
	Origin string
}

SessionOptions configures one conversation.

type TraceEvent added in v0.53.0

type TraceEvent struct {
	ID               int64           `json:"id"`
	SessionID        string          `json:"session_id"`
	TurnID           string          `json:"turn_id,omitempty"`
	Kind             string          `json:"kind"`
	Name             string          `json:"name,omitempty"`
	Status           string          `json:"status,omitempty"`
	StartedAt        time.Time       `json:"started_at"`
	DurationMs       int64           `json:"duration_ms,omitempty"`
	TTFTMs           int64           `json:"ttft_ms,omitempty"`
	InputTokens      int64           `json:"input_tokens,omitempty"`
	OutputTokens     int64           `json:"output_tokens,omitempty"`
	CacheReadTokens  int64           `json:"cache_read_tokens,omitempty"`
	CacheWriteTokens int64           `json:"cache_write_tokens,omitempty"`
	Error            string          `json:"error,omitempty"`
	Attrs            json.RawMessage `json:"attrs,omitempty"`
}

TraceEvent is one trace event of a session (turn, model call, tool call, denial, ...) as shown by `suga inspect trace`. ID is the stable, increasing cursor for paging; Attrs is the event's raw JSON attribute object.

type Usage

type Usage struct {
	InputTokens      int     `json:"input_tokens,omitempty"`
	OutputTokens     int     `json:"output_tokens,omitempty"`
	TotalTokens      int     `json:"total_tokens,omitempty"`
	CacheReadTokens  int     `json:"cache_read_tokens,omitempty"`
	CacheWriteTokens int     `json:"cache_write_tokens,omitempty"`
	CostUSD          float64 `json:"cost_usd,omitempty"`
	// ModelCalls counts the model calls this invocation made (a result's
	// Usage only).
	ModelCalls int `json:"model_calls,omitempty"`
}

Usage is model token usage.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL