Documentation
¶
Overview ¶
Package api is the canonical surface of gramaton's operations. Every transport (HTTP, MCP, CLI proxy, future gRPC/websocket) consumes this package. The goal is one definition of "what fields an operation accepts" and "what it does" -- no transport-specific struct drift.
Each operation lives in its own file (api/<op>.go) and follows the same shape:
type XxxRequest struct { ... with json + jsonschema tags ... }
type XxxResponse struct { ... }
const XxxDescription = "..."
func (a *API) Xxx(ctx context.Context, req XxxRequest) (XxxResponse, *APIError)
Transports read these types and methods via hand-written binding tables in their own packages. There is no reflection or codegen.
Index ¶
- Constants
- Variables
- func ListTemplates() []string
- func MaxKeywords() int
- func MaxSummaryShort() int
- func SetLimits(lim config.LimitsConfig)
- func WithTenant(ctx context.Context, tenant string) context.Context
- type API
- func (a *API) BackupCreate(ctx context.Context) (BackupCreateResponse, *APIError)
- func (a *API) BackupExport(ctx context.Context, req ExportRequest, w io.Writer) (string, *APIError)
- func (a *API) BackupImport(ctx context.Context, req ImportRequest) (ImportResponse, *APIError)
- func (a *API) BackupRestore(ctx context.Context, req RestoreRequest) (RestoreResponse, *APIError)
- func (a *API) BackupStatus(ctx context.Context) (BackupStatusResponse, *APIError)
- func (a *API) BranchCheckout(ctx context.Context, name string) (BranchCheckoutResponse, *APIError)
- func (a *API) BranchCreate(ctx context.Context, req BranchCreateRequest) (BranchCreateResponse, *APIError)
- func (a *API) BranchDiscard(ctx context.Context, name string) (BranchDiscardResponse, *APIError)
- func (a *API) BranchList(ctx context.Context) (BranchListResponse, *APIError)
- func (a *API) BranchMerge(ctx context.Context, name string) (BranchMergeResponse, *APIError)
- func (a *API) Capture(ctx context.Context, req CaptureRequest) (CaptureResponse, *APIError)
- func (a *API) CaptureBatch(ctx context.Context, req CaptureBatchRequest) (CaptureBatchResponse, *APIError)
- func (a *API) CaptureBatchCancel(ctx context.Context, req CaptureBatchCancelRequest) (CaptureBatchCancelResponse, *APIError)
- func (a *API) CaptureBatchResult(ctx context.Context, req CaptureBatchResultRequest) (CaptureBatchResponse, *APIError)
- func (a *API) CaptureBatchStatus(ctx context.Context, req CaptureBatchStatusRequest) (CaptureBatchStatusResponse, *APIError)
- func (a *API) Classify(ctx context.Context, req ClassifyRequest) (ClassifyResponse, *APIError)
- func (a *API) CollectionAdd(ctx context.Context, collectionID string, req CollectionAddRequest) (CollectionAddResponse, *APIError)
- func (a *API) CollectionAddBatch(ctx context.Context, collectionID string, req CollectionAddBatchRequest) (CollectionAddBatchResponse, *APIError)
- func (a *API) CollectionCreate(_ context.Context, req CollectionCreateRequest) (CollectionCreateResponse, *APIError)
- func (a *API) CollectionDelete(ctx context.Context, collectionID string) (CollectionDeleteResponse, *APIError)
- func (a *API) CollectionItems(ctx context.Context, collectionID string, req CollectionItemsRequest) (CollectionItemsResponse, *APIError)
- func (a *API) CollectionList(ctx context.Context, req CollectionListRequest) (CollectionListResponse, *APIError)
- func (a *API) CollectionMigrate(ctx context.Context, collectionID string, req CollectionMigrateRequest) (CollectionMigrateResponse, *APIError)
- func (a *API) CollectionMove(ctx context.Context, collectionID, itemID string, req CollectionMoveRequest) (CollectionMoveResponse, *APIError)
- func (a *API) CollectionRemove(ctx context.Context, collectionID, itemID string) (CollectionRemoveResponse, *APIError)
- func (a *API) CollectionRename(ctx context.Context, collectionID string, req CollectionRenameRequest) (CollectionRenameResponse, *APIError)
- func (a *API) CollectionSchemaRead(ctx context.Context, collectionID string) (CollectionSchemaReadResponse, *APIError)
- func (a *API) CollectionSchemaUpdate(ctx context.Context, collectionID string, req CollectionSchemaUpdateRequest) (CollectionSchemaUpdateResponse, *APIError)
- func (a *API) CollectionUpdate(ctx context.Context, collectionID, itemID string, req CollectionUpdateRequest) (CollectionUpdateResponse, *APIError)
- func (a *API) ConfigDir() string
- func (a *API) CurationBatch(ctx context.Context) (CurationBatchResponse, *APIError)
- func (a *API) CurationDrainContradictions(ctx context.Context) (CurationDrainResponse, *APIError)
- func (a *API) CurationDryRun(ctx context.Context) (CurationDryRunResponse, *APIError)
- func (a *API) CurationListStuck(ctx context.Context) (CurationListStuckResponse, *APIError)
- func (a *API) CurationResetStuck(ctx context.Context, req CurationResetStuckRequest) (CurationResetStuckResponse, *APIError)
- func (a *API) CurationStatus(ctx context.Context) (CurationStatusResponse, *APIError)
- func (a *API) CurationTrigger(ctx context.Context) (CurationTriggerResponse, *APIError)
- func (a *API) DeleteRecord(ctx context.Context, req DeleteRecordRequest) (DeleteRecordResponse, *APIError)
- func (a *API) Diff(ctx context.Context, req DiffRequest) (DiffResponse, *APIError)
- func (a *API) Duplicates(ctx context.Context, req DuplicatesRequest) (DuplicatesResponse, *APIError)
- func (a *API) Engine() *core.Engine
- func (a *API) Explore(ctx context.Context, req ExploreRequest) (ExploreResponse, *APIError)
- func (a *API) History(ctx context.Context, req HistoryRequest) (HistoryResponse, *APIError)
- func (a *API) Inspect(ctx context.Context, req InspectRequest) (InspectResponse, *APIError)
- func (a *API) JobsList(ctx context.Context, req JobsListRequest) (JobsListResponse, *APIError)
- func (a *API) Link(ctx context.Context, req LinkRequest) (LinkResponse, *APIError)
- func (a *API) Log(ctx context.Context, req LogRequest) (LogResponse, *APIError)
- func (a *API) Logger() *slog.Logger
- func (a *API) Pending(ctx context.Context, req PendingRequest) (PendingResponse, *APIError)
- func (a *API) Reembed(ctx context.Context, req ReembedRequest) (ReembedResponse, *APIError)
- func (a *API) Resolve(ctx context.Context, req ResolveRequest) (ResolveResponse, *APIError)
- func (a *API) Runner() *curation.Runner
- func (a *API) Search(ctx context.Context, req SearchRequest) (SearchResponse, *APIError)
- func (a *API) SessionArchive(ctx context.Context, sessionID string, sourcePath string) (map[string]any, *APIError)
- func (a *API) SessionCommit(ctx context.Context, sessionID string, segments []CommitSegment) (SessionCommitResponse, *APIError)
- func (a *API) SessionGet(ctx context.Context, sessionID string) (map[string]any, *APIError)
- func (a *API) SessionPrepare(ctx context.Context, sessionID string) (map[string]any, *APIError)
- func (a *API) SessionStart(ctx context.Context, clientSessionID string, source string) (map[string]any, *APIError)
- func (a *API) SetBackupSnapshotHook(ch chan struct{})
- func (a *API) SetChunkSizeForTests(size int)
- func (a *API) SetFaultInjector(fi FaultInjector)
- func (a *API) SetRunner(r *curation.Runner)
- func (a *API) ShutdownAsync(ctx context.Context) error
- func (a *API) StartPreparedSweeper()
- func (a *API) Stats(ctx context.Context) (StatsResponse, *APIError)
- func (a *API) Status(ctx context.Context, _ StatusRequest) (StatusResponse, *APIError)
- func (a *API) StopPreparedSweeper()
- func (a *API) Unlink(ctx context.Context, req UnlinkRequest) (UnlinkResponse, *APIError)
- func (a *API) Update(ctx context.Context, req UpdateRequest) (UpdateResponse, *APIError)
- func (a *API) UsageTracker() *llm.UsageTracker
- type APIError
- func ErrConflict(msg string) *APIError
- func ErrForbidden(msg string) *APIError
- func ErrInternal(msg string) *APIError
- func ErrInvalid(msg string) *APIError
- func ErrMissing(msg string) *APIError
- func ErrNotFound(msg string) *APIError
- func ErrPrepareRequired(msg string) *APIError
- func ErrUnavailable(msg string) *APIError
- type BackupCreateResponse
- type BackupInfo
- type BackupStatusResponse
- type BatchAddFailure
- type BatchAddSuccess
- type BatchItemFailure
- type BranchCheckoutResponse
- type BranchCreateRequest
- type BranchCreateResponse
- type BranchDiscardResponse
- type BranchEntry
- type BranchListResponse
- type BranchMergeResponse
- type CaptureBatchAdded
- type CaptureBatchCancelRequest
- type CaptureBatchCancelResponse
- type CaptureBatchItem
- type CaptureBatchRequest
- type CaptureBatchResponse
- type CaptureBatchResultRequest
- type CaptureBatchStats
- type CaptureBatchStatusRequest
- type CaptureBatchStatusResponse
- type CaptureRequest
- type CaptureResponse
- type ClassifyRequest
- type ClassifyResponse
- type ClearMode
- type CollectionAddBatchRequest
- type CollectionAddBatchResponse
- type CollectionAddItem
- type CollectionAddRequest
- type CollectionAddResponse
- type CollectionCreateRequest
- type CollectionCreateResponse
- type CollectionDeleteResponse
- type CollectionItem
- type CollectionItemsRequest
- type CollectionItemsResponse
- type CollectionListEntry
- type CollectionListRequest
- type CollectionListResponse
- type CollectionMigrateRequest
- type CollectionMigrateResponse
- type CollectionMigrationState
- type CollectionMoveRequest
- type CollectionMoveResponse
- type CollectionRemoveResponse
- type CollectionRenameRequest
- type CollectionRenameResponse
- type CollectionSchema
- type CollectionSchemaReadResponse
- type CollectionSchemaUpdateRequest
- type CollectionSchemaUpdateResponse
- type CollectionUpdateRequest
- type CollectionUpdateResponse
- type CommitSegment
- type ConfidenceDist
- type Contradictions
- type Curation
- type CurationBatchResponse
- type CurationDrainResponse
- type CurationDryRunResponse
- type CurationListStuckResponse
- type CurationResetStuckRequest
- type CurationResetStuckResponse
- type CurationStatusResponse
- type CurationTriggerResponse
- type DeleteRecordRequest
- type DeleteRecordResponse
- type Dependencies
- type DiffEntry
- type DiffRequest
- type DiffResponse
- type DuplicatesRequest
- type DuplicatesResponse
- type EdgeAdded
- type EdgeFailure
- type EdgeSpec
- type ExploreRequest
- type ExploreResponse
- type ExportRequest
- type FaultInjector
- type HistoryChange
- type HistoryRequest
- type HistoryResponse
- type ImportRequest
- type ImportResponse
- type InspectRequest
- type InspectResponse
- type ItemFailure
- type JobSummary
- type JobsListRequest
- type JobsListResponse
- type LinkRequest
- type LinkResponse
- type LogEntry
- type LogRequest
- type LogResponse
- type MutationSummary
- type PageRef
- type PendingRecord
- type PendingRequest
- type PendingResponse
- type ReembedRequest
- type ReembedResponse
- type RelatedEdge
- type ResolveRequest
- type ResolveResponse
- type RestoreRequest
- type RestoreResponse
- type RetrievalTracker
- type SchemaField
- type SchemaFieldType
- type SearchRequest
- type SearchResponse
- type SessionCommitResponse
- type StatsResponse
- type StatusRequest
- type StatusResponse
- type StuckRecord
- type SupersededRecord
- type Supersession
- type Template
- type UnlinkRequest
- type UnlinkResponse
- type UpdateRequest
- type UpdateResponse
Constants ¶
const ( FaultPhaseChunkSave = "chunk_save" FaultPhaseJobstoreUpdate = "jobstore_update" // FaultPhaseEdgeFixup fires inside the L6 chunked runner's // post-chunks edge-fixup save. Returning an error simulates the // fixup commit failing; the runner rolls back the in-memory edges // and marks Job failed/edge_fixup_failed. FaultPhaseEdgeFixup = "edge_fixup" // FaultPhasePanic is honored only by FaultInjector implementations // that can panic on demand. CaptureBatch's runner consults this // via tests via the panic-injection seam. FaultPhasePanic = "panic" )
Phase names recognized by FaultInjector. Defined as constants so implementations don't drift from the call sites.
const ( BackupStatusDescription = "List existing backups with size and creation time." BackupCreateDescription = "" /* 157-byte string literal not displayed */ BackupRestoreDescription = "Restore the store from a backup archive. Overwrites current data -- requires force=true." BackupExportDescription = "Export the store as json, csv, or markdown. Streams the export bytes to the caller." BackupImportDescription = "Import records from a prior export (JSON lines)." )
const ( BranchListDescription = "List all branches with their commit hashes and which one is active." BranchCreateDescription = "Create a new branch at the current HEAD. Use for safe experimentation before merging into main." BranchCheckoutDescription = "Switch to an existing branch. The graph is loaded from the branch's commit off-lock; indexes are rebuilt under lock." BranchMergeDescription = "Merge a branch into main (fast-forward). Deletes the branch ref on success." BranchDiscardDescription = "Discard a branch without merging. Switches back to main if the discarded branch was active." )
const ( DefaultClearMode = ClearModeResolve DefaultSupersession = SupersessionCollection DefaultCuration = CurationNone DefaultContradictions = ContradictionsOn )
Default values used when a collection's property is absent. The read-time fallback these constants power is why we don't need a migrate-time sweep on every config change.
DefaultCuration is CurationNone. Bare-bones collections created without a template or explicit curation knob skip LLM work -- the safe default for "I want a collection, didn't say anything else." Templates that want LLM-driven enrichment (backlog, todo, reading-list, journal, references) declare curation=standard explicitly. The flip from CurationStandard followed activation of curation on collection items: default=standard was risk-free while items lacked content_full and no LLM stage actually ran; once activation made the knob load-bearing, the deliberate choice was to make LLM costs explicitly opt-in rather than rely on an inherited default.
const ( CurationStatusDescription = "" /* 239-byte string literal not displayed */ CurationTriggerDescription = "Run a curation cycle now. Returns triggered=false (with the prior status) when a cycle is already in progress." CurationDryRunDescription = "" /* 132-byte string literal not displayed */ CurationBatchDescription = "Classify every pending record in one call (LLM required). Use when piggyback curation has fallen behind." CurationDrainDescription = "" /* 416-byte string literal not displayed */ )
Description constants are shared by HTTP, MCP, and CLI proxy transports so the surface text never drifts between them.
const ( MaxKeywordLength = 256 MaxSourceRefLen = 2048 MaxContextFieldLen = 2048 MaxEdgeTypeLen = 256 MaxMatchLength = 1024 MaxTopicLength = 1024 MaxFactLen = 10000 MaxMetaKeys = 50 MaxMetaKeyLen = 64 MaxMetaValueLen = 1024 MaxReembedBatch = 500 // MaxCollectionBatchSize caps how many items a single bulk add // can commit. Bigger batches would tie up the engine write lock // for an extended period and potentially exceed provider // batch-embed limits. 500 is a starting point -- raise it only // after profiling. MaxCollectionBatchSize = 500 // MaxSyncBatchSize caps the synchronous capture_batch path. Beyond // this, the wall-clock and lock-hold cost outweigh the latency // savings vs a series of single captures; the async path (Layer 5) // raises the cap to MaxAsyncBatchSize. MaxSyncBatchSize = 500 // MaxBatchBytes is the per-request total content-byte ceiling for // the capture_batch path. Defends against a 1000-item × 100MB-each // memory blowup; Phase 0 validation rejects oversize before any // allocation. MaxBatchBytes = 256 * 1024 * 1024 // MaxClientRefLen caps the per-item ClientRef label. MaxClientRefLen = 128 // MaxBatchEdgeMultiplier caps how many edges a batch may carry // relative to its item count. The cap is len(Items) * // MaxBatchEdgeMultiplier; rejecting a 10000-edge request against // a 5-item batch keeps Phase 0 from chewing up unbounded // validation work for an obviously-malformed request. MaxBatchEdgeMultiplier = 10 // MaxAsyncBatchSize caps the async capture_batch path. The async // runner splits work into MaxSyncBatchSize-per-chunk pieces and // commits per-chunk progress, so this can be much larger than the // sync cap. Operator override via cfg.Jobs.MaxAsyncBatchSize. // MaxBatchBytes (256MB) remains the byte-level safety net. MaxAsyncBatchSize = 10000 // MaxJobsListLimit caps gramaton_jobs_list pagination. Above // this an operator should narrow filters (status, kind, time // range) rather than scroll a single huge response. MaxJobsListLimit = 200 // DefaultJobsListLimit is the limit applied when the request // omits one. DefaultJobsListLimit = 50 // MaxJobsListOffset caps the pagination offset. Once a caller // is scrolling past 100k jobs, narrowing by status / kind / time // is the right tool; allowing arbitrary offset turns a single // request into an unbounded bbolt scan. MaxJobsListOffset = 100_000 // MaxKindLen caps the Job kind filter string. The kind set is // closed (capture_batch and future ops); 64 is generous. MaxKindLen = 64 // MaxRFC3339Len caps the wire length of an RFC3339 timestamp // argument. Real RFC3339 maxes around 30 characters; 64 leaves // headroom for nanoseconds + offset and rejects pathological // 10MB inputs. MaxRFC3339Len = 64 // MaxResultTimeoutMS caps CaptureBatchResult's blocking timeout. // Holding a connection for longer than this is a footgun; the // caller should poll Status instead. MaxResultTimeoutMS = 30 * 60 * 1000 // 30 minutes )
Per-field length + cardinality limits used by api method validation. Keep these in sync with anything the HTTP layer enforces separately (e.g. JSON body size, ingest size) -- those limits are at a coarser layer and stay with the transport.
const ( MaxSearchTop = 1000 MaxMissingFields = 50 MaxSearchHops = 10 MaxExploreDepth = 10 MaxExploreNodes = 10000 MaxEdgeTypes = 50 MaxDuplicatePairs = 1000 MaxLogLimit = 500 MaxLogTraversal = 5000 // MaxLogActionsFilter bounds the size of the Actions filter // array on gramaton_log. A caller passing thousands of Kinds // would otherwise inflate the in-memory set and force a scan // of every commit's Actions slice against all of them. 64 is // generous -- the Kind set today is under 20. MaxLogActionsFilter = 64 )
Search input cardinality limits.
const ( MaxProjectionFields = 64 MaxFilterKeys = 20 MaxFilterValuesPerKey = 100 )
Collection item listing limits. Bounds on the new projection and filter knobs keep CollectionItems from being a DoS amplifier -- 10k field names or a filter map with 1000 keys * 1000 values each would otherwise be valid inputs.
const CaptureBatchCancelDescription = `` /* 450-byte string literal not displayed */
CaptureBatchCancelDescription is the MCP tool description for gramaton_capture_batch_cancel.
const CaptureBatchDescription = `` /* 894-byte string literal not displayed */
CaptureBatchDescription is the MCP tool description shared by every transport (MCP server registration and CLI MCP proxy).
const CaptureBatchResultDescription = `` /* 523-byte string literal not displayed */
CaptureBatchResultDescription is the MCP tool description for gramaton_capture_batch_result.
const CaptureBatchStatusDescription = `` /* 325-byte string literal not displayed */
CaptureBatchStatusDescription is the MCP tool description for gramaton_capture_batch_status.
const CaptureDescription = `` /* 947-byte string literal not displayed */
CaptureDescription is the MCP tool description shared by every transport that surfaces capture (direct MCP registration and the CLI MCP proxy). Changes here update both surfaces.
const ClassifyDescription = "Classify a pending record with metadata. Sets processing_status to processed."
ClassifyDescription is the MCP tool description for gramaton_classify.
const CollectionAddBatchDescription = "" /* 785-byte string literal not displayed */
const CollectionAddDescription = "" /* 515-byte string literal not displayed */
const CollectionCreateDescription = "" /* 255-byte string literal not displayed */
const CollectionDeleteDescription = "Retire a collection (reversible). Items and edges are preserved. Call again on a retired collection to re-activate it."
const CollectionItemsDescription = "" /* 483-byte string literal not displayed */
const CollectionListDescription = "" /* 181-byte string literal not displayed */
const CollectionMigrateDescription = "" /* 156-byte string literal not displayed */
const CollectionMoveDescription = "Move an item from one collection to another. The item's fields are validated against the target collection's schema."
const CollectionRemoveDescription = "Remove an item from a collection. The item node is preserved in the graph; only the membership edge is deleted."
const CollectionRenameDescription = "Rename a collection. Name must be unique."
const CollectionSchemaDescription = "Read a collection's schema and migration status."
const CollectionUpdateDescription = "" /* 142-byte string literal not displayed */
const DeleteRecordDescription = "Soft-delete a record. Sets processing_status=deleted and records deleted_at; the node is retained for provenance/rollback."
DeleteRecordDescription is the MCP tool description for the delete operation. Soft-delete semantics: sets processing_status = "deleted" rather than removing the node.
const DiffDescription = "" /* 171-byte string literal not displayed */
DiffDescription is shared by HTTP, MCP, and CLI proxy transports.
const DuplicatesDescription = "Find near-duplicate records by embedding similarity."
DuplicatesDescription is the MCP tool description.
const ExploreDescription = "Traverse the graph from a starting record. Returns connected nodes and edges within the given depth."
ExploreDescription is the MCP tool description for gramaton_explore.
const HistoryDescription = "View the change history for a specific record, walking commit metadata backwards from HEAD."
HistoryDescription is the MCP tool description for gramaton_history.
const InspectDescription = "" /* 551-byte string literal not displayed */
InspectDescription is the MCP tool description for gramaton_inspect.
const JobsListDescription = `` /* 444-byte string literal not displayed */
JobsListDescription is the MCP tool description for gramaton_jobs_list.
const LinkDescription = "Create a typed edge from one record to another."
LinkDescription is the MCP tool description for gramaton_link.
const LogDescription = "" /* 608-byte string literal not displayed */
LogDescription is shared by HTTP, MCP, and CLI proxy transports.
const MaxClientSessionIDLen = 256
MaxClientSessionIDLen caps how long a client_session_id can be. Keeps pathological callers from blowing up hook-state file paths.
const MaxMutationsPerCommit = 20
MaxMutationsPerCommit caps the per-commit mutation slice when IncludeRecordMutations=true. A curation batch touching 50 records would otherwise balloon a single log entry; truncation keeps response size predictable and is flagged via LogEntry.MutationsTruncated so callers know to drop to gramaton_history if they need the full set.
const MaxResetStuckIDs = 10000
MaxResetStuckIDs caps the number of explicit IDs accepted by CurationResetStuck. The operation is loopback-gated and the body size is already bounded, but an explicit cap keeps the api layer honest about its blast radius. 10000 matches MaxExploreNodes -- "max population we'll touch in one operation." Operators with more than 10k stuck records have a deeper problem the recovery verb alone can't help with.
const PendingDescription = "List records awaiting classification (processing_status=captured)."
PendingDescription is the MCP tool description for gramaton_pending.
const ReembedDescription = "" /* 133-byte string literal not displayed */
ReembedDescription is shared by HTTP, MCP, and CLI proxy.
const ResolveDescription = "" /* 439-byte string literal not displayed */
ResolveDescription is the MCP tool description for gramaton_resolve.
const SearchDescription = "" /* 1487-byte string literal not displayed */
SearchDescription is the MCP tool description for gramaton_search. Leads with triggers (not mechanics) to prompt agents to call it BEFORE producing project-state content, not after. The retrieval failure mode that motivated this framing was agents writing architecture answers from general knowledge without first checking for project-specific prior thinking in the store.
const SessionCommitDescription = `` /* 246-byte string literal not displayed */
SessionCommitDescription is the MCP tool description for gramaton_session_commit.
const SessionGetDescription = `Get the current session state including all topics and segments. Use to review what has been captured so far.`
SessionGetDescription is the MCP tool description for gramaton_session_get.
const SessionPrepareDescription = `` /* 626-byte string literal not displayed */
SessionPrepareDescription is the MCP tool description for gramaton_session_prepare. Leads with "eagerly throughout" language to counter the prior-version regression where agents self-triggered far less often than the old gramaton_observe tool did.
const SessionStartDescription = `` /* 186-byte string literal not displayed */
SessionStartDescription is the MCP tool description for gramaton_session_start.
const StatsDescription = "" /* 340-byte string literal not displayed */
StatsDescription is the MCP tool description for gramaton_stats.
const StatusDescription = "Get store health: node/edge counts, embedding status."
StatusDescription is the MCP tool description for gramaton_status.
const UnlinkDescription = "Delete an edge by its edge_id."
UnlinkDescription is the MCP tool description for gramaton_unlink.
const UpdateDescription = "Update metadata on a Memory record. For collection item fields, use gramaton_collection_update instead."
UpdateDescription is the MCP tool description for gramaton_update.
Variables ¶
var ( ValidTemporalities = map[string]bool{ "immutable": true, "durable": true, "temporal": true, "ephemeral": true, } ValidKnowledgeTypes = map[string]bool{ "episodic": true, "semantic": true, "procedural": true, "conceptual": true, "reference": true, "collection": true, } ValidEpistemicStatuses = map[string]bool{ "well_established": true, "probable": true, "speculative": true, "contested": true, "refuted": true, } ValidResolutions = map[string]bool{ "completed": true, "superseded": true, "abandoned": true, "obsolete": true, } )
Enum sets. Exposed so transport-level validators (e.g. MCP schema hints) can reference the same source of truth.
Functions ¶
func ListTemplates ¶
func ListTemplates() []string
ListTemplates returns the names of all registered templates sorted alphabetically. Useful for a future "gramaton template list" CLI or the collection-creation wizard.
func MaxKeywords ¶
func MaxKeywords() int
MaxKeywords returns the configured cap on keyword list length. Falls back to 100 when unset.
func MaxSummaryShort ¶
func MaxSummaryShort() int
MaxSummaryShort returns the configured cap on summary_short length in characters. Falls back to 1000 when unset.
func SetLimits ¶
func SetLimits(lim config.LimitsConfig)
SetLimits installs the configured limits. Zero values are preserved verbatim (no silent fallback) so config omissions surface clearly.
func WithTenant ¶
WithTenant returns a derived context carrying the supplied tenant identifier. Empty string is treated identically to "no tenant" (single-tenant deployment); pass it explicitly only when you have a meaningful identity.
The api/ layer reads this back via tenantFromContext when creating or filtering jobs. Until real caller identity wires in (HTTP middleware on a remote-callable mode, MCP session token, etc.), every request runs with tenant="" and the persisted Job records reflect that. The data layer is ready for the multi-tenant switch-over without a migration.
IMPORTANT — trust boundary: when remote-callable mode wires this in, the tenant value MUST come from a verified identity (signed JWT, OIDC subject claim, HTTP middleware that authenticates a session before stamping ctx). It must NEVER be read from a caller-controlled HTTP header or JSON field — that would let any caller list any tenant's jobs by spoofing the value. tenantContextKey is unexported precisely to keep external packages from constructing it; only this package's setter is the official path.
Types ¶
type API ¶
type API struct {
// contains filtered or unexported fields
}
API is the single operational surface consumed by all transports. Construct one per server process; pass it to each transport's binding registrar.
func New ¶
func New(deps Dependencies) *API
New constructs an API. The returned pointer is safe for concurrent use -- methods acquire engine locks as needed.
func (*API) BackupCreate ¶
func (a *API) BackupCreate(ctx context.Context) (BackupCreateResponse, *APIError)
BackupCreate snapshots HEAD/refs/FORMAT under RLock, releases, and then runs the compression pass off-lock. Concurrent writes can land during the compression; they are not included in the archive (which is what "snapshot at time T" means).
func (*API) BackupExport ¶
BackupExport streams matching records in the requested format.
Three-phase pattern (lock-discipline preserving):
- Phase 1 (RLock): apply filters + collect candidate IDs. Filter args (Text, Match, Filter, etc.) reuse the search machinery; an empty filter set means "every record."
- Phase 2 (no lock): the response writer.
- Phase 3 (per-record RLock + write): backup.StreamRecords reacquires the lock briefly per record, fetches it, releases, then writes to w. Concurrent writers aren't blocked across the entire export.
Returns the content-type for the format on success. The export is exhaustive over the matched set -- no candidate_cap, no pagination -- since the loopback gate already restricts callers.
func (*API) BackupImport ¶
func (a *API) BackupImport(ctx context.Context, req ImportRequest) (ImportResponse, *APIError)
BackupImport takes a batch of ExportRecord values and imports them. Current behavior matches pre-migration -- backup.ImportJSON handles its own concurrency, and we rebuild indexes after.
func (*API) BackupRestore ¶
func (a *API) BackupRestore(ctx context.Context, req RestoreRequest) (RestoreResponse, *APIError)
BackupRestore overwrites the current data directory with the archive's contents. Necessarily holds the engine write lock for the duration of extraction + index rebuild; this is a rare destructive operation and splitting it further would add complexity without real value.
Path confinement: req.Path must live under the configured backup directory. Without this gate any caller could restore from an arbitrary tarball on the host filesystem -- a malicious archive could exploit tar-extraction edge cases or simply replace the live store with attacker-controlled state.
func (*API) BackupStatus ¶
func (a *API) BackupStatus(ctx context.Context) (BackupStatusResponse, *APIError)
BackupStatus lists archives in the backup directory. No engine lock needed -- the backup directory is independent of the live store.
func (*API) BranchCheckout ¶
BranchCheckout loads the branch's committed graph state. Three-phase lock discipline:
- RLock: read the target ref hash, release.
- No lock: parse the committed graph into a fresh *graph.Graph that SHARES the engine's BboltEdgeStore -- otherwise edges added on the new branch silently bypass bbolt persistence.
- Lock: write HEAD + active branch FIRST (so a partial failure leaves no in-memory/on-disk divergence), then SwapGraph, then rebuild indexes.
func (*API) BranchCreate ¶
func (a *API) BranchCreate(ctx context.Context, req BranchCreateRequest) (BranchCreateResponse, *APIError)
BranchCreate writes a new ref at the current HEAD. Short lock hold -- one ReadRef + one WriteRef -- so no off-lock split.
func (*API) BranchDiscard ¶
BranchDiscard deletes a branch ref without merging. If the discarded branch is the active one, switches HEAD + active back to main BEFORE deleting -- otherwise we'd leave HEAD pointing at a missing ref. Short lock hold -- only on-disk writes.
func (*API) BranchList ¶
func (a *API) BranchList(ctx context.Context) (BranchListResponse, *APIError)
BranchList returns every ref plus the active branch.
func (*API) BranchMerge ¶
BranchMerge fast-forwards main to absorb the named branch, then deletes the branch ref. Same off-lock parse pattern as checkout; the new graph shares the engine's BboltEdgeStore so post-merge edge writes persist.
Note: engine.Save() writes HEAD as part of its commit path, so merge's "swap then save" sequence ends with HEAD pointing at the new merge commit. main ref is updated after Save -- if that ref write fails the new commit exists in the object store and HEAD points at it (recoverable: re-running merge will pick up where we left off, since the graph is still in main's state).
func (*API) Capture ¶
func (a *API) Capture(ctx context.Context, req CaptureRequest) (CaptureResponse, *APIError)
Capture creates a new knowledge record. Pre-embeds content_short outside the engine write lock, then holds the lock for the minimum time needed to insert the node, attach the embedding, check dedup, and save. Auto-supersession: if the captured record is a near-duplicate (cosine >= dedup.threshold) of an existing record, the older one is marked historical and a "supersedes" edge links the new record to it. Returns ErrConflict only when dedup.action = "reject" AND a duplicate is found.
func (*API) CaptureBatch ¶
func (a *API) CaptureBatch(ctx context.Context, req CaptureBatchRequest) (CaptureBatchResponse, *APIError)
CaptureBatch dispatches to either the synchronous core or the async runner based on req.Wait. Both paths share envelope validation, ClientToken idempotency, and Job.Create up front; the per-item commit work runs inline (sync) or in a goroutine (async).
L5 single-chunk runner: the entire batch commits in one Save call in the runner goroutine (same shape as sync, just off the request path). L6 introduces multi-chunk + cross-chunk edge fixup.
func (*API) CaptureBatchCancel ¶
func (a *API) CaptureBatchCancel(ctx context.Context, req CaptureBatchCancelRequest) (CaptureBatchCancelResponse, *APIError)
CaptureBatchCancel flips the Job's status to cancelled and signals the runner's context (which the runner observes between chunks and during embed). One retry on transient JobStore.Update failure to tolerate brief bbolt contention.
func (*API) CaptureBatchResult ¶
func (a *API) CaptureBatchResult(ctx context.Context, req CaptureBatchResultRequest) (CaptureBatchResponse, *APIError)
CaptureBatchResult blocks (with poll backoff) until the Job reaches a terminal state or the timeout elapses. On timeout returns the current Job snapshot and a "timeout" APIError so the caller knows the wait didn't complete.
The timeout is bounded by MaxResultTimeoutMS even when the caller passes a larger value. Holding a connection for longer is a footgun; the caller should poll Status instead. Per-tenant Job access is enforced inside the poll loop.
func (*API) CaptureBatchStatus ¶
func (a *API) CaptureBatchStatus(ctx context.Context, req CaptureBatchStatusRequest) (CaptureBatchStatusResponse, *APIError)
CaptureBatchStatus reads the current Job state. Read-only; never touches the engine write lock. Cross-tenant access surfaces ErrNotFound rather than ErrForbidden so existence isn't leaked.
func (*API) Classify ¶
func (a *API) Classify(ctx context.Context, req ClassifyRequest) (ClassifyResponse, *APIError)
Classify moves a record out of the "captured" state by setting its classification fields and flipping processing_status to "processed". Unlike Update, Classify is idempotent -- calling it twice with the same args is safe.
func (*API) CollectionAdd ¶
func (a *API) CollectionAdd(ctx context.Context, collectionID string, req CollectionAddRequest) (CollectionAddResponse, *APIError)
func (*API) CollectionAddBatch ¶
func (a *API) CollectionAddBatch(ctx context.Context, collectionID string, req CollectionAddBatchRequest) (CollectionAddBatchResponse, *APIError)
CollectionAddBatch adds many items to a collection in one call. The implementation runs in two phases:
Phase 1 (off-lock): schema-validate every item and batch-embed the concatenated text per item in a single provider call. Per- item validation failures are recorded without engaging the engine. An embed-call failure is tolerated -- items that would have been embedded fall back to embed-less add, preserving the rest of the batch. Phase 2 (write lock): load the collection + schema, run the dedup pass (existing members via CollCache plus intra-batch titles) and commit all passing items inside a single BatchIndexWrites transaction. One Save at the end.
Best-effort semantics: per-item validation and dedup failures are reported in Failed; items that pass pre-checks commit atomically. A Save-phase failure aborts the whole batch with a top-level APIError; it does not produce partial per-item results.
func (*API) CollectionCreate ¶
func (a *API) CollectionCreate(_ context.Context, req CollectionCreateRequest) (CollectionCreateResponse, *APIError)
func (*API) CollectionDelete ¶
func (*API) CollectionItems ¶
func (a *API) CollectionItems(ctx context.Context, collectionID string, req CollectionItemsRequest) (CollectionItemsResponse, *APIError)
CollectionItems is deliberately unpaginated -- exhaustive retrieval is the contract that distinguishes Collections from Memory. If a collection grows large enough to need pagination, it's a signal to split it. Filter narrows the result by exact schema-field match (preserving the exhaustive contract). Fields projects the per-item `fields` sub-map down to a allowlist -- both are there so agents can audit large collections without dragging the full-fidelity `details` payload.
When req.AsOf is set, CollectionItems switches to point-in-time mode: the response reflects the commit at-or-before AsOf (D7 CommitAt), and each member is read at its per-commit state. The response carries `as_of` + `semantics: "point_in_time"` so agents don't have to guess.
func (*API) CollectionList ¶
func (a *API) CollectionList(ctx context.Context, req CollectionListRequest) (CollectionListResponse, *APIError)
func (*API) CollectionMigrate ¶
func (a *API) CollectionMigrate(ctx context.Context, collectionID string, req CollectionMigrateRequest) (CollectionMigrateResponse, *APIError)
func (*API) CollectionMove ¶
func (a *API) CollectionMove(ctx context.Context, collectionID, itemID string, req CollectionMoveRequest) (CollectionMoveResponse, *APIError)
func (*API) CollectionRemove ¶
func (*API) CollectionRename ¶
func (a *API) CollectionRename(ctx context.Context, collectionID string, req CollectionRenameRequest) (CollectionRenameResponse, *APIError)
func (*API) CollectionSchemaRead ¶
func (*API) CollectionSchemaUpdate ¶
func (a *API) CollectionSchemaUpdate(ctx context.Context, collectionID string, req CollectionSchemaUpdateRequest) (CollectionSchemaUpdateResponse, *APIError)
func (*API) CollectionUpdate ¶
func (a *API) CollectionUpdate(ctx context.Context, collectionID, itemID string, req CollectionUpdateRequest) (CollectionUpdateResponse, *APIError)
func (*API) ConfigDir ¶
ConfigDir returns the configuration directory path (where hook-state files and similar artifacts live).
func (*API) CurationBatch ¶
func (a *API) CurationBatch(ctx context.Context) (CurationBatchResponse, *APIError)
CurationBatch classifies every pending record in one pass. Requires an LLM provider on the engine. Long-running; the caller should expect this to block for the duration.
func (*API) CurationDrainContradictions ¶
func (a *API) CurationDrainContradictions(ctx context.Context) (CurationDrainResponse, *APIError)
CurationDrainContradictions artificially marks every in-window contradiction-candidate pair as "no_contradiction" without calling the LLM. The operator is saying "I don't want to pay for the autonomous pass to organically drain this pool; I accept that real contradictions in the drained set won't be flagged." Edges carry an artificial: true property so future re-check logic can distinguish them from LLM-verified marks.
func (*API) CurationDryRun ¶
func (a *API) CurationDryRun(ctx context.Context) (CurationDryRunResponse, *APIError)
CurationDryRun runs the autonomous curation pipeline without applying changes. The LLM is still called so callers see what would have happened. Deterministic curation runs normally.
func (*API) CurationListStuck ¶
func (a *API) CurationListStuck(ctx context.Context) (CurationListStuckResponse, *APIError)
CurationListStuck walks the graph and returns every record with a stuck task status. Read-only; safe to call frequently.
func (*API) CurationResetStuck ¶
func (a *API) CurationResetStuck(ctx context.Context, req CurationResetStuckRequest) (CurationResetStuckResponse, *APIError)
CurationResetStuck flips stuck records back to their pre-failure status and clears their per-task attempts counter + last-error property. The next curation cycle will retry them. Operator-driven recovery; use the matching CLI verb gramaton curation stuck-records-reset which adds a count + LLM-cost-warning + Y/N confirmation around this call.
When req.IDs is empty: reset every stuck record across all tasks. When req.IDs is non-empty: reset only the listed records; non-stuck IDs in the list are silently ignored (no error -- caller may pass a list from a prior CurationListStuck snapshot whose state has since changed).
func (*API) CurationStatus ¶
func (a *API) CurationStatus(ctx context.Context) (CurationStatusResponse, *APIError)
CurationStatus returns the runner's status and current manifest. Cheap; safe to call frequently. Returns ErrUnavailable if the runner is not configured.
func (*API) CurationTrigger ¶
func (a *API) CurationTrigger(ctx context.Context) (CurationTriggerResponse, *APIError)
CurationTrigger asks the runner to start a cycle. Returns triggered=false (not an error) when a cycle is already in flight.
func (*API) DeleteRecord ¶
func (a *API) DeleteRecord(ctx context.Context, req DeleteRecordRequest) (DeleteRecordResponse, *APIError)
DeleteRecord sets processing_status to "deleted" and timestamps the delete. Caller can still inspect the record; search deprioritizes deleted records by default.
func (*API) Diff ¶
func (a *API) Diff(ctx context.Context, req DiffRequest) (DiffResponse, *APIError)
Diff computes added/modified/removed records between two commits identified by since and until. When since is empty, diffs against the chain root (full history). When until is empty, diffs up to HEAD. When since is provided but no commit before it exists (newer store), returns empty buckets rather than an error; same for until set to a date before the earliest indexed commit.
func (*API) Duplicates ¶
func (a *API) Duplicates(ctx context.Context, req DuplicatesRequest) (DuplicatesResponse, *APIError)
Duplicates runs FindDuplicates with the given threshold/cap.
func (*API) Engine ¶
Engine returns the underlying engine. Exposed for transport-layer wiring that needs direct access (e.g. MCP request bindings that want to acquire engine locks around registered tool metadata). Prefer calling API methods over reaching through this accessor.
func (*API) Explore ¶
func (a *API) Explore(ctx context.Context, req ExploreRequest) (ExploreResponse, *APIError)
Explore runs a bounded BFS from NodeID. MaxNodes caps the returned subgraph; the response reports Truncated=true when the cap fires so callers know the result is incomplete.
func (*API) History ¶
func (a *API) History(ctx context.Context, req HistoryRequest) (HistoryResponse, *APIError)
History walks the commit chain back from HEAD looking for commits where the record's serialized property hash changed. Without Since/Until, traversal is capped at MaxLogTraversal to bound the read-lock hold. With Since/Until, the walk narrows via the D7 timestamp index: start from CommitAt(Until) (default HEAD), stop when a commit's timestamp falls before Since. Date-bounded walks bypass the traversal cap -- the range itself bounds the work.
RC-4: a record that's deleted and later recreated should surface the recreation as a first-appearance, not a spurious modification against the pre-deletion hash. Reset prevHash on found=false so the not-found gap breaks the comparison chain cleanly.
func (*API) Inspect ¶
func (a *API) Inspect(ctx context.Context, req InspectRequest) (InspectResponse, *APIError)
Inspect returns a record with its properties, metadata summary, and related edges. Records access and spreads activation (D14). When IncludeContent is false, content_full is omitted from the properties map. Lazily loads the node from storage if not cached.
func (*API) JobsList ¶
func (a *API) JobsList(ctx context.Context, req JobsListRequest) (JobsListResponse, *APIError)
JobsList enumerates JobStore entries with the supplied filter, scoped to the caller's tenant. Cross-tenant rows never leak: the JobStore filter pins TenantID to the value derived from context.
func (*API) Link ¶
func (a *API) Link(ctx context.Context, req LinkRequest) (LinkResponse, *APIError)
Link adds an edge between two records. Returns ErrNotFound if either endpoint doesn't exist; ErrInvalid for bad weight or overlong type.
func (*API) Log ¶
func (a *API) Log(ctx context.Context, req LogRequest) (LogResponse, *APIError)
Log walks the commit chain back from HEAD under a read lock. By default, capped at MaxLogLimit entries and never traverses past the chain root. When Since/Until are set, the walk is narrowed via the D7 timestamp index: start from CommitAt(Until) (default HEAD), stop when a commit's timestamp falls before Since. Date-bounded walks bypass MaxLogTraversal because the range itself bounds the work.
Phase 8 adds three filters + an enrichment flag: Actions filters by CommitAction.Kind (D3), ExcludeCuration filters by Message prefix so it works against pre-D3 commits, and IncludeRecordMutations adds per-record mutation summaries inline.
func (*API) Logger ¶
Logger returns the API's logger. Transports should use this for anything emitted under the api component namespace.
func (*API) Pending ¶
func (a *API) Pending(ctx context.Context, req PendingRequest) (PendingResponse, *APIError)
Pending returns records that have been captured but not yet classified. Ordering is index-walk order (not time-based) so agents that classify-and-move cover the set over multiple calls.
func (*API) Reembed ¶
func (a *API) Reembed(ctx context.Context, req ReembedRequest) (ReembedResponse, *APIError)
Reembed regenerates embeddings for records whose stored embedding_model differs from the current embedder, or whose content_short embedding is missing. Three-phase to avoid holding the engine lock during embedding I/O:
- RLock: identify candidates and gather embedding source texts.
- (no lock): run the embedder; on context-length errors, retry each text individually with halving truncation.
- Lock: apply vectors and persist.
func (*API) Resolve ¶
func (a *API) Resolve(ctx context.Context, req ResolveRequest) (ResolveResponse, *APIError)
Resolve marks a record and auto-sets valid_until so search deprioritizes the record going forward. Repeated calls with different resolutions overwrite; resolution_note is set only when provided.
When the record is a collection item, also flips the collection's `status` enum field (when present) to a closed-equivalent value. See inferClosedStatus for the heuristic.
func (*API) Runner ¶
Runner returns the curation runner. Exposed for transports that need to trigger or inspect curation state directly.
func (*API) Search ¶
func (a *API) Search(ctx context.Context, req SearchRequest) (SearchResponse, *APIError)
Search executes a hybrid BM25 + vector query. Pre-embeds query text outside the read lock, runs the search under RLock, then records access under Lock so retrieval metadata is kept fresh. Retrieved IDs are tracked so the observe pipeline can skip re-extracting content we just surfaced to the agent.
Pagination: a fresh call materializes up to cfg.Search.Pagination. CandidateCap ranked candidates into a snapshot keyed by a ULID query_id, slices the first PageSize for the response, and emits a page table covering the snapshot. A subsequent call with the same Cursor (from any PageRef.Cursor or NextCursor) slices the same snapshot at the encoded boundaries; record content is fetched fresh per page so modifications surface immediately while the match set stays stable for the snapshot's TTL.
func (*API) SessionArchive ¶
func (a *API) SessionArchive(ctx context.Context, sessionID string, sourcePath string) (map[string]any, *APIError)
SessionArchive compresses a conversation transcript and stores it as a gzip file referenced from the Session node. The archive is NOT indexed or searchable -- it's a break-glass backup of the raw conversation.
func (*API) SessionCommit ¶
func (a *API) SessionCommit(ctx context.Context, sessionID string, segments []CommitSegment) (SessionCommitResponse, *APIError)
SessionCommit appends extracted segments to the session. Validates that prepare was called first. Creates new topics as needed. Phase 2: stores in Session only (no Memory records, no embedding).
func (*API) SessionGet ¶
SessionGet returns the full state of a Session.
func (*API) SessionPrepare ¶
SessionPrepare returns extraction instructions and current session state. Sets an in-memory prepared flag so commit can validate the two-phase flow.
func (*API) SessionStart ¶
func (a *API) SessionStart(ctx context.Context, clientSessionID string, source string) (map[string]any, *APIError)
SessionStart creates a new Session, chains to previous sessions on resume, or returns the current session for idempotent agent calls.
source="startup": fresh session, no chaining source="resume": new session chained to latest with same client_session_id source="" (agent call): return existing if found, create fresh otherwise
func (*API) SetBackupSnapshotHook ¶
func (a *API) SetBackupSnapshotHook(ch chan struct{})
SetBackupSnapshotHook installs a channel that BackupCreate closes after phase-1 snapshot returns. Tests use this to race a concurrent capture in between snapshot and compression with no timing assumptions. Pass nil to clear.
func (*API) SetChunkSizeForTests ¶
SetChunkSizeForTests overrides the chunked async runner's chunk size so tests can exercise multi-chunk behavior without seeding 1000+ items. Pass 0 to clear (production behavior: MaxSyncBatchSize). Production must never set this; in-package tests only.
func (*API) SetFaultInjector ¶
func (a *API) SetFaultInjector(fi FaultInjector)
SetFaultInjector installs the FaultInjector consulted at named phases of long-running operations. Pass nil to clear. Production must never set this; in-package tests only.
func (*API) SetRunner ¶
SetRunner installs the curation runner after construction. The runner is created later in the server lifecycle (after New returns) so it can't be passed via Dependencies at construction time; this setter bridges that gap. Safe to call once before any session or curation operations are invoked.
func (*API) ShutdownAsync ¶
ShutdownAsync prevents new async runners from spawning, cancels every in-flight runner's context, and waits for all of them to exit (or until ctx.Done()). Call this before closing the engine so runners don't touch a closed bbolt handle.
func (*API) StartPreparedSweeper ¶
func (a *API) StartPreparedSweeper()
StartPreparedSweeper launches the background sweeper goroutine and stores its cancel function for shutdown. Idempotent -- if a sweeper is already running, return without starting a second one. A server with multiple entry points (Serve, StartHTTP) could otherwise leak goroutines with every additional start.
func (*API) Stats ¶
func (a *API) Stats(ctx context.Context) (StatsResponse, *APIError)
Stats iterates the graph under a read lock and counts records by key metadata fields. Excludes chunk nodes and deleted records.
func (*API) Status ¶
func (a *API) Status(ctx context.Context, _ StatusRequest) (StatusResponse, *APIError)
Status returns liveness-adjacent counters. Light enough to call every few seconds from a dashboard.
func (*API) StopPreparedSweeper ¶
func (a *API) StopPreparedSweeper()
StopPreparedSweeper cancels the sweeper goroutine started by StartPreparedSweeper. Safe to call even if the sweeper never started (no-op).
func (*API) Unlink ¶
func (a *API) Unlink(ctx context.Context, req UnlinkRequest) (UnlinkResponse, *APIError)
Unlink removes an edge. Returns ErrNotFound if the edge doesn't exist.
func (*API) Update ¶
func (a *API) Update(ctx context.Context, req UpdateRequest) (UpdateResponse, *APIError)
Update sets metadata fields on an existing record. Empty / nil fields leave the existing property unchanged. Setting valid_until to "clear" removes the valid_until + resolution + resolved_at triple (undoes supersession or resolution). Returns ErrInvalid for any unknown enum value or out-of-range numeric. Refuses to update Session segments (append-only per D19).
func (*API) UsageTracker ¶
func (a *API) UsageTracker() *llm.UsageTracker
UsageTracker returns the LLM usage tracker. Exposed for transports that need to surface cost information outside of a specific operation call (e.g. /v1/llm/stats).
type APIError ¶
type APIError struct {
Code string // stable, machine-readable (e.g. "not_found", "input_error")
Message string // human-readable; safe to show end-users
HTTPStatus int // maps directly to HTTP response status
Retryable bool // true when the caller can retry without changing the request
Cause error // optional underlying error for errors.Is/As chaining (never serialized)
}
APIError is the canonical error type returned by every api method. Preserving the structured fields (vs. plain error wrapping) lets transports format the same error consistently:
- HTTP writes Code/Message/Retryable into the error envelope at HTTPStatus
- MCP emits the message with a structured error return
- CLI surfaces Code/Message
Methods return (Response, *APIError); nil means success. Do not return a non-nil APIError alongside a partial Response -- callers should assume a non-nil APIError means the operation did not commit.
func ErrConflict ¶
ErrConflict signals a precondition that prevents the write (e.g. duplicate detected, record in wrong state). 409. Not retryable without a behavior change from the caller.
func ErrForbidden ¶
ErrForbidden signals an operation not permitted for this caller/surface (e.g. loopback-only endpoint called from a non-loopback origin). 403.
func ErrInternal ¶
ErrInternal signals an unexpected failure that the caller cannot fix. 500, retryable (the transient cases are the common ones).
func ErrInvalid ¶
ErrInvalid signals a field has the wrong shape/value. 400, retryable once the caller fixes the value.
func ErrMissing ¶
ErrMissing signals a required field is empty. 400, retryable once the caller includes the field.
func ErrNotFound ¶
ErrNotFound signals the target resource does not exist. 404. Not retryable -- the caller should not keep asking.
func ErrPrepareRequired ¶
ErrPrepareRequired signals that gramaton_session_commit was called without a prior gramaton_session_prepare. 409 because the server is in a wrong-state rather than the request being malformed; retryable after the caller prepares.
func ErrUnavailable ¶
ErrUnavailable signals that an operation cannot proceed because a required dependency is not configured (e.g. curation runner is off, LLM provider is missing, no embedder). 503 because the server is healthy but the feature is not. Not retryable: the caller cannot fix this without an operator changing config.
func (*APIError) Error ¶
Error makes APIError satisfy the error interface for callers that want to treat it as one. Transports typically do not use this; they read the fields directly.
type BackupCreateResponse ¶
type BackupInfo ¶
type BackupInfo struct {
Path string `json:"path"`
SizeBytes int64 `json:"size_bytes"`
Created string `json:"created"`
}
BackupInfo describes one archive found in the backup directory.
type BackupStatusResponse ¶
type BackupStatusResponse struct {
BackupDir string `json:"backup_dir"`
Backups []BackupInfo `json:"backups"`
Count int `json:"count"`
}
type BatchAddFailure ¶
type BatchAddFailure struct {
Index int `json:"index"`
ClientRef string `json:"client_ref,omitempty"`
Code string `json:"code"`
Message string `json:"message"`
}
BatchAddFailure is one entry in CollectionAddBatchResponse.Failed. Code matches the APIError codes ("input_error", "duplicate", etc.).
type BatchAddSuccess ¶
type BatchAddSuccess struct {
Index int `json:"index"`
ClientRef string `json:"client_ref,omitempty"`
ID string `json:"id"`
Deduplicated bool `json:"deduplicated,omitempty"`
}
BatchAddSuccess is one entry in CollectionAddBatchResponse.Added. Deduplicated=true means the item's title already existed on a curation=none collection and ID points to the pre-existing item; the batch did not create a new node for this entry. This mirrors single-add's idempotent-return shape so callers don't need to branch on batch vs. single for the same collection profile.
type BatchItemFailure ¶
type BatchItemFailure struct {
Index int `json:"index"`
ClientRef string `json:"client_ref,omitempty"`
Code string `json:"code"`
Message string `json:"message"`
}
BatchItemFailure describes one item that did NOT commit. Index maps back to the original Items slice; ClientRef is echoed when the caller supplied one. Code is a stable machine-readable token; Message is human-readable. Distinct from api.ItemFailure (which uses ItemID for pre-existing record references in SessionCommit/CollectionMigrate).
type BranchCheckoutResponse ¶
type BranchCreateRequest ¶
type BranchCreateRequest struct {
Name string `json:"name" jsonschema:"branch name (see ValidBranchName)"`
}
type BranchCreateResponse ¶
type BranchDiscardResponse ¶
type BranchDiscardResponse struct {
Discarded string `json:"discarded"`
}
type BranchEntry ¶
type BranchEntry struct {
Name string `json:"name"`
Commit string `json:"commit"`
Active bool `json:"active,omitempty"`
}
BranchEntry is one branch in a list response. Hash is truncated for display consistency with gramaton_log.
type BranchListResponse ¶
type BranchListResponse struct {
Branches []BranchEntry `json:"branches"`
Current string `json:"current"`
}
type BranchMergeResponse ¶
type CaptureBatchAdded ¶
type CaptureBatchAdded struct {
ID string `json:"id"`
ClientRef string `json:"client_ref,omitempty"`
Warnings []string `json:"warnings,omitempty"`
Superseded []SupersededRecord `json:"superseded,omitempty"`
}
CaptureBatchAdded describes one record that the batch successfully committed. ClientRef is echoed back when the request supplied one. Warnings collect non-fatal events (embed fallback, internal supersession, etc.) per item.
type CaptureBatchCancelRequest ¶
type CaptureBatchCancelRequest struct {
JobID string `json:"job_id" jsonschema:"the job_id returned by gramaton_capture_batch"`
}
CaptureBatchCancelRequest selects a job by ID.
type CaptureBatchCancelResponse ¶
type CaptureBatchCancelResponse struct {
JobID string `json:"job_id"`
Status string `json:"status"`
Cancelled bool `json:"cancelled"`
}
CaptureBatchCancelResponse echoes the post-cancel terminal state. If the job was already terminal (completed/failed/cancelled), the call is a no-op and Status reflects the prior terminal value; Cancelled is true only when this call moved the state.
type CaptureBatchItem ¶
type CaptureBatchItem struct {
CaptureRequest
ClientRef string `` /* 203-byte string literal not displayed */
}
CaptureBatchItem is one record in a CaptureBatchRequest. Embeds the existing single-capture shape to keep field semantics identical and adds a per-item ClientRef the caller can use to wire intra-batch edges (Layer 4).
type CaptureBatchRequest ¶
type CaptureBatchRequest struct {
Items []CaptureBatchItem `` /* 135-byte string literal not displayed */
Edges []EdgeSpec `` /* 196-byte string literal not displayed */
Wait *bool `` /* 181-byte string literal not displayed */
ClientToken string `` /* 164-byte string literal not displayed */
SkipSupersession bool `` /* 141-byte string literal not displayed */
}
CaptureBatchRequest captures up to MaxSyncBatchSize records in a single call. Items follow the same shape as CaptureRequest with an optional ClientRef for in-batch identity.
Layer 3 honors only the synchronous path; passing Wait=false returns ErrInvalid until Layer 5 wires the async runner. ClientToken + canonicalized RequestHash provide cross-call idempotency.
type CaptureBatchResponse ¶
type CaptureBatchResponse struct {
JobID string `json:"job_id"`
Status string `json:"status"`
Added []CaptureBatchAdded `json:"added,omitempty"`
Failed []BatchItemFailure `json:"failed,omitempty"`
Edges []EdgeAdded `json:"edges,omitempty"`
EdgesFailed []EdgeFailure `json:"edges_failed,omitempty"`
Stats CaptureBatchStats `json:"stats"`
Warnings []string `json:"warnings,omitempty"`
}
CaptureBatchResponse is the canonical output of CaptureBatch. Sync mode populates Added/Failed/Stats inline; async mode (Layer 5) fills JobID + Status only and the caller polls.
type CaptureBatchResultRequest ¶
type CaptureBatchResultRequest struct {
JobID string `json:"job_id" jsonschema:"the job_id returned by gramaton_capture_batch"`
TimeoutMS int `` /* 151-byte string literal not displayed */
}
CaptureBatchResultRequest selects a job by ID with an optional timeout. TimeoutMS=0 falls back to cfg.Jobs.ResultDefaultTimeout (30 minutes) so a caller doesn't accidentally hang forever on a stuck job.
type CaptureBatchStats ¶
type CaptureBatchStats struct {
TotalItems int `json:"total_items"`
AddedCount int `json:"added_count"`
FailedCount int `json:"failed_count"`
SupersededCount int `json:"superseded_count"`
EdgesAdded int `json:"edges_added,omitempty"`
EdgesFailed int `json:"edges_failed,omitempty"`
}
CaptureBatchStats summarizes the outcome counts. Always populated (zero values when nothing happened).
type CaptureBatchStatusRequest ¶
type CaptureBatchStatusRequest struct {
JobID string `json:"job_id" jsonschema:"the job_id returned by gramaton_capture_batch"`
}
CaptureBatchStatusRequest selects a job by ID for a status read.
type CaptureBatchStatusResponse ¶
type CaptureBatchStatusResponse struct {
JobID string `json:"job_id"`
Status string `json:"status"`
Kind string `json:"kind"`
TotalItems int `json:"total_items"`
ProcessedCount int `json:"processed_count"`
FailureReason string `json:"failure_reason,omitempty"`
Errors []BatchItemFailure `json:"errors,omitempty"`
ClientRefToID map[string]string `json:"client_ref_to_id,omitempty"`
ClientToken string `json:"client_token,omitempty"`
}
CaptureBatchStatusResponse is the live snapshot of a Job. Errors[] surfaces per-item failures collected so far so a caller can correct inputs and retry without waiting for the run to finish. ClientRefToID maps caller-supplied refs to assigned ULIDs; with failed runs it lets a caller resume edge creation via gramaton_link.
type CaptureRequest ¶
type CaptureRequest struct {
Content string `json:"content" jsonschema:"the knowledge to store (required)"`
Temporality string `json:"temporality,omitempty" jsonschema:"immutable|durable|temporal|ephemeral"`
Confidence *float64 `json:"confidence,omitempty" jsonschema:"number between 0.0 and 1.0"`
KnowledgeType string `json:"knowledge_type,omitempty" jsonschema:"episodic|semantic|procedural|conceptual|reference"`
EpistemicStatus string `json:"epistemic_status,omitempty" jsonschema:"well_established|probable|speculative|contested|refuted"`
Importance *float64 `json:"importance,omitempty" jsonschema:"number between 0.0 and 1.0"`
Keywords []string `json:"keywords,omitempty" jsonschema:"array of keyword strings for search"`
SummaryShort string `json:"summary_short,omitempty" jsonschema:"~750 chars (semantic anchor for embedding)"`
SourceRef string `json:"source_ref,omitempty" jsonschema:"source URL or path"`
SourceCredibility *float64 `json:"source_credibility,omitempty" jsonschema:"number between 0.0 and 1.0"`
TestimonyHops *int64 `` /* 152-byte string literal not displayed */
ContextAbout string `json:"context_about,omitempty" jsonschema:"topic/domain"`
ContextWho string `json:"context_who,omitempty" jsonschema:"entities involved"`
ContextPrompted string `json:"context_prompted,omitempty" jsonschema:"what prompted this capture"`
ContextFindable string `json:"context_findable_by,omitempty" jsonschema:"future retrieval terms"`
ContextRelated string `json:"context_related,omitempty" jsonschema:"related concepts or records"`
ContextSourceType string `` /* 142-byte string literal not displayed */
ContextTimeSensitivity string `` /* 133-byte string literal not displayed */
ContextReliability string `json:"context_reliability,omitempty" jsonschema:"reliability signals (e.g. peer-reviewed, unverified, first-hand experience)"`
ContextCaptureReason string `` /* 134-byte string literal not displayed */
ValidFrom string `json:"valid_from,omitempty" jsonschema:"RFC3339; optional lower lifecycle bound"`
ValidUntil string `json:"valid_until,omitempty" jsonschema:"RFC3339; optional expiration"`
AssertedAsOf string `` /* 135-byte string literal not displayed */
Meta map[string]any `` /* 183-byte string literal not displayed */
}
CaptureRequest is the canonical input to the capture operation. Every transport (HTTP, MCP, CLI proxy) uses this struct directly -- there is no per-transport copy to drift from.
json tags are the HTTP wire format. jsonschema tags surface as MCP tool descriptions (the MCP SDK reads them via reflection when the struct is passed as a tool args type).
type CaptureResponse ¶
type CaptureResponse struct {
ID string `json:"id"`
Warnings []string `json:"warnings,omitempty"`
Superseded []SupersededRecord `json:"superseded,omitempty"`
}
CaptureResponse is the canonical output of the capture operation. Omitted fields use json:",omitempty" so the wire format stays tight on the happy path (no warnings, no supersession).
type ClassifyRequest ¶
type ClassifyRequest struct {
ID string `json:"-" jsonschema:"-"`
Temporality string `json:"temporality,omitempty" jsonschema:"immutable|durable|temporal|ephemeral"`
Confidence *float64 `json:"confidence,omitempty" jsonschema:"number between 0.0 and 1.0"`
KnowledgeType string `json:"knowledge_type,omitempty" jsonschema:"episodic|semantic|procedural|conceptual|reference"`
EpistemicStatus string `json:"epistemic_status,omitempty" jsonschema:"well_established|probable|speculative|contested|refuted"`
Importance *float64 `json:"importance,omitempty" jsonschema:"number between 0.0 and 1.0"`
Keywords []string `json:"keywords,omitempty" jsonschema:"array of keyword strings"`
SummaryShort string `json:"summary_short,omitempty" jsonschema:"~750 chars (semantic anchor for embedding)"`
}
ClassifyRequest carries the metadata fields to apply when promoting a pending record to processed. ID is transport-set.
type ClassifyResponse ¶
ClassifyResponse confirms the record was promoted.
type ClearMode ¶
type ClearMode string
ClearMode controls what happens when a collection is cleared (e.g. via a future `gramaton collection clear` or the resolve path on bulk operations).
resolve (default) -- item records get resolution="completed"
and valid_until set to the clear time.
Historical purchase queries keep working.
unlink -- remove the member_of edge at HEAD; the
item record persists and can be re-linked.
func CollectionClearMode ¶
CollectionClearMode returns the collection's clear_mode config, falling back to DefaultClearMode when the property is absent or holds an empty string.
type CollectionAddBatchRequest ¶
type CollectionAddBatchRequest struct {
Items []CollectionAddItem `json:"items" jsonschema:"array of items to add (max 500)"`
}
type CollectionAddBatchResponse ¶
type CollectionAddBatchResponse struct {
CollectionID string `json:"collection_id"`
Added []BatchAddSuccess `json:"added"`
Failed []BatchAddFailure `json:"failed"`
}
type CollectionAddItem ¶
type CollectionAddItem struct {
Fields map[string]any `json:"fields" jsonschema:"item fields (must match collection schema if defined)"`
ClientRef string `json:"client_ref,omitempty" jsonschema:"optional caller handle echoed in the per-item result"`
}
CollectionAddItem is one item inside a CollectionAddBatchRequest. The optional ClientRef is echoed back in the per-item result so callers can correlate outcomes with their own records without relying on positional order.
type CollectionAddRequest ¶
type CollectionAddResponse ¶
type CollectionAddResponse struct {
ID string `json:"id"`
CollectionID string `json:"collection_id"`
Deduplicated bool `json:"deduplicated,omitempty"`
}
CollectionAddResponse covers both the normal-add and the minimal-curation idempotent-dedup branches. Deduplicated is true when the item's title already existed on a curation=minimal collection; the ID points at the pre-existing item (no new node created).
type CollectionCreateRequest ¶
type CollectionCreateRequest struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Schema *CollectionSchema `json:"schema,omitempty"`
// Behaviour knobs. All optional -- absent means "use the default",
// via the read-time fallback in collection_config.go. Passing an
// explicit value stores it on the collection node so future reads
// surface it without the fallback (useful for visibility).
ClearMode string `json:"clear_mode,omitempty"`
Supersession string `json:"supersession,omitempty"`
Curation string `json:"curation,omitempty"`
Contradictions string `json:"contradictions,omitempty"`
// Template names a pre-built Collection shape. Valid names are
// exposed via api.ListTemplates; ships with backlog / todo /
// reading-list / shopping-list / packing-list / journal /
// references. When set, the template's schema + behaviour fields
// populate any caller fields that are left empty. Caller-provided
// fields always win (shallow merge).
Template string `json:"template,omitempty"`
}
type CollectionCreateResponse ¶
CollectionCreateResponse: {id, name}.
type CollectionDeleteResponse ¶
type CollectionDeleteResponse struct {
ID string `json:"id"`
Retired bool `json:"retired,omitempty"`
Unretired bool `json:"unretired,omitempty"`
ItemsPreserved int `json:"items_preserved,omitempty"`
}
CollectionDeleteResponse covers both the retire and unretire branches. Exactly one of Retired / Unretired is true. ItemsPreserved is set only on the retire branch (count of items left intact under the retired collection).
type CollectionItem ¶
type CollectionItem struct {
ID string `json:"id"`
CreatedAt string `json:"created_at,omitempty"`
Fields map[string]any `json:"fields,omitempty"`
NeedsMigration []string `json:"needs_migration,omitempty"`
}
CollectionItem is one row in CollectionItemsResponse.Items. Fields is dynamic (collection-schema-driven, optionally projected); typing it as map[string]any preserves wire shape and avoids per-schema codegen.
type CollectionItemsRequest ¶
type CollectionItemsRequest struct {
Sort string `json:"sort,omitempty"`
Order string `json:"order,omitempty"`
IncludeRetired bool `json:"include_retired,omitempty"`
// Fields is a allowlist of schema field names to include in each
// item's `fields` sub-map. Empty/nil means return every field
// (today's behavior). `id`, `created_at`, and `needs_migration`
// are always included at the top level regardless of this list.
Fields []string `json:"fields,omitempty"`
// Filter is a schema-field -> expected-value(s) map that keeps an
// item only when every listed field matches. Values may be a
// single string for exact match, or a []string / []any of strings
// for "any-of" match (OR within a field, AND across fields).
// Unknown field names match nothing (empty result). Filtering
// preserves the exhaustive-retrieval contract because matches are
// exact, not ranked.
Filter map[string]any `json:"filter,omitempty"`
// Match is a literal substring search across the item's string
// fields (case-insensitive). Use to narrow within an exhaustive
// collection list (e.g. "all open backlog items mentioning
// 'auth'" via filter={"status":"open"} + match="auth"). Distinct
// from Filter which is exact-match: Match scans every field.*
// string property for the substring. Mirrors SearchRequest.Match
// semantics but scoped to a single collection.
Match string `json:"match,omitempty"`
// AsOf, when set, returns point-in-time membership: the members
// that had `member_of` edges to the collection at the commit
// immediately before AsOf, with each member's state at that
// commit. Response carries `as_of` + `semantics: "point_in_time"`
// so agents don't have to guess. Accepts YYYY-MM-DD or RFC3339.
// Future dates are rejected. The filter/sort/projection knobs
// still apply, but migration accounting is skipped (historical
// snapshots are read-only).
AsOf string `json:"as_of,omitempty"`
}
type CollectionItemsResponse ¶
type CollectionItemsResponse struct {
CollectionID string `json:"collection_id"`
Items []CollectionItem `json:"items"`
Count int `json:"count"`
Migration *CollectionMigrationState `json:"migration,omitempty"`
AsOf string `json:"as_of,omitempty"`
Semantics string `json:"semantics,omitempty"`
}
CollectionItemsResponse covers both the live (HEAD) read and the point-in-time (as_of) branch. AsOf + Semantics are emitted only on the point-in-time branch.
type CollectionListEntry ¶
type CollectionListEntry struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
HasSchema bool `json:"has_schema,omitempty"`
ItemCount int `json:"item_count"`
Retired bool `json:"retired,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
}
CollectionListEntry is one row in CollectionListResponse.Collections. Description / HasSchema / Retired / CreatedAt are optional and are emitted only when present on the underlying node.
type CollectionListRequest ¶
type CollectionListResponse ¶
type CollectionListResponse struct {
Collections []CollectionListEntry `json:"collections"`
Showing int `json:"showing"`
Total int `json:"total"`
HasMore bool `json:"has_more,omitempty"`
NextOffset int `json:"next_offset,omitempty"`
}
CollectionListResponse pagination matches the original map shape: HasMore + NextOffset are emitted only when a next page exists.
type CollectionMigrateResponse ¶
type CollectionMigrateResponse struct {
Migrated int `json:"migrated"`
Field string `json:"field"`
MigrationComplete bool `json:"migration_complete"`
Failed []ItemFailure `json:"failed,omitempty"`
}
CollectionMigrateResponse: {migrated, field, migration_complete, failed?}.
Failed is the per-item failure list (P3-B). Today the migration loop has no per-item failure path -- the only loop branch is "node gone between collect and apply" which silently `continue`s -- so Failed is omitempty and currently nil-emitted. The slot is reserved for future partial-success work where caller-recoverable failures (validation drift, contended writes) are recorded alongside the items that did migrate.
type CollectionMigrationState ¶
type CollectionMigrationState struct {
Fields []string `json:"fields"`
Total int64 `json:"total"`
Done int `json:"done,omitempty"`
Remaining int `json:"remaining,omitempty"`
Message string `json:"message,omitempty"`
}
CollectionMigrationState describes an in-progress schema migration. Returned inside CollectionItemsResponse, CollectionSchemaReadResponse, and CollectionSchemaUpdateResponse. Done/Remaining are only populated by CollectionItems (computed over the live member set); Message is only set by CollectionSchemaUpdate.
type CollectionMoveRequest ¶
type CollectionMoveRequest struct {
TargetCollectionID string `json:"target_collection_id"`
}
type CollectionMoveResponse ¶
type CollectionMoveResponse struct {
Moved bool `json:"moved"`
ItemID string `json:"item_id"`
FromCollectionID string `json:"from_collection_id"`
ToCollectionID string `json:"to_collection_id"`
}
CollectionMoveResponse: {moved, item_id, from/to_collection_id}.
type CollectionRemoveResponse ¶
type CollectionRemoveResponse struct {
Removed bool `json:"removed"`
ItemID string `json:"item_id"`
CollectionID string `json:"collection_id"`
}
CollectionRemoveResponse: {removed, item_id, collection_id}.
type CollectionRenameRequest ¶
type CollectionRenameRequest struct {
Name string `json:"name"`
}
type CollectionRenameResponse ¶
type CollectionRenameResponse struct {
Renamed bool `json:"renamed"`
ID string `json:"id"`
Name string `json:"name"`
}
CollectionRenameResponse: {renamed, id, name}.
type CollectionSchema ¶
type CollectionSchema struct {
Fields []SchemaField `json:"fields"`
ContentFields []string `json:"content_fields,omitempty" yaml:"content_fields,omitempty"`
}
CollectionSchema defines what fields items in a collection must/may have.
ContentFields is an ordered list of field names whose values constitute the canonical text representation of an item for LLM-stage curation (classify, summarize, contradictions, concept synthesis) and for embedding. Each name must reference a declared field of type=string. When unset, items in this collection use a schemaless wide concatenation of every field.* string property (acceptable for curation=none collections; rejected at create time for curation=standard collections lacking a template).
type CollectionSchemaReadResponse ¶
type CollectionSchemaReadResponse struct {
CollectionID string `json:"collection_id"`
Schema *CollectionSchema `json:"schema,omitempty"`
Migration *CollectionMigrationState `json:"migration,omitempty"`
}
CollectionSchemaReadResponse: {collection_id, schema?, migration?}.
type CollectionSchemaUpdateRequest ¶
type CollectionSchemaUpdateRequest struct {
Schema CollectionSchema `json:"schema"`
}
type CollectionSchemaUpdateResponse ¶
type CollectionSchemaUpdateResponse struct {
Updated bool `json:"updated"`
CollectionID string `json:"collection_id"`
Migration *CollectionMigrationState `json:"migration,omitempty"`
}
CollectionSchemaUpdateResponse: {updated, collection_id, migration?}.
type CollectionUpdateRequest ¶
type CollectionUpdateResponse ¶
type CollectionUpdateResponse struct {
Updated bool `json:"updated"`
ItemID string `json:"item_id"`
}
CollectionUpdateResponse: {updated, item_id}.
type CommitSegment ¶
type CommitSegment struct {
Content string `json:"content"`
TopicName string `json:"topic"`
Temporality string `json:"temporality,omitempty"`
Confidence *float64 `json:"confidence,omitempty"`
KnowledgeType string `json:"knowledge_type,omitempty"`
EpistemicStatus string `json:"epistemic_status,omitempty"`
Keywords []string `json:"keywords,omitempty"`
SummaryShort string `json:"summary_short,omitempty"`
PromoteToMemory *bool `json:"promote_to_memory,omitempty"`
}
CommitSegment is a single segment submitted via session_commit.
PromoteToMemory implements the two-tier extraction model: when true (or unset), the segment becomes both a Session segment (BM25-indexed) and a Memory record (vector + BM25 indexed, full epistemic metadata, auto-supersession). When false, only the Session segment is created -- BM25-searchable but not vector-embedded, no Memory record, no extracted_as edge. Use false for exploration, dead ends, open questions, and other "valuable context" content that shouldn't pollute the Memory store's vector space.
type ConfidenceDist ¶
type ConfidenceDist struct {
High int `json:"high"` // >= 0.9
Medium int `json:"medium"` // 0.7-0.9
Moderate int `json:"moderate"` // 0.4-0.7
Low int `json:"low"` // < 0.4
Unset int `json:"unset"`
}
ConfidenceDist groups records into confidence bands for summary.
type Contradictions ¶
type Contradictions string
Contradictions controls whether the system generates contradicts edges between records in this collection and other records. The stage is LLM-driven, so off saves cost on collections where pairwise contradiction detection is meaningless (journal entries, bookmarks, recipe collections).
on (default) -- contradictions stage runs against records here. off -- contradictions stage skipped.
const ( ContradictionsOn Contradictions = "on" ContradictionsOff Contradictions = "off" )
func CollectionContradictions ¶
func CollectionContradictions(n *graph.Node) Contradictions
CollectionContradictions returns the collection's contradictions config, falling back to DefaultContradictions when absent.
type Curation ¶
type Curation string
Curation controls per-collection LLM-analysis intensity. Each pipeline stage that consults this knob (classify, summarize, observation_extract, concept synthesis) runs only when the effective value resolves to standard.
standard (default) -- LLM analysis runs.
none -- no LLM analysis runs. Records still get
embedded for vector search; supersession
and contradictions are governed by their
own knobs.
Legacy values "minimal" and "full" are normalized on read -- minimal -> none, full -> standard -- so existing collections keep working without a migration sweep. Writes reject the legacy values.
func CollectionCuration ¶
CollectionCuration returns the collection's curation profile, falling back to DefaultCuration when absent. Legacy values from the pre-redesign 4-level enum are normalized on read so existing stores keep working without a migration sweep.
type CurationBatchResponse ¶
type CurationBatchResponse struct {
Result *curation.BatchResult `json:"result"`
}
CurationBatchResponse wraps the BatchResult from the curation package so transport callers see the same shape regardless of surface.
type CurationDrainResponse ¶
type CurationDrainResponse struct {
Result *curation.DrainResult `json:"result"`
}
CurationDrainResponse reports the outcome of an artificial drain of the contradiction-detection candidate pool. See CurationDrainContradictions for the safety tradeoffs.
type CurationDryRunResponse ¶
type CurationDryRunResponse struct {
DryRun bool `json:"dry_run"`
PlannedChanges []curation.PlannedChange `json:"planned_changes"`
Classified int `json:"classified"`
Summaries int `json:"summaries"`
LLMCalls int `json:"llm_calls"`
Errors int `json:"errors"`
Status curation.EnhancedStatus `json:"status"`
}
CurationDryRunResponse mirrors the trigger response but reports what the autonomous pipeline *would* have changed instead of applying the changes. Deterministic curation still ran (it is always safe).
type CurationListStuckResponse ¶
type CurationListStuckResponse struct {
Records []StuckRecord `json:"records"`
Counts map[string]int `json:"counts"`
}
CurationListStuckResponse is the read-only stuck-record inventory. Records is the per-record breakdown; Counts is a per-task summary for callers that only need totals.
type CurationResetStuckRequest ¶
type CurationResetStuckRequest struct {
IDs []string `json:"ids,omitempty" jsonschema:"specific record IDs to reset; empty resets all stuck records"`
}
CurationResetStuckRequest selects which stuck records to un-stick. IDs empty = reset every stuck record. IDs non-empty = reset only those records (and only the ones in that set that are actually stuck; non-stuck IDs in the list are silently ignored).
type CurationResetStuckResponse ¶
type CurationResetStuckResponse struct {
Reset int `json:"reset"`
Counts map[string]int `json:"counts"`
}
CurationResetStuckResponse reports how many records were reset and the per-task breakdown. Reset is the total across all tasks.
type CurationStatusResponse ¶
type CurationStatusResponse struct {
Status curation.EnhancedStatus `json:"status"`
Manifest *curation.StoreManifest `json:"manifest,omitempty"`
}
CurationStatusResponse reports the runner's current state plus the most-recent store manifest. Both fields may be nil when the runner has not yet completed its first cycle.
type CurationTriggerResponse ¶
type CurationTriggerResponse struct {
Triggered bool `json:"triggered"`
Message string `json:"message,omitempty"`
Status curation.EnhancedStatus `json:"status"`
}
CurationTriggerResponse reports whether a manual trigger was accepted (false when a cycle was already in progress) and the runner's status after the call.
type DeleteRecordRequest ¶
type DeleteRecordRequest struct {
ID string `json:"-" jsonschema:"-"`
Reason string `json:"reason,omitempty" jsonschema:"why the record is being deleted (stored on the record)"`
}
DeleteRecordRequest soft-deletes a record with an optional reason.
type DeleteRecordResponse ¶
DeleteRecordResponse confirms the soft-delete.
type Dependencies ¶
type Dependencies struct {
Engine *core.Engine
Runner *curation.Runner
UsageTracker *llm.UsageTracker
Log *slog.Logger
ConfigDir string
StoreName string
}
Dependencies holds the collaborators an API needs at construction. Keeping this explicit (rather than letting methods reach into a god-object) makes it obvious what an operation depends on and gives tests a clean surface to stub.
type DiffEntry ¶
type DiffEntry struct {
ID string `json:"id"`
SummaryShort string `json:"summary_short,omitempty"`
}
DiffEntry is one record in the diff. SummaryShort is omitted when the record no longer exists (Removed entries) or has no short.
type DiffRequest ¶
type DiffRequest struct {
Since string `json:"since,omitempty" jsonschema:"show changes after date (YYYY-MM-DD or RFC3339); empty means against chain root"`
Until string `json:"until,omitempty" jsonschema:"show changes up to date (YYYY-MM-DD or RFC3339); empty means up to HEAD"`
Topic string `json:"topic,omitempty" jsonschema:"filter by topic substring (matches content_keywords + content_short, case-insensitive)"`
Limit int `json:"limit,omitempty" jsonschema:"max changes to return (default 50, max 1000)"`
}
DiffRequest carries the diff window + optional topic filter. Since is empty -> diff against the chain root (full history). Until is empty -> diff up to HEAD. Both accept YYYY-MM-DD or RFC3339.
type DiffResponse ¶
type DiffResponse struct {
Added []DiffEntry `json:"added"`
Modified []DiffEntry `json:"modified"`
Removed []DiffEntry `json:"removed"`
Truncated bool `json:"truncated,omitempty"`
Limit int `json:"limit,omitempty"`
}
DiffResponse partitions the changed nodes into added/modified/ removed buckets. Modified means the node ID appeared in both the added and removed sets at the prolly-tree level (content hash changed).
type DuplicatesRequest ¶
type DuplicatesRequest struct {
Threshold float64 `json:"threshold,omitempty" jsonschema:"minimum cosine similarity (default 0.92, must be > 0 and <= 1)"`
MaxPairs int `json:"max_pairs,omitempty" jsonschema:"maximum pair count to return (default 50, max 1000)"`
}
DuplicatesRequest carries the similarity threshold + pair cap.
type DuplicatesResponse ¶
type DuplicatesResponse struct {
Pairs []search.DuplicatePair `json:"pairs"`
Count int `json:"count"`
Truncated bool `json:"truncated,omitempty"`
}
DuplicatesResponse lists duplicate pairs.
type EdgeAdded ¶
type EdgeAdded struct {
Index int `json:"index"`
EdgeID string `json:"edge_id"`
SourceID string `json:"source_id"`
TargetID string `json:"target_id"`
Type string `json:"type"`
Weight float64 `json:"weight"`
}
EdgeAdded describes one edge that was successfully created. Index maps back to the original Edges slice so callers can correlate.
type EdgeFailure ¶
type EdgeFailure struct {
Index int `json:"index"`
Code string `json:"code"`
Message string `json:"message"`
}
EdgeFailure describes one edge that did NOT commit. Code is one of:
- source_item_failed / target_item_failed: the referenced ClientRef points at an item whose Phase 0 validation failed
- source_id_not_found / target_id_not_found: the referenced ID (or ClientRef) doesn't resolve to any record
- self_loop: source and target resolve to the same node
- duplicate_edge: same (source, target, type) tuple appears earlier in the batch
- invalid_type / invalid_weight: per-edge shape rejected
- missing_endpoint: neither id nor client_ref supplied for an endpoint, or both supplied for the same endpoint
type EdgeSpec ¶
type EdgeSpec struct {
SourceID string `json:"source_id,omitempty" jsonschema:"existing record id OR id assigned to a successful batch item"`
SourceClientRef string `json:"source_client_ref,omitempty" jsonschema:"client_ref of a batch item (mutually exclusive with source_id)"`
TargetID string `json:"target_id,omitempty" jsonschema:"existing record id OR id assigned to a successful batch item"`
TargetClientRef string `json:"target_client_ref,omitempty" jsonschema:"client_ref of a batch item (mutually exclusive with target_id)"`
Type string `json:"type" jsonschema:"edge type (e.g. related_to, supports, contradicts)"`
Weight *float64 `json:"weight,omitempty" jsonschema:"0.0-1.0; default 0.5"`
}
EdgeSpec describes a single edge to create alongside the batch's items. Exactly one of (SourceID, SourceClientRef) must be set per endpoint; same for target. ID resolves to an existing record OR a successful item from this batch. ClientRef resolves only to a successful item in this batch.
type ExploreRequest ¶
type ExploreRequest struct {
NodeID string `json:"node_id" jsonschema:"starting record ID"`
Depth int `json:"depth,omitempty" jsonschema:"max traversal depth (default 2, max 10)"`
EdgeTypes []string `json:"edge_types,omitempty" jsonschema:"restrict to these edge types (empty = all)"`
MinWeight float64 `json:"min_weight,omitempty" jsonschema:"drop edges below this weight (default 0.0)"`
MaxNodes int `json:"max_nodes,omitempty" jsonschema:"cap result node count (default 100, max 10000)"`
}
ExploreRequest traverses the graph from a starting node.
type ExploreResponse ¶
type ExploreResponse struct {
Nodes []graph.SubgraphNode `json:"nodes"`
Edges []graph.SubgraphEdge `json:"edges"`
Truncated bool `json:"truncated,omitempty"`
MaxNodes int `json:"max_nodes,omitempty"`
}
ExploreResponse carries the traversal result subgraph.
type ExportRequest ¶
type ExportRequest struct {
Format string `` /* 150-byte string literal not displayed */
// Filter fields. Additive; absent fields mean "no filter on
// this dimension."
Text string `json:"text,omitempty" jsonschema:"vector-similarity query; ranks results by relevance (otherwise sorted by created_at desc)"`
Match string `json:"match,omitempty" jsonschema:"literal substring match across content fields (case-insensitive)"`
Store string `json:"store,omitempty" jsonschema:"memory|sessions|all (default: all)"`
Keywords []string `json:"keywords,omitempty" jsonschema:"keywords that must all be present"`
Temporality string `json:"temporality,omitempty"`
KnowledgeType string `json:"knowledge_type,omitempty"`
EpistemicStatus string `json:"epistemic_status,omitempty"`
Resolution string `json:"resolution,omitempty"`
ProcessingStatus string `json:"processing_status,omitempty"`
Since string `json:"since,omitempty" jsonschema:"YYYY-MM-DD or RFC3339 lower bound on created_at"`
Meta map[string]string `json:"meta,omitempty"`
}
ExportRequest controls a streaming record export. Filter fields mirror SearchRequest's most useful subset; when none are set the request behaves like a full-store dump (legacy compatibility). When any filter is set, only matching records are exported.
The export is exhaustive over the matched set -- there is no candidate_cap or pagination on this path. The CLI is the "give me everything" escape valve from gramaton_search's MCP-side pagination.
type FaultInjector ¶
FaultInjector is the test-only fault-injection seam. Each long-running operation calls Inject at named phases; a non-nil returned error short-circuits the operation along its error path. The interface is exported so external test packages can provide implementations, but the SetFaultInjector setter is intended for in-package tests only.
type HistoryChange ¶
type HistoryChange struct {
Commit string `json:"commit"`
Timestamp string `json:"timestamp"`
Action string `json:"action"`
}
HistoryChange represents a single change event for a record.
type HistoryRequest ¶
type HistoryRequest struct {
ID string `json:"-" jsonschema:"-"`
Limit int `json:"limit,omitempty" jsonschema:"max entries (default 20, max 500)"`
Since string `json:"since,omitempty" jsonschema:"only include changes on or after this date (YYYY-MM-DD or RFC3339)"`
Until string `json:"until,omitempty" jsonschema:"only include changes up to this date (YYYY-MM-DD or RFC3339); empty means up to HEAD"`
}
HistoryRequest returns the per-record change history. ID is transport-set from the URL path. Limit defaults to 20 and is clamped to MaxLogLimit. Since and Until narrow the walk to a date range and bypass MaxLogTraversal when set (the timestamp index gives us O(log N) entry points).
type HistoryResponse ¶
type HistoryResponse struct {
ID string `json:"id"`
Changes []HistoryChange `json:"changes"`
}
HistoryResponse lists the changes in reverse-chronological order (most recent first).
type ImportRequest ¶
type ImportRequest struct {
Records []backup.ExportRecord `json:"records"`
}
type ImportResponse ¶
type InspectRequest ¶
type InspectRequest struct {
ID string `json:"id" jsonschema:"record ID to inspect"`
IncludeContent *bool `json:"include_content,omitempty" jsonschema:"include content_full in response (default true)"`
}
InspectRequest identifies the record to inspect and whether to include the full content in the response.
type InspectResponse ¶
type InspectResponse struct {
ID string `json:"id"`
Properties map[string]any `json:"properties"`
MetadataSummary string `json:"metadata_summary"`
Related []RelatedEdge `json:"related"`
// EffectiveCuration is the resolved per-record curation behaviour
// computed from the node's member_of edges. Tells callers exactly
// what curation work will run on this record (curation, supersession,
// contradictions). Absent on structural/container nodes (collections,
// sessions, topics) and concept-synthesis nodes -- those are not
// records that flow through curation.
EffectiveCuration *curation.EffectiveConfig `json:"effective_curation,omitempty"`
}
InspectResponse is the full view of a record.
type ItemFailure ¶
type ItemFailure struct {
Index int `json:"index"`
ItemID string `json:"item_id,omitempty"`
Code string `json:"code"`
Message string `json:"message"`
}
ItemFailure is the per-item failure shape used by SessionCommit and CollectionMigrate (and structurally compatible with BatchAddFailure in the AddBatch path). Index correlates to the caller's input position; ItemID correlates to a pre-existing record the operation iterated over.
type JobSummary ¶
type JobSummary struct {
ID string `json:"id"`
Kind string `json:"kind"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
StartedAt time.Time `json:"started_at,omitempty"`
CompletedAt time.Time `json:"completed_at,omitempty"`
TotalItems int `json:"total_items"`
ProcessedCount int `json:"processed_count"`
FailureReason string `json:"failure_reason,omitempty"`
}
JobSummary mirrors jobs.JobSummary at the api/ layer so callers don't have to import the internal jobs package types.
ClientToken is intentionally NOT included here. Listing other tenants' tokens (in the multi-tenant future) would let one caller guess another's idempotency window. A caller that wants to look up their own jobs by token uses CaptureBatchStatus on a known JobID, or filters JobsList by their own ClientToken via the request.
type JobsListRequest ¶
type JobsListRequest struct {
Status string `json:"status,omitempty" jsonschema:"pending|running|completed|failed|cancelled (single status; omit for all)"`
Kind string `json:"kind,omitempty" jsonschema:"e.g. capture_batch (max 64 chars; omit for all kinds)"`
ClientToken string `json:"client_token,omitempty" jsonschema:"exact-match UUID; scoped to the caller's tenant"`
Since string `json:"since,omitempty" jsonschema:"RFC3339 inclusive lower-bound on created_at; max 64 chars"`
Until string `json:"until,omitempty" jsonschema:"RFC3339 inclusive upper-bound on created_at; max 64 chars"`
Limit int `json:"limit,omitempty" jsonschema:"page size (1..200, default 50)"`
Offset int `json:"offset,omitempty" jsonschema:"pagination offset (0..100000)"`
}
JobsListRequest filters and paginates the JobStore. Empty fields are unconstrained except TenantID, which is always read from context and never accepted from the wire (a tenant cannot list another tenant's jobs by passing their id).
type JobsListResponse ¶
type JobsListResponse struct {
Jobs []JobSummary `json:"jobs"`
Total int `json:"total"`
Limit int `json:"limit"`
Offset int `json:"offset"`
}
JobsListResponse is the lightweight summary projection. Heavy per-item fields (Result, ClientRefToID) are intentionally omitted here; callers that need them follow up with gramaton_capture_batch_status.
type LinkRequest ¶
type LinkRequest struct {
SourceID string `json:"-" jsonschema:"-"`
TargetID string `json:"target_id" jsonschema:"destination record ID"`
EdgeType string `json:"edge_type" jsonschema:"relationship name (e.g. related_to, supports, contradicts)"`
EdgeWeight *float64 `json:"edge_weight,omitempty" jsonschema:"0.0-1.0, default 0.5"`
}
LinkRequest creates an edge from the source record to a target. SourceID is transport-set from the URL path. EdgeWeight is optional (default 0.5) and must be in [0.0, 1.0].
type LinkResponse ¶
type LinkResponse struct {
ID string `json:"id"`
EdgeID string `json:"edge_id"`
Updated bool `json:"updated"`
}
LinkResponse returns the source record's ID + the newly created edge ID.
type LogEntry ¶
type LogEntry struct {
Hash string `json:"hash"`
Timestamp string `json:"timestamp"`
Action string `json:"action"`
Mutations []MutationSummary `json:"mutations,omitempty"`
MutationsTruncated bool `json:"mutations_truncated,omitempty"`
}
LogEntry is one commit in the chain. Hash is truncated to 12 characters to keep CLI/MCP output readable; full hashes can be fetched via History when needed. Mutations is populated when IncludeRecordMutations=true; MutationsTruncated flags when the per-commit cap was hit.
type LogRequest ¶
type LogRequest struct {
Limit int `json:"limit,omitempty" jsonschema:"max entries (default 20, max 500)"`
Since string `json:"since,omitempty" jsonschema:"only include commits on or after this date (YYYY-MM-DD or RFC3339)"`
Until string `json:"until,omitempty" jsonschema:"only include commits up to this date (YYYY-MM-DD or RFC3339); empty means up to HEAD"`
Actions []string `` /* 185-byte string literal not displayed */
ExcludeCuration bool `` /* 197-byte string literal not displayed */
IncludeRecordMutations bool `` /* 261-byte string literal not displayed */
}
LogRequest carries the commit-walk knobs. Since and Until narrow the walk to a date range (both optional, accept YYYY-MM-DD or RFC3339); when set they bypass MaxLogTraversal because the D7 timestamp index gives range scans directly. Actions filter by structured CommitAction.Kind (Phase 3 D3); ExcludeCuration filters via Message-prefix matching so it works against pre-D3 commits. IncludeRecordMutations enriches each returned commit with per- record mutation summaries, saving a follow-up gramaton_inspect round-trip for the common "what records changed yesterday" flow.
type LogResponse ¶
type LogResponse struct {
Commits []LogEntry `json:"commits"`
}
LogResponse holds commit entries newest-first.
type MutationSummary ¶
type MutationSummary struct {
RecordID string `json:"record_id,omitempty"`
Kind string `json:"kind"`
Field string `json:"field,omitempty"`
Title string `json:"title,omitempty"`
SummaryShort string `json:"summary_short,omitempty"`
}
MutationSummary is the enriched per-record description included in LogEntry when IncludeRecordMutations=true. Title and SummaryShort are pulled from the current HEAD record (may be absent if the record was deleted since); both are omitempty so JSON stays lean.
type PageRef ¶
PageRef points at one page's worth of results within a search snapshot. The Range is a human-readable 1-indexed slice description; the Cursor is the opaque token to pass on a subsequent call to retrieve that page.
type PendingRecord ¶
type PendingRecord struct {
ID string `json:"id"`
SummaryShort string `json:"summary_short,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
}
PendingRecord is a lightweight row in a pending listing.
type PendingRequest ¶
type PendingRequest struct {
Limit int `json:"limit,omitempty" jsonschema:"max records to return (default 50, max 500)"`
}
PendingRequest limits how many pending records to return.
type PendingResponse ¶
type PendingResponse struct {
Records []PendingRecord `json:"records"`
Total int `json:"total"`
Truncated bool `json:"truncated,omitempty"`
}
PendingResponse reports the pending records and whether the result was truncated.
type ReembedRequest ¶
type ReembedRequest struct {
Batch int `json:"batch,omitempty" jsonschema:"max records to process (default 50, max 500)"`
}
ReembedRequest bounds how many records the cycle processes per call. Reembed is idempotent and pageable: callers can drive the store to completion by looping until reembedded+errors == 0.
type ReembedResponse ¶
type ReembedResponse struct {
Reembedded int `json:"reembedded"`
Skipped int `json:"skipped"`
Errors int `json:"errors"`
ErrorIDs []string `json:"error_ids,omitempty"`
}
ReembedResponse summarises one batch. ErrorIDs is omitted when no records failed.
type RelatedEdge ¶
type RelatedEdge struct {
ID string `json:"id"` // the other node's ID
EdgeType string `json:"edge_type"`
EdgeID string `json:"edge_id"`
EdgeWeight float64 `json:"edge_weight"`
Direction string `json:"direction"` // "outbound" or "inbound"
SummaryShort string `json:"summary_short,omitempty"`
}
RelatedEdge describes an edge connected to an inspected record.
type ResolveRequest ¶
type ResolveRequest struct {
ID string `json:"-" jsonschema:"-"`
Resolution string `json:"resolution" jsonschema:"completed|superseded|abandoned|obsolete"`
ResolutionNote string `json:"resolution_note,omitempty" jsonschema:"free-form note about why/how"`
AutoCloseCollectionStatus *bool `` /* 160-byte string literal not displayed */
}
ResolveRequest marks a record as resolved (completed, superseded, abandoned, or obsolete) with an optional note.
AutoCloseCollectionStatus defaults to true when nil. Set to false when the caller wants to expire the record at the Memory layer but keep the collection item visible in the open view (rare; useful when manually staging a multi-step close).
type ResolveResponse ¶
type ResolveResponse struct {
ID string `json:"id"`
Resolved bool `json:"resolved"`
AutoClosedStatus map[string]string `json:"auto_closed_status,omitempty"`
CollectionWarning string `json:"collection_warning,omitempty"`
}
ResolveResponse confirms the resolution. AutoClosedStatus reports any collection items whose schema-declared `status` enum field was also flipped to a closed-equivalent value (mapped from the resolution verb). CollectionWarning fires when the record is in a collection where the auto-close heuristic could not find a matching status field or value -- the caller should fall back to gramaton_collection_update for those.
type RestoreRequest ¶
type RestoreResponse ¶
type RetrievalTracker ¶
type RetrievalTracker struct {
// contains filtered or unexported fields
}
RetrievalTracker records which node IDs were served to agents via search/inspect/explore. The observe pipeline's feedback-loop detection reads this to avoid re-extracting knowledge that was just retrieved. Moved from server.Server because the track-serving path is now owned by api methods (formerly serviceSearch/serviceInspect/ serviceExplore lived on *Server and called s.retrieval).
func NewRetrievalTracker ¶
func NewRetrievalTracker() *RetrievalTracker
NewRetrievalTracker returns a tracker with the historical defaults (4h max age, 500 max size). Caller can adjust via SetBounds.
func (*RetrievalTracker) Len ¶
func (rt *RetrievalTracker) Len() int
Len returns the current tracked entry count (after pruning expired entries).
func (*RetrievalTracker) RetrievedIDs ¶
func (rt *RetrievalTracker) RetrievedIDs() []string
RetrievedIDs returns all currently tracked, not-yet-expired IDs.
func (*RetrievalTracker) Track ¶
func (rt *RetrievalTracker) Track(ids ...string)
Track records that the given IDs were served to an agent.
type SchemaField ¶
type SchemaField struct {
Name string `json:"name"`
Type SchemaFieldType `json:"type"`
Required bool `json:"required"`
Values []string `json:"values,omitempty"` // enum and enum[] only
}
SchemaField defines a single field in a collection schema.
type SchemaFieldType ¶
type SchemaFieldType string
SchemaFieldType identifies the type of a collection schema field.
const ( FieldTypeString SchemaFieldType = "string" FieldTypeNumber SchemaFieldType = "number" FieldTypeBoolean SchemaFieldType = "boolean" FieldTypeDate SchemaFieldType = "date" FieldTypeEnum SchemaFieldType = "enum" FieldTypeEnumSet SchemaFieldType = "enum[]" )
type SearchRequest ¶
type SearchRequest struct {
Text string `json:"text,omitempty" jsonschema:"search query text (optional -- omit for filter-only queries)"`
Top int `json:"top,omitempty" jsonschema:"integer, number of results (default 10)"`
Temporality string `` /* 130-byte string literal not displayed */
KnowledgeType string `` /* 129-byte string literal not displayed */
EpistemicStatus string `` /* 137-byte string literal not displayed */
Resolution string `` /* 132-byte string literal not displayed */
ProcessingStatus string `` /* 213-byte string literal not displayed */
ConfidenceMin *float64 `json:"confidence_min,omitempty" jsonschema:"0.0-1.0"`
ConfidenceMax *float64 `json:"confidence_max,omitempty" jsonschema:"0.0-1.0"`
ImportanceMin *float64 `json:"importance_min,omitempty" jsonschema:"0.0-1.0"`
ImportanceMax *float64 `json:"importance_max,omitempty" jsonschema:"0.0-1.0"`
IncludeHistorical bool `json:"include_historical,omitempty" jsonschema:"include records past valid_until"`
IncludeConcepts bool `` /* 366-byte string literal not displayed */
Since string `json:"since,omitempty" jsonschema:"filter: created after date (YYYY-MM-DD or RFC3339)"`
Missing []string `json:"missing,omitempty" jsonschema:"array of field names that must be unset (e.g. [temporality, confidence])"`
Keywords []string `json:"keywords,omitempty" jsonschema:"array of keywords that must all be present on the record (exact match)"`
AccessCountMin *int64 `json:"access_count_min,omitempty" jsonschema:"integer, minimum access count"`
AccessCountMax *int64 `json:"access_count_max,omitempty" jsonschema:"integer, maximum access count"`
LastAccessedAfter string `json:"last_accessed_after,omitempty" jsonschema:"filter: accessed after date (YYYY-MM-DD or RFC3339)"`
LastAccessedBefore string `json:"last_accessed_before,omitempty" jsonschema:"filter: accessed before date (YYYY-MM-DD or RFC3339)"`
ValidAfter string `json:"valid_after,omitempty" jsonschema:"filter: valid_from after date"`
ValidBefore string `json:"valid_before,omitempty" jsonschema:"filter: valid_from before date"`
ExpiresAfter string `json:"expires_after,omitempty" jsonschema:"filter: valid_until after date (find records expiring after X)"`
ExpiresBefore string `json:"expires_before,omitempty" jsonschema:"filter: valid_until before date (find records expiring before X)"`
Match string `` /* 141-byte string literal not displayed */
SimilarTo string `json:"similar_to,omitempty" jsonschema:"record ID -- find records similar to this one using its stored embedding"`
NearNode string `json:"near_node,omitempty" jsonschema:"record ID -- restrict results to records within MaxHops of this node in the graph"`
MaxHops int `json:"max_hops,omitempty" jsonschema:"integer, max BFS hops from NearNode (default unbounded when NearNode set)"`
MinEdges *int `json:"min_edges,omitempty" jsonschema:"integer, minimum total edge count (orphan detection: max_edges=0)"`
MaxEdges *int `json:"max_edges,omitempty" jsonschema:"integer, maximum total edge count"`
Random bool `json:"random,omitempty" jsonschema:"return random results (ignores sort/score). Useful for serendipitous discovery or review"`
Sort string `` /* 192-byte string literal not displayed */
Order string `json:"order,omitempty" jsonschema:"asc or desc (default: desc)"`
Meta map[string]string `json:"meta,omitempty" jsonschema:"filter by structured metadata (e.g. {assignee: Sarah Chen, status: in_progress})"`
Store string `json:"store,omitempty" jsonschema:"filter by store: memory|sessions|all (default: all)"`
// Pagination fields. Cursor takes precedence: when set, all
// other filter args are ignored (the cursor encodes the slice
// against a previously-materialized snapshot) and the response
// carries `ignored_params` listing what was dropped. PageSize
// applies to both fresh searches and cursor calls.
Cursor string `` /* 228-byte string literal not displayed */
PageSize int `json:"page_size,omitempty" jsonschema:"results per page (default from server config; capped at server-side max)."`
}
SearchRequest is the canonical search input. Most fields are filters evaluated inside search.Execute; see package search for semantics.
type SearchResponse ¶
type SearchResponse struct {
Results []search.Result `json:"results"`
Facets search.Facets `json:"facets,omitempty"`
Suggestions *search.Suggestions `json:"suggestions,omitempty"`
// Warnings surfaces non-fatal degradations -- e.g. the query
// embedder failed so the request fell back to BM25-only, or the
// underlying match set exceeded the snapshot's candidate cap.
// Callers can decide whether to surface them to the user. Empty
// on the happy path.
Warnings []string `json:"warnings,omitempty"`
// Pagination fields. Always populated for fresh searches;
// populated for cursor calls based on the looked-up snapshot.
Page int `json:"page,omitempty"`
PageSize int `json:"page_size,omitempty"`
Total int `json:"total,omitempty"`
NextCursor string `json:"next_cursor,omitempty"`
QueryID string `json:"query_id,omitempty"`
Pages []PageRef `json:"pages,omitempty"`
// IgnoredParams names request fields that were dropped because
// a Cursor was provided. Empty on fresh searches; non-empty
// only on cursor calls where the request also carried filter
// args.
IgnoredParams []string `json:"ignored_params,omitempty"`
}
SearchResponse carries ranked results plus aggregates (facets, refinement suggestions) plus pagination scaffolding.
type SessionCommitResponse ¶
type SessionCommitResponse struct {
SessionID string `json:"session_id"`
SegmentsAdded int `json:"segments_added"`
SessionOnlySegments int `json:"session_only_segments"`
TopicsCreated int `json:"topics_created"`
MemoryRecordsCreated int `json:"memory_records_created"`
EdgesCreated int `json:"edges_created"`
Superseded []map[string]any `json:"superseded,omitempty"`
Failed []ItemFailure `json:"failed,omitempty"`
}
SessionCommitResponse pins SessionCommit's previous map[string]any shape. The legacy map emits session_only_segments unconditionally, so it has no omitempty here. Superseded is omitempty (emitted only when at least one record got auto-superseded by a commit segment). Failed is the per-segment failure list reserved for future partial-success work (see CollectionMigrateResponse.Failed for the same disclaimer).
type StatsResponse ¶
type StatsResponse struct {
TotalRecords int `json:"total_records"`
Temporality map[string]int `json:"temporality"`
KnowledgeType map[string]int `json:"knowledge_type"`
EpistemicStatus map[string]int `json:"epistemic_status"`
Confidence ConfidenceDist `json:"confidence"`
}
StatsResponse summarises the knowledge store's composition.
Counts include ALL non-deleted, non-structural-child nodes: user records AND derived concept nodes. The manifest produced by curation (`records_by_type` etc.) deliberately excludes concept nodes since concepts are derived from clusters rather than captured by the user; both counts are correct under their own semantics.
type StatusResponse ¶
type StatusResponse struct {
Nodes int `json:"nodes"`
Edges int `json:"edges"`
Embedding bool `json:"embedding"`
}
StatusResponse summarises server health at a glance.
type StuckRecord ¶
type StuckRecord struct {
ID string `json:"id"`
Task string `json:"task"`
Error string `json:"error,omitempty"`
}
StuckRecord identifies a single record-task pair flagged as stuck. A record can in principle appear under multiple tasks if it has multiple per-task status fields stuck simultaneously, though in practice each task targets a different node shape.
type SupersededRecord ¶
type SupersededRecord struct {
ID string `json:"id"`
Summary string `json:"summary,omitempty"`
Similarity float64 `json:"similarity"`
EdgeID string `json:"edge_id"`
}
SupersededRecord describes a record that Capture automatically marked as historical because the new record was near-duplicate.
type Supersession ¶
type Supersession string
Supersession controls the candidate scope for auto-supersession on short-content records.
collection (default) -- only records sharing this collection
participate in same-collection supersession.
Cross-collection collisions ("eggs" in
Grocery vs "eggs" in Recipes) don't fire.
store -- legacy behaviour: any record in the store
is a candidate. Default for memory orphans.
none -- collection's items never participate in
auto-supersession.
const ( SupersessionCollection Supersession = "collection" SupersessionStore Supersession = "store" SupersessionNone Supersession = "none" )
func CollectionSupersession ¶
func CollectionSupersession(n *graph.Node) Supersession
CollectionSupersession returns the collection's supersession config, falling back to DefaultSupersession when absent.
type Template ¶
type Template struct {
Name string `yaml:"name"`
Description string `yaml:"description,omitempty"`
Schema *CollectionSchema `yaml:"schema,omitempty"`
ClearMode string `yaml:"clear_mode,omitempty"`
Supersession string `yaml:"supersession,omitempty"`
Curation string `yaml:"curation,omitempty"`
Contradictions string `yaml:"contradictions,omitempty"`
}
Template is a reusable collection shape -- schema + behaviour knobs -- that CollectionCreate can instantiate by name. Templates ship embedded in the binary so fresh stores have them available without extra provisioning, and so callers can name them without worrying about filesystem paths.
Template fields mirror the fields on CollectionCreateRequest so the merge at CollectionCreate time is a plain "non-empty wins" shallow merge -- whatever the caller passes explicitly overrides the template's default.
func LookupTemplate ¶
LookupTemplate returns a named template from the embedded registry. The second return is false when no template matches. Lazy-initialises the registry on first call; subsequent calls are a bare map lookup.
type UnlinkRequest ¶
type UnlinkRequest struct {
EdgeID string `json:"-" jsonschema:"-"`
}
UnlinkRequest identifies an edge to remove by its edge ID.
type UnlinkResponse ¶
UnlinkResponse confirms deletion.
type UpdateRequest ¶
type UpdateRequest struct {
ID string `json:"-" jsonschema:"-"` // transport-set
Confidence *float64 `json:"confidence,omitempty" jsonschema:"0.0-1.0"`
Temporality string `json:"temporality,omitempty" jsonschema:"immutable|durable|temporal|ephemeral"`
KnowledgeType string `json:"knowledge_type,omitempty" jsonschema:"episodic|semantic|procedural|conceptual|reference"`
EpistemicStatus string `json:"epistemic_status,omitempty" jsonschema:"well_established|probable|speculative|contested|refuted"`
Importance *float64 `json:"importance,omitempty" jsonschema:"0.0-1.0"`
Keywords []string `json:"keywords,omitempty" jsonschema:"array of keyword strings"`
SummaryShort string `json:"summary_short,omitempty" jsonschema:"~750 chars (semantic anchor for embedding)"`
ValidUntil string `` /* 135-byte string literal not displayed */
AssertedAsOf string `json:"asserted_as_of,omitempty" jsonschema:"when the source made this claim (YYYY-MM-DD or RFC3339)"`
Meta map[string]any `json:"meta,omitempty" jsonschema:"structured metadata (e.g. {assignee: Sarah, status: done})"`
}
UpdateRequest is the input to the update operation. ID is set by the transport from the URL path / tool args and is not part of the HTTP request body.
type UpdateResponse ¶
type UpdateResponse struct {
ID string `json:"id"`
Updated bool `json:"updated"`
CollectionWarning string `json:"collection_warning,omitempty"`
}
UpdateResponse carries the id that was updated, whether any field actually changed, and an optional warning when updating a record that's a collection member.
Source Files
¶
- api.go
- backup.go
- branches.go
- capture.go
- capture_batch.go
- capture_batch_async.go
- capture_batch_cancel.go
- capture_batch_canonical.go
- capture_batch_chunked.go
- capture_batch_result.go
- capture_batch_status.go
- classify.go
- collection_config.go
- collection_responses.go
- collection_schema.go
- collection_template.go
- collections.go
- commit_helpers.go
- curation.go
- delete_record.go
- diff.go
- errors.go
- explore.go
- history.go
- inspect.go
- internal.go
- jobs_list.go
- link.go
- log.go
- ops.go
- reembed.go
- resolve.go
- retrieval.go
- search.go
- search_pagination.go
- sessions.go
- tenant.go
- update.go
- validate.go