sessionio

package module
v0.2.3 Latest Latest
Warning

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

Go to latest
Published: Aug 11, 2026 License: MPL-2.0 Imports: 11 Imported by: 0

README

agent-session-io

ci release

Harness-neutral access to local coding-agent sessions.

agent-session-io is a Go library and a single sessionio CLI for discovering, reading, exporting, and inspecting current sessions from coding-agent harnesses. Codex and Claude Code are the first full-fidelity targets. Catalog-backed scan and search commands are in development against an optional PostgreSQL 18 service.

The core reader stays usable without PostgreSQL, embeddings, a model provider, or a background service.

Install

macOS or Linux:

curl --proto '=https' --tlsv1.2 -fsSL \
  https://raw.githubusercontent.com/nikitatsym/agent-session-io/main/scripts/install.sh | sh

Windows PowerShell:

irm https://raw.githubusercontent.com/nikitatsym/agent-session-io/main/scripts/install.ps1 | iex

With a Go toolchain:

go install github.com/nikitatsym/agent-session-io/cmd/sessionio@latest

The release installers select the current operating system and architecture, download the latest GitHub Release archive, verify its SHA-256 checksum, install into a user-owned directory, and connect shell completion. Restart the shell after installation. Set SESSIONIO_VERSION to install a specific tag, SESSIONIO_INSTALL_DIR to choose another directory, SESSIONIO_COMPLETION_SHELL to override shell detection, or SESSIONIO_NO_COMPLETION=1 to skip completion setup.

Release archives are available for macOS, Linux, and Windows on amd64 and arm64. GitHub build provenance can be verified with:

gh attestation verify sessionio_darwin_arm64.tar.gz \
  --repo nikitatsym/agent-session-io

CLI

Fang and Cobra provide styled help, shell completion, and manpage generation:

sessionio --help
sessionio --version
sessionio version --json
sessionio completion zsh
sessionio completion install
sessionio update
sessionio sources
sessionio list --harness codex --since 7d
sessionio list --current
sessionio list --current=exact --format json
sessionio show SESSION_ID
sessionio export SESSION_ID

sessionio completion install generates a static completion script and connects it through a managed block in the detected shell profile. It is safe to run repeatedly. PowerShell users can override the profile with --profile.

sessionio update selects the latest release for the current platform, verifies it against the published SHA-256 checksum file, and replaces the current executable with rollback on failure. Public release redirects and asset URLs are used directly, so checking for an update does not require a GitHub API token or consume the GitHub REST API rate limit.

sources and list default to human-readable tables. Both accept --format human|json|ndjson, and --harness codex|claude can be repeated. list also accepts inclusive --since and --until bounds as RFC3339 or elapsed durations such as 30m, 7d, or 2w. list --current reports sessions tied to live Codex or Claude processes; --current=exact excludes probable evidence before matching and regrouping. Runtime presence cannot be combined with --since or --until.

Listing is served through an advisory per-source cache, so a warm list, shell completion, session-selector resolution, and scan open no transcript whose size, modification time, and file identity are unchanged. The cache never changes an output byte: an absent, stale, corrupt, or unwritable cache only costs the source read it could not save. A cache file that cannot be parsed is discarded whole and reported on stderr as a human diagnostic. Runtime presence (--current) is never cached.

The cache directory is the platform user cache directory unless SESSIONIO_CACHE_DIR or a [cache] section names another one:

[cache]
dir = "fixtures/cache"
enabled = true

show and export take the session ID printed by list; a unique prefix of the ID or of its digest part is enough, and an ambiguous prefix fails with the matching candidates. show provides --detail normalized|native|provenance. export is the lossless machine interface: it defaults to streaming, self-describing NDJSON and accepts --format json for a single buffered document. Scripts and agents should always pass their desired format explicitly.

Catalog-backed commands need a configured PostgreSQL 18 endpoint and never run implicitly. postgres/compose.yaml provides the canonical profile.

sessionio --config config.toml catalog init
sessionio --config config.toml scan
sessionio --config config.toml search --mode lexical 'why did the protocol change'
sessionio --config config.toml search --mode literal 'ECONNRESET: socket hang up'
sessionio --config config.toml catalog state export --output state.ndjson
sessionio --config config.toml doctor --scope postgres

[search] is optional in the rest of the configuration: a file that declares only [sources] or [cache] serves every reader command, and a catalog-backed command under it fails with postgres_not_configured and exit 3.

Configured source roots decide what a scan reads:

[sources.codex]
home = "fixtures/codex"

[sources.claude]
config_dir = "fixtures/claude"

A declared root wins over the harness environment variable (CODEX_HOME, CLAUDE_CONFIG_DIR), which wins over the platform default. A relative root resolves against the directory holding the configuration file, and every command that reads sessions - sources, list, show, export, and scan - uses the same resolution. Without a [sources] section discovery is unchanged.

scan reconciles every discovered session into a new candidate generation and publishes it in one metadata transaction. A scan that fails before publication leaves the previous generation active and unchanged, and reclaims the rows its candidate had already written. One scan writes a catalog at a time: a scan takes a writer lease for its whole lifecycle - write, publish, reclaim - and a second scan fails with scan_in_progress and exit 3 instead of racing it. Every scan starts by failing and reclaiming the candidate generations of writers that no longer exist, so a catalog left dirty by a killed scan is repaired by the next one.

Derived rows - sessions, events, evidence, relations, passages, projections, and facets - live in shared immutable tables keyed by the session revision and the builder versions that produced them. A generation is the set of derived sessions it presents, recorded as membership rows; publishing moves a pointer and copies nothing. Search takes that membership as a hard predicate before every candidate limit, over one shared BM25 index and one shared trigram index. Because the shared tables also hold superseded revisions until they are reclaimed, index statistics cover more rows than any single generation presents, so BM25 scores are comparable in order and sign, not in absolute value.

