Documentation
¶
Index ¶
- Constants
- func BuildPrompt(segments []Segment, targetChars int, hint string) string
- func CacheKey(contentKey string, zoom ZoomLevel, contentHash string) string
- func ExtractSummary(segments []Segment, zoom ZoomLevel) string
- func IsAppleMLAvailable() bool
- func ValidateEndpoint(endpoint, provider, apiKey string) error
- type AnthropicProvider
- type AppleProvider
- type OllamaProvider
- type OpenAIProvider
- type Provider
- type Request
- type Result
- type Segment
- type Summarizer
- type SummaryCache
- type SummaryReadyMsg
- type ZoomLevel
Constants ¶
const ( HintGap = "gap" // summarizing missed messages HintTicker = "ticker" // one-line ambient display HintScan = "scan" // front page overview )
Hint types for prompt construction.
Variables ¶
This section is empty.
Functions ¶
func BuildPrompt ¶
BuildPrompt constructs an LLM prompt for the given segments and hint.
func CacheKey ¶
CacheKey computes a content-aware cache key. key = sha256(contentKey + ":" + zoomBucket + ":" + contentHash)
func ExtractSummary ¶
ExtractSummary produces an extractive summary at the given zoom level.
func IsAppleMLAvailable ¶
func IsAppleMLAvailable() bool
IsAppleMLAvailable returns false on non-darwin platforms.
func ValidateEndpoint ¶ added in v0.8.0
ValidateEndpoint validates llm_endpoint only for providers that could send llm_api_key to it: the scheme/host structural check plus an HTTPS gate when a credential is present. It lives here, next to DetectProvider, because this package owns the provider→endpoint routing it reasons about — and it must run before DetectProvider on every LLM path, since config keeps file- and env-sourced endpoints even if malformed. llm_endpoint is consumed ONLY on this path, so callers elsewhere (e.g. root command setup) must not gate unrelated commands on it.
The provider exemption runs FIRST, before any structural check. Providers that neither send llm_api_key to llm_endpoint nor consume the endpoint at all skip ALL validation: "apple", "none", and "disabled" transmit no key and ignore the endpoint; "anthropic" ignores the custom endpoint entirely (NewAnthropicProvider takes no endpoint and always calls https://api.anthropic.com); and "auto"/"" auto-detect only Apple or a hardcoded localhost Ollama (autoDetectProvider never receives the endpoint or key). Rejecting a malformed endpoint for these providers would block the LLM path over a value that is never consumed — e.g. a stale llm_endpoint left over from a previous provider — a repair lockout with no security payoff.
"ollama" is credential-less but DOES consume llm_endpoint (OllamaProvider posts to endpoint+"/api/generate"), so it does NOT skip validation: it falls through to the structural IsHTTPURL check, which fails closed on a malformed endpoint (file://, hostless, non-http(s)) at config time rather than deep in the summarizer at use time. But ollama IS exempt from the HTTPS/apiKey gate: OllamaProvider never transmits llm_api_key (DetectProvider calls NewOllamaProvider(endpoint, model), dropping the key), yet ValidateEndpoint receives the RAW Config.LLMAPIKey, which may be a stale value left from a previous provider. Gating ollama on that key would reject a plain-HTTP LAN Ollama (http://192.168.x.x:11434) and block the TUI over a secret that is never sent, so the apiKey branch below explicitly skips ollama — it stays endpoint-consuming but credential-less, subject only to the structural check.
For "openai" (which sends the key to the configured endpoint) and any unknown provider name (fail closed on names we can't reason about), the structural check rejects non-http(s)/hostless endpoints, and when an llm_api_key is present the endpoint must also pass RequireSecureURL so the secret can't leak in cleartext to a non-localhost http:// endpoint. RequireSecureURL only blocks http:// for non-localhost — it would let file://, ssh:// etc. through — so the IsHTTPURL scheme/host check runs even without a key. An empty endpoint is a no-op.
Types ¶
type AnthropicProvider ¶
type AnthropicProvider struct {
// contains filtered or unexported fields
}
AnthropicProvider calls the Anthropic Messages API.
func NewAnthropicProvider ¶
func NewAnthropicProvider(apiKey, model string) *AnthropicProvider
NewAnthropicProvider creates an Anthropic provider.
type AppleProvider ¶
type AppleProvider struct{}
AppleProvider is a stub for non-darwin platforms.
func NewAppleProvider ¶
func NewAppleProvider() *AppleProvider
NewAppleProvider returns nil on non-darwin platforms.
type OllamaProvider ¶
type OllamaProvider struct {
// contains filtered or unexported fields
}
OllamaProvider calls a local Ollama server.
func NewOllamaProvider ¶
func NewOllamaProvider(endpoint, model string) *OllamaProvider
NewOllamaProvider creates an Ollama provider.
type OpenAIProvider ¶
type OpenAIProvider struct {
// contains filtered or unexported fields
}
OpenAIProvider calls any OpenAI-compatible API (OpenAI, OpenRouter, local).
func NewOpenAIProvider ¶
func NewOpenAIProvider(endpoint, apiKey, model string) *OpenAIProvider
NewOpenAIProvider creates an OpenAI-compatible provider.
type Provider ¶
type Provider interface {
Complete(ctx context.Context, prompt string, maxTokens int) (string, error)
}
Provider generates summaries via an LLM or similar service.
func DetectProvider ¶
DetectProvider returns the best available provider based on configuration.
type Request ¶
type Request struct {
ContentKey string // human-readable grouping key, e.g. "chat:123:gap:45-67"
Content []Segment // the messages to summarize
TargetChars int // desired output length
Hint string // context hint: "gap", "ticker", "scan"
}
Request describes what to summarize and at what zoom level.
type Summarizer ¶
type Summarizer struct {
// contains filtered or unexported fields
}
Summarizer provides synchronous and async summary generation. When a Provider is available, it uses LLM; otherwise extractive fallback.
func NewSummarizer ¶
func NewSummarizer(provider Provider, cache *SummaryCache, maxConcurrent int) *Summarizer
NewSummarizer creates a Summarizer with the given provider and cache. If provider is nil, SummarizeSync always returns extractive fallback.
func (*Summarizer) Summarize ¶
Summarize returns a tea.Cmd that runs an async LLM summary. On completion, emits SummaryReadyMsg. The caller should then call SummarizeSync to get the (now cached) result. Returns nil if no provider is configured or request is already in-flight. The parent context is used to cancel in-flight LLM calls on shutdown.
func (*Summarizer) SummarizeSync ¶
func (s *Summarizer) SummarizeSync(req Request) Result
SummarizeSync returns a summary immediately. Never blocks on LLM. Returns cached LLM result if available, otherwise extractive fallback.
type SummaryCache ¶
type SummaryCache struct {
// contains filtered or unexported fields
}
SummaryCache provides disk-backed caching with in-memory eviction (oldest-first).
func NewSummaryCache ¶
func NewSummaryCache(dir string, ttl time.Duration, maxMemEntries int) *SummaryCache
NewSummaryCache creates a cache backed by the given directory.
func (*SummaryCache) Get ¶
func (c *SummaryCache) Get(key string) (string, bool)
Get looks up a cached summary. Returns ("", false) on miss.
func (*SummaryCache) Put ¶
func (c *SummaryCache) Put(key, summary string)
Put stores a summary in both memory and disk cache.
type SummaryReadyMsg ¶
type SummaryReadyMsg struct {
ContentKey string
}
SummaryReadyMsg is sent when an async summary completes.
type ZoomLevel ¶
type ZoomLevel int
ZoomLevel represents a target character budget for summaries.
func BucketZoom ¶
BucketZoom normalizes a target char count to the nearest zoom bucket.