database

package
v0.0.0-...-1f7dd92 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2026 License: Apache-2.0 Imports: 31 Imported by: 0

README

Database style guide

This package owns PostgreSQL persistence and transactional invariants. Use the existing pgx driver and parameterized SQL alongside the operation that owns it. Keep the code easy to read without adding another database library or query layer. The repository style guide also applies.

Queries and reuse

  • Start with inline SQL. Extract a private helper when production code or tests repeat the same query, or when a shared operation enforces a real invariant.
  • Share the actual SQL. A helper that only calls another reader and returns one field adds little: call the reader and use row.HistoryID directly.
  • Use the existing dbExecutor when a shared query needs to accept either a pool or transaction. Keep transaction ownership with the operation coordinating the writes; a helper receiving an executor does not make multiple writes atomic.
  • Keep SQL as literals so the preparation test can check it. Avoid column-list concatenation, query builders, and optional flags that combine unrelated queries. A locking read and an ordinary read have different contracts.
  • Bind values with $1, $2, etc. Keep parameter order aligned with the SQL. List columns explicitly and format clauses so predicates and writes are easy to review.

Rows and types

  • Scan directly into an existing model when its fields and SQL semantics match. Keep a private row type when stored protobuf bytes, metadata, or nullability actually differ from the model.
  • Reuse shared row types for ordinary reads. Do not create a type for every query merely to avoid selecting a few scalar columns.
  • When a specialized read avoids large payloads or substantially unused data, define its small result struct inside the function. Scan a single value with pgx.RowTo[T]; it does not need a struct.
  • Remove fields that nobody consumes from the scan type and selected columns. A column can still be needed by a predicate, write, or constraint without being returned to Go.
  • Use pointers only for meaningful absence. A nullable table column may be nonnullable in a query result when its predicate excludes NULL. Do not silently skip malformed durable records.

Schema and validation

  • Enforce required values with NOT NULL, defaults, foreign keys, and CHECK constraints. Use COALESCE when the query intentionally maps meaningful NULLs to another value, rather than compensating for unnecessarily nullable columns.
  • Store protobuf enum values using their full .String() representation. Keep schema constraints and SQL predicates consistent; validate stored values when decoding. Avoid prefix trimming, alternate spellings, or special mappings.
  • Add metadata such as labels only for a concrete feature. Avoid copying fields through several records without a consumer.
  • Validate wire inputs at their entry point. Declare gRPC request-intrinsic rules in protobuf annotations; service entry points used outside that interceptor must also enforce their input contract. Authorization and state-dependent checks stay with the owning service or store operation.
  • Do not use uuid.MustParse on runtime inputs. Pass validated values as SQL parameters; use checked parsing when Go needs a UUID for comparison. Store calls must return errors instead of panicking on malformed IDs.
  • Migration 1 is currently the unreleased baseline: fold approved schema changes into it and recreate local databases. After release, use new migrations. Keep both Up and Down valid.

Atomicity and performance

  • Prefer one statement for one logical change, such as deleting both spellings of an agent's memories. Use a transaction for coordinated writes.
  • Preserve ownership predicates, idempotency checks, lock ordering, and lifecycle conditions when simplifying SQL. Never hold a transaction across a network call.
  • Use RETURNING for values the caller needs from the database. If the validated result is already in memory, a conditional Exec and RowsAffected check may suffice. Preserve the distinction between a successful no-op and a conflict.
  • Consider joins that remove preliminary reads, but preserve missing-record semantics.
  • Match predicates to existing indexes before adding indexes. Use a stable timestamp such as statement_timestamp() when eligibility is defined at query start; retain clock_timestamp() when lease expiry requires actual elapsed time. Do not replace clocks indiscriminately.
  • Use EXPLAIN (ANALYZE, BUFFERS) on representative disposable data for suspected performance problems. Report synthetic results as synthetic. Add batching or specialized projections when their benefit justifies the extra code.

Comments and checks

Document every production database function's observable behavior: what it reads or persists, ownership scope, ordering, missing-record behavior, conflicts, retry semantics, and atomicity where relevant. Private readers should say when callers must authorize access or supply a transaction. Avoid narrating each SQL line.

Exercise behavior through store methods in integration tests. Use shared query helpers when inspecting durable representations; direct SQL is appropriate for constraint tests or deliberately malformed fixtures. Do not copy production SQL into a test. Cover meaningful failure paths, isolation, and rollback rather than asserting the implementation's wording.

After SQL or schema changes, run from go/ with Docker available:

go test -race ./core/internal/database ./core/pkg/migrations
make lint

The database suite prepares every inline statement against the migrated schema; do not skip it with -short. Run affected caller tests when behavior changes, format Go code, and check the diff. Use Go's default build cache; never put GOCACHE under /tmp.

Documentation

Index

Constants

View Source
const RuntimeOperationTimeout = 2 * time.Minute

RuntimeOperationTimeout bounds one inline attempt and its execution claim. A client can retry an abandoned attempt after this bound without a sweeper.

Variables

View Source
var (
	// ErrCheckpointAdvanced requires the caller to select a new terminal task.
	ErrCheckpointAdvanced = fmt.Errorf("conversation advanced beyond the expected task: %w", ErrFailedPrecondition)
	// ErrSnapshotPending permits retrying the same checkpoint request and task.
	ErrSnapshotPending = fmt.Errorf("snapshot for the expected task is not ready: %w", ErrFailedPrecondition)
)
View Source
var (
	// ErrNotFound also covers records that are not visible to the given user.
	ErrNotFound = errors.New("record not found")
	// ErrConflict reports an operation blocked by current state or a concurrent change.
	ErrConflict = errors.New("resource conflict")
	// ErrFailedPrecondition reports an unmet requirement for an operation.
	ErrFailedPrecondition = errors.New("precondition failed")
	// ErrIdempotencyConflict is distinct because clients must use a new request ID.
	ErrIdempotencyConflict = errors.New("request id was already used with different parameters")
)

Store errors describe resource-independent categories. Wrap them with resource and operation context using %w; callers match them with errors.Is.

View Source
var ErrDispatchBusy = errors.New("session temporarily unavailable for dispatch")

ErrDispatchBusy means a send has not been forwarded because another dispatch or idle lifecycle operation currently owns the session.

View Source
var ErrMessageAccepted = errors.New("message already accepted")

ErrMessageAccepted means an earlier dispatch already persisted this initial input.

