summarize

package
v0.10.0 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Index

Constants

View Source
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

func BuildPrompt(segments []Segment, targetChars int, hint string) string

BuildPrompt constructs an LLM prompt for the given segments and hint.

func CacheKey

func CacheKey(contentKey string, zoom ZoomLevel, contentHash string) string

CacheKey computes a content-aware cache key. key = sha256(contentKey + ":" + zoomBucket + ":" + contentHash)

func ExtractSummary

func ExtractSummary(segments []Segment, zoom ZoomLevel) string

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

func ValidateEndpoint(endpoint, provider, apiKey string) error

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.

func (*AnthropicProvider) Complete

func (p *AnthropicProvider) Complete(ctx context.Context, prompt string, maxTokens int) (string, error)

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.

func (*AppleProvider) Complete

func (p *AppleProvider) Complete(_ context.Context, _ string, _ int) (string, error)

Complete is a stub that always returns an error 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.

func (*OllamaProvider) Complete

func (p *OllamaProvider) Complete(ctx context.Context, prompt string, maxTokens int) (string, error)

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.

func (*OpenAIProvider) Complete

func (p *OpenAIProvider) Complete(ctx context.Context, prompt string, maxTokens int) (string, error)

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

func DetectProvider(providerName, endpoint, apiKey, model string) Provider

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 Result

type Result struct {
	ContentKey string
	Summary    string
	FromCache  bool
}

Result holds a completed summary.

type Segment

type Segment struct {
	Author string
	Time   string
	Text   string
}

Segment represents a single message in a conversation.

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

func (s *Summarizer) Summarize(ctx context.Context, req Request) tea.Cmd

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.

const (
	Zoom40   ZoomLevel = 40   // Ticker line
	Zoom80   ZoomLevel = 80   // One-liner
	Zoom200  ZoomLevel = 200  // 2-3 line preview
	Zoom500  ZoomLevel = 500  // Paragraph
	Zoom1000 ZoomLevel = 1000 // Full digest
)

func BucketZoom

func BucketZoom(targetChars int) ZoomLevel

BucketZoom normalizes a target char count to the nearest zoom bucket.

Jump to

Keyboard shortcuts

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