ak-claude 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/GUIDE.md +1457 -0
- package/README.md +530 -0
- package/agent-query.js +139 -0
- package/base.js +609 -0
- package/chat.js +76 -0
- package/code-agent.js +609 -0
- package/index.cjs +2348 -0
- package/index.js +46 -0
- package/json-helpers.js +352 -0
- package/logger.js +17 -0
- package/message.js +217 -0
- package/package.json +88 -0
- package/rag-agent.js +351 -0
- package/tool-agent.js +343 -0
- package/transformer.js +423 -0
- package/types.d.ts +555 -0
package/README.md
ADDED
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
# ak-claude
|
|
2
|
+
|
|
3
|
+
**Modular, type-safe wrapper for Anthropic's Claude AI.** Eight class exports for different interaction patterns — JSON transformation, chat, stateless messages, tool-using agents, code-writing agents, document Q&A, and autonomous agent queries — all sharing a common base.
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm install ak-claude
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Requires Node.js 18+ and [@anthropic-ai/sdk](https://www.npmjs.com/package/@anthropic-ai/sdk).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
import { Transformer, Chat, Message, ToolAgent, CodeAgent, RagAgent, AgentQuery } from 'ak-claude';
|
|
17
|
+
|
|
18
|
+
// Vertex AI auth (recommended for GCP deployments — uses Application Default Credentials)
|
|
19
|
+
new Chat({ vertexai: true });
|
|
20
|
+
|
|
21
|
+
// Or direct API key auth
|
|
22
|
+
// export ANTHROPIC_API_KEY=your-key
|
|
23
|
+
new Chat({ apiKey: 'your-key' });
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Classes
|
|
29
|
+
|
|
30
|
+
### Transformer — JSON Transformation
|
|
31
|
+
|
|
32
|
+
Transform structured data using few-shot examples with validation and retry.
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
const transformer = new Transformer({
|
|
36
|
+
modelName: 'claude-sonnet-4-6',
|
|
37
|
+
sourceKey: 'INPUT',
|
|
38
|
+
targetKey: 'OUTPUT'
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
await transformer.init();
|
|
42
|
+
await transformer.seed([
|
|
43
|
+
{
|
|
44
|
+
INPUT: { name: 'Alice' },
|
|
45
|
+
OUTPUT: { name: 'Alice', role: 'engineer', emoji: '👩💻' }
|
|
46
|
+
}
|
|
47
|
+
]);
|
|
48
|
+
|
|
49
|
+
const result = await transformer.send({ name: 'Bob' });
|
|
50
|
+
// → { name: 'Bob', role: '...', emoji: '...' }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Validation & self-healing:**
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
const result = await transformer.send({ name: 'Bob' }, {}, async (output) => {
|
|
57
|
+
if (!output.role) throw new Error('Missing role field');
|
|
58
|
+
return output;
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Chat — Multi-Turn Conversation
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
const chat = new Chat({
|
|
66
|
+
systemPrompt: 'You are a helpful assistant.'
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const r1 = await chat.send('My name is Alice.');
|
|
70
|
+
const r2 = await chat.send('What is my name?');
|
|
71
|
+
// r2.text → "Alice"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Message — Stateless One-Off
|
|
75
|
+
|
|
76
|
+
Each call is independent — no history maintained.
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
const msg = new Message({
|
|
80
|
+
systemPrompt: 'Extract entities as JSON.',
|
|
81
|
+
responseSchema: {
|
|
82
|
+
type: 'object',
|
|
83
|
+
properties: {
|
|
84
|
+
entities: {
|
|
85
|
+
type: 'array',
|
|
86
|
+
items: {
|
|
87
|
+
type: 'object',
|
|
88
|
+
properties: {
|
|
89
|
+
name: { type: 'string' },
|
|
90
|
+
type: { type: 'string' }
|
|
91
|
+
},
|
|
92
|
+
required: ['name', 'type']
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
required: ['entities']
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const result = await msg.send('Alice works at Acme Corp in New York.');
|
|
101
|
+
// result.data → { entities: [{ name: 'Alice', type: 'person' }, ...] }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
When `responseSchema` is provided, the API guarantees valid JSON matching the schema via native structured output (`output_config`). For a lighter alternative without schema guarantees, use `responseFormat: 'json'` instead.
|
|
105
|
+
|
|
106
|
+
### ToolAgent — Agent with User-Provided Tools
|
|
107
|
+
|
|
108
|
+
Provide tool declarations and an executor function. The agent manages the tool-use loop automatically.
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
const agent = new ToolAgent({
|
|
112
|
+
systemPrompt: 'You are a research assistant.',
|
|
113
|
+
tools: [
|
|
114
|
+
{
|
|
115
|
+
name: 'http_get',
|
|
116
|
+
description: 'Fetch a URL',
|
|
117
|
+
input_schema: {
|
|
118
|
+
type: 'object',
|
|
119
|
+
properties: { url: { type: 'string' } },
|
|
120
|
+
required: ['url']
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
],
|
|
124
|
+
toolExecutor: async (toolName, args) => {
|
|
125
|
+
if (toolName === 'http_get') {
|
|
126
|
+
const res = await fetch(args.url);
|
|
127
|
+
return { status: res.status, body: await res.text() };
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
onBeforeExecution: async (toolName, args) => {
|
|
131
|
+
console.log(`About to call ${toolName}`);
|
|
132
|
+
return true; // return false to deny
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const result = await agent.chat('Fetch https://api.example.com/data');
|
|
137
|
+
console.log(result.text); // Agent's summary
|
|
138
|
+
console.log(result.toolCalls); // [{ name, args, result }]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Streaming:**
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
for await (const event of agent.stream('Fetch the data')) {
|
|
145
|
+
if (event.type === 'text') process.stdout.write(event.text);
|
|
146
|
+
if (event.type === 'tool_call') console.log(`Calling ${event.toolName}...`);
|
|
147
|
+
if (event.type === 'tool_result') console.log(`Result:`, event.result);
|
|
148
|
+
if (event.type === 'done') console.log('Done!');
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### CodeAgent — Agent That Writes and Executes Code
|
|
153
|
+
|
|
154
|
+
Instead of calling tools one by one, the model writes JavaScript that can do everything — read files, write files, run commands — in a single script.
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
const agent = new CodeAgent({
|
|
158
|
+
workingDirectory: '/path/to/my/project',
|
|
159
|
+
onCodeExecution: (code, output) => {
|
|
160
|
+
console.log('Ran:', code.slice(0, 100));
|
|
161
|
+
console.log('Output:', output.stdout);
|
|
162
|
+
},
|
|
163
|
+
onBeforeExecution: async (code) => {
|
|
164
|
+
// Review code before execution
|
|
165
|
+
console.log('About to run:', code);
|
|
166
|
+
return true; // return false to deny
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const result = await agent.chat('Find all TODO comments in the codebase');
|
|
171
|
+
console.log(result.text); // Agent's summary
|
|
172
|
+
console.log(result.codeExecutions); // [{ code, output, stderr, exitCode }]
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**How it works:**
|
|
176
|
+
1. On `init()`, gathers codebase context (file tree + key files like package.json)
|
|
177
|
+
2. Injects context into the system prompt so the model understands the project
|
|
178
|
+
3. Model writes JavaScript using the `execute_code` tool
|
|
179
|
+
4. Code runs in a Node.js child process that inherits `process.env`
|
|
180
|
+
5. Output (stdout/stderr) feeds back to the model
|
|
181
|
+
6. Model decides if more work is needed
|
|
182
|
+
|
|
183
|
+
**Streaming:**
|
|
184
|
+
|
|
185
|
+
```javascript
|
|
186
|
+
for await (const event of agent.stream('Refactor the auth module')) {
|
|
187
|
+
if (event.type === 'text') process.stdout.write(event.text);
|
|
188
|
+
if (event.type === 'code') console.log('\n[Running code...]');
|
|
189
|
+
if (event.type === 'output') console.log('[Output]:', event.stdout);
|
|
190
|
+
if (event.type === 'done') console.log('\nDone!');
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### RagAgent — Document & Data Q&A
|
|
195
|
+
|
|
196
|
+
Ground responses in user-provided documents and data. Supports text files, in-memory data, and media files (images, PDFs) via base64 encoding. Optionally enable Claude's built-in citations feature for source attribution.
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
199
|
+
const rag = new RagAgent({
|
|
200
|
+
localFiles: ['./docs/api.md', './config.yaml'],
|
|
201
|
+
localData: [
|
|
202
|
+
{ name: 'users', data: [{ id: 1, name: 'Alice' }] }
|
|
203
|
+
],
|
|
204
|
+
mediaFiles: ['./diagram.png', './report.pdf'],
|
|
205
|
+
enableCitations: true
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
const result = await rag.chat('What does the API doc say about auth?');
|
|
209
|
+
console.log(result.text);
|
|
210
|
+
console.log(result.citations); // [{ type, cited_text, document_title, ... }]
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**Context input types:**
|
|
214
|
+
- **`localFiles`** — read from disk as UTF-8 text (md, json, csv, yaml, txt, js, py, etc.)
|
|
215
|
+
- **`localData`** — in-memory objects serialized as JSON: `{ name: string, data: any }[]`
|
|
216
|
+
- **`mediaFiles`** — images (png, jpg, gif, webp) and PDFs encoded as base64 content blocks
|
|
217
|
+
|
|
218
|
+
**Dynamic context:**
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
await rag.addLocalFiles(['./new-doc.md']);
|
|
222
|
+
await rag.addMediaFiles(['./chart.png']);
|
|
223
|
+
await rag.addLocalData([{ name: 'metrics', data: { dau: 50000 } }]);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### AgentQuery — Autonomous Agent via Claude Agent SDK
|
|
227
|
+
|
|
228
|
+
Wraps `@anthropic-ai/claude-agent-sdk` to launch a full autonomous Claude agent with built-in tools (Read, Write, Edit, Bash, Glob, Grep, etc.). Unlike the other classes which use the Messages API directly, AgentQuery launches a separate agent process.
|
|
229
|
+
|
|
230
|
+
```javascript
|
|
231
|
+
import { AgentQuery } from 'ak-claude';
|
|
232
|
+
|
|
233
|
+
const agent = new AgentQuery({
|
|
234
|
+
cwd: '/path/to/project',
|
|
235
|
+
allowedTools: ['Read', 'Glob', 'Grep'],
|
|
236
|
+
maxTurns: 20,
|
|
237
|
+
maxBudgetUsd: 1.00
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
for await (const msg of agent.run('Find all TODO comments in the codebase')) {
|
|
241
|
+
if (msg.type === 'assistant') {
|
|
242
|
+
console.log(msg.message.content);
|
|
243
|
+
}
|
|
244
|
+
if (msg.type === 'result') {
|
|
245
|
+
console.log('Done:', msg.result);
|
|
246
|
+
console.log('Cost:', msg.total_cost_usd);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Resume a previous session:**
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
const sessionId = agent.lastSessionId;
|
|
255
|
+
|
|
256
|
+
for await (const msg of agent.resume(sessionId, 'Now fix those TODOs')) {
|
|
257
|
+
// ...
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Requires separate installation: `npm install @anthropic-ai/claude-agent-sdk`
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Stopping Agents
|
|
266
|
+
|
|
267
|
+
Both `ToolAgent` and `CodeAgent` support a `stop()` method to cancel execution mid-loop. This is useful for implementing user-facing cancel buttons or safety limits.
|
|
268
|
+
|
|
269
|
+
```javascript
|
|
270
|
+
const agent = new CodeAgent({ workingDirectory: '.' });
|
|
271
|
+
|
|
272
|
+
// Stop from a callback
|
|
273
|
+
const agent = new ToolAgent({
|
|
274
|
+
tools: [...],
|
|
275
|
+
toolExecutor: myExecutor,
|
|
276
|
+
onBeforeExecution: async (toolName, args) => {
|
|
277
|
+
if (toolName === 'dangerous_tool') {
|
|
278
|
+
agent.stop(); // Stop the agent entirely
|
|
279
|
+
return false; // Deny this specific execution
|
|
280
|
+
}
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Stop externally (e.g., from a timeout or user action)
|
|
286
|
+
setTimeout(() => agent.stop(), 60_000);
|
|
287
|
+
const result = await agent.chat('Do some work');
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
For `CodeAgent`, `stop()` also kills any currently running child process via SIGTERM.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Shared Features
|
|
295
|
+
|
|
296
|
+
All classes extend `BaseClaude` and share these features (except `AgentQuery`, which wraps the Claude Agent SDK separately).
|
|
297
|
+
|
|
298
|
+
### Authentication
|
|
299
|
+
|
|
300
|
+
```javascript
|
|
301
|
+
// Vertex AI (GCP — uses Application Default Credentials, no API key needed)
|
|
302
|
+
new Chat({ vertexai: true });
|
|
303
|
+
|
|
304
|
+
// Vertex AI with explicit project/region
|
|
305
|
+
new Chat({ vertexai: true, vertexProjectId: 'my-project', vertexRegion: 'us-central1' });
|
|
306
|
+
|
|
307
|
+
// Direct API key
|
|
308
|
+
new Chat({ apiKey: 'your-key' }); // or ANTHROPIC_API_KEY / CLAUDE_API_KEY env var
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Token Estimation
|
|
312
|
+
|
|
313
|
+
Uses Claude's `countTokens` API for exact input token counts before sending.
|
|
314
|
+
|
|
315
|
+
```javascript
|
|
316
|
+
const { inputTokens } = await instance.estimate({ some: 'payload' });
|
|
317
|
+
const cost = await instance.estimateCost({ some: 'payload' });
|
|
318
|
+
// → { inputTokens, model, pricing, estimatedInputCost, note }
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Usage Tracking
|
|
322
|
+
|
|
323
|
+
```javascript
|
|
324
|
+
const usage = instance.getLastUsage();
|
|
325
|
+
// { promptTokens, responseTokens, totalTokens, cacheCreationTokens, cacheReadTokens,
|
|
326
|
+
// attempts, modelVersion, requestedModel, stopReason, timestamp }
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Few-Shot Seeding
|
|
330
|
+
|
|
331
|
+
```javascript
|
|
332
|
+
await instance.seed([
|
|
333
|
+
{ PROMPT: { x: 1 }, ANSWER: { y: 2 } }
|
|
334
|
+
]);
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Extended Thinking
|
|
338
|
+
|
|
339
|
+
```javascript
|
|
340
|
+
new Chat({
|
|
341
|
+
modelName: 'claude-sonnet-4-6',
|
|
342
|
+
thinking: { type: 'enabled', budget_tokens: 1024 }
|
|
343
|
+
});
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
When thinking is enabled, `temperature` is forced to 1 and `top_p`/`top_k` are not sent (Anthropic API requirement).
|
|
347
|
+
|
|
348
|
+
### Web Search
|
|
349
|
+
|
|
350
|
+
Ground responses in real-time web search results. Uses Claude's built-in server-managed web search tool.
|
|
351
|
+
|
|
352
|
+
```javascript
|
|
353
|
+
const chat = new Chat({
|
|
354
|
+
enableWebSearch: true,
|
|
355
|
+
webSearchConfig: {
|
|
356
|
+
max_uses: 5,
|
|
357
|
+
allowed_domains: ['docs.anthropic.com'],
|
|
358
|
+
blocked_domains: ['example.com']
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
const result = await chat.send('What are the latest Claude model features?');
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
The web search tool is automatically prepended to any existing tools (ToolAgent/CodeAgent tool declarations coexist).
|
|
366
|
+
|
|
367
|
+
### Prompt Caching
|
|
368
|
+
|
|
369
|
+
Reduce costs by caching the system prompt. When enabled, the system prompt is sent with `cache_control: { type: 'ephemeral' }`, allowing Anthropic to cache it across requests.
|
|
370
|
+
|
|
371
|
+
```javascript
|
|
372
|
+
const chat = new Chat({
|
|
373
|
+
systemPrompt: longSystemPrompt,
|
|
374
|
+
cacheSystemPrompt: true
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
const result = await chat.send('Hello!');
|
|
378
|
+
const usage = chat.getLastUsage();
|
|
379
|
+
console.log(usage.cacheCreationTokens); // Tokens used to create cache
|
|
380
|
+
console.log(usage.cacheReadTokens); // Tokens read from cache (cheaper)
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Rate Limit Handling (429)
|
|
384
|
+
|
|
385
|
+
The Anthropic SDK handles 429 retries natively via its built-in retry mechanism. Configure the max retry count at construction:
|
|
386
|
+
|
|
387
|
+
```javascript
|
|
388
|
+
// Defaults: 5 retries with SDK-managed exponential backoff
|
|
389
|
+
const chat = new Chat({ systemPrompt: 'Hello' });
|
|
390
|
+
|
|
391
|
+
// Customize
|
|
392
|
+
const transformer = new Transformer({
|
|
393
|
+
maxRetries: 10 // more retries for high-throughput pipelines
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// Disable entirely
|
|
397
|
+
const msg = new Message({ maxRetries: 0 });
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Constructor Options
|
|
403
|
+
|
|
404
|
+
All classes (except AgentQuery) accept `BaseClaudeOptions`:
|
|
405
|
+
|
|
406
|
+
| Option | Type | Default | Description |
|
|
407
|
+
|--------|------|---------|-------------|
|
|
408
|
+
| `modelName` | string | `'claude-sonnet-4-6'` | Claude model to use |
|
|
409
|
+
| `systemPrompt` | string | varies by class | System prompt |
|
|
410
|
+
| `apiKey` | string | env var | Anthropic API key (not needed with `vertexai`) |
|
|
411
|
+
| `vertexai` | boolean | `false` | Use Vertex AI auth (Application Default Credentials) |
|
|
412
|
+
| `vertexProjectId` | string | `GOOGLE_CLOUD_PROJECT` | GCP project ID (Vertex AI only) |
|
|
413
|
+
| `vertexRegion` | string | `'us-east5'` | GCP region (Vertex AI only) |
|
|
414
|
+
| `maxTokens` | number | `8192` | Max tokens in response |
|
|
415
|
+
| `temperature` | number | `0.7` | Temperature (not used with thinking) |
|
|
416
|
+
| `topP` | number | `0.95` | Top-P (not used with thinking) |
|
|
417
|
+
| `topK` | number | — | Top-K (optional) |
|
|
418
|
+
| `thinking` | object | — | Extended thinking: `{ type: 'enabled', budget_tokens: N }` |
|
|
419
|
+
| `cacheSystemPrompt` | boolean | `false` | Enable prompt caching on system prompt |
|
|
420
|
+
| `enableWebSearch` | boolean | `false` | Enable Claude's web search tool |
|
|
421
|
+
| `webSearchConfig` | object | — | Web search config (`max_uses`, `allowed_domains`, `blocked_domains`) |
|
|
422
|
+
| `maxRetries` | number | `5` | Max SDK-level retry attempts for 429 errors |
|
|
423
|
+
| `healthCheck` | boolean | `false` | Run API connectivity check during `init()` |
|
|
424
|
+
| `logLevel` | string | based on NODE_ENV | `'trace'`\|`'debug'`\|`'info'`\|`'warn'`\|`'error'`\|`'none'` |
|
|
425
|
+
|
|
426
|
+
### Transformer-Specific
|
|
427
|
+
|
|
428
|
+
| Option | Type | Default | Description |
|
|
429
|
+
|--------|------|---------|-------------|
|
|
430
|
+
| `sourceKey`/`promptKey` | string | `'PROMPT'` | Key for input in examples |
|
|
431
|
+
| `targetKey`/`answerKey` | string | `'ANSWER'` | Key for output in examples |
|
|
432
|
+
| `contextKey` | string | `'CONTEXT'` | Key for context in examples |
|
|
433
|
+
| `maxRetries` | number | `3` | Retry attempts for validation |
|
|
434
|
+
| `retryDelay` | number | `1000` | Initial retry delay (ms) |
|
|
435
|
+
| `onlyJSON` | boolean | `true` | Enforce JSON-only responses |
|
|
436
|
+
| `asyncValidator` | function | — | Global async validator |
|
|
437
|
+
| `examplesFile` | string | — | Path to JSON file with examples |
|
|
438
|
+
| `exampleData` | array | — | Inline example data |
|
|
439
|
+
|
|
440
|
+
### Message-Specific
|
|
441
|
+
|
|
442
|
+
| Option | Type | Default | Description |
|
|
443
|
+
|--------|------|---------|-------------|
|
|
444
|
+
| `responseSchema` | object | — | JSON Schema for native structured output |
|
|
445
|
+
| `responseFormat` | string | — | `'json'` for system-prompt-based JSON mode |
|
|
446
|
+
|
|
447
|
+
### ToolAgent-Specific
|
|
448
|
+
|
|
449
|
+
| Option | Type | Default | Description |
|
|
450
|
+
|--------|------|---------|-------------|
|
|
451
|
+
| `tools` | array | — | Tool declarations (`{ name, description, input_schema }`) |
|
|
452
|
+
| `toolExecutor` | function | — | `async (toolName, args) => result` |
|
|
453
|
+
| `maxToolRounds` | number | `10` | Max tool-use loop iterations |
|
|
454
|
+
| `onToolCall` | function | — | Notification callback when tool is called |
|
|
455
|
+
| `onBeforeExecution` | function | — | `async (toolName, args) => boolean` — gate execution |
|
|
456
|
+
| `toolChoice` | object | — | Tool choice config (`auto`, `any`, `tool`, `none`) |
|
|
457
|
+
| `disableParallelToolUse` | boolean | `false` | Force sequential tool calls |
|
|
458
|
+
|
|
459
|
+
### CodeAgent-Specific
|
|
460
|
+
|
|
461
|
+
| Option | Type | Default | Description |
|
|
462
|
+
|--------|------|---------|-------------|
|
|
463
|
+
| `workingDirectory` | string | `process.cwd()` | Directory for code execution |
|
|
464
|
+
| `maxRounds` | number | `10` | Max code execution loop iterations |
|
|
465
|
+
| `timeout` | number | `30000` | Per-execution timeout (ms) |
|
|
466
|
+
| `onBeforeExecution` | function | — | `async (code) => boolean` — gate execution |
|
|
467
|
+
| `onCodeExecution` | function | — | Notification after execution |
|
|
468
|
+
| `importantFiles` | array | — | File paths to include in system prompt context |
|
|
469
|
+
| `writeDir` | string | `'{cwd}/tmp'` | Directory for writing script files |
|
|
470
|
+
| `keepArtifacts` | boolean | `false` | Keep script files on disk after execution |
|
|
471
|
+
| `comments` | boolean | `false` | Instruct model to write JSDoc comments |
|
|
472
|
+
| `maxRetries` | number | `3` | Max consecutive failures before stopping |
|
|
473
|
+
|
|
474
|
+
### RagAgent-Specific
|
|
475
|
+
|
|
476
|
+
| Option | Type | Default | Description |
|
|
477
|
+
|--------|------|---------|-------------|
|
|
478
|
+
| `localFiles` | array | — | Paths to text files read from disk |
|
|
479
|
+
| `localData` | array | — | In-memory data: `{ name, data }[]` |
|
|
480
|
+
| `mediaFiles` | array | — | Paths to images/PDFs (base64 encoded) |
|
|
481
|
+
| `enableCitations` | boolean | `false` | Enable Claude's built-in citations |
|
|
482
|
+
|
|
483
|
+
### AgentQuery-Specific
|
|
484
|
+
|
|
485
|
+
| Option | Type | Default | Description |
|
|
486
|
+
|--------|------|---------|-------------|
|
|
487
|
+
| `model` | string | `'claude-sonnet-4-6'` | Model to use |
|
|
488
|
+
| `allowedTools` | array | — | Allowed tools (e.g., `['Read', 'Glob', 'Grep']`) |
|
|
489
|
+
| `disallowedTools` | array | — | Disallowed tools |
|
|
490
|
+
| `cwd` | string | `process.cwd()` | Working directory |
|
|
491
|
+
| `maxTurns` | number | — | Max agentic turns |
|
|
492
|
+
| `maxBudgetUsd` | number | — | Maximum budget in USD |
|
|
493
|
+
| `systemPrompt` | string | — | System prompt |
|
|
494
|
+
| `permissionMode` | string | — | Permission mode |
|
|
495
|
+
| `mcpServers` | object | — | MCP server configuration |
|
|
496
|
+
| `hooks` | object | — | Lifecycle hooks |
|
|
497
|
+
|
|
498
|
+
---
|
|
499
|
+
|
|
500
|
+
## Exports
|
|
501
|
+
|
|
502
|
+
```javascript
|
|
503
|
+
// Named exports
|
|
504
|
+
import { Transformer, Chat, Message, ToolAgent, CodeAgent, RagAgent, AgentQuery, BaseClaude, log } from 'ak-claude';
|
|
505
|
+
import { extractJSON, attemptJSONRecovery } from 'ak-claude';
|
|
506
|
+
|
|
507
|
+
// Default export (namespace)
|
|
508
|
+
import AI from 'ak-claude';
|
|
509
|
+
new AI.Transformer({ ... });
|
|
510
|
+
new AI.AgentQuery({ ... });
|
|
511
|
+
|
|
512
|
+
// CommonJS
|
|
513
|
+
const { Transformer, Chat, AgentQuery } = require('ak-claude');
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
## Testing
|
|
519
|
+
|
|
520
|
+
```sh
|
|
521
|
+
npm test
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
All tests use real Anthropic API calls (no mocks). Rate limiting (429 errors) can cause intermittent failures.
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
528
|
+
## Migration from ak-gemini
|
|
529
|
+
|
|
530
|
+
See [MIGRATION.md](./MIGRATION.md) for a detailed guide on migrating from ak-gemini to ak-claude.
|
package/agent-query.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview AgentQuery class — wraps @anthropic-ai/claude-agent-sdk's query().
|
|
3
|
+
*
|
|
4
|
+
* Provides a simplified, declarative interface over the Claude Agent SDK.
|
|
5
|
+
* This class does NOT extend BaseClaude — it wraps a completely different SDK
|
|
6
|
+
* with its own auth, session, and execution model.
|
|
7
|
+
*
|
|
8
|
+
* The Agent SDK launches an autonomous Claude agent with built-in tools
|
|
9
|
+
* (Read, Write, Edit, Bash, Glob, Grep, etc.) that can operate on files
|
|
10
|
+
* and codebases directly.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import log from './logger.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {import('./types').AgentQueryOptions} AgentQueryOptions
|
|
17
|
+
* @typedef {import('./types').AgentQueryRunOptions} AgentQueryRunOptions
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Wraps the Claude Agent SDK's query() function for autonomous agent tasks.
|
|
22
|
+
*
|
|
23
|
+
* Unlike the other classes which use the Messages API directly, AgentQuery
|
|
24
|
+
* launches a full Claude Code agent process with built-in tools for
|
|
25
|
+
* file operations, shell commands, and code search.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```javascript
|
|
29
|
+
* import { AgentQuery } from 'ak-claude';
|
|
30
|
+
*
|
|
31
|
+
* const agent = new AgentQuery({
|
|
32
|
+
* cwd: '/path/to/project',
|
|
33
|
+
* allowedTools: ['Read', 'Glob', 'Grep'],
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* for await (const msg of agent.run('Find all TODO comments in the codebase')) {
|
|
37
|
+
* if (msg.type === 'assistant') {
|
|
38
|
+
* console.log(msg.message.content);
|
|
39
|
+
* }
|
|
40
|
+
* if (msg.type === 'result') {
|
|
41
|
+
* console.log('Done:', msg.result);
|
|
42
|
+
* console.log('Cost:', msg.total_cost_usd);
|
|
43
|
+
* }
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
class AgentQuery {
|
|
48
|
+
/**
|
|
49
|
+
* @param {AgentQueryOptions} [options={}]
|
|
50
|
+
*/
|
|
51
|
+
constructor(options = {}) {
|
|
52
|
+
this.model = options.model || 'claude-sonnet-4-6';
|
|
53
|
+
this.allowedTools = options.allowedTools || undefined;
|
|
54
|
+
this.disallowedTools = options.disallowedTools || undefined;
|
|
55
|
+
this.cwd = options.cwd || process.cwd();
|
|
56
|
+
this.maxTurns = options.maxTurns || undefined;
|
|
57
|
+
this.maxBudgetUsd = options.maxBudgetUsd || undefined;
|
|
58
|
+
this.systemPrompt = options.systemPrompt || undefined;
|
|
59
|
+
this.permissionMode = options.permissionMode || undefined;
|
|
60
|
+
this.mcpServers = options.mcpServers || undefined;
|
|
61
|
+
this.hooks = options.hooks || undefined;
|
|
62
|
+
|
|
63
|
+
this._lastSessionId = null;
|
|
64
|
+
this._queryFn = null;
|
|
65
|
+
|
|
66
|
+
log.debug(`AgentQuery created with model: ${this.model}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Lazily imports the query function from claude-agent-sdk.
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
73
|
+
async _getQueryFn() {
|
|
74
|
+
if (this._queryFn) return this._queryFn;
|
|
75
|
+
try {
|
|
76
|
+
const sdk = await import(/** @type {any} */ ('@anthropic-ai/claude-agent-sdk'));
|
|
77
|
+
this._queryFn = sdk.query;
|
|
78
|
+
return this._queryFn;
|
|
79
|
+
} catch (e) {
|
|
80
|
+
throw new Error(
|
|
81
|
+
`Failed to import @anthropic-ai/claude-agent-sdk. ` +
|
|
82
|
+
`Install it with: npm install @anthropic-ai/claude-agent-sdk\n` +
|
|
83
|
+
`Error: ${e.message}`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Run an autonomous agent query. Yields messages as they arrive.
|
|
90
|
+
*
|
|
91
|
+
* @param {string} prompt - The task for the agent
|
|
92
|
+
* @param {AgentQueryRunOptions} [opts={}] - Per-run overrides
|
|
93
|
+
* @yields {Object} Messages from the agent (system, assistant, tool_progress, result)
|
|
94
|
+
*/
|
|
95
|
+
async *run(prompt, opts = {}) {
|
|
96
|
+
const queryFn = await this._getQueryFn();
|
|
97
|
+
|
|
98
|
+
const options = {
|
|
99
|
+
model: opts.model || this.model,
|
|
100
|
+
cwd: opts.cwd || this.cwd,
|
|
101
|
+
...(opts.allowedTools || this.allowedTools ? { allowedTools: opts.allowedTools || this.allowedTools } : {}),
|
|
102
|
+
...(opts.disallowedTools || this.disallowedTools ? { disallowedTools: opts.disallowedTools || this.disallowedTools } : {}),
|
|
103
|
+
...(opts.maxTurns || this.maxTurns ? { maxTurns: opts.maxTurns || this.maxTurns } : {}),
|
|
104
|
+
...(opts.maxBudgetUsd || this.maxBudgetUsd ? { maxBudgetUsd: opts.maxBudgetUsd || this.maxBudgetUsd } : {}),
|
|
105
|
+
...(opts.systemPrompt || this.systemPrompt ? { systemPrompt: opts.systemPrompt || this.systemPrompt } : {}),
|
|
106
|
+
...(opts.permissionMode || this.permissionMode ? { permissionMode: opts.permissionMode || this.permissionMode } : {}),
|
|
107
|
+
...(opts.mcpServers || this.mcpServers ? { mcpServers: opts.mcpServers || this.mcpServers } : {}),
|
|
108
|
+
...(opts.hooks || this.hooks ? { hooks: opts.hooks || this.hooks } : {}),
|
|
109
|
+
...(opts.sessionId ? { resume: opts.sessionId } : {}),
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
for await (const message of queryFn({ prompt, options })) {
|
|
113
|
+
this._lastSessionId = message.session_id || message.sessionId || this._lastSessionId;
|
|
114
|
+
yield message;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Resume a previous agent session with a new prompt.
|
|
120
|
+
*
|
|
121
|
+
* @param {string} sessionId - The session ID to resume
|
|
122
|
+
* @param {string} prompt - The follow-up prompt
|
|
123
|
+
* @param {AgentQueryRunOptions} [opts={}]
|
|
124
|
+
* @yields {Object} Messages from the agent
|
|
125
|
+
*/
|
|
126
|
+
async *resume(sessionId, prompt, opts = {}) {
|
|
127
|
+
yield* this.run(prompt, { ...opts, sessionId });
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* The session ID from the last run.
|
|
132
|
+
* @returns {string|null}
|
|
133
|
+
*/
|
|
134
|
+
get lastSessionId() {
|
|
135
|
+
return this._lastSessionId;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export default AgentQuery;
|