A scan is incremental. Every source occurrence carries a checkpoint, and the next scan classifies its container as initial, unchanged, grown, truncated, rewritten, or replaced. An unchanged occurrence costs one membership row: its transcript is never reopened and no derived row is written. A session is rebuilt only when its revision has no retained rows for the current builder versions. A source that disappeared keeps its retained evidence and gains a tombstone. Structural relations are retained per session, and a relation that points at another session or at another session's record is resolved against the revisions the generation presents rather than by rereading a peer transcript. A record-level target names the harness's own record identifier, which the reader exposes as the observation's native key and the catalog retains on every event row; a target that two retained records claim stays unresolved and is counted.

Reclaim removes the membership of a superseded or failed generation and then every derived row no live generation still references. A concurrent reader is isolated by its own snapshot, so reclaim never removes a row a running search depends on. A reclaim that deleted rows also takes them out of the BM25 corpus statistics, so two generations that present the same rows score them identically; this is why a scan that wrote rows persists them into their own index segment before it publishes.

The scan record counts what the new generation presents. A refresh derives those counts from what its parent presented plus the sessions the two do not share, so its cost follows the sessions that changed rather than the corpus. Relation resolution cannot be derived that way - whether a target reaches a session depends on the whole presented set - so it is a full-build diagnostic: resolved_relations and unresolved_relations are numbers when a generation has no parent, are inherited when a refresh changed nothing, and are null with relations: N (resolution not computed) otherwise.

Each scanned session retains a content-addressed compressed snapshot of its native records, so two copies of one transcript share exactly one blob while remaining two distinct observations. --partial publishes a generation even when a source cannot be read; the failed source set travels with the generation, the command exits 4, and every result reports catalog_complete:false.

catalog state export|import moves retained evidence - sources, occurrences, snapshot blobs, immutable session revisions, and scan checkpoints - as one versioned NDJSON stream. The stream starts with a sessionio.catalog.state-manifest/v1 record carrying the record counts and a checksum over everything that follows. import validates the whole stream, its checksum, every blob digest, and every reference before a single transaction, requires an empty target, and commits all records or none. export refuses to overwrite an existing file.

search answers only from a fresh, quiescent catalog. Before it reads, it compares the sources it can list - through the advisory listing cache, opening no transcript - with what the active generation presents, and checks that no generation is left unreclaimed. A catalog that is already current costs that comparison and nothing else. A catalog that is behind or dirty is scanned first: the command reports index is N sessions behind, scanning or index holds unreclaimed rows of an interrupted scan, scanning on stderr, runs the scan, and answers from the generation it published. The machine record states which happened in catalog_refresh. There is no serving from a generation while it is being replaced: while another scan holds the writer lease every search fails with scan_in_progress and exit 3, and a scan the gate had to run and that failed fails the search. A session belonging to a source the active generation declares failed is not counted as behind, and a catch-up the gate runs tolerates exactly the sources that generation declares failed: it attempts each of them again, includes what it can now read, and publishes the same failed set for what it still cannot. A generation published with --partial therefore stays searchable and keeps reporting catalog_complete:false until its sources recover. A source the active generation does not declare failed still fails the scan, and with it the search, so an automatic catch-up never widens a partial generation. A catalog with no generation at all is not caught up automatically: initialization and the first scan stay explicit.

--mode lexical uses the BM25 leg, --mode literal uses case-sensitive exact containment, and every result carries its session, passage, evidence locators, matched leg, catalog generation, and completeness. Literal results report whether PostgreSQL used the trigram index or the bounded scan. Projection text is byte-exact to the native content except for U+0000, which no PostgreSQL text column can store; a result whose text lost NUL bytes reports a nul_removed entry with the removed-byte count in projection_limitations, and the evidence locator still addresses the original bytes. Exit statuses are 0 for a match, 1 for a valid search with no match, 2 for an invalid request, 3 for a missing capability or a catalog that cannot answer yet, 4 for an explicitly requested partial result, and 5 for a runtime or integrity failure.

Machine output and the Go reader API are current drafts until an explicit contract-freeze decision. Before that decision, the project updates them in place without compatibility shims.

The durable reader semantics are documented in the reader contract.

Development

The repository requires Go, Python 3, and uv.

python3 dev.py check
uvx pre-commit install

dev.py is the single development entry point:

  • python3 dev.py lint
  • python3 dev.py test
  • python3 dev.py e2e
  • python3 dev.py check

Lint includes project-owned Go checks and uvx tackbox@latest lint .. Pre-commit and CI run the same complete dev.py check.

PostgreSQL-backed tests default to the project-owned Compose profile. With SESSIONIO_TEST_DATABASE_URL set to a PostgreSQL 18 endpoint that serves the pinned extensions, they run there instead and Docker is not used at all. SESSIONIO_TEST_ADMIN_DATABASE_URL names the endpoint the privilege tests use to create a temporary limited role; it defaults to the primary endpoint, whose role must then be a superuser. The pg-adversarial cases always need Docker: they boot deliberately broken servers.

Release

Pushing a semantic version tag runs the complete check, builds cross-platform archives with GoReleaser, publishes checksums, and records GitHub build provenance:

git tag v0.1.0
git push origin v0.1.0

License

Mozilla Public License 2.0. See LICENSE.

Documentation

Overview

Package sessionio provides harness-neutral access to coding-agent sessions.

Index

Constants

View Source
const PresenceSchema = "sessionio.presence/v1"

PresenceSchema identifies the runtime-presence machine-output schema.

View Source
const ReaderSchema = "sessionio.reader/v1"

ReaderSchema identifies the initial reader machine-output schema.

Variables