View Source
var ErrObjectDeleting = fmt.Errorf("object is being deleted: %w", ErrNotFound)

ErrObjectDeleting reports that deletion has started. The object is unavailable to new callers, so it also matches ErrNotFound.

Functions

func Connect

func Connect(ctx context.Context, cfg *PostgresConfig) (*pgxpool.Pool, error)

Connect returns a PostgreSQL pool after a successful ping, retrying until the context is canceled or two minutes elapse. Invalid configuration fails immediately. VectorEnabled registers pgvector types on each connection. The caller closes the pool.

Types

type AgentDefinition

type AgentDefinition struct {
	Namespace   string
	AgentName   string
	AgentUID    string
	EgressGrant egress.Access
	// DesiredRevision is a compiled runtime digest, or empty while inputs are unresolved.
	DesiredRevision string
}

AgentDefinition tracks the desired and last successful runtime for an Agent UID.

type AgentMemorySearchResult

type AgentMemorySearchResult struct {
	Memory
	Score float64 `json:"score"`
}

AgentMemorySearchResult is the result of a vector similarity search over Memory.

type Client

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

Client persists control-plane state in PostgreSQL. Callers define the narrow interfaces they need; SQL rows and protobuf encoding stay inside the store.

func NewClient

func NewClient(db *pgxpool.Pool, vectorSchema string) *Client

NewClient wraps an existing PostgreSQL pool without connecting or migrating. The caller owns the pool and must close it. vectorSchema is the schema pgvector is installed in.

func (*Client) BeginDeleteSessionCheckpoint

func (c *Client) BeginDeleteSessionCheckpoint(ctx context.Context, id, userID string) (*SessionTaskSnapshot, string, error)

BeginDeleteSessionCheckpoint marks an owned READY or FAILED checkpoint DELETING and returns the snapshot and tag identity for external cleanup. Retrying a DELETING checkpoint is allowed. A fork reference, another lifecycle state, or a missing/unowned checkpoint returns ErrNotFound.

func (*Client) BeginIdleSessionDeletion

func (c *Client) BeginIdleSessionDeletion(ctx context.Context, id string, before time.Time) (*IdleSessionDeletion, error)

BeginIdleSessionDeletion admits ordinary deletion only after rechecking idle eligibility. Once admitted, its reason survives retries and TTL changes.

func (*Client) BeginRuntimeRevisionDeletion

func (c *Client) BeginRuntimeRevisionDeletion(ctx context.Context, revision string) (*RuntimeArtifact, error)

BeginRuntimeRevisionDeletion marks an unreferenced revision as deleting, preventing new references before runtime cleanup. Retrying returns the pending revision; nil means the revision is missing or still referenced.

func (*Client) BeginSandboxOperation

func (c *Client) BeginSandboxOperation(ctx context.Context, id string, kind apiv1.RuntimeOperation) (*SandboxOperation, error)

func (*Client) BeginSessionOperation

func (c *Client) BeginSessionOperation(ctx context.Context, sessionID string, kind apiv1.RuntimeOperation) (*SessionOperation, error)

BeginSessionOperation admits or joins current lifecycle work under the session lock. Creation retries and already-at-target requests return current state. Delete alone may supersede unclaimed work; uncertain work blocks it. Callers authorize access. Deleted sessions return ErrNotFound, except Delete can observe the tombstone for a caller already authorized before deletion.

func (*Client) ClaimDuePushDelivery

func (c *Client) ClaimDuePushDelivery(ctx context.Context) (*PushDelivery, error)

ClaimDuePushDelivery claims one due or abandoned registration and captures its current published status. Registration locks serialize replacement and claims; no session/task lock is acquired here and no lock is held across HTTP. Invalid task data commits a failed attempt before returning an error, allowing other registrations to proceed while this one waits for its retry deadline.

func (*Client) ClaimSandboxOperation

func (c *Client) ClaimSandboxOperation(ctx context.Context, id string, operationID, executorID uuid.UUID) (bool, error)

func (*Client) ClaimScheduledRunDispatch

func (c *Client) ClaimScheduledRunDispatch(ctx context.Context, lease ScheduledRunExecutionLease) error

ClaimScheduledRunDispatch records that a worker may issue its one A2A send. It requires an unexpired lease and a linked, pending execution. Once claimed, later workers recover the task from history; they never resend an uncertain dispatch. A crash before sending therefore waits for the execution deadline.

func (*Client) ClaimSessionOperation

func (c *Client) ClaimSessionOperation(ctx context.Context, sessionID string, id, executorID uuid.UUID) (bool, error)

ClaimSessionOperation grants one bounded attempt permission to issue this generation's runtime work. An ended or expired attempt can be retried, but a stale generation cannot claim, even when later work has the same kind and state.

func (*Client) ClaimSessionQuiescence

func (c *Client) ClaimSessionQuiescence(ctx context.Context) (*SessionQuiescence, error)

ClaimSessionQuiescence claims an idle session at its latest settled task version. A new turn supersedes unclaimed idle work; a claim blocks task writes, checkpoints, and explicit lifecycle operations until it finishes. Missing work returns ErrNotFound. Uncertain issued work is never reassigned after a timeout.

func (*Client) CreateRuntimeTask

func (c *Client) CreateRuntimeTask(ctx context.Context, sessionID string, mutationHash []byte, task *a2a.Task, dispatchID string) (int64, error)

CreateRuntimeTask stores a new SDK task and its history atomically. An identical storage retry returns the original version; a different write to the same ID conflicts. It does not deduplicate user requests or grant execution permission.

func (*Client) CreateSandbox

func (c *Client) CreateSandbox(ctx context.Context, request *apiv1.Sandbox, requestID string, options SandboxCreateOptions) (*apiv1.Sandbox, bool, error)

CreateSandbox atomically reserves a sandbox and its latest successful revision, or returns ErrNotFound if none is available. A duplicate creator/requestID returns the original resource when inputs match. The boolean reports whether this call created the sandbox.

func (*Client) CreateScheduledRun

func (c *Client) CreateScheduledRun(ctx context.Context, request *apiv1.ScheduledRun, requestID string, hash []byte) (*apiv1.ScheduledRun, error)

CreateScheduledRun atomically stores a schedule with a new ID, etag, and initial due time. Reusing a creator/requestID returns the existing schedule if the request hash matches, or ErrIdempotencyConflict otherwise. Paused schedules have no due time; execution is left to the scheduler.

