Skip to content
reaatech

@reaatech/context-window-planner

npm v0.1.0

A TypeScript library providing typed context items, packing strategies, and tokenizer adapters for deciding what to include, summarize, or drop when fitting prompts into LLM context windows. It exports factory functions for six context item primitives (SystemPrompt, ConversationTurn, RAGChunk, ToolSchema, ToolResult, GenerationBuffer), four packing strategies (priority-greedy, sliding-window, summarize-and-replace, RAG relevance), and three tokenizer adapters (OpenAI/tiktoken, Anthropic approximate, mock), all orchestrated through a `ContextPlannerBuilder` class.

@reaatech/context-window-planner

npm version License: MIT CI

Status: Pre-1.0 — APIs may change in minor versions. Pin to a specific version in production.

Canonical TypeScript types, packing strategies, tokenizer adapters, and context item primitives for managing LLM context windows. This package is the single source of truth for deciding what to include, what to summarize, and what to drop when packing prompts for Claude, GPT, and other LLMs.

Installation

terminal
npm install @reaatech/context-window-planner
# or
pnpm add @reaatech/context-window-planner

Feature Overview

  • 88 exported types, classes, and factories — every context packing concept has a corresponding implementation
  • 6 typed context item primitivesSystemPrompt, ConversationTurn, RAGChunk, ToolSchema, ToolResult, GenerationBuffer
  • 4 packing strategies — priority-greedy, sliding-window, summarize-and-replace, and RAG relevance selection
  • 3 tokenizer adapters — OpenAI (tiktoken), Anthropic (approximate), and mock (for testing)
  • 7 typed error classes — all extend ContextPlannerError with stable error codes
  • Pluggable architecture — custom strategies, tokenizers, summarizers, and item types via interfaces
  • Deterministic and framework-agnostic — zero runtime dependencies beyond js-tiktoken
  • Dual ESM/CJS output — works with import and require

Quick Start

typescript
import {
  ContextPlannerBuilder,
  createTokenizer,
  createPriorityGreedyStrategy,
  createSystemPrompt,
  createConversationTurn,
  createGenerationBuffer,
  Priority,
} from "@reaatech/context-window-planner";
 
const tokenizer = createTokenizer("gpt-4");
 
const planner = new ContextPlannerBuilder()
  .withBudget(8000)
  .withReserved(1000)
  .withTokenizer(tokenizer)
  .withStrategy(createPriorityGreedyStrategy())
  .build();
 
planner.addAll([
  createSystemPrompt({ content: "You are a helpful assistant." }, tokenizer),
  createConversationTurn({ role: "user", content: "Hello!" }, tokenizer),
  createGenerationBuffer({ reservedTokens: 500 }),
]);
 
const result = planner.pack();
console.log(result.included.length, "items fit");
console.log(result.summarize.length, "items to summarize");
console.log(result.dropped.length, "items dropped");
console.log(result.warnings); // machine-readable warnings

API Reference

Context Items

Six built-in item types with factory functions that auto-compute tokenCount:

ExportDefault PrioritySummarizableDescription
SystemPrompt / createSystemPromptCriticalnoModel instructions, fixed at packing
ConversationTurn / createConversationTurnHighyesChat message with role, content, timestamp
ToolSchema / createToolSchemaHighnoFunction/tool definition with JSON Schema
ToolResult / createToolResultMediumyesTool execution output with toolName, result
RAGChunk / createRAGChunkMediumyesRetrieved document chunk with relevanceScore
GenerationBuffer / createGenerationBufferCriticalnoReserved output space, no content

All items implement the ContextItem interface (id, type, priority, tokenCount, canSummarize(), summarize?()). Summarizable items also implement Summarizable which adds estimatedSummarizedTokenCount and guarantees a summarize(targetTokens?) method.

Packing Strategies

StrategyNameOptionsBehavior
PriorityGreedyStrategypriority-greedynoneFill highest-priority items first, then fall through to lower ones
SlidingWindowStrategysliding-windowwindowSize, prioritizeRecentKeep N most recent conversation turns; older turns become summarizable
SummarizeAndReplaceStrategysummarize-replacecompressionRatio, maxSummaries, summarizerActively summarize items that don’t fit, up to maxSummaries
RelevanceScoredRAGStrategyrag-selectionragBudgetRatio, minRelevanceScore, maxChunksAllocate a budget fraction to RAG chunks sorted by relevance

Create strategies via the centralized factory:

typescript
import { strategies } from "@reaatech/context-window-planner";
 