View Source
var ErrStreamClosed = errors.New("sessionio: stream closed")

ErrStreamClosed is returned when Next is called after Close.

Functions

func ValidatePresenceSnapshot

func ValidatePresenceSnapshot(snapshot PresenceSnapshot) error

ValidatePresenceSnapshot validates a runtime-presence snapshot before use or encoding.

func WriteJSON

func WriteJSON(writer io.Writer, producer Producer, records []Record) error

WriteJSON writes one validated reader document followed by a newline.

func WritePresenceJSON

func WritePresenceJSON(writer io.Writer, producer Producer, snapshot PresenceSnapshot) error

WritePresenceJSON writes one validated presence snapshot followed by a newline.

Types

type Adapter

type Adapter interface {
	Descriptor() AdapterDescriptor
	Sources(context.Context) (Stream[Source], error)
	Sessions(context.Context, SessionRequest) (Stream[SessionRef], error)
	Read(context.Context, SessionRef) (Stream[ReadItem], error)
}

Adapter discovers and reads sessions for one harness.

type AdapterDescriptor

type AdapterDescriptor struct {
	Harness      Harness            `json:"harness"`
	Version      string             `json:"version"`
	Capabilities []CapabilityStatus `json:"capabilities"`
}

AdapterDescriptor declares an adapter's identity and capabilities.

type ByteRange

type ByteRange struct {
	Start int64 `json:"start"`
	End   int64 `json:"end"`
}

ByteRange is a half-open source byte range.

type Capability

type Capability string

Capability identifies a reader feature exposed by a source or adapter.

const (
	CapabilityDiscovery          Capability = "discovery"
	CapabilityMessages           Capability = "messages"
	CapabilityRichContent        Capability = "rich_content"
	CapabilityTools              Capability = "tools"
	CapabilityReasoning          Capability = "reasoning"
	CapabilityBranches           Capability = "branches"
	CapabilityUsage              Capability = "usage"
	CapabilityEnvironment        Capability = "environment"
	CapabilityRepository         Capability = "repository"
	CapabilityIncrementalReading Capability = "incremental_reading"
)

type CapabilityStatus

type CapabilityStatus struct {
	Capability Capability   `json:"capability"`
	Support    SupportLevel `json:"support"`
	Detail     string       `json:"detail,omitempty"`
}

CapabilityStatus describes one capability.

type CaptureKind

type CaptureKind string

CaptureKind distinguishes exact bytes from a logical structured snapshot.

const (
	CaptureKindByteExact          CaptureKind = "byte_exact"
	CaptureKindStructuredSnapshot CaptureKind = "structured_snapshot"
	CaptureKindDecodedStream      CaptureKind = "decoded_stream"
)

type ContentAvailability

type ContentAvailability string

ContentAvailability describes why content is or is not directly readable.

const (
	ContentAvailabilityAvailable   ContentAvailability = "available"
	ContentAvailabilityEncrypted   ContentAvailability = "encrypted"
	ContentAvailabilityRedacted    ContentAvailability = "redacted"
	ContentAvailabilityExternal    ContentAvailability = "external"
	ContentAvailabilityUnavailable ContentAvailability = "unavailable"
)

type ContentBlock

type ContentBlock struct {
	ID           ContentID           `json:"id"`
	Kind         ContentKind         `json:"kind"`
	Availability ContentAvailability `json:"availability"`
	Text         *TextContent        `json:"text,omitempty"`
	Media        *MediaContent       `json:"media,omitempty"`
	Opaque       *OpaqueContent      `json:"opaque,omitempty"`
}

ContentBlock is one typed message or reasoning content block.

type ContentID

type ContentID string

ContentID is an opaque content-block identifier.

type ContentKind

type ContentKind string

ContentKind selects the active ContentBlock variant.

const (
	ContentKindText   ContentKind = "text"
	ContentKindMedia  ContentKind = "media"
	ContentKindOpaque ContentKind = "opaque"
)

type DatabaseKey

type DatabaseKey struct {
	Name  string `json:"name"`
	Value string `json:"value"`
}

DatabaseKey is one native database key component.

type DatabaseLocator

type DatabaseLocator struct {
	Path  string        `json:"path"`
	Table string        `json:"table"`
	Keys  []DatabaseKey `json:"keys,omitempty"`
}

DatabaseLocator identifies a row or event within a database.

type Diagnostic

type Diagnostic struct {
	Code     string             `json:"code"`
	Severity DiagnosticSeverity `json:"severity"`
	Message  string             `json:"message"`
	Locator  *SourceLocator     `json:"locator,omitempty"`
	Cause    error              `json:"-"`
}

Diagnostic reports a non-fatal source or capability condition.

type DiagnosticSeverity

type DiagnosticSeverity string

DiagnosticSeverity identifies the impact of a reader diagnostic.

const (
	DiagnosticSeverityInfo    DiagnosticSeverity = "info"
	DiagnosticSeverityWarning DiagnosticSeverity = "warning"
	DiagnosticSeverityError   DiagnosticSeverity = "error"
)

type DiscoveryRevision

type DiscoveryRevision string

DiscoveryRevision is an opaque, non-authoritative discovery change token.

type Event

type Event struct {
	ID         EventID          `json:"id"`
	Kind       EventKind        `json:"kind"`
	Timestamp  *time.Time       `json:"timestamp,omitempty"`
	Evidence   []EvidenceRef    `json:"evidence"`
	Message    *MessageEvent    `json:"message,omitempty"`
	Reasoning  *ReasoningEvent  `json:"reasoning,omitempty"`
	ToolCall   *ToolCallEvent   `json:"tool_call,omitempty"`
	ToolResult *ToolResultEvent `json:"tool_result,omitempty"`
	Usage      *UsageEvent      `json:"usage,omitempty"`
	Facts      *FactEvent       `json:"facts,omitempty"`
	Marker     *MarkerEvent     `json:"marker,omitempty"`
	Unknown    *UnknownEvent    `json:"unknown,omitempty"`
}