func (*Client) CreateSession

func (c *Client) CreateSession(ctx context.Context, request *apiv1.Session, requestID string) (*apiv1.Session, bool, error)

CreateSession atomically reserves a session, its conversation history, and the latest successful revision, or returns ErrNotFound if none is available. A repeated creator/requestID returns the existing session when the Agent matches, or ErrIdempotencyConflict otherwise. A deleted session returns ErrFailedPrecondition and keeps its request ID reserved. The boolean reports whether this call created the session; runtime provisioning belongs to the caller.

func (*Client) CreateSessionShare

func (c *Client) CreateSessionShare(ctx context.Context, share *apiv1.SessionShare, tokenHash []byte, userID string) (*apiv1.SessionShare, error)

CreateSessionShare stores a read-only share with the supplied ID, expiry, and token hash for a session owned by userID and sets its creation time. A missing or unowned session returns ErrNotFound. Callers authorize sharing and generate the token; the plaintext token is never stored. Insertion locks the live session so concurrent deletion either revokes this share or prevents its creation.

func (*Client) DeleteAgentMemory

func (c *Client) DeleteAgentMemory(ctx context.Context, agentName, userID string) error

DeleteAgentMemory atomically deletes a user's memories for the agent and its legacy underscore spelling. Missing rows are a no-op.

func (*Client) DeleteRuntimeRevision

func (c *Client) DeleteRuntimeRevision(ctx context.Context, revision, actorTemplateUID string) error

DeleteRuntimeRevision atomically releases retired success pointers and removes a revision after compute cleanup. Missing, unmarked, or changed-UID revisions are a no-op so retries cannot finalize a replacement runtime.

func (*Client) DeleteScheduledRun

func (c *Client) DeleteScheduledRun(ctx context.Context, id uuid.UUID, creator string) (*apiv1.ScheduledRun, error)

DeleteScheduledRun stops future scheduling and returns an owned deletion tombstone while retaining execution history and request deduplication. Repeated deletion succeeds. Malformed payloads are retained for repair and return only authoritative tombstone metadata.

func (*Client) DeleteSessionCheckpoint

func (c *Client) DeleteSessionCheckpoint(ctx context.Context, id, userID string) error

DeleteSessionCheckpoint removes an owned DELETING checkpoint after the caller cleans up its external tag. No matching row is a successful no-op.

func (*Client) DeleteSessionShare

func (c *Client) DeleteSessionShare(ctx context.Context, id, userID string) error

DeleteSessionShare revokes a share only when its session belongs to userID. A missing or unowned share returns ErrNotFound.

func (*Client) DeleteTaskPushConfig

func (c *Client) DeleteTaskPushConfig(ctx context.Context, sessionID, taskID, configID string) error

DeleteTaskPushConfig is idempotent. A closed receipt prevents initial send retries from restoring a deleted embedded callback.

func (*Client) DeleteToolServer

func (c *Client) DeleteToolServer(ctx context.Context, serverName, groupKind string) error

DeleteToolServer atomically hides the server and its tools for the exact name and group kind. A missing server is a successful no-op.

func (*Client) ExpireUnboundPushRegistrations

func (c *Client) ExpireUnboundPushRegistrations(ctx context.Context) error

ExpireUnboundPushRegistrations closes receipts whose send never accepted a task.

func (*Client) FinalizeSessionCheckpoint

func (c *Client) FinalizeSessionCheckpoint(ctx context.Context, id, tagUID, snapshotURI, failure string) (*apiv1.Checkpoint, error)

FinalizeSessionCheckpoint records either a retained tag UID and snapshot URI as READY, or a failure as FAILED. An identical terminal retry returns the existing checkpoint; a different terminal result returns ErrNotFound. This internal operation does not check ownership or create the external snapshot.

func (*Client) FindScheduledRunRequest

func (c *Client) FindScheduledRunRequest(ctx context.Context, creator, requestID string, hash []byte) (*apiv1.ScheduledRun, error)

FindScheduledRunRequest returns the schedule created by the creator/requestID pair, including later edits or deletion. A different request hash returns ErrIdempotencyConflict; an unknown request returns ErrNotFound.

func (*Client) FinishPushDelivery

func (c *Client) FinishPushDelivery(ctx context.Context, delivery PushDelivery, delivered bool) error

FinishPushDelivery records only a matching generation and claim. Stale success and failure responses cannot clear newer work or change its retry schedule. Exhausted failures retire pending work without closing the registration.

func (*Client) FinishSandboxOperation

func (c *Client) FinishSandboxOperation(ctx context.Context, id string, operationID, executorID uuid.UUID, failure string) (*apiv1.Sandbox, error)

func (*Client) FinishSessionOperation

func (c *Client) FinishSessionOperation(ctx context.Context, sessionID string, id, executorID uuid.UUID, authority, actorUID, failure string) (*apiv1.Session, error)

FinishSessionOperation publishes known success only for the claiming executor. A nonempty failure releases only unclaimed preparation and invalidates its generation. Uncertain issued work must remain pending. Stale completion or release returns ErrConflict. Deletion revokes shares and releases resource pins atomically. Explicit deletion retains a tombstone; idle deletion also removes the session and creation receipt in this transaction.

func (*Client) FinishSessionQuiescence

func (c *Client) FinishSessionQuiescence(ctx context.Context, work *SessionQuiescence, snapshot *SessionTaskSnapshot) error

FinishSessionQuiescence records a claimed suspension outcome and releases the session for new execution. Every settled task requires the matching snapshot. Retries are harmless, and a stale claim cannot release another operation. Task state and history remain readable throughout lifecycle work.

func (*Client) ForkSession

func (c *Client) ForkSession(ctx context.Context, checkpointID, userID, requestID, sessionID string) (*apiv1.Session, bool, error)

ForkSession atomically creates a session and independent history from an owned READY checkpoint, replaying only events through its saved boundary. The fork retains the source revision and snapshot, with fresh context and task IDs. A repeated owner/requestID returns the existing fork for the same checkpoint, or ErrIdempotencyConflict otherwise. The boolean reports creation; callers provision the runtime separately. A deleted fork returns ErrFailedPrecondition and retains its request identity.

func (*Client) GetAgentEgressGrant

func (c *Client) GetAgentEgressGrant(ctx context.Context, namespace, uid string) (egress.Access, error)

GetAgentEgressGrant returns the active identity's last admitted grants. Missing or retired identities return empty access; malformed stored grants fail.