const greedy = strategies.create("priority-greedy");
const window = strategies.create("sliding-window", { windowSize: 10 });
const replace = strategies.create("summarize-replace", { compressionRatio: 0.3 });
const rag = strategies.create("rag-selection", { ragBudgetRatio: 0.4, minRelevanceScore: 0.6 });

Or use the direct factory functions: createPriorityGreedyStrategy(), createSlidingWindowStrategy(opts), createSummarizeAndReplaceStrategy(opts), createRAGSelectionStrategy(opts).

Planner & Builder

ExportDescription
ContextPlannerMain planning engine. Manages items, budget, and strategy. Methods: add(), addAll(), remove(), removeByType(), pack(), repack(), plan(), getSummary(), getTokenUsage(), clear(), getItems(), fitsInBudget(), getBudget(). Property: isDirty.
ContextPlannerBuilderFluent builder. Methods: withBudget(), withTokenizer(), withStrategy(), withReserved(), withSafetyMargin(), addItem(), addItems(), build().
PriorityResolverDynamically adjusts item priorities based on recency, age decay, type overrides, and custom rules.

Token Budget

ExportDescription
TokenBudgetManages total, reserved, and available (total − reserved) tokens.
createBudgetValidates and creates a TokenBudget from raw values.
validateBudgetThrows ValidationError if budget is invalid.
safetyMargin (option)Defaults to 0.05 (5%), applied once inside the planner. Strategies work against budget.available directly.

Packing Result

Every pack() call returns a PackingResult:

FieldTypeDescription
includedReadonlyArray<ContextItem>Items packed as-is
summarizeReadonlyArray<ContextItem>Items to summarize before inclusion
droppedReadonlyArray<ContextItem>Items that didn’t fit
usedTokensnumberTotal tokens used by included items
remainingTokensnumberRemaining available tokens
warningsReadonlyArray<PackWarning>Machine-readable alerts (code, message, item?, suggestion?)

Tokenizer Adapters

AdapterModel PrefixDescription
TiktokenTokenizerAdaptergpt-4*, gpt-3.5*Accurate token counting via js-tiktoken
AnthropicTokenizerAdapterclaude*Approximate counting (~3.5 chars/token)
MockTokenizerAdaptermockDeterministic word-based counter for tests
typescript
import { tokenizers } from "@reaatech/context-window-planner";
 
const gpt4 = tokenizers.create("gpt-4");
const claude = tokenizers.create("claude-3-opus-20240229");
const mock = tokenizers.create("mock");

Or use createTokenizer(model) as a convenience alias.

Error Classes

All errors extend ContextPlannerError which includes code: string, message: string, and optional details?: Record<string, unknown>.

ClassCodeWhen
ContextPlannerError(base)Base class for all context planner errors
BudgetExceededErrorBUDGET_EXCEEDEDPacking result exceeds available budget
TokenCountErrorTOKEN_COUNT_ERRORToken counting failed
InvalidItemErrorINVALID_ITEMInvalid context item provided
TokenizerErrorTOKENIZER_ERRORTokenizer operation failed
StrategyErrorSTRATEGY_ERRORInvalid strategy configuration
ValidationErrorVALIDATION_ERRORInput validation failed
typescript
import { ContextPlannerError } from "@reaatech/context-window-planner";
 
try {
  const result = planner.pack();
} catch (err) {
  if (err instanceof ContextPlannerError) {
    console.error(err.code, err.message, err.details);
  }
}

Utilities

ExportDescription
generateIdGenerates unique IDs via crypto.randomUUID()
TokenCacheLRU cache for token counts keyed by content
PackingMemoizerMemoizes packing results by item fingerprint
validateContextItemValidates an item’s id, type, priority, and tokenCount
validateModelValidates model identifier is non-empty and ≤100 chars
truncateContentTruncates content to fit a target token count

Custom Strategies

Implement the PackingStrategy interface:

typescript
import type {
  PackingStrategy,
  PackingContext,
  PackingResult,
} from "@reaatech/context-window-planner";
 
class MyStrategy implements PackingStrategy {
  readonly name = "my-strategy";
 
  execute(context: PackingContext): PackingResult {
    // decide which items go into `included`, `summarize`, or `dropped`
    // and return usedTokens / remainingTokens / warnings
  }
}
 
const planner = new ContextPlanner({ budget: 128000, tokenizer, strategy: new MyStrategy() });

Examples

Runnable examples live in the repository under examples/:

ExampleDemonstrates
basic-packingMinimal end-to-end planner usage
conversation-managementSliding-window over chat history
custom-strategyImplementing a custom PackingStrategy
with-ragRelevance-scored RAG chunk selection

License

MIT