tok

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 25, 2026 License: MIT Imports: 25 Imported by: 0

README

tok

Go License CI Go Report Card Go Reference

Cut LLM token costs by 60–90%. A Go library for prompt compression, output filtering, token estimation, and secrets scanning — built for AI coding agents.


What tok Is

tok is a library, not a CLI. It exposes token-efficiency primitives as a clean Go API:

  • Prompt compressiontok.PromptCompress / tok.Compress shrink verbose prompts 20–70% (six modes).
  • Output filtering — a 31-layer pipeline (entropy pruning, perplexity filtering, AST-aware compression, H2O heavy-hitter, …) that strips noise from command output before it re-enters an LLM context.
  • Token estimationtok.EstimateTokens* and tok.EstimateCost give model-aware token counts and pricing.
  • Secrets scanningtok.SecretDetector and tok.IsSensitiveFilename catch credentials before they leak into prompts.
  • Rate limiting & tracking — persistent SQLite-backed gain tracking (tok.NewTracker).

It is consumed directly as a Go module, and it powers the tok commands inside Hawk (hawk tok ...), which imports it as a library.

Ecosystem Boundaries

tok is a Hawk support engine. Keep the dependency edge one-way:

  • use hawk-core-contracts for any cross-repo shared contracts
  • do not import hawk/internal/*
  • do not import removed legacy path hawk/shared/types; use hawk-core-contracts/types
  • do not import other engines (eyrie, yaad, trace, sight, inspect) — engines are peers, not dependencies

Install

go get github.com/GrayCodeAI/tok
import "github.com/GrayCodeAI/tok"

tok ships no standalone tok CLI binary. Its CLI surface is exposed through Hawk, which embeds this library: hawk tok compress, hawk tok estimate, and hawk tok scan.


Quick Start

Compress a prompt
out := tok.PromptCompress("Please implement authentication", tok.IntensityUltra)
// → "Implement auth."
Filter command output
out, _ := tok.Compress(verboseOutput, tok.Aggressive)
// 200 lines → a few lines: pass/fail + failures
Estimate tokens & cost
n    := tok.EstimateTokensForModel(text, "gpt-4o")
cost := tok.EstimateCost(text, "gpt-4o")
Scan for secrets
d := tok.NewSecretDetector()
findings := d.DetectSecrets(text)
redacted := d.RedactSecrets(text)

Library API Highlights

  • tok.PromptCompress(text, intensity) — prompt compression (Lite / Full / Ultra). ~150 phrase substitutions, drop-lists for articles / filler / pleasantries, and auto-clarity (security/destructive segments pass through verbatim). intensity is monotonic: len(ultra) <= len(full) <= len(lite).
  • tok.Compress(text, opts...) — the full output pipeline with options: WithCustomFilters, WithCodeAware(lang), WithPerplexityGuided(scorer, ratio), profile options, and more.
  • tok.IsSensitiveFilename(path) — 3-layer filename detection (exact basename, sensitive directory, name token). Companion to the content-based SecretDetector. Catches .env, id_rsa, ~/.ssh/..., test_credentials.json, etc.
  • tok.SmartTruncate(content, maxLines, lang) — code truncation that preserves function signatures and always reports the exact drop count (kept + dropped == total).
  • tok.ExtractJSON / ExtractJSONArray / ExtractAllJSON — brace-balanced JSON extraction from LLM output with surrounding prose, markdown fences, and unterminated objects.
  • tok.NewTracker(ctx) — persistent gain tracker (SQLite + WAL, 90-day retention, pure-Go via modernc.org/sqlite). Aggregate, Recent, Prune queries.
  • tok.EstimateTokensFast / WithEncoding / ForModel — model-aware token estimation.
  • filter.CompressWithRetry — validate-fix-retry loop: caller supplies a Validator and AdjustFunc; the loop escalates mode/intensity and retries up to N times.
  • filter.NewTOMLFilter / LoadTOMLFilterFile — full 8-stage TOML pipeline as a pluggable Filter.

Full reference: pkg.go.dev/github.com/GrayCodeAI/tok.


Compression Modes

Mode Style Savings
lite Drop filler, keep grammar ~20%
full Drop articles, fragments OK ~40% (default)
ultra Telegraphic, abbreviations ~60%
wenyan-lite Classical Chinese light ~30%
wenyan Classical Chinese standard ~50%
wenyan-ultra Classical Chinese max ~70%
Output Filtering (31-Layer Pipeline)

Research-backed algorithms: entropy pruning, perplexity filtering, AST-aware compression, H2O heavy-hitter, attention sink preservation, semantic chunking, and 25+ more.

Custom Filter DSL

Define regex find/replace rules in a TOML file and plug them into the pipeline. Opt-in — no rules, no change.

# filters.toml
[[rule]]
name        = "collapse-uuids"
pattern     = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
replacement = "<uuid>"
priority    = 10
rules, _ := tok.LoadFilterRules("filters.toml")
out, _ := tok.Compress(text, tok.WithCustomFilters(rules))
Team / Shared Compression Profiles

Bundle mode + tier + budget into a named, versioned TOML profile teams can share. Built-ins: default, aggressive, code-safe.

p, _ := tok.LoadProfile(".tok/profiles/code-safe.toml")
out, _ := tok.Compress(text, p.Options()...)
Code-Aware (Symbol-Preserving) Compression

tok.WithCodeAware(lang) marks input as source code and guards function/type/export signatures so compression can never strip them. Defaults to a dependency-light regex symbol provider; swap in an LSP-backed one via WithSymbolProvider.

Perplexity-Guided Token Dropping

tok.WithPerplexityGuided(scorer, ratio) (LLMLingua-style) drops the lowest-importance tokens first. Default HeuristicPerplexityScorer is zero-dependency; plug in your own PerplexityScorer, or tok's experimental OllamaScorer when built with -tags experimental_ollama. Opt-in.


Benchmarks

Measured on this repo via benchmarks/run.sh (raw vs tok.Compress(..., tok.Aggressive)):

fixture raw bytes raw tokens tok bytes tok tokens saved
git log 2,873 718 298 74 89 %
git diff 385,051 96,262 1,117 279 99 %
ls -la 66,341 16,585 148 37 99 %
find .go 19,145 4,786 147 36 99 %

Profile the hot paths with ./scripts/profile.sh [compress|tokens|filter|secrets|all].


Architecture

tok
├── tok.go, *.go         Public library API (top-level package)
├── internal/
│   ├── compress/        Input compression engine (6 modes)
│   ├── filter/          Output pipeline (31 layers)
│   ├── secrets/         Secret detection + redaction
│   ├── tracking/        SQLite token-usage database
│   ├── fastops/         Hot-path primitives (entropy, etc.)
│   └── core/            Token estimation & cost
├── benchmarks/          Token-savings benchmarks
└── evals/               Eval harness

Pure-Go, zero CGO, no runtime dependencies.


Contributing

git clone https://github.com/GrayCodeAI/tok.git && cd tok
make test && make lint
./scripts/build.sh        # verifies the library compiles (go build ./... + go vet)

See CONTRIBUTING.md.


License

MIT

Documentation

Overview

Prompt compression — public API.

This file exposes the algorithm (port from prompt-compression algorithm) as a top-level tok API. It is independent of the main compression pipeline and does not use tiers/modes/budgets; it is a self-contained, deterministic prose compression function with three intensity levels.

Usage:

out, stats := tok.PromptCompress("Sure, I can help you with that.", tok.IntensityLite)
out, stats := tok.PromptCompress(prompt, tok.IntensityUltra)

The function NEVER modifies sensitive segments (security warnings, destructive commands, credential mentions) — those are passed through verbatim regardless of intensity. CJK text is also passed through unchanged (the rules assume Latin grammar).

JSON extraction from prose — public API.

Wraps internal/extract to expose brace-balanced JSON object and array extraction as a top-level tok API. Useful for parsing LLM output that contains JSON embedded in surrounding prose.

Custom filter DSL — user-defined compression rules.

This file exposes a small, public rule format that lets users define their own regex-based find/replace rules in a TOML file (e.g. ~/.tok/filters.toml) and apply them as an early or late stage of the compression pipeline.

The file format reuses TOML (already a dependency via BurntSushi/toml). Each rule is a [[rule]] array-of-tables entry:

# ~/.tok/filters.toml
[[rule]]
name        = "collapse-uuids"
pattern     = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
replacement = "<uuid>"
priority    = 10
enabled     = true
applies_to  = "*.log"   # optional content-type or glob hint

[[rule]]
name        = "strip-timestamps"
pattern     = "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z\\s*"
replacement = ""
priority    = 20

Rules are applied in ascending priority order (lower priority numbers run first). Invalid regex patterns are skipped with a logged warning rather than crashing the whole load — a single bad rule never disables the rest.

Usage:

rules, _ := tok.LoadFilterRules(filepath.Join(home, ".tok", "filters.toml"))
out, stats := tok.Compress(text, tok.WithCustomFilters(rules))

Perplexity-guided selective token dropping (LLMLingua-style) — public API.

Paper: "LLMLingua" — Jiang et al., Microsoft, 2023 (https://arxiv.org/abs/2310.05736)

This file exposes an opt-in, pluggable compression path that drops the lowest-importance tokens from text, mirroring LLMLingua's perplexity-based pruning: tokens a language model finds predictable (low surprise) carry less information and are dropped first, while surprising / information-dense tokens are retained.

The scoring is abstracted behind PerplexityScorer so callers can plug in a real model-backed scorer without changing the drop logic. The DEFAULT scorer (HeuristicPerplexityScorer) is a zero-dependency stand-in: it approximates token importance from local rarity + structural cues. It is a HEURISTIC, not true model perplexity — use a model-backed implementation when fidelity matters. tok ships an experimental OllamaScorer behind the experimental_ollama build tag.

Usage:

out, stats := tok.CompressPerplexityGuided(text, tok.NewHeuristicPerplexityScorer(), 0.4)
out, stats := tok.Compress(text, tok.WithPerplexityGuided(scorer, 0.4))

Package tok provides high-performance text compression for LLM context windows.

Usage:

compressed, stats := tok.Compress(text, tok.Aggressive)
compressed, stats := tok.Compress(text, tok.WithBudget(4000))

c := tok.NewCompressor(tok.Adaptive)
compressed, stats := c.Compress(text)

Persistent gain tracking — public API.

Wraps internal/tracking to expose a top-level tok.Tracker type that records compression events to a local SQLite database and supports aggregate queries for dashboards, budgets, and self-tuning.

Default location: ~/.tok/tracker.db (WAL mode, 90-day retention).

Index

Examples

Constants

View Source
const (
	DefaultMaxBudget  = 50000
	DefaultBudgetPct  = 0.15
	PriorityWriteEdit = 100
	PrioritySkill     = 80
	PriorityRead      = 50
)
View Source
const CompactionSystemPrompt = `` /* 662-byte string literal not displayed */