func (*Client) GetRuntimeEgressPolicy

func (c *Client) GetRuntimeEgressPolicy(ctx context.Context, revision string) (egress.Access, error)

GetRuntimeEgressPolicy merges pinned inputs with the active source UID's grants in one database snapshot. Missing/deleting revisions and malformed inputs fail closed. Retired or replaced identities contribute no grants. Older revisions retain their pinned base and only the grants compatible with it.

func (*Client) GetRuntimeRevision

func (c *Client) GetRuntimeRevision(ctx context.Context, revision string) (*RuntimeRevision, error)

GetRuntimeRevision returns a prepared revision and its decoded agent card, or ErrNotFound if absent.

func (*Client) GetSandbox

func (c *Client) GetSandbox(ctx context.Context, id, userID string) (*apiv1.Sandbox, error)

GetSandbox includes deletion tombstones so authorized retries can observe cleanup.

func (*Client) GetSandboxEgressGrant

func (c *Client) GetSandboxEgressGrant(ctx context.Context, namespace, uid string) (egress.Access, error)

GetSandboxEgressGrant returns the active identity's last admitted grants. Missing or retired identities return empty access; malformed stored grants fail.

func (*Client) GetSandboxOperation

func (c *Client) GetSandboxOperation(ctx context.Context, id string) (*SandboxOperation, error)

func (*Client) GetSandboxRevision

func (c *Client) GetSandboxRevision(ctx context.Context, revision string) (*SandboxRevision, error)

GetSandboxRevision reads immutable sandbox inputs; missing revisions return ErrNotFound.

func (*Client) GetScheduledRun

func (c *Client) GetScheduledRun(ctx context.Context, id uuid.UUID, creator string) (*apiv1.ScheduledRun, error)

GetScheduledRun returns a creator's schedule, including a deletion tombstone. Missing schedules and other owners return ErrNotFound.

func (*Client) GetScheduledRunExecution

func (c *Client) GetScheduledRunExecution(ctx context.Context, id uuid.UUID, creator string) (*apiv1.ScheduledRunExecution, error)

GetScheduledRunExecution returns an execution only for its schedule's creator, including after schedule deletion. Missing executions and other owners return ErrNotFound.

func (*Client) GetSession

func (c *Client) GetSession(ctx context.Context, id, userID string) (*apiv1.Session, error)

GetSession returns a session only when it belongs to userID. Missing sessions and sessions owned by another user return ErrNotFound. Tombstones are hidden.

func (*Client) GetSessionByID

func (c *Client) GetSessionByID(ctx context.Context, id string) (*apiv1.Session, error)

GetSessionByID returns a session without filtering by owner, or ErrNotFound if absent or deleted. Callers must authorize access; malformed UUIDs return an error.

func (*Client) GetSessionCheckpoint

func (c *Client) GetSessionCheckpoint(ctx context.Context, id, userID string) (*apiv1.Checkpoint, error)

GetSessionCheckpoint returns an owned READY checkpoint. Missing checkpoints, other owners, and other lifecycle states return ErrNotFound.

func (*Client) GetSessionCheckpointSnapshot

func (c *Client) GetSessionCheckpointSnapshot(ctx context.Context, id, userID string) (*SessionTaskSnapshot, string, error)

GetSessionCheckpointSnapshot returns an owned checkpoint's snapshot reference and tag UID in any lifecycle state. Before finalization the URI refers to the source snapshot; afterward it refers to the retained copy. Missing checkpoints and other owners return ErrNotFound.

func (*Client) GetSessionForRuntime

func (c *Client) GetSessionForRuntime(ctx context.Context, id, actorUID string) (*apiv1.Session, error)

GetSessionForRuntime binds a verified Substrate actor UID to the session created for it. Deleted sessions and obsolete actors cannot access retained task data. Actor identity is private and is never caller metadata.

func (*Client) GetSessionOperation

func (c *Client) GetSessionOperation(ctx context.Context, sessionID string, id uuid.UUID) (*SessionOperation, error)

GetSessionOperation observes this generation only while it remains current, including its deletion tombstone. A superseded or missing generation returns ErrConflict. Callers must have authorized the session at admission. It never returns historical results or grants permission to issue runtime work.

func (*Client) GetSessionShareByTokenHash

func (c *Client) GetSessionShareByTokenHash(ctx context.Context, tokenHash []byte) (*apiv1.SessionShare, string, error)

GetSessionShareByTokenHash resolves a token digest to its share and the session owner's ID, or ErrNotFound, which an expired share is too. Callers restrict access to read-only operations on the shared session.

func (*Client) GetSessionTask

func (c *Client) GetSessionTask(ctx context.Context, sessionID, taskID string, historyLength *int) (*a2a.Task, error)

GetSessionTask returns a task with up to historyLength latest archived messages, or ErrNotFound if the session or task is absent. Nil or negative historyLength loads all history; zero skips it. Callers authorize session access.

func (*Client) GetSessionTaskByMessage

func (c *Client) GetSessionTaskByMessage(ctx context.Context, sessionID, taskID, messageID string) (*a2a.Task, error)

GetSessionTaskByMessage finds the task containing an input after a runtime disconnects before returning its unary response. Ambiguous message IDs fail; this read never deduplicates sends or authorizes another execution.

func (*Client) GetSettledSessionTask

func (c *Client) GetSettledSessionTask(ctx context.Context, sessionID, taskID string, historyLength *int) (*a2a.Task, error)

GetSettledSessionTask reads the public task after native cleanup publishes its pending update. ErrConflict means cleanup is still pending. A later admitted turn may already be current; callers must not wait for an old status value to recur. Ownership and missing-record semantics match GetSessionTask.

func (*Client) GetTaskPushConfig

func (c *Client) GetTaskPushConfig(ctx context.Context, sessionID, taskID, configID string) (*TaskPushConfig, error)

GetTaskPushConfig reads one active configuration.

func (*Client) GetVersionedSessionTask

func (c *Client) GetVersionedSessionTask(ctx context.Context, sessionID, taskID string) (*a2a.Task, int64, error)

GetVersionedSessionTask returns one consistent task, full history, and storage version for a runtime read. Versions come from the retained history, so forks have independent versions even when their wire task IDs are shared. Missing or deleted sessions and absent tasks return ErrNotFound. Callers authenticate session authority before reading.

func (*Client) HasPendingPushDelivery

