compilr-dev/agents:轻量级多 LLM 智能体库
compilr-dev/agents
compilr-dev 发布轻量级多 LLM 智能体库 agents,支持 Claude、OpenAI、Gemini、Ollama 等 9 家提供商,内置 17 个工具、9 类子智能体、11 个技能模板,并具备上下文压缩、事件流、护栏与权限控制。
\|/
╭══════════╮ ___ ___ _ __ ___ _ __ (_) |_ __
║' ▐▌ ▐▌ │ / __|/ _ \| '_ ` _ \| '_ \| | | '__|
║ │ | (__| (_) | | | | | | |_) | | | |
╰─═──────═─╯ \___|\___/|_| |_| |_| .__/|_|_|_|
\________\ | | .dev
|_| agents
Lightweight multi-LLM agent library for building CLI AI assistants
API Reference | llms.txt (for AI agents)
Warning
This package is in beta. APIs may change between minor versions.
Features
- Multi-LLM Support: 9 providers -- Claude, OpenAI, Gemini, Ollama (local), Together AI, Groq, Fireworks, Perplexity, OpenRouter
- 17 Built-in Tools: File ops, bash, grep, glob, edit, web fetch, sub-agents, todos, backlog, and more
- Sub-agents: Spawn specialized agents for complex tasks (9 built-in agent types)
- 11 Skills: Reusable prompt templates for common workflows
- Context Management: Token budgeting, compaction, summarization
- Event Streaming: Real-time execution monitoring with typed events and abort support
- Anchors: Critical information that survives context compaction
- Guardrails: 15 built-in patterns for safety checks (warn/confirm/block)
- Permissions: Tool-level access control (always/session/once/deny) with wildcards
- Project Memory: Auto-loads CLAUDE.md, GEMINI.md, CURSOR.md, and more
- Hooks System: Lifecycle hooks for beforeChat, afterChat, beforeToolCall, afterToolCall
- Rate Limiting: Automatic retry with exponential backoff
- TypeScript First: Full type safety with strict mode
Installation
npm install @compilr-dev/agents
For Claude support:
npm install @compilr-dev/agents @anthropic-ai/sdk
Quick Start
import { Agent, MockProvider } from '@compilr-dev/agents'; // Create an agent with a provider const provider = new MockProvider(); provider.addResponse('Hello! How can I help you today?'); const agent = new Agent({ provider, systemPrompt: 'You are a helpful assistant.', }); // Run the agent const result = await agent.run('Hello!'); console.log(result.response); // "Hello! How can I help you today?" console.log(result.iterations); // 1
With Claude
import { Agent, ClaudeProvider } from '@compilr-dev/agents'; const agent = new Agent({ provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }), systemPrompt: 'You are a helpful coding assistant.', maxIterations: 10, }); const result = await agent.run('Explain async/await in JavaScript'); console.log(result.response);
Core Concepts
Agent
The Agent class orchestrates LLM interactions and tool execution:
import { Agent, ClaudeProvider } from '@compilr-dev/agents'; const agent = new Agent({ provider: new ClaudeProvider({ apiKey: 'your-key' }), systemPrompt: 'You are a helpful assistant.', maxIterations: 10, // Default: 10 onEvent: (event) => { // Real-time execution monitoring console.log(event.type); }, });
Messages
The library provides utilities for working with conversation messages:
import { createUserMessage, createAssistantMessage, createToolResultMessage, getTextContent } from '@compilr-dev/agents'; // Create messages const userMsg = createUserMessage('Hello!'); const assistantMsg = createAssistantMessage('Hi there!'); // Extract text from message with multiple content blocks const text = getTextContent(assistantMsg);
Tools
Define tools that agents can use:
import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents'; const calculatorTool = defineTool({ name: 'calculator', description: 'Perform basic math operations', inputSchema: { type: 'object', properties: { operation: { type: 'string', description: 'add, subtract, multiply, divide' }, a: { type: 'number' }, b: { type: 'number' }, }, required: ['operation', 'a', 'b'], }, execute: async ({ operation, a, b }) => { switch (operation) { case 'add': return createSuccessResult(a + b); case 'subtract': return createSuccessResult(a - b); case 'multiply': return createSuccessResult(a * b); case 'divide': if (b === 0) return createErrorResult('Division by zero'); return createSuccessResult(a / b); default: return createErrorResult(`Unknown operation: ${operation}`); } }, }); // Register with agent agent.registerTool(calculatorTool);
Tool Registry
Manage tools with the registry:
import { DefaultToolRegistry, defineTool } from '@compilr-dev/agents'; const registry = new DefaultToolRegistry(); // Register tools registry.register(myTool); // Get tool definitions for LLM const definitions = registry.getDefinitions(); // Execute a tool const result = await registry.execute('tool_name', { arg: 'value' });
Built-in Tools
File Operations
import { readFileTool, writeFileTool } from '@compilr-dev/agents'; agent.registerTool(readFileTool); agent.registerTool(writeFileTool);
Bash Execution
import { createBashTool } from '@compilr-dev/agents'; const bashTool = createBashTool({ workingDir: '/path/to/project', timeout: 30000, // 30 seconds allowedCommands: ['git', 'npm', 'ls'], // Optional whitelist }); agent.registerTool(bashTool);
Event System
Monitor agent execution in real-time:
import type { AgentEvent } from '@compilr-dev/agents'; const agent = new Agent({ provider, onEvent: (event: AgentEvent) => { switch (event.type) { case 'iteration_start': console.log(`Starting iteration ${event.iteration}`); break; case 'llm_start': console.log('LLM thinking...'); break; case 'llm_end': console.log(`LLM done, tool uses: ${event.hasToolUses}`); break; case 'tool_start': console.log(`Calling tool: ${event.name}`); break; case 'tool_end': console.log(`Tool result: ${event.result.success}`); break; case 'done': console.log(`Final: ${event.response}`); break; } }, });
Streaming Events
For CLI applications, stream events as they happen:
for await (const event of agent.stream('Hello!')) { if (event.type === 'llm_chunk') { process.stdout.write(event.chunk.text || ''); } }
Abort Support
Cancel running agents:
const controller = new AbortController(); // Cancel after 5 seconds setTimeout(() => controller.abort(), 5000); try { const result = await agent.run('Complex task...', { signal: controller.signal, }); } catch (error) { if (error instanceof AbortError) { console.log('Agent was cancelled'); } }
Error Handling
The library provides specific error types:
import { AgentError, ProviderError, ToolError, ValidationError, MaxIterationsError, AbortError, isAgentError, isProviderError, isToolError, wrapError, } from '@compilr-dev/agents'; try { await agent.run('...'); } catch (error) { if (isProviderError(error)) { console.log(`Provider ${error.provider} failed: ${error.message}`); } else if (isToolError(error)) { console.log(`Tool ${error.toolName} failed: ${error.message}`); } else if (error instanceof MaxIterationsError) { console.log(`Reached max iterations: ${error.maxIterations}`); } }
Providers
Built-in Providers
import { ClaudeProvider, // Anthropic Claude OpenAIProvider, // OpenAI GPT GeminiProvider, // Google Gemini OllamaProvider, // Local models (no API key) TogetherProvider, // Together AI GroqProvider, // Groq (fast inference) FireworksProvider, // Fireworks AI PerplexityProvider, // Perplexity (search-augmented) OpenRouterProvider, // OpenRouter (multi-provider) } from '@compilr-dev/agents'; // Claude (recommended) const claude = new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY, model: 'claude-sonnet-4-20250514', }); // OpenAI const openai = new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY, model: 'gpt-4o', }); // Gemini const gemini = new GeminiProvider({ apiKey: process.env.GOOGLE_AI_API_KEY, model: 'gemini-2.0-flash', }); // Ollama (local, no API key) const ollama = new OllamaProvider({ model: 'llama3.1:8b', baseUrl: 'http://localhost:11434', });
MockProvider (for testing)
import { MockProvider } from '@compilr-dev/agents'; const provider = new MockProvider(); // Queue responses provider.addResponse('Simple text response'); provider.addResponse({ text: 'Using a tool...', toolCalls: [{ id: 'call_1', name: 'my_tool', input: { arg: 'value' } }], }); // Queue an error provider.addError(new Error('API failed')); // Add delay provider.addResponse('Delayed response', 1000); // Access history console.log(provider.history); // All chat() calls
Custom Providers
Implement the LLMProvider interface:
import type { LLMProvider, Message, ChatOptions, StreamChunk } from '@compilr-dev/agents'; class MyProvider implements LLMProvider { readonly name = 'my-provider'; async *chat( messages: Message[], options?: ChatOptions ): AsyncIterable<StreamChunk> { // Your implementation yield { type: 'text', text: 'Response text' }; yield { type: 'end', stopReason: 'end_turn' }; } async countTokens(messages: Message[]): Promise<number> { // Optional token counting return messages.length * 100; } }
API Reference
Agent
class Agent { constructor(options: AgentOptions); // Run agent and return final result run(userMessage: string, options?: RunOptions): Promise<AgentResult>; // Stream events during execution stream(userMessage: string, options?: RunOptions): AsyncIterable<AgentEvent>; // Tool management registerTool(tool: Tool): void; registerTools(tools: Tool[]): void; getToolDefinitions(): ToolDefinition[]; }
Types
interface AgentOptions { provider: LLMProvider; systemPrompt?: string; maxIterations?: number; onEvent?: (event: AgentEvent) => void; } interface RunOptions { signal?: AbortSignal; } interface AgentResult { response: string; iterations: number; toolCalls: ToolCallInfo[]; } type AgentEvent = | { type: 'iteration_start'; iteration: number } | { type: 'llm_start' } | { type: 'llm_chunk'; chunk: StreamChunk } | { type: 'llm_end'; text: string; hasToolUses: boolean } | { type: 'tool_start'; name: string; input: Record<string, unknown> } | { type: 'tool_end'; name: string; result: ToolExecutionResult } | { type: 'iteration_end'; iteration: number } | { type: 'done'; response: string };
Context Management
Manage context windows in long-running agent sessions:
import { ContextManager, DEFAULT_CONTEXT_CONFIG } from '@compilr-dev/agents'; const contextManager = new ContextManager({ provider, config: { maxContextTokens: 200000, // Claude's limit compaction: { triggerThreshold: 0.5, // Compact at 50% utilization preserveRecentTurns: 10, // Keep last 10 turns }, summarization: { triggerThreshold: 0.9, // Summarize at 90% preserveRecentMessages: 6, }, }, onEvent: (event) => { if (event.type === 'context_warning') { console.log(`Context at ${event.utilization * 100}%`); } }, }); // Track token usage await contextManager.updateTokenCount(messages); console.log(`Utilization: ${contextManager.getUtilization() * 100}%`); // Check if action needed if (contextManager.needsSummarization()) { const { messages: summarized } = await contextManager.summarize( messages, async (msgs) => 'Summary of conversation...' // Your LLM call ); } // Filter large content before adding const { content, filtered } = contextManager.filterContent( largeToolResult, 'tool_result' );
Context Strategies
| Strategy | Trigger | Reversible | Description |
|---|---|---|---|
| Filtering | Before add | N/A | Truncate large content (>80K tokens) |
| Compaction | 50% or 20 turns | Yes | Save old results to files |
| Summarization | 90% | No | Compress entire history |
Anchors (Critical Information Persistence)
Anchors are critical pieces of information that survive context compaction. They're automatically re-injected into every LLM call:
import { Agent, AnchorManager, ClaudeProvider } from '@compilr-dev/agents'; const agent = new Agent({ provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }), systemPrompt: 'You are a helpful assistant.', anchors: { maxAnchors: 20, // Maximum number of anchors maxTokens: 2000, // Token budget for anchors includeDefaults: true, // Include safety anchors (git, file operations) }, }); // Add a session anchor (survives until session ends) agent.addAnchor({ content: 'User prefers TypeScript with strict mode', priority: 'critical', scope: 'session', }); // Add a persistent anchor (saved to disk) agent.addAnchor({ content: 'Never modify files in /etc', priority: 'safety', scope: 'persistent', tags: ['filesystem'], }); // Add a temporary anchor (expires after a time) agent.addAnchor({ content: 'Currently debugging the auth module', priority: 'info', scope: 'temporary', expiresAt: new Date(Date.now() + 3600000), // 1 hour });
Anchor Priorities
| Priority | Description | Format in LLM |
|---|---|---|
critical |
Must remember | ### CRITICAL (Must Remember) |
safety |
Check before acting | ### SAFETY (Check Before Acting) |
info |
Contextual information | ### INFO |
Standalone AnchorManager
import { AnchorManager } from '@compilr-dev/agents'; const anchors = new AnchorManager({ maxAnchors: 20, maxTokens: 2000, persistPath: '~/.myapp/anchors.json', // Optional persistence includeDefaults: true, }); // Add anchors anchors.add({ content: 'Important info', priority: 'critical', scope: 'session' }); // Query anchors const critical = anchors.getAll({ priority: 'critical' }); const tagged = anchors.getAll({ tags: ['git'] }); // Format for LLM injection const formatted = anchors.format(); // Returns: // ### CRITICAL (Must Remember) // - Important info // Monitor token usage console.log(`Utilization: ${anchors.getUtilization() * 100}%`);
Guardrails (Safety Checks)
Guardrails are pattern-based safety checks that run before tool execution. They can warn, require confirmation, or block dangerous operations:
import { Agent, ClaudeProvider } from '@compilr-dev/agents'; const agent = new Agent({ provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }), systemPrompt: 'You are a helpful assistant.', guardrails: { enabled: true, includeDefaults: true, // 15 built-in patterns for git, rm, DROP TABLE, etc. custom: [ { id: 'no-prod-db', name: 'Production Database Protection', description: 'Prevent operations on production database', patterns: [/prod.*db/i, /production.*database/i], action: 'block', // 'warn' | 'confirm' | 'block' message: 'Operations on production database are blocked', scope: ['bash'], // Optional: limit to specific tools tags: ['database', 'production'], }, ], onTriggered: async (result, context) => { // Handle 'confirm' actions if (result.action === 'confirm') { return await askUserConfirmation(result.guardrail.message); } return result.action !== 'block'; }, }, });
Built-in Guardrails
| ID | Action | Pattern | Description |
|---|---|---|---|
git-reset-hard |
confirm | git reset --hard |
Prevents accidental loss of uncommitted changes |
git-push-force |
confirm | git push --force |
Prevents force pushing to branches |
rm-rf |
confirm | rm -rf |
Prevents recursive deletion |
rm-root |
block | rm -rf / |
Blocks deletion of root filesystem |
drop-table |
confirm | DROP TABLE |
Prevents accidental table deletion |
truncate-table |
confirm | TRUNCATE |
Prevents data loss |
delete-where-all |
warn | DELETE FROM without WHERE |
Warns about deleting all rows |
secrets-env |
warn | API keys, passwords | Warns about exposing secrets |
chmod-777 |
warn | chmod 777 |
Warns about insecure permissions |
curl-pipe-bash |
block | `curl | bash` |
eval-code |
warn | eval() patterns |
Warns about code injection risks |
sudo-rm |
confirm | sudo rm |
Confirms privileged deletion |
git-clean |
confirm | git clean -fd |
Confirms removing untracked files |
format-disk |
block | mkfs, dd |
Blocks disk formatting |
kill-all |
confirm | killall, pkill |
Confirms killing processes |
Standalone GuardrailManager
import { GuardrailManager, getGuardrailsByTag } from '@compilr-dev/agents'; const guardrails = new GuardrailManager({ enabled: true, includeDefaults: true, }); // Check before tool execution const result = guardrails.check('bash', { command: 'rm -rf /tmp/test' }); if (result.triggered) { console.log(`Guardrail triggered: ${result.guardrail.name}`); console.log(`Action: ${result.action}`); // 'warn' | 'confirm' | 'block' console.log(`Message: ${result.guardrail.message}`); } // Check and handle (with confirmation callback) const { proceed, result } = await guardrails.checkAndHandle('bash', input); if (!proceed) { console.log('Operation blocked by guardrail'); } // Get guardrails by tag const gitGuardrails = getGuardrailsByTag('git'); const destructiveGuardrails = getGuardrailsByTag('destructive'); // Enable/disable individual guardrails guardrails.disable('rm-rf'); guardrails.enable('rm-rf');
Guardrail Events
Monitor guardrail activity:
guardrails.onEvent((event) => { switch (event.type) { case 'guardrail:triggered': console.log(`Guardrail ${event.result.guardrail.name} triggered`); break; case 'guardrail:blocked': console.log('Operation blocked'); break; case 'guardrail:warning': console.log('Warning issued'); break; case 'guardrail:confirmed': console.log('User confirmed dangerous operation'); break; case 'guardrail:cancelled': console.log('User cancelled operation'); break; } });
Permissions (Tool-level Access Control)
Permissions provide fine-grained control over which tools can execute and when user approval is required:
import { Agent, ClaudeProvider } from '@compilr-dev/agents'; const agent = new Agent({ provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }), systemPrompt: 'You are a helpful assistant.', permissions: { enabled: true, defaultLevel: 'always', // Default for tools without rules includeDefaults: true, // Include default rules for bash, write_file, edit rules: [ { toolName: 'bash', level: 'once', description: 'Shell commands' }, { toolName: 'write_file', level: 'session', description: 'File writes' }, { toolName: 'delete_*', level: 'deny', description: 'Delete operations' }, ], onPermissionRequest: async (request) => { // Handle permission requests (e.g., prompt user) console.log(`Tool: ${request.toolName}`); console.log(`Preview: ${request.preview}`); return await askUser(`Allow ${request.toolName}?`); }, }, });
Permission Levels
| Level | Description | Behavior |
|---|---|---|
always |
No approval needed | Tool executes immediately |
session |
Ask once per session | After approval, tool runs freely |
once |
Ask every time | User must approve each execution |
deny |
Always blocked | Tool cannot execute |
Wildcard Patterns
Permission rules support wildcards for flexible matching:
// Match all tools starting with "delete_" { toolName: 'delete_*', level: 'deny' } // Match all tools ending with "_file" { toolName: '*_file', level: 'session' } // Match tools containing "dangerous" { toolName: '*dangerous*', level: 'once' }
Standalone PermissionManager
import { PermissionManager } from '@compilr-dev/agents'; const permissions = new PermissionManager({ enabled: true, defaultLevel: 'always', onPermissionRequest: async (request) => { return await promptUser(request.preview); }, }); // Add rules dynamically permissions.addRule({ toolName: 'bash', level: 'once', description: 'Shell commands', tags: ['shell', 'dangerous'], }); // Check permission before execution const result = await permissions.check('bash', { command: 'rm -rf /tmp/test' }); if (result.allowed) { // Proceed with execution } else { console.log(`Denied: ${result.reason}`); } // Grant session-level permission programmatically permissions.grantSession('write_file'); // Check if tool has session grant if (permissions.hasSessionGrant('write_file')) { console.log('write_file approved for this session'); }
Permission Events
Monitor permission activity:
permissions.onEvent((event) => { switch (event.type) { case 'permission:granted': console.log(`${event.toolName} allowed`); break; case 'permission:denied': console.log(`${event.toolName} denied`); break; case 'permission:asked': console.log(`Asking about ${event.toolName}`); break; case 'permission:session_granted': console.log(`${event.toolName} approved for session`); break; } });
Permissions vs Guardrails
Both systems provide safety, but serve different purposes:
| Aspect | Permissions | Guardrails |
|---|---|---|
| Purpose | Access control | Content safety |
| Scope | Tool-level | Input patterns |
| Timing | Before tool call | Before execution |
| Typical Use | "Can this tool run?" | "Is this input safe?" |
| User Interaction | Session/once approval | Confirm dangerous ops |
Use them together for comprehensive safety:
- Permissions control which tools can be used
- Guardrails check what inputs are safe
Project Memory (CLAUDE.md, GEMINI.md, etc.)
Project Memory automatically discovers and loads project-specific instructions from markdown files. It supports various LLM-specific naming conventions:
| Provider | Files Searched |
|---|---|
| Claude | CLAUDE.md, .claude.md, .claude/instructions.md |
| Gemini | GEMINI.md, .gemini.md, .gemini/instructions.md |
| OpenAI/GPT | OPENAI.md, GPT.md, CHATGPT.md |
| Copilot | COPILOT.md, .github/copilot-instructions.md |
| Cursor | CURSOR.md, .cursorrules, .cursor/rules |
| Generic | PROJECT.md, INSTRUCTIONS.md, AI.md, CONTEXT.md |
Using with Agent
import { Agent, ClaudeProvider } from '@compilr-dev/agents'; // Option 1: Factory method (recommended) const agent = await Agent.createWithMemory( { provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }), systemPrompt: 'You are a helpful assistant.', }, { providers: 'claude', includeGeneric: true }, '/path/to/project' // defaults to cwd ); // Access loaded memory const memory = agent.getProjectMemory(); console.log(`Loaded ${memory?.files.length} instruction files`); // Option 2: Pre-load memory manually import { ProjectMemoryLoader } from '@compilr-dev/agents'; const loader = new ProjectMemoryLoader({ providers: ['claude', 'gemini'], includeGeneric: true, }); const memory = await loader.load('/path/to/project'); const agent = new Agent({ provider, systemPrompt: 'You are a helpful assistant.', projectMemory: memory, });
Multiple Providers
Search for instructions from multiple LLM providers:
const agent = await Agent.createWithMemory( { provider }, { providers: ['claude', 'gemini', 'openai'], includeGeneric: true, // Also search PROJECT.md, AI.md, etc. combineStrategy: 'concat', // Combine all found files } );
ProjectMemoryLoader Options
const loader = new ProjectMemoryLoader({ // Provider(s) to search for providers: 'claude', // or ['claude', 'gemini'] // Include generic patterns (PROJECT.md, AI.md, etc.) includeGeneric: true, // Search parent directories up to git root searchParents: true, stopAtGitRoot: true, maxParentDepth: 10, // How to combine multiple files combineStrategy: 'concat', // 'concat' | 'priority' | 'dedupe' // Content limits maxContentSize: 100000, // 100KB max // Headers in combined output includeHeaders: true, headerFormat: '# From: {relativePath}\n\n', });
Combine Strategies
| Strategy | Description |
|---|---|
concat |
Concatenate all files with separators (default) |
priority |
Use only the highest priority file |
dedupe |
Concatenate but remove duplicate content |
Custom Patterns
Add custom file patterns for your own naming conventions:
const loader = new ProjectMemoryLoader({ providers: 'claude', customPatterns: [ { pattern: 'TEAM-RULES.md', priority: 0, description: 'Team rules' }, { pattern: '.ai-config.md', priority: 1, description: 'AI config' }, ], });
Standalone Usage
Use the loader without an Agent:
import { loadProjectMemory, hasProjectMemory, getSupportedProviders, getProviderPatterns, } from '@compilr-dev/agents'; // Quick check if memory files exist if (await hasProjectMemory('/path/to/project', { providers: 'claude' })) { console.log('Found project instructions!'); } // Load memory directly const memory = await loadProjectMemory('/path/to/project', { providers: ['claude', 'gemini'], }); console.log(`Loaded ${memory.files.length} files`); console.log(`Estimated tokens: ${memory.estimatedTokens}`); // Get patterns for a provider const patterns = getProviderPatterns('cursor'); // Returns: [{ pattern: 'CURSOR.md', ... }, { pattern: '.cursorrules', ... }] // List all supported providers const providers = getSupportedProviders(); // Returns: ['claude', 'anthropic', 'gemini', 'openai', 'gpt', 'copilot', 'cursor', 'codeium']
Rate Limiting
Protect against API rate limits with automatic retry and backoff:
import { Agent, ClaudeProvider, createRateLimitedProvider } from '@compilr-dev/agents'; // Wrap any provider with rate limiting const provider = createRateLimitedProvider( new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }), { maxRequestsPerMinute: 50, maxTokensPerMinute: 100000, maxRetries: 3, initialBackoffMs: 1000, maxBackoffMs: 60000, backoffMultiplier: 2, onRateLimited: (info) => { console.log(`Rate limited, waiting ${info.waitMs}ms`); }, } ); const agent = new Agent({ provider });
Standalone Rate Limiter
import { RateLimiter } from '@compilr-dev/agents'; const limiter = new RateLimiter({ maxRequestsPerMinute: 60, maxTokensPerMinute: 100000, }); // Check before making requests await limiter.waitForCapacity(); // Record usage after requests limiter.recordRequest(1500); // tokens used // Check current state console.log(`Requests remaining: ${limiter.getAvailableRequests()}`); console.log(`Tokens remaining: ${limiter.getAvailableTokens()}`);
Usage Tracking
Track token usage across agent sessions:
import { Agent, ClaudeProvider } from '@compilr-dev/agents'; const agent = new Agent({ provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }), usage: { enabled: true, warnThresholds: { inputTokens: 100000, outputTokens: 50000, }, onWarning: (warning) => { console.log(`Usage warning: ${warning.metric} at ${warning.currentValue}`); }, }, }); // After running the agent const result = await agent.run('Hello!'); // Get usage stats const usage = agent.getUsage(); console.log(`Input tokens: ${usage.inputTokens}`); console.log(`Output tokens: ${usage.outputTokens}`); console.log(`Total tokens: ${usage.totalTokens}`); console.log(`Requests: ${usage.requests}`);
Rehearsal System (Impact Analysis)
Rehearsal analyzes potentially destructive operations before execution, showing what files and git state would be affected:
import { Agent, ClaudeProvider } from '@compilr-dev/agents'; const agent = new Agent({ provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }), rehearsal: { enabled: true, gitAnalysis: true, // Analyze git impact fileAnalysis: true, // Analyze file impact autoConfirm: false, // Require user confirmation workingDirectory: '/path/to/project', onRehearsalComplete: async (result) => { console.log('=== Rehearsal Report ==='); console.log(`Files affected: ${result.files?.filesAffected || 0}`); console.log(`Git impact: ${result.git?.summary || 'None'}`); // Return true to proceed, false to cancel return await askUserConfirmation('Proceed with these changes?'); }, }, }); // Destructive operations trigger rehearsal automatically await agent.run('Delete all .log files and reset the git branch');
Rehearsal Report
The rehearsal system provides detailed impact analysis:
interface RehearsalResult { files?: { filesAffected: number; deletions: string[]; modifications: string[]; creations: string[]; totalSizeImpact: number; }; git?: { hasUncommittedChanges: boolean; uncommittedFiles: string[]; branchesAffected: string[]; commitsAffected: number; summary: string; }; riskLevel: 'low' | 'medium' | 'high' | 'critical'; warnings: string[]; }
Task Tool (Sub-Agents)
Spawn specialized sub-agents for complex tasks:
import { Agent, ClaudeProvider, createTaskTool } from '@compilr-dev/agents'; const taskTool = createTaskTool({ provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }), agentTypes: { explore: { systemPrompt: 'You are a code exploration expert.', tools: ['read_file', 'glob', 'grep'], contextMode: 'full', // Inherit full conversation context }, 'code-review': { systemPrompt: 'You are a code reviewer.', tools: ['read_file', 'grep'], contextMode: 'summary', // Get summarized context }, refactor: { systemPrompt: 'You are a refactoring expert.', tools: ['read_file', 'write_file', 'edit'], contextMode: 'none', // No inherited context }, }, defaultThoroughness: 'medium', // 'quick' | 'medium' | 'thorough' maxConcurrentTasks: 3, }); agent.registerTool(taskTool); // The LLM can now spawn sub-agents: // task({ agentType: 'explore', prompt: 'Find all React components' })
Built-in Agent Types
| Type | Purpose | Default Tools |
|---|---|---|
explore |
Codebase exploration | glob, grep, read_file |
code-review |
Code quality review | read_file, grep |
refactor |
Code refactoring | read_file, write_file, edit |
test-runner |
Running tests | bash, read_file |
doc-lookup |
Documentation search | read_file, grep, web_fetch |
debug |
Debugging assistance | read_file, grep, bash |
security-audit |
Security analysis | read_file, grep |
plan |
Task planning | read_file, glob |
general |
General purpose | All tools |
Hooks System
Extend agent behavior with lifecycle hooks:
import { Agent, ClaudeProvider, HooksManager } from '@compilr-dev/agents'; const hooks = new HooksManager(); // Before each LLM call hooks.register('beforeChat', async (context) => { console.log(`Sending ${context.messages.length} messages`); // Modify messages if needed return { messages: context.messages }; }); // After each LLM response hooks.register('afterChat', async (context) => { console.log(`Received: ${context.response.text?.slice(0, 50)}...`); }); // Before tool execution hooks.register('beforeToolCall', async (context) => { console.log(`Calling ${context.toolName} with`, context.input); // Return { skip: true } to skip execution }); // After tool execution hooks.register('afterToolCall', async (context) => { console.log(`${context.toolName} returned:`, context.result); // Modify result if needed return { result: context.result }; }); const agent = new Agent({ provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }), hooks, });
Skills
Skills are reusable prompt templates that enhance agent capabilities:
import { Agent, ClaudeProvider, SkillsManager, BUILTIN_SKILLS } from '@compilr-dev/agents'; // Use built-in skills const skills = new SkillsManager({ skills: BUILTIN_SKILLS, // code-review, debug, explain, refactor, planning, security-review }); const agent = new Agent({ provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }), skills, }); // Invoke a skill const result = await agent.run('/skill code-review src/auth.ts');
Custom Skills
const customSkills = new SkillsManager({ skills: [ { name: 'optimize', description: 'Optimize code for performance', prompt: `Analyze the following code and suggest performance optimizations: - Identify bottlenecks - Suggest algorithmic improvements - Recommend caching strategies - Consider memory usage`, tags: ['performance', 'optimization'], }, ], });
Built-in Skills
| Skill | Description |
|---|---|
code-review |
Comprehensive code review with quality, security, and style feedback |
debug |
Step-by-step debugging assistance |
explain |
Clear explanations of code functionality |
refactor |
Refactoring suggestions with clean code principles |
planning |
Task breakdown and implementation planning |
security-review |
Security vulnerability analysis |
Tracing & Logging
Monitor agent execution with structured logging:
import { Agent, ClaudeProvider, TracingManager } from '@compilr-dev/agents'; const tracing = new TracingManager({ enabled: true, logLevel: 'info', // 'debug' | 'info' | 'warn' | 'error' destination: 'console', // or 'file' or custom function filePath: './agent-logs.jsonl', includeTimestamps: true, redactPatterns: [/api[_-]?key/i, /password/i], // Redact sensitive data }); const agent = new Agent({ provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }), tracing, }); // Logs include: // - LLM requests/responses // - Tool calls and results // - Errors and warnings // - Timing information
OpenTelemetry Integration
import { createOtelTracing } from '@compilr-dev/agents'; // Export traces to your observability platform const tracing = createOtelTracing({ serviceName: 'my-agent', endpoint: 'http://localhost:4318/v1/traces', }); const agent = new Agent({ provider, tracing });
Requirements
- Node.js 18 or higher
- API Key for your chosen provider (except Ollama)
Peer Dependencies
@anthropic-ai/sdk(optional, for Claude)@modelcontextprotocol/sdk(optional, for MCP)
Design Philosophy
- Minimal dependencies: Only
@anthropic-ai/sdkand@modelcontextprotocol/sdkas optional peer deps - Type safety: Full TypeScript support with strict mode
- Extensibility: Easy to add new providers and tools
- Testability: MockProvider for easy unit testing
- Real-time feedback: Event system for CLI applications
Related Packages
- @compilr-dev/cli - AI-powered CLI assistant
- @compilr-dev/agents-coding - Coding-specific tools (git, runners, code search)
Links
License
FSL-1.1-MIT - See LICENSE for details. Converts to MIT after 2 years per version.
Built with care by compilr.dev
来源:GitHub · github.com