application

package
v3.0.1-alpha9 Latest Latest
Warning

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

Go to latest
Published: Jul 5, 2026 License: AGPL-3.0 Imports: 56 Imported by: 0

Documentation

Index

Constants

View Source
const (
	LexicalModeFTS5        = "fts5"
	LexicalModeGraphLabels = "graph-labels"
)

Lexical search modes reported to callers so agents know whether results came from full text or the degraded label search.

View Source
const AgentSkillTypeSlug = "agent-skill"

AgentSkillTypeSlug is the resource type declarative agent skills live in.

View Source
const NoteTypeSlug = "note"

NoteTypeSlug is the memory preset's episodic input type — the only type background consolidation (#386) distills facts from by default.

Variables

View Source
var ErrForbidden = errors.New("forbidden")

ErrForbidden is returned when the caller lacks required permissions.

View Source
var ErrKGQueryNotPermitted = errors.New("knowledge graph query form not permitted for this caller")

ErrKGQueryNotPermitted is returned when a scoped (non-system) caller submits a free-form SPARQL query whose results cannot be permission-filtered after execution. Post-execution filtering only works when forbidden data surfaces as a gated IRI in the result rows; it cannot redact a bare boolean (ASK), an aggregate literal (COUNT/SUM/…), or a row deliberately built to omit the forbidden subject. Those shapes are refused for scoped callers. Row- projecting SELECT/CONSTRUCT/DESCRIBE queries and the structured KG tools (expand/search/describe/path) remain available. System callers (nil identity) are unaffected.

View Source
var ErrKGUnavailable = errors.New("knowledge graph not configured")

ErrKGUnavailable is returned when a knowledge-graph operation is requested but the underlying store is not configured. Callers (notably MCP tool handlers) translate this to a "knowledge graph not configured" message instead of an empty result so the LLM doesn't reason on a false negative.

View Source
var ErrLexicalUnavailable = errors.New(
	"lexical search unavailable: no FTS5 index and no knowledge graph configured")

ErrLexicalUnavailable is returned when neither the FTS5 index nor the knowledge graph is available to answer a lexical search.

View Source
var ErrUnknownEvent = fmt.Errorf("the event is unknown")

ErrUnknownEvent distinguishes a well-formed event URN that matches no stored event — a clear error, never an empty success.

View Source
var ErrUnknownSeedEvent = fmt.Errorf("the seed event is unknown")

ErrUnknownSeedEvent distinguishes a well-formed seed that matches no stored event: similarity is undefined without a seed, so this is an error, not an empty success.

View Source
var ErrValidation = errors.New("validation error")

ErrValidation is returned for client-side validation failures (bad input).

View Source
var ODRLActions = map[string]string{
	"read":   authentities.ActionRead,
	"modify": authentities.ActionModify,
	"delete": authentities.ActionDelete,
}

ODRLActions maps short action names used in the API to ODRL IRIs.

Functions

func AddEdgeToGraph

func AddEdgeToGraph(
	data json.RawMessage, predicate, objectID, subjectID string,
) (json.RawMessage, error)

AddEdgeToGraph adds a relationship edge to a JSON-LD @graph document. Multi-valued predicates accumulate into an array. Re-adding an edge that already exists with the same (predicate, object) pair is a no-op — this lets the Triple.Created projection replay edges already materialized in Resource.Created's @graph body without duplicating them. If no edges node exists, one is created. If no @graph exists, the data is wrapped as an entity node with a new edges node. Returns an error if the edges node contains a value of an unexpected shape (not nil, not a map with @id, not a slice of such maps), since silently overwriting would destroy data that the caller cannot see.

func AsSubscriberGroup

func AsSubscriberGroup(constructor any) any

AsSubscriberGroup tags a SubscriberGroup constructor so its result joins the "subscriber_groups" value group the Manager collects. Use it to register a peripheral handler group:

fx.Provide(application.AsSubscriberGroup(provideOxigraphGroup))

func AsSubscriberGroups

func AsSubscriberGroups(constructor any) any

AsSubscriberGroups tags a constructor returning []SubscriberGroup so its elements are flattened into the "subscriber_groups" value group. Use it for providers that contribute zero or more groups depending on configuration (e.g. an Oxigraph group only when the store is active).

func BuildResourceGraph

func BuildResourceGraph(
	data json.RawMessage,
	refProps []ReferencePropertyDef,
	resourceID, typeName string,
	ldContext json.RawMessage,
) (json.RawMessage, error)

BuildResourceGraph takes flat input data and separates it into a JSON-LD @graph with an entity node (intrinsic properties) and an edges node (resource references). Reference properties are identified by x-resource-type markers in the schema. The edges node uses JSON-LD {"@id": "..."} format for object references.

func DecorateNotifyingEventStore

func DecorateNotifyingEventStore(
	primary domain.EventStore,
	notifier *subscriptions.InProcessNotifier,
	cfg config.Config,
) domain.EventStore

DecorateNotifyingEventStore wraps the event store so each successful Append wakes background subscribers immediately, on SQLite / single-process deployments. On Postgres the store NOTIFYs on commit itself, so the store is returned unwrapped and PostgresListener handles cross-process wake-ups.

func EdgeValue

func EdgeValue(graphData, ldContext json.RawMessage, propertyName string) string

EdgeValue reads a specific reference property value from a JSON-LD @graph's edges node. The propertyName is the original schema property name (e.g., "courseId"). It resolves the property to its predicate IRI using the document's @context, then looks up that predicate in the edges node and unwraps the {"@id": "..."} value. Falls back to reading from flat data for legacy format.

For multi-valued reference properties (where the edge is stored as an array of refs), this returns the first @id. Use EdgeValues to read every entry.

func EdgeValues

func EdgeValues(graphData, ldContext json.RawMessage, propertyName string) []string

EdgeValues reads every reference value for the given property from a JSON-LD @graph's edges node. Returns a single-element slice for the scalar-edge case and one entry per ref for the array-edge case (which BuildResourceGraph emits when the schema declares x-resource-type on an array property).

Falls back to reading the property directly for legacy flat data. Returns an empty slice when the property is absent.

func ExtractAndStripReferences

func ExtractAndStripReferences(
	data json.RawMessage,
	refProps []ReferencePropertyDef,
) (json.RawMessage, []repositories.Triple, error)

ExtractAndStripReferences extracts reference property values from data as triples and removes the reference keys from the data. Returns the stripped data and the extracted triples (with subject left empty — caller sets it).

Prefer ExtractReferenceTriples when the caller doesn't need the stripped data — it avoids the unmarshal/marshal round-trip that this function performs solely to produce the stripped output.

func ExtractEdgesNode

func ExtractEdgesNode(graphData json.RawMessage) json.RawMessage

ExtractEdgesNode extracts the edges node (relationship references) from a JSON-LD @graph. Returns nil if no edges node exists or if the data is in legacy flat format.

func ExtractEntityNode

func ExtractEntityNode(graphData json.RawMessage) json.RawMessage

ExtractEntityNode extracts the intrinsic entity node from a JSON-LD @graph document. Falls back to returning the input as-is if it has no @graph key (legacy flat format).

func ExtractEventReferences

func ExtractEventReferences(event domain.EventEnvelope[any]) []string

ExtractEventReferences returns the resource URNs an event references, in deterministic (sorted) order: the aggregate itself plus every resource URN in the payload. Extraction is purely structural:

  • Resource.* events: every URN-shaped string anywhere under the payload's Data document (flat properties, @graph edge nodes, arrays alike);
  • Triple.* events: the subject and object terms;
  • anything else: just the aggregate.

A "resource URN" follows the isGatedResourceURN precedent — plain resources (urn:<slug>:<ksuid>) plus person and organization URNs. Event URNs (urn:event:...) are excluded so provenance fields like wasDerivedFrom do not read as resource references; type/theme/site URNs are configuration, not data, and never match.

func ExtractReferenceTriples

func ExtractReferenceTriples(
	data json.RawMessage,
	refProps []ReferencePropertyDef,
) ([]repositories.Triple, error)

ExtractReferenceTriples decodes data and pulls out reference property values as triples without modifying or re-marshaling the data. Use this in callers that already pass the original data (refs intact) into BuildResourceGraph and only need the triples for event sourcing — the stripped output that ExtractAndStripReferences produces would just be discarded.

Returned triples have empty Subject; the caller sets it.

func ExtractResourceFields

func ExtractResourceFields(r *entities.Resource) (map[string]any, error)

ExtractResourceFields parses intrinsic properties from a Resource's JSON-LD data.

func ExtractTriplesFromData

func ExtractTriplesFromData(
	refProps []ReferencePropertyDef,
	data json.RawMessage,
	subjectID string,
) []repositories.Triple

ExtractTriplesFromData produces concrete triples from resource data using reference property definitions. Supports both @graph format and legacy flat format. Each non-empty reference property value becomes a triple.

