Store.Project.ConversationIndex (fnord v0.9.29)
View SourceManages semantic index data for conversations within a project.
Index data is stored under the project's store path in a parallel directory tree to conversations themselves:
<store_path>/conversations/index/<conversation-id>/
embeddings.json
metadata.jsonThis module is responsible for tracking which conversations are indexed, determining which ones are new or stale, and reading/writing embeddings and associated metadata.
Summary
Functions
Enumerates all indexed conversations, yielding {id, embedding_vector, metadata}.
Deletes the index entry for the given conversation id.
Returns the status of the conversation index for the given project.
Reads embeddings and metadata for a conversation.
Reads only the metadata for a conversation index entry.
Returns true when the given conversation still needs indexing in this project. Stale when any of
Writes embeddings and metadata for a conversation.
Types
@type status() :: %{ new: [Store.Project.Conversation.t()], stale: [Store.Project.Conversation.t()], deleted: [String.t()] }
Functions
@spec all_embeddings(Store.Project.t()) :: Enumerable.t()
Enumerates all indexed conversations, yielding {id, embedding_vector, metadata}.
@spec delete(Store.Project.t(), String.t()) :: :ok
Deletes the index entry for the given conversation id.
@spec index_status(Store.Project.t()) :: status()
Returns the status of the conversation index for the given project.
It classifies conversations into:
:deleted- indexed conversations whose source conversation no longer exists:stale- conversations whose index metadata is stale compared to theon-disk conversation timestamp or embedding model:new- conversations that exist but have no index entry
@spec path_for(Store.Project.t(), String.t()) :: String.t()
@spec read_embeddings(Store.Project.t(), String.t()) :: {:ok, %{embeddings: any(), metadata: metadata()}} | {:error, term()}
Reads embeddings and metadata for a conversation.
Returns {:ok, %{embeddings: embeddings, metadata: metadata}} on success
or an error tuple if either file cannot be read/decoded.
@spec read_metadata(Store.Project.t(), String.t()) :: {:ok, metadata()} | {:error, term()}
Reads only the metadata for a conversation index entry.
@spec root(Store.Project.t()) :: String.t()
@spec stale?(Store.Project.t(), Store.Project.Conversation.t()) :: boolean()
Returns true when the given conversation still needs indexing in this project. Stale when any of:
- No index entry on disk.
- The entry's
last_indexed_tsis older than the conversation'stimestamp. - The stored embedding was produced by a different model (vector dimension doesn't match the current embedder).
Used by foreground indexers to re-check freshness inside a per-conversation lock: if a parallel indexer already refreshed the entry, skip instead of re-running the summarizer + embedder.
@spec write_embeddings(Store.Project.t(), String.t(), any(), metadata()) :: :ok | {:error, term()}
Writes embeddings and metadata for a conversation.
The embeddings are stored in embeddings.json and the metadata in
metadata.json under the conversation's index directory.