func (c *Client) HasPendingPushDelivery(ctx context.Context) (bool, error)

HasPendingPushDelivery includes future retries and leases awaiting recovery. Exhausted generations are retired and do not keep workers polling.

func (*Client) HasPendingSessionQuiescence

func (c *Client) HasPendingSessionQuiescence(ctx context.Context) (bool, error)

HasPendingSessionQuiescence includes ready sessions temporarily blocked by dispatch, checkpoints, lifecycle operations, or row locks. Already claimed work is excluded: its runtime outcome may be uncertain and cannot be retried by another worker. Suspended/deleted sessions need no automatic runtime work.

func (*Client) IsPushDeliveryCurrent

func (c *Client) IsPushDeliveryCurrent(ctx context.Context, delivery PushDelivery) (bool, error)

IsPushDeliveryCurrent checks immediately before HTTP whether publication, resume, configuration edits, or lease recovery have superseded this attempt. A transition after this check can still make an in-flight request stale.

func (*Client) LeaseScheduledRunExecutions

func (c *Client) LeaseScheduledRunExecutions(ctx context.Context, limit int) ([]LeasedScheduledRunExecution, error)

LeaseScheduledRunExecutions claims up to limit pending or running executions due for retry, excluding rows held by other workers. Each claim lasts thirty seconds and must be supplied when recording progress. Malformed executions are logged and omitted, retaining their lease delay before retry.

func (*Client) ListAgentEgressSources

func (c *Client) ListAgentEgressSources(ctx context.Context) ([]RuntimeEgressSource, error)

ListAgentEgressSources returns names for active Agent definitions and retired identities that still have non-deleted instances. Startup recovery includes retired identities because a crash may interrupt revocation after retirement.

func (*Client) ListAgentMemories

func (c *Client) ListAgentMemories(ctx context.Context, agentName, userID string) ([]Memory, error)

ListAgentMemories returns a user's memories for the agent and its legacy underscore spelling, ordered by descending access count. Expired rows remain visible until pruned.

func (*Client) ListAgentTasks

func (c *Client) ListAgentTasks(ctx context.Context, sessionIDs []string, afterID string, state a2a.TaskState, statusTimestampAfter *time.Time, limit int, historyLength *int) ([]*a2a.Task, int, error)

ListAgentTasks applies authorization before pagination: sessionIDs contains only the conversations the caller may read. Task IDs break ties between copies of the same historical position in different forks.

func (*Client) ListExpiredSandboxes

func (c *Client) ListExpiredSandboxes(ctx context.Context, afterID string, limit int) ([]string, error)

func (*Client) ListIdleSessions

func (c *Client) ListIdleSessions(ctx context.Context, before time.Time, afterID string, limit int) ([]string, error)

ListIdleSessions returns candidates, including unfinished idle deletions. Empty histories and old fork histories may be newer sessions; admission checks creation time and rechecks activity under the task/lifecycle lock.

func (*Client) ListRuntimeEgressSourceTargets

func (c *Client) ListRuntimeEgressSourceTargets(ctx context.Context, source RuntimeEgressSource, afterID string, limit int) ([]RuntimeEgressTarget, error)

ListRuntimeEgressSourceTargets pages allocated instances across a source's UIDs in ID order, excluding deletions and unissued creations. Invalid sources return an error; a missing source yields an empty page.

func (*Client) ListSandboxes

func (c *Client) ListSandboxes(ctx context.Context, userID, afterID string, limit int, template *apiv1.ResourceReference) ([]*apiv1.Sandbox, error)

func (*Client) ListScheduledRunExecutions

func (c *Client) ListScheduledRunExecutions(ctx context.Context, query ScheduledRunExecutionQuery) ([]*apiv1.ScheduledRunExecution, error)

ListScheduledRunExecutions returns a creator's execution history for one schedule in descending ID order after AfterID, up to Limit. History remains available after schedule deletion.

func (*Client) ListScheduledRuns

func (c *Client) ListScheduledRuns(ctx context.Context, query ScheduledRunQuery) ([]*apiv1.ScheduledRun, error)

ListScheduledRuns returns the creator's undeleted schedules in ascending ID order after AfterID, up to Limit.

func (*Client) ListSessionCheckpoints

func (c *Client) ListSessionCheckpoints(ctx context.Context, sessionID, userID, afterID string, limit int) ([]*apiv1.Checkpoint, error)

ListSessionCheckpoints returns an owner's READY checkpoints for the source session in ascending ID order after afterID, up to limit. Retained checkpoints remain listable after the source session is deleted.

func (*Client) ListSessionShares

func (c *Client) ListSessionShares(ctx context.Context, sessionID, userID, afterID string, limit int) ([]*apiv1.SessionShare, error)

ListSessionShares returns shares only for a session owned by userID, in ascending ID order after afterID, up to limit. A missing or unowned session yields an empty page.

func (*Client) ListSessionTasks

func (c *Client) ListSessionTasks(ctx context.Context, sessionID, afterID string, state a2a.TaskState, statusTimestampAfter *time.Time, limit int, historyLength *int) ([]*a2a.Task, int, error)

ListSessionTasks returns tasks with archived messages in immutable creation order after afterID, with optional state and exclusive status-timestamp filters. The total counts all matching tasks before pagination; it is read separately and can differ under concurrent writes. History limits have the same semantics as GetSessionTask. Callers authorize session access.

func (*Client) ListSessions

func (c *Client) ListSessions(ctx context.Context, query SessionQuery) ([]*apiv1.Session, error)

ListSessions returns up to Limit sessions in ascending ID order after AfterID, filtered by optional Agent reference. It restricts results to UserID unless AllUsers is set; callers must authorize that broader access.

func (*Client) ListTaskPushConfigs

func (c *Client) ListTaskPushConfigs(ctx context.Context, sessionID, taskID, afterID string, limit int) ([]TaskPushConfig, error)

ListTaskPushConfigs pages by configuration ID within the authorized task.

func (*Client) ListToolServers

func (c *Client) ListToolServers(ctx context.Context) ([]ToolServer, error)

ListToolServers returns all undeleted servers in ascending creation-time order.

func (*Client) ListTools

func (c *Client) ListTools(ctx context.Context) ([]Tool, error)

ListTools returns all undeleted tools in ascending creation-time order.

func (*Client) ListUnreferencedRuntimeRevisions

func (c *Client) ListUnreferencedRuntimeRevisions(ctx context.Context) ([]RuntimeArtifact, error)

