agentool 0.0.1 → 1.1.0

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.
Files changed (147) hide show
  1. package/README.md +738 -52
  2. package/dist/ask-user/index.cjs +8 -0
  3. package/dist/ask-user/index.d.cts +68 -0
  4. package/dist/ask-user/index.d.ts +68 -0
  5. package/dist/ask-user/index.js +8 -0
  6. package/dist/bash/index.cjs +8 -0
  7. package/dist/bash/index.d.cts +63 -0
  8. package/dist/bash/index.d.ts +63 -0
  9. package/dist/bash/index.js +8 -0
  10. package/dist/chunk-3EPGFWZV.cjs +30 -0
  11. package/dist/chunk-3VO6NETR.cjs +79 -0
  12. package/dist/chunk-44AFQ2B7.js +30 -0
  13. package/dist/chunk-4HIATLKI.js +112 -0
  14. package/dist/chunk-4HXAKPQH.cjs +36 -0
  15. package/dist/chunk-4YI2H55A.js +142 -0
  16. package/dist/chunk-56CL4JCW.cjs +53 -0
  17. package/dist/chunk-5NW4OGRI.cjs +99 -0
  18. package/dist/chunk-5O55DKOB.cjs +112 -0
  19. package/dist/chunk-5TDZF4IM.cjs +197 -0
  20. package/dist/chunk-6DJSWTWQ.cjs +40 -0
  21. package/dist/chunk-6PQLFDGT.js +117 -0
  22. package/dist/chunk-ACGW44YT.js +47 -0
  23. package/dist/chunk-CAEVLIQB.cjs +117 -0
  24. package/dist/chunk-CGTPF6IS.js +90 -0
  25. package/dist/chunk-E6NBEYZD.js +51 -0
  26. package/dist/chunk-EA3YV7ZG.js +79 -0
  27. package/dist/chunk-ECYT46FP.js +40 -0
  28. package/dist/chunk-FV2R5FFQ.cjs +102 -0
  29. package/dist/chunk-FW3UJ622.cjs +59 -0
  30. package/dist/chunk-G3ITTPGX.js +99 -0
  31. package/dist/chunk-HDKXSKMO.js +30 -0
  32. package/dist/chunk-HNP7JDQC.cjs +159 -0
  33. package/dist/chunk-HNUL2CID.cjs +34 -0
  34. package/dist/chunk-HZAQRHBT.js +99 -0
  35. package/dist/chunk-I3ONDY7P.js +46 -0
  36. package/dist/chunk-I6KFFQPV.cjs +58 -0
  37. package/dist/chunk-IEX4NOVN.cjs +48 -0
  38. package/dist/chunk-IRRNYFI5.js +48 -0
  39. package/dist/chunk-K77GC2QI.js +59 -0
  40. package/dist/chunk-L5JH4I77.cjs +51 -0
  41. package/dist/chunk-LK6SQH2G.cjs +30 -0
  42. package/dist/chunk-LPV5CN2K.js +58 -0
  43. package/dist/chunk-LTE5NG4D.js +53 -0
  44. package/dist/chunk-MF7CJVIZ.js +40 -0
  45. package/dist/chunk-MIYA7TNR.cjs +123 -0
  46. package/dist/chunk-MJCAXASI.js +123 -0
  47. package/dist/chunk-OM2UFTGS.cjs +47 -0
  48. package/dist/chunk-ONBH74ZV.cjs +90 -0
  49. package/dist/chunk-OXLQ7QVL.cjs +40 -0
  50. package/dist/chunk-P6Z5XFDS.js +73 -0
  51. package/dist/chunk-QZ5GS6HW.cjs +46 -0
  52. package/dist/chunk-S7IVHOA6.js +75 -0
  53. package/dist/chunk-SUSAPI5W.cjs +142 -0
  54. package/dist/chunk-TMW3XKKJ.js +34 -0
  55. package/dist/chunk-UDIG7332.js +159 -0
  56. package/dist/chunk-VLNDEVKS.js +102 -0
  57. package/dist/chunk-VXZ4RKJI.js +36 -0
  58. package/dist/chunk-XAQGZ374.js +197 -0
  59. package/dist/chunk-YPPPGGLA.cjs +99 -0
  60. package/dist/chunk-ZBLQV6UO.cjs +73 -0
  61. package/dist/chunk-ZFQZWXOI.cjs +75 -0
  62. package/dist/context-compaction/index.cjs +8 -0
  63. package/dist/context-compaction/index.d.cts +77 -0
  64. package/dist/context-compaction/index.d.ts +77 -0
  65. package/dist/context-compaction/index.js +8 -0
  66. package/dist/diff/index.cjs +9 -0
  67. package/dist/diff/index.d.cts +72 -0
  68. package/dist/diff/index.d.ts +72 -0
  69. package/dist/diff/index.js +9 -0
  70. package/dist/edit/index.cjs +10 -0
  71. package/dist/edit/index.d.cts +53 -0
  72. package/dist/edit/index.d.ts +53 -0
  73. package/dist/edit/index.js +10 -0
  74. package/dist/glob/index.cjs +10 -0
  75. package/dist/glob/index.d.cts +47 -0
  76. package/dist/glob/index.d.ts +47 -0
  77. package/dist/glob/index.js +10 -0
  78. package/dist/grep/index.cjs +10 -0
  79. package/dist/grep/index.d.cts +50 -0
  80. package/dist/grep/index.d.ts +50 -0
  81. package/dist/grep/index.js +10 -0
  82. package/dist/http-request/index.cjs +8 -0
  83. package/dist/http-request/index.d.cts +60 -0
  84. package/dist/http-request/index.d.ts +60 -0
  85. package/dist/http-request/index.js +8 -0
  86. package/dist/index.cjs +133 -0
  87. package/dist/index.d.cts +23 -0
  88. package/dist/index.d.ts +23 -0
  89. package/dist/index.js +133 -0
  90. package/dist/lsp/index.cjs +10 -0
  91. package/dist/lsp/index.d.cts +35 -0
  92. package/dist/lsp/index.d.ts +35 -0
  93. package/dist/lsp/index.js +10 -0
  94. package/dist/memory/index.cjs +9 -0
  95. package/dist/memory/index.d.cts +63 -0
  96. package/dist/memory/index.d.ts +63 -0
  97. package/dist/memory/index.js +9 -0
  98. package/dist/multi-edit/index.cjs +11 -0
  99. package/dist/multi-edit/index.d.cts +72 -0
  100. package/dist/multi-edit/index.d.ts +72 -0
  101. package/dist/multi-edit/index.js +11 -0
  102. package/dist/read/index.cjs +10 -0
  103. package/dist/read/index.d.cts +67 -0
  104. package/dist/read/index.d.ts +67 -0
  105. package/dist/read/index.js +10 -0
  106. package/dist/sleep/index.cjs +8 -0
  107. package/dist/sleep/index.d.cts +60 -0
  108. package/dist/sleep/index.d.ts +60 -0
  109. package/dist/sleep/index.js +8 -0
  110. package/dist/task-create/index.cjs +9 -0
  111. package/dist/task-create/index.d.cts +19 -0
  112. package/dist/task-create/index.d.ts +19 -0
  113. package/dist/task-create/index.js +9 -0
  114. package/dist/task-get/index.cjs +9 -0
  115. package/dist/task-get/index.d.cts +15 -0
  116. package/dist/task-get/index.d.ts +15 -0
  117. package/dist/task-get/index.js +9 -0
  118. package/dist/task-list/index.cjs +9 -0
  119. package/dist/task-list/index.d.cts +11 -0
  120. package/dist/task-list/index.d.ts +11 -0
  121. package/dist/task-list/index.js +9 -0
  122. package/dist/task-update/index.cjs +9 -0
  123. package/dist/task-update/index.d.cts +31 -0
  124. package/dist/task-update/index.d.ts +31 -0
  125. package/dist/task-update/index.js +9 -0
  126. package/dist/tool-search/index.cjs +8 -0
  127. package/dist/tool-search/index.d.cts +18 -0
  128. package/dist/tool-search/index.d.ts +18 -0
  129. package/dist/tool-search/index.js +8 -0
  130. package/dist/types-3QPDuCXN.d.cts +45 -0
  131. package/dist/types-3QPDuCXN.d.ts +45 -0
  132. package/dist/web-fetch/index.cjs +8 -0
  133. package/dist/web-fetch/index.d.cts +54 -0
  134. package/dist/web-fetch/index.d.ts +54 -0
  135. package/dist/web-fetch/index.js +8 -0
  136. package/dist/web-search/index.cjs +8 -0
  137. package/dist/web-search/index.d.cts +21 -0
  138. package/dist/web-search/index.d.ts +21 -0
  139. package/dist/web-search/index.js +8 -0
  140. package/dist/write/index.cjs +10 -0
  141. package/dist/write/index.d.cts +47 -0
  142. package/dist/write/index.d.ts +47 -0
  143. package/dist/write/index.js +10 -0
  144. package/package.json +170 -20
  145. package/dist/core/index.d.ts +0 -20
  146. package/dist/core/index.js +0 -1
  147. package/dist/core/index.js.map +0 -1