func FlattenGraph

func FlattenGraph(graphData, ldContext json.RawMessage) json.RawMessage

FlattenGraph converts a @graph document back to flat JSON by merging the entity node and edges node into a single object. Edge values are converted from {"@id": "..."} to their original property names using the resource type's ldContext for reverse-mapping. Falls back to returning data as-is if not in @graph format.

func Module

func Module(cfg config.Config, registry *PresetRegistry) fx.Option

Module provides all application dependencies. It accepts a Config parameter that must be provided by the calling application.

func NewAccountFlagFromContext

func NewAccountFlagFromContext(ctx context.Context) *bool

NewAccountFlagFromContext returns the flag pointer installed by WithNewAccountFlag, or nil if the caller didn't ask for the signal. The OAuth callback wrapper reads it after the login completes to decide whether to add the new-account marker to its redirect.

func ParseSkillDefinition

func ParseSkillDefinition(id string, data json.RawMessage) (entities.SkillDefinition, error)

ParseSkillDefinition parses an agent-skill resource's JSON-LD data into a definition, applying v1 defaults (schemaVersion 1, task mode). Validation is separate so callers control the known-tools check.

func ProvideAuthenticationService

func ProvideAuthenticationService(params struct {
	fx.In
	Registry            authapp.OAuthProviderRegistry
	Agents              authrepos.AgentRepository
	Credentials         authrepos.CredentialRepository
	Sessions            authrepos.AuthSessionRepository
	Accounts            authrepos.AccountRepository
	PasswordCredentials authrepos.PasswordCredentialRepository
	AuthzChecker        *authcasbin.CasbinAuthorizationChecker
	EventStore          esdomain.EventStore       `optional:"true"`
	EventDispatcher     *esdomain.EventDispatcher `optional:"true"`
	JWTService          authapp.JWTService        `optional:"true"`
}) authapp.AuthenticationService

func ProvideAuthorizationChecker

func ProvideAuthorizationChecker(db *gorm.DB) (*authcasbin.CasbinAuthorizationChecker, error)

func ProvideCheckpointStore

func ProvideCheckpointStore(db *gorm.DB) (subscriptions.CheckpointStore, error)

ProvideCheckpointStore supplies the GORM checkpoint store, auto-migrating the subscriber_checkpoints table.

func ProvideFactExtractor

func ProvideFactExtractor(adk *infraagents.ADKConfig, logger entities.Logger) entities.FactExtractor

ProvideFactExtractor supplies the BYOK LLM port for consolidation: the ADK/Gemini implementation when an API key is configured, nil otherwise (the consolidation subscriber is then not registered — a graceful no-op).

func ProvideInProcessNotifier

func ProvideInProcessNotifier() *subscriptions.InProcessNotifier

ProvideInProcessNotifier supplies the singleton in-process commit notifier. On SQLite it is wired to the event store (see DecorateNotifyingEventStore) so background subscribers wake on commit; on Postgres it is unused (the database NOTIFYs on commit itself) but harmless to provide.

func ProvideOAuthProviderRegistry

func ProvideOAuthProviderRegistry(params struct {
	fx.In
	Config config.Config
}) authapp.OAuthProviderRegistry

func ProvideParkingLot

func ProvideParkingLot(db *gorm.DB) (subscriptions.ParkingLot, error)

ProvideParkingLot supplies the GORM parking lot, auto-migrating the parked_events table. Poison events that exhaust their retries land here so the events behind them keep flowing; operators list and replay them via the worker CLI.

func ProvideSessionManager

func ProvideSessionManager(params struct {
	fx.In
	Config config.Config
	Store  sessions.Store
}) session.SessionManager

func RecordAgentTurn

func RecordAgentTurn(resources ResourceCreator) appagents.EpisodeRecorder

RecordAgentTurn returns an EpisodeRecorder that persists each completed in-app agent turn as a note resource. The note flows through the normal UnitOfWork → events → projection pipeline, so it is episodic memory: consolidation can distill durable facts from what users discuss with their app, exactly as it does for hand-written notes.

func RegisterLink(def PresetLinkDefinition) error

RegisterLink appends a link definition to the process-wide default registry. Intended for package init() of integration packages that don't carry a full PresetDefinition but still want to declare a cross-preset link — e.g. a lightweight "finance-education" integration package that connects Invoice to Guardian without either preset depending on the other.

Links declared inside a PresetDefinition.Links slice are collected through preset registration separately; the runtime *LinkRegistry seen by the application is assembled later by the DI wiring from both PresetRegistry and DefaultLinkRegistry().

func RemoveEdgeFromGraph

func RemoveEdgeFromGraph(
	data json.RawMessage, predicate, objectID string,
) (json.RawMessage, error)

RemoveEdgeFromGraph removes a specific relationship edge from a JSON-LD @graph document. For multi-valued predicates (arrays), only the matching objectID is removed. If the edges node becomes empty (only @id remains), it is removed from the @graph array.

func ReservedResourceTypeSlugs

func ReservedResourceTypeSlugs() map[string]bool

ReservedResourceTypeSlugs returns the set of slugs that cannot be used as resource type identifiers because they conflict with API route prefixes or are reserved for dedicated domain entities (auth).

func SeedAdminPolicies

func SeedAdminPolicies(checker *authcasbin.CasbinAuthorizationChecker) error

SeedAdminPolicies ensures admin and owner roles have wildcard access. Idempotent — safe to call on every startup.

func StringField

func StringField(m map[string]any, key string) string

StringField extracts a string value from a map, returning "" if missing.

func SubscribeResourceHandlers

func SubscribeResourceHandlers(
	d *domain.EventDispatcher,
	eventStore domain.EventStore,
	repo repositories.ResourceRepository,
	logger entities.Logger,
) error

SubscribeResourceHandlers exports the subscription for tests.

func SubscribeResourceTypeHandlers

func SubscribeResourceTypeHandlers(
	d *domain.EventDispatcher,
	repo repositories.ResourceTypeRepository,
	projMgr repositories.ProjectionManager,
	logger entities.Logger,
) error

SubscribeResourceTypeHandlers exports the subscription for tests.

func SubscribeTripleHandlers

func SubscribeTripleHandlers(
	d *domain.EventDispatcher,
	tripleRepo repositories.TripleRepository,
	logger entities.Logger,
) error

SubscribeTripleHandlers exports the subscription for tests.

func SyncAccessMapToCasbin

func SyncAccessMapToCasbin(
	checker *authcasbin.CasbinAuthorizationChecker,
	newMap, oldMap entities.AccessMap,
) error

SyncAccessMapToCasbin clears stale role policies and re-adds from the new access map. oldAccessMap may be nil (on startup). It preserves admin and owner wildcard policies.

func WireResourceWriter

func WireResourceWriter(writer *lazyResourceWriter, svc ResourceService) error

WireResourceWriter installs the real ResourceService into the lazy writer proxy after both have been constructed by Fx.

Fx guarantees that lazyResourceWriter and ResourceService are available before this invoke runs (parameter-level dependency ordering), but it does NOT impose ordering relative to other fx.Invoke calls that also depend on ResourceService. Any startup invoke that may call ResourceService.Create, Update, or Delete — and thus trigger behavior hooks that use BehaviorServices.Writer — MUST be registered after WireResourceWriter in application/module.go. Today the only such invoke is ensureBuiltInResourceTypes, and the module registers WireResourceWriter first; adding a new hook-triggering invoke earlier would silently regress this contract.

Returns an error on nil svc, self-target, or double-set so Fx aborts startup loudly instead of silently installing a broken proxy.

func WithNewAccountFlag

func WithNewAccountFlag(ctx context.Context, flag *bool) context.Context

WithNewAccountFlag returns a context carrying flag, which a wrapped AuthenticationService will set to true when FindOrCreateAgent creates a brand new account (rather than matching an existing one). The OAuth callback uses this to append ?new_account=1 to its post-login redirect so the frontend can route first-time users into onboarding.

func WorkerModule

func WorkerModule() fx.Option

WorkerModule provides the background subscriber runtime: the checkpoint and parking stores, the in-process wake notifier, the Manager, and the lifecycle hook that runs/drains the workers (gated by WorkerConfig.RunInProcess).

It is part of the application Module so every entry point (serve, CLI, tests) can construct the Manager — but only processes that set RunInProcess actually start background processing.

Types

type BehaviorFactory

type BehaviorFactory func(services BehaviorServices) entities.ResourceBehavior

BehaviorFactory constructs a ResourceBehavior given the available application services. Factories are invoked once at startup, after the Fx container is wired, allowing behaviors to close over real repositories and loggers. A factory must not return nil — that is treated as a programmer error and fails startup.

func StaticBehavior

func StaticBehavior(b entities.ResourceBehavior) BehaviorFactory

