convcontext

package
v1.14.0 Latest Latest
Warning

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

Go to latest
Published: Mar 26, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package convcontext provides context window management and message pruning for conversations.

Package convcontext provides context window management and message pruning for conversations. ABOUTME: Message summarization using Claude API ABOUTME: Reduces token usage by summarizing old conversation context

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreateSummaryMessage

func CreateSummaryMessage(summary string) core.Message

CreateSummaryMessage creates a system message containing a summary

func EstimateMessageTokens

func EstimateMessageTokens(msg core.Message) int

EstimateMessageTokens estimates tokens for a single message

func EstimateMessagesTokens

func EstimateMessagesTokens(messages []core.Message) int

EstimateMessagesTokens estimates total tokens for a slice of messages

func EstimateTokens

func EstimateTokens(text string) int

EstimateTokens estimates tokens in a string using a simple heuristic This is a rough estimate: actual token count depends on tokenizer

func PruneContext

func PruneContext(messages []core.Message, maxTokens int) []core.Message

PruneContext prunes messages to fit within maxTokens Strategy: - Always keep first message if it's a system message - Keep most recent messages - Preserve messages with tool calls - Remove middle messages if needed

Example

ExamplePruneContext demonstrates context pruning preserving important messages

package main

import (
	"fmt"

	"github.com/2389-research/hex/internal/convcontext"
	"github.com/2389-research/hex/internal/core"
)

func main() {
	messages := []core.Message{
		{Role: "system", Content: "You are a helpful assistant."},
		{Role: "user", Content: "Old message 1"},
		{Role: "assistant", Content: "Old response 1"},
		{Role: "user", Content: "Old message 2"},
		{Role: "assistant", Content: "Old response 2"},
		{Role: "user", Content: "Use the read tool"},
		{Role: "assistant", Content: "Reading file", ToolCalls: []core.ToolUse{{Name: "read_file", ID: "1"}}},
		{Role: "user", Content: "Recent message"},
		{Role: "assistant", Content: "Recent response"},
	}

	pruned := convcontext.PruneContext(messages, 100)

	fmt.Printf("Original: %d messages\n", len(messages))
	fmt.Printf("Pruned: %d messages\n", len(pruned))
	fmt.Printf("Kept system message: %v\n", pruned[0].Role == "system")

	hasToolCall := false
	for _, msg := range pruned {
		if len(msg.ToolCalls) > 0 {
			hasToolCall = true
			break
		}
	}
	fmt.Printf("Kept tool call message: %v\n", hasToolCall)
	fmt.Printf("Kept recent messages: %v\n", pruned[len(pruned)-1].Content == "Recent response")

}
Output:
Original: 9 messages
Pruned: 9 messages
Kept system message: true
Kept tool call message: true
Kept recent messages: true

func SummarizeToolResult added in v1.11.0

func SummarizeToolResult(toolName, content string) string

SummarizeToolResult creates a brief summary of a tool result for context pruning

Types

type ContextUsage

type ContextUsage struct {
	EstimatedTokens int
	MaxTokens       int
	PercentUsed     float64
	NearLimit       bool
}

ContextUsage provides information about context token usage

type Manager

type Manager struct {
	MaxTokens int
	Strategy  PruneStrategy
}

Manager handles context pruning and token estimation

Example (TokenSavings)

ExampleManager_tokenSavings demonstrates the token savings from context pruning

package main

import (
	"fmt"

	"github.com/2389-research/hex/internal/convcontext"
	"github.com/2389-research/hex/internal/core"
)

func main() {
	// Simulate a long conversation (500 messages with substantial content)
	messages := make([]core.Message, 500)
	messages[0] = core.Message{Role: "system", Content: "You are a helpful coding assistant with extensive knowledge of Go, Python, JavaScript, and software architecture."}

	for i := 1; i < 500; i++ {
		if i%2 == 1 {
			messages[i] = core.Message{
				Role: "user",
				Content: fmt.Sprintf("This is user message #%d asking a detailed question about coding in Go and Python. "+
					"I need help understanding how to implement a feature with proper error handling, testing, and documentation. "+
					"Can you provide a complete example with best practices?", i),
			}
		} else {
			messages[i] = core.Message{
				Role: "assistant",
				Content: fmt.Sprintf("This is assistant response #%d providing a detailed explanation of code concepts with examples. "+
					"Here's how you implement that feature: First, you need to set up the proper structure, then handle errors appropriately, "+
					"write comprehensive tests, and document your code thoroughly. Let me show you a complete example...", i),
			}
		}
	}

	// Without context management
	tokensWithoutPruning := convcontext.EstimateMessagesTokens(messages)

	// With context management (1000 token limit for demonstration)
	manager := convcontext.NewManager(1000)
	prunedMessages := manager.Prune(messages)
	tokensWithPruning := convcontext.EstimateMessagesTokens(prunedMessages)

	// Calculate savings
	tokensSaved := tokensWithoutPruning - tokensWithPruning
	percentSaved := float64(tokensSaved) / float64(tokensWithoutPruning) * 100

	// Cost calculation (Sonnet 4.5 pricing: $3/million input tokens)
	costWithout := float64(tokensWithoutPruning) * 3.0 / 1_000_000
	costWith := float64(tokensWithPruning) * 3.0 / 1_000_000
	costSaved := costWithout - costWith

	fmt.Printf("Original conversation: %d messages, ~%d tokens\n", len(messages), tokensWithoutPruning)
	fmt.Printf("After pruning: %d messages, ~%d tokens\n", len(prunedMessages), tokensWithPruning)
	fmt.Printf("Tokens saved: %d (%.1f%%)\n", tokensSaved, percentSaved)
	fmt.Printf("Cost saved per request: $%.4f\n", costSaved)
	fmt.Printf("Cost saved over 100 requests: $%.2f\n", costSaved*100)

}
Output:
Original conversation: 500 messages, ~37400 tokens
After pruning: 14 messages, ~995 tokens
Tokens saved: 36405 (97.3%)
Cost saved per request: $0.1092
Cost saved over 100 requests: $10.92

func NewManager

func NewManager(maxTokens int) *Manager

NewManager creates a new context manager

func (*Manager) GetUsage

func (m *Manager) GetUsage(messages []core.Message) ContextUsage

GetUsage returns current context usage information

func (*Manager) Prune

func (m *Manager) Prune(messages []core.Message) []core.Message

Prune prunes the messages according to the manager's strategy

func (*Manager) ShouldPrune

func (m *Manager) ShouldPrune(messages []core.Message) bool

ShouldPrune returns true if messages should be pruned

type PruneStrategy

type PruneStrategy int

PruneStrategy defines how to handle context pruning

const (
	// StrategyKeepAll preserves all messages without pruning
	StrategyKeepAll PruneStrategy = iota
	// StrategyPrune removes old messages when context limit is reached
	StrategyPrune
	// StrategySummarize summarizes old messages to save tokens
	StrategySummarize
)

type Summarizer

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

Summarizer creates summaries of conversation history

func NewSummarizer

func NewSummarizer(client *core.Client) *Summarizer

NewSummarizer creates a new summarizer

func (*Summarizer) ClearCache

func (s *Summarizer) ClearCache()

ClearCache clears the summary cache

func (*Summarizer) SummarizeMessages

func (s *Summarizer) SummarizeMessages(ctx context.Context, messages []core.Message) (string, error)

SummarizeMessages creates a concise summary of messages using Claude

Jump to

Keyboard shortcuts

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