CompactionSystemPrompt is the system prompt for LLM-based structured compaction.

View Source
const DefaultMinChunkSize = 250

DefaultMinChunkSize is the default minimum chunk size in tokens.

Variables

View Source
var (
	// ErrInputTooLarge is returned when input exceeds the configured max context tokens.
	ErrInputTooLarge = errors.New("input exceeds max context tokens")

	// ErrConfigInvalid is returned when configuration validation fails.
	ErrConfigInvalid = errors.New("config validation failed")

	// ErrNoReversibleEntries is returned when no reversible entries are found for decoding.
	ErrNoReversibleEntries = errors.New("no reversible entries found")

	// ErrHashNotFound is returned when a hash prefix is not found in the reversible map.
	ErrHashNotFound = errors.New("hash not found in reversible map")

	// ErrCommandUnsafe is returned when a command contains shell meta-characters.
	ErrCommandUnsafe = errors.New("command contains unsafe shell meta-characters")

	// ErrCacheOpen is returned when the cache database cannot be opened.
	ErrCacheOpen = errors.New("failed to open cache database")

	// ErrChunkFailed is returned when chunk processing fails.
	ErrChunkFailed = errors.New("chunk processing failed")
)

Sentinel errors for tok pipeline operations. Use errors.Is/As for programmatic error handling.

View Source
var ModelToEncoding = map[string]Encoding{

	"o1-":         O200kBase,
	"o1":          O200kBase,
	"o3-":         O200kBase,
	"o3":          O200kBase,
	"o4-":         O200kBase,
	"o4":          O200kBase,
	"chatgpt-4o-": O200kBase,

	"gpt-4.1-": O200kBase,
	"gpt-4.1":  O200kBase,

	"gpt-4o-": O200kBase,
	"gpt-4o":  O200kBase,

	"gpt-4-": Cl100kBase,
	"gpt-4":  Cl100kBase,

	"gpt-3.5-turbo-": Cl100kBase,
	"gpt-3.5-turbo":  Cl100kBase,
	"gpt-35-turbo-":  Cl100kBase,
	"gpt-35-turbo":   Cl100kBase,

	"ft:gpt-4":         Cl100kBase,
	"ft:gpt-3.5-turbo": Cl100kBase,
	"ft:davinci-002":   Cl100kBase,
	"ft:babbage-002":   Cl100kBase,

	"claude-4-":   ClaudeBase,
	"claude-4":    ClaudeBase,
	"claude-3.5-": ClaudeBase,
	"claude-3.5":  ClaudeBase,
	"claude-3-":   ClaudeBase,
	"claude-3":    ClaudeBase,
	"claude-":     ClaudeBase,
	"claude":      ClaudeBase,

	"gemini-2.5-": GeminiBase,
	"gemini-2.5":  GeminiBase,
	"gemini-2.0-": GeminiBase,
	"gemini-2.0":  GeminiBase,
	"gemini-1.5-": GeminiBase,
	"gemini-1.5":  GeminiBase,
	"gemini-":     GeminiBase,
	"gemini":      GeminiBase,
}

ModelToEncoding maps model name prefixes to their BPE encoding. Longer prefixes should come first for correct matching.

View Source
var Version = strings.TrimSpace(versionFile)

Version of the tok library. Sourced from the VERSION file at the repo root. Release builds may override it via ldflags:

-X github.com/GrayCodeAI/tok.Version={{.Version}}

Do not edit this variable directly — bump the VERSION file instead, or let release-please/goreleaser do it.

Functions

func BuildCompactionPrompt added in v0.1.1

func BuildCompactionPrompt(context string, maxChars int) string

BuildCompactionPrompt builds a prompt for LLM-based structured compaction.

func BuiltinProfiles added in v0.1.1

func BuiltinProfiles() map[string]*Profile

BuiltinProfiles returns copies of all registered built-in profiles keyed by name.

func ClassifyContent added in v0.1.1

func ClassifyContent(text string) string

ClassifyContent determines the content type of a text string.

func CompressJSON

func CompressJSON(text string, maxItems int) string

CompressJSON samples large JSON arrays, keeping error/failure items, first 2, last 2, and a random sample of the middle. If maxItems <= 0, defaults to 20. Non-array input is returned unchanged.

func CompressLog

func CompressLog(text string) string

CompressLog preserves ERROR/WARN/FATAL lines and stack traces, collapsing runs of 3+ similar INFO/DEBUG lines into a summary.

func DetectLanguageByExtension

func DetectLanguageByExtension(path string) string