StaticBehavior wraps a pre-constructed ResourceBehavior in a BehaviorFactory. Use this for behaviors that have no service dependencies, so presets can declare them inline without writing a factory function. Panics if b is nil.

type BehaviorInfo

type BehaviorInfo struct {
	Slug        string `json:"slug"`
	DisplayName string `json:"displayName"`
	Description string `json:"description"`
	Enabled     bool   `json:"enabled"`
	Manageable  bool   `json:"manageable"`
}

BehaviorInfo describes a behavior's state for a resource type within the caller's account context.

type BehaviorMetaRegistry

type BehaviorMetaRegistry map[string]entities.BehaviorMeta

BehaviorMetaRegistry maps resource type slugs to their behavior metadata. Used by services to expose available behaviors and enforce manageability.

func ProvideBehaviorMetaRegistry

func ProvideBehaviorMetaRegistry(registry *PresetRegistry) BehaviorMetaRegistry

ProvideBehaviorMetaRegistry builds the metadata registry from all presets.

type BehaviorServices

type BehaviorServices struct {
	Resources     repositories.ResourceRepository
	Triples       repositories.TripleRepository
	ResourceTypes repositories.ResourceTypeRepository
	Logger        entities.Logger
	// Writer lets behaviors create, update, or delete other resources through
	// the full ResourceService pipeline. See lazyResourceWriter for the
	// cycle-breaking rationale behind how this is wired.
	Writer ResourceWriter
}

BehaviorServices bundles application services that ResourceBehavior factories may depend on. All fields are required when constructed by ProvideResourceBehaviorRegistry; tests that build BehaviorServices directly must supply real or fake implementations for any field their behavior touches.

type ClassDescription

type ClassDescription struct {
	ClassIRI   string                `json:"class_iri"`
	Predicates []string              `json:"predicates"`
	Instances  []repositories.KGTerm `json:"instances,omitempty"`
}

ClassDescription captures the metadata returned by DescribeClass.

type ConsolidationGroupParams

type ConsolidationGroupParams struct {
	fx.In
	EventStore domain.EventStore
	Extractor  entities.FactExtractor `optional:"true"`
	Service    ResourceService
	TypeRepo   repositories.ResourceTypeRepository
	Registry   *PresetRegistry
	Logger     entities.Logger
}

ConsolidationGroupParams bundles the consolidation group's dependencies.

type ConversationalAgent

type ConversationalAgent interface {
	// Configured reports whether an LLM is configured; when false, the other
	// methods return a clear not-configured error and the UI should say so.
	Configured() bool
	// Converse runs one turn synchronously and returns the response as the
	// versioned widget contract (pkg/widgets).
	Converse(ctx context.Context, conversationID, userID, message string) (widgets.Response, error)
	// ConverseStream runs one turn, emitting text deltas, any pending tool
	// confirmation (input_requested), then widgets and done. A non-empty
	// skill converses with that one skill directly — built as the turn's
	// root agent, bypassing coordinator routing — so a client's flow stays
	// deterministic; empty keeps the coordinator.
	ConverseStream(ctx context.Context, conversationID, userID, message, skill string, emit appagents.EventSink) error
	// ResumeConfirmation answers a pending mutating-tool confirmation and
	// streams the rest of the turn. Pending confirmations live in the
	// durable session, so they survive refreshes and restarts. A non-nil
	// payload on an approval replaces the tool call's arguments wholesale
	// (approve-with-edits): what executes is exactly what the user
	// submitted. A nil payload runs the original arguments; a payload on a
	// rejection is ignored. skill must repeat the value the paused turn ran
	// with (the resume rebuilds the same root agent).
	ResumeConfirmation(
		ctx context.Context, conversationID, userID, callID string, confirmed bool,
		payload map[string]any, skill string, emit appagents.EventSink,
	) error
	// History returns the conversation so far, oldest first.
	History(ctx context.Context, conversationID, userID string) ([]entities.AgentMessage, error)
}

ConversationalAgent is the provider-agnostic surface of the in-app agent. API handlers and CLI commands consume this interface; the ADK-backed implementation lives in application/agents and never leaks provider types through it.

For every method taking a ctx: it must carry the caller's identity (tool authorization reads it) and must be request-scoped (e.g. the HTTP request context) — tool sessions live exactly as long as ctx.

type CreateResourceCommand

type CreateResourceCommand struct {
	TypeSlug string
	Data     json.RawMessage
}

type CreateResourceTypeCommand

type CreateResourceTypeCommand struct {
	Name        string
	Slug        string
	Description string
	Context     json.RawMessage
	Schema      json.RawMessage
}

type DeleteResourceCommand

type DeleteResourceCommand struct {
	ID string
}

type DeleteResourceTypeCommand

type DeleteResourceTypeCommand struct {
	ID string
}

type DisplayValuesGroupParams

type DisplayValuesGroupParams struct {
	fx.In
	EventStore domain.EventStore
	ProjMgr    repositories.ProjectionManager
	Logger     entities.Logger
}

DisplayValuesGroupParams bundles the display-value propagation group's dependencies.

type EnsureCheckpointFunc

type EnsureCheckpointFunc func(ctx context.Context, subscriber string, position int64) error

EnsureCheckpointFunc creates the named subscriber's checkpoint row at the given position only when no row exists yet; an existing row — including one an operator explicitly reset to 0 — is never moved. It backs SubscriberGroup.StartAtHead. The pericarp CheckpointStore interface cannot express this (Position returns 0 both for "unknown" and "reset to 0"), so the gorm layer provides it against the checkpoint table directly.

func ProvideEnsureCheckpoint

func ProvideEnsureCheckpoint(db *gorm.DB) EnsureCheckpointFunc

ProvideEnsureCheckpoint supplies the create-if-missing checkpoint primitive behind SubscriberGroup.StartAtHead. It writes the same subscriber_checkpoints table the GORM checkpoint store owns (pericarp exports the model), with an insert that does nothing when the row exists — so it can never move a checkpoint, only seed a brand-new one.

type EpisodicQuery

type EpisodicQuery struct {
	From         string
	Until        string
	Anchors      []string
	EventType    string
	ResourceType string
	// Limit caps results (default 20, max 100 — over-asks are capped, not errors).
	Limit  int
	Cursor string
}

EpisodicQuery is a structured recall request over the event log. From and Until accept RFC3339 timestamps or the relative forms "last N days" / "N days ago"; empty bounds leave that side of the window open. Anchors are resource URNs; an event matches when any anchor is its aggregate or is referenced in its payload.

type EpisodicRecall

type EpisodicRecall interface {
	Recall(ctx context.Context, q EpisodicQuery) (*EpisodicRecallResult, error)
	// Similar ranks events by deterministic structural similarity to the
	// seed event (see the weight constants in episodic_similar.go).
	Similar(ctx context.Context, q SimilarQuery) (*SimilarResult, error)
	// EventByURN returns one event's full stored payload — the explicit
	// drill-in complement to the compact shapes above.
	EventByURN(ctx context.Context, urn string) (*FetchedEvent, error)
}

EpisodicRecall answers scoped, deterministic queries over the event store's episodic record: time-windowed, filterable, time-ordered, paginated recall, plus structural similar-event search from a seed event. Tools retrieve; agents interpret — no learned ranking, no LLM calls.

func NewEpisodicRecall

NewEpisodicRecall builds the episodic recall service over the event-log read surface and the event-reference projection.

type EpisodicRecallResult

type EpisodicRecallResult struct {
	Events  []RecalledEvent
	Cursor  string
	HasMore bool
}

EpisodicRecallResult is one page of recalled events.

type EventReferenceGroupParams

type EventReferenceGroupParams struct {
	fx.In
	References repositories.EventReferenceRepository
	Logger     entities.Logger
}

EventReferenceGroupParams bundles the reference projection's dependencies.

type FetchedEvent

type FetchedEvent struct {
	RecalledEvent
	Payload map[string]any `json:"payload"`
}