ListUnreferencedRuntimeRevisions lists revisions unused by active Agents, instances, or checkpoints, including deletions still awaiting compute cleanup.

func (*Client) PruneExpiredMemories

func (c *Client) PruneExpiredMemories(ctx context.Context) error

PruneExpiredMemories atomically extends expired memories with at least ten accesses by fifteen days and resets their access count, then deletes expired memories with fewer than ten accesses. Memories without an expiration remain untouched.

func (*Client) RecordRuntimeRevision

func (c *Client) RecordRuntimeRevision(ctx context.Context, revision RuntimeRevision, options RecordRevisionOptions) error

RecordRuntimeRevision atomically stores immutable inputs and, when Ready, promotes the revision for its active source if still desired. Existing inputs are preserved; actor UID and update time refresh. Stale reports cannot replace the last successful revision. Deleting revisions return ErrObjectDeleting.

func (*Client) RecordSandboxOperationFailure

func (c *Client) RecordSandboxOperationFailure(ctx context.Context, id string, operationID uuid.UUID) error

func (*Client) RecordSandboxRevision

func (c *Client) RecordSandboxRevision(ctx context.Context, revision SandboxRevision, options RecordRevisionOptions) error

RecordSandboxRevision atomically stores immutable inputs and, when Ready, promotes the revision for its active source if still desired. Existing inputs are preserved; actor UID and update time refresh. Stale reports cannot replace the last successful revision. Deleting revisions return ErrObjectDeleting.

func (*Client) RefreshToolServer

func (c *Client) RefreshToolServer(ctx context.Context, server *ToolServer, tools ...*v1alpha3.MCPTool) error

RefreshToolServer atomically publishes a server and replaces its visible tools. Removed servers and tools are revived when supplied again, preserving creation times. An empty tool list keeps the server visible and hides its previous tools.

func (*Client) RegisterSessionPushNotification

func (c *Client) RegisterSessionPushNotification(ctx context.Context, sessionID, messageID, taskID string, config *a2a.PushConfig) error

An embedded callback starts as a receipt for one input message. It gains a task ID only when that task accepts the message. Explicit Create already has a task ID and stores a bound row through SaveTaskPushConfig instead. Binding never queues delivery: SettleSessionTask replaces pending work when it publishes a later eligible task state.

RegisterSessionPushNotification saves the callback supplied with SendMessage before dispatch. The message may name an existing task, but the receipt remains unbound until a task write proves that task accepted this input. Its original request fingerprint survives later edits or deletion, so retrying the send cannot restore old settings or attach the callback to another task.

func (*Client) ReleaseRuntimeOperation

func (c *Client) ReleaseRuntimeOperation(ctx context.Context, id string, operationID, executorID uuid.UUID) error

ReleaseRuntimeOperation ends an attempt, not the durable operation. Keeping executor_id prevents uncertain issued work from being discarded as preparation. A stale attempt cannot release a retry's claim or a newer operation.

func (*Client) ReserveDueScheduledRuns

func (c *Client) ReserveDueScheduledRuns(ctx context.Context, limit int) error

ReserveDueScheduledRuns atomically reserves due occurrences and advances their schedules, skipping rows held by other workers. Limit must be between 1 and 100. Occurrences over thirty seconds late are skipped; malformed schedules are removed from the due queue with their payloads retained for repair. Execution workers claim the stored reservations separately.

func (*Client) ReserveScheduledRunExecutionSession

func (c *Client) ReserveScheduledRunExecutionSession(ctx context.Context, id uuid.UUID, creator string) (*apiv1.ScheduledRunExecution, error)

ReserveScheduledRunExecutionSession atomically reserves an owned execution's session and saves its historical link. Existing links and non-pending executions are returned unchanged, even if the linked session was deleted. An elapsed deadline marks the execution timed out; an unprepared target returns ErrFailedPrecondition for retry. Callers provision the runtime separately.

func (*Client) ReserveSessionCheckpoint

func (c *Client) ReserveSessionCheckpoint(ctx context.Context, checkpoint *apiv1.Checkpoint, userID, requestID string) (*apiv1.Checkpoint, *SessionTaskSnapshot, error)

ReserveSessionCheckpoint captures the terminal task named by HeadTaskId, provided it is still the latest boundary. ErrSnapshotPending permits retry; ErrCheckpointAdvanced requires a new selection. The session must be READY. A repeated owner/requestID returns the same reservation for the same source and task, or ErrIdempotencyConflict otherwise. A CREATING reservation blocks new task writes and lifecycle operations while the caller retains the external snapshot.

func (*Client) ReserveSessionDispatch

func (c *Client) ReserveSessionDispatch(ctx context.Context, sessionID string, dispatchID uuid.UUID, initialMessageID string) error

ReserveSessionDispatch prevents pause/suspend between routing a request and its first persisted task. The attempt expires after two minutes; a late first save must fail before native execution. This is not a native work lease.

func (*Client) RetireAgentIdentities

func (c *Client) RetireAgentIdentities(ctx context.Context, namespace, name string) error

RetireAgentIdentities retires identities at the given namespace/Agent name. Existing sessions retain their pinned revisions. Missing and already-retired identities are a no-op.

func (*Client) RetireSandboxTemplateIdentities

func (c *Client) RetireSandboxTemplateIdentities(ctx context.Context, namespace, name string) error

RetireSandboxTemplateIdentities retires active identities at this source name. Missing/already-retired identities are a no-op; retained actors lose live grants.

func (*Client) RevokeSessionDispatch

func (c *Client) RevokeSessionDispatch(ctx context.Context, sessionID string, dispatchID uuid.UUID, messageID string) (bool, error)

RevokeSessionDispatch fences an unused attempt. True proves its first save did not commit and cannot commit later, so retrying the send is safe. False does not prove acceptance: callers must preserve ambiguous outcomes.

func (*Client) SaveTaskPushConfig

func (c *Client) SaveTaskPushConfig(ctx context.Context, sessionID, taskID string, config *a2a.PushConfig) error

SaveTaskPushConfig creates or replaces a task configuration. Changing its URL invalidates pending work and claims; the next publication uses the new URL.

func (*Client) SearchAgentMemory

func (c *Client) SearchAgentMemory(ctx context.Context, agentName, userID string, embedding pgvector.Vector, limit int) ([]AgentMemorySearchResult, error)