DetectLanguageByExtension returns the programming language name for a file path based on its extension. Returns "" for unknown extensions.

func EstimateCompression added in v0.1.1

func EstimateCompression(content string, ratio float64) string

EstimateCompression applies ratio-based truncation intelligently, keeping first/last and dropping middle.

func EstimateCostSavings added in v0.1.1

func EstimateCostSavings(stats Stats, model string) float64

EstimateCostSavings estimates the dollar savings from compression based on model pricing. It assumes saved tokens are input tokens (conservative estimate). Returns 0 if the model is unknown.

func EstimateTokens

func EstimateTokens(text string) int

EstimateTokens returns the estimated token count for the given text.

Example
package main

import (
	"fmt"

	"github.com/GrayCodeAI/tok"
)

func main() {
	text := "Hello, how are you today?"

	// Fast heuristic estimate
	count := tok.EstimateTokens(text)
	fmt.Printf("Estimated tokens: %d\n", count)
}

func EstimateTokensFast added in v0.1.1

func EstimateTokensFast(text string) int

EstimateTokensFast provides a fast estimate without BPE. Use this when exact count isn't critical (e.g. internal budget checks before doing precise BPE work).

func EstimateTokensForModel added in v0.1.1

func EstimateTokensForModel(text string, model string) int

EstimateTokensForModel uses BPE for the encoding associated with a specific model (e.g. "gpt-4o", "claude-3", "gemini-2.5"). See WithModel for the supported model prefixes.

func EstimateTokensPrecise

func EstimateTokensPrecise(text string) int

EstimateTokensPrecise uses BPE tokenization (slower, more accurate).

func EstimateTokensWithEncoding added in v0.1.1

func EstimateTokensWithEncoding(text string, encoding string) int

EstimateTokensWithEncoding uses BPE for a specific encoding (e.g. "cl100k_base", "o200k_base", "p50k_base"). The encoding must be one of the names accepted by the BPE tokenizer.

func FormatCostSavings added in v0.1.1

func FormatCostSavings(stats Stats, model string) string

FormatCostSavings returns a human-readable cost savings string. Returns "$X.XX saved" if the model is known, or empty string if unknown.

func FormatResult added in v0.1.1

func FormatResult(result *OptimizationResult) string

FormatResult produces a human-readable summary of the optimization result.

func FormatStats added in v0.1.1

func FormatStats(stats Stats) string

FormatStats returns a human-readable summary of compression statistics. If a model is specified, includes dollar-based cost savings.

func FormatUsageBar added in v0.1.1

func FormatUsageBar(pct float64, width int) string

FormatUsageBar creates an ASCII progress bar.

func GetLanguagePatterns

func GetLanguagePatterns(lang string) []string

GetLanguagePatterns returns custom patterns if registered, else built-in pattern strings.

func IsHighEntropy added in v0.1.1

func IsHighEntropy(s string, threshold float64) bool

IsHighEntropy returns true if the string's Shannon entropy exceeds the given threshold. A threshold of 4.5 is generally a good indicator for detecting random secrets/keys. Most English text has entropy around 3.5-4.0, while random base64/hex strings typically have entropy above 4.5.

func IsSensitiveBasename added in v0.1.1

func IsSensitiveBasename(name string) bool

IsSensitiveBasename is a convenience wrapper for the common case where the caller already has just the basename (no directory). Equivalent to IsSensitiveFilename(name) and discarding the match details.

func IsSensitiveFilename added in v0.1.1

func IsSensitiveFilename(path string) (bool, secrets.FilenameMatch)

IsSensitiveFilename reports whether path is likely to contain secrets (e.g. ".env", "id_rsa", "/home/user/.ssh/...", "test_credentials.json"). Companion to SecretDetector which inspects file *content*; this function inspects file *names and paths*.

Returns (sensitive, match). The match contains the category that fired (CatExactBasename, CatSensitiveDirectory, or CatNameToken) and a human-readable reason.

All matching is case-insensitive. The function is safe to call from multiple goroutines and never returns false positives for ordinary source files (main.go, README.md, etc.).

func ListModels added in v0.1.1

func ListModels() []string

ListModels returns a sorted list of all known model names.

func LoadProfiles added in v0.1.1

func LoadProfiles(dir string) (map[string]*Profile, error)

LoadProfiles reads every *.toml profile in dir, keyed by profile name. A missing directory yields an empty map and no error so callers can treat "no shared profiles" as a normal state.

func MaskSecret added in v0.1.1

func MaskSecret(value, secretType string) string

MaskSecret masks a secret value for safe display.

func OptimalBudget added in v0.1.1

func OptimalBudget(contentType string, importance float64) int

OptimalBudget recommends how many tokens to allocate based on content type and importance (0.0-1.0).

func RecommendMode added in v0.1.1

func RecommendMode(contentType string, budget int) string

RecommendMode recommends the best compression mode for a given content type and token budget.

func RegisterChunker

func RegisterChunker(ext string, fn ChunkerFunc)

RegisterChunker registers a custom chunker for a file extension (e.g. ".go").

func RegisterLanguagePatterns

func RegisterLanguagePatterns(lang string, patterns []string)

RegisterLanguagePatterns registers custom boundary patterns for a language. These override the built-in patterns when looking up boundaries.

func RegisterModelPricing added in v0.1.1

func RegisterModelPricing(model string, inputPricePer1K, outputPricePer1K float64)

RegisterModelPricing adds or overwrites pricing for a model at runtime. This allows users and plugins to keep pricing current without code changes.

func ShannonEntropy added in v0.1.1

func ShannonEntropy(s string) float64

ShannonEntropy calculates the Shannon entropy of a string in bits per character. Higher values indicate more randomness, which is characteristic of secrets and keys.

func SuggestBudget added in v0.1.1

func SuggestBudget(blocks []ContentBlock) int

SuggestBudget recommends an optimal budget based on content blocks.

func WarmupTokenizer

func WarmupTokenizer()

WarmupTokenizer pre-initializes the BPE tokenizer in the background. Call at application startup to avoid latency on the first Compress call.

func WastedTokens added in v0.1.1

func WastedTokens(events []CompressionEvent) int

WastedTokens calculates how many tokens could have been saved with optimal compression strategies.

Types

type Alert added in v0.1.1

type Alert struct {
	Level     string // "warning", "critical", "limit_reached"
	Message   string
	Timestamp time.Time
	Threshold float64 // what % triggered it
}

Alert represents a usage threshold alert.

type ChunkOptions

type ChunkOptions struct {
	MaxTokens     int
	MinTokens     int
	MinChunkSize  int // hard minimum; chunks below this get heavy DP penalty (default: DefaultMinChunkSize)
	Language      string
	Overlap       int           // number of tokens worth of content to repeat from previous chunk
	KeepSeparator SeparatorKeep // controls boundary line placement (default: SepLeft)
}

ChunkOptions configures the code chunking behavior.

func DefaultChunkOptions

func DefaultChunkOptions() ChunkOptions

DefaultChunkOptions returns sensible defaults for code chunking.

type ChunkerFunc

type ChunkerFunc func(path, content string) (language string, chunks []CodeChunk)

ChunkerFunc is a custom chunker that takes a file path and content, returning the detected language and code chunks.

type CodeChunk

type CodeChunk struct {
	Content   string `json:"content"`
	StartLine int    `json:"start_line"`
	EndLine   int    `json:"end_line"`
	Symbol    string `json:"symbol,omitempty"`
	Tokens    int    `json:"tokens"`
}

CodeChunk represents a semantically meaningful chunk of source code.

func ChunkCode

func ChunkCode(source string, opts ChunkOptions) []CodeChunk

ChunkCode splits source code into semantically meaningful chunks based on language-aware boundary detection (function/class/method definitions). If a custom chunker is registered for the file extension in opts.Language, it is used instead of the default pipeline.

