Releases: markhuangai/agentool
Release list
v1.5.2
Release 1.5.2
- Enhances output-validator errors with instance values, union-error collapse, error modes, prompt examples, and required-field hints.
- Bumps package metadata to 1.5.2.
v1.5.1
Changes
- Fix agent tool JSON schema for native Anthropic tool validation.
- Keep strict runtime validation for agent actions while exposing a flat provider-facing object schema.
- Add provider compatibility functional test for OpenAI-compatible and Anthropic protocols.
Verification
- npm run test:provider-compat
- npm run typecheck
- npm run lint
- npm test
v1.5.0
What's Changed
- Add the managed agent tool with start, wait, status, result, list, and stop actions.
- Add subagent task management with timeouts, wait polling, result formatting, and concurrency limits.
- Prevent recursive subagent spawning by stripping nested agent tools from child toolsets.
- Add unit, build, and real-AI functional coverage for the agent tool.
- Export agentool/agent and bump package metadata to 1.5.0.
Verification
- npm run lint
- npm run typecheck
- npm run test
- npm run test:functional
- npm run build
v1.4.0
Changes
- Add output-validator tool for validating final JSON output against an application-configured JSON Schema.
- Export output-validator from the root package and subpath export.
- Add README documentation and unit tests for per-turn schema validation.
- Update package version to 1.4.0 and test against ai 6.0.175.
Verification
- npm run typecheck
- npm run lint
- npm test
- npm run build
v1.3.0 - compactMessages helper (breaking)
v1.3.0 — compactMessages helper (breaking)
Why this release
The 1.2.0 createContextCompaction middleware was stateless: every over-threshold turn re-summarized the older history from scratch, since the AI SDK middleware contract gives no path to mutate the caller's messages array. That made compaction expensive on every subsequent turn and busted provider prompt caches (each summary was a non-deterministic new prefix).
Breaking changes
- Removed:
createContextCompaction,ContextCompactionConfig - Added:
compactMessages,CompactMessagesOptions,CompactSummarizer
The shape of the migration is one of intent — the old middleware ran on every model call automatically; the new function runs explicitly before each call and the caller assigns the result back. That's what makes the compacted state actually persist.
Migration
Before (1.2.x):
import { createContextCompaction } from 'agentool/context-compaction';
import { wrapLanguageModel, generateText } from 'ai';
const model = wrapLanguageModel({
model: anthropic('claude-sonnet-4-20250514'),
middleware: createContextCompaction({ maxContextTokens: 200_000 }),
});
const { text } = await generateText({ model, messages });After (1.3.0):
import { compactMessages } from 'agentool/context-compaction';
import { generateText } from 'ai';
const model = anthropic('claude-sonnet-4-20250514');
messages = await compactMessages({
messages,
summaryModel: model,
maxContextTokens: 200_000,
});
const { text } = await generateText({ model, messages });When usage is under threshold, compactMessages returns the same messages reference (===) — second-call cost is cheap, no LLM round trip.
Provider compatibility
Operates on the AI SDK's unified ModelMessage[], so works with any provider the SDK supports — OpenAI, Anthropic, Google Gemini, Mistral, xAI, etc. summaryModel need not match the main model (use a cheap summarizer with a powerful main model).
Output shape
[ ...leadingSystemPrefix,
{ role: 'user', content: <summary> },
{ role: 'assistant', content: 'Understood.' },
...lastNMessages ]
The synthetic user → assistant ack pair preserves role alternation (required by Anthropic and Google providers).
Tool-chain safety
The recent-window boundary auto-extends backwards via toolCallId and approvalId tracking, so tool-call / tool-result / tool-approval-request / tool-approval-response pairs are never split across the summarization boundary — no MissingToolResultsError from the SDK.
Other behavior
- Mid-conversation
systemmessages stay in place (only the leading contiguous system prefix is hoisted as system). - Multimodal content (images, files) is reduced to placeholders during summarization. Original binary data is gone from the persisted compacted history.
- Custom
summarizecallback is supported as an alternative tosummaryModel(e.g. local model, cached, or anything else).
Options
| Option | Type | Default |
|---|---|---|
messages |
ModelMessage[] |
required |
maxContextTokens |
number |
required |
summaryModel or summarize |
LanguageModelV3 or fn |
required (exactly one) |
autoCompactThresholdPct |
number (0-1) |
0.8 |
summaryTargetTokens |
number |
floor(maxContextTokens * 0.05) |
reservedOutputTokens |
number |
16384 |
keepRecentMessages |
number |
1 |
estimateTokens |
(msgs) => number |
char/4 heuristic |
onCompactionFailure |
'passthrough' | 'throw' |
'passthrough' |
Caveats
- Default token estimation is char/4 — coarse but provider-agnostic. For accuracy pass
estimateTokenswith a real tokenizer (e.g.tiktokenfor OpenAI,@anthropic-ai/tokenizerfor Anthropic). - Summary-of-summary degradation accumulates over very long sessions. Recommend periodic session restarts for long-lived agents.
🤖 Generated with Claude Code
v1.2.0 - Context Compaction Middleware
v1.2.0 - Context Compaction Middleware
Breaking Changes
- Removed:
contextCompactiontool (old LLM-callable implementation) - Added:
createContextCompactionmiddleware for Vercel AI SDK - Peer dependency:
aipackage bumped to>=5.0.17
New Features
The context-compaction middleware automatically summarizes conversation history when it exceeds a configurable threshold:
import { createContextCompaction } from 'agentool/context-compaction';
import { wrapLanguageModel } from 'ai';
const model = wrapLanguageModel({
model: anthropic('claude-sonnet-4-20250514'),
middleware: createContextCompaction({
maxContextTokens: 200_000,
autoCompactThresholdPct: 0.80,
summaryTargetPct: 0.05,
}),
});Configuration options:
maxContextTokens- Model's context window size (required)autoCompactThresholdPct- Trigger compaction at this usage % (default: 0.80)summaryTargetPct- Target summary size as % of max (default: 0.05)reservedOutputTokens- Tokens reserved for output (default: 16384)estimateTokens- Custom token estimator functionsummarize- Custom summarizer functiononCompactionFailure- 'passthrough' or 'throw' (default: 'passthrough')
Technical Details
- Middleware intercepts
generateText/streamTextcalls viawrapLanguageModel - Preserves system messages verbatim
- Maintains recent conversation window (~20% of context)
- Handles cross-provider compatibility (OpenAI, Anthropic, Google)
- Role alternation preserved for Anthropic compatibility
Testing
- 26 unit tests for middleware logic
- 2 functional tests with real LLM
- All 437 tests passing
v1.1.1
What's Changed
Internal Refactoring
- Centralized filesystem access: All
node:fsoperations now route throughsrc/shared/file.tswith 4 new utilities (readTextContent,listDirectory,removeFile,getFileStats) - Unified error handling: Extracted
extractErrorMessage()tosrc/shared/errors.ts, replacing 21 duplicated patterns across all tools - Deduplicated
countOccurrences: Moved tosrc/shared/edit-helpers.tswith explicit non-overlapping semantics, shared by botheditandmulti-edit - ESLint enforcement: Added
no-restricted-importsrule banning directnode:fsimports outside ofsrc/shared/file.ts
Testing
- Added 22 new unit tests for all new shared utilities
- All 420 unit tests and 30 functional tests passing
No public API changes. This is a purely internal quality improvement.
v1.1.0
What's New
6 New Tools
- task-create — Create tasks with subject, description, and metadata
- task-get — Retrieve a task by ID
- task-update — Update status, owner, metadata, and dependencies (blocks/blockedBy)
- task-list — List all non-deleted tasks
- web-search — Callback-based web search with domain filtering
- tool-search — Registry-based tool discovery by name/keyword
Aligned with Claude Code
- Read —
file_pathenforces "absolute path";offsetvalidates.int().nonnegative();limitvalidates.int().positive() - Write —
file_pathdescription says "absolute path, not relative" - Edit —
file_pathdescription says "absolute path to modify";replace_alluses.default(false).optional() - Grep — All 14 parameter descriptions match Claude Code verbatim
- WebFetch —
urluses.url()validation; unusedpromptparam removed - LSP — 1-based indexing (required),
prepareCallHierarchyadded,queryremoved, boundary conversion
Breaking Changes
agentool/taskremoved — replaced byagentool/task-create,agentool/task-get,agentool/task-update,agentool/task-list- LSP
line/characterare now required and 1-based (previously optional, 0-based) - LSP
queryparameter removed - WebFetch
promptparameter removed - WebFetch rejects invalid URLs at schema level
Infrastructure
- 22 tools total (was 16), 22 subpath exports
- Shared task store at
src/shared/task-store.ts - 398 unit tests, 30 functional tests (all with real AI provider)
- Full pipeline: typecheck, lint, test, functional test, build — all pass