@alexanderfortin/pi-tavily-tools 0.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.
- package/LICENSE +21 -0
- package/README.md +366 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +7 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/shared/truncation.d.ts +21 -0
- package/dist/tools/shared/truncation.d.ts.map +1 -0
- package/dist/tools/shared/truncation.js +55 -0
- package/dist/tools/shared/truncation.js.map +1 -0
- package/dist/tools/tavily/client.d.ts +27 -0
- package/dist/tools/tavily/client.d.ts.map +1 -0
- package/dist/tools/tavily/client.js +62 -0
- package/dist/tools/tavily/client.js.map +1 -0
- package/dist/tools/tavily/formatters.d.ts +21 -0
- package/dist/tools/tavily/formatters.d.ts.map +1 -0
- package/dist/tools/tavily/formatters.js +108 -0
- package/dist/tools/tavily/formatters.js.map +1 -0
- package/dist/tools/tavily/renderers.d.ts +28 -0
- package/dist/tools/tavily/renderers.d.ts.map +1 -0
- package/dist/tools/tavily/renderers.js +116 -0
- package/dist/tools/tavily/renderers.js.map +1 -0
- package/dist/tools/tavily/schemas.d.ts +24 -0
- package/dist/tools/tavily/schemas.d.ts.map +1 -0
- package/dist/tools/tavily/schemas.js +36 -0
- package/dist/tools/tavily/schemas.js.map +1 -0
- package/dist/tools/tavily/types.d.ts +53 -0
- package/dist/tools/tavily/types.d.ts.map +1 -0
- package/dist/tools/tavily/types.js +5 -0
- package/dist/tools/tavily/types.js.map +1 -0
- package/dist/tools/web-search.d.ts +16 -0
- package/dist/tools/web-search.d.ts.map +1 -0
- package/dist/tools/web-search.js +120 -0
- package/dist/tools/web-search.js.map +1 -0
- package/package.json +77 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alexander Fortin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
# Pi Tavily Web Search Extension
|
|
2
|
+
|
|
3
|
+
Add web search capabilities to Pi using the Tavily search API.
|
|
4
|
+
|
|
5
|
+
This extension provides a `web_search` tool that the LLM can use to find current information, recent news, documentation, and time-sensitive data.
|
|
6
|
+
|
|
7
|
+
Requires a valid `TAVILY_API_KEY` exported in the enviornment, e.g.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
TAVILY_API_KEY=tvly-xxxx-xxxxxxx-xxxxxxxxxx pi
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
You can get a free one at <https://tavily.com>
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- **Web Search:** Query the web for real-time information
|
|
18
|
+
- **AI-Generated Answers:** Get direct answers to questions powered by Tavily
|
|
19
|
+
- **Configurable Depth:** Choose between "basic" and "advanced" search modes
|
|
20
|
+
- **Time Filtering:** Limit results to recent timeframes (e.g., last 7 days)
|
|
21
|
+
- **Image Support:** Include relevant images in search results
|
|
22
|
+
- **Content Extraction:** Optional raw content for deeper analysis
|
|
23
|
+
- **Proper Truncation:** Output truncated to 50KB / 2000 lines to avoid context overflow
|
|
24
|
+
- **Custom TUI Rendering:** Beautiful display with expandable results
|
|
25
|
+
- **Error Handling:** Graceful failures with helpful error messages
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
### Option 1: Install from npm (Recommended)
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pi install npm:@alexanderfortin/pi-tavily-tools
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Option 2: Install from Git
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pi install git:github.com/shaftoe/pi-tavily-tools
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Option 3: Quick Test with -e flag
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git clone https://github.com/shaftoe/pi-tavily-tools
|
|
45
|
+
cd pi-tavily-tools
|
|
46
|
+
pi -e ./src/index.ts
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Setup
|
|
50
|
+
|
|
51
|
+
### 1. Get a Tavily API Key
|
|
52
|
+
|
|
53
|
+
Visit <https://tavily.com> and sign up for a free account. The free tier includes:
|
|
54
|
+
|
|
55
|
+
- 1,000 requests per month
|
|
56
|
+
- Basic search depth
|
|
57
|
+
- Standard rate limits
|
|
58
|
+
|
|
59
|
+
### 2. Configure the API Key
|
|
60
|
+
|
|
61
|
+
Set the `TAVILY_API_KEY` environment variable:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
export TAVILY_API_KEY="your-api-key-here"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Add to your shell profile** (~/.zshrc, ~/.bashrc, etc.) for persistent access:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
echo 'export TAVILY_API_KEY="your-api-key-here"' >> ~/.zshrc
|
|
71
|
+
source ~/.zshrc
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
### Basic Web Search
|
|
77
|
+
|
|
78
|
+
Simply ask Pi to search the web:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
Search for the latest version of React
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
What are the new features in TypeScript 6.0?
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
Find recent news about artificial intelligence
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Time-Limited Search
|
|
93
|
+
|
|
94
|
+
Limit results to a specific timeframe:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
Search for AI news from the last 7 days
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
Show me the latest JavaScript updates from the past 30 days
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Advanced Search
|
|
105
|
+
|
|
106
|
+
Use advanced search depth for more detailed results:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
Search for quantum computing trends using advanced search
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Image Search
|
|
113
|
+
|
|
114
|
+
Include relevant images in results:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
Find cute cats with images
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Raw Content
|
|
121
|
+
|
|
122
|
+
Get detailed content from search results:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
Search for Bun test runner documentation and include raw content
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Available Parameters
|
|
129
|
+
|
|
130
|
+
The `web_search` tool accepts the following parameters:
|
|
131
|
+
|
|
132
|
+
| Parameter | Type | Required | Default | Description |
|
|
133
|
+
| --------------------- | ------- | -------- | ------- | ---------------------------------------------- |
|
|
134
|
+
| `query` | string | Yes | - | The search query string |
|
|
135
|
+
| `max_results` | number | No | 5 | Number of results to return (1-20) |
|
|
136
|
+
| `search_depth` | string | No | "basic" | Search depth: "basic" or "advanced" |
|
|
137
|
+
| `include_answer` | boolean | No | true | Include AI-generated answer |
|
|
138
|
+
| `include_raw_content` | boolean | No | false | Include raw page content (markdown or text) |
|
|
139
|
+
| `include_images` | boolean | No | false | Include relevant images |
|
|
140
|
+
| `days` | number | No | - | Limit results to last N days (e.g., 7, 30, 90) |
|
|
141
|
+
|
|
142
|
+
### Parameter Examples
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// Basic search
|
|
146
|
+
{ query: "TypeScript 6" }
|
|
147
|
+
|
|
148
|
+
// Time-limited search
|
|
149
|
+
{ query: "AI news", days: 7 }
|
|
150
|
+
|
|
151
|
+
// Advanced search with more results
|
|
152
|
+
{ query: "quantum computing", search_depth: "advanced", max_results: 10 }
|
|
153
|
+
|
|
154
|
+
// Search with images
|
|
155
|
+
{ query: "cute cats", include_images: true }
|
|
156
|
+
|
|
157
|
+
// Search with raw content
|
|
158
|
+
{ query: "Bun documentation", include_raw_content: true }
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Output Truncation
|
|
162
|
+
|
|
163
|
+
To prevent overwhelming the LLM context, tool output is truncated to:
|
|
164
|
+
|
|
165
|
+
- **50KB** of data
|
|
166
|
+
- **2,000 lines** of text
|
|
167
|
+
|
|
168
|
+
Whichever limit is hit first triggers truncation.
|
|
169
|
+
|
|
170
|
+
When output is truncated:
|
|
171
|
+
|
|
172
|
+
- A warning is displayed in the results
|
|
173
|
+
- Full output is saved to a temp file in your project directory: `.pi-tavily-temp/search-{timestamp}.txt`
|
|
174
|
+
- The LLM is informed where to find the complete output
|
|
175
|
+
|
|
176
|
+
## Troubleshooting
|
|
177
|
+
|
|
178
|
+
### "TAVILY_API_KEY is not set"
|
|
179
|
+
|
|
180
|
+
**Error Message:**
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
Error: TAVILY_API_KEY environment variable is not set.
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Solution:**
|
|
187
|
+
|
|
188
|
+
1. Get an API key from <https://tavily.com>
|
|
189
|
+
2. Set the environment variable:
|
|
190
|
+
```bash
|
|
191
|
+
export TAVILY_API_KEY="your-api-key-here"
|
|
192
|
+
```
|
|
193
|
+
3. Add to your shell profile for persistence:
|
|
194
|
+
```bash
|
|
195
|
+
echo 'export TAVILY_API_KEY="your-api-key-here"' >> ~/.zshrc
|
|
196
|
+
source ~/.zshrc
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### "Failed to initialize Tavily client"
|
|
200
|
+
|
|
201
|
+
**Error Message:**
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
Error: Failed to initialize Tavily client: ...
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Possible Causes:**
|
|
208
|
+
|
|
209
|
+
1. Invalid API key format
|
|
210
|
+
2. Network connectivity issues
|
|
211
|
+
3. Tavily API is down
|
|
212
|
+
|
|
213
|
+
**Solutions:**
|
|
214
|
+
|
|
215
|
+
1. Verify your API key is correct (should start with "tvly-")
|
|
216
|
+
2. Check your internet connection
|
|
217
|
+
3. Try a simple curl test:
|
|
218
|
+
```bash
|
|
219
|
+
curl -X POST https://api.tavily.com/search \\
|
|
220
|
+
-H "Content-Type: application/json" \\
|
|
221
|
+
-d '{"api_key":"YOUR_KEY","query":"test","max_results":1}'
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Rate Limit Errors
|
|
225
|
+
|
|
226
|
+
**Error Message:**
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
Error: You have exceeded your monthly request limit
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Solution:**
|
|
233
|
+
|
|
234
|
+
- The free tier includes 1,000 requests per month
|
|
235
|
+
- Upgrade your Tavily plan if you need more requests
|
|
236
|
+
- Visit <https://tavily.com/pricing> for details
|
|
237
|
+
|
|
238
|
+
### No Results Found
|
|
239
|
+
|
|
240
|
+
**Symptoms:**
|
|
241
|
+
|
|
242
|
+
- Search returns "No results found."
|
|
243
|
+
- Empty results list
|
|
244
|
+
|
|
245
|
+
**Solutions:**
|
|
246
|
+
|
|
247
|
+
1. Try a broader or different search query
|
|
248
|
+
2. Check spelling of your query
|
|
249
|
+
3. Remove any special characters or complex filters
|
|
250
|
+
4. Try basic search depth instead of advanced
|
|
251
|
+
|
|
252
|
+
## Development
|
|
253
|
+
|
|
254
|
+
### Project Structure
|
|
255
|
+
|
|
256
|
+
```
|
|
257
|
+
pi-tavily-tools/
|
|
258
|
+
├── .github/
|
|
259
|
+
│ └── dependabot.yml # Dependency update configuration
|
|
260
|
+
├── .envrc # Direnv configuration for API keys
|
|
261
|
+
├── .gitignore
|
|
262
|
+
├── .prettierignore
|
|
263
|
+
├── .prettierrc # Prettier code formatter config
|
|
264
|
+
├── AGENTS.md # Project guidelines for Pi agents
|
|
265
|
+
├── LICENSE
|
|
266
|
+
├── README.md
|
|
267
|
+
├── bun.lock
|
|
268
|
+
├── eslint.config.js # ESLint linting config
|
|
269
|
+
├── lefthook.yml # Git hooks configuration
|
|
270
|
+
├── package.json # Package manifest
|
|
271
|
+
├── tsconfig.json # TypeScript compiler config
|
|
272
|
+
├── src/
|
|
273
|
+
│ ├── index.ts # Extension entry point
|
|
274
|
+
│ └── tools/
|
|
275
|
+
│ ├── index.ts # Tool exports
|
|
276
|
+
│ ├── web-search.ts # Web search tool implementation
|
|
277
|
+
│ ├── tavily/ # Tavily API integration
|
|
278
|
+
│ │ ├── client.ts # Tavily client & initialization
|
|
279
|
+
│ │ ├── formatters.ts # Response formatting
|
|
280
|
+
│ │ ├── renderers.ts # TUI rendering utilities
|
|
281
|
+
│ │ ├── schemas.ts # TypeBox parameter schemas
|
|
282
|
+
│ │ └── types.ts # Type definitions
|
|
283
|
+
│ └── shared/ # Shared utilities
|
|
284
|
+
│ └── truncation.ts # Output truncation utilities
|
|
285
|
+
└── tests/
|
|
286
|
+
├── integration/ # Integration tests
|
|
287
|
+
│ └── web-search.test.ts
|
|
288
|
+
├── client.test.ts
|
|
289
|
+
├── create-error-output.test.ts
|
|
290
|
+
├── formatters.test.ts
|
|
291
|
+
├── renderers.test.ts
|
|
292
|
+
├── schemas.test.ts
|
|
293
|
+
└── truncation.test.ts
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Running Type Checks
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
bun run check
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Watch mode for instant feedback during development:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
bun run check:watch
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Running Tests
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
bun run test
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Watch mode for continuous testing:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
bun run test:watch
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Run only integration tests (requires valid API key):
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
bun test tests/integration/
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Running Linting
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
bun run lint
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Formatting Code
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
bun run format:fix
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### All Checks
|
|
339
|
+
|
|
340
|
+
Run all checks before committing:
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
bun run check && bun run lint && bun run test
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## License
|
|
347
|
+
|
|
348
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
349
|
+
|
|
350
|
+
## Contributing
|
|
351
|
+
|
|
352
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
353
|
+
|
|
354
|
+
## Support
|
|
355
|
+
|
|
356
|
+
- **GitHub Issues:** [shaftoe/pi-tavily-tools/issues](https://github.com/shaftoe/pi-tavily-tools/issues)
|
|
357
|
+
- **Tavily Documentation:** [https://docs.tavily.com](https://docs.tavily.com)
|
|
358
|
+
- **Pi Documentation:** [https://shittycodingagent.ai](https://shittycodingagent.ai)
|
|
359
|
+
|
|
360
|
+
## Acknowledgments
|
|
361
|
+
|
|
362
|
+
Built with:
|
|
363
|
+
|
|
364
|
+
- [Tavily API](https://tavily.com) - Web search and AI answers
|
|
365
|
+
- [Pi Coding Agent](https://pi.dev) - Extension framework
|
|
366
|
+
- [Bun](https://bun.sh) - Package manager and test runner
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pi Tavily Web Search Extension
|
|
3
|
+
*
|
|
4
|
+
* Provides web search capabilities to Pi using Tavily's search API.
|
|
5
|
+
* Adds a `web_search` tool that the LLM can use to find current
|
|
6
|
+
* information, recent news, documentation, and time-sensitive data.
|
|
7
|
+
*/
|
|
8
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
9
|
+
/**
|
|
10
|
+
* Main extension entry point.
|
|
11
|
+
*
|
|
12
|
+
* Defers tool registration to `session_start` so Pi can start
|
|
13
|
+
* even if the TAVILY_API_KEY is missing. The tool is registered only
|
|
14
|
+
* once on the first agent run and persists across sessions.
|
|
15
|
+
*/
|
|
16
|
+
export default function (pi: ExtensionAPI): void;
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAIlE;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,YAAY,GAAG,IAAI,CAmB/C"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pi Tavily Web Search Extension
|
|
3
|
+
*
|
|
4
|
+
* Provides web search capabilities to Pi using Tavily's search API.
|
|
5
|
+
* Adds a `web_search` tool that the LLM can use to find current
|
|
6
|
+
* information, recent news, documentation, and time-sensitive data.
|
|
7
|
+
*/
|
|
8
|
+
import { createTavilyClient } from "./tools/tavily/client.js";
|
|
9
|
+
import { registerWebSearchTool } from "./tools/web-search.js";
|
|
10
|
+
/**
|
|
11
|
+
* Main extension entry point.
|
|
12
|
+
*
|
|
13
|
+
* Defers tool registration to `session_start` so Pi can start
|
|
14
|
+
* even if the TAVILY_API_KEY is missing. The tool is registered only
|
|
15
|
+
* once on the first agent run and persists across sessions.
|
|
16
|
+
*/
|
|
17
|
+
export default function (pi) {
|
|
18
|
+
let registered = false;
|
|
19
|
+
pi.on("session_start", (_event, ctx) => {
|
|
20
|
+
if (registered)
|
|
21
|
+
return;
|
|
22
|
+
registered = true;
|
|
23
|
+
try {
|
|
24
|
+
const client = createTavilyClient();
|
|
25
|
+
registerWebSearchTool(pi, client);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (error instanceof Error) {
|
|
29
|
+
ctx.ui.notify(`[pi-tavily-tools] ${error.message}`, "error");
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// Re-throw non-Error types (shouldn't happen, but be safe)
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,WAAW,EAAgB;IACvC,IAAI,UAAU,GAAG,KAAK,CAAC;IAEvB,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QACrC,IAAI,UAAU;YAAE,OAAO;QACvB,UAAU,GAAG,IAAI,CAAC;QAElB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;YACpC,qBAAqB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,qBAAqB,KAAK,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;YAC/D,CAAC;iBAAM,CAAC;gBACN,2DAA2D;gBAC3D,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared truncation utilities
|
|
3
|
+
*/
|
|
4
|
+
import { type TruncationResult } from "@mariozechner/pi-coding-agent";
|
|
5
|
+
export interface TruncatedOutput {
|
|
6
|
+
content: string;
|
|
7
|
+
truncation?: TruncationResult;
|
|
8
|
+
fullOutputPath?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Apply truncation to output and save full content to temp file if needed
|
|
12
|
+
*/
|
|
13
|
+
export declare function applyTruncation(fullOutput: string, cwd: string, toolName: string): Promise<TruncatedOutput>;
|
|
14
|
+
/**
|
|
15
|
+
* Create error output
|
|
16
|
+
*/
|
|
17
|
+
export declare function createErrorOutput(errorMessage: string, baseDetails: Record<string, unknown>): {
|
|
18
|
+
content: string;
|
|
19
|
+
details: Record<string, unknown>;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=truncation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncation.d.ts","sourceRoot":"","sources":["../../../src/tools/shared/truncation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAML,KAAK,gBAAgB,EACtB,MAAM,+BAA+B,CAAC;AAMvC,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC,CAuC1B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAUvD"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared truncation utilities
|
|
3
|
+
*/
|
|
4
|
+
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead, withFileMutationQueue, } from "@mariozechner/pi-coding-agent";
|
|
5
|
+
/**
|
|
6
|
+
* Apply truncation to output and save full content to temp file if needed
|
|
7
|
+
*/
|
|
8
|
+
export async function applyTruncation(fullOutput, cwd, toolName) {
|
|
9
|
+
const truncation = truncateHead(fullOutput, {
|
|
10
|
+
maxLines: DEFAULT_MAX_LINES,
|
|
11
|
+
maxBytes: DEFAULT_MAX_BYTES,
|
|
12
|
+
});
|
|
13
|
+
let content = truncation.content;
|
|
14
|
+
// Save full output to temp file if truncated
|
|
15
|
+
if (truncation.truncated) {
|
|
16
|
+
const tempDir = `${cwd}/.pi-tavily-temp`;
|
|
17
|
+
const timestamp = Date.now();
|
|
18
|
+
const tempFile = `${tempDir}/${toolName}-${timestamp}.txt`;
|
|
19
|
+
await withFileMutationQueue(tempFile, async () => {
|
|
20
|
+
const { writeFile, mkdir } = await import("node:fs/promises");
|
|
21
|
+
await mkdir(tempDir, { recursive: true });
|
|
22
|
+
await writeFile(tempFile, fullOutput, "utf8");
|
|
23
|
+
});
|
|
24
|
+
// Add truncation notice
|
|
25
|
+
const truncatedLines = truncation.totalLines - truncation.outputLines;
|
|
26
|
+
const truncatedBytes = truncation.totalBytes - truncation.outputBytes;
|
|
27
|
+
content += "\n\n";
|
|
28
|
+
content += "[Output truncated: ";
|
|
29
|
+
content += `showing ${truncation.outputLines} of ${truncation.totalLines} lines, `;
|
|
30
|
+
content += `(${formatSize(truncation.outputBytes)} of ${formatSize(truncation.totalBytes)}). `;
|
|
31
|
+
content += `${truncatedLines} lines (${formatSize(truncatedBytes)}) omitted. `;
|
|
32
|
+
content += `Full output saved to: ${tempFile}]`;
|
|
33
|
+
return {
|
|
34
|
+
content,
|
|
35
|
+
truncation,
|
|
36
|
+
fullOutputPath: tempFile,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return { content };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create error output
|
|
43
|
+
*/
|
|
44
|
+
export function createErrorOutput(errorMessage, baseDetails) {
|
|
45
|
+
return {
|
|
46
|
+
content: `Error: ${errorMessage}`,
|
|
47
|
+
details: {
|
|
48
|
+
...baseDetails,
|
|
49
|
+
resultCount: 0,
|
|
50
|
+
sources: [],
|
|
51
|
+
error: errorMessage,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=truncation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncation.js","sourceRoot":"","sources":["../../../src/tools/shared/truncation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,qBAAqB,GAEtB,MAAM,+BAA+B,CAAC;AAYvC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAAkB,EAClB,GAAW,EACX,QAAgB;IAEhB,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,EAAE;QAC1C,QAAQ,EAAE,iBAAiB;QAC3B,QAAQ,EAAE,iBAAiB;KAC5B,CAAC,CAAC;IAEH,IAAI,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;IAEjC,6CAA6C;IAC7C,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,GAAG,GAAG,kBAAkB,CAAC;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,GAAG,OAAO,IAAI,QAAQ,IAAI,SAAS,MAAM,CAAC;QAE3D,MAAM,qBAAqB,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;YAC9D,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1C,MAAM,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,wBAAwB;QACxB,MAAM,cAAc,GAAG,UAAU,CAAC,UAAU,GAAG,UAAU,CAAC,WAAW,CAAC;QACtE,MAAM,cAAc,GAAG,UAAU,CAAC,UAAU,GAAG,UAAU,CAAC,WAAW,CAAC;QAEtE,OAAO,IAAI,MAAM,CAAC;QAClB,OAAO,IAAI,qBAAqB,CAAC;QACjC,OAAO,IAAI,WAAW,UAAU,CAAC,WAAW,OAAO,UAAU,CAAC,UAAU,UAAU,CAAC;QACnF,OAAO,IAAI,IAAI,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,OAAO,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC;QAC/F,OAAO,IAAI,GAAG,cAAc,WAAW,UAAU,CAAC,cAAc,CAAC,aAAa,CAAC;QAC/E,OAAO,IAAI,yBAAyB,QAAQ,GAAG,CAAC;QAEhD,OAAO;YACL,OAAO;YACP,UAAU;YACV,cAAc,EAAE,QAAQ;SACzB,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,YAAoB,EACpB,WAAoC;IAEpC,OAAO;QACL,OAAO,EAAE,UAAU,YAAY,EAAE;QACjC,OAAO,EAAE;YACP,GAAG,WAAW;YACd,WAAW,EAAE,CAAC;YACd,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,YAAY;SACpB;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tavily Client Management
|
|
3
|
+
*
|
|
4
|
+
* Creates Tavily client instances with proper initialization.
|
|
5
|
+
*/
|
|
6
|
+
import { type TavilyClient, type TavilySearchOptions } from "@tavily/core";
|
|
7
|
+
/**
|
|
8
|
+
* Create a new Tavily client instance
|
|
9
|
+
* @throws {Error} If TAVILY_API_KEY is not set or client initialization fails
|
|
10
|
+
*/
|
|
11
|
+
export declare function createTavilyClient(apiKey?: string): TavilyClient;
|
|
12
|
+
/**
|
|
13
|
+
* Build Tavily search options from parameters
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildSearchOptions(params: Record<string, unknown>): TavilySearchOptions;
|
|
16
|
+
/**
|
|
17
|
+
* Create a search function pre-bound with a client
|
|
18
|
+
* @param client Tavily client instance
|
|
19
|
+
* @returns Search function
|
|
20
|
+
*/
|
|
21
|
+
export declare function createSearchFunction(client: TavilyClient): import("@tavily/core").TavilySearchFuncton;
|
|
22
|
+
/**
|
|
23
|
+
* Validate search query
|
|
24
|
+
* @throws {Error} If query is empty or whitespace only
|
|
25
|
+
*/
|
|
26
|
+
export declare function validateQuery(query: string): string;
|
|
27
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/tools/tavily/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAU,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAMnF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAiBhE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,mBAAmB,CAYvF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,8CAExD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMnD"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tavily Client Management
|
|
3
|
+
*
|
|
4
|
+
* Creates Tavily client instances with proper initialization.
|
|
5
|
+
*/
|
|
6
|
+
import { tavily } from "@tavily/core";
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Client Creation
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Create a new Tavily client instance
|
|
12
|
+
* @throws {Error} If TAVILY_API_KEY is not set or client initialization fails
|
|
13
|
+
*/
|
|
14
|
+
export function createTavilyClient(apiKey) {
|
|
15
|
+
const key = apiKey ?? process.env.TAVILY_API_KEY;
|
|
16
|
+
if (!key) {
|
|
17
|
+
throw new Error("TAVILY_API_KEY environment variable is not set. " +
|
|
18
|
+
'Please set it with: export TAVILY_API_KEY="your-api-key" ' +
|
|
19
|
+
"or get a free key from https://tavily.com");
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
return tavily({ apiKey: key });
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
throw new Error(`Failed to initialize Tavily client: ${error instanceof Error ? error.message : String(error)}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build Tavily search options from parameters
|
|
30
|
+
*/
|
|
31
|
+
export function buildSearchOptions(params) {
|
|
32
|
+
return {
|
|
33
|
+
maxResults: typeof params.max_results === "number" ? Math.max(1, Math.min(20, params.max_results)) : 5,
|
|
34
|
+
searchDepth: params.search_depth ?? "basic",
|
|
35
|
+
includeAnswer: params.include_answer !== false,
|
|
36
|
+
includeImages: params.include_images === true,
|
|
37
|
+
includeRawContent: params.include_raw_content === true ? "markdown" : false,
|
|
38
|
+
days: typeof params.days === "number" ? params.days : undefined,
|
|
39
|
+
includeDomains: undefined,
|
|
40
|
+
excludeDomains: undefined,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Create a search function pre-bound with a client
|
|
45
|
+
* @param client Tavily client instance
|
|
46
|
+
* @returns Search function
|
|
47
|
+
*/
|
|
48
|
+
export function createSearchFunction(client) {
|
|
49
|
+
return client.search.bind(client);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Validate search query
|
|
53
|
+
* @throws {Error} If query is empty or whitespace only
|
|
54
|
+
*/
|
|
55
|
+
export function validateQuery(query) {
|
|
56
|
+
const trimmed = query.trim();
|
|
57
|
+
if (!trimmed) {
|
|
58
|
+
throw new Error("Query cannot be empty");
|
|
59
|
+
}
|
|
60
|
+
return trimmed;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/tools/tavily/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAA+C,MAAM,cAAc,CAAC;AAEnF,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAe;IAChD,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IACjD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,kDAAkD;YAChD,2DAA2D;YAC3D,2CAA2C,CAC9C,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,uCAAuC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAChG,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAA+B;IAChE,OAAO;QACL,UAAU,EACR,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5F,WAAW,EAAG,MAAM,CAAC,YAAqC,IAAI,OAAO;QACrE,aAAa,EAAE,MAAM,CAAC,cAAc,KAAK,KAAK;QAC9C,aAAa,EAAE,MAAM,CAAC,cAAc,KAAK,IAAI;QAC7C,iBAAiB,EAAE,MAAM,CAAC,mBAAmB,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK;QAC3E,IAAI,EAAE,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QAC/D,cAAc,EAAE,SAAS;QACzB,cAAc,EAAE,SAAS;KAC1B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAoB;IACvD,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response formatters for Tavily tools
|
|
3
|
+
*/
|
|
4
|
+
import type { FormattedOutputParts, ImageResult, SearchResult } from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Format Tavily search response into human-readable text
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatWebSearchResponse(answer: string | null, results: SearchResult[], images: ImageResult[], includeImages: boolean | undefined): string;
|
|
9
|
+
/**
|
|
10
|
+
* Format Tavily search results into compact parts structure
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatSearchResults(answer: string | null, results: SearchResult[], images: ImageResult[], includeImages: boolean): FormattedOutputParts;
|
|
13
|
+
/**
|
|
14
|
+
* Extract and type-safe Tavily response data
|
|
15
|
+
*/
|
|
16
|
+
export declare function extractSearchResults(response: unknown): {
|
|
17
|
+
answer: string | null;
|
|
18
|
+
results: SearchResult[];
|
|
19
|
+
images: ImageResult[];
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=formatters.d.ts.map
|