func ChunkCodePath

func ChunkCodePath(path, source string, opts ChunkOptions) []CodeChunk

ChunkCodePath is like ChunkCode but accepts a file path for registry lookup.

type CompactionSchema added in v0.1.1

type CompactionSchema struct {
	TaskOverview         string   `json:"task_overview"`
	CurrentState         string   `json:"current_state"`
	ImportantDiscoveries []string `json:"important_discoveries"`
	NextSteps            []string `json:"next_steps"`
	ContextToPreserve    []string `json:"context_to_preserve"`
}

CompactionSchema is a 5-field structured schema for LLM-based context compaction. It preserves critical information while maximizing compression.

func ParseCompactionResponse added in v0.1.1

func ParseCompactionResponse(response string) (*CompactionSchema, error)

ParseCompactionResponse parses an LLM's JSON response into a CompactionSchema.

func (*CompactionSchema) ToPrompt added in v0.1.1

func (s *CompactionSchema) ToPrompt() string

ToPrompt renders the schema as a structured prompt for reinsertion into context.

type CompressionAdvisor added in v0.1.1

type CompressionAdvisor struct {
	History    []CompressionEvent
	Strategies map[string]*StrategyStats
	// contains filtered or unexported fields
}

CompressionAdvisor analyzes compression sessions and recommends optimal strategies.

func NewCompressionAdvisor added in v0.1.1

func NewCompressionAdvisor() *CompressionAdvisor

NewCompressionAdvisor creates a new CompressionAdvisor instance.

func (*CompressionAdvisor) Analyze added in v0.1.1

func (ca *CompressionAdvisor) Analyze() []Recommendation

Analyze examines the history and produces recommendations per content type.

func (*CompressionAdvisor) FormatAdvice added in v0.1.1

func (ca *CompressionAdvisor) FormatAdvice() string

FormatAdvice returns a human-readable report of compression advice.

func (*CompressionAdvisor) Record added in v0.1.1

func (ca *CompressionAdvisor) Record(event CompressionEvent)

Record records a compression event and updates strategy statistics.

type CompressionEvent added in v0.1.1

type CompressionEvent struct {
	Input        string
	Output       string
	Mode         string
	InputTokens  int
	OutputTokens int
	Savings      float64
	Timestamp    time.Time
	ContentType  string
}

CompressionEvent records a single compression operation.

type Compressor

type Compressor struct {
	// contains filtered or unexported fields
}

Compressor is a reusable compression instance. Reuses internal caches across calls for better performance.

func NewCompressor

func NewCompressor(opts ...Option) *Compressor

NewCompressor creates a reusable compressor.

Example
package main

import (
	"fmt"

	"github.com/GrayCodeAI/tok"
)

func main() {
	// Create a reusable compressor for multiple calls
	c := tok.NewCompressor(
		tok.WithBudget(1000),
	)

	text1 := "First document to compress..."
	text2 := "Second document to compress..."

	_, stats1 := c.Compress(text1)
	_, stats2 := c.Compress(text2)

	fmt.Printf("Doc 1 saved: %d tokens\n", stats1.TokensSaved)
	fmt.Printf("Doc 2 saved: %d tokens\n", stats2.TokensSaved)
}

func (*Compressor) Compress

func (c *Compressor) Compress(text string) (string, Stats)

Compress applies the compression pipeline to the input text.

type ContentBlock added in v0.1.1

type ContentBlock struct {
	ID                string
	Content           string
	Tokens            int
	Priority          float64
	Category          string // "system", "memory", "conversation", "tool_output", "context"
	Compressible      bool
	CompressedContent string
}

ContentBlock represents a unit of content that can be optimized.

func CompressBlock added in v0.1.1

func CompressBlock(block ContentBlock, targetTokens int) ContentBlock

CompressBlock applies compression to a block proportional to how much we need to save. targetTokens is the desired token count after compression.

type ContextOptimizer added in v0.1.1

type ContextOptimizer struct {
	Budget   int
	Strategy string // "greedy", "balanced", "priority"
	// contains filtered or unexported fields
}

ContextOptimizer maximizes information density within a token budget.

func NewContextOptimizer added in v0.1.1

func NewContextOptimizer(budget int) *ContextOptimizer

NewContextOptimizer creates an optimizer with the given token budget.

func (*ContextOptimizer) Optimize added in v0.1.1

func (co *ContextOptimizer) Optimize(blocks []ContentBlock) *OptimizationResult

Optimize selects the best strategy and optimizes content blocks within budget.

type CustomFilter added in v0.1.1

type CustomFilter struct {
	// contains filtered or unexported fields
}

CustomFilter applies a set of user-defined FilterRules to text in priority order. Regexes are compiled once at construction; rules whose pattern fails to compile are skipped with a logged warning so a single bad rule never disables the rest.

CustomFilter is read-only after construction and safe for concurrent use.

func NewCustomFilter added in v0.1.1

func NewCustomFilter(rules []FilterRule) *CustomFilter

NewCustomFilter compiles rules into an applicable filter. Disabled rules and rules with invalid patterns are dropped (the latter with a logged warning). Rules are stored in ascending priority order regardless of input ordering.

func (*CustomFilter) Apply added in v0.1.1

func (f *CustomFilter) Apply(text string) string

Apply runs every compiled rule against text in priority order and returns the transformed result. It is equivalent to ApplyTo(text, "").

func (*CustomFilter) ApplyTo added in v0.1.1

func (f *CustomFilter) ApplyTo(text, contentType string) string

ApplyTo runs the compiled rules against text in priority order, skipping any rule whose AppliesTo glob does not match the supplied contentType hint.

An empty contentType means "no hint": only rules with an empty AppliesTo are applied. A rule with an empty AppliesTo always applies regardless of hint.

func (*CustomFilter) Len added in v0.1.1

func (f *CustomFilter) Len() int

Len reports how many compiled (enabled, valid) rules the filter holds.

type Encoding added in v0.1.1

type Encoding string

Encoding represents a BPE encoding scheme.

const (
	// Cl100kBase is used by GPT-4, GPT-3.5-turbo, and text-embedding-ada-002.
	Cl100kBase Encoding = "cl100k_base"
	// O200kBase is used by GPT-4o, GPT-4.1, o1, o3, o4-mini.
	O200kBase Encoding = "o200k_base"
	// ClaudeBase is used by Claude models (uses cl100k_base as closest approximation).
	ClaudeBase Encoding = "cl100k_base"
	// GeminiBase is used by Gemini models (uses cl100k_base as closest approximation).
	GeminiBase Encoding = "cl100k_base"
	// R50kBase is used by older GPT-3 models.
	R50kBase Encoding = "r50k_base"
	// P50kBase is used by code-davinci and text-davinci-002/003.
	P50kBase Encoding = "p50k_base"
)

func GetEncodingForModel added in v0.1.1

func GetEncodingForModel(model string) Encoding

GetEncodingForModel returns the BPE encoding for the given model name. If the model is not recognized, it falls back to Cl100kBase.

type FilterRule added in v0.1.1

type FilterRule struct {
	// Name is a human-readable identifier (used in logged warnings).
	Name string `toml:"name"`
	// Pattern is the regex to match.
	Pattern string `toml:"pattern"`
	// Replacement is substituted for each match.
	Replacement string `toml:"replacement"`
	// Priority orders rule application: lower runs first. Defaults to 0.
	Priority int `toml:"priority"`
	// Enabled gates the rule. Rules default to enabled when the field is
	// omitted from the TOML (see LoadFilterRules).
	Enabled bool `toml:"enabled"`
	// AppliesTo is an optional content-type label or filename glob (e.g.
	// "*.log", "json"). Empty means the rule applies to all input. The glob,
	// when set, is matched against the content-type hint passed to
	// CustomFilter.ApplyTo (callers that compress raw text without a hint get
	// all enabled rules).
	AppliesTo string `toml:"applies_to"`
}