Event is one normalized event backed by native evidence.

type EventID

type EventID string

EventID is an opaque normalized-event identifier.

type EventKind

type EventKind string

EventKind selects the active Event variant.

const (
	EventKindMessage    EventKind = "message"
	EventKindReasoning  EventKind = "reasoning"
	EventKindToolCall   EventKind = "tool_call"
	EventKindToolResult EventKind = "tool_result"
	EventKindUsage      EventKind = "usage"
	EventKindFacts      EventKind = "facts"
	EventKindMarker     EventKind = "marker"
	EventKindUnknown    EventKind = "unknown"
)

type EvidenceRef

type EvidenceRef struct {
	Observation ObservationID `json:"observation"`
	Locator     SourceLocator `json:"locator"`
}

EvidenceRef points from normalized data to a native observation.

type Fact

type Fact struct {
	Kind  FactKind `json:"kind"`
	Value string   `json:"value"`
}

Fact is one typed normalized fact.

type FactEvent

type FactEvent struct {
	Facts []Fact `json:"facts"`
}

FactEvent contains normalized session facts.

type FactKind

type FactKind string

FactKind identifies a normalized session fact.

const (
	FactKindLaunchDirectory  FactKind = "launch_directory"
	FactKindWorkingDirectory FactKind = "working_directory"
	FactKindModel            FactKind = "model"
	FactKindProvider         FactKind = "provider"
	FactKindEffort           FactKind = "effort"
	FactKindGitRoot          FactKind = "git_root"
	FactKindGitRemote        FactKind = "git_remote"
	FactKindGitBranch        FactKind = "git_branch"
	FactKindGitCommit        FactKind = "git_commit"
	FactKindApprovalPolicy   FactKind = "approval_policy"
	FactKindSandboxPolicy    FactKind = "sandbox_policy"
	FactKindTimezone         FactKind = "timezone"
	FactKindCurrentDate      FactKind = "current_date"
)

type FileLocator

type FileLocator struct {
	Root      string     `json:"root"`
	Path      string     `json:"path"`
	Record    *uint64    `json:"record,omitempty"`
	Line      *uint64    `json:"line,omitempty"`
	ByteRange *ByteRange `json:"byte_range,omitempty"`
}

FileLocator identifies a record or byte range within a root-relative file.

type Harness

type Harness string

Harness identifies a coding-agent harness.

const (
	HarnessCodex    Harness = "codex"
	HarnessClaude   Harness = "claude"
	HarnessOMP      Harness = "omp"
	HarnessOpenCode Harness = "opencode"
)

type LimitationKind

type LimitationKind string

LimitationKind identifies missing fidelity in the upstream source.

const (
	LimitationKindUpstreamTruncation     LimitationKind = "upstream_truncation"
	LimitationKindExternalPayload        LimitationKind = "external_payload"
	LimitationKindMissingExternalPayload LimitationKind = "missing_external_payload"
	LimitationKindMutableMaterialization LimitationKind = "mutable_materialization"
)

type ListingCache added in v0.2.0

type ListingCache interface {
	// Lookup returns the retained listing record for key while stamp matches.
	Lookup(key string, stamp string) (SessionRef, bool)
	// Retain stores the listing record that key produced under stamp.
	Retain(key string, stamp string, ref SessionRef)
}

ListingCache is an advisory per-source cache of session listing records. It never changes what an adapter lists: a miss, a changed stamp, or an unusable cache only costs the source read that produced the record before.

The stamp is opaque to the cache and is built by the adapter from the size, modification time, and file identity of every container the listing record was read from.

type ListingCacheSource added in v0.2.0

type ListingCacheSource interface {
	ListingCache(sourceID string) (ListingCache, bool)
}

ListingCacheSource hands an adapter the advisory cache of one source. An adapter resolves its own source identity, so the cache file of one source never serves another.

type LocatorKind

type LocatorKind string

LocatorKind selects the active SourceLocator variant.

const (
	LocatorKindFile     LocatorKind = "file"
	LocatorKindDatabase LocatorKind = "database"
	LocatorKindOpaque   LocatorKind = "opaque"
)

type MarkerEvent

type MarkerEvent struct {
	Name  string `json:"name"`
	State string `json:"state,omitempty"`
}

MarkerEvent preserves an operational or structural native marker.

type MediaContent

type MediaContent struct {
	MediaType string `json:"media_type,omitempty"`
	Data      []byte `json:"data,omitempty"`
	Reference string `json:"reference,omitempty"`
}

MediaContent contains inline or externally referenced media.

type MessageEvent

type MessageEvent struct {
	Role    MessageRole    `json:"role"`
	Content []ContentBlock `json:"content,omitempty"`
}

MessageEvent contains ordered native message content.

type MessageRole

type MessageRole string

MessageRole identifies the native conversational role.

const (
	MessageRoleUser      MessageRole = "user"
	MessageRoleAssistant MessageRole = "assistant"
	MessageRoleDeveloper MessageRole = "developer"
	MessageRoleSystem    MessageRole = "system"
	MessageRoleTool      MessageRole = "tool"
	MessageRoleUnknown   MessageRole = "unknown"
)

type NDJSONEncoder

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

NDJSONEncoder writes independently decodable reader records.

func NewNDJSONEncoder

func NewNDJSONEncoder(writer io.Writer, producer Producer) (*NDJSONEncoder, error)

NewNDJSONEncoder creates a validated NDJSON encoder.

func (*NDJSONEncoder) Encode

func (encoder *NDJSONEncoder) Encode(record Record) error