SearchAgentMemory returns up to limit memories for the user and agent, ranked by cosine similarity. It also matches the legacy agent spelling with hyphens replaced by underscores. Expired rows remain searchable until pruned; access-count updates are best-effort and cannot fail a successful search.

func (*Client) SessionForTask

func (c *Client) SessionForTask(ctx context.Context, taskID string) (string, error)

SessionForTask resolves a globally unique public task ID. The caller must authorize the resulting session before returning data or invoking its runtime.

func (*Client) SettleSessionTask

func (c *Client) SettleSessionTask(ctx context.Context, sessionID, taskID string, version int64) error

SettleSessionTask publishes a saved terminal/waiting task and its history atomically after native cleanup. It does not wait for runtime pause or snapshots. Retries cannot republish an old state over a later turn. Callers authenticate runtime authority; a missing or deleted session returns ErrNotFound.

func (*Client) StoreAgentMemories

func (c *Client) StoreAgentMemories(ctx context.Context, memories ...*Memory) error

StoreAgentMemories inserts one or more memories atomically and assigns generated IDs only after success. A single insert uses one statement; a batch uses a transaction. Creation time comes from the database. Empty input is a no-op, and failures leave input IDs unchanged.

func (*Client) TriggerScheduledRun

func (c *Client) TriggerScheduledRun(ctx context.Context, id uuid.UUID, creator, requestID string) (*apiv1.ScheduledRunExecution, error)

TriggerScheduledRun reserves a manual execution for an owned schedule, including when paused, without starting runtime work or changing the next scheduled occurrence. Reusing requestID for that schedule returns the same execution, even after deletion; new triggers on a deleted schedule return ErrFailedPrecondition.

func (*Client) UpdateCheckpointName

func (c *Client) UpdateCheckpointName(ctx context.Context, id, userID, name string) (*apiv1.Checkpoint, error)

UpdateCheckpointName renames an owned, ready checkpoint, and with it the name its forks are given. An empty name restores the generated default rather than leaving the checkpoint nameless. Missing, unowned and not-yet-ready checkpoints return ErrNotFound: a checkpoint Get and List will not show is not one a caller may rename, or read back through the rename's response.

func (*Client) UpdateScheduledRun

func (c *Client) UpdateScheduledRun(ctx context.Context, id uuid.UUID, creator, etag string, config *apiv1.ScheduledRunConfig) (*apiv1.ScheduledRun, error)

UpdateScheduledRun replaces an owned schedule's config and etag only if the supplied etag matches; stale edits return ErrConflict and deleted schedules return ErrFailedPrecondition. The next occurrence changes only when the schedule, time zone, or pause setting changes, so unrelated edits cannot skip an already-due occurrence.

func (*Client) UpdateScheduledRunExecution

func (c *Client) UpdateScheduledRunExecution(ctx context.Context, lease ScheduledRunExecutionLease, progress ScheduledRunExecutionProgress) error

UpdateScheduledRunExecution records progress only under a matching, unexpired lease on a pending or running execution. It preserves an existing task ID, records terminal completion time, and releases the lease with a one-second retry delay. A lost lease or conflicting task ID returns ErrConflict.

func (*Client) UpdateSessionName

func (c *Client) UpdateSessionName(ctx context.Context, id, userID, name string) (*apiv1.Session, error)

UpdateSessionName renames an owned session while preserving concurrent lifecycle changes. Missing sessions and sessions owned by another user return ErrNotFound.

func (*Client) UpdateSessionTask

func (c *Client) UpdateSessionTask(ctx context.Context, sessionID string, expectedVersion int64, mutationHash []byte, task *a2a.Task, event a2a.Event, dispatchID string) (int64, error)

UpdateSessionTask applies a runtime update only to the version it read. The transition and history commit together. An identical retry returns the original committed version, even after later updates; a different stale save returns ErrConflict. Callers authenticate the runtime's session authority and provide a SHA-256 digest of the complete mutation. This never creates a task.

func (*Client) UpsertAgentDefinition

func (c *Client) UpsertAgentDefinition(ctx context.Context, definition AgentDefinition) error

UpsertAgentDefinition records the desired runtime revision for a Kubernetes Agent identity. Updating an existing definition revives it if retired and preserves its latest successful revision. It atomically retires older identities at the same names and rejects revisions whose deletion has started. Grants are canonicalized before writing; errors may include an uncertain commit outcome.

func (*Client) UpsertSandboxTemplateDefinition

func (c *Client) UpsertSandboxTemplateDefinition(ctx context.Context, definition SandboxTemplateDefinition) error

UpsertSandboxTemplateDefinition pins desired inputs before any backend mutation. A new Kubernetes UID retires the former identity without inheriting its last success. Grants are canonicalized before writing; errors may include an uncertain commit outcome.

type IdleSessionDeletion

type IdleSessionDeletion struct {
	Operation *SessionOperation
	IdleSince time.Time
}

IdleSessionDeletion combines admitted deletion with activity information for sweep observability. Idle timing is not part of the lifecycle operation.

type LeasedScheduledRunExecution

type LeasedScheduledRunExecution struct {
	Execution *apiv1.ScheduledRunExecution
	Lease     ScheduledRunExecutionLease
}

LeasedScheduledRunExecution keeps the immutable lease identity separate from the snapshot.

type Memory

type Memory struct {
	ID          string          `json:"id"`
	AgentName   string          `json:"agent_name"`
	UserID      string          `json:"user_id"`
	Content     string          `json:"content"`
	Embedding   pgvector.Vector `json:"embedding"`
	Metadata    string          `json:"metadata"`
	CreatedAt   time.Time       `json:"created_at"`
	ExpiresAt   *time.Time      `json:"expires_at,omitempty"`
	AccessCount int64           `json:"access_count"`
}

type PostgresConfig

type PostgresConfig struct {
	Pool            *pgxpool.Config
	Schema          string
	VectorSchema    string
	VectorEnabled   bool
	MaxConns        *int32
	MinConns        *int32
	MaxConnIdleTime *time.Duration
	MaxConnLifetime *time.Duration
}

PostgresConfig holds the connection parameters for a Postgres database. Pool is the login's base configuration from postgres.PoolConfig; Connect copies it and never modifies it. Pool fields are optional: nil leaves the corresponding pgxpool.Config value from ParseConfig unchanged (pgx library defaults). Schema is required when vectors are enabled; VectorSchema defaults to extensions.

type PushDelivery

