@compilr-dev/agents 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1277 -0
- package/dist/agent.d.ts +1272 -0
- package/dist/agent.js +1912 -0
- package/dist/anchors/builtin.d.ts +24 -0
- package/dist/anchors/builtin.js +61 -0
- package/dist/anchors/index.d.ts +6 -0
- package/dist/anchors/index.js +5 -0
- package/dist/anchors/manager.d.ts +115 -0
- package/dist/anchors/manager.js +412 -0
- package/dist/anchors/types.d.ts +168 -0
- package/dist/anchors/types.js +10 -0
- package/dist/context/index.d.ts +12 -0
- package/dist/context/index.js +10 -0
- package/dist/context/manager.d.ts +224 -0
- package/dist/context/manager.js +770 -0
- package/dist/context/types.d.ts +377 -0
- package/dist/context/types.js +7 -0
- package/dist/costs/index.d.ts +8 -0
- package/dist/costs/index.js +7 -0
- package/dist/costs/tracker.d.ts +121 -0
- package/dist/costs/tracker.js +295 -0
- package/dist/costs/types.d.ts +157 -0
- package/dist/costs/types.js +8 -0
- package/dist/errors.d.ts +178 -0
- package/dist/errors.js +249 -0
- package/dist/guardrails/builtin.d.ts +27 -0
- package/dist/guardrails/builtin.js +223 -0
- package/dist/guardrails/index.d.ts +6 -0
- package/dist/guardrails/index.js +5 -0
- package/dist/guardrails/manager.d.ts +117 -0
- package/dist/guardrails/manager.js +288 -0
- package/dist/guardrails/types.d.ts +159 -0
- package/dist/guardrails/types.js +7 -0
- package/dist/hooks/index.d.ts +31 -0
- package/dist/hooks/index.js +29 -0
- package/dist/hooks/manager.d.ts +147 -0
- package/dist/hooks/manager.js +600 -0
- package/dist/hooks/types.d.ts +368 -0
- package/dist/hooks/types.js +12 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +73 -0
- package/dist/mcp/client.d.ts +93 -0
- package/dist/mcp/client.js +287 -0
- package/dist/mcp/errors.d.ts +60 -0
- package/dist/mcp/errors.js +78 -0
- package/dist/mcp/index.d.ts +43 -0
- package/dist/mcp/index.js +45 -0
- package/dist/mcp/manager.d.ts +120 -0
- package/dist/mcp/manager.js +276 -0
- package/dist/mcp/tools.d.ts +54 -0
- package/dist/mcp/tools.js +99 -0
- package/dist/mcp/types.d.ts +150 -0
- package/dist/mcp/types.js +40 -0
- package/dist/memory/index.d.ts +8 -0
- package/dist/memory/index.js +7 -0
- package/dist/memory/loader.d.ts +114 -0
- package/dist/memory/loader.js +463 -0
- package/dist/memory/types.d.ts +182 -0
- package/dist/memory/types.js +8 -0
- package/dist/messages/index.d.ts +82 -0
- package/dist/messages/index.js +155 -0
- package/dist/permissions/index.d.ts +5 -0
- package/dist/permissions/index.js +4 -0
- package/dist/permissions/manager.d.ts +125 -0
- package/dist/permissions/manager.js +379 -0
- package/dist/permissions/types.d.ts +162 -0
- package/dist/permissions/types.js +7 -0
- package/dist/providers/claude.d.ts +90 -0
- package/dist/providers/claude.js +348 -0
- package/dist/providers/index.d.ts +8 -0
- package/dist/providers/index.js +11 -0
- package/dist/providers/mock.d.ts +133 -0
- package/dist/providers/mock.js +204 -0
- package/dist/providers/types.d.ts +168 -0
- package/dist/providers/types.js +4 -0
- package/dist/rate-limit/index.d.ts +45 -0
- package/dist/rate-limit/index.js +47 -0
- package/dist/rate-limit/limiter.d.ts +104 -0
- package/dist/rate-limit/limiter.js +326 -0
- package/dist/rate-limit/provider-wrapper.d.ts +112 -0
- package/dist/rate-limit/provider-wrapper.js +201 -0
- package/dist/rate-limit/retry.d.ts +108 -0
- package/dist/rate-limit/retry.js +287 -0
- package/dist/rate-limit/types.d.ts +181 -0
- package/dist/rate-limit/types.js +22 -0
- package/dist/rehearsal/file-analyzer.d.ts +22 -0
- package/dist/rehearsal/file-analyzer.js +351 -0
- package/dist/rehearsal/git-analyzer.d.ts +22 -0
- package/dist/rehearsal/git-analyzer.js +472 -0
- package/dist/rehearsal/index.d.ts +35 -0
- package/dist/rehearsal/index.js +36 -0
- package/dist/rehearsal/manager.d.ts +100 -0
- package/dist/rehearsal/manager.js +290 -0
- package/dist/rehearsal/types.d.ts +235 -0
- package/dist/rehearsal/types.js +8 -0
- package/dist/skills/index.d.ts +160 -0
- package/dist/skills/index.js +282 -0
- package/dist/state/agent-state.d.ts +41 -0
- package/dist/state/agent-state.js +88 -0
- package/dist/state/checkpointer.d.ts +110 -0
- package/dist/state/checkpointer.js +362 -0
- package/dist/state/errors.d.ts +66 -0
- package/dist/state/errors.js +88 -0
- package/dist/state/index.d.ts +35 -0
- package/dist/state/index.js +37 -0
- package/dist/state/serializer.d.ts +55 -0
- package/dist/state/serializer.js +172 -0
- package/dist/state/types.d.ts +312 -0
- package/dist/state/types.js +14 -0
- package/dist/tools/builtin/bash-output.d.ts +61 -0
- package/dist/tools/builtin/bash-output.js +90 -0
- package/dist/tools/builtin/bash.d.ts +150 -0
- package/dist/tools/builtin/bash.js +354 -0
- package/dist/tools/builtin/edit.d.ts +50 -0
- package/dist/tools/builtin/edit.js +215 -0
- package/dist/tools/builtin/glob.d.ts +62 -0
- package/dist/tools/builtin/glob.js +244 -0
- package/dist/tools/builtin/grep.d.ts +74 -0
- package/dist/tools/builtin/grep.js +363 -0
- package/dist/tools/builtin/index.d.ts +44 -0
- package/dist/tools/builtin/index.js +69 -0
- package/dist/tools/builtin/kill-shell.d.ts +44 -0
- package/dist/tools/builtin/kill-shell.js +80 -0
- package/dist/tools/builtin/read-file.d.ts +57 -0
- package/dist/tools/builtin/read-file.js +184 -0
- package/dist/tools/builtin/shell-manager.d.ts +176 -0
- package/dist/tools/builtin/shell-manager.js +337 -0
- package/dist/tools/builtin/task.d.ts +202 -0
- package/dist/tools/builtin/task.js +350 -0
- package/dist/tools/builtin/todo.d.ts +207 -0
- package/dist/tools/builtin/todo.js +453 -0
- package/dist/tools/builtin/utils.d.ts +27 -0
- package/dist/tools/builtin/utils.js +70 -0
- package/dist/tools/builtin/web-fetch.d.ts +96 -0
- package/dist/tools/builtin/web-fetch.js +290 -0
- package/dist/tools/builtin/write-file.d.ts +54 -0
- package/dist/tools/builtin/write-file.js +147 -0
- package/dist/tools/define.d.ts +60 -0
- package/dist/tools/define.js +65 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.js +37 -0
- package/dist/tools/registry.d.ts +79 -0
- package/dist/tools/registry.js +151 -0
- package/dist/tools/types.d.ts +59 -0
- package/dist/tools/types.js +4 -0
- package/dist/tracing/hooks.d.ts +58 -0
- package/dist/tracing/hooks.js +377 -0
- package/dist/tracing/index.d.ts +51 -0
- package/dist/tracing/index.js +55 -0
- package/dist/tracing/logging.d.ts +78 -0
- package/dist/tracing/logging.js +310 -0
- package/dist/tracing/manager.d.ts +160 -0
- package/dist/tracing/manager.js +468 -0
- package/dist/tracing/otel.d.ts +102 -0
- package/dist/tracing/otel.js +246 -0
- package/dist/tracing/types.d.ts +346 -0
- package/dist/tracing/types.js +38 -0
- package/dist/utils/index.d.ts +23 -0
- package/dist/utils/index.js +44 -0
- package/package.json +79 -0
package/README.md
ADDED
|
@@ -0,0 +1,1277 @@
|
|
|
1
|
+
# @compilr-dev/agents
|
|
2
|
+
|
|
3
|
+
Lightweight multi-LLM agent library for building CLI AI assistants.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multi-LLM Support**: Abstract provider interface supporting Claude, OpenAI, Gemini, and local models
|
|
8
|
+
- **Tool System**: Type-safe tool definitions with JSON Schema validation
|
|
9
|
+
- **Event Streaming**: Real-time execution monitoring with typed events
|
|
10
|
+
- **Abort Support**: Cancel running agents with `AbortSignal`
|
|
11
|
+
- **Built-in Tools**: Ready-to-use file and bash tools
|
|
12
|
+
- **Anchors**: Critical information that survives context compaction
|
|
13
|
+
- **Guardrails**: Pattern-based safety checks (warn/confirm/block dangerous operations)
|
|
14
|
+
- **Permissions**: Tool-level permission management (always/session/once/deny)
|
|
15
|
+
- **Project Memory**: Load project instructions from CLAUDE.md, GEMINI.md, etc.
|
|
16
|
+
- **TypeScript First**: Full type safety throughout
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @compilr-dev/agents
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
For Claude support:
|
|
25
|
+
```bash
|
|
26
|
+
npm install @compilr-dev/agents @anthropic-ai/sdk
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { Agent, MockProvider } from '@compilr-dev/agents';
|
|
33
|
+
|
|
34
|
+
// Create an agent with a provider
|
|
35
|
+
const provider = new MockProvider();
|
|
36
|
+
provider.addResponse('Hello! How can I help you today?');
|
|
37
|
+
|
|
38
|
+
const agent = new Agent({
|
|
39
|
+
provider,
|
|
40
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Run the agent
|
|
44
|
+
const result = await agent.run('Hello!');
|
|
45
|
+
console.log(result.response); // "Hello! How can I help you today?"
|
|
46
|
+
console.log(result.iterations); // 1
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### With Claude
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { Agent, ClaudeProvider } from '@compilr-dev/agents';
|
|
53
|
+
|
|
54
|
+
const agent = new Agent({
|
|
55
|
+
provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
|
|
56
|
+
systemPrompt: 'You are a helpful coding assistant.',
|
|
57
|
+
maxIterations: 10,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const result = await agent.run('Explain async/await in JavaScript');
|
|
61
|
+
console.log(result.response);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Core Concepts
|
|
65
|
+
|
|
66
|
+
### Agent
|
|
67
|
+
|
|
68
|
+
The `Agent` class orchestrates LLM interactions and tool execution:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { Agent, ClaudeProvider } from '@compilr-dev/agents';
|
|
72
|
+
|
|
73
|
+
const agent = new Agent({
|
|
74
|
+
provider: new ClaudeProvider({ apiKey: 'your-key' }),
|
|
75
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
76
|
+
maxIterations: 10, // Default: 10
|
|
77
|
+
onEvent: (event) => {
|
|
78
|
+
// Real-time execution monitoring
|
|
79
|
+
console.log(event.type);
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Messages
|
|
85
|
+
|
|
86
|
+
The library provides utilities for working with conversation messages:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import {
|
|
90
|
+
createUserMessage,
|
|
91
|
+
createAssistantMessage,
|
|
92
|
+
createToolResultMessage,
|
|
93
|
+
getTextContent
|
|
94
|
+
} from '@compilr-dev/agents';
|
|
95
|
+
|
|
96
|
+
// Create messages
|
|
97
|
+
const userMsg = createUserMessage('Hello!');
|
|
98
|
+
const assistantMsg = createAssistantMessage('Hi there!');
|
|
99
|
+
|
|
100
|
+
// Extract text from message with multiple content blocks
|
|
101
|
+
const text = getTextContent(assistantMsg);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Tools
|
|
105
|
+
|
|
106
|
+
Define tools that agents can use:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
|
|
110
|
+
|
|
111
|
+
const calculatorTool = defineTool({
|
|
112
|
+
name: 'calculator',
|
|
113
|
+
description: 'Perform basic math operations',
|
|
114
|
+
inputSchema: {
|
|
115
|
+
type: 'object',
|
|
116
|
+
properties: {
|
|
117
|
+
operation: { type: 'string', description: 'add, subtract, multiply, divide' },
|
|
118
|
+
a: { type: 'number' },
|
|
119
|
+
b: { type: 'number' },
|
|
120
|
+
},
|
|
121
|
+
required: ['operation', 'a', 'b'],
|
|
122
|
+
},
|
|
123
|
+
execute: async ({ operation, a, b }) => {
|
|
124
|
+
switch (operation) {
|
|
125
|
+
case 'add': return createSuccessResult(a + b);
|
|
126
|
+
case 'subtract': return createSuccessResult(a - b);
|
|
127
|
+
case 'multiply': return createSuccessResult(a * b);
|
|
128
|
+
case 'divide':
|
|
129
|
+
if (b === 0) return createErrorResult('Division by zero');
|
|
130
|
+
return createSuccessResult(a / b);
|
|
131
|
+
default:
|
|
132
|
+
return createErrorResult(`Unknown operation: ${operation}`);
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Register with agent
|
|
138
|
+
agent.registerTool(calculatorTool);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Tool Registry
|
|
142
|
+
|
|
143
|
+
Manage tools with the registry:
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
import { DefaultToolRegistry, defineTool } from '@compilr-dev/agents';
|
|
147
|
+
|
|
148
|
+
const registry = new DefaultToolRegistry();
|
|
149
|
+
|
|
150
|
+
// Register tools
|
|
151
|
+
registry.register(myTool);
|
|
152
|
+
|
|
153
|
+
// Get tool definitions for LLM
|
|
154
|
+
const definitions = registry.getDefinitions();
|
|
155
|
+
|
|
156
|
+
// Execute a tool
|
|
157
|
+
const result = await registry.execute('tool_name', { arg: 'value' });
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Built-in Tools
|
|
161
|
+
|
|
162
|
+
### File Operations
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
import { readFileTool, writeFileTool } from '@compilr-dev/agents';
|
|
166
|
+
|
|
167
|
+
agent.registerTool(readFileTool);
|
|
168
|
+
agent.registerTool(writeFileTool);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Bash Execution
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import { createBashTool } from '@compilr-dev/agents';
|
|
175
|
+
|
|
176
|
+
const bashTool = createBashTool({
|
|
177
|
+
workingDir: '/path/to/project',
|
|
178
|
+
timeout: 30000, // 30 seconds
|
|
179
|
+
allowedCommands: ['git', 'npm', 'ls'], // Optional whitelist
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
agent.registerTool(bashTool);
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Event System
|
|
186
|
+
|
|
187
|
+
Monitor agent execution in real-time:
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import type { AgentEvent } from '@compilr-dev/agents';
|
|
191
|
+
|
|
192
|
+
const agent = new Agent({
|
|
193
|
+
provider,
|
|
194
|
+
onEvent: (event: AgentEvent) => {
|
|
195
|
+
switch (event.type) {
|
|
196
|
+
case 'iteration_start':
|
|
197
|
+
console.log(`Starting iteration ${event.iteration}`);
|
|
198
|
+
break;
|
|
199
|
+
case 'llm_start':
|
|
200
|
+
console.log('LLM thinking...');
|
|
201
|
+
break;
|
|
202
|
+
case 'llm_end':
|
|
203
|
+
console.log(`LLM done, tool uses: ${event.hasToolUses}`);
|
|
204
|
+
break;
|
|
205
|
+
case 'tool_start':
|
|
206
|
+
console.log(`Calling tool: ${event.name}`);
|
|
207
|
+
break;
|
|
208
|
+
case 'tool_end':
|
|
209
|
+
console.log(`Tool result: ${event.result.success}`);
|
|
210
|
+
break;
|
|
211
|
+
case 'done':
|
|
212
|
+
console.log(`Final: ${event.response}`);
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Streaming Events
|
|
220
|
+
|
|
221
|
+
For CLI applications, stream events as they happen:
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
for await (const event of agent.stream('Hello!')) {
|
|
225
|
+
if (event.type === 'llm_chunk') {
|
|
226
|
+
process.stdout.write(event.chunk.text || '');
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Abort Support
|
|
232
|
+
|
|
233
|
+
Cancel running agents:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
const controller = new AbortController();
|
|
237
|
+
|
|
238
|
+
// Cancel after 5 seconds
|
|
239
|
+
setTimeout(() => controller.abort(), 5000);
|
|
240
|
+
|
|
241
|
+
try {
|
|
242
|
+
const result = await agent.run('Complex task...', {
|
|
243
|
+
signal: controller.signal,
|
|
244
|
+
});
|
|
245
|
+
} catch (error) {
|
|
246
|
+
if (error instanceof AbortError) {
|
|
247
|
+
console.log('Agent was cancelled');
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Error Handling
|
|
253
|
+
|
|
254
|
+
The library provides specific error types:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import {
|
|
258
|
+
AgentError,
|
|
259
|
+
ProviderError,
|
|
260
|
+
ToolError,
|
|
261
|
+
ValidationError,
|
|
262
|
+
MaxIterationsError,
|
|
263
|
+
AbortError,
|
|
264
|
+
isAgentError,
|
|
265
|
+
isProviderError,
|
|
266
|
+
isToolError,
|
|
267
|
+
wrapError,
|
|
268
|
+
} from '@compilr-dev/agents';
|
|
269
|
+
|
|
270
|
+
try {
|
|
271
|
+
await agent.run('...');
|
|
272
|
+
} catch (error) {
|
|
273
|
+
if (isProviderError(error)) {
|
|
274
|
+
console.log(`Provider ${error.provider} failed: ${error.message}`);
|
|
275
|
+
} else if (isToolError(error)) {
|
|
276
|
+
console.log(`Tool ${error.toolName} failed: ${error.message}`);
|
|
277
|
+
} else if (error instanceof MaxIterationsError) {
|
|
278
|
+
console.log(`Reached max iterations: ${error.maxIterations}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Providers
|
|
284
|
+
|
|
285
|
+
### ClaudeProvider
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
import { ClaudeProvider } from '@compilr-dev/agents';
|
|
289
|
+
|
|
290
|
+
const provider = new ClaudeProvider({
|
|
291
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
292
|
+
model: 'claude-sonnet-4-20250514', // Default
|
|
293
|
+
maxTokens: 4096,
|
|
294
|
+
});
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### MockProvider (for testing)
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
import { MockProvider } from '@compilr-dev/agents';
|
|
301
|
+
|
|
302
|
+
const provider = new MockProvider();
|
|
303
|
+
|
|
304
|
+
// Queue responses
|
|
305
|
+
provider.addResponse('Simple text response');
|
|
306
|
+
provider.addResponse({
|
|
307
|
+
text: 'Using a tool...',
|
|
308
|
+
toolCalls: [{ id: 'call_1', name: 'my_tool', input: { arg: 'value' } }],
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// Queue an error
|
|
312
|
+
provider.addError(new Error('API failed'));
|
|
313
|
+
|
|
314
|
+
// Add delay
|
|
315
|
+
provider.addResponse('Delayed response', 1000);
|
|
316
|
+
|
|
317
|
+
// Access history
|
|
318
|
+
console.log(provider.history); // All chat() calls
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Custom Providers
|
|
322
|
+
|
|
323
|
+
Implement the `LLMProvider` interface:
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
import type { LLMProvider, Message, ChatOptions, StreamChunk } from '@compilr-dev/agents';
|
|
327
|
+
|
|
328
|
+
class MyProvider implements LLMProvider {
|
|
329
|
+
readonly name = 'my-provider';
|
|
330
|
+
|
|
331
|
+
async *chat(
|
|
332
|
+
messages: Message[],
|
|
333
|
+
options?: ChatOptions
|
|
334
|
+
): AsyncIterable<StreamChunk> {
|
|
335
|
+
// Your implementation
|
|
336
|
+
yield { type: 'text', text: 'Response text' };
|
|
337
|
+
yield { type: 'end', stopReason: 'end_turn' };
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
async countTokens(messages: Message[]): Promise<number> {
|
|
341
|
+
// Optional token counting
|
|
342
|
+
return messages.length * 100;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## API Reference
|
|
348
|
+
|
|
349
|
+
### Agent
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
class Agent {
|
|
353
|
+
constructor(options: AgentOptions);
|
|
354
|
+
|
|
355
|
+
// Run agent and return final result
|
|
356
|
+
run(userMessage: string, options?: RunOptions): Promise<AgentResult>;
|
|
357
|
+
|
|
358
|
+
// Stream events during execution
|
|
359
|
+
stream(userMessage: string, options?: RunOptions): AsyncIterable<AgentEvent>;
|
|
360
|
+
|
|
361
|
+
// Tool management
|
|
362
|
+
registerTool(tool: Tool): void;
|
|
363
|
+
registerTools(tools: Tool[]): void;
|
|
364
|
+
getToolDefinitions(): ToolDefinition[];
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Types
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
interface AgentOptions {
|
|
372
|
+
provider: LLMProvider;
|
|
373
|
+
systemPrompt?: string;
|
|
374
|
+
maxIterations?: number;
|
|
375
|
+
onEvent?: (event: AgentEvent) => void;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
interface RunOptions {
|
|
379
|
+
signal?: AbortSignal;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
interface AgentResult {
|
|
383
|
+
response: string;
|
|
384
|
+
iterations: number;
|
|
385
|
+
toolCalls: ToolCallInfo[];
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
type AgentEvent =
|
|
389
|
+
| { type: 'iteration_start'; iteration: number }
|
|
390
|
+
| { type: 'llm_start' }
|
|
391
|
+
| { type: 'llm_chunk'; chunk: StreamChunk }
|
|
392
|
+
| { type: 'llm_end'; text: string; hasToolUses: boolean }
|
|
393
|
+
| { type: 'tool_start'; name: string; input: Record<string, unknown> }
|
|
394
|
+
| { type: 'tool_end'; name: string; result: ToolExecutionResult }
|
|
395
|
+
| { type: 'iteration_end'; iteration: number }
|
|
396
|
+
| { type: 'done'; response: string };
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
## Context Management
|
|
400
|
+
|
|
401
|
+
Manage context windows in long-running agent sessions:
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
import { ContextManager, DEFAULT_CONTEXT_CONFIG } from '@compilr-dev/agents';
|
|
405
|
+
|
|
406
|
+
const contextManager = new ContextManager({
|
|
407
|
+
provider,
|
|
408
|
+
config: {
|
|
409
|
+
maxContextTokens: 200000, // Claude's limit
|
|
410
|
+
compaction: {
|
|
411
|
+
triggerThreshold: 0.5, // Compact at 50% utilization
|
|
412
|
+
preserveRecentTurns: 10, // Keep last 10 turns
|
|
413
|
+
},
|
|
414
|
+
summarization: {
|
|
415
|
+
triggerThreshold: 0.9, // Summarize at 90%
|
|
416
|
+
preserveRecentMessages: 6,
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
onEvent: (event) => {
|
|
420
|
+
if (event.type === 'context_warning') {
|
|
421
|
+
console.log(`Context at ${event.utilization * 100}%`);
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
// Track token usage
|
|
427
|
+
await contextManager.updateTokenCount(messages);
|
|
428
|
+
console.log(`Utilization: ${contextManager.getUtilization() * 100}%`);
|
|
429
|
+
|
|
430
|
+
// Check if action needed
|
|
431
|
+
if (contextManager.needsSummarization()) {
|
|
432
|
+
const { messages: summarized } = await contextManager.summarize(
|
|
433
|
+
messages,
|
|
434
|
+
async (msgs) => 'Summary of conversation...' // Your LLM call
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Filter large content before adding
|
|
439
|
+
const { content, filtered } = contextManager.filterContent(
|
|
440
|
+
largeToolResult,
|
|
441
|
+
'tool_result'
|
|
442
|
+
);
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Context Strategies
|
|
446
|
+
|
|
447
|
+
| Strategy | Trigger | Reversible | Description |
|
|
448
|
+
|----------|---------|------------|-------------|
|
|
449
|
+
| **Filtering** | Before add | N/A | Truncate large content (>80K tokens) |
|
|
450
|
+
| **Compaction** | 50% or 20 turns | Yes | Save old results to files |
|
|
451
|
+
| **Summarization** | 90% | No | Compress entire history |
|
|
452
|
+
|
|
453
|
+
## Anchors (Critical Information Persistence)
|
|
454
|
+
|
|
455
|
+
Anchors are critical pieces of information that survive context compaction. They're automatically re-injected into every LLM call:
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
import { Agent, AnchorManager, ClaudeProvider } from '@compilr-dev/agents';
|
|
459
|
+
|
|
460
|
+
const agent = new Agent({
|
|
461
|
+
provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
|
|
462
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
463
|
+
anchors: {
|
|
464
|
+
maxAnchors: 20, // Maximum number of anchors
|
|
465
|
+
maxTokens: 2000, // Token budget for anchors
|
|
466
|
+
includeDefaults: true, // Include safety anchors (git, file operations)
|
|
467
|
+
},
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
// Add a session anchor (survives until session ends)
|
|
471
|
+
agent.addAnchor({
|
|
472
|
+
content: 'User prefers TypeScript with strict mode',
|
|
473
|
+
priority: 'critical',
|
|
474
|
+
scope: 'session',
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
// Add a persistent anchor (saved to disk)
|
|
478
|
+
agent.addAnchor({
|
|
479
|
+
content: 'Never modify files in /etc',
|
|
480
|
+
priority: 'safety',
|
|
481
|
+
scope: 'persistent',
|
|
482
|
+
tags: ['filesystem'],
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
// Add a temporary anchor (expires after a time)
|
|
486
|
+
agent.addAnchor({
|
|
487
|
+
content: 'Currently debugging the auth module',
|
|
488
|
+
priority: 'info',
|
|
489
|
+
scope: 'temporary',
|
|
490
|
+
expiresAt: new Date(Date.now() + 3600000), // 1 hour
|
|
491
|
+
});
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### Anchor Priorities
|
|
495
|
+
|
|
496
|
+
| Priority | Description | Format in LLM |
|
|
497
|
+
|----------|-------------|---------------|
|
|
498
|
+
| `critical` | Must remember | `### CRITICAL (Must Remember)` |
|
|
499
|
+
| `safety` | Check before acting | `### SAFETY (Check Before Acting)` |
|
|
500
|
+
| `info` | Contextual information | `### INFO` |
|
|
501
|
+
|
|
502
|
+
### Standalone AnchorManager
|
|
503
|
+
|
|
504
|
+
```typescript
|
|
505
|
+
import { AnchorManager } from '@compilr-dev/agents';
|
|
506
|
+
|
|
507
|
+
const anchors = new AnchorManager({
|
|
508
|
+
maxAnchors: 20,
|
|
509
|
+
maxTokens: 2000,
|
|
510
|
+
persistPath: '~/.myapp/anchors.json', // Optional persistence
|
|
511
|
+
includeDefaults: true,
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
// Add anchors
|
|
515
|
+
anchors.add({ content: 'Important info', priority: 'critical', scope: 'session' });
|
|
516
|
+
|
|
517
|
+
// Query anchors
|
|
518
|
+
const critical = anchors.getAll({ priority: 'critical' });
|
|
519
|
+
const tagged = anchors.getAll({ tags: ['git'] });
|
|
520
|
+
|
|
521
|
+
// Format for LLM injection
|
|
522
|
+
const formatted = anchors.format();
|
|
523
|
+
// Returns:
|
|
524
|
+
// ### CRITICAL (Must Remember)
|
|
525
|
+
// - Important info
|
|
526
|
+
|
|
527
|
+
// Monitor token usage
|
|
528
|
+
console.log(`Utilization: ${anchors.getUtilization() * 100}%`);
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
## Guardrails (Safety Checks)
|
|
532
|
+
|
|
533
|
+
Guardrails are pattern-based safety checks that run before tool execution. They can warn, require confirmation, or block dangerous operations:
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
import { Agent, ClaudeProvider } from '@compilr-dev/agents';
|
|
537
|
+
|
|
538
|
+
const agent = new Agent({
|
|
539
|
+
provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
|
|
540
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
541
|
+
guardrails: {
|
|
542
|
+
enabled: true,
|
|
543
|
+
includeDefaults: true, // 15 built-in patterns for git, rm, DROP TABLE, etc.
|
|
544
|
+
custom: [
|
|
545
|
+
{
|
|
546
|
+
id: 'no-prod-db',
|
|
547
|
+
name: 'Production Database Protection',
|
|
548
|
+
description: 'Prevent operations on production database',
|
|
549
|
+
patterns: [/prod.*db/i, /production.*database/i],
|
|
550
|
+
action: 'block', // 'warn' | 'confirm' | 'block'
|
|
551
|
+
message: 'Operations on production database are blocked',
|
|
552
|
+
scope: ['bash'], // Optional: limit to specific tools
|
|
553
|
+
tags: ['database', 'production'],
|
|
554
|
+
},
|
|
555
|
+
],
|
|
556
|
+
onTriggered: async (result, context) => {
|
|
557
|
+
// Handle 'confirm' actions
|
|
558
|
+
if (result.action === 'confirm') {
|
|
559
|
+
return await askUserConfirmation(result.guardrail.message);
|
|
560
|
+
}
|
|
561
|
+
return result.action !== 'block';
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
});
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
### Built-in Guardrails
|
|
568
|
+
|
|
569
|
+
| ID | Action | Pattern | Description |
|
|
570
|
+
|----|--------|---------|-------------|
|
|
571
|
+
| `git-reset-hard` | confirm | `git reset --hard` | Prevents accidental loss of uncommitted changes |
|
|
572
|
+
| `git-push-force` | confirm | `git push --force` | Prevents force pushing to branches |
|
|
573
|
+
| `rm-rf` | confirm | `rm -rf` | Prevents recursive deletion |
|
|
574
|
+
| `rm-root` | block | `rm -rf /` | Blocks deletion of root filesystem |
|
|
575
|
+
| `drop-table` | confirm | `DROP TABLE` | Prevents accidental table deletion |
|
|
576
|
+
| `truncate-table` | confirm | `TRUNCATE` | Prevents data loss |
|
|
577
|
+
| `delete-where-all` | warn | `DELETE FROM` without WHERE | Warns about deleting all rows |
|
|
578
|
+
| `secrets-env` | warn | API keys, passwords | Warns about exposing secrets |
|
|
579
|
+
| `chmod-777` | warn | `chmod 777` | Warns about insecure permissions |
|
|
580
|
+
| `curl-pipe-bash` | block | `curl | bash` | Blocks unsafe remote execution |
|
|
581
|
+
| `eval-code` | warn | `eval()` patterns | Warns about code injection risks |
|
|
582
|
+
| `sudo-rm` | confirm | `sudo rm` | Confirms privileged deletion |
|
|
583
|
+
| `git-clean` | confirm | `git clean -fd` | Confirms removing untracked files |
|
|
584
|
+
| `format-disk` | block | `mkfs`, `dd` | Blocks disk formatting |
|
|
585
|
+
| `kill-all` | confirm | `killall`, `pkill` | Confirms killing processes |
|
|
586
|
+
|
|
587
|
+
### Standalone GuardrailManager
|
|
588
|
+
|
|
589
|
+
```typescript
|
|
590
|
+
import { GuardrailManager, getGuardrailsByTag } from '@compilr-dev/agents';
|
|
591
|
+
|
|
592
|
+
const guardrails = new GuardrailManager({
|
|
593
|
+
enabled: true,
|
|
594
|
+
includeDefaults: true,
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
// Check before tool execution
|
|
598
|
+
const result = guardrails.check('bash', { command: 'rm -rf /tmp/test' });
|
|
599
|
+
if (result.triggered) {
|
|
600
|
+
console.log(`Guardrail triggered: ${result.guardrail.name}`);
|
|
601
|
+
console.log(`Action: ${result.action}`); // 'warn' | 'confirm' | 'block'
|
|
602
|
+
console.log(`Message: ${result.guardrail.message}`);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Check and handle (with confirmation callback)
|
|
606
|
+
const { proceed, result } = await guardrails.checkAndHandle('bash', input);
|
|
607
|
+
if (!proceed) {
|
|
608
|
+
console.log('Operation blocked by guardrail');
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// Get guardrails by tag
|
|
612
|
+
const gitGuardrails = getGuardrailsByTag('git');
|
|
613
|
+
const destructiveGuardrails = getGuardrailsByTag('destructive');
|
|
614
|
+
|
|
615
|
+
// Enable/disable individual guardrails
|
|
616
|
+
guardrails.disable('rm-rf');
|
|
617
|
+
guardrails.enable('rm-rf');
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
### Guardrail Events
|
|
621
|
+
|
|
622
|
+
Monitor guardrail activity:
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
guardrails.onEvent((event) => {
|
|
626
|
+
switch (event.type) {
|
|
627
|
+
case 'guardrail:triggered':
|
|
628
|
+
console.log(`Guardrail ${event.result.guardrail.name} triggered`);
|
|
629
|
+
break;
|
|
630
|
+
case 'guardrail:blocked':
|
|
631
|
+
console.log('Operation blocked');
|
|
632
|
+
break;
|
|
633
|
+
case 'guardrail:warning':
|
|
634
|
+
console.log('Warning issued');
|
|
635
|
+
break;
|
|
636
|
+
case 'guardrail:confirmed':
|
|
637
|
+
console.log('User confirmed dangerous operation');
|
|
638
|
+
break;
|
|
639
|
+
case 'guardrail:cancelled':
|
|
640
|
+
console.log('User cancelled operation');
|
|
641
|
+
break;
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
## Permissions (Tool-level Access Control)
|
|
647
|
+
|
|
648
|
+
Permissions provide fine-grained control over which tools can execute and when user approval is required:
|
|
649
|
+
|
|
650
|
+
```typescript
|
|
651
|
+
import { Agent, ClaudeProvider } from '@compilr-dev/agents';
|
|
652
|
+
|
|
653
|
+
const agent = new Agent({
|
|
654
|
+
provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
|
|
655
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
656
|
+
permissions: {
|
|
657
|
+
enabled: true,
|
|
658
|
+
defaultLevel: 'always', // Default for tools without rules
|
|
659
|
+
includeDefaults: true, // Include default rules for bash, write_file, edit
|
|
660
|
+
rules: [
|
|
661
|
+
{ toolName: 'bash', level: 'once', description: 'Shell commands' },
|
|
662
|
+
{ toolName: 'write_file', level: 'session', description: 'File writes' },
|
|
663
|
+
{ toolName: 'delete_*', level: 'deny', description: 'Delete operations' },
|
|
664
|
+
],
|
|
665
|
+
onPermissionRequest: async (request) => {
|
|
666
|
+
// Handle permission requests (e.g., prompt user)
|
|
667
|
+
console.log(`Tool: ${request.toolName}`);
|
|
668
|
+
console.log(`Preview: ${request.preview}`);
|
|
669
|
+
return await askUser(`Allow ${request.toolName}?`);
|
|
670
|
+
},
|
|
671
|
+
},
|
|
672
|
+
});
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
### Permission Levels
|
|
676
|
+
|
|
677
|
+
| Level | Description | Behavior |
|
|
678
|
+
|-------|-------------|----------|
|
|
679
|
+
| `always` | No approval needed | Tool executes immediately |
|
|
680
|
+
| `session` | Ask once per session | After approval, tool runs freely |
|
|
681
|
+
| `once` | Ask every time | User must approve each execution |
|
|
682
|
+
| `deny` | Always blocked | Tool cannot execute |
|
|
683
|
+
|
|
684
|
+
### Wildcard Patterns
|
|
685
|
+
|
|
686
|
+
Permission rules support wildcards for flexible matching:
|
|
687
|
+
|
|
688
|
+
```typescript
|
|
689
|
+
// Match all tools starting with "delete_"
|
|
690
|
+
{ toolName: 'delete_*', level: 'deny' }
|
|
691
|
+
|
|
692
|
+
// Match all tools ending with "_file"
|
|
693
|
+
{ toolName: '*_file', level: 'session' }
|
|
694
|
+
|
|
695
|
+
// Match tools containing "dangerous"
|
|
696
|
+
{ toolName: '*dangerous*', level: 'once' }
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
### Standalone PermissionManager
|
|
700
|
+
|
|
701
|
+
```typescript
|
|
702
|
+
import { PermissionManager } from '@compilr-dev/agents';
|
|
703
|
+
|
|
704
|
+
const permissions = new PermissionManager({
|
|
705
|
+
enabled: true,
|
|
706
|
+
defaultLevel: 'always',
|
|
707
|
+
onPermissionRequest: async (request) => {
|
|
708
|
+
return await promptUser(request.preview);
|
|
709
|
+
},
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
// Add rules dynamically
|
|
713
|
+
permissions.addRule({
|
|
714
|
+
toolName: 'bash',
|
|
715
|
+
level: 'once',
|
|
716
|
+
description: 'Shell commands',
|
|
717
|
+
tags: ['shell', 'dangerous'],
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
// Check permission before execution
|
|
721
|
+
const result = await permissions.check('bash', { command: 'rm -rf /tmp/test' });
|
|
722
|
+
if (result.allowed) {
|
|
723
|
+
// Proceed with execution
|
|
724
|
+
} else {
|
|
725
|
+
console.log(`Denied: ${result.reason}`);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// Grant session-level permission programmatically
|
|
729
|
+
permissions.grantSession('write_file');
|
|
730
|
+
|
|
731
|
+
// Check if tool has session grant
|
|
732
|
+
if (permissions.hasSessionGrant('write_file')) {
|
|
733
|
+
console.log('write_file approved for this session');
|
|
734
|
+
}
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
### Permission Events
|
|
738
|
+
|
|
739
|
+
Monitor permission activity:
|
|
740
|
+
|
|
741
|
+
```typescript
|
|
742
|
+
permissions.onEvent((event) => {
|
|
743
|
+
switch (event.type) {
|
|
744
|
+
case 'permission:granted':
|
|
745
|
+
console.log(`${event.toolName} allowed`);
|
|
746
|
+
break;
|
|
747
|
+
case 'permission:denied':
|
|
748
|
+
console.log(`${event.toolName} denied`);
|
|
749
|
+
break;
|
|
750
|
+
case 'permission:asked':
|
|
751
|
+
console.log(`Asking about ${event.toolName}`);
|
|
752
|
+
break;
|
|
753
|
+
case 'permission:session_granted':
|
|
754
|
+
console.log(`${event.toolName} approved for session`);
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
});
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
### Permissions vs Guardrails
|
|
761
|
+
|
|
762
|
+
Both systems provide safety, but serve different purposes:
|
|
763
|
+
|
|
764
|
+
| Aspect | Permissions | Guardrails |
|
|
765
|
+
|--------|-------------|------------|
|
|
766
|
+
| **Purpose** | Access control | Content safety |
|
|
767
|
+
| **Scope** | Tool-level | Input patterns |
|
|
768
|
+
| **Timing** | Before tool call | Before execution |
|
|
769
|
+
| **Typical Use** | "Can this tool run?" | "Is this input safe?" |
|
|
770
|
+
| **User Interaction** | Session/once approval | Confirm dangerous ops |
|
|
771
|
+
|
|
772
|
+
Use them together for comprehensive safety:
|
|
773
|
+
- Permissions control *which* tools can be used
|
|
774
|
+
- Guardrails check *what* inputs are safe
|
|
775
|
+
|
|
776
|
+
## Project Memory (CLAUDE.md, GEMINI.md, etc.)
|
|
777
|
+
|
|
778
|
+
Project Memory automatically discovers and loads project-specific instructions from markdown files. It supports various LLM-specific naming conventions:
|
|
779
|
+
|
|
780
|
+
| Provider | Files Searched |
|
|
781
|
+
|----------|----------------|
|
|
782
|
+
| Claude | `CLAUDE.md`, `.claude.md`, `.claude/instructions.md` |
|
|
783
|
+
| Gemini | `GEMINI.md`, `.gemini.md`, `.gemini/instructions.md` |
|
|
784
|
+
| OpenAI/GPT | `OPENAI.md`, `GPT.md`, `CHATGPT.md` |
|
|
785
|
+
| Copilot | `COPILOT.md`, `.github/copilot-instructions.md` |
|
|
786
|
+
| Cursor | `CURSOR.md`, `.cursorrules`, `.cursor/rules` |
|
|
787
|
+
| Generic | `PROJECT.md`, `INSTRUCTIONS.md`, `AI.md`, `CONTEXT.md` |
|
|
788
|
+
|
|
789
|
+
### Using with Agent
|
|
790
|
+
|
|
791
|
+
```typescript
|
|
792
|
+
import { Agent, ClaudeProvider } from '@compilr-dev/agents';
|
|
793
|
+
|
|
794
|
+
// Option 1: Factory method (recommended)
|
|
795
|
+
const agent = await Agent.createWithMemory(
|
|
796
|
+
{
|
|
797
|
+
provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
|
|
798
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
799
|
+
},
|
|
800
|
+
{ providers: 'claude', includeGeneric: true },
|
|
801
|
+
'/path/to/project' // defaults to cwd
|
|
802
|
+
);
|
|
803
|
+
|
|
804
|
+
// Access loaded memory
|
|
805
|
+
const memory = agent.getProjectMemory();
|
|
806
|
+
console.log(`Loaded ${memory?.files.length} instruction files`);
|
|
807
|
+
|
|
808
|
+
// Option 2: Pre-load memory manually
|
|
809
|
+
import { ProjectMemoryLoader } from '@compilr-dev/agents';
|
|
810
|
+
|
|
811
|
+
const loader = new ProjectMemoryLoader({
|
|
812
|
+
providers: ['claude', 'gemini'],
|
|
813
|
+
includeGeneric: true,
|
|
814
|
+
});
|
|
815
|
+
const memory = await loader.load('/path/to/project');
|
|
816
|
+
|
|
817
|
+
const agent = new Agent({
|
|
818
|
+
provider,
|
|
819
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
820
|
+
projectMemory: memory,
|
|
821
|
+
});
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
### Multiple Providers
|
|
825
|
+
|
|
826
|
+
Search for instructions from multiple LLM providers:
|
|
827
|
+
|
|
828
|
+
```typescript
|
|
829
|
+
const agent = await Agent.createWithMemory(
|
|
830
|
+
{ provider },
|
|
831
|
+
{
|
|
832
|
+
providers: ['claude', 'gemini', 'openai'],
|
|
833
|
+
includeGeneric: true, // Also search PROJECT.md, AI.md, etc.
|
|
834
|
+
combineStrategy: 'concat', // Combine all found files
|
|
835
|
+
}
|
|
836
|
+
);
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
### ProjectMemoryLoader Options
|
|
840
|
+
|
|
841
|
+
```typescript
|
|
842
|
+
const loader = new ProjectMemoryLoader({
|
|
843
|
+
// Provider(s) to search for
|
|
844
|
+
providers: 'claude', // or ['claude', 'gemini']
|
|
845
|
+
|
|
846
|
+
// Include generic patterns (PROJECT.md, AI.md, etc.)
|
|
847
|
+
includeGeneric: true,
|
|
848
|
+
|
|
849
|
+
// Search parent directories up to git root
|
|
850
|
+
searchParents: true,
|
|
851
|
+
stopAtGitRoot: true,
|
|
852
|
+
maxParentDepth: 10,
|
|
853
|
+
|
|
854
|
+
// How to combine multiple files
|
|
855
|
+
combineStrategy: 'concat', // 'concat' | 'priority' | 'dedupe'
|
|
856
|
+
|
|
857
|
+
// Content limits
|
|
858
|
+
maxContentSize: 100000, // 100KB max
|
|
859
|
+
|
|
860
|
+
// Headers in combined output
|
|
861
|
+
includeHeaders: true,
|
|
862
|
+
headerFormat: '# From: {relativePath}\n\n',
|
|
863
|
+
});
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
### Combine Strategies
|
|
867
|
+
|
|
868
|
+
| Strategy | Description |
|
|
869
|
+
|----------|-------------|
|
|
870
|
+
| `concat` | Concatenate all files with separators (default) |
|
|
871
|
+
| `priority` | Use only the highest priority file |
|
|
872
|
+
| `dedupe` | Concatenate but remove duplicate content |
|
|
873
|
+
|
|
874
|
+
### Custom Patterns
|
|
875
|
+
|
|
876
|
+
Add custom file patterns for your own naming conventions:
|
|
877
|
+
|
|
878
|
+
```typescript
|
|
879
|
+
const loader = new ProjectMemoryLoader({
|
|
880
|
+
providers: 'claude',
|
|
881
|
+
customPatterns: [
|
|
882
|
+
{ pattern: 'TEAM-RULES.md', priority: 0, description: 'Team rules' },
|
|
883
|
+
{ pattern: '.ai-config.md', priority: 1, description: 'AI config' },
|
|
884
|
+
],
|
|
885
|
+
});
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
### Standalone Usage
|
|
889
|
+
|
|
890
|
+
Use the loader without an Agent:
|
|
891
|
+
|
|
892
|
+
```typescript
|
|
893
|
+
import {
|
|
894
|
+
loadProjectMemory,
|
|
895
|
+
hasProjectMemory,
|
|
896
|
+
getSupportedProviders,
|
|
897
|
+
getProviderPatterns,
|
|
898
|
+
} from '@compilr-dev/agents';
|
|
899
|
+
|
|
900
|
+
// Quick check if memory files exist
|
|
901
|
+
if (await hasProjectMemory('/path/to/project', { providers: 'claude' })) {
|
|
902
|
+
console.log('Found project instructions!');
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// Load memory directly
|
|
906
|
+
const memory = await loadProjectMemory('/path/to/project', {
|
|
907
|
+
providers: ['claude', 'gemini'],
|
|
908
|
+
});
|
|
909
|
+
|
|
910
|
+
console.log(`Loaded ${memory.files.length} files`);
|
|
911
|
+
console.log(`Estimated tokens: ${memory.estimatedTokens}`);
|
|
912
|
+
|
|
913
|
+
// Get patterns for a provider
|
|
914
|
+
const patterns = getProviderPatterns('cursor');
|
|
915
|
+
// Returns: [{ pattern: 'CURSOR.md', ... }, { pattern: '.cursorrules', ... }]
|
|
916
|
+
|
|
917
|
+
// List all supported providers
|
|
918
|
+
const providers = getSupportedProviders();
|
|
919
|
+
// Returns: ['claude', 'anthropic', 'gemini', 'openai', 'gpt', 'copilot', 'cursor', 'codeium']
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
## Rate Limiting
|
|
923
|
+
|
|
924
|
+
Protect against API rate limits with automatic retry and backoff:
|
|
925
|
+
|
|
926
|
+
```typescript
|
|
927
|
+
import { Agent, ClaudeProvider, createRateLimitedProvider } from '@compilr-dev/agents';
|
|
928
|
+
|
|
929
|
+
// Wrap any provider with rate limiting
|
|
930
|
+
const provider = createRateLimitedProvider(
|
|
931
|
+
new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
|
|
932
|
+
{
|
|
933
|
+
maxRequestsPerMinute: 50,
|
|
934
|
+
maxTokensPerMinute: 100000,
|
|
935
|
+
maxRetries: 3,
|
|
936
|
+
initialBackoffMs: 1000,
|
|
937
|
+
maxBackoffMs: 60000,
|
|
938
|
+
backoffMultiplier: 2,
|
|
939
|
+
onRateLimited: (info) => {
|
|
940
|
+
console.log(`Rate limited, waiting ${info.waitMs}ms`);
|
|
941
|
+
},
|
|
942
|
+
}
|
|
943
|
+
);
|
|
944
|
+
|
|
945
|
+
const agent = new Agent({ provider });
|
|
946
|
+
```
|
|
947
|
+
|
|
948
|
+
### Standalone Rate Limiter
|
|
949
|
+
|
|
950
|
+
```typescript
|
|
951
|
+
import { RateLimiter } from '@compilr-dev/agents';
|
|
952
|
+
|
|
953
|
+
const limiter = new RateLimiter({
|
|
954
|
+
maxRequestsPerMinute: 60,
|
|
955
|
+
maxTokensPerMinute: 100000,
|
|
956
|
+
});
|
|
957
|
+
|
|
958
|
+
// Check before making requests
|
|
959
|
+
await limiter.waitForCapacity();
|
|
960
|
+
|
|
961
|
+
// Record usage after requests
|
|
962
|
+
limiter.recordRequest(1500); // tokens used
|
|
963
|
+
|
|
964
|
+
// Check current state
|
|
965
|
+
console.log(`Requests remaining: ${limiter.getAvailableRequests()}`);
|
|
966
|
+
console.log(`Tokens remaining: ${limiter.getAvailableTokens()}`);
|
|
967
|
+
```
|
|
968
|
+
|
|
969
|
+
## Usage Tracking
|
|
970
|
+
|
|
971
|
+
Track token usage across agent sessions:
|
|
972
|
+
|
|
973
|
+
```typescript
|
|
974
|
+
import { Agent, ClaudeProvider } from '@compilr-dev/agents';
|
|
975
|
+
|
|
976
|
+
const agent = new Agent({
|
|
977
|
+
provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
|
|
978
|
+
usage: {
|
|
979
|
+
enabled: true,
|
|
980
|
+
warnThresholds: {
|
|
981
|
+
inputTokens: 100000,
|
|
982
|
+
outputTokens: 50000,
|
|
983
|
+
},
|
|
984
|
+
onWarning: (warning) => {
|
|
985
|
+
console.log(`Usage warning: ${warning.metric} at ${warning.currentValue}`);
|
|
986
|
+
},
|
|
987
|
+
},
|
|
988
|
+
});
|
|
989
|
+
|
|
990
|
+
// After running the agent
|
|
991
|
+
const result = await agent.run('Hello!');
|
|
992
|
+
|
|
993
|
+
// Get usage stats
|
|
994
|
+
const usage = agent.getUsage();
|
|
995
|
+
console.log(`Input tokens: ${usage.inputTokens}`);
|
|
996
|
+
console.log(`Output tokens: ${usage.outputTokens}`);
|
|
997
|
+
console.log(`Total tokens: ${usage.totalTokens}`);
|
|
998
|
+
console.log(`Requests: ${usage.requests}`);
|
|
999
|
+
```
|
|
1000
|
+
|
|
1001
|
+
## Rehearsal System (Impact Analysis)
|
|
1002
|
+
|
|
1003
|
+
Rehearsal analyzes potentially destructive operations before execution, showing what files and git state would be affected:
|
|
1004
|
+
|
|
1005
|
+
```typescript
|
|
1006
|
+
import { Agent, ClaudeProvider } from '@compilr-dev/agents';
|
|
1007
|
+
|
|
1008
|
+
const agent = new Agent({
|
|
1009
|
+
provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
|
|
1010
|
+
rehearsal: {
|
|
1011
|
+
enabled: true,
|
|
1012
|
+
gitAnalysis: true, // Analyze git impact
|
|
1013
|
+
fileAnalysis: true, // Analyze file impact
|
|
1014
|
+
autoConfirm: false, // Require user confirmation
|
|
1015
|
+
workingDirectory: '/path/to/project',
|
|
1016
|
+
onRehearsalComplete: async (result) => {
|
|
1017
|
+
console.log('=== Rehearsal Report ===');
|
|
1018
|
+
console.log(`Files affected: ${result.files?.filesAffected || 0}`);
|
|
1019
|
+
console.log(`Git impact: ${result.git?.summary || 'None'}`);
|
|
1020
|
+
|
|
1021
|
+
// Return true to proceed, false to cancel
|
|
1022
|
+
return await askUserConfirmation('Proceed with these changes?');
|
|
1023
|
+
},
|
|
1024
|
+
},
|
|
1025
|
+
});
|
|
1026
|
+
|
|
1027
|
+
// Destructive operations trigger rehearsal automatically
|
|
1028
|
+
await agent.run('Delete all .log files and reset the git branch');
|
|
1029
|
+
```
|
|
1030
|
+
|
|
1031
|
+
### Rehearsal Report
|
|
1032
|
+
|
|
1033
|
+
The rehearsal system provides detailed impact analysis:
|
|
1034
|
+
|
|
1035
|
+
```typescript
|
|
1036
|
+
interface RehearsalResult {
|
|
1037
|
+
files?: {
|
|
1038
|
+
filesAffected: number;
|
|
1039
|
+
deletions: string[];
|
|
1040
|
+
modifications: string[];
|
|
1041
|
+
creations: string[];
|
|
1042
|
+
totalSizeImpact: number;
|
|
1043
|
+
};
|
|
1044
|
+
git?: {
|
|
1045
|
+
hasUncommittedChanges: boolean;
|
|
1046
|
+
uncommittedFiles: string[];
|
|
1047
|
+
branchesAffected: string[];
|
|
1048
|
+
commitsAffected: number;
|
|
1049
|
+
summary: string;
|
|
1050
|
+
};
|
|
1051
|
+
riskLevel: 'low' | 'medium' | 'high' | 'critical';
|
|
1052
|
+
warnings: string[];
|
|
1053
|
+
}
|
|
1054
|
+
```
|
|
1055
|
+
|
|
1056
|
+
## Task Tool (Sub-Agents)
|
|
1057
|
+
|
|
1058
|
+
Spawn specialized sub-agents for complex tasks:
|
|
1059
|
+
|
|
1060
|
+
```typescript
|
|
1061
|
+
import { Agent, ClaudeProvider, createTaskTool } from '@compilr-dev/agents';
|
|
1062
|
+
|
|
1063
|
+
const taskTool = createTaskTool({
|
|
1064
|
+
provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
|
|
1065
|
+
agentTypes: {
|
|
1066
|
+
explore: {
|
|
1067
|
+
systemPrompt: 'You are a code exploration expert.',
|
|
1068
|
+
tools: ['read_file', 'glob', 'grep'],
|
|
1069
|
+
contextMode: 'full', // Inherit full conversation context
|
|
1070
|
+
},
|
|
1071
|
+
'code-review': {
|
|
1072
|
+
systemPrompt: 'You are a code reviewer.',
|
|
1073
|
+
tools: ['read_file', 'grep'],
|
|
1074
|
+
contextMode: 'summary', // Get summarized context
|
|
1075
|
+
},
|
|
1076
|
+
refactor: {
|
|
1077
|
+
systemPrompt: 'You are a refactoring expert.',
|
|
1078
|
+
tools: ['read_file', 'write_file', 'edit'],
|
|
1079
|
+
contextMode: 'none', // No inherited context
|
|
1080
|
+
},
|
|
1081
|
+
},
|
|
1082
|
+
defaultThoroughness: 'medium', // 'quick' | 'medium' | 'thorough'
|
|
1083
|
+
maxConcurrentTasks: 3,
|
|
1084
|
+
});
|
|
1085
|
+
|
|
1086
|
+
agent.registerTool(taskTool);
|
|
1087
|
+
|
|
1088
|
+
// The LLM can now spawn sub-agents:
|
|
1089
|
+
// task({ agentType: 'explore', prompt: 'Find all React components' })
|
|
1090
|
+
```
|
|
1091
|
+
|
|
1092
|
+
### Built-in Agent Types
|
|
1093
|
+
|
|
1094
|
+
| Type | Purpose | Default Tools |
|
|
1095
|
+
|------|---------|---------------|
|
|
1096
|
+
| `explore` | Codebase exploration | glob, grep, read_file |
|
|
1097
|
+
| `code-review` | Code quality review | read_file, grep |
|
|
1098
|
+
| `refactor` | Code refactoring | read_file, write_file, edit |
|
|
1099
|
+
| `test-runner` | Running tests | bash, read_file |
|
|
1100
|
+
| `doc-lookup` | Documentation search | read_file, grep, web_fetch |
|
|
1101
|
+
| `debug` | Debugging assistance | read_file, grep, bash |
|
|
1102
|
+
| `security-audit` | Security analysis | read_file, grep |
|
|
1103
|
+
| `plan` | Task planning | read_file, glob |
|
|
1104
|
+
| `general` | General purpose | All tools |
|
|
1105
|
+
|
|
1106
|
+
## Hooks System
|
|
1107
|
+
|
|
1108
|
+
Extend agent behavior with lifecycle hooks:
|
|
1109
|
+
|
|
1110
|
+
```typescript
|
|
1111
|
+
import { Agent, ClaudeProvider, HooksManager } from '@compilr-dev/agents';
|
|
1112
|
+
|
|
1113
|
+
const hooks = new HooksManager();
|
|
1114
|
+
|
|
1115
|
+
// Before each LLM call
|
|
1116
|
+
hooks.register('beforeChat', async (context) => {
|
|
1117
|
+
console.log(`Sending ${context.messages.length} messages`);
|
|
1118
|
+
// Modify messages if needed
|
|
1119
|
+
return { messages: context.messages };
|
|
1120
|
+
});
|
|
1121
|
+
|
|
1122
|
+
// After each LLM response
|
|
1123
|
+
hooks.register('afterChat', async (context) => {
|
|
1124
|
+
console.log(`Received: ${context.response.text?.slice(0, 50)}...`);
|
|
1125
|
+
});
|
|
1126
|
+
|
|
1127
|
+
// Before tool execution
|
|
1128
|
+
hooks.register('beforeToolCall', async (context) => {
|
|
1129
|
+
console.log(`Calling ${context.toolName} with`, context.input);
|
|
1130
|
+
// Return { skip: true } to skip execution
|
|
1131
|
+
});
|
|
1132
|
+
|
|
1133
|
+
// After tool execution
|
|
1134
|
+
hooks.register('afterToolCall', async (context) => {
|
|
1135
|
+
console.log(`${context.toolName} returned:`, context.result);
|
|
1136
|
+
// Modify result if needed
|
|
1137
|
+
return { result: context.result };
|
|
1138
|
+
});
|
|
1139
|
+
|
|
1140
|
+
const agent = new Agent({
|
|
1141
|
+
provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
|
|
1142
|
+
hooks,
|
|
1143
|
+
});
|
|
1144
|
+
```
|
|
1145
|
+
|
|
1146
|
+
## Skills
|
|
1147
|
+
|
|
1148
|
+
Skills are reusable prompt templates that enhance agent capabilities:
|
|
1149
|
+
|
|
1150
|
+
```typescript
|
|
1151
|
+
import { Agent, ClaudeProvider, SkillsManager, BUILTIN_SKILLS } from '@compilr-dev/agents';
|
|
1152
|
+
|
|
1153
|
+
// Use built-in skills
|
|
1154
|
+
const skills = new SkillsManager({
|
|
1155
|
+
skills: BUILTIN_SKILLS, // code-review, debug, explain, refactor, planning, security-review
|
|
1156
|
+
});
|
|
1157
|
+
|
|
1158
|
+
const agent = new Agent({
|
|
1159
|
+
provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
|
|
1160
|
+
skills,
|
|
1161
|
+
});
|
|
1162
|
+
|
|
1163
|
+
// Invoke a skill
|
|
1164
|
+
const result = await agent.run('/skill code-review src/auth.ts');
|
|
1165
|
+
```
|
|
1166
|
+
|
|
1167
|
+
### Custom Skills
|
|
1168
|
+
|
|
1169
|
+
```typescript
|
|
1170
|
+
const customSkills = new SkillsManager({
|
|
1171
|
+
skills: [
|
|
1172
|
+
{
|
|
1173
|
+
name: 'optimize',
|
|
1174
|
+
description: 'Optimize code for performance',
|
|
1175
|
+
prompt: `Analyze the following code and suggest performance optimizations:
|
|
1176
|
+
- Identify bottlenecks
|
|
1177
|
+
- Suggest algorithmic improvements
|
|
1178
|
+
- Recommend caching strategies
|
|
1179
|
+
- Consider memory usage`,
|
|
1180
|
+
tags: ['performance', 'optimization'],
|
|
1181
|
+
},
|
|
1182
|
+
],
|
|
1183
|
+
});
|
|
1184
|
+
```
|
|
1185
|
+
|
|
1186
|
+
### Built-in Skills
|
|
1187
|
+
|
|
1188
|
+
| Skill | Description |
|
|
1189
|
+
|-------|-------------|
|
|
1190
|
+
| `code-review` | Comprehensive code review with quality, security, and style feedback |
|
|
1191
|
+
| `debug` | Step-by-step debugging assistance |
|
|
1192
|
+
| `explain` | Clear explanations of code functionality |
|
|
1193
|
+
| `refactor` | Refactoring suggestions with clean code principles |
|
|
1194
|
+
| `planning` | Task breakdown and implementation planning |
|
|
1195
|
+
| `security-review` | Security vulnerability analysis |
|
|
1196
|
+
|
|
1197
|
+
## Tracing & Logging
|
|
1198
|
+
|
|
1199
|
+
Monitor agent execution with structured logging:
|
|
1200
|
+
|
|
1201
|
+
```typescript
|
|
1202
|
+
import { Agent, ClaudeProvider, TracingManager } from '@compilr-dev/agents';
|
|
1203
|
+
|
|
1204
|
+
const tracing = new TracingManager({
|
|
1205
|
+
enabled: true,
|
|
1206
|
+
logLevel: 'info', // 'debug' | 'info' | 'warn' | 'error'
|
|
1207
|
+
destination: 'console', // or 'file' or custom function
|
|
1208
|
+
filePath: './agent-logs.jsonl',
|
|
1209
|
+
includeTimestamps: true,
|
|
1210
|
+
redactPatterns: [/api[_-]?key/i, /password/i], // Redact sensitive data
|
|
1211
|
+
});
|
|
1212
|
+
|
|
1213
|
+
const agent = new Agent({
|
|
1214
|
+
provider: new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
|
|
1215
|
+
tracing,
|
|
1216
|
+
});
|
|
1217
|
+
|
|
1218
|
+
// Logs include:
|
|
1219
|
+
// - LLM requests/responses
|
|
1220
|
+
// - Tool calls and results
|
|
1221
|
+
// - Errors and warnings
|
|
1222
|
+
// - Timing information
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
### OpenTelemetry Integration
|
|
1226
|
+
|
|
1227
|
+
```typescript
|
|
1228
|
+
import { createOtelTracing } from '@compilr-dev/agents';
|
|
1229
|
+
|
|
1230
|
+
// Export traces to your observability platform
|
|
1231
|
+
const tracing = createOtelTracing({
|
|
1232
|
+
serviceName: 'my-agent',
|
|
1233
|
+
endpoint: 'http://localhost:4318/v1/traces',
|
|
1234
|
+
});
|
|
1235
|
+
|
|
1236
|
+
const agent = new Agent({ provider, tracing });
|
|
1237
|
+
```
|
|
1238
|
+
|
|
1239
|
+
## Examples
|
|
1240
|
+
|
|
1241
|
+
See the `examples/` directory for runnable demos:
|
|
1242
|
+
|
|
1243
|
+
```bash
|
|
1244
|
+
# Basic agent usage
|
|
1245
|
+
npx tsx examples/basic-agent.ts
|
|
1246
|
+
|
|
1247
|
+
# Agent with custom tools
|
|
1248
|
+
npx tsx examples/agent-with-tools.ts
|
|
1249
|
+
|
|
1250
|
+
# Streaming events
|
|
1251
|
+
npx tsx examples/streaming-events.ts
|
|
1252
|
+
```
|
|
1253
|
+
|
|
1254
|
+
## Testing
|
|
1255
|
+
|
|
1256
|
+
```bash
|
|
1257
|
+
# Run tests
|
|
1258
|
+
npm test
|
|
1259
|
+
|
|
1260
|
+
# Run with coverage
|
|
1261
|
+
npm run test:coverage
|
|
1262
|
+
|
|
1263
|
+
# Watch mode
|
|
1264
|
+
npm run test:watch
|
|
1265
|
+
```
|
|
1266
|
+
|
|
1267
|
+
## Design Philosophy
|
|
1268
|
+
|
|
1269
|
+
1. **Minimal dependencies**: Only `@anthropic-ai/sdk` as optional peer dep
|
|
1270
|
+
2. **Type safety**: Full TypeScript support with strict mode
|
|
1271
|
+
3. **Extensibility**: Easy to add new providers and tools
|
|
1272
|
+
4. **Testability**: MockProvider for easy unit testing
|
|
1273
|
+
5. **Real-time feedback**: Event system for CLI applications
|
|
1274
|
+
|
|
1275
|
+
## License
|
|
1276
|
+
|
|
1277
|
+
MIT
|