Encode validates and writes one self-describing NDJSON record.

type NativeAgentMetadata

type NativeAgentMetadata struct {
	Nickname string `json:"nickname,omitempty"`
	Role     string `json:"role,omitempty"`
	Path     string `json:"path,omitempty"`
}

type NativeHistoryMetadata

type NativeHistoryMetadata struct {
	BaseNativeID        string  `json:"base_native_id,omitempty"`
	EndOrdinalExclusive *uint64 `json:"end_ordinal_exclusive,omitempty"`
	EndByteOffset       *uint64 `json:"end_byte_offset,omitempty"`
	OwnStartOrdinal     *uint64 `json:"own_start_ordinal,omitempty"`
}

type NativeIdentity

type NativeIdentity struct {
	Kind  NativeIdentityKind `json:"kind"`
	Value string             `json:"value"`
}

type NativeIdentityKind

type NativeIdentityKind string

NativeIdentityKind identifies one native session identity.

const NativeIdentityKindSession NativeIdentityKind = "session"

type NativeObservation

type NativeObservation struct {
	ID         ObservationID `json:"id"`
	NativeKind string        `json:"native_kind"`
	// NativeKey is the harness's own record identifier, empty where a harness
	// has none. Sessionio stores and matches it but never interprets it.
	NativeKey      string               `json:"native_key,omitempty"`
	NativeVersion  string               `json:"native_version,omitempty"`
	Timestamp      *time.Time           `json:"timestamp,omitempty"`
	Locator        SourceLocator        `json:"locator"`
	Revision       Revision             `json:"revision"`
	Representation NativeRepresentation `json:"representation"`
	Limitations    []SourceLimitation   `json:"limitations,omitempty"`
}

NativeObservation is the smallest independently locatable native unit.

type NativeRelationshipHint

type NativeRelationshipHint struct {
	Kind           NativeRelationshipKind `json:"kind"`
	TargetNativeID string                 `json:"target_native_id"`
}

type NativeRelationshipKind

type NativeRelationshipKind string

NativeRelationshipKind identifies a native session relationship hint.

const (
	NativeRelationshipKindForkParent    NativeRelationshipKind = "fork_parent"
	NativeRelationshipKindControlParent NativeRelationshipKind = "control_parent"
)

type NativeRepresentation

type NativeRepresentation struct {
	Capture   CaptureKind `json:"capture"`
	Codec     string      `json:"codec,omitempty"`
	MediaType string      `json:"media_type"`
	Data      []byte      `json:"data"`
	Framing   []byte      `json:"framing,omitempty"`
}

NativeRepresentation preserves a source-native observation.

type NativeSessionMetadata

type NativeSessionMetadata struct {
	Identities    []NativeIdentity         `json:"identities,omitempty"`
	Relationships []NativeRelationshipHint `json:"relationships,omitempty"`
	Agent         *NativeAgentMetadata     `json:"agent,omitempty"`
	History       *NativeHistoryMetadata   `json:"history,omitempty"`
}

NativeSessionMetadata preserves native identities and session topology.

type NextFunc

type NextFunc[T any] func(context.Context) (T, error)

NextFunc produces the next stream value.

type NodeKind

type NodeKind string

NodeKind identifies the object addressed by a relation endpoint.

const (
	NodeKindSession     NodeKind = "session"
	NodeKindObservation NodeKind = "observation"
	NodeKindEvent       NodeKind = "event"
	NodeKindContent     NodeKind = "content"
	// NodeKindNativeRecord addresses a native record by its NativeKey, so a
	// relation can name a peer record without reading the peer source.
	NodeKindNativeRecord NodeKind = "native_record"
)

type NodeRef

type NodeRef struct {
	Kind NodeKind `json:"kind"`
	ID   string   `json:"id"`
}

NodeRef identifies one relation endpoint.

type ObservationID

type ObservationID string

ObservationID is an opaque source-native observation identifier.

type OccurrenceID

type OccurrenceID string

OccurrenceID is an opaque source-occurrence identifier.

type OpaqueContent

type OpaqueContent struct {
	NativeType string `json:"native_type"`
	MediaType  string `json:"media_type,omitempty"`
	Data       []byte `json:"data,omitempty"`
}

OpaqueContent preserves a harness-specific content block.

type OpaqueLocator

type OpaqueLocator struct {
	Scheme string `json:"scheme"`
	Value  string `json:"value"`
}

OpaqueLocator identifies a unit through an adapter-defined scheme.

type Payload

type Payload struct {
	MediaType string `json:"media_type"`
	Data      []byte `json:"data"`
}

Payload preserves a typed tool payload without interpreting its bytes.

type PresenceCapability

type PresenceCapability string

PresenceCapability identifies a runtime-presence signal a provider can inspect.

const (
	PresenceCapabilityExactMatch    PresenceCapability = "exact_match"
	PresenceCapabilityProbableMatch PresenceCapability = "probable_match"
)

type PresenceCapabilityStatus

type PresenceCapabilityStatus struct {
	Capability PresenceCapability `json:"capability"`
	Support    PresenceSupport    `json:"support"`
	Reason     *PresenceReason    `json:"reason,omitempty"`
	Detail     string             `json:"detail,omitempty"`
}

PresenceCapabilityStatus reports one provider capability for one harness.

type PresenceCertainty

type PresenceCertainty string

PresenceCertainty describes the strength of a runtime-to-session match.

const (
	PresenceCertaintyExact    PresenceCertainty = "exact"
	PresenceCertaintyProbable PresenceCertainty = "probable"
)

type PresenceEvidence

type PresenceEvidence struct {
	Kind      PresenceEvidenceKind `json:"kind"`
	Certainty PresenceCertainty    `json:"certainty"`
	Detail    string               `json:"detail,omitempty"`
}

