Documentation
¶
Overview ¶
Package attachments provides a content-addressed attachment store backed by SHA-256 hashing and a SQLite metadata index. Duplicate files are stored only once on disk; metadata records track provenance per ingest, enabling queries by sender, channel, conversation, and content hash.
Index ¶
- type Analyzer
- type AnalyzerConfig
- type IngestParams
- type Record
- type SearchParams
- type Store
- func (s *Store) AbsPath(rec *Record) string
- func (s *Store) ByHash(ctx context.Context, hash string) (*Record, error)
- func (s *Store) ByID(ctx context.Context, id string) (*Record, error)
- func (s *Store) Close() error
- func (s *Store) Ingest(ctx context.Context, params IngestParams) (*Record, error)
- func (s *Store) Search(ctx context.Context, params SearchParams) ([]*Record, error)
- func (s *Store) TelemetryStats(ctx context.Context) (total, totalBytes, unique int64, err error)
- func (s *Store) UpdateVision(ctx context.Context, id, description, model string) error
- func (s *Store) VisionByHash(ctx context.Context, hash string) (description, model string, ok bool)
- type Tools
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Analyzer ¶
type Analyzer struct {
// contains filtered or unexported fields
}
Analyzer performs vision analysis on image attachments using an LLM. Results are cached in the attachment metadata index so identical content is only analyzed once (leveraging content-addressed dedup).
func NewAnalyzer ¶
func NewAnalyzer(store *Store, cfg AnalyzerConfig) *Analyzer
NewAnalyzer creates an Analyzer that uses the given store and LLM client for vision analysis.
func (*Analyzer) Analyze ¶
Analyze performs vision analysis on an image attachment. It returns the description text, or an empty string if the record is not an image. Results are cached in the attachment store: subsequent calls for the same record (or any record with the same content hash) return the cached description without calling the LLM.
type AnalyzerConfig ¶
type AnalyzerConfig struct {
Client llm.Client // multi-client routes to the correct provider
Model string // vision model name (must be in models.available)
Prompt string // custom analysis prompt; empty uses default
Timeout time.Duration // per-analysis timeout; 0 uses defaultVisionTimeout
Logger *slog.Logger
}
AnalyzerConfig holds the dependencies for an Analyzer.
type IngestParams ¶
type IngestParams struct {
Source io.Reader // attachment data to read
OriginalName string // original filename if known
ContentType string // MIME type
Size int64 // declared size in bytes (informational)
Width int // image width in pixels
Height int // image height in pixels
Channel string // source channel ("signal", "email", etc.)
Sender string // channel-specific sender identifier
ConversationID string // conversation context
ReceivedAt time.Time // when the attachment was received
}
IngestParams describes an attachment to be ingested into the store.
type Record ¶
type Record struct {
ID string // UUIDv4 primary key
Hash string // hex-encoded SHA-256 of file content
StorePath string // relative path in store: ab/cd/abcd...ef.jpg
OriginalName string // filename as provided by sender
ContentType string // MIME type (e.g. "image/jpeg")
Size int64 // file size in bytes
Width int // image width in pixels (0 if not applicable)
Height int // image height in pixels (0 if not applicable)
Channel string // ingest channel ("signal", "email", etc.)
Sender string // channel-specific sender identifier
ConversationID string // conversation the attachment belongs to
ReceivedAt time.Time // when the attachment was received
// Vision analysis fields (populated by Analyzer).
Description string // vision analysis text (empty = not analyzed)
AnalyzedAt time.Time // when analysis was performed (zero = not analyzed)
AnalysisModel string // model used for analysis
}
Record is one metadata entry for an ingested attachment.
type SearchParams ¶
type SearchParams struct {
ConversationID string // filter to a specific conversation
Channel string // filter by channel ("signal", "email")
Sender string // filter by sender identifier
ContentType string // MIME prefix filter (e.g. "image/")
Query string // text search across name, description, sender
Limit int // max results; 0 → 20, capped at 50
}
SearchParams controls attachment listing and search queries.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store manages content-addressed file storage with a SQLite metadata index.
func NewStore ¶
NewStore creates an attachment store rooted at rootDir with a SQLite metadata index at dbPath. The root directory is created if it does not exist.
func (*Store) ByHash ¶
ByHash returns the first metadata record matching the given SHA-256 hash, or nil if no record exists.
func (*Store) Ingest ¶
Ingest reads the attachment from params.Source, computes its SHA-256 hash, stores it content-addressed on disk, and records metadata in the index. If a file with the same hash already exists on disk, the file is not rewritten (dedup). A new metadata record is always created so that provenance is tracked per ingest. Returns the created Record.
func (*Store) Search ¶
Search returns attachment records matching the given filters, ordered by received_at descending (newest first). All filter fields are optional; an empty SearchParams returns the most recent attachments.
func (*Store) TelemetryStats ¶
TelemetryStats returns aggregate attachment statistics for operational dashboards. The three counts (total records, total bytes, unique content hashes) are computed in a single query.
func (*Store) UpdateVision ¶
UpdateVision stores vision analysis results for an attachment record. An empty description is rejected — callers should only store meaningful analysis results. The analyzed_at timestamp is set automatically.
func (*Store) VisionByHash ¶
VisionByHash returns cached vision analysis for any record matching the given content hash. This enables reuse across dedup hits — if the same image was already analyzed for a different sender, the cached description is returned. Returns ok=false if no analyzed record exists for the hash. Non-ErrNoRows database errors are logged and treated as cache misses.
type Tools ¶
type Tools struct {
// contains filtered or unexported fields
}
Tools provides agent tool handlers for attachment operations. The analyzer is optional — when nil, describe operations return cached descriptions only and cannot trigger new analysis.
func NewTools ¶
NewTools creates attachment tool handlers backed by the given store and optional vision analyzer.
func (*Tools) Describe ¶
Describe returns the vision description for an attachment. When the attachment has not been analyzed and a vision analyzer is available, analysis is triggered automatically. Supports re-analysis with optional model and prompt overrides.