@compilr-dev/agents

中文文档
0.9.1发布于 2026/10/19FSL-1.1-MITTypeScriptES Module近 30 天下载 4204

Lightweight multi-LLM agent library for building CLI AI assistants

原始使用文档
文档目录64 节
  1. Features
  2. Installation
  3. Quick Start
  4. With Claude
  5. Core Concepts
  6. Agent
  7. Messages
  8. Tools
  9. Tool Registry
  10. Built-in Tools
  11. File Operations
  12. Bash Execution
  13. Event System
  14. Streaming Events
  15. Abort Support
  16. Error Handling
  17. Providers
  18. Built-in Providers
  19. MockProvider (for testing)
  20. Custom Providers
  21. API Reference
  22. Agent
  23. Types
  24. Context Management
  25. Context Strategies
  26. Anchors (Critical Information Persistence)
  27. Anchor Priorities
  28. Standalone AnchorManager
  29. Guardrails (Safety Checks)
  30. Built-in Guardrails
  31. Standalone GuardrailManager
  32. Guardrail Events
  33. Permissions (Tool-level Access Control)
  34. Permission Levels
  35. Wildcard Patterns
  36. Standalone PermissionManager
  37. Permission Events
  38. Permissions vs Guardrails
  39. Project Memory (CLAUDE.md, GEMINI.md, etc.)
  40. Using with Agent
  41. Multiple Providers
  42. ProjectMemoryLoader Options
  43. Combine Strategies
  44. Custom Patterns
  45. Standalone Usage
  46. Rate Limiting
  47. Standalone Rate Limiter
  48. Usage Tracking
  49. Rehearsal System (Impact Analysis)
  50. Rehearsal Report
  51. Task Tool (Sub-Agents)
  52. Built-in Agent Types
  53. Hooks System
  54. Skills
  55. Custom Skills
  56. Built-in Skills
  57. Tracing & Logging
  58. OpenTelemetry Integration
  59. Requirements
  60. Peer Dependencies
  61. Design Philosophy
  62. Related Packages
  63. Links
  64. License

@compilr-dev/agents

      \|/
    ╭══════════╮     ___  ___  _ __ ___  _ __ (_) |_ __
    ║'  ▐▌  ▐▌ │    / __|/ _ \| '_ ` _ \| '_ \| | | '__|
    ║          │   | (__| (_) | | | | | | |_) | | | |
    ╰─═──────═─╯    \___|\___/|_| |_| |_| .__/|_|_|_|
      \________\                        | | .dev
                                        |_| agents

Lightweight multi-LLM agent library for building CLI AI assistants

npm version License: FSL-1.1-MIT API Docs

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

StrategyTriggerReversibleDescription
FilteringBefore addN/ATruncate large content (>80K tokens)
Compaction50% or 20 turnsYesSave old results to files
Summarization90%NoCompress 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

PriorityDescriptionFormat in LLM
criticalMust remember### CRITICAL (Must Remember)
safetyCheck before acting### SAFETY (Check Before Acting)
infoContextual 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

IDActionPatternDescription
git-reset-hardconfirmgit reset --hardPrevents accidental loss of uncommitted changes
git-push-forceconfirmgit push --forcePrevents force pushing to branches
rm-rfconfirmrm -rfPrevents recursive deletion
rm-rootblockrm -rf /Blocks deletion of root filesystem
drop-tableconfirmDROP TABLEPrevents accidental table deletion
truncate-tableconfirmTRUNCATEPrevents data loss
delete-where-allwarnDELETE FROM without WHEREWarns about deleting all rows
secrets-envwarnAPI keys, passwordsWarns about exposing secrets
chmod-777warnchmod 777Warns about insecure permissions
curl-pipe-bashblock`curlbash`
eval-codewarneval() patternsWarns about code injection risks
sudo-rmconfirmsudo rmConfirms privileged deletion
git-cleanconfirmgit clean -fdConfirms removing untracked files
format-diskblockmkfs, ddBlocks disk formatting
kill-allconfirmkillall, pkillConfirms 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

LevelDescriptionBehavior
alwaysNo approval neededTool executes immediately
sessionAsk once per sessionAfter approval, tool runs freely
onceAsk every timeUser must approve each execution
denyAlways blockedTool 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:

AspectPermissionsGuardrails
PurposeAccess controlContent safety
ScopeTool-levelInput patterns
TimingBefore tool callBefore execution
Typical Use"Can this tool run?""Is this input safe?"
User InteractionSession/once approvalConfirm 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:

ProviderFiles Searched
ClaudeCLAUDE.md, .claude.md, .claude/instructions.md
GeminiGEMINI.md, .gemini.md, .gemini/instructions.md
OpenAI/GPTOPENAI.md, GPT.md, CHATGPT.md
CopilotCOPILOT.md, .github/copilot-instructions.md
CursorCURSOR.md, .cursorrules, .cursor/rules
GenericPROJECT.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

StrategyDescription
concatConcatenate all files with separators (default)
priorityUse only the highest priority file
dedupeConcatenate 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

TypePurposeDefault Tools
exploreCodebase explorationglob, grep, read_file
code-reviewCode quality reviewread_file, grep
refactorCode refactoringread_file, write_file, edit
test-runnerRunning testsbash, read_file
doc-lookupDocumentation searchread_file, grep, web_fetch
debugDebugging assistanceread_file, grep, bash
security-auditSecurity analysisread_file, grep
planTask planningread_file, glob
generalGeneral purposeAll 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

SkillDescription
code-reviewComprehensive code review with quality, security, and style feedback
debugStep-by-step debugging assistance
explainClear explanations of code functionality
refactorRefactoring suggestions with clean code principles
planningTask breakdown and implementation planning
security-reviewSecurity 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

  1. Minimal dependencies: Only @anthropic-ai/sdk and @modelcontextprotocol/sdk as optional peer deps
  2. Type safety: Full TypeScript support with strict mode
  3. Extensibility: Easy to add new providers and tools
  4. Testability: MockProvider for easy unit testing
  5. Real-time feedback: Event system for CLI applications

License

FSL-1.1-MIT - See LICENSE for details. Converts to MIT after 2 years per version.


Built with care by compilr.dev

版本与发布记录

@compilr-dev/agents 共发布 64 个版本,首次发布于 2025/12/03;过去 12 个月发布了 64 个版本。

版本发布日期距今
0.9.1latest2026/10/1922 天前
0.9.02026/10/041 个月前
0.8.12026/10/031 个月前
0.8.02026/10/031 个月前
0.7.12026/10/011 个月前
0.7.02026/10/011 个月前

关于 @compilr-dev/agents 的常见问题

@compilr-dev/agents 是什么?

Lightweight multi-LLM agent library for building CLI AI assistants

如何安装 @compilr-dev/agents?

在项目目录运行 npm install @compilr-dev/agents,或使用 pnpm add / yarn add / bun add。

@compilr-dev/agents 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@compilr-dev/agents 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@compilr-dev/agents 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@compilr-dev/agents 可以商用吗?

@compilr-dev/agents 使用 FSL-1.1-MIT 许可。声明的许可为 FSL-1.1-MIT,请阅读许可原文确认使用条件。以上为概括,不构成法律意见,请以许可原文为准。

@compilr-dev/agents 的下载量有多少?

根据 npm 官方下载统计,@compilr-dev/agents 在 2026/10/11 – 2026/11/09 这 30 天内被下载 4,204 次,日均约 140 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@compilr-dev/agents 还在维护吗?

最新版本 0.9.1 发布于 2026/10/19(22 天前);至今共发布 64 个版本,其中过去 12 个月发布了 64 个;首次发布于 2025/12/03。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。