PresenceEvidence is a typed, non-secret observation supporting a presence result.

type PresenceEvidenceKind

type PresenceEvidenceKind string

PresenceEvidenceKind identifies a non-secret runtime-presence observation.

const (
	PresenceEvidenceProcessIdentity       PresenceEvidenceKind = "process_identity"
	PresenceEvidenceNativeSessionRegistry PresenceEvidenceKind = "native_session_registry"
	PresenceEvidenceOpenSessionFile       PresenceEvidenceKind = "open_session_file"
	PresenceEvidenceTerminalIdentity      PresenceEvidenceKind = "terminal_identity"
	PresenceEvidenceTerminalBreadcrumb    PresenceEvidenceKind = "terminal_breadcrumb"
	PresenceEvidenceLoopbackListener      PresenceEvidenceKind = "loopback_listener"
	PresenceEvidenceHealthEndpoint        PresenceEvidenceKind = "health_endpoint"
	PresenceEvidenceSessionStatus         PresenceEvidenceKind = "session_status"
)

type PresenceMatch

type PresenceMatch struct {
	Harness         Harness              `json:"harness"`
	NativeSessionID string               `json:"native_session_id"`
	Certainty       PresenceCertainty    `json:"certainty"`
	Occurrences     []PresenceOccurrence `json:"occurrences"`
	Selection       PresenceSelection    `json:"selection"`
	Processes       []ProcessInstance    `json:"processes"`
	Evidence        []PresenceEvidence   `json:"evidence"`
}

PresenceMatch groups runtime observations by harness and native session ID.

type PresenceNDJSONEncoder

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

PresenceNDJSONEncoder writes independently decodable presence snapshots.

func NewPresenceNDJSONEncoder

func NewPresenceNDJSONEncoder(writer io.Writer, producer Producer) (*PresenceNDJSONEncoder, error)

NewPresenceNDJSONEncoder creates a validated presence NDJSON encoder.

func (*PresenceNDJSONEncoder) Encode

func (encoder *PresenceNDJSONEncoder) Encode(snapshot PresenceSnapshot) error

Encode validates and writes one self-describing presence snapshot.

type PresenceOccurrence

type PresenceOccurrence struct {
	Session  SessionRef                 `json:"session"`
	Relation PresenceOccurrenceRelation `json:"relation"`
}

PresenceOccurrence attaches one persisted session occurrence to a native session match.

type PresenceOccurrenceRelation

type PresenceOccurrenceRelation string

PresenceOccurrenceRelation describes how a persisted occurrence matches a native session.

const (
	PresenceOccurrenceRelationExactLocator   PresenceOccurrenceRelation = "exact_locator"
	PresenceOccurrenceRelationNativeIdentity PresenceOccurrenceRelation = "native_identity"
)

type PresenceProviderStatus

type PresenceProviderStatus struct {
	Harness      Harness                    `json:"harness"`
	Version      string                     `json:"version"`
	Support      PresenceSupport            `json:"support"`
	Reason       *PresenceReason            `json:"reason,omitempty"`
	Detail       string                     `json:"detail,omitempty"`
	Capabilities []PresenceCapabilityStatus `json:"capabilities"`
}

PresenceProviderStatus reports a versioned runtime-presence provider for one harness.

type PresenceReason

type PresenceReason string

PresenceReason explains a non-match or unavailable runtime-presence signal.

const (
	PresenceReasonAccessDenied            PresenceReason = "access_denied"
	PresenceReasonAuthenticationRequired  PresenceReason = "authentication_required"
	PresenceReasonCrossEnvironment        PresenceReason = "cross_environment"
	PresenceReasonInspectionFailed        PresenceReason = "inspection_failed"
	PresenceReasonNoSessionIdentity       PresenceReason = "no_session_identity"
	PresenceReasonPrerequisiteMissing     PresenceReason = "prerequisite_missing"
	PresenceReasonProcessExited           PresenceReason = "process_exited"
	PresenceReasonProviderUnavailable     PresenceReason = "provider_unavailable"
	PresenceReasonProviderUnsupported     PresenceReason = "provider_unsupported"
	PresenceReasonStaleProcessIdentity    PresenceReason = "stale_process_identity"
	PresenceReasonUnmatchedNativeIdentity PresenceReason = "unmatched_native_identity"
)

type PresenceSelection

type PresenceSelection struct {
	Status    PresenceSelectionStatus `json:"status"`
	SessionID SessionID               `json:"session_id,omitempty"`
}

PresenceSelection records the selected persisted occurrence, if resolution was possible.

type PresenceSelectionStatus

type PresenceSelectionStatus string

PresenceSelectionStatus describes whether one persisted occurrence was selected.

const (
	PresenceSelectionResolved  PresenceSelectionStatus = "resolved"
	PresenceSelectionAmbiguous PresenceSelectionStatus = "ambiguous"
)

type PresenceSnapshot

type PresenceSnapshot struct {
	ObservedAt         time.Time                `json:"observed_at"`
	ExpiresAt          time.Time                `json:"expires_at"`
	Providers          []PresenceProviderStatus `json:"providers"`
	Matches            []PresenceMatch          `json:"matches"`
	UnmatchedProcesses []UnmatchedProcess       `json:"unmatched_processes"`
}

PresenceSnapshot is one ephemeral, time-bounded runtime-presence observation.

type PresenceSupport

type PresenceSupport string

PresenceSupport describes whether a runtime-presence signal is available.

const (
	PresenceSupportSupported   PresenceSupport = "supported"
	PresenceSupportUnavailable PresenceSupport = "unavailable"
	PresenceSupportUnsupported PresenceSupport = "unsupported"
)

type ProcessInstance

type ProcessInstance struct {
	PID       uint64             `json:"pid"`
	StartedAt time.Time          `json:"started_at"`
	Evidence  []PresenceEvidence `json:"evidence"`
}