type PushDelivery struct {
	ID         uuid.UUID
	Sequence   int64
	ClaimToken uuid.UUID
	TaskID     string
	URL        string
	Payload    []byte
}

PushDelivery captures one attempt at the current published task. ID identifies the registration; Sequence and ClaimToken fence superseded and expired attempts.

type RecordRevisionOptions

type RecordRevisionOptions struct {
	// Ready promotes the revision only while its source is active and still desires it.
	Ready bool
}

RecordRevisionOptions controls whether a prepared revision becomes available.

type RuntimeArtifact

type RuntimeArtifact struct {
	Revision              string
	Kind                  string
	Namespace             string
	ActorTemplateAtespace string
	ActorTemplateName     string
	ActorTemplateUID      string
	DeletedAt             *time.Time
}

RuntimeArtifact identifies backend resources retained by either runtime kind. Agent configuration and SandboxTemplate provenance stay in their extensions.

type RuntimeEgressSource

type RuntimeEgressSource struct {
	Kind      RuntimeEgressSourceKind
	Namespace string
	Name      string
}

RuntimeEgressSource includes former UIDs whose grants must be revoked on recreation.

type RuntimeEgressSourceKind

type RuntimeEgressSourceKind string

RuntimeEgressSourceKind identifies a Kubernetes owner of runtime instances.

const (
	RuntimeEgressAgent   RuntimeEgressSourceKind = runtimeKindAgent
	RuntimeEgressSandbox RuntimeEgressSourceKind = runtimeKindSandbox
)

type RuntimeEgressTarget

type RuntimeEgressTarget struct {
	ID           string
	Revision     string
	Namespace    string
	Atespace     string
	TemplateName string
	ActorUID     string
}

RuntimeEgressTarget identifies allocated instances, including suspended actors.

type RuntimeOperation

type RuntimeOperation[T any] struct {
	ID         uuid.UUID
	ExecutorID uuid.UUID
	Instance   T
}

RuntimeOperation carries a typed resource and its current execution authority. Completion retains the generation for observers. Executor IDs record that work may have been issued even after an individual attempt ends.

type RuntimeRevision

type RuntimeRevision struct {
	Revision                string
	Namespace               string
	AgentName               string
	AgentUID                string
	SourceSnapshot          json.RawMessage
	AgentCard               *a2apb.AgentCard
	Credentials             []egress.Credential
	EgressDestinations      []string
	TokenPassthroughOrigins []string
	ActorTemplateAtespace   string
	ActorTemplateName       string
	ActorTemplateUID        string
}

type SandboxCreateOptions

type SandboxCreateOptions struct {
	RequestHash []byte
	TemplateUID string
	TTL         time.Duration
}

SandboxCreateOptions contains creation inputs that are not part of the resource.

type SandboxOperation

type SandboxOperation = RuntimeOperation[*apiv1.Sandbox]

type SandboxRevision

type SandboxRevision struct {
	RuntimeArtifact
	SandboxTemplateName string
	SandboxTemplateUID  string
	SourceSnapshot      json.RawMessage
}

type SandboxTemplateDefinition

type SandboxTemplateDefinition struct {
	Namespace           string
	SandboxTemplateName string
	SandboxTemplateUID  string
	EgressGrant         egress.Access
	DesiredRevision     string
}

SandboxTemplateDefinition tracks the desired and last successful runtime for a SandboxTemplate UID.

type ScheduledRunExecutionLease

type ScheduledRunExecutionLease struct {
	ExecutionID uuid.UUID
	Token       uuid.UUID
}

ScheduledRunExecutionLease fences status updates from a previous worker. Leases expire after 30 seconds; network work must finish within that lease.

type ScheduledRunExecutionProgress

type ScheduledRunExecutionProgress struct {
	State         apiv1.ScheduledRunExecutionState
	TaskID        string
	FailureReason string
}

ScheduledRunExecutionProgress contains only fields a worker may change.

type ScheduledRunExecutionQuery

type ScheduledRunExecutionQuery struct {
	ScheduledRunQuery
	ScheduledRunID uuid.UUID
}

type ScheduledRunQuery

type ScheduledRunQuery struct {
	Creator string
	AfterID *uuid.UUID
	Limit   int
}

type SessionOperation

type SessionOperation struct {
	RuntimeOperation[*apiv1.Session]
	SourceCheckpointID *uuid.UUID
}

SessionOperation is the current lifecycle generation on a session. Once Session.Operation is unspecified, callers may return the current session. ExecutorID marks possibly issued runtime work and never expires. The value is an observation, not permission to execute: callers must win Claim first.

type SessionQuery

type SessionQuery struct {
	UserID   string
	AllUsers bool
	Agent    *apiv1.ResourceReference
	AfterID  string
	Limit    int
}

SessionQuery narrows a page of sessions to an optional Agent.

type SessionQuiescence

type SessionQuiescence struct {
	Session    *apiv1.Session
	TaskID     string
	State      a2a.TaskState
	Version    int64
	ExecutorID uuid.UUID
}

SessionQuiescence grants one worker permission to suspend an idle session and record its snapshot. Task publication has already completed.

type SessionTaskSnapshot

type SessionTaskSnapshot struct {
	Atespace string
	URI      string
	Fidelity string
}

SessionTaskSnapshot records the external snapshot at an A2A turn boundary. Only an explicit checkpoint retains a copy after the Actor advances or is deleted.

type TaskPushConfig

type TaskPushConfig struct {
	ID  string
	URL string
}

TaskPushConfig is a stored active configuration; closed receipts are hidden.

type Tool

type Tool struct {
	ID          string     `json:"id"`
	ServerName  string     `json:"server_name"`
	GroupKind   string     `json:"group_kind"`
	CreatedAt   time.Time  `json:"created_at"`
	UpdatedAt   time.Time  `json:"updated_at"`
	DeletedAt   *time.Time `json:"deleted_at,omitempty"`
	Description string     `json:"description"`
}

type ToolServer

type ToolServer struct {
	CreatedAt     time.Time  `json:"created_at"`
	UpdatedAt     time.Time  `json:"updated_at"`
	DeletedAt     *time.Time `json:"deleted_at,omitempty"`
	Name          string     `json:"name"`
	GroupKind     string     `json:"group_kind"`
	Description   string     `json:"description"`
	LastConnected *time.Time `json:"last_connected,omitempty"`
}

Jump to

Keyboard shortcuts

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