FilterRule is a single user-defined find/replace rule.

Pattern is a Go (RE2) regular expression. Replacement may reference capture groups using the $1 / ${name} syntax accepted by regexp.ReplaceAllString.

func LoadFilterRules added in v0.1.1

func LoadFilterRules(path string) ([]FilterRule, error)

LoadFilterRules parses a TOML rules file at path and returns the rules in ascending priority order.

A rule with `enabled` omitted defaults to enabled. Rules with an empty pattern are dropped with a logged warning. Regex validity is NOT checked here — it is checked (once) when building a CustomFilter, so that an invalid pattern is skipped rather than failing the whole load. A malformed TOML file returns a non-nil error.

type HeuristicPerplexityScorer added in v0.1.1

type HeuristicPerplexityScorer struct {
	// RarityWeight scales the inverse-frequency (surprise) signal.
	RarityWeight float64
	// StructureWeight scales the structural-importance signal.
	StructureWeight float64
	// LengthWeight scales the token-length signal.
	LengthWeight float64
}

HeuristicPerplexityScorer is the DEFAULT zero-dependency scorer. It is a HEURISTIC stand-in for true model perplexity: it estimates token importance from purely local statistics, with no model calls, keeping tok dependency-light.

Score(token) blends three signals:

  • Inverse document frequency / rarity: tokens that occur rarely within the text are more surprising and score higher (the perplexity proxy).
  • Structural importance: identifiers, code-like tokens, numbers and punctuation that carry syntactic weight are boosted.
  • Length: longer tokens tend to be more specific and informative.

This is NOT a substitute for a real language model. Plug in your own PerplexityScorer, or tok's experimental OllamaScorer when built with -tags experimental_ollama, when you need genuine perplexity.

func NewHeuristicPerplexityScorer added in v0.1.1

func NewHeuristicPerplexityScorer() *HeuristicPerplexityScorer

NewHeuristicPerplexityScorer returns the default heuristic scorer with tuned weights. It is the zero-dependency default used by WithPerplexityGuided when no scorer is supplied.

func (*HeuristicPerplexityScorer) Score added in v0.1.1

func (h *HeuristicPerplexityScorer) Score(_ context.Context, tokens []string) ([]float64, error)

Score implements PerplexityScorer using local rarity + structural cues. It never returns an error: the heuristic is always defined for any input.

type Intensity added in v0.1.1

type Intensity = compress.Intensity

Intensity selects how aggressive prompt compression should be.

  • IntensityLite: drops pleasantries only ("Sure", "Of course", "Please").
  • IntensityFull: Lite + articles ("a", "an", "the") + filler + hedging.
  • IntensityUltra: Full + conjunctions + intensifiers + redundant pronouns.

Each level is a superset of the previous; higher intensity never produces a longer output than a lower intensity on the same input.

const (
	IntensityLite  Intensity = compress.Lite
	IntensityFull  Intensity = compress.Full
	IntensityUltra Intensity = compress.Ultra
)

Intensity preset constants. Use as a direct argument to PromptCompress.

type JSONExtract added in v0.1.1

type JSONExtract = extract.Result

JSONExtract is the result of an extraction attempt.

func ExtractAllJSON added in v0.1.1

func ExtractAllJSON(text string) []JSONExtract

ExtractAllJSON returns every top-level balanced JSON object in text, in source order. Useful for parsing LLM output that contains multiple JSON snippets.

func ExtractJSON added in v0.1.1

func ExtractJSON(text string) JSONExtract

ExtractJSON returns the first complete JSON object found in text, or JSONExtract{Found: false} if no balanced object exists.

Handles nested objects, arrays, escaped quotes, and double-quoted strings. Skips preceding and trailing prose. Apostrophes in English prose (e.g. "Here's the JSON:") are NOT treated as string delimiters (only standard JSON double-quotes are).

Example:

out := tok.ExtractJSON(`Sure! Here's the data: {"name": "alice"}`)
// out.JSON = `{"name": "alice"}`, out.Found = true

func ExtractJSONArray added in v0.1.1

func ExtractJSONArray(text string) JSONExtract

ExtractJSONArray is the array counterpart of ExtractJSON. It looks for a balanced `[...]` instead of `{...}`.

type LayerStat

type LayerStat struct {
	TokensSaved int
	DurationMs  int64
}

LayerStat contains per-layer statistics.

type Mode

type Mode string

Mode controls compression aggressiveness.

const (
	ModeMinimal    Mode = "minimal"
	ModeAggressive Mode = "aggressive"
)

type ModelPricing added in v0.1.1

type ModelPricing struct {
	InputPricePer1K  float64 // Cost per 1K input tokens in USD
	OutputPricePer1K float64 // Cost per 1K output tokens in USD
}

ModelPricing holds per-token pricing for a model.

func GetModelPricing added in v0.1.1

func GetModelPricing(model string) (ModelPricing, bool)

GetModelPricing returns the pricing for a model. Returns the pricing and true if found, or zero pricing and false if unknown.

type OptimizationResult added in v0.1.1

type OptimizationResult struct {
	Kept        []ContentBlock
	Dropped     []ContentBlock
	Compressed  []ContentBlock
	TotalTokens int
	BudgetUsed  float64
	Savings     int
}

OptimizationResult holds the outcome of an optimization pass.

func BalancedOptimize added in v0.1.1

func BalancedOptimize(blocks []ContentBlock, budget int) *OptimizationResult

BalancedOptimize ensures each category gets minimum representation, then fills by priority.

func GreedyOptimize added in v0.1.1

func GreedyOptimize(blocks []ContentBlock, budget int) *OptimizationResult

GreedyOptimize takes highest priority blocks until budget is full.

func PriorityOptimize added in v0.1.1

func PriorityOptimize(blocks []ContentBlock, budget int) *OptimizationResult

PriorityOptimize uses strict priority ordering, compressing before dropping.

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option configures compression behavior.

Pre-built option presets (use directly as options).

func WithBudget

func WithBudget(tokens int) Option

WithBudget sets a hard token limit for the output.

func WithCodeAware added in v0.1.1

func WithCodeAware(language string) Option

WithCodeAware marks the input as source code and activates symbol preservation. Lines that declare semantically significant symbols (function/type/export declarations and their signatures) are identified via the configured SymbolProvider and guarded so that downstream compression stages can never strip them: any protected line removed by the pipeline is re-injected into the output.

The lang argument is a language name as understood by the chunker (e.g. "go", "python", "typescript", "rust", "java"). An empty string triggers best-effort auto-detection.