ProcessInstance is a live process identity sampled with its start time.

type Producer

type Producer struct {
	Name    string `json:"name"`
	Version string `json:"version"`
}

Producer identifies the program that emitted machine output.

type ReadItem

type ReadItem struct {
	Session     SessionRef        `json:"session"`
	Observation NativeObservation `json:"observation"`
	Events      []Event           `json:"events,omitempty"`
	Relations   []Relation        `json:"relations,omitempty"`
	Diagnostics []Diagnostic      `json:"diagnostics,omitempty"`
}

ReadItem contains one native observation and its normalized projections.

type ReaderError

type ReaderError struct {
	Operation      string
	Harness        Harness
	AdapterVersion string
	SessionID      SessionID
	Locator        *SourceLocator
	Err            error
}

ReaderError adds reader context while preserving the underlying error.

func (*ReaderError) Error

func (readerError *ReaderError) Error() string

func (*ReaderError) Unwrap

func (readerError *ReaderError) Unwrap() error

Unwrap returns the underlying reader failure.

type ReasoningEvent

type ReasoningEvent struct {
	Content []ContentBlock `json:"content,omitempty"`
	Summary []ContentBlock `json:"summary,omitempty"`
}

ReasoningEvent contains reasoning and any separately exposed summary.

type Record

type Record struct {
	Kind       RecordKind  `json:"kind"`
	Source     *Source     `json:"source,omitempty"`
	Session    *SessionRef `json:"session,omitempty"`
	ReadItem   *ReadItem   `json:"read_item,omitempty"`
	Diagnostic *Diagnostic `json:"diagnostic,omitempty"`
}

Record is one validated reader machine-output record.

type RecordKind

type RecordKind string

RecordKind selects the active Record variant.

const (
	RecordKindSource     RecordKind = "source"
	RecordKindSession    RecordKind = "session"
	RecordKindReadItem   RecordKind = "read_item"
	RecordKindDiagnostic RecordKind = "diagnostic"
)

type Registry

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

Registry stores one validated adapter per harness.

func NewRegistry

func NewRegistry(adapters ...Adapter) (*Registry, error)

NewRegistry creates a registry and validates every supplied adapter.

func (*Registry) Adapter

func (registry *Registry) Adapter(harness Harness) (Adapter, bool)

Adapter returns the adapter registered for a harness.

func (*Registry) Descriptors

func (registry *Registry) Descriptors() []AdapterDescriptor

Descriptors returns descriptors ordered lexically by harness.

func (*Registry) Register

func (registry *Registry) Register(adapter Adapter) error

Register adds an adapter after validating its descriptor.

type Relation

type Relation struct {
	ID       RelationID     `json:"id"`
	Kind     RelationKind   `json:"kind"`
	From     NodeRef        `json:"from"`
	To       NodeRef        `json:"to"`
	Origin   RelationOrigin `json:"origin"`
	Evidence []EvidenceRef  `json:"evidence"`
}

Relation links two typed nodes using native evidence.

type RelationID

type RelationID string

RelationID is an opaque structural-relation identifier.

type RelationKind

type RelationKind string

RelationKind identifies a structural relation.

const (
	RelationKindPrevious     RelationKind = "previous"
	RelationKindNext         RelationKind = "next"
	RelationKindReplyTo      RelationKind = "reply_to"
	RelationKindBranchParent RelationKind = "branch_parent"
	RelationKindContains     RelationKind = "contains"
	RelationKindToolPair     RelationKind = "tool_pair"
	RelationKindMaterializes RelationKind = "materializes"
	RelationKindUpdates      RelationKind = "updates"
	// RelationKindActiveLeaf identifies the source-selected leaf of a persisted branch tree.
	RelationKindActiveLeaf RelationKind = "active_leaf"
)

type RelationOrigin

type RelationOrigin string

RelationOrigin distinguishes native relations from deterministic projections.

const (
	RelationOriginNative        RelationOrigin = "native"
	RelationOriginDeterministic RelationOrigin = "deterministic"
)

type Revision

type Revision struct {
	Kind  RevisionKind `json:"kind"`
	Value string       `json:"value"`
}

Revision identifies the immutable source state used for a read.

type RevisionKind

type RevisionKind string

RevisionKind identifies the source revision mechanism.

const (
	RevisionKindFileSnapshot        RevisionKind = "file_snapshot"
	RevisionKindDatabaseTransaction RevisionKind = "database_transaction"
	RevisionKindEventSequence       RevisionKind = "event_sequence"
	RevisionKindOpaque              RevisionKind = "opaque"
)

type SessionID

type SessionID string

SessionID is an opaque occurrence-scoped session identifier.

type SessionRef

type SessionRef struct {
	ID                SessionID             `json:"id"`
	NativeID          string                `json:"native_id"`
	Title             string                `json:"title,omitempty"`
	DiscoveryRevision DiscoveryRevision     `json:"discovery_revision"`
	Native            NativeSessionMetadata `json:"native"`
	Occurrence        SourceOccurrence      `json:"occurrence"`
	StartedAt         *time.Time            `json:"started_at,omitempty"`
	UpdatedAt         *time.Time            `json:"updated_at,omitempty"`
	Diagnostics       []Diagnostic          `json:"diagnostics,omitempty"`
}

SessionRef identifies one native session within one source occurrence.

type SessionRequest

type SessionRequest struct {
	Sources []SourceID
}

SessionRequest filters session discovery by source.

type Source

type Source struct {
	ID           SourceID           `json:"id"`
	Harness      Harness            `json:"harness"`
	Kind         SourceKind         `json:"kind"`
	Status       SourceStatus       `json:"status"`
	Locator      SourceLocator      `json:"locator"`
	Capabilities []CapabilityStatus `json:"capabilities,omitempty"`
	Diagnostics  []Diagnostic       `json:"diagnostics,omitempty"`
}