package/README.md CHANGED
@@ -1,80 +1,766 @@
1
+ <div align="center">
2
+
1
3
  # agentool
2
4
 
3
- Lightweight, provider-agnostic AI agent toolkit for CI/CD. Built-in bash, edit, grep, git, and HTTP tools with modular add-ons for Docker, test runners, and MCP.
5
+ **22 AI agent tools as standalone [Vercel AI SDK](https://sdk.vercel.ai/) modules.**
6
+
7
+ <p>
8
+ <a href="https://www.npmjs.com/package/agentool"><img src="https://img.shields.io/npm/v/agentool?style=flat-square&color=cb3837&logo=npm" alt="npm version" /></a>
9
+ <a href="https://www.npmjs.com/package/agentool"><img src="https://img.shields.io/npm/dm/agentool?style=flat-square&color=cb3837&logo=npm" alt="npm downloads" /></a>
10
+ <a href="https://github.com/Z-M-Huang/agentool"><img src="https://img.shields.io/github/stars/Z-M-Huang/agentool?style=flat-square&logo=github" alt="GitHub stars" /></a>
11
+ <a href="https://github.com/Z-M-Huang/agentool/issues"><img src="https://img.shields.io/github/issues/Z-M-Huang/agentool?style=flat-square&logo=github" alt="GitHub issues" /></a>
12
+ <a href="https://github.com/Z-M-Huang/agentool/blob/main/LICENSE"><img src="https://img.shields.io/github/license/Z-M-Huang/agentool?style=flat-square" alt="License" /></a>
13
+ </p>
14
+ <p>
15
+ <img src="https://img.shields.io/badge/node-%3E%3D18.0.0-339933?style=flat-square&logo=node.js&logoColor=white" alt="Node.js" />
16
+ <img src="https://img.shields.io/badge/TypeScript-5.7+-3178c6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript" />
17
+ <img src="https://img.shields.io/badge/Vercel%20AI%20SDK-v4%2B-000000?style=flat-square&logo=vercel&logoColor=white" alt="Vercel AI SDK" />
18
+ <img src="https://img.shields.io/badge/ESM%20%2B%20CJS-supported-22c55e?style=flat-square" alt="ESM + CJS" />
19
+ <img src="https://img.shields.io/badge/coverage-96%25-brightgreen?style=flat-square" alt="Test Coverage" />
20
+ <img src="https://visitor-badge.laobi.icu/badge?page_id=Z-M-Huang.agentool&style=flat-square" alt="Visitors" />
21
+ </p>
22
+ </div>
23
+
24
+ File operations, shell execution, code search, web fetching, and more -- everything an AI agent needs to interact with a codebase and system.
25
+
26
+ ---
27
+
28
+ ## Features
29
+
30
+ - **22 production-ready tools** -- bash, grep, glob, read, edit, write, web-fetch, web-search, tool-search, memory, multi-edit, diff, task-create, task-get, task-update, task-list, lsp, http-request, context-compaction, ask-user, sleep
31
+ - **Vercel AI SDK compatible** -- works with `generateText()`, `streamText()`, and any AI SDK provider (OpenAI, Anthropic, Google, etc.)
32
+ - **Factory + default pattern** -- `createBash({ cwd: '/my/project' })` for custom config, or just use `bash` with zero config
33
+ - **Dual ESM/CJS** -- works everywhere with proper `exports` map
34
+ - **TypeScript-first** -- full type declarations, strict mode, no `any`
35
+ - **Never throws** -- every `execute()` returns a descriptive error string instead of throwing
36
+ - **Tree-shakeable** -- 22 subpath exports, only import what you need
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ npm install agentool ai zod
42
+ ```
43
+
44
+ > `ai` and `zod` are peer dependencies. You also need an AI SDK provider like `@ai-sdk/openai`, `@ai-sdk/anthropic`, etc.
45
+
46
+ ### Prerequisites
47
+
48
+ - **Node.js >= 18**
49
+ - **[ripgrep](https://github.com/BurntSushi/ripgrep#installation)** (`rg`) -- required for `grep` and `glob` tools
50
+
51
+ ```bash
52
+ # macOS
53
+ brew install ripgrep
54
+
55
+ # Ubuntu/Debian
56
+ sudo apt install ripgrep
57
+
58
+ # Windows
59
+ choco install ripgrep
60
+ ```
61
+
62
+ ## Quick Start
63
+
64
+ ```typescript
65
+ import { generateText } from 'ai';
66
+ import { openai } from '@ai-sdk/openai';
67
+ import { bash, read, edit, glob, grep } from 'agentool';
68
+
69
+ const { text } = await generateText({
70
+ model: openai('gpt-4o'),
71
+ tools: { bash, read, edit, glob, grep },
72
+ maxSteps: 10,
73
+ prompt: 'Find all TypeScript files with TODO comments and list them',
74
+ });
75
+ ```
76
+
77
+ ### Tree-shake with subpath imports
78
+
79
+ ```typescript
80
+ // Only import what you need -- no unused code loaded
81
+ import { bash } from 'agentool/bash';
82
+ import { grep } from 'agentool/grep';
83
+ ```
84
+
85
+ ### Custom configuration
86
+
87
+ Use factory functions when you need to configure tools (custom `cwd`, timeouts, etc.):
88
+
89
+ ```typescript
90
+ import { createBash } from 'agentool/bash';
91
+ import { createRead } from 'agentool/read';
92
+
93
+ const myBash = createBash({ cwd: '/my/project', timeout: 60000 });
94
+ const myRead = createRead({ cwd: '/my/project' });
95
+
96
+ // Use them like any other tool
97
+ const { text } = await generateText({
98
+ model: openai('gpt-4o'),
99
+ tools: { bash: myBash, read: myRead },
100
+ maxSteps: 10,
101
+ prompt: 'List all files and read package.json',
102
+ });
103
+ ```
104
+
105
+ ## Tools Reference
106
+
107
+ ### bash
108
+
109
+ Execute shell commands with timeout and signal handling.
110
+
111
+ ```typescript
112
+ import { bash } from 'agentool/bash';
113
+
114
+ const result = await bash.execute(
115
+ { command: 'echo hello && ls -la' },
116
+ { toolCallId: 'id', messages: [] },
117
+ );
118
+ ```
119
+
120
+ With custom config:
121
+
122
+ ```typescript
123
+ import { createBash } from 'agentool/bash';
124
+
125
+ const bash = createBash({
126
+ cwd: '/my/project',
127
+ timeout: 60000, // 60s timeout (default: 120s)
128
+ shell: '/bin/zsh', // custom shell
129
+ });
130
+ ```
131
+
132
+ **Parameters:** `command` (string), `timeout?` (number), `description?` (string)
133
+
134
+ ---
135
+
136
+ ### read
137
+
138
+ Read files with line numbers, offset/limit pagination, and dual-path reading (fast for <10MB, streaming for larger).
139
+
140
+ ```typescript
141
+ import { read } from 'agentool/read';
142
+
143
+ // Read entire file
144
+ const content = await read.execute(
145
+ { file_path: '/app/src/index.ts' },
146
+ { toolCallId: 'id', messages: [] },
147
+ );
148
+ // Returns: "1\texport function hello() {\n2\t return 'world';\n3\t}"
149
+
150
+ // Read specific range
151
+ const range = await read.execute(
152
+ { file_path: '/app/src/index.ts', offset: 10, limit: 20 },
153
+ { toolCallId: 'id', messages: [] },
154
+ );
155
+ ```
156
+
157
+ **Parameters:** `file_path` (string), `offset?` (number), `limit?` (number)
158
+
159
+ ---
160
+
161
+ ### edit
162
+
163
+ Exact string replacement with curly-quote normalization fallback.
164
+
165
+ ```typescript
166
+ import { edit } from 'agentool/edit';
167
+
168
+ const result = await edit.execute(
169
+ {
170
+ file_path: '/app/src/config.ts',
171
+ old_string: 'const PORT = 3000;',
172
+ new_string: 'const PORT = 8080;',
173
+ },
174
+ { toolCallId: 'id', messages: [] },
175
+ );
176
+
177
+ // Replace all occurrences
178
+ const resultAll = await edit.execute(
179
+ {
180
+ file_path: '/app/src/config.ts',
181
+ old_string: 'localhost',
182
+ new_string: '0.0.0.0',
183
+ replace_all: true,
184
+ },
185
+ { toolCallId: 'id', messages: [] },
186
+ );
187
+ ```
188
+
189
+ **Parameters:** `file_path` (string), `old_string` (string), `new_string` (string), `replace_all?` (boolean)
190
+
191
+ ---
192
+
193
+ ### write
194
+
195
+ Write files with automatic parent directory creation.
196
+
197
+ ```typescript
198
+ import { write } from 'agentool/write';
199
+
200
+ const result = await write.execute(
201
+ {
202
+ file_path: '/app/src/utils/helpers.ts',
203
+ content: 'export function add(a: number, b: number) {\n return a + b;\n}\n',
204
+ },
205
+ { toolCallId: 'id', messages: [] },
206
+ );
207
+ // Returns: "Created file: /app/src/utils/helpers.ts (62 bytes)"
208
+ ```
209
+
210
+ **Parameters:** `file_path` (string), `content` (string)
211
+
212
+ ---
213
+
214
+ ### grep
215
+
216
+ Search file contents with ripgrep. Three output modes, context lines, pagination.
217
+
218
+ ```typescript
219
+ import { grep } from 'agentool/grep';
220
+
221
+ // Find matching lines with context
222
+ const content = await grep.execute(
223
+ { pattern: 'TODO|FIXME', output_mode: 'content', '-C': 2 },
224
+ { toolCallId: 'id', messages: [] },
225
+ );
226
+
227
+ // List files containing matches (sorted by mtime)
228
+ const files = await grep.execute(
229
+ { pattern: 'import.*react', output_mode: 'files_with_matches', glob: '*.tsx' },
230
+ { toolCallId: 'id', messages: [] },
231
+ );
232
+
233
+ // Count matches per file
234
+ const counts = await grep.execute(
235
+ { pattern: 'console\\.log', output_mode: 'count' },
236
+ { toolCallId: 'id', messages: [] },
237
+ );
238
+ ```
239
+
240
+ **Parameters:** `pattern` (string), `path?` (string), `output_mode?` (`'content'` | `'files_with_matches'` | `'count'`), `glob?` (string), `type?` (string), `-i?` (boolean), `-n?` (boolean), `-A?` (number), `-B?` (number), `-C?` / `context?` (number), `head_limit?` (number), `offset?` (number), `multiline?` (boolean)
241
+
242
+ ---
243
+
244
+ ### glob
245
+
246
+ Find files by pattern with ripgrep, sorted by modification time.
247
+
248
+ ```typescript
249
+ import { glob } from 'agentool/glob';
250
+
251
+ const result = await glob.execute(
252
+ { pattern: '**/*.test.ts' },
253
+ { toolCallId: 'id', messages: [] },
254
+ );
255
+ // Returns: "Found 27 files\n/app/tests/unit/bash.test.ts\n..."
256
+
257
+ // Search in specific directory
258
+ const result2 = await glob.execute(
259
+ { pattern: '*.json', path: '/app/config' },
260
+ { toolCallId: 'id', messages: [] },
261
+ );
262
+ ```
263
+
264
+ **Parameters:** `pattern` (string), `path?` (string)
265
+
266
+ ---
267
+
268
+ ### multi-edit
269
+
270
+ Atomically apply multiple edits to a single file. All succeed or none are applied.
271
+
272
+ ```typescript
273
+ import { multiEdit } from 'agentool/multi-edit';
274
+
275
+ const result = await multiEdit.execute(
276
+ {
277
+ file_path: '/app/src/config.ts',
278
+ edits: [
279
+ { old_string: 'const PORT = 3000;', new_string: 'const PORT = 8080;' },
280
+ { old_string: "const HOST = 'localhost';", new_string: "const HOST = '0.0.0.0';" },
281
+ ],
282
+ },
283
+ { toolCallId: 'id', messages: [] },
284
+ );
285
+ ```
286
+
287
+ **Parameters:** `file_path` (string), `edits` (array of `{ old_string, new_string }`)
288
+
289
+ ---
290
+
291
+ ### diff
292
+
293
+ Generate unified diffs between files or strings.
294
+
295
+ ```typescript
296
+ import { diff } from 'agentool/diff';
297
+
298
+ // Compare two files
299
+ const fileDiff = await diff.execute(
300
+ { file_path: '/app/old.ts', other_file_path: '/app/new.ts' },
301
+ { toolCallId: 'id', messages: [] },
302
+ );
303
+
304
+ // Compare strings
305
+ const stringDiff = await diff.execute(
306
+ { old_content: 'hello world', new_content: 'hello universe' },
307
+ { toolCallId: 'id', messages: [] },
308
+ );
309
+ ```
310
+
311
+ **Parameters:** `file_path?` (string), `other_file_path?` (string), `old_content?` (string), `new_content?` (string)
312
+
313
+ ---
314
+
315
+ ### web-fetch
316
+
317
+ Fetch URLs with automatic HTML-to-markdown conversion.
318
+
319
+ ```typescript
320
+ import { webFetch } from 'agentool/web-fetch';
321
+
322
+ const result = await webFetch.execute(
323
+ { url: 'https://example.com' },
324
+ { toolCallId: 'id', messages: [] },
325
+ );
326
+ // Returns markdown content (HTML converted via Turndown, truncated at 100K chars)
327
+ ```
328
+
329
+ **Parameters:** `url` (string, must be valid URL)
330
+
331
+ ---
332
+
333
+ ### web-search
334
+
335
+ Search the web with a callback-based implementation (bring your own search provider).
4
336
 
5
- ## What it is
337
+ ```typescript
338
+ import { createWebSearch } from 'agentool/web-search';
6
339
 
7
- A single npm package that gives AI agents a complete set of system tools for CI/CD automation. It wraps Vercel AI SDK v6 (`ai` package) and provides prebuilt tools, a simple agent runner, and modular add-ons via Node.js subpath exports.
340
+ const webSearch = createWebSearch({
341
+ onSearch: async (query, { allowed_domains, blocked_domains }) => {
342
+ // Use Tavily, SerpAPI, Google, or any search provider
343
+ const results = await mySearchProvider.search(query, { allowed_domains, blocked_domains });
344
+ return results.map(r => `${r.title}: ${r.url}\n${r.snippet}`).join('\n\n');
345
+ },
346
+ });
8
347
 
9
- The problem: if you want an AI agent that can run bash, edit files, grep code, call APIs, and interact with GitHub in a CI pipeline, you either use Claude Code (locked to Anthropic) or wire up a dozen libraries yourself. agentool gives you all of that out of the box, with any LLM provider — OpenAI, Anthropic, LiteLLM, or any OpenAI-compatible endpoint.
348
+ const result = await webSearch.execute(
349
+ { query: 'TypeScript best practices 2024', allowed_domains: ['typescript-eslint.io'] },
350
+ { toolCallId: 'id', messages: [] },
351
+ );
352
+ ```
10
353
 
11
- ## Tech stack
354
+ **Parameters:** `query` (string, min 2 chars), `allowed_domains?` (string[]), `blocked_domains?` (string[])
12
355
 
13
- - TypeScript (strict), Node.js 20+
14
- - Build: tsup
15
- - AI SDK: Vercel AI SDK v6 (`ai`) as peer dependency
16
- - Testing: vitest
17
- - Package manager: pnpm
18
- - License: Apache-2.0
356
+ ---
19
357
 
20
- ## Package structure
358
+ ### tool-search
21
359
 
22
- Single npm package, multiple entry points via subpath exports. Users install once (`npm install agentool`) and import only what they need.
360
+ Search through a registry of available tools by name or keyword.
23
361
 
24
362
  ```typescript
25
- import { createAgent, coreTools } from "agentool/core";
26
- import { dockerTools } from "agentool/docker";
27
- import { testRunnerTools } from "agentool/test-runner";
363
+ import { createToolSearch } from 'agentool/tool-search';
364
+
365
+ const toolSearch = createToolSearch({
366
+ tools: {
367
+ bash: { description: 'Execute shell commands' },
368
+ grep: { description: 'Search file contents with regex' },
369
+ read: { description: 'Read file contents' },
370
+ },
371
+ });
372
+
373
+ const result = await toolSearch.execute(
374
+ { query: 'file', max_results: 3 },
375
+ { toolCallId: 'id', messages: [] },
376
+ );
377
+ // Returns matching tools sorted by relevance
28
378
  ```
29
379
 
30
- ## Modules
380
+ **Parameters:** `query` (string), `max_results?` (number, default 5)
381
+
382
+ ---
383
+
384
+ ### http-request
31
385
 
32
- **agentool/core** (must-have, zero optional deps)
33
- - `createAgent` — agent runner wrapping AI SDK ToolLoopAgent, auto-assembles system prompt from tool descriptions
34
- - `bash` — shell command execution via child_process
35
- - `read_file` — read file contents with optional line range
36
- - `write_file` — create/overwrite files
37
- - `edit` — str_replace style find-and-replace (oldStr must be unique in file)
38
- - `grep` — structured search, uses ripgrep if available, falls back to native grep
39
- - `find` — find files by glob pattern
40
- - `git` — diff, log, status, blame, show
41
- - `gh` — GitHub CLI wrapper (pr, issue, workflow, api)
42
- - `http` — structured HTTP requests via native fetch
386
+ Make raw HTTP requests without markdown conversion.
43
387
 
44
- **agentool/docker** (add-on)
45
- - docker build, run, compose, logs
388
+ ```typescript
389
+ import { httpRequest } from 'agentool/http-request';
46
390
 
47
- **agentool/test-runner** (add-on)
48
- - Generic test runner with structured output parsing (jest, vitest, pytest)
391
+ const result = await httpRequest.execute(
392
+ {
393
+ method: 'POST',
394
+ url: 'https://api.example.com/data',
395
+ headers: { 'Content-Type': 'application/json' },
396
+ body: JSON.stringify({ key: 'value' }),
397
+ timeout: 5000,
398
+ },
399
+ { toolCallId: 'id', messages: [] },
400
+ );
401
+ // Returns JSON: { status, statusText, headers, body }
402
+ ```
49
403
 
50
- **agentool/data-parse** (add-on)
51
- - jq, yq, csv parsing
404
+ **Parameters:** `method` (`'GET'` | `'POST'` | `'PUT'` | `'PATCH'` | `'DELETE'` | `'HEAD'`), `url` (string), `headers?` (object), `body?` (string), `timeout?` (number)
52
405
 
53
- **agentool/code-intel** (add-on)
54
- - ast-grep, directory tree, symbol extraction
406
+ ---
55
407
 
56
- **agentool/mcp** (add-on)
57
- - Generic MCP client bridge — connect to any MCP server and expose its tools
408
+ ### memory
58
409
 
59
- ## Usage
410
+ File-based key-value store for persistent agent memory.
60
411
 
61
412
  ```typescript
62
- import { createAgent, coreTools } from "agentool/core";
413
+ import { memory } from 'agentool/memory';
414
+
415
+ // Write
416
+ await memory.execute(
417
+ { action: 'write', key: 'user-prefs', content: 'Prefers dark mode' },
418
+ { toolCallId: 'id', messages: [] },
419
+ );
420
+
421
+ // Read
422
+ const data = await memory.execute(
423
+ { action: 'read', key: 'user-prefs' },
424
+ { toolCallId: 'id', messages: [] },
425
+ );
426
+
427
+ // List all keys
428
+ const keys = await memory.execute(
429
+ { action: 'list' },
430
+ { toolCallId: 'id', messages: [] },
431
+ );
432
+
433
+ // Delete
434
+ await memory.execute(
435
+ { action: 'delete', key: 'user-prefs' },
436
+ { toolCallId: 'id', messages: [] },
437
+ );
438
+ ```
439
+
440
+ **Parameters:** `action` (`'read'` | `'write'` | `'list'` | `'delete'`), `key?` (string), `content?` (string)
441
+
442
+ ---
443
+
444
+ ### task-create
445
+
446
+ Create a new task with subject, description, and optional metadata.
447
+
448
+ ```typescript
449
+ import { taskCreate } from 'agentool/task-create';
450
+
451
+ const result = await taskCreate.execute(
452
+ { subject: 'Fix login bug', description: 'Auth fails on refresh', metadata: { priority: 'high' } },
453
+ { toolCallId: 'id', messages: [] },
454
+ );
455
+ ```
456
+
457
+ **Parameters:** `subject` (string), `description` (string), `metadata?` (Record<string, unknown>)
458
+
459
+ ---
460
+
461
+ ### task-get
462
+
463
+ Retrieve a task by ID to see full details.
464
+
465
+ ```typescript
466
+ import { taskGet } from 'agentool/task-get';
467
+
468
+ const result = await taskGet.execute(
469
+ { taskId: 'abc123' },
470
+ { toolCallId: 'id', messages: [] },
471
+ );
472
+ ```
63
473
 
64
- const agent = createAgent({
65
- model: "openai/gpt-4o",
66
- // Or LiteLLM: baseURL: "http://localhost:4000/v1"
67
- tools: { ...coreTools() },
474
+ **Parameters:** `taskId` (string)
475
+
476
+ ---
477
+
478
+ ### task-update
479
+
480
+ Update a task's status, owner, metadata, and dependency relationships.
481
+
482
+ ```typescript
483
+ import { taskUpdate } from 'agentool/task-update';
484
+
485
+ // Update status and owner
486
+ await taskUpdate.execute(
487
+ { taskId: 'abc123', status: 'in_progress', owner: 'agent-1' },
488
+ { toolCallId: 'id', messages: [] },
489
+ );
490
+
491
+ // Add dependencies and merge metadata (null deletes a key)
492
+ await taskUpdate.execute(
493
+ { taskId: 'abc123', addBlockedBy: ['def456'], metadata: { priority: null, notes: 'reviewed' } },
494
+ { toolCallId: 'id', messages: [] },
495
+ );
496
+ ```
497
+
498
+ **Parameters:** `taskId` (string), `subject?` (string), `description?` (string), `status?` (`'pending'` | `'in_progress'` | `'completed'` | `'deleted'`), `owner?` (string), `activeForm?` (string), `addBlocks?` (string[]), `addBlockedBy?` (string[]), `metadata?` (Record<string, unknown>)
499
+
500
+ ---
501
+
502
+ ### task-list
503
+
504
+ List all non-deleted tasks with status and dependencies.
505
+
506
+ ```typescript
507
+ import { taskList } from 'agentool/task-list';
508
+
509
+ const result = await taskList.execute(
510
+ {},
511
+ { toolCallId: 'id', messages: [] },
512
+ );
513
+ ```
514
+
515
+ **Parameters:** none
516
+
517
+ ---
518
+
519
+ ### lsp
520
+
521
+ Language Server Protocol operations for code intelligence.
522
+
523
+ ```typescript
524
+ import { createLsp } from 'agentool/lsp';
525
+
526
+ const lsp = createLsp({
527
+ servers: {
528
+ '.ts': { command: 'typescript-language-server', args: ['--stdio'] },
529
+ '.py': { command: 'pylsp' },
530
+ },
68
531
  });
69
532
 
70
- const result = await agent.run("Find why the tests are failing and fix it");
533
+ const result = await lsp.execute(
534
+ { operation: 'goToDefinition', filePath: 'src/index.ts', line: 10, character: 5 },
535
+ { toolCallId: 'id', messages: [] },
536
+ );
71
537
  ```
72
538
 
73
- ## Implementation priorities
539
+ **Parameters:** `operation` (`'goToDefinition'` | `'findReferences'` | `'hover'` | `'documentSymbol'` | `'workspaceSymbol'` | `'goToImplementation'` | `'prepareCallHierarchy'` | `'incomingCalls'` | `'outgoingCalls'`), `filePath` (string), `line` (number, 1-based), `character` (number, 1-based)
540
+
541
+ ---
542
+
543
+ ### context-compaction
544
+
545
+ Compact conversation history to fit within token budgets.
546
+
547
+ ```typescript
548
+ import { createContextCompaction } from 'agentool/context-compaction';
549
+
550
+ const compact = createContextCompaction({
551
+ maxTokens: 4096,
552
+ summarize: async (messages) => {
553
+ // Call your LLM to summarize
554
+ return 'Summary of previous conversation...';
555
+ },
556
+ });
557
+
558
+ const result = await compact.execute(
559
+ {
560
+ messages: [
561
+ { role: 'user', content: 'Long conversation...' },
562
+ { role: 'assistant', content: 'Long response...' },
563
+ ],
564
+ },
565
+ { toolCallId: 'id', messages: [] },
566
+ );
567
+ ```
568
+
569
+ **Parameters:** `messages` (array of `{ role, content }`), `maxTokens?` (number)
570
+
571
+ ---
572
+
573
+ ### ask-user
574
+
575
+ Prompt the user for input during agent execution.
576
+
577
+ ```typescript
578
+ import { createAskUser } from 'agentool/ask-user';
579
+
580
+ const askUser = createAskUser({
581
+ onQuestion: async (question, options) => {
582
+ // Your UI logic to prompt the user
583
+ return 'User response here';
584
+ },
585
+ });
586
+
587
+ const answer = await askUser.execute(
588
+ { question: 'Which database should I use?', options: ['PostgreSQL', 'MySQL', 'SQLite'] },
589
+ { toolCallId: 'id', messages: [] },
590
+ );
591
+ ```
592
+
593
+ **Parameters:** `question` (string), `options?` (string[])
594
+
595
+ ---
596
+
597
+ ### sleep
598
+
599
+ Pause execution for rate limiting or polling intervals.
600
+
601
+ ```typescript
602
+ import { sleep } from 'agentool/sleep';
603
+
604
+ const result = await sleep.execute(
605
+ { durationMs: 2000, reason: 'Waiting for deployment' },
606
+ { toolCallId: 'id', messages: [] },
607
+ );
608
+ // Returns: "Slept for 2001ms. Reason: Waiting for deployment"
609
+ ```
610
+
611
+ **Parameters:** `durationMs` (number, max 300000), `reason?` (string)
612
+
613
+ ## Configuration
614
+
615
+ Every tool follows the **factory + default** pattern:
616
+
617
+ ```typescript
618
+ // Default instance -- uses process.cwd(), default timeouts
619
+ import { bash } from 'agentool/bash';
620
+
621
+ // Custom instance -- configure cwd, timeouts, and tool-specific options
622
+ import { createBash } from 'agentool/bash';
623
+ const myBash = createBash({
624
+ cwd: '/my/project',
625
+ timeout: 60000,
626
+ shell: '/bin/zsh',
627
+ });
628
+ ```
629
+
630
+ ### Base configuration
631
+
632
+ All tools accept `BaseToolConfig`:
633
+
634
+ | Option | Type | Default | Description |
635
+ |--------|------|---------|-------------|
636
+ | `cwd` | `string` | `process.cwd()` | Working directory for file operations |
637
+
638
+ Tools that support timeouts extend `TimeoutConfig`:
639
+
640
+ | Option | Type | Default | Description |
641
+ |--------|------|---------|-------------|
642
+ | `timeout` | `number` | varies | Timeout in milliseconds |
643
+
644
+ ### Tool-specific configuration
645
+
646
+ | Tool | Extra Config |
647
+ |------|-------------|
648
+ | `bash` | `shell?: string` -- shell binary path |
649
+ | `read` | `maxLines?: number` -- max lines to return (default: 2000) |
650
+ | `memory` | `memoryDir?: string` -- storage directory |
651
+ | `task-create` | `tasksFile?: string` -- JSON file path |
652
+ | `task-get` | `tasksFile?: string` -- JSON file path |
653
+ | `task-update` | `tasksFile?: string` -- JSON file path |
654
+ | `task-list` | `tasksFile?: string` -- JSON file path |
655
+ | `web-search` | `onSearch?: (query, opts) => Promise<string>` -- search callback |
656
+ | `tool-search` | `tools?: Record<string, { description }>` -- tool registry |
657
+ | `lsp` | `servers?: Record<string, LspServerConfig>` -- LSP servers by file extension |
658
+ | `http-request` | `defaultHeaders?: Record<string, string>` -- headers merged into every request |
659
+ | `web-fetch` | `maxContentLength?: number`, `userAgent?: string` |
660
+ | `context-compaction` | `summarize?: (messages) => Promise<string>`, `maxTokens?: number` |
661
+ | `ask-user` | `onQuestion?: (question, options?) => Promise<string>` |
662
+ | `sleep` | `maxDuration?: number` -- cap in ms (default: 300000) |
663
+
664
+ ## Error Handling
665
+
666
+ Every tool's `execute()` catches errors internally and returns a descriptive string -- **it never throws**:
667
+
668
+ ```typescript
669
+ const result = await read.execute(
670
+ { file_path: '/nonexistent/file.ts' },
671
+ { toolCallId: 'id', messages: [] },
672
+ );
673
+ // Returns: "Error [read]: Failed to read file: ENOENT: no such file or directory..."
674
+ ```
675
+
676
+ Error strings follow the format: `Error [tool-name]: {description}` with actionable context to help the AI model recover.
677
+
678
+ ## Imports
679
+
680
+ ### Barrel import (all tools)
681
+
682
+ ```typescript
683
+ import {
684
+ bash, createBash,
685
+ read, createRead,
686
+ edit, createEdit,
687
+ write, createWrite,
688
+ grep, createGrep,
689
+ glob, createGlob,
690
+ webFetch, createWebFetch,
691
+ webSearch, createWebSearch,
692
+ toolSearch, createToolSearch,
693
+ httpRequest, createHttpRequest,
694
+ memory, createMemory,
695
+ multiEdit, createMultiEdit,
696
+ diff, createDiff,
697
+ taskCreate, createTaskCreate,
698
+ taskGet, createTaskGet,
699
+ taskUpdate, createTaskUpdate,
700
+ taskList, createTaskList,
701
+ lsp, createLsp,
702
+ contextCompaction, createContextCompaction,
703
+ askUser, createAskUser,
704
+ sleep, createSleep,
705
+ } from 'agentool';
706
+ ```
707
+
708
+ ### Subpath imports (tree-shakeable)
709
+
710
+ ```typescript
711
+ import { bash } from 'agentool/bash';
712
+ import { grep } from 'agentool/grep';
713
+ import { glob } from 'agentool/glob';
714
+ import { read } from 'agentool/read';
715
+ import { edit } from 'agentool/edit';
716
+ import { write } from 'agentool/write';
717
+ import { webFetch } from 'agentool/web-fetch';
718
+ import { httpRequest } from 'agentool/http-request';
719
+ import { memory } from 'agentool/memory';
720
+ import { multiEdit } from 'agentool/multi-edit';
721
+ import { diff } from 'agentool/diff';
722
+ import { taskCreate } from 'agentool/task-create';
723
+ import { taskGet } from 'agentool/task-get';
724
+ import { taskUpdate } from 'agentool/task-update';
725
+ import { taskList } from 'agentool/task-list';
726
+ import { webSearch } from 'agentool/web-search';
727
+ import { toolSearch } from 'agentool/tool-search';
728
+ import { lsp } from 'agentool/lsp';
729
+ import { contextCompaction } from 'agentool/context-compaction';
730
+ import { askUser } from 'agentool/ask-user';
731
+ import { sleep } from 'agentool/sleep';
732
+ ```
733
+
734
+ ## Full Example: AI Coding Agent
735
+
736
+ ```typescript
737
+ import { generateText } from 'ai';
738
+ import { openai } from '@ai-sdk/openai';
739
+ import { bash, read, edit, write, glob, grep, diff } from 'agentool';
740
+
741
+ const { text, steps } = await generateText({
742
+ model: openai('gpt-4o'),
743
+ tools: { bash, read, edit, write, glob, grep, diff },
744
+ maxSteps: 20,
745
+ system: `You are a coding assistant. You can read, search, edit, and write files.
746
+ Always read a file before editing it. Use grep to search for patterns.
747
+ Use glob to find files. Use bash for git, build, and test commands.`,
748
+ prompt: 'Find all console.log statements in src/ and replace them with proper logger calls',
749
+ });
750
+
751
+ console.log(`Completed in ${steps.length} steps`);
752
+ console.log(text);
753
+ ```
754
+
755
+ ## Requirements
756
+
757
+ | Dependency | Version | Required |
758
+ |-----------|---------|----------|
759
+ | Node.js | >= 18 | Yes |
760
+ | `ai` (Vercel AI SDK) | >= 4.0.0 | Peer dependency |
761
+ | `zod` | >= 3.23.0 | Peer dependency |
762
+ | `ripgrep` (`rg`) | any | For grep/glob tools |
763
+
764
+ ## License
74
765
 
75
- 1. Core types (ToolDefinition, ToolResult, ToolPack interfaces)
76
- 2. Core tools (bash, read_file, write_file, edit, grep, find, git, gh, http)
77
- 3. createAgent runner
78
- 4. System prompt auto-assembly
79
- 5. Add-on modules (docker, test-runner, data-parse, code-intel, mcp)
80
- 6. Tests for each tool
766
+ [Apache-2.0](LICENSE)