The default SymbolProvider is regex-backed (RegexSymbolProvider, using the chunker's symbol patterns). Pass a custom provider — e.g. an LSP-backed one — with WithSymbolProvider.

func WithCustomFilters added in v0.1.1

func WithCustomFilters(rules []FilterRule) Option

WithCustomFilters registers user-defined regex find/replace rules (see FilterRule / LoadFilterRules) to run as a post-pipeline stage. The rules are compiled once into a CustomFilter and applied in ascending priority order to the compressed output; invalid patterns are skipped with a logged warning.

Passing nil or an empty slice is a no-op.

func WithLLMLinguaProse added in v0.1.1

func WithLLMLinguaProse() Option

WithLLMLinguaProse enables the opt-in LLMLingua prose compression layer. It drops low-information sentences from natural-language prose using a local perplexity proxy (no model calls); code and short inputs are passed through unchanged. It is disabled unless explicitly requested.

func WithMode

func WithMode(m Mode) Option

WithMode sets the compression mode.

func WithModel added in v0.1.1

func WithModel(model string) Option

WithModel sets the target LLM model and auto-selects the appropriate BPE encoding. This configures both the model name (for cost calculations) and the tokenizer encoding.

Supported model prefixes:

  • OpenAI: gpt-4, gpt-4o, gpt-4.1, gpt-3.5-turbo, o1, o3, o4
  • Anthropic: claude-3, claude-3.5, claude-4
  • Google: gemini-1.5, gemini-2.0, gemini-2.5

Unknown models fall back to cl100k_base encoding.

func WithModelEncoding added in v0.1.1

func WithModelEncoding(encoding Encoding) Option

WithModelEncoding sets a specific BPE encoding for tokenization. Use this when you need direct control over the encoding, bypassing model detection.

func WithPerplexityGuided added in v0.1.1

func WithPerplexityGuided(scorer PerplexityScorer, dropRatio float64) Option

WithPerplexityGuided enables an opt-in compression layer that drops the lowest-importance tokens (per scorer) up to dropRatio of the token count, while preserving sentence boundaries and protected symbols.

dropRatio is clamped to [0, 0.9]; values <= 0 disable the layer. If scorer is nil, the default HeuristicPerplexityScorer is used.

This runs as a final stage after the standard pipeline (it operates on the pipeline output), so it composes with tiers, modes, and budgets.

func WithQuery

func WithQuery(intent string) Option

WithQuery provides intent context for goal-driven filtering.

func WithSymbolProvider added in v0.1.1

func WithSymbolProvider(p SymbolProvider) Option

WithSymbolProvider overrides the SymbolProvider used by WithCodeAware. It lets an embedder (e.g. hawk) inject a real LSP-backed provider in place of the default regex implementation. Passing a nil provider is a no-op.

func WithTier

func WithTier(t Tier) Option

WithTier selects a pipeline profile.

type PerplexityScorer added in v0.1.1

type PerplexityScorer interface {
	Score(ctx context.Context, tokens []string) ([]float64, error)
}

PerplexityScorer assigns an importance score to each token in a sequence. Higher scores mean more important / more surprising tokens that should be preserved; lower scores are dropped first. The returned slice MUST have the same length as tokens (one score per token); implementations that cannot honor that contract should return an error.

The interface deliberately mirrors a model's per-token perplexity output so a real LM-backed scorer can be swapped in for the default heuristic without touching the drop logic.

type Profile added in v0.1.1

type Profile struct {
	Name            string `toml:"name"`              // Human-readable profile name.
	Version         string `toml:"version"`           // Profile version (e.g. "1", "2024.1").
	Mode            Mode   `toml:"mode"`              // Compression mode (minimal/aggressive).
	Tier            Tier   `toml:"tier"`              // Pipeline tier (surface/trim/...).
	Budget          int    `toml:"budget"`            // Hard token budget (0 = unlimited).
	FilterRulesPath string `toml:"filter_rules_path"` // Optional path to custom filter rules.
	Notes           string `toml:"notes"`             // Free-form description / changelog.
}

Profile is a named, versionable bundle of compression settings that teams can share. It captures the mode, tier, budget, an optional path to custom filter rules, and free-form notes. A Profile resolves to a slice of Option via Options, so it can be applied directly:

p, _ := tok.LoadProfile(".tok/profiles/code-safe.toml")
out, stats := tok.Compress(text, p.Options()...)

func BuiltinProfile added in v0.1.1

func BuiltinProfile(name string) (*Profile, bool)

BuiltinProfile returns a copy of the named built-in profile and whether it exists. Returning a copy keeps the registry immutable to callers.

func LoadProfile added in v0.1.1

func LoadProfile(path string) (*Profile, error)

LoadProfile reads a single profile from a TOML file. If the profile omits a name, the file's base name (without extension) is used.

func (*Profile) Options added in v0.1.1

func (p *Profile) Options() []Option

Options resolves the profile into the equivalent slice of Option values, so it can be passed to Compress or NewCompressor.

func (*Profile) Validate added in v0.1.1

func (p *Profile) Validate() error

Validate checks the profile for obviously invalid field values.

type PromptStats added in v0.1.1

type PromptStats = compress.Stats

PromptStats is the statistics struct returned from PromptCompress.

func PromptCompress added in v0.1.1

func PromptCompress(text string, intensity Intensity) (string, PromptStats)

PromptCompress applies the prompt-compression algorithm to text.

Behavior:

  • Empty input returns ("", zero stats).
  • Sensitive segments (security/destructive keywords) are preserved verbatim.
  • CJK text is passed through unchanged.
  • Multi-word drop-list entries are matched as whole phrases.
  • Dictionary substitutions preserve the case of the first character.

This is independent of tok.Compress() and does not consume options/presets.

type Recommendation added in v0.1.1

type Recommendation struct {
	Strategy        string
	Reason          string
	ExpectedSavings float64
	ContentType     string
	Priority        int
}

Recommendation represents an advisor suggestion for improving compression.

type RegexSymbolProvider added in v0.1.1

type RegexSymbolProvider struct{}

RegexSymbolProvider is the default, dependency-light SymbolProvider. It reuses the chunker's language boundary and symbol patterns to find declaration and signature lines without any LSP integration.

func (RegexSymbolProvider) Symbols added in v0.1.1

func (RegexSymbolProvider) Symbols(code, lang string) []Span

Symbols implements SymbolProvider using the chunker's boundary/symbol regexes.

A line is treated as a protected signature when it matches the language boundary pattern (function/type/class/export/etc.). For each such line the returned Span covers the signature itself plus any continuation lines that complete a multi-line signature (an unbalanced "(" run, typical of long parameter lists), so the full signature is preserved as a unit.

type RestorationEntry added in v0.1.1

type RestorationEntry struct {
	Path      string
	Content   string
	Tokens    int
	Priority  int    // writes/edits=100, skills=80, reads=50
	OpType    string // "write", "edit", "read", "skill"
	Timestamp time.Time
}

RestorationEntry represents a tracked file operation.

type RestorationTracker added in v0.1.1

type RestorationTracker struct {
	// contains filtered or unexported fields
}

RestorationTracker tracks file operations for selective context re-injection after compaction. When a conversation is compacted, important context (recent writes, skill activations, file reads) can be lost. The tracker records these operations and, after compaction, selects the highest-priority items to re-inject within a token budget.

func NewRestorationTracker added in v0.1.1

func NewRestorationTracker() *RestorationTracker

NewRestorationTracker creates a tracker with default settings.

func (*RestorationTracker) Clear added in v0.1.1

func (rt *RestorationTracker) Clear()

Clear removes all tracked entries.

func (*RestorationTracker) ComputeBudget added in v0.1.1

func (rt *RestorationTracker) ComputeBudget(usedTokens, reserveTokens int) int

ComputeBudget calculates the available restoration budget. Formula: min(maxBudget, contextWindow * budgetPct, contextWindow - usedTokens - reserveTokens)

func (*RestorationTracker) Entries added in v0.1.1

func (rt *RestorationTracker) Entries() []RestorationEntry

Entries returns a snapshot of all tracked entries (for testing/debugging).

func (*RestorationTracker) GetRestorations added in v0.1.1

func (rt *RestorationTracker) GetRestorations(budget int) []RestorationEntry

GetRestorations returns the highest-priority entries that fit within the given budget. Entries are sorted by priority (desc) then timestamp (desc, most recent first).

func (*RestorationTracker) Len added in v0.1.1

func (rt *RestorationTracker) Len() int

Len returns the number of tracked entries.

func (*RestorationTracker) Track added in v0.1.1

func (rt *RestorationTracker) Track(path, content, opType string)

Track records a file operation. Deduplicates by path (latest wins).

func (*RestorationTracker) WithBudgetPct added in v0.1.1

func (rt *RestorationTracker) WithBudgetPct(pct float64) *RestorationTracker

WithBudgetPct sets the percentage of context window for restoration.

func (*RestorationTracker) WithContextWindow added in v0.1.1

func (rt *RestorationTracker) WithContextWindow(tokens int) *RestorationTracker

WithContextWindow sets the context window size in tokens.

func (*RestorationTracker) WithMaxBudget added in v0.1.1

func (rt *RestorationTracker) WithMaxBudget(tokens int) *RestorationTracker

WithMaxBudget sets the maximum token budget for restoration.

type ScorerFunc added in v0.1.1

type ScorerFunc func(ctx context.Context, tokens []string) ([]float64, error)

ScorerFunc adapts an ordinary function to the PerplexityScorer interface.

func (ScorerFunc) Score added in v0.1.1

func (f ScorerFunc) Score(ctx context.Context, tokens []string) ([]float64, error)

Score implements PerplexityScorer.

type SecretDetector added in v0.1.1

type SecretDetector struct {
	// contains filtered or unexported fields
}

SecretDetector detects and redacts secrets from text using compiled regex patterns.

func DefaultSecretDetector added in v0.1.1

func DefaultSecretDetector() *SecretDetector

DefaultSecretDetector returns the singleton SecretDetector instance with all built-in patterns. It is safe for concurrent use.

func NewSecretDetector added in v0.1.1

func NewSecretDetector() *SecretDetector

NewSecretDetector creates a SecretDetector with all built-in patterns compiled and ready.

func (*SecretDetector) DetectAndRedactWithEntropy added in v0.1.1

func (sd *SecretDetector) DetectAndRedactWithEntropy(text string, entropyThreshold float64) string

DetectAndRedactWithEntropy detects secrets using both pattern matching and entropy analysis.

func (*SecretDetector) DetectSecrets added in v0.1.1

func (sd *SecretDetector) DetectSecrets(text string) []SecretMatch

DetectSecrets finds all secrets in the given text.

func (*SecretDetector) RedactSecrets added in v0.1.1

func (sd *SecretDetector) RedactSecrets(text string) string

RedactSecrets replaces detected secrets with [REDACTED] markers.

type SecretMatch added in v0.1.1

type SecretMatch = secrets.SecretMatch

SecretMatch represents a detected secret within text.

type SeparatorKeep

type SeparatorKeep int

SeparatorKeep controls what happens to boundary separators during splitting.

const (
	SepLeft    SeparatorKeep = iota // separator stays with preceding chunk (default)
	SepRight                        // separator stays with following chunk
	SepDiscard                      // separator is removed from output
)

type Span added in v0.1.1

type Span struct {
	StartLine int    `json:"start_line"` // 1-based, inclusive
	EndLine   int    `json:"end_line"`   // 1-based, inclusive
	Symbol    string `json:"symbol,omitempty"`
	Lines     []string
}

Span identifies a protected region of source code that must survive compression. Spans are line-oriented (1-based, inclusive) and carry the extracted symbol name when one is available.

Spans are the unit of "code intelligence" exchanged between a SymbolProvider and the compression pipeline. The default provider derives them from the chunker's symbol regexes, but an embedder can supply spans from any source (e.g. an LSP server) via a custom SymbolProvider.

type Stats

type Stats struct {
	OriginalTokens   int
	FinalTokens      int
	TokensSaved      int
	ReductionPercent float64
	Layers           map[string]LayerStat
	Model            string  // Model used for cost calculation
	CostSavings      float64 // Dollar savings from compression
}

Stats contains compression statistics.

func Compress

func Compress(text string, opts ...Option) (string, Stats)

Compress applies tok's compression pipeline to the input text.

Example
package main

import (
	"fmt"

	"github.com/GrayCodeAI/tok"
)

func main() {
	text := `This is a very long piece of text that contains redundant information.
The purpose of this text is to demonstrate how tok can compress it.
We repeat the same ideas multiple times to inflate the token count.
The key insight is that tok uses entropy-based filtering to remove low-information tokens.
This allows us to reduce the token count while preserving the core meaning.`

	compressed, stats := tok.Compress(text)

	fmt.Printf("Original tokens: %d\n", stats.OriginalTokens)
	fmt.Printf("Final tokens: %d\n", stats.FinalTokens)
	fmt.Printf("Tokens saved: %d\n", stats.TokensSaved)
	fmt.Printf("Reduction: %.1f%%\n", stats.ReductionPercent)
	fmt.Printf("Compressed text length: %d\n", len(compressed))
}
Example (WithBudget)
package main

import (
	"fmt"

	"github.com/GrayCodeAI/tok"
)

func main() {
	text := `Long document with many details that we want to fit within a token budget.
We can use the budget option to limit the output to a specific number of tokens.
This is useful when working with context windows that have strict limits.`

	compressed, stats := tok.Compress(text, tok.WithBudget(50))

	fmt.Printf("Final tokens: %d (budget: 50)\n", stats.FinalTokens)
	fmt.Printf("Compressed text: %s\n", compressed[:50]+"...")
}
Example (WithQuery)
package main

import (
	"fmt"

	"github.com/GrayCodeAI/tok"
)

func main() {
	text := `The application uses a REST API with JSON payloads.
Database migrations are handled by the migration package.
The frontend is built with React and TypeScript.
Authentication uses JWT tokens with refresh token rotation.
The CI/CD pipeline runs on GitHub Actions.`

	// Query-aware compression preserves content relevant to the query
	_, stats := tok.Compress(text, tok.WithQuery("authentication"))

	fmt.Printf("Tokens saved: %d\n", stats.TokensSaved)
}

func CompressPerplexityGuided added in v0.1.1

func CompressPerplexityGuided(text string, scorer PerplexityScorer, dropRatio float64) (string, Stats)

CompressPerplexityGuided applies ONLY perplexity-guided token dropping to text (no other pipeline layers). It is a self-contained entry point for callers who want the LLMLingua-style drop in isolation.

If scorer is nil, the default HeuristicPerplexityScorer is used. dropRatio is clamped to [0, 0.9].

type StrategyStats added in v0.1.1

type StrategyStats struct {
	Name         string
	TotalEvents  int
	AvgSavings   float64
	BestSavings  float64
	WorstSavings float64
	AvgQuality   float64
}

StrategyStats tracks performance statistics for a compression strategy.

type StreamCompressor

type StreamCompressor struct {
	// contains filtered or unexported fields
}

StreamCompressor maintains a background-compressed version of accumulating content. As new content is appended, it re-compresses in the background so a compressed snapshot is always available without blocking.

Delta-only compression: once initial compression has run, subsequent compressions only process the new (delta) content using context-independent layers (entropy, ngram), then append the result to the existing compressed output. This avoids re-compressing the entire accumulated content each time the threshold is crossed.

func NewStreamCompressor

func NewStreamCompressor(threshold int, opts ...Option) *StreamCompressor

NewStreamCompressor creates a background compressor that keeps compressed output ready at all times. Threshold is the token count that triggers background re-compression. If threshold <= 0, it defaults to 2000 tokens.

func (*StreamCompressor) Append

func (sc *StreamCompressor) Append(content string)

Append adds new content. If accumulated tokens exceed the threshold, triggers background re-compression. Only the new delta (content added since the last compression) is compressed using context-independent layers, then merged with the existing compressed output.

func (*StreamCompressor) Close

func (sc *StreamCompressor) Close()

Close shuts down the background compressor and waits for any in-progress compression to finish.

func (*StreamCompressor) Raw

func (sc *StreamCompressor) Raw() string

Raw returns all accumulated raw content.

func (*StreamCompressor) Reset added in v0.1.1

func (sc *StreamCompressor) Reset()

Reset clears all accumulated content and resets the compressor to its initial state, allowing it to be reused.

func (*StreamCompressor) Snapshot

func (sc *StreamCompressor) Snapshot() (string, Stats)

Snapshot returns the current compressed output without blocking. If compression hasn't run yet, returns the raw content joined.

func (*StreamCompressor) TokenCount

func (sc *StreamCompressor) TokenCount() int

TokenCount returns estimated token count of raw content.

type SymbolProvider added in v0.1.1

type SymbolProvider interface {
	Symbols(code, lang string) []Span
}

SymbolProvider identifies the semantically significant spans of a piece of source code. It is the seam that lets hawk later inject a real LSP-backed provider in place of tok's dependency-light regex default.

Implementations must be safe for concurrent use; they receive the full code text and a language name (e.g. "go", "python"), and return the spans that compression must preserve. An empty lang signals best-effort detection.

var DefaultSymbolProvider SymbolProvider = RegexSymbolProvider{}

DefaultSymbolProvider is the SymbolProvider used by WithCodeAware when no other provider is supplied via WithSymbolProvider.

type Tier

type Tier string

Tier selects a pre-built pipeline profile.

const (
	TierSurface  Tier = "surface"  // 4 layers, fast
	TierTrim     Tier = "trim"     // 8 layers, balanced
	TierExtract  Tier = "extract"  // 20 layers, max compression
	TierCore     Tier = "core"     // 20 layers, quality-first
	TierCode     Tier = "code"     // code-aware
	TierLog      Tier = "log"      // log-aware
	TierThread   Tier = "thread"   // conversation-aware
	TierAdaptive Tier = "adaptive" // auto-detect content type
)

type Tracker added in v0.1.1

type Tracker struct {
	// contains filtered or unexported fields
}

Tracker is a persistent gain tracker. Safe for concurrent use.

func NewTracker added in v0.1.1

func NewTracker(ctx context.Context) (*Tracker, error)

NewTracker creates a tracker at the default path (~/.tok/tracker.db).

func NewTrackerAt added in v0.1.1

func NewTrackerAt(ctx context.Context, path string) (*Tracker, error)

NewTrackerAt creates a tracker at a custom path.

func (*Tracker) Aggregate added in v0.1.1

func (t *Tracker) Aggregate(ctx context.Context, days int) (TrackerAggregate, error)

Aggregate returns aggregate stats over the last `days` days (or the configured retention period if days is 0).

func (*Tracker) Close added in v0.1.1

func (t *Tracker) Close() error

Close releases the underlying DB. Safe to call multiple times.

func (*Tracker) Prune added in v0.1.1

func (t *Tracker) Prune(ctx context.Context) (int64, error)

Prune deletes events older than the configured retention period.

func (*Tracker) Recent added in v0.1.1

func (t *Tracker) Recent(ctx context.Context, n int) ([]TrackerEvent, error)

Recent returns the most recent n events, newest first.

func (*Tracker) Record added in v0.1.1

func (t *Tracker) Record(ctx context.Context, ev TrackerEvent) error

Record adds a new compression event. SavingsPct in the event is ignored; it's computed from byte counts.

func (*Tracker) WithRetention added in v0.1.1

func (t *Tracker) WithRetention(days int) *Tracker

WithRetention overrides the default 90-day retention period.

type TrackerAggregate added in v0.1.1

type TrackerAggregate = tracking.Aggregate

TrackerAggregate is the result of an aggregate query.

type TrackerEvent added in v0.1.1

type TrackerEvent = tracking.Event

TrackerEvent is a single compression event recorded by the tracker.

type UsageEntry added in v0.1.1

type UsageEntry struct {
	Tokens    int
	CostUSD   float64
	Timestamp time.Time
	Provider  string
	Model     string
}

UsageEntry represents a single recorded usage event.

type UsageSummary added in v0.1.1

type UsageSummary struct {
	HourlyTokens     int
	HourlyRemaining  int
	DailyTokens      int
	DailyRemaining   int
	SessionTokens    int
	SessionRemaining int
	DailyCostUSD     float64
	CostRemaining    float64
	HourlyPct        float64
	DailyPct         float64
}

UsageSummary provides a snapshot of current usage across all windows.

type UsageTracker added in v0.1.1

type UsageTracker struct {
	DailyLimit   int
	HourlyLimit  int
	SessionLimit int
	CostLimitUSD float64

	Alerts []Alert
	// contains filtered or unexported fields
}

UsageTracker tracks API usage across sessions and prevents surprise bills.

func NewUsageTracker added in v0.1.1

func NewUsageTracker() *UsageTracker

NewUsageTracker creates a UsageTracker with sensible defaults.

func (*UsageTracker) CanProceed added in v0.1.1

func (u *UsageTracker) CanProceed() (bool, string)

CanProceed checks all limits and returns whether another request is allowed. If not, it returns false and a reason string.

func (*UsageTracker) CheckThresholds added in v0.1.1

func (u *UsageTracker) CheckThresholds()

CheckThresholds evaluates current usage against threshold levels and generates alerts.

func (*UsageTracker) EstimateRemaining added in v0.1.1

func (u *UsageTracker) EstimateRemaining(tokensPerRequest int) int

EstimateRemaining estimates how many more requests of the given size fit in the budget.

func (*UsageTracker) FormatSummary added in v0.1.1

func (u *UsageTracker) FormatSummary() string

FormatSummary returns a human-readable usage summary.

func (*UsageTracker) GetUsage added in v0.1.1

func (u *UsageTracker) GetUsage() UsageSummary

GetUsage returns a snapshot of current usage.

func (*UsageTracker) PruneOld added in v0.1.1

func (u *UsageTracker) PruneOld()

PruneOld removes entries older than their respective windows.

func (*UsageTracker) Record added in v0.1.1

func (u *UsageTracker) Record(tokens int, costUSD float64, provider, model string)

Record adds a usage entry and checks thresholds.

func (*UsageTracker) Reset added in v0.1.1

func (u *UsageTracker) Reset()

Reset clears the session counter and alerts.

Directories

Path Synopsis
benchmarks
quality
Package quality implements an offline compression-quality benchmark harness.
Package quality implements an offline compression-quality benchmark harness.
quality/cmd command
Command quality-bench runs the offline compression-quality harness and emits a markdown report (and optionally CSV) into benchmarks/.
Command quality-bench runs the offline compression-quality harness and emits a markdown report (and optionally CSV) into benchmarks/.
cache
Package cache provides persistent query caching for tok.
Package cache provides persistent query caching for tok.
compress
Package compress implements the prompt-compression algorithm GrayCode native prompt-compression implementation.
Package compress implements the prompt-compression algorithm GrayCode native prompt-compression implementation.
config
Package config provides configuration management for tok.
Package config provides configuration management for tok.
core
Package core provides core interfaces and utilities for tok.
Package core provides core interfaces and utilities for tok.
extract
Package extract provides utilities for extracting structured data (JSON objects, arrays) from text that may contain prose around it.
Package extract provides utilities for extracting structured data (JSON objects, arrays) from text that may contain prose around it.
fastops
Package fastops CPU feature detection.
Package fastops CPU feature detection.
filter
Package filter provides LRU caching using the unified cache package.
Package filter provides LRU caching using the unified cache package.
secrets
Package secrets: filename-based sensitive path detection.
Package secrets: filename-based sensitive path detection.
tracking
Package tracking provides persistent gain tracking for tok compression calls via a local SQLite database.
Package tracking provides persistent gain tracking for tok compression calls via a local SQLite database.
Package mcp provides a minimal in-memory MCP (Model Context Protocol) server pre-loaded with tok tools.
Package mcp provides a minimal in-memory MCP (Model Context Protocol) server pre-loaded with tok tools.

Jump to

Keyboard shortcuts

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