FetchedEvent is one event with its full stored payload — the explicit drill-in complement to the compact recall shape (epic #409, story #414). Payload is returned exactly as stored; recall stays token-frugal by default and this fetch is the only episodic surface that returns it.

type FileService

type FileService = services.FileService

FileService is the application-layer alias for the domain FileService interface.

type GrantPermissionCommand

type GrantPermissionCommand struct {
	ResourceID string          `json:"resource_id"`
	AgentID    string          `json:"agent_id"`
	Actions    json.RawMessage `json:"actions"` // JSON array: ["read","modify","delete"]
}

type InstallPresetResult

type InstallPresetResult struct {
	Created   []string       `json:"created"`
	Updated   []string       `json:"updated,omitempty"`
	Unchanged []string       `json:"unchanged,omitempty"`
	Skipped   []string       `json:"skipped"`
	Seeded    map[string]int `json:"seeded,omitempty"` // slug -> count of fixtures created
	Warnings  []string       `json:"warnings,omitempty"`
}

InstallPresetResult reports which types were created, updated, unchanged, or skipped. Unchanged differs from Skipped: Unchanged means update=true and the preset matches what's stored (no event emitted), while Skipped means update=false and the caller asked to leave existing types alone.

type KnowledgeGraphService

type KnowledgeGraphService interface {
	// Active reports whether the underlying store is connected. MCP tools
	// short-circuit when inactive so the LLM gets a clear "not configured"
	// signal instead of empty results.
	Active() bool

	// Query runs an arbitrary SPARQL query (SELECT/ASK/CONSTRUCT/DESCRIBE).
	// Use for the LLM-facing kg_sparql_query tool when something complex is
	// needed; the other methods cover most reasoning patterns more cheaply.
	Query(ctx context.Context, sparql string) (repositories.KGQueryResult, error)

	// ExpandEntity returns the one-hop neighborhood of an IRI as a list of
	// triples. depth defaults to 1; depths >1 walk reference chains via
	// SPARQL property paths.
	ExpandEntity(ctx context.Context, iri string, depth int) ([]repositories.Triple, error)

	// SearchEntities returns IRIs whose label-like properties (rdfs:label,
	// schema:name, foaf:name, dcterms:title) match q (case-insensitive
	// substring). When classIRI is non-empty, results are restricted to
	// instances of that class (subclasses included via rdfs:subClassOf*).
	// limit defaults to 20, capped at 100.
	SearchEntities(ctx context.Context, q, classIRI string, limit int) ([]repositories.KGTerm, error)

	// DescribeClass returns the predicates and (optionally) example instances
	// of a class IRI. Useful for LLM introspection — "what does foaf:Person
	// look like in this graph?".
	DescribeClass(ctx context.Context, classIRI string, sampleInstances int) (ClassDescription, error)

	// FindPath returns a best-effort path of triples connecting two IRIs
	// within maxHops. Returns nil triples when no path is found within the
	// hop budget; nil error in that case (path-not-found is not an error).
	FindPath(ctx context.Context, from, to string, maxHops int) ([]repositories.Triple, error)

	// ListClasses returns the IRIs of every class declared in the graph
	// (anything typed `rdfs:Class` or `owl:Class`). Useful for LLM
	// introspection — "what kinds of things does this user's graph
	// contain?".
	ListClasses(ctx context.Context) ([]repositories.KGTerm, error)
}

KnowledgeGraphService is the application-layer entry point for the `knowledge-graph` MCP tool group. It composes SPARQL on top of the storage-agnostic KnowledgeGraphStore so MCP tool handlers stay declarative — they describe intent ("expand this entity"), the service translates that to a SPARQL query the store can answer.

func ProvideKnowledgeGraphService

func ProvideKnowledgeGraphService(params struct {
	fx.In
	Store    repositories.KnowledgeGraphStore
	Resource ResourceService
	Logger   entities.Logger
}) KnowledgeGraphService

ProvideKnowledgeGraphService wires the service. When the store is inactive the service still works (returns errors) so MCP tool handlers can report a clear "knowledge graph not configured" message instead of being absent.

The ResourceService dependency is for the permission filter: every result returned to an MCP tool handler is passed through FilterAccessibleResourceIDs so the LLM never sees a resource the calling agent can't read. System context (nil identity) bypasses the filter — that matches the existing services' behavior for stdio/CLI/system callers.

type KnownToolsFunc

type KnownToolsFunc func(ctx context.Context) (map[string]bool, error)

KnownToolsFunc returns the names of the tools currently registered on the instance's tool surface. The registry uses it to fail skills whose allowlist references a tool that does not exist. It is injected late (the tool surface is assembled downstream of this package); until set, the unknown-tool check is skipped.

type LexicalGroupParams

type LexicalGroupParams struct {
	fx.In
	EventStore domain.EventStore
	Index      repositories.LexicalIndex
	Logger     entities.Logger
}

LexicalGroupParams bundles the lexical index subscriber's dependencies.

type LexicalSearch

type LexicalSearch interface {
	// Search returns matches plus the mode that produced them
	// (LexicalModeFTS5 or LexicalModeGraphLabels).
	Search(ctx context.Context, query string, limit int) ([]repositories.LexicalHit, string, error)
}

LexicalSearch finds resources by keyword. FTS5-first; on installations without FTS5 (PostgreSQL — the pure-Go SQLite driver always has it) it degrades to the knowledge graph's label search.

func NewLexicalSearch

NewLexicalSearch builds the lexical search service. kg may be nil.

type LinkActivator

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

LinkActivator walks the LinkRegistry and activates any link whose source and target resource types are both installed. Activation means asking the ProjectionManager to add the FK + display columns and record forward/reverse reference entries — the same effects schema-declared x-resource-type properties produce.

Reconcile is idempotent and safe to call repeatedly. It's the single entry point used from both startup (builtin_resource_types.go after AutoInstall) and InstallPreset, so any path that adds a resource type re-evaluates every previously-dormant link.

func NewLinkActivator

func NewLinkActivator(
	registry *LinkRegistry,
	projMgr repositories.ProjectionManager,
	typeRepo repositories.ResourceTypeRepository,
	logger entities.Logger,
) (*LinkActivator, error)

NewLinkActivator constructs a LinkActivator, validating that every dependency is present. Moving the nil-check to construction time keeps Reconcile's hot path honest: a running activator is guaranteed to have a working registry, projection manager, repo, and logger. Returns an error (rather than panicking) so Fx surfaces wiring mistakes cleanly.

func ProvideLinkActivator

func ProvideLinkActivator(params struct {
	fx.In
	Registry *LinkRegistry
	ProjMgr  repositories.ProjectionManager
	TypeRepo repositories.ResourceTypeRepository
	Logger   entities.Logger
}) (*LinkActivator, error)

ProvideLinkActivator constructs the activator used to reconcile link definitions after resource types are installed. It depends on the ProjectionManager and the ResourceTypeRepository because activation needs to know which types are installed (repo) and where to add FK columns (projection manager). Returns an error (surfaced by Fx) if any dependency is missing — preferable to a runtime panic in Reconcile.

func (*LinkActivator) Reconcile

func (a *LinkActivator) Reconcile(ctx context.Context) error

Reconcile loads the set of installed resource-type slugs and activates every link in the registry whose endpoints are both present. Links whose source type lacks a projection table are skipped silently by ProjectionManager.RegisterLink; they'll activate on a subsequent call after the source is installed.

Individual RegisterLink failures are logged and collected but don't stop the pass — one bad link shouldn't block siblings. The returned error is the errors.Join of every per-link failure, each wrapped with the (source, target, property) triple so API/CLI callers reading InstallPresetResult.Warnings can identify which link(s) failed without needing log access. A Go 1.20+ errors.Is walk still finds the underlying cause for each branch.

type LinkRegistry

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

LinkRegistry holds cross-type link definitions contributed by presets and by packages that call application.RegisterLink at startup. Definitions are declarative code: "pending vs active" is a runtime view computed by ActiveFor given the set of installed type slugs, not a stored state.

func DefaultLinkRegistry

func DefaultLinkRegistry() *LinkRegistry

DefaultLinkRegistry returns the process-wide registry seeded by package-init RegisterLink calls. Exported for the DI layer to use as the seed for the Fx-provided *LinkRegistry.

func NewLinkRegistry

func NewLinkRegistry() *LinkRegistry

NewLinkRegistry creates an empty registry.

func (*LinkRegistry) ActiveFor

func (r *LinkRegistry) ActiveFor(installed map[string]bool) []PresetLinkDefinition

ActiveFor returns the subset of links whose SourceType and TargetType both appear as keys in installed. The caller supplies the installed set rather than having the registry query a repository, so the registry stays dependency-free and trivially testable.

func (*LinkRegistry) Add

Add registers a link definition. If another definition already maps to the same source type and derived FK column — i.e. the same (SourceType, CamelToSnake(PropertyName)) pair — the new definition replaces the old one (last-writer-wins), so a package-init RegisterLink that overrides a preset-declared link takes effect without the caller needing to unregister first. Keying on the snake_case form (not the raw PropertyName) catches ambiguous camelCase spellings like "guardianId" vs "guardianID" that both project to the same "guardian_id" column.

func (*LinkRegistry) All

All returns a copy of every registered link definition, sorted by (SourceType, PropertyName) for deterministic iteration.

func (*LinkRegistry) BySource

func (r *LinkRegistry) BySource(slug string) []PresetLinkDefinition

BySource returns every link whose SourceType matches slug. Used by the resource write path to merge link-derived reference properties with the schema-derived x-resource-type properties for triple extraction.

func (*LinkRegistry) ByTarget

func (r *LinkRegistry) ByTarget(slug string) []PresetLinkDefinition

ByTarget returns every link whose TargetType matches slug.

func (*LinkRegistry) LinkReferencesForSource

func (r *LinkRegistry) LinkReferencesForSource(sourceSlug string) []repositories.LinkReference

LinkReferencesForSource implements repositories.LinkSource so the projection manager can replay link-declared refs after a schema re-parse clears its forward/reverse maps. Returns an empty slice (not nil) for unknown slugs so callers can range over the result without a nil check.

func (*LinkRegistry) MustAdd

func (r *LinkRegistry) MustAdd(def PresetLinkDefinition)

MustAdd is the panicking form of Add for init-time registration of known-good link definitions.

type Manager

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

Manager owns the background subscriber runtime: it builds a pericarp Subscriber per registered group, runs them as crash-safe workers, drains them on shutdown, and periodically reports checkpoint lag. The same Manager also backs the operator CLI (list/replay parked events, reset checkpoints), which constructs subscribers on demand without running them.

func NewManager

func NewManager(p ManagerParams) (*Manager, error)

NewManager validates the group set and constructs the runtime. It does not start any processing; call Start (or use a single subscriber via the CLI accessors).

func ProvideWorkerManager

func ProvideWorkerManager(p workerManagerParams) (*Manager, error)

ProvideWorkerManager constructs the subscriber Manager from the registered groups. It does not start processing — runWorkerManager wires that into the Fx lifecycle.

func (*Manager) LogLag

func (m *Manager) LogLag(ctx context.Context)

LogLag emits one checkpoint-lag log line per subscriber. Exposed so the CLI can report lag on demand as well.

func (*Manager) Names

func (m *Manager) Names() []string

Names returns the registered subscriber group names, sorted for stable CLI output.

func (*Manager) ParkedEvents

func (m *Manager) ParkedEvents(ctx context.Context, subscriber string) ([]subscriptions.ParkedEvent, error)

ParkedEvents returns parked (poison) events for one subscriber, or across all registered subscribers when subscriber is empty. The result is flat; each ParkedEvent carries its own Subscriber. Backs `weos worker parked list`.

func (*Manager) ReplayParked

func (m *Manager) ReplayParked(ctx context.Context, subscriber, eventID string) error

ReplayParked re-runs the handler for one parked event of a subscriber and clears the row on success (a failed replay leaves it parked). Backs `weos worker parked replay`.

func (*Manager) ResetCheckpoint

func (m *Manager) ResetCheckpoint(ctx context.Context, subscriber string, truncate bool) error

ResetCheckpoint resets a subscriber's checkpoint to 0 so it replays all history — the one mechanism for rebuild, recovery, and backfill. When truncate is set, the group's projection is cleared first (so the replay repopulates from empty); a group with no Truncate action rejects --truncate. Replay is incremental and resumable: it uses the same batch/checkpoint cycle as live processing, so interrupting and restarting continues from where it left off. Backs `weos worker checkpoint reset`.

func (*Manager) Start

func (m *Manager) Start(_ context.Context) error

Start launches every registered subscriber as a background worker, plus the wake source (Postgres listener) and the lag reporter. It returns immediately; the workers run until Stop. Calling Start twice is a no-op.

func (*Manager) Stop

func (m *Manager) Stop(ctx context.Context) error

Stop cancels the workers and waits for them to drain, bounded by ctx. A batch already in flight finishes — handlers complete and the checkpoint advances — before its subscriber returns, so a clean shutdown never loses work and preserves feed order. Delivery is at-least-once in general (exactly-once only for handlers that write through the batch transaction via TxFromContext); an unclean kill can redeliver the in-flight batch on restart.

func (*Manager) Subscriber

func (m *Manager) Subscriber(name string) (*subscriptions.Subscriber, error)

Subscriber builds a fresh (non-running) Subscriber for the named group, for CLI operations like listing/replaying parked events and resetting checkpoints. The checkpoint and parking stores are shared, so these operations coordinate correctly with a running worker.

type ManagerParams

type ManagerParams struct {
	EventStore  domain.EventStore
	Checkpoints subscriptions.CheckpointStore
	Parking     subscriptions.ParkingLot
	Notifier    WakeSource
	Config      config.Config
	Logger      entities.Logger
	Groups      []SubscriberGroup
	// RebuildOnStart names groups whose checkpoint is reset (and projection
	// truncated) before the workers launch — the OXIGRAPH_REBUILD path, now
	// expressed as a checkpoint reset so there is one replay mechanism.
	RebuildOnStart []string
	// EnsureCheckpoint backs SubscriberGroup.StartAtHead. nil is only valid
	// when no group sets StartAtHead — such a group would then never start.
	EnsureCheckpoint EnsureCheckpointFunc
}

ManagerParams bundles the Manager's dependencies. groups arrives via the "subscriber_groups" Fx value group, so any provider can contribute one.

type MemoryRecall

type MemoryRecall interface {
	Recall(ctx context.Context, q RecallQuery) ([]RecalledFact, error)
}

MemoryRecall answers structured recall queries against semantic memory, composing the knowledge graph with the working set so just-written facts appear the same turn. Superseded facts never appear.

func NewMemoryRecall

func NewMemoryRecall(kg KnowledgeGraphService, working WorkingMemory) MemoryRecall

NewMemoryRecall builds the recall service. kg may be nil (Oxigraph not configured) — recall then serves from the working set alone rather than failing, and never blocks on any projection checkpoint.

type MountedHandler

type MountedHandler struct {
	Method    string
	Path      string
	Protected bool
	Handler   http.HandlerFunc
	Source    string
}

MountedHandler is a fully-resolved preset HTTP route, ready to mount on the HTTP router. Source names the preset that contributed it, surfaced in collision errors and startup logs.

type OxigraphGroupParams

type OxigraphGroupParams struct {
	fx.In
	EventStore domain.EventStore
	Store      repositories.KnowledgeGraphStore
	TypeRepo   repositories.ResourceTypeRepository
	Logger     entities.Logger
}

OxigraphGroupParams bundles the Oxigraph projector group's dependencies.

type PlaybookService

type PlaybookService interface {
	RecordOutcome(ctx context.Context, id string, outcome entities.PlaybookOutcome, note string) (
		*entities.Resource, error)
}

PlaybookService records agent verdicts on playbooks (procedural memory). Counters are never written directly: RecordOutcome increments them through an ordinary event-sourced resource update, and the playbook behavior records the Playbook.Confirmed / Playbook.Rejected signal in the same commit — so replay reconstructs both counter state and audit trail.

func NewPlaybookService

func NewPlaybookService(resources ResourceService) PlaybookService

NewPlaybookService wraps the resource service with playbook outcome recording.

type PresetDefinition

type PresetDefinition struct {
	Name         string
	Description  string
	Types        []PresetResourceType
	Behaviors    map[string]BehaviorFactory       // slug -> factory invoked at startup with services
	BehaviorMeta map[string]entities.BehaviorMeta // slug -> metadata for UI/config
	Screens      fs.FS                            // optional embedded screen components
	Sidebar      *PresetSidebarConfig             // optional sidebar defaults
	Handlers     []PresetHTTPHandler              // optional HTTP routes mounted under /api
	// Links declares cross-type relationships that live outside any resource
	// type's schema. Each link activates when both SourceType and TargetType
	// are installed — enabling a "finance-education" integration preset to
	// link Invoice and Guardian without either preset depending on the other.
	// See PresetLinkDefinition for semantics.
	Links       []PresetLinkDefinition
	AutoInstall bool // if true, types are auto-created at startup
	// Consolidates lists resource type slugs whose resources carry
	// unstructured episodic content (notes, transcripts, captured web pages,
	// free-text observations) that memory consolidation should distill facts
	// from. Structured domain types are already semantic memory — their typed
	// data and graph projection state the knowledge directly — so running LLM
	// fact-extraction over them would only duplicate it at BYOK cost; leave
	// them undeclared. Nothing is eligible by default, and a preset may
	// declare slugs a companion preset defines. Memory types themselves
	// (fact, playbook) are never eligible regardless of declarations.
	Consolidates []string
}

PresetDefinition defines a named preset package that bundles resource types, behaviors, screen components, sidebar configuration, and HTTP routes.

func (PresetDefinition) ScreenManifest

func (d PresetDefinition) ScreenManifest() map[string][]string

ScreenManifest walks the Screens FS and returns a map of typeSlug to screen filenames. Returns nil if Screens is nil or contains no .mjs files. Only files at exactly one level of nesting (<typeSlug>/<ScreenName>.mjs) are included; deeper paths are ignored.

type PresetHTTPHandler

type PresetHTTPHandler struct {
	Method    string // GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD
	Path      string // relative to /api, e.g. "/leads/upload"
	Factory   func(BehaviorServices) http.HandlerFunc
	Protected bool // true => mount behind auth middleware
}

PresetHTTPHandler describes one HTTP route contributed by a preset. The Factory is invoked once at server start with the same BehaviorServices that behavior factories receive, so handlers can close over real repositories without depending on Fx directly.

Path is relative to /api: a preset declaring Path "/leads/upload" mounts at /api/leads/upload. Protected selects the auth-gated group; public handlers land on the bare /api group and run without auth middleware.

type PresetHTTPHandlers

type PresetHTTPHandlers []MountedHandler

PresetHTTPHandlers is a distinct nominal type for the Fx-provided list of resolved preset routes — keeps it from being confused with any other []MountedHandler that might enter the graph later.

func ProvidePresetHTTPHandlers

func ProvidePresetHTTPHandlers(
	registry *PresetRegistry,
	resources repositories.ResourceRepository,
	triples repositories.TripleRepository,
	resourceTypes repositories.ResourceTypeRepository,
	logger entities.Logger,
	writer *lazyResourceWriter,
) (PresetHTTPHandlers, error)

ProvidePresetHTTPHandlers resolves preset-contributed HTTP routes against the same BehaviorServices that behavior factories receive, so handlers and behaviors share a single application-services view.

type PresetLinkDefinition

type PresetLinkDefinition struct {
	Name            string
	SourceType      string
	TargetType      string
	PropertyName    string
	PredicateIRI    string
	DisplayProperty string
}

PresetLinkDefinition declares a relationship between two resource types that lives outside either type's schema. Unlike x-resource-type properties baked into a schema, link definitions can be registered by a third package so neither the source nor target type needs to know about the other.

A link activates the first time both SourceType and TargetType exist as installed resource types; until then it remains dormant. Activation is idempotent.

Fields:

  • Name is a human-readable identifier ("invoice-guardian"). Used in logs and for disambiguation; not persisted.
  • SourceType and TargetType are resource type slugs.
  • PropertyName is the attribute name on the source resource that carries the reference (e.g. "guardian"). This drives the FK column name and the predicate IRI derivation.
  • PredicateIRI, if empty, is derived later from the source type's JSON-LD context and PropertyName using the same rule as schema-derived x-resource-type properties; activation itself does not resolve or validate it.
  • DisplayProperty defaults to "name" when empty; it names the property on the target whose value is denormalized into <prop>_display.

type PresetRegistry

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

PresetRegistry holds all registered presets. Preset packages call Add() to register.

func NewPresetRegistry

func NewPresetRegistry() *PresetRegistry

NewPresetRegistry creates an empty registry.

func (*PresetRegistry) Add

Add registers a preset. Returns an error if the definition is invalid. If a preset with the same name already exists, it is replaced.

func (*PresetRegistry) Behaviors

Behaviors returns a merged ResourceBehaviorRegistry from all registered presets, invoking each preset's BehaviorFactory exactly once with the supplied services. Presets are processed in alphabetical order; if multiple presets declare a behavior for the same slug, the last preset alphabetically wins and a warning is logged (when services.Logger is non-nil). Returns an error if any factory is nil or returns a nil ResourceBehavior — Add() rejects nil factories at registration time, so the nil-factory branch here is defense in depth.

func (*PresetRegistry) BehaviorsMeta

func (r *PresetRegistry) BehaviorsMeta() BehaviorMetaRegistry

BehaviorsMeta returns a merged BehaviorMetaRegistry from all registered presets. Same merge semantics as Behaviors(): alphabetical order, last wins.

func (*PresetRegistry) ConsolidationEligible

func (r *PresetRegistry) ConsolidationEligible() map[string]bool

ConsolidationEligible returns the union of resource type slugs the registered presets declare consolidation-eligible (PresetDefinition. Consolidates). Memory type slugs are stripped as a hard invariant — a preset that (incorrectly) declares fact or playbook never loops the consolidation subscriber onto its own output. An empty set means consolidation has nothing to process, which is the correct default.

func (*PresetRegistry) Get

func (r *PresetRegistry) Get(name string) (PresetDefinition, bool)

Get returns a preset by name. The returned value is a deep copy safe to mutate.

func (*PresetRegistry) Handlers

func (r *PresetRegistry) Handlers(services BehaviorServices) ([]MountedHandler, error)

Handlers returns all preset-contributed HTTP routes, with each Factory invoked once with the supplied services. Ordering is alphabetical by preset name, preserving each preset's declared handler order. Returns an error if any factory is nil or returns nil, or if two presets declare the same "METHOD /path" — startup fails so the conflict can't go unnoticed.

func (*PresetRegistry) List

func (r *PresetRegistry) List() []PresetDefinition

List returns all registered presets sorted by name. Returned values are deep copies.

func (*PresetRegistry) MustAdd

func (r *PresetRegistry) MustAdd(def PresetDefinition)

MustAdd registers a preset and panics if the definition is invalid. Use for init-time registration of known-good preset data.

type PresetResourceType

type PresetResourceType struct {
	Name        string
	Slug        string
	Description string
	Context     json.RawMessage
	Schema      json.RawMessage
	Fixtures    []json.RawMessage // optional seed data created on install
}

PresetResourceType defines a single resource type within a preset.

func NewPresetType

func NewPresetType(name, slug, desc, ctx, schema string) PresetResourceType

NewPresetType is a helper to create a PresetResourceType from raw strings.

type PresetSidebarConfig

type PresetSidebarConfig struct {
	HiddenSlugs []string          // resource type slugs hidden by default
	MenuGroups  map[string]string // slug -> parent slug for sidebar nesting
}

PresetSidebarConfig holds default sidebar settings applied when a preset is installed.

type RecallQuery

type RecallQuery struct {
	// About restricts results to facts about this entity URN.
	About string
	// Keyword is a case-insensitive substring match on the fact statement.
	Keyword string
	// Limit caps results (default 20, max 100).
	Limit int
	// IncludeProvenance adds the prov:wasDerivedFrom source event IDs.
	IncludeProvenance bool
}

RecallQuery is a structured memory-recall request. Free-form SPARQL stays on kg_sparql_query; recall builds the query itself with supersession filtering always applied.

type RecalledEvent

type RecalledEvent struct {
	// ID is the event URN (urn:event:<id>), consistent with the
	// prov:wasDerivedFrom identifiers in the memory preset.
	ID           string `json:"id"`
	EventType    string `json:"eventType"`
	Timestamp    string `json:"timestamp"`
	AggregateID  string `json:"aggregateId"`
	ResourceType string `json:"resourceType,omitempty"`
	Summary      string `json:"summary,omitempty"`
	// ReferencedResources lists the resource URNs the event references — the
	// aggregate itself plus resource URNs in the payload — from the
	// event-reference projection (story #411). Empty until the projection has
	// caught up with the event.
	ReferencedResources []string `json:"referencedResources,omitempty"`
}

RecalledEvent is the compact episodic result shape: enough to know what happened and fetch more, never the full raw payload.

type RecalledFact

type RecalledFact struct {
	ID              string  `json:"id"`
	Statement       string  `json:"statement"`
	About           string  `json:"about,omitempty"`
	Confidence      float64 `json:"confidence,omitempty"`
	AttributedTo    string  `json:"attributedTo,omitempty"`
	GeneratedAtTime string  `json:"generatedAtTime,omitempty"`
	WasRevisionOf   string  `json:"wasRevisionOf,omitempty"`
	// DerivedFrom holds the prov:wasDerivedFrom source event IDs.
	DerivedFrom []string `json:"wasDerivedFrom,omitempty"`
	// Source is "working" for facts read from the synchronous SQL projection
	// (may not be in the graph yet) or "graph" for knowledge-graph results.
	Source string `json:"source,omitempty"`
}

RecalledFact is the recall read-model for one fact, whichever store it came from: the knowledge graph or the working set.

func MergeRecalledFacts

func MergeRecalledFacts(working, graph []RecalledFact) []RecalledFact

MergeRecalledFacts combines working-set facts with graph recall results, deduplicating by URN. Working-set entries win on conflict — they reflect the synchronous projection, which is never behind the graph.

type ReferencePropertyDef

type ReferencePropertyDef struct {
	PropertyName    string // e.g. "invoiceId"
	PredicateIRI    string // e.g. "https://schema.org/object"
	TargetType      string // e.g. "invoice"
	DisplayProperty string // e.g. "name" — property on the target resource shown in lists
}

ReferencePropertyDef describes a JSON Schema property that references another resource.

func ExtractReferenceProperties

func ExtractReferenceProperties(
	schema json.RawMessage, ldContext json.RawMessage,
) []ReferencePropertyDef

ExtractReferenceProperties parses a JSON Schema and JSON-LD context to find properties that reference other resources (marked with x-resource-type). Schema-only form: use when no LinkRegistry is available (pure parsers, static analyzers). Call sites inside ResourceService go through ExtractReferencePropertiesWithLinks so cross-preset links participate.

func ExtractReferencePropertiesWithLinks(
	schema, ldContext json.RawMessage,
	externalLinks []PresetLinkDefinition,
) []ReferencePropertyDef

ExtractReferencePropertiesWithLinks combines schema-declared x-resource-type references with link-declared references from external PresetLinkDefinitions. Both contribute to the same []ReferencePropertyDef downstream, so the write path (BuildResourceGraph, ExtractReferenceTriples, projection FK/display population) treats them identically.

Merge rule: when both the schema and a link define a reference on the same PropertyName, the schema wins and the conflicting link is silently dropped. The function returns no signal for the drop — callers that need to surface conflicts should inspect the registry against the schema before calling. Callers with a *LinkRegistry typically pass registry.BySource(typeSlug) as externalLinks.

type ResourceBehaviorRegistry

type ResourceBehaviorRegistry map[string]entities.ResourceBehavior

ResourceBehaviorRegistry maps resource type slugs to their custom behaviors. Types without a registered behavior use DefaultBehavior (no-op).

func ProvideResourceBehaviorRegistry

func ProvideResourceBehaviorRegistry(
	registry *PresetRegistry,
	resources repositories.ResourceRepository,
	triples repositories.TripleRepository,
	resourceTypes repositories.ResourceTypeRepository,
	logger entities.Logger,
	writer *lazyResourceWriter,
) (ResourceBehaviorRegistry, error)

ProvideResourceBehaviorRegistry builds the behavior registry from all registered presets, invoking each factory with the supplied services. Fails startup if any injected dependency is nil or any factory returns nil. The writer parameter is an unwired *lazyResourceWriter — see that type for the cycle-breaking rationale.

type ResourceCreator

type ResourceCreator interface {
	Create(ctx context.Context, cmd CreateResourceCommand) (*entities.Resource, error)
}

ResourceCreator is the slice of ResourceService episode recording needs.

type ResourcePermissionService

type ResourcePermissionService interface {
	Grant(ctx context.Context, cmd GrantPermissionCommand) error
	Revoke(ctx context.Context, cmd RevokePermissionCommand) error
	ListForResource(ctx context.Context, resourceID string) ([]*entities.ResourcePermission, error)
}

func ProvideResourcePermissionService

func ProvideResourcePermissionService(params struct {
	fx.In
	PermRepo     repositories.ResourcePermissionRepository
	ResourceRepo repositories.ResourceRepository
	AccountRepo  authrepos.AccountRepository
	Logger       entities.Logger
}) ResourcePermissionService

type ResourceService

type ResourceService interface {
	// FilterAccessibleResourceIDs returns the subset of `ids` that the
	// caller is allowed to read. Used by the knowledge-graph permission
	// filter to drop forbidden subjects/objects from query results before
	// they leave the MCP server. Nil identity (system context) returns the
	// input unchanged. `urn:person:*` and `urn:org:*` ARE gated alongside
	// regular resources because they carry FOAF/vCard PII; `urn:type:*` /
	// `urn:theme:*`, full ontology IRIs, blank nodes, and literals pass
	// through unchanged.
	FilterAccessibleResourceIDs(ctx context.Context, ids []string) ([]string, error)
	Create(ctx context.Context, cmd CreateResourceCommand) (*entities.Resource, error)
	GetByID(ctx context.Context, id string) (*entities.Resource, error)
	// GetFlat returns a single resource as a flat projection row (camelCase keys),
	// including denormalized _display columns for x-resource-type references.
	// Used by detail views so the frontend can render reference names without a
	// client-side ID→name lookup cache. Returns an error for types with no
	// projection table; caller should fall back to GetByID.
	GetFlat(ctx context.Context, typeSlug, id string) (map[string]any, error)
	List(ctx context.Context, typeSlug, cursor string, limit int, sort repositories.SortOptions) (
		repositories.PaginatedResponse[*entities.Resource], error)
	ListFlat(ctx context.Context, typeSlug, cursor string, limit int, sort repositories.SortOptions) (
		repositories.PaginatedResponse[map[string]any], error)
	ListByField(ctx context.Context, typeSlug, fieldName, fieldValue string) (
		repositories.PaginatedResponse[*entities.Resource], error)
	ListWithFilters(ctx context.Context, typeSlug string, filters []repositories.FilterCondition,
		cursor string, limit int, sort repositories.SortOptions) (
		repositories.PaginatedResponse[*entities.Resource], error)
	ListFlatWithFilters(ctx context.Context, typeSlug string, filters []repositories.FilterCondition,
		cursor string, limit int, sort repositories.SortOptions) (
		repositories.PaginatedResponse[map[string]any], error)
	Update(ctx context.Context, cmd UpdateResourceCommand) (*entities.Resource, error)
	Delete(ctx context.Context, cmd DeleteResourceCommand) error
}

func NewResourceServiceForTest

NewResourceServiceForTest creates a ResourceService without fx wiring. Pass nil for behaviors to use DefaultBehavior for all types.

func NewResourceServiceForTestWithSettings

func NewResourceServiceForTestWithSettings(
	repo repositories.ResourceRepository,
	typeRepo repositories.ResourceTypeRepository,
	tripleRepo repositories.TripleRepository,
	eventStore domain.EventStore,
	dispatcher *domain.EventDispatcher,
	logger entities.Logger,
	behaviors ResourceBehaviorRegistry,
	behaviorMeta BehaviorMetaRegistry,
	behaviorSettings repositories.BehaviorSettingsRepository,
) ResourceService

NewResourceServiceForTestWithSettings creates a ResourceService with behavior settings support for tests that need account-scoped behavior config.

type ResourceTypeService

type ResourceTypeService interface {
	Create(ctx context.Context, cmd CreateResourceTypeCommand) (*entities.ResourceType, error)
	GetByID(ctx context.Context, id string) (*entities.ResourceType, error)
	GetBySlug(ctx context.Context, slug string) (*entities.ResourceType, error)
	List(ctx context.Context, cursor string, limit int) (
		repositories.PaginatedResponse[*entities.ResourceType], error)
	Update(ctx context.Context, cmd UpdateResourceTypeCommand) (*entities.ResourceType, error)
	Delete(ctx context.Context, cmd DeleteResourceTypeCommand) error
	ListPresets() []PresetDefinition
	InstallPreset(ctx context.Context, presetName string, update bool) (*InstallPresetResult, error)
	ListBehaviors(ctx context.Context, typeSlug string) ([]BehaviorInfo, error)
	SetBehaviors(ctx context.Context, typeSlug string, slugs []string) error
}

func NewResourceTypeServiceForTest

func NewResourceTypeServiceForTest(
	repo repositories.ResourceTypeRepository,
	projMgr repositories.ProjectionManager,
	eventStore domain.EventStore,
	dispatcher *domain.EventDispatcher,
	registry *PresetRegistry,
	logger entities.Logger,
	resourceSvc ResourceService,
) ResourceTypeService

NewResourceTypeServiceForTest creates a ResourceTypeService without fx wiring.

func ProvideResourceTypeService

func ProvideResourceTypeService(params struct {
	fx.In
	Repo             repositories.ResourceTypeRepository
	ProjMgr          repositories.ProjectionManager
	EventStore       domain.EventStore
	Dispatcher       *domain.EventDispatcher
	Registry         *PresetRegistry
	Logger           entities.Logger
	ResourceSvc      ResourceService
	Behaviors        ResourceBehaviorRegistry
	BehaviorMeta     BehaviorMetaRegistry
	BehaviorSettings repositories.BehaviorSettingsRepository
	AccountRepo      authrepos.AccountRepository
	LinkActivator    *LinkActivator `optional:"true"`
}) ResourceTypeService

type ResourceWriter

type ResourceWriter interface {
	Create(ctx context.Context, cmd CreateResourceCommand) (*entities.Resource, error)
	Update(ctx context.Context, cmd UpdateResourceCommand) (*entities.Resource, error)
	Delete(ctx context.Context, cmd DeleteResourceCommand) error
}

ResourceWriter is the subset of ResourceService that behaviors need to create, update, and delete other resources from inside a hook. It intentionally omits queries — use BehaviorServices.Resources for reads.

Write methods go through the full ResourceService pipeline: schema validation, JSON-LD graph assembly, triple extraction, event recording, and UnitOfWork commit, including nested behavior dispatch on the affected resources.

type RevokePermissionCommand

type RevokePermissionCommand struct {
	ResourceID string `json:"resource_id"`
	AgentID    string `json:"agent_id"`
}

type SimilarEvent

type SimilarEvent struct {
	RecalledEvent
	Similarity float64 `json:"similarity"`
}

SimilarEvent is one ranked result: the compact event shape plus its deterministic similarity score.

type SimilarQuery

type SimilarQuery struct {
	// Seed is the seed event URN (urn:event:<id>).
	Seed string
	// Limit caps results (default 20, max 100 — over-asks are capped).
	Limit int
}

SimilarQuery asks for events structurally similar to a seed event.

type SimilarResult

type SimilarResult struct {
	Events []SimilarEvent
}

SimilarResult is the ranked, limit-bounded result set.

type SkillRegistry

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

SkillRegistry holds the validated agent-skill definitions the orchestrator builds sub-agents from. It loads lazily from published agent-skill resources and reloads after any agent-skill resource event, so adding a skill is a data change — no recompile, no redeploy.

func NewSkillRegistry

func NewSkillRegistry(resources ResourceService, logger entities.Logger) *SkillRegistry

NewSkillRegistry creates the registry. It is provided via fx; the orchestrator wiring calls SetKnownTools once the tool surface exists.

func (*SkillRegistry) MarkDirty

func (r *SkillRegistry) MarkDirty()

MarkDirty invalidates the cache; the next Skills call reloads. Wired to agent-skill resource events.

func (*SkillRegistry) SetKnownTools

func (r *SkillRegistry) SetKnownTools(f KnownToolsFunc)

SetKnownTools installs the tool-name source and invalidates the cache so the next load re-validates every allowlist.

func (*SkillRegistry) Skills

Skills returns the currently-loaded definitions, reloading if a skill resource changed since the last call. Invalid definitions are skipped with a log line; they never take the rest of the registry down.

type SortOptions

type SortOptions = repositories.SortOptions

SortOptions re-exports for integration test convenience.

type SubscriberGroup

type SubscriberGroup struct {
	// Name is the subscriber's checkpoint name. Processes using the same name
	// share one position, so it must be stable across restarts and unique
	// across groups.
	Name string
	// Handler processes a single event from the feed. A group-private
	// EventDispatcher's Dispatch method satisfies this signature.
	Handler subscriptions.Handler
	// Options are per-group overrides appended after the Manager's defaults
	// (e.g. a smaller batch size for an expensive handler).
	Options []subscriptions.SubscriberOption
	// Truncate optionally clears the group's projection so a checkpoint reset
	// rebuilds it from empty (e.g. the Oxigraph store's Clear). nil means the
	// group has no separate projection to clear — display-values, for instance,
	// writes denormalized columns into other types' rows rather than owning a
	// table — and `worker checkpoint reset --truncate` reports that.
	Truncate func(context.Context) error
	// StartAtHead initializes a group that has never run before at the
	// current feed head instead of position 0, so enabling it on an instance
	// with existing history does not replay that history through the handler.
	// Only a missing checkpoint row is initialized — an existing row is never
	// moved, so an explicit `worker checkpoint reset` (which creates the row
	// at 0) remains the opt-in backfill path. Groups whose head
	// initialization fails are not started that run (fail closed): for an
	// expensive handler like consolidation, silently falling back to a
	// full-history replay is worse than sitting out one process lifetime.
	StartAtHead bool
}

SubscriberGroup defines one named background subscriber: the handler that processes the event feed and any per-group option overrides. Grouping decides what shares a checkpoint and fails, lags, and parks together — peripheral subsystems (knowledge-graph sync, denormalization) each get their own group so an outage in one never stalls the others.

Groups are contributed into the Fx graph via the "subscriber_groups" value group (see AsSubscriberGroup); the Manager collects them all and builds a pericarp Subscriber per group.

func ProvideConsolidationGroup

func ProvideConsolidationGroup(p ConsolidationGroupParams) []SubscriberGroup

ProvideConsolidationGroup contributes the "consolidation" subscriber group when a fact extractor is available AND at least one registered preset declares a consolidation-eligible resource type, and nothing otherwise. Like the oxigraph group it runs off the write path with its own checkpoint, so consolidation lag or failure never stalls a user's request, and a checkpoint reset replays history through the same handler.

The group starts at the feed head on its first ever run (StartAtHead): installing the memory preset on an instance with existing domain history must not trigger an LLM pass over the whole event log. Backfill stays an explicit operation — `worker checkpoint reset consolidation`.

func ProvideDisplayValuesGroup

func ProvideDisplayValuesGroup(p DisplayValuesGroupParams) []SubscriberGroup

ProvideDisplayValuesGroup contributes the "display-values" subscriber group, which denormalizes a resource's display label into the rows of other types that reference it. This reverse-reference propagation used to run inside the synchronous Resource.Published projection; moving it to a background group keeps the user's write fast and decouples it from the critical read model. The forward direction (a new row's own display columns) stays synchronous in the resource repository.

func ProvideEventReferenceGroup

func ProvideEventReferenceGroup(p EventReferenceGroupParams) []SubscriberGroup

ProvideEventReferenceGroup contributes the "event-references" subscriber group. No StartAtHead: the projection's value is completeness over history, so a fresh install replays the full log.

func ProvideLexicalGroup

func ProvideLexicalGroup(p LexicalGroupParams) []SubscriberGroup

ProvideLexicalGroup contributes the "lexical-index" subscriber group when the index is active (SQLite with FTS5), and nothing otherwise. The index is a rebuildable derived view: `worker checkpoint reset lexical-index --truncate` clears it and replays history through this handler.

func ProvideOxigraphGroup

func ProvideOxigraphGroup(p OxigraphGroupParams) []SubscriberGroup

ProvideOxigraphGroup contributes the "oxigraph" subscriber group when the knowledge-graph store is configured, and nothing otherwise (so leaving Oxigraph unconfigured costs no subscriber). It returns a slice so it can contribute zero or one group into the flattened "subscriber_groups" value group (see AsSubscriberGroups).

type UpdateResourceCommand

type UpdateResourceCommand struct {
	ID   string
	Data json.RawMessage
}

type UpdateResourceTypeCommand

type UpdateResourceTypeCommand struct {
	ID          string
	Name        string
	Slug        string
	Description string
	Context     json.RawMessage
	Schema      json.RawMessage
	Status      string
}

type UploadParams

type UploadParams = services.UploadParams

UploadParams is the application-layer alias for the domain UploadParams type.

type UploadResult

type UploadResult = services.UploadResult

UploadResult is the application-layer alias for the domain UploadResult type.

type WakeSource

type WakeSource interface {
	Subscribe() <-chan struct{}
}

WakeSource hands out wake channels so idle subscribers react to new commits instead of waiting out the poll interval. Each subscriber gets its own channel (channel receives are point-to-point). Implemented by pericarp's InProcessNotifier (SQLite / single process) and PostgresListener (cross process via LISTEN/NOTIFY).

type WorkingMemory

type WorkingMemory interface {
	// RecentFacts returns the newest non-superseded facts from the SQL
	// projection, freshest first. A non-empty about restricts to facts about
	// that entity INSIDE the query — filtering after the limit would silently
	// drop matches once other facts crowd the freshness window. limit <= 0
	// uses the default working-set size.
	RecentFacts(ctx context.Context, about string, limit int) ([]RecalledFact, error)
}

WorkingMemory surfaces just-written facts during the projection-lag window. The SQL fact projection is written synchronously on commit (read-your-writes) while the Oxigraph projection catches up on its own checkpoint, so a fact recorded this turn is visible here before it is queryable in the graph. Reads never block on any checkpoint.

func NewWorkingMemory

func NewWorkingMemory(service ResourceService) WorkingMemory

NewWorkingMemory builds the working-memory read model over the resource service's flat projection reads.

Directories

Path Synopsis
Package presets provides functions to register all built-in presets and create a fully populated registry.
Package presets provides functions to register all built-in presets and create a fully populated registry.
agents
Package agents provides the resource types for in-app agents: declarative agent-skill definitions that a WeOS app's orchestrator turns into runnable ADK sub-agents.
Package agents provides the resource types for in-app agents: declarative agent-skill definitions that a WeOS app's orchestrator turns into runnable ADK sub-agents.
core
Package core provides the built-in Person and Organization resource types with their associated behaviors.
Package core provides the built-in Person and Organization resource types with their associated behaviors.
ecommerce
Package ecommerce provides resource types for e-commerce: products, offers, reviews, and services.
Package ecommerce provides resource types for e-commerce: products, offers, reviews, and services.
events
Package events provides resource types for event management.
Package events provides resource types for event management.
knowledge
Package knowledge provides SKOS-based resource types for knowledge organization.
Package knowledge provides SKOS-based resource types for knowledge organization.
memory
Package memory provides resource types for agent memory: episodic notes, plus consolidated facts distilled from them carrying PROV-O provenance and supersession, and playbooks with event-sourced outcome counters.
Package memory provides resource types for agent memory: episodic notes, plus consolidated facts distilled from them carrying PROV-O provenance and supersession, and playbooks with event-sourced outcome counters.
tasks
Package tasks provides resource types for task and project management.
Package tasks provides resource types for task and project management.
website
Package website provides resource types for website structure and content.
Package website provides resource types for website structure and content.

Jump to

Keyboard shortcuts

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