Source describes one discovered native source.

type SourceID

type SourceID string

SourceID is an opaque discovered-source identifier.

type SourceKind

type SourceKind string

SourceKind distinguishes canonical transcripts from auxiliary stores.

const (
	SourceKindCanonical SourceKind = "canonical"
	SourceKindAuxiliary SourceKind = "auxiliary"
)

type SourceLimitation

type SourceLimitation struct {
	Kind   LimitationKind `json:"kind"`
	Detail string         `json:"detail,omitempty"`
}

SourceLimitation records a native-source fidelity limitation.

type SourceLocator

type SourceLocator struct {
	Kind     LocatorKind      `json:"kind"`
	File     *FileLocator     `json:"file,omitempty"`
	Database *DatabaseLocator `json:"database,omitempty"`
	Opaque   *OpaqueLocator   `json:"opaque,omitempty"`
}

SourceLocator locates a source-native unit.

type SourceOccurrence

type SourceOccurrence struct {
	ID       OccurrenceID  `json:"id"`
	SourceID SourceID      `json:"source_id"`
	Harness  Harness       `json:"harness"`
	Locator  SourceLocator `json:"locator"`
}

SourceOccurrence identifies one observed instance of a source.

type SourceStatus

type SourceStatus string

SourceStatus describes whether a discovered source can be read.

const (
	SourceStatusAvailable   SourceStatus = "available"
	SourceStatusMissing     SourceStatus = "missing"
	SourceStatusDisabled    SourceStatus = "disabled"
	SourceStatusUnsupported SourceStatus = "unsupported"
)

type Stream

type Stream[T any] interface {
	Next(context.Context) (T, error)
	Close() error
}

Stream is a pull-based sequence with explicit resource ownership.

func NewStream

func NewStream[T any](next NextFunc[T], close func() error) (Stream[T], error)

NewStream wraps callbacks in the Stream lifecycle contract.

type SupportLevel

type SupportLevel string

SupportLevel describes how completely a capability is implemented.

const (
	SupportFull         SupportLevel = "full"
	SupportPartial      SupportLevel = "partial"
	SupportExperimental SupportLevel = "experimental"
	SupportUnavailable  SupportLevel = "unavailable"
)

type TextContent

type TextContent struct {
	Text string `json:"text"`
}

TextContent contains a native text block.

type ToolCallEvent

type ToolCallEvent struct {
	CallID string  `json:"call_id"`
	Name   string  `json:"name"`
	Input  Payload `json:"input"`
}

ToolCallEvent contains one native tool invocation.

type ToolResultEvent

type ToolResultEvent struct {
	CallID string           `json:"call_id"`
	Status ToolResultStatus `json:"status"`
	Output Payload          `json:"output"`
}

ToolResultEvent contains one native tool result or state transition.

type ToolResultStatus

type ToolResultStatus string

ToolResultStatus describes the state represented by a tool result.

const (
	ToolResultStatusSuccess ToolResultStatus = "success"
	ToolResultStatusError   ToolResultStatus = "error"
	ToolResultStatusPending ToolResultStatus = "pending"
	ToolResultStatusRunning ToolResultStatus = "running"
	ToolResultStatusUnknown ToolResultStatus = "unknown"
)

type UnknownEvent

type UnknownEvent struct {
	NativeType string `json:"native_type"`
}

UnknownEvent preserves the type of an otherwise unknown native record.

type UnmatchedProcess

type UnmatchedProcess struct {
	Harness          Harness            `json:"harness"`
	Process          ProcessInstance    `json:"process"`
	ClaimedNativeIDs []string           `json:"claimed_native_ids,omitempty"`
	Reason           PresenceReason     `json:"reason"`
	Evidence         []PresenceEvidence `json:"evidence"`
}

UnmatchedProcess is a live harness process that was not assigned to a persisted session.

type UsageEvent

type UsageEvent struct {
	InputTokens      *int64 `json:"input_tokens,omitempty"`
	OutputTokens     *int64 `json:"output_tokens,omitempty"`
	ReasoningTokens  *int64 `json:"reasoning_tokens,omitempty"`
	CacheReadTokens  *int64 `json:"cache_read_tokens,omitempty"`
	CacheWriteTokens *int64 `json:"cache_write_tokens,omitempty"`
	TotalTokens      *int64 `json:"total_tokens,omitempty"`
}

UsageEvent contains normalized optional token counters.

Directories

Path Synopsis
adapters
claude
Package claude reads Claude Code transcript JSONL files.
Package claude reads Claude Code transcript JSONL files.
codex
Package codex reads Codex rollout JSONL files.
Package codex reads Codex rollout JSONL files.
cmd
sessionio command
internal
catalog
Package catalog owns the PostgreSQL search catalog and its typed failures.
Package catalog owns the PostgreSQL search catalog and its typed failures.
cli
config
Package config loads the versioned strict TOML configuration file.
Package config loads the versioned strict TOML configuration file.
fileid
Package fileid produces a persistable file identity, so a later run can tell an in-place rewrite from an atomic replacement at the same path.
Package fileid produces a persistable file identity, so a later run can tell an in-place rewrite from an atomic replacement at the same path.
passage
Package passage turns normalized reader items into deterministic passages and their searchable projections.
Package passage turns normalized reader items into deterministic passages and their searchable projections.
readercache
Package readercache retains an advisory per-source listing cache, so a warm listing reopens no source container whose stat identity is unchanged.
Package readercache retains an advisory per-source listing cache, so a warm listing reopens no source container whose stat identity is unchanged.

Jump to

Keyboard shortcuts

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