bashkit 0.1.1 → 0.1.3
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/AGENTS.md +35 -1
- package/README.md +41 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +541 -97
- package/dist/tools/ask-user.d.ts +41 -11
- package/dist/tools/grep.d.ts +3 -2
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/task.d.ts +14 -6
- package/dist/types.d.ts +5 -1
- package/package.json +1 -1
- package/dist/tools/lsp.d.ts +0 -94
package/AGENTS.md
CHANGED
|
@@ -122,7 +122,7 @@ await sandbox.destroy();
|
|
|
122
122
|
|
|
123
123
|
## Sub-agents with Task Tool
|
|
124
124
|
|
|
125
|
-
The Task tool spawns new
|
|
125
|
+
The Task tool spawns new agents for complex subtasks:
|
|
126
126
|
|
|
127
127
|
```typescript
|
|
128
128
|
import { createTaskTool } from "bashkit";
|
|
@@ -157,6 +157,40 @@ The parent agent calls Task like any other tool:
|
|
|
157
157
|
}}
|
|
158
158
|
```
|
|
159
159
|
|
|
160
|
+
### Streaming Sub-agent Activity to UI
|
|
161
|
+
|
|
162
|
+
Pass a `streamWriter` to stream real-time sub-agent activity:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
import { createUIMessageStream } from "ai";
|
|
166
|
+
|
|
167
|
+
const stream = createUIMessageStream({
|
|
168
|
+
execute: async ({ writer }) => {
|
|
169
|
+
const taskTool = createTaskTool({
|
|
170
|
+
model,
|
|
171
|
+
tools: sandboxTools,
|
|
172
|
+
streamWriter: writer, // Enable real-time streaming
|
|
173
|
+
subagentTypes: { ... },
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const result = streamText({
|
|
177
|
+
model,
|
|
178
|
+
tools: { Task: taskTool },
|
|
179
|
+
...
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
writer.merge(result.toUIMessageStream());
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
When `streamWriter` is provided:
|
|
188
|
+
- Uses `streamText` internally (instead of `generateText`)
|
|
189
|
+
- Emits `data-subagent` events: `start`, `tool-call`, `done`, `complete`
|
|
190
|
+
- Events appear in `message.parts` as `{ type: "data-subagent", data: SubagentEventData }`
|
|
191
|
+
|
|
192
|
+
**Note:** TaskOutput does NOT include messages (to avoid context bloat). The UI accesses the full conversation via the streamed `complete` event.
|
|
193
|
+
|
|
160
194
|
## Prompt Caching
|
|
161
195
|
|
|
162
196
|
Enable Anthropic prompt caching to reduce costs on repeated prefixes:
|
package/README.md
CHANGED
|
@@ -219,7 +219,7 @@ const { tools, planModeState } = createAgentTools(sandbox, {
|
|
|
219
219
|
|
|
220
220
|
## Sub-agents with Task Tool
|
|
221
221
|
|
|
222
|
-
The Task tool spawns new
|
|
222
|
+
The Task tool spawns new agents for complex subtasks:
|
|
223
223
|
|
|
224
224
|
```typescript
|
|
225
225
|
import { createTaskTool } from 'bashkit';
|
|
@@ -254,6 +254,46 @@ The parent agent calls Task like any other tool:
|
|
|
254
254
|
}}
|
|
255
255
|
```
|
|
256
256
|
|
|
257
|
+
### Streaming Sub-agent Activity to UI
|
|
258
|
+
|
|
259
|
+
Pass a `streamWriter` to stream real-time sub-agent activity to the UI:
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
import { createUIMessageStream } from 'ai';
|
|
263
|
+
|
|
264
|
+
const stream = createUIMessageStream({
|
|
265
|
+
execute: async ({ writer }) => {
|
|
266
|
+
const taskTool = createTaskTool({
|
|
267
|
+
model,
|
|
268
|
+
tools: sandboxTools,
|
|
269
|
+
streamWriter: writer, // Enable real-time streaming
|
|
270
|
+
subagentTypes: { ... },
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// Use with streamText
|
|
274
|
+
const result = streamText({
|
|
275
|
+
model,
|
|
276
|
+
tools: { Task: taskTool },
|
|
277
|
+
...
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
writer.merge(result.toUIMessageStream());
|
|
281
|
+
},
|
|
282
|
+
});
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
When `streamWriter` is provided:
|
|
286
|
+
- Uses `streamText` internally (instead of `generateText`)
|
|
287
|
+
- Emits `data-subagent` events to the UI stream:
|
|
288
|
+
- `start` - Sub-agent begins work
|
|
289
|
+
- `tool-call` - Each tool the sub-agent uses (with args)
|
|
290
|
+
- `done` - Sub-agent finished
|
|
291
|
+
- `complete` - Full messages array for UI access
|
|
292
|
+
|
|
293
|
+
These appear in `message.parts` on the client as `{ type: "data-subagent", data: SubagentEventData }`.
|
|
294
|
+
|
|
295
|
+
**Important:** The TaskOutput returned to the lead agent does NOT include messages (to avoid context bloat). The UI accesses the full conversation via the streamed `complete` event.
|
|
296
|
+
|
|
257
297
|
## Context Management
|
|
258
298
|
|
|
259
299
|
### Conversation Compaction
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
export type { UIMessageStreamWriter } from "ai";
|
|
1
2
|
export { anthropicPromptCacheMiddleware } from "./middleware";
|
|
2
3
|
export type { E2BSandboxConfig, LocalSandboxConfig, VercelSandboxConfig, } from "./sandbox";
|
|
3
4
|
export { createE2BSandbox, createLocalSandbox, createVercelSandbox, } from "./sandbox";
|
|
4
5
|
export type { ExecOptions, ExecResult, Sandbox } from "./sandbox/interface";
|
|
5
|
-
export type { AgentToolsResult, AskUserError, AskUserOutput, AskUserResponseHandler, BashError, BashOutput, EditError, EditOutput, EnterPlanModeError, EnterPlanModeOutput, ExitPlanModeError, ExitPlanModeOutput, PlanModeState, GlobError, GlobOutput, GrepContentOutput, GrepCountOutput, GrepError, GrepFilesOutput, GrepMatch, GrepOutput, ReadDirectoryOutput, ReadError, ReadOutput, ReadTextOutput, SkillError, SkillOutput, SkillToolConfig, SubagentStepEvent, SubagentTypeConfig, TaskError, TaskOutput, TaskToolConfig, TodoItem, TodoState, TodoWriteError, TodoWriteOutput, WebFetchError, WebFetchOutput, WebFetchToolConfig, WebSearchError, WebSearchOutput, WebSearchResult, WebSearchToolConfig, WriteError, WriteOutput, } from "./tools";
|
|
6
|
+
export type { AgentToolsResult, AskUserError, AskUserOutput, AskUserResponseHandler, BashError, BashOutput, EditError, EditOutput, EnterPlanModeError, EnterPlanModeOutput, ExitPlanModeError, ExitPlanModeOutput, PlanModeState, GlobError, GlobOutput, GrepContentOutput, GrepCountOutput, GrepError, GrepFilesOutput, GrepMatch, GrepOutput, ReadDirectoryOutput, ReadError, ReadOutput, ReadTextOutput, SkillError, SkillOutput, SkillToolConfig, SubagentEventData, SubagentStepEvent, SubagentTypeConfig, TaskError, TaskOutput, TaskToolConfig, TodoItem, TodoState, TodoWriteError, TodoWriteOutput, WebFetchError, WebFetchOutput, WebFetchToolConfig, WebSearchError, WebSearchOutput, WebSearchResult, WebSearchToolConfig, WriteError, WriteOutput, } from "./tools";
|
|
6
7
|
export { createAgentTools, createAskUserTool, createBashTool, createEditTool, createEnterPlanModeTool, createExitPlanModeTool, createGlobTool, createGrepTool, createReadTool, createSkillTool, createTaskTool, createTodoWriteTool, createWebFetchTool, createWebSearchTool, createWriteTool, } from "./tools";
|
|
7
8
|
export type { AgentConfig, AskUserConfig, SkillConfig, ToolConfig, WebFetchConfig, WebSearchConfig, } from "./types";
|
|
8
9
|
export { DEFAULT_CONFIG } from "./types";
|
package/dist/index.js
CHANGED
|
@@ -361,10 +361,27 @@ var DEFAULT_CONFIG = {
|
|
|
361
361
|
// src/tools/ask-user.ts
|
|
362
362
|
import { tool, zodSchema } from "ai";
|
|
363
363
|
import { z } from "zod";
|
|
364
|
+
var questionOptionSchema = z.object({
|
|
365
|
+
label: z.string().describe("The display text for this option. Should be concise (1-5 words). Add '(Recommended)' suffix for suggested options."),
|
|
366
|
+
description: z.string().optional().describe("Explanation of what this option means or its implications.")
|
|
367
|
+
});
|
|
368
|
+
var structuredQuestionSchema = z.object({
|
|
369
|
+
header: z.string().optional().describe("Very short label displayed as a chip/tag (max 12 chars). Examples: 'Auth method', 'Library', 'Approach'."),
|
|
370
|
+
question: z.string().describe("The complete question to ask the user. Should be clear and specific."),
|
|
371
|
+
options: z.array(questionOptionSchema).min(2).max(4).optional().describe("Available choices for this question. 2-4 options. An 'Other' option is automatically available to users."),
|
|
372
|
+
multiSelect: z.boolean().optional().describe("Set to true to allow the user to select multiple options instead of just one.")
|
|
373
|
+
});
|
|
364
374
|
var askUserInputSchema = z.object({
|
|
365
|
-
question: z.string().describe("
|
|
375
|
+
question: z.string().optional().describe("Simple question string (for backward compatibility). Use 'questions' for structured multi-choice."),
|
|
376
|
+
questions: z.array(structuredQuestionSchema).min(1).max(4).optional().describe("Structured questions with options (1-4 questions).")
|
|
366
377
|
});
|
|
367
|
-
var ASK_USER_DESCRIPTION = `
|
|
378
|
+
var ASK_USER_DESCRIPTION = `Use this tool when you need to ask the user questions during execution.
|
|
379
|
+
|
|
380
|
+
**Capabilities:**
|
|
381
|
+
- Gather user preferences or requirements
|
|
382
|
+
- Clarify ambiguous instructions
|
|
383
|
+
- Get decisions on implementation choices
|
|
384
|
+
- Offer choices about what direction to take
|
|
368
385
|
|
|
369
386
|
**When to use:**
|
|
370
387
|
- You need clarification on ambiguous requirements
|
|
@@ -377,23 +394,54 @@ var ASK_USER_DESCRIPTION = `Ask the user a clarifying question when you need mor
|
|
|
377
394
|
- The question is trivial or can be inferred
|
|
378
395
|
- You're just being overly cautious
|
|
379
396
|
|
|
380
|
-
|
|
381
|
-
|
|
397
|
+
**Simple question format:**
|
|
398
|
+
Use the 'question' parameter for a single free-form question.
|
|
399
|
+
|
|
400
|
+
**Structured questions format:**
|
|
401
|
+
Use the 'questions' parameter for multiple-choice questions with options:
|
|
402
|
+
- 1-4 questions allowed
|
|
403
|
+
- Each question can have 2-4 options with labels and descriptions
|
|
404
|
+
- Use multiSelect: true to allow multiple answers
|
|
405
|
+
- Users can always select "Other" to provide custom text input
|
|
406
|
+
- Place recommended option first and add "(Recommended)" to label`;
|
|
407
|
+
function createAskUserTool(config) {
|
|
408
|
+
const normalizedConfig = typeof config === "function" ? { onQuestion: config } : config ?? {};
|
|
382
409
|
return tool({
|
|
383
410
|
description: ASK_USER_DESCRIPTION,
|
|
384
411
|
inputSchema: zodSchema(askUserInputSchema),
|
|
385
|
-
execute: async ({
|
|
386
|
-
question
|
|
387
|
-
}) => {
|
|
412
|
+
execute: async (input) => {
|
|
388
413
|
try {
|
|
389
|
-
if (
|
|
390
|
-
|
|
391
|
-
|
|
414
|
+
if (!input.question && !input.questions) {
|
|
415
|
+
return {
|
|
416
|
+
error: "Either 'question' or 'questions' must be provided"
|
|
417
|
+
};
|
|
392
418
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
419
|
+
if (input.questions && input.questions.length > 0) {
|
|
420
|
+
if (normalizedConfig.onStructuredQuestions) {
|
|
421
|
+
const answers = await normalizedConfig.onStructuredQuestions(input.questions);
|
|
422
|
+
const firstKey = Object.keys(answers)[0];
|
|
423
|
+
const firstAnswer = answers[firstKey];
|
|
424
|
+
return {
|
|
425
|
+
answer: Array.isArray(firstAnswer) ? firstAnswer.join(", ") : firstAnswer,
|
|
426
|
+
answers
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
return {
|
|
430
|
+
questions: input.questions,
|
|
431
|
+
awaiting_response: true
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
if (input.question) {
|
|
435
|
+
if (normalizedConfig.onQuestion) {
|
|
436
|
+
const answer = await normalizedConfig.onQuestion(input.question);
|
|
437
|
+
return { answer };
|
|
438
|
+
}
|
|
439
|
+
return {
|
|
440
|
+
question: input.question,
|
|
441
|
+
awaiting_response: true
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
return { error: "No question provided" };
|
|
397
445
|
} catch (error) {
|
|
398
446
|
return {
|
|
399
447
|
error: error instanceof Error ? error.message : "Unknown error"
|
|
@@ -412,15 +460,40 @@ var bashInputSchema = z2.object({
|
|
|
412
460
|
description: z2.string().optional().describe("Clear, concise description of what this command does in 5-10 words"),
|
|
413
461
|
run_in_background: z2.boolean().optional().describe("Set to true to run this command in the background")
|
|
414
462
|
});
|
|
415
|
-
var BASH_DESCRIPTION = `Executes bash
|
|
463
|
+
var BASH_DESCRIPTION = `Executes a bash command in a persistent shell session with optional timeout.
|
|
416
464
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
- If
|
|
423
|
-
-
|
|
465
|
+
IMPORTANT: For file operations (reading, writing, editing, searching, finding files) - use the specialized tools instead of bash commands.
|
|
466
|
+
|
|
467
|
+
Before executing the command, please follow these steps:
|
|
468
|
+
|
|
469
|
+
1. Directory Verification:
|
|
470
|
+
- If the command will create new directories or files, first use \`ls\` to verify the parent directory exists and is the correct location
|
|
471
|
+
- For example, before running "mkdir foo/bar", first use \`ls foo\` to check that "foo" exists
|
|
472
|
+
|
|
473
|
+
2. Command Execution:
|
|
474
|
+
- Always quote file paths that contain spaces with double quotes (e.g., cd "/path/with spaces")
|
|
475
|
+
- Examples of proper quoting:
|
|
476
|
+
- cd "/Users/name/My Documents" (correct)
|
|
477
|
+
- cd /Users/name/My Documents (incorrect - will fail)
|
|
478
|
+
- After ensuring proper quoting, execute the command
|
|
479
|
+
|
|
480
|
+
Usage notes:
|
|
481
|
+
- The command argument is required
|
|
482
|
+
- You can specify an optional timeout in milliseconds (max 600000ms / 10 minutes). Default is 120000ms (2 minutes).
|
|
483
|
+
- It is very helpful if you write a clear, concise description of what this command does in 5-10 words
|
|
484
|
+
- If the output exceeds 30000 characters, output will be truncated
|
|
485
|
+
- Avoid using \`find\`, \`grep\`, \`cat\`, \`head\`, \`tail\`, \`sed\`, \`awk\`, or \`echo\` commands. Instead, use dedicated tools:
|
|
486
|
+
- File search: Use Glob (NOT find or ls)
|
|
487
|
+
- Content search: Use Grep (NOT grep or rg)
|
|
488
|
+
- Read files: Use Read (NOT cat/head/tail)
|
|
489
|
+
- Edit files: Use Edit (NOT sed/awk)
|
|
490
|
+
- Write files: Use Write (NOT echo >/cat <<EOF)
|
|
491
|
+
- When issuing multiple commands:
|
|
492
|
+
- If commands are independent, make multiple Bash tool calls in parallel
|
|
493
|
+
- If commands depend on each other, use '&&' to chain them (e.g., \`git add . && git commit -m "message"\`)
|
|
494
|
+
- Use ';' only when you need sequential execution but don't care if earlier commands fail
|
|
495
|
+
- DO NOT use newlines to separate commands
|
|
496
|
+
- Try to maintain your current working directory by using absolute paths and avoiding \`cd\``;
|
|
424
497
|
function createBashTool(sandbox, config) {
|
|
425
498
|
const maxOutputLength = config?.maxOutputLength ?? 30000;
|
|
426
499
|
const defaultTimeout = config?.timeout ?? 120000;
|
|
@@ -482,9 +555,26 @@ var editInputSchema = z3.object({
|
|
|
482
555
|
new_string: z3.string().describe("The text to replace it with (must be different from old_string)"),
|
|
483
556
|
replace_all: z3.boolean().optional().describe("Replace all occurrences of old_string (default false)")
|
|
484
557
|
});
|
|
558
|
+
var EDIT_DESCRIPTION = `Performs exact string replacements in files.
|
|
559
|
+
|
|
560
|
+
**Important guidelines:**
|
|
561
|
+
- You MUST use the Read tool first before editing any file
|
|
562
|
+
- Preserve exact indentation (tabs/spaces) when replacing text
|
|
563
|
+
- The old_string must be unique in the file, or the edit will fail
|
|
564
|
+
- If old_string appears multiple times, either provide more context to make it unique, or use replace_all=true
|
|
565
|
+
|
|
566
|
+
**Parameters:**
|
|
567
|
+
- old_string: The exact text to find and replace (must match exactly, including whitespace)
|
|
568
|
+
- new_string: The replacement text (must be different from old_string)
|
|
569
|
+
- replace_all: Set to true to replace all occurrences (useful for renaming variables)
|
|
570
|
+
|
|
571
|
+
**When to use:**
|
|
572
|
+
- Making targeted changes to existing files
|
|
573
|
+
- Renaming variables or functions (with replace_all=true)
|
|
574
|
+
- Updating specific sections`;
|
|
485
575
|
function createEditTool(sandbox, config) {
|
|
486
576
|
return tool3({
|
|
487
|
-
description:
|
|
577
|
+
description: EDIT_DESCRIPTION,
|
|
488
578
|
inputSchema: zodSchema3(editInputSchema),
|
|
489
579
|
execute: async ({
|
|
490
580
|
file_path,
|
|
@@ -546,24 +636,61 @@ import { z as z4 } from "zod";
|
|
|
546
636
|
var enterPlanModeInputSchema = z4.object({
|
|
547
637
|
reason: z4.string().describe("Brief explanation of why you're entering planning mode (e.g., 'Need to explore codebase architecture before implementing feature')")
|
|
548
638
|
});
|
|
549
|
-
var ENTER_PLAN_MODE_DESCRIPTION = `
|
|
639
|
+
var ENTER_PLAN_MODE_DESCRIPTION = `Use this tool proactively when you're about to start a non-trivial task. Getting user sign-off on your approach prevents wasted effort and ensures alignment. This tool transitions you into plan mode where you can explore and design an approach for user approval.
|
|
550
640
|
|
|
551
|
-
|
|
552
|
-
- Complex tasks requiring research or exploration
|
|
553
|
-
- Need to understand codebase structure before implementing
|
|
554
|
-
- Multiple approaches possible and you need to evaluate trade-offs
|
|
555
|
-
- User explicitly asks you to plan before executing
|
|
641
|
+
## When to Use This Tool
|
|
556
642
|
|
|
557
|
-
**
|
|
558
|
-
- Focus on reading, searching, and understanding
|
|
559
|
-
- Avoid making file changes (use Read, Grep, Glob instead of Write, Edit)
|
|
560
|
-
- Document your findings and proposed approach
|
|
561
|
-
- Use ExitPlanMode when ready with a plan for user approval
|
|
643
|
+
**Prefer using EnterPlanMode** for tasks unless they're simple. Use it when ANY of these conditions apply:
|
|
562
644
|
|
|
563
|
-
**
|
|
564
|
-
-
|
|
565
|
-
-
|
|
566
|
-
|
|
645
|
+
1. **New Functionality**: Adding meaningful new capabilities
|
|
646
|
+
- Example: "Add a new report" - what format? What data?
|
|
647
|
+
- Example: "Add validation" - what rules? What error messages?
|
|
648
|
+
|
|
649
|
+
2. **Multiple Valid Approaches**: The task can be solved in several different ways
|
|
650
|
+
- Example: "Add caching" - could use Redis, in-memory, file-based, etc.
|
|
651
|
+
- Example: "Improve performance" - many optimization strategies possible
|
|
652
|
+
|
|
653
|
+
3. **Modifications**: Changes that affect existing behavior or structure
|
|
654
|
+
- Example: "Update the workflow" - what exactly should change?
|
|
655
|
+
- Example: "Refactor this component" - what's the target architecture?
|
|
656
|
+
|
|
657
|
+
4. **Architectural Decisions**: The task requires choosing between patterns or technologies
|
|
658
|
+
- Example: "Add real-time updates" - WebSockets vs SSE vs polling
|
|
659
|
+
- Example: "Implement state management" - different approaches possible
|
|
660
|
+
|
|
661
|
+
5. **Multi-File Changes**: The task will likely touch more than 2-3 files
|
|
662
|
+
|
|
663
|
+
6. **Unclear Requirements**: You need to explore before understanding the full scope
|
|
664
|
+
- Example: "Make this faster" - need to profile and identify bottlenecks
|
|
665
|
+
- Example: "Fix the bug" - need to investigate root cause
|
|
666
|
+
|
|
667
|
+
7. **User Preferences Matter**: The approach could reasonably go multiple ways
|
|
668
|
+
- If you would use AskUser to clarify the approach, use EnterPlanMode instead
|
|
669
|
+
- Plan mode lets you explore first, then present options with context
|
|
670
|
+
|
|
671
|
+
## When NOT to Use This Tool
|
|
672
|
+
|
|
673
|
+
Only skip EnterPlanMode for simple tasks:
|
|
674
|
+
- Single-line or few-line fixes (typos, obvious bugs, small tweaks)
|
|
675
|
+
- Adding a single function with clear requirements
|
|
676
|
+
- Tasks where the user has given very specific, detailed instructions
|
|
677
|
+
- Pure research/exploration tasks
|
|
678
|
+
|
|
679
|
+
## What Happens in Plan Mode
|
|
680
|
+
|
|
681
|
+
In plan mode, you'll:
|
|
682
|
+
1. Thoroughly explore using Glob, Grep, and Read tools
|
|
683
|
+
2. Understand existing patterns and architecture
|
|
684
|
+
3. Design an approach
|
|
685
|
+
4. Present your plan to the user for approval
|
|
686
|
+
5. Use AskUser if you need to clarify approaches
|
|
687
|
+
6. Exit plan mode with ExitPlanMode when ready to execute
|
|
688
|
+
|
|
689
|
+
## Important Notes
|
|
690
|
+
|
|
691
|
+
- This tool REQUIRES user approval - they must consent to entering plan mode
|
|
692
|
+
- If unsure whether to use it, err on the side of planning - it's better to get alignment upfront than to redo work
|
|
693
|
+
- Users appreciate being consulted before significant changes`;
|
|
567
694
|
function createEnterPlanModeTool(state, onEnter) {
|
|
568
695
|
return tool4({
|
|
569
696
|
description: ENTER_PLAN_MODE_DESCRIPTION,
|
|
@@ -602,9 +729,30 @@ import { z as z5 } from "zod";
|
|
|
602
729
|
var exitPlanModeInputSchema = z5.object({
|
|
603
730
|
plan: z5.string().describe("The plan to present to the user for approval")
|
|
604
731
|
});
|
|
732
|
+
var EXIT_PLAN_MODE_DESCRIPTION = `Use this tool when you are in plan mode and have finished planning and are ready for user approval.
|
|
733
|
+
|
|
734
|
+
## How This Tool Works
|
|
735
|
+
- Pass your completed plan as a parameter
|
|
736
|
+
- This tool signals that you're done planning and ready for the user to review
|
|
737
|
+
- The user will see your plan and can approve or request changes
|
|
738
|
+
|
|
739
|
+
## When to Use This Tool
|
|
740
|
+
IMPORTANT: Only use this tool when the task requires planning implementation steps. For research tasks where you're gathering information, searching files, or understanding the codebase - do NOT use this tool.
|
|
741
|
+
|
|
742
|
+
## Handling Ambiguity in Plans
|
|
743
|
+
Before using this tool, ensure your plan is clear and unambiguous. If there are multiple valid approaches or unclear requirements:
|
|
744
|
+
1. Ask the user to clarify (use AskUser tool if available)
|
|
745
|
+
2. Ask about specific implementation choices (e.g., architectural patterns, which library to use)
|
|
746
|
+
3. Clarify any assumptions that could affect the implementation
|
|
747
|
+
4. Only proceed with ExitPlanMode after resolving ambiguities
|
|
748
|
+
|
|
749
|
+
## Examples
|
|
750
|
+
1. "Search for and understand the implementation of X" - Do NOT use this tool (research task)
|
|
751
|
+
2. "Help me implement feature Y" - Use this tool after planning the implementation steps
|
|
752
|
+
3. "Add user authentication" - If unsure about approach (OAuth vs JWT), clarify first, then use this tool`;
|
|
605
753
|
function createExitPlanModeTool(config, onPlanSubmit) {
|
|
606
754
|
return tool5({
|
|
607
|
-
description:
|
|
755
|
+
description: EXIT_PLAN_MODE_DESCRIPTION,
|
|
608
756
|
inputSchema: zodSchema5(exitPlanModeInputSchema),
|
|
609
757
|
execute: async ({
|
|
610
758
|
plan
|
|
@@ -634,9 +782,17 @@ var globInputSchema = z6.object({
|
|
|
634
782
|
pattern: z6.string().describe('Glob pattern to match files (e.g., "**/*.ts", "src/**/*.js", "*.md")'),
|
|
635
783
|
path: z6.string().optional().describe("Directory to search in (defaults to working directory)")
|
|
636
784
|
});
|
|
785
|
+
var GLOB_DESCRIPTION = `
|
|
786
|
+
- Fast file pattern matching tool that works with any codebase size
|
|
787
|
+
- Supports glob patterns like "**/*.js" or "src/**/*.ts"
|
|
788
|
+
- Returns matching file paths sorted by modification time
|
|
789
|
+
- Use this tool when you need to find files by name patterns
|
|
790
|
+
- When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Task tool instead
|
|
791
|
+
- It is always better to speculatively perform multiple searches in parallel if they are potentially useful
|
|
792
|
+
`;
|
|
637
793
|
function createGlobTool(sandbox, config) {
|
|
638
794
|
return tool6({
|
|
639
|
-
description:
|
|
795
|
+
description: GLOB_DESCRIPTION,
|
|
640
796
|
inputSchema: zodSchema6(globInputSchema),
|
|
641
797
|
execute: async ({
|
|
642
798
|
pattern,
|
|
@@ -674,22 +830,46 @@ function createGlobTool(sandbox, config) {
|
|
|
674
830
|
import { tool as tool7, zodSchema as zodSchema7 } from "ai";
|
|
675
831
|
import { z as z7 } from "zod";
|
|
676
832
|
var grepInputSchema = z7.object({
|
|
677
|
-
pattern: z7.string().describe("The regular expression pattern to search for"),
|
|
833
|
+
pattern: z7.string().describe("The regular expression pattern to search for in file contents"),
|
|
678
834
|
path: z7.string().optional().describe("File or directory to search in (defaults to cwd)"),
|
|
679
|
-
glob: z7.string().optional().describe('Glob pattern to filter files (e.g. "*.js")'),
|
|
835
|
+
glob: z7.string().optional().describe('Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}")'),
|
|
680
836
|
type: z7.string().optional().describe('File type to search (e.g. "js", "py", "rust")'),
|
|
681
|
-
output_mode: z7.enum(["content", "files_with_matches", "count"]).optional().describe('Output mode: "content", "files_with_matches",
|
|
837
|
+
output_mode: z7.enum(["content", "files_with_matches", "count"]).optional().describe('Output mode: "content" shows matching lines, "files_with_matches" shows file paths (default), "count" shows match counts'),
|
|
682
838
|
"-i": z7.boolean().optional().describe("Case insensitive search"),
|
|
683
|
-
"-n": z7.boolean().optional().describe("Show line numbers
|
|
684
|
-
"-B": z7.number().optional().describe("
|
|
685
|
-
"-A": z7.number().optional().describe("
|
|
686
|
-
"-C": z7.number().optional().describe("
|
|
687
|
-
head_limit: z7.number().optional().describe("Limit output to first N lines/entries"),
|
|
688
|
-
|
|
839
|
+
"-n": z7.boolean().optional().describe("Show line numbers in output. Requires output_mode: 'content'. Defaults to true."),
|
|
840
|
+
"-B": z7.number().optional().describe("Number of lines to show before each match. Requires output_mode: 'content'."),
|
|
841
|
+
"-A": z7.number().optional().describe("Number of lines to show after each match. Requires output_mode: 'content'."),
|
|
842
|
+
"-C": z7.number().optional().describe("Number of lines to show before and after each match. Requires output_mode: 'content'."),
|
|
843
|
+
head_limit: z7.number().optional().describe("Limit output to first N lines/entries. Works across all output modes. Defaults to 0 (unlimited)."),
|
|
844
|
+
offset: z7.number().optional().describe("Skip first N lines/entries before applying head_limit. Works across all output modes. Defaults to 0."),
|
|
845
|
+
multiline: z7.boolean().optional().describe("Enable multiline mode where patterns can span lines (requires ripgrep). Default: false.")
|
|
689
846
|
});
|
|
847
|
+
var GREP_DESCRIPTION = `A powerful content search tool with regex support. Use this instead of running grep commands directly.
|
|
848
|
+
|
|
849
|
+
**Usage:**
|
|
850
|
+
- ALWAYS use Grep for search tasks. NEVER invoke \`grep\` or \`rg\` as a Bash command.
|
|
851
|
+
- Supports regex syntax (e.g., "log.*Error", "function\\s+\\w+")
|
|
852
|
+
- Filter files with glob parameter (e.g., "*.js", "**/*.tsx") or type parameter (e.g., "js", "py", "rust")
|
|
853
|
+
|
|
854
|
+
**Output modes:**
|
|
855
|
+
- "content": Shows matching lines with optional context
|
|
856
|
+
- "files_with_matches": Shows only file paths (default)
|
|
857
|
+
- "count": Shows match counts per file
|
|
858
|
+
|
|
859
|
+
**Context options (content mode only):**
|
|
860
|
+
- -B: Lines to show before each match
|
|
861
|
+
- -A: Lines to show after each match
|
|
862
|
+
- -C: Lines to show before and after each match
|
|
863
|
+
|
|
864
|
+
**Pagination:**
|
|
865
|
+
- Use offset to skip results (useful for pagination)
|
|
866
|
+
- Use head_limit to limit total results returned
|
|
867
|
+
|
|
868
|
+
**Note:** Set useRipgrep: true in config for better performance and multiline support (requires ripgrep installed).`;
|
|
690
869
|
function createGrepTool(sandbox, config) {
|
|
870
|
+
const useRipgrep = config?.useRipgrep ?? false;
|
|
691
871
|
return tool7({
|
|
692
|
-
description:
|
|
872
|
+
description: GREP_DESCRIPTION,
|
|
693
873
|
inputSchema: zodSchema7(grepInputSchema),
|
|
694
874
|
execute: async (input) => {
|
|
695
875
|
const {
|
|
@@ -697,13 +877,14 @@ function createGrepTool(sandbox, config) {
|
|
|
697
877
|
path,
|
|
698
878
|
glob,
|
|
699
879
|
type,
|
|
700
|
-
output_mode = "
|
|
880
|
+
output_mode = "files_with_matches",
|
|
701
881
|
"-i": caseInsensitive,
|
|
702
882
|
"-n": showLineNumbers = true,
|
|
703
883
|
"-B": beforeContext,
|
|
704
884
|
"-A": afterContext,
|
|
705
885
|
"-C": context,
|
|
706
886
|
head_limit,
|
|
887
|
+
offset = 0,
|
|
707
888
|
multiline
|
|
708
889
|
} = input;
|
|
709
890
|
const searchPath = path || ".";
|
|
@@ -713,32 +894,52 @@ function createGrepTool(sandbox, config) {
|
|
|
713
894
|
return { error: `Path not allowed: ${searchPath}` };
|
|
714
895
|
}
|
|
715
896
|
}
|
|
897
|
+
if (multiline && !useRipgrep) {
|
|
898
|
+
return {
|
|
899
|
+
error: "Multiline mode requires ripgrep. Set useRipgrep: true in config."
|
|
900
|
+
};
|
|
901
|
+
}
|
|
716
902
|
try {
|
|
717
|
-
|
|
718
|
-
if (
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
flags.push("-U");
|
|
724
|
-
if (context) {
|
|
725
|
-
flags.push(`-C ${context}`);
|
|
726
|
-
} else {
|
|
727
|
-
if (beforeContext)
|
|
728
|
-
flags.push(`-B ${beforeContext}`);
|
|
729
|
-
if (afterContext)
|
|
730
|
-
flags.push(`-A ${afterContext}`);
|
|
903
|
+
let paginationSuffix = "";
|
|
904
|
+
if (offset > 0) {
|
|
905
|
+
paginationSuffix += ` | tail -n +${offset + 1}`;
|
|
906
|
+
}
|
|
907
|
+
if (head_limit && head_limit > 0) {
|
|
908
|
+
paginationSuffix += ` | head -${head_limit}`;
|
|
731
909
|
}
|
|
732
|
-
if (glob)
|
|
733
|
-
flags.push(`--include="${glob}"`);
|
|
734
|
-
if (type)
|
|
735
|
-
flags.push(`--include="*.${type}"`);
|
|
736
|
-
const flagStr = flags.join(" ");
|
|
737
|
-
const limit = head_limit || 1000;
|
|
738
910
|
let cmd;
|
|
911
|
+
if (useRipgrep) {
|
|
912
|
+
cmd = buildRipgrepCommand({
|
|
913
|
+
pattern,
|
|
914
|
+
searchPath,
|
|
915
|
+
output_mode,
|
|
916
|
+
caseInsensitive,
|
|
917
|
+
showLineNumbers,
|
|
918
|
+
beforeContext,
|
|
919
|
+
afterContext,
|
|
920
|
+
context,
|
|
921
|
+
glob,
|
|
922
|
+
type,
|
|
923
|
+
multiline,
|
|
924
|
+
paginationSuffix
|
|
925
|
+
});
|
|
926
|
+
} else {
|
|
927
|
+
cmd = buildGrepCommand({
|
|
928
|
+
pattern,
|
|
929
|
+
searchPath,
|
|
930
|
+
output_mode,
|
|
931
|
+
caseInsensitive,
|
|
932
|
+
showLineNumbers,
|
|
933
|
+
beforeContext,
|
|
934
|
+
afterContext,
|
|
935
|
+
context,
|
|
936
|
+
glob,
|
|
937
|
+
type,
|
|
938
|
+
paginationSuffix
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
const result = await sandbox.exec(cmd, { timeout: config?.timeout });
|
|
739
942
|
if (output_mode === "files_with_matches") {
|
|
740
|
-
cmd = `grep -rl ${flagStr} "${pattern}" ${searchPath} 2>/dev/null | head -${limit}`;
|
|
741
|
-
const result = await sandbox.exec(cmd, { timeout: config?.timeout });
|
|
742
943
|
const files = result.stdout.split(`
|
|
743
944
|
`).filter(Boolean);
|
|
744
945
|
return {
|
|
@@ -746,8 +947,6 @@ function createGrepTool(sandbox, config) {
|
|
|
746
947
|
count: files.length
|
|
747
948
|
};
|
|
748
949
|
} else if (output_mode === "count") {
|
|
749
|
-
cmd = `grep -rc ${flagStr} "${pattern}" ${searchPath} 2>/dev/null | grep -v ':0$' | head -${limit}`;
|
|
750
|
-
const result = await sandbox.exec(cmd, { timeout: config?.timeout });
|
|
751
950
|
const lines = result.stdout.split(`
|
|
752
951
|
`).filter(Boolean);
|
|
753
952
|
const counts = lines.map((line) => {
|
|
@@ -763,8 +962,6 @@ function createGrepTool(sandbox, config) {
|
|
|
763
962
|
total
|
|
764
963
|
};
|
|
765
964
|
} else {
|
|
766
|
-
cmd = `grep -rn ${flagStr} "${pattern}" ${searchPath} 2>/dev/null | head -${limit}`;
|
|
767
|
-
const result = await sandbox.exec(cmd, { timeout: config?.timeout });
|
|
768
965
|
if (!result.stdout.trim()) {
|
|
769
966
|
return {
|
|
770
967
|
matches: [],
|
|
@@ -798,6 +995,66 @@ function createGrepTool(sandbox, config) {
|
|
|
798
995
|
}
|
|
799
996
|
});
|
|
800
997
|
}
|
|
998
|
+
function buildRipgrepCommand(opts) {
|
|
999
|
+
const flags = [];
|
|
1000
|
+
if (opts.caseInsensitive)
|
|
1001
|
+
flags.push("-i");
|
|
1002
|
+
if (opts.multiline)
|
|
1003
|
+
flags.push("-U", "--multiline-dotall");
|
|
1004
|
+
if (opts.output_mode === "content") {
|
|
1005
|
+
if (opts.showLineNumbers)
|
|
1006
|
+
flags.push("-n");
|
|
1007
|
+
if (opts.context) {
|
|
1008
|
+
flags.push(`-C ${opts.context}`);
|
|
1009
|
+
} else {
|
|
1010
|
+
if (opts.beforeContext)
|
|
1011
|
+
flags.push(`-B ${opts.beforeContext}`);
|
|
1012
|
+
if (opts.afterContext)
|
|
1013
|
+
flags.push(`-A ${opts.afterContext}`);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
if (opts.glob)
|
|
1017
|
+
flags.push(`-g "${opts.glob}"`);
|
|
1018
|
+
if (opts.type)
|
|
1019
|
+
flags.push(`-t ${opts.type}`);
|
|
1020
|
+
const flagStr = flags.join(" ");
|
|
1021
|
+
if (opts.output_mode === "files_with_matches") {
|
|
1022
|
+
return `rg -l ${flagStr} "${opts.pattern}" ${opts.searchPath} 2>/dev/null${opts.paginationSuffix}`;
|
|
1023
|
+
} else if (opts.output_mode === "count") {
|
|
1024
|
+
return `rg -c ${flagStr} "${opts.pattern}" ${opts.searchPath} 2>/dev/null${opts.paginationSuffix}`;
|
|
1025
|
+
} else {
|
|
1026
|
+
return `rg ${flagStr} "${opts.pattern}" ${opts.searchPath} 2>/dev/null${opts.paginationSuffix}`;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
function buildGrepCommand(opts) {
|
|
1030
|
+
const flags = ["-r"];
|
|
1031
|
+
if (opts.caseInsensitive)
|
|
1032
|
+
flags.push("-i");
|
|
1033
|
+
if (opts.output_mode === "content") {
|
|
1034
|
+
if (opts.showLineNumbers)
|
|
1035
|
+
flags.push("-n");
|
|
1036
|
+
if (opts.context) {
|
|
1037
|
+
flags.push(`-C ${opts.context}`);
|
|
1038
|
+
} else {
|
|
1039
|
+
if (opts.beforeContext)
|
|
1040
|
+
flags.push(`-B ${opts.beforeContext}`);
|
|
1041
|
+
if (opts.afterContext)
|
|
1042
|
+
flags.push(`-A ${opts.afterContext}`);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
if (opts.glob)
|
|
1046
|
+
flags.push(`--include="${opts.glob}"`);
|
|
1047
|
+
if (opts.type)
|
|
1048
|
+
flags.push(`--include="*.${opts.type}"`);
|
|
1049
|
+
const flagStr = flags.join(" ");
|
|
1050
|
+
if (opts.output_mode === "files_with_matches") {
|
|
1051
|
+
return `grep -l ${flagStr} "${opts.pattern}" ${opts.searchPath} 2>/dev/null${opts.paginationSuffix}`;
|
|
1052
|
+
} else if (opts.output_mode === "count") {
|
|
1053
|
+
return `grep -c ${flagStr} "${opts.pattern}" ${opts.searchPath} 2>/dev/null | grep -v ':0$'${opts.paginationSuffix}`;
|
|
1054
|
+
} else {
|
|
1055
|
+
return `grep ${flagStr} "${opts.pattern}" ${opts.searchPath} 2>/dev/null${opts.paginationSuffix}`;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
801
1058
|
|
|
802
1059
|
// src/tools/read.ts
|
|
803
1060
|
import { tool as tool8, zodSchema as zodSchema8 } from "ai";
|
|
@@ -807,9 +1064,21 @@ var readInputSchema = z8.object({
|
|
|
807
1064
|
offset: z8.number().optional().describe("Line number to start reading from (1-indexed)"),
|
|
808
1065
|
limit: z8.number().optional().describe("Maximum number of lines to read")
|
|
809
1066
|
});
|
|
1067
|
+
var READ_DESCRIPTION = `Reads a file from the local filesystem. You can access any file directly by using this tool.
|
|
1068
|
+
Assume this tool is able to read all files on the machine. If the User provides a path to a file assume that path is valid. It is okay to read a file that does not exist; an error will be returned.
|
|
1069
|
+
|
|
1070
|
+
Usage:
|
|
1071
|
+
- The file_path parameter must be an absolute path, not a relative path
|
|
1072
|
+
- By default, it reads up to 500 lines starting from the beginning of the file
|
|
1073
|
+
- You can optionally specify a line offset and limit (especially handy for long files)
|
|
1074
|
+
- Results are returned with line numbers starting at 1
|
|
1075
|
+
- This tool can only read text files, not binary files (images, PDFs, etc.)
|
|
1076
|
+
- This tool can only read files, not directories. To read a directory, use an ls command via the Bash tool.
|
|
1077
|
+
- It is always better to speculatively read multiple potentially useful files in parallel
|
|
1078
|
+
- If you read a file that exists but has empty contents you will receive a warning in place of file contents`;
|
|
810
1079
|
function createReadTool(sandbox, config) {
|
|
811
1080
|
return tool8({
|
|
812
|
-
description:
|
|
1081
|
+
description: READ_DESCRIPTION,
|
|
813
1082
|
inputSchema: zodSchema8(readInputSchema),
|
|
814
1083
|
execute: async ({
|
|
815
1084
|
file_path,
|
|
@@ -972,10 +1241,26 @@ var webFetchInputSchema = z10.object({
|
|
|
972
1241
|
prompt: z10.string().describe("The prompt to run on the fetched content")
|
|
973
1242
|
});
|
|
974
1243
|
var RETRYABLE_CODES = [408, 429, 500, 502, 503];
|
|
1244
|
+
var WEB_FETCH_DESCRIPTION = `
|
|
1245
|
+
- Fetches content from a specified URL and processes it using an AI model
|
|
1246
|
+
- Takes a URL and a prompt as input
|
|
1247
|
+
- Fetches the URL content and extracts text
|
|
1248
|
+
- Processes the content with the prompt using the configured model
|
|
1249
|
+
- Returns the model's response about the content
|
|
1250
|
+
- Use this tool when you need to retrieve and analyze web content
|
|
1251
|
+
|
|
1252
|
+
Usage notes:
|
|
1253
|
+
- The URL must be a fully-formed valid URL
|
|
1254
|
+
- HTTP URLs will be automatically upgraded to HTTPS
|
|
1255
|
+
- The prompt should describe what information you want to extract from the page
|
|
1256
|
+
- This tool is read-only and does not modify any files
|
|
1257
|
+
- Results may be summarized if the content is very large
|
|
1258
|
+
- When a URL redirects to a different host, the tool will inform you and provide the redirect URL. You should then make a new WebFetch request with the redirect URL to fetch the content.
|
|
1259
|
+
`;
|
|
975
1260
|
function createWebFetchTool(config) {
|
|
976
1261
|
const { apiKey, model } = config;
|
|
977
1262
|
return tool10({
|
|
978
|
-
description:
|
|
1263
|
+
description: WEB_FETCH_DESCRIPTION,
|
|
979
1264
|
inputSchema: zodSchema10(webFetchInputSchema),
|
|
980
1265
|
execute: async (input) => {
|
|
981
1266
|
const { url, prompt } = input;
|
|
@@ -1045,10 +1330,30 @@ var webSearchInputSchema = z11.object({
|
|
|
1045
1330
|
blocked_domains: z11.array(z11.string()).optional().describe("Never include results from these domains")
|
|
1046
1331
|
});
|
|
1047
1332
|
var RETRYABLE_CODES2 = [408, 429, 500, 502, 503];
|
|
1333
|
+
var WEB_SEARCH_DESCRIPTION = `Searches the web and returns results with links. Use this for accessing up-to-date information beyond your knowledge cutoff.
|
|
1334
|
+
|
|
1335
|
+
**Capabilities:**
|
|
1336
|
+
- Provides current information for recent events and data
|
|
1337
|
+
- Returns results formatted with titles, URLs, and snippets
|
|
1338
|
+
- Supports domain filtering to include or block specific websites
|
|
1339
|
+
|
|
1340
|
+
**CRITICAL REQUIREMENT - You MUST follow this:**
|
|
1341
|
+
After answering using search results, you MUST include a "Sources:" section listing relevant URLs as markdown hyperlinks:
|
|
1342
|
+
|
|
1343
|
+
Sources:
|
|
1344
|
+
- [Source Title 1](https://example.com/1)
|
|
1345
|
+
- [Source Title 2](https://example.com/2)
|
|
1346
|
+
|
|
1347
|
+
**Important - Use the correct year:**
|
|
1348
|
+
When searching for recent information, documentation, or current events, use the current year in your query (e.g., "React documentation 2025" not "2024").
|
|
1349
|
+
|
|
1350
|
+
**Domain filtering:**
|
|
1351
|
+
- allowed_domains: Only include results from these domains
|
|
1352
|
+
- blocked_domains: Never include results from these domains`;
|
|
1048
1353
|
function createWebSearchTool(config) {
|
|
1049
1354
|
const { apiKey } = config;
|
|
1050
1355
|
return tool11({
|
|
1051
|
-
description:
|
|
1356
|
+
description: WEB_SEARCH_DESCRIPTION,
|
|
1052
1357
|
inputSchema: zodSchema11(webSearchInputSchema),
|
|
1053
1358
|
execute: async (input) => {
|
|
1054
1359
|
const { query, allowed_domains, blocked_domains } = input;
|
|
@@ -1101,9 +1406,21 @@ var writeInputSchema = z12.object({
|
|
|
1101
1406
|
file_path: z12.string().describe("Path to the file to write"),
|
|
1102
1407
|
content: z12.string().describe("Content to write to the file")
|
|
1103
1408
|
});
|
|
1409
|
+
var WRITE_DESCRIPTION = `Writes content to a file on the filesystem.
|
|
1410
|
+
|
|
1411
|
+
**Important guidelines:**
|
|
1412
|
+
- This tool will overwrite existing files at the provided path
|
|
1413
|
+
- If modifying an existing file, you MUST use the Read tool first to read the file's contents
|
|
1414
|
+
- ALWAYS prefer editing existing files over creating new ones
|
|
1415
|
+
- NEVER proactively create documentation files (*.md) or README files unless explicitly requested
|
|
1416
|
+
- The file_path must be an absolute path, not relative
|
|
1417
|
+
|
|
1418
|
+
**When to use Write vs Edit:**
|
|
1419
|
+
- Use Write for creating new files or completely replacing file contents
|
|
1420
|
+
- Use Edit for making targeted changes to existing files (preferred for modifications)`;
|
|
1104
1421
|
function createWriteTool(sandbox, config) {
|
|
1105
1422
|
return tool12({
|
|
1106
|
-
description:
|
|
1423
|
+
description: WRITE_DESCRIPTION,
|
|
1107
1424
|
inputSchema: zodSchema12(writeInputSchema),
|
|
1108
1425
|
execute: async ({
|
|
1109
1426
|
file_path,
|
|
@@ -1139,6 +1456,7 @@ function createWriteTool(sandbox, config) {
|
|
|
1139
1456
|
// src/tools/task.ts
|
|
1140
1457
|
import {
|
|
1141
1458
|
generateText as generateText2,
|
|
1459
|
+
streamText,
|
|
1142
1460
|
stepCountIs,
|
|
1143
1461
|
tool as tool13,
|
|
1144
1462
|
zodSchema as zodSchema13
|
|
@@ -1149,6 +1467,30 @@ var taskInputSchema = z13.object({
|
|
|
1149
1467
|
prompt: z13.string().describe("The task for the agent to perform"),
|
|
1150
1468
|
subagent_type: z13.string().describe("The type of specialized agent to use for this task")
|
|
1151
1469
|
});
|
|
1470
|
+
var TASK_DESCRIPTION = `Launch a new agent to handle complex, multi-step tasks autonomously.
|
|
1471
|
+
|
|
1472
|
+
The Task tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it.
|
|
1473
|
+
|
|
1474
|
+
When using the Task tool, you must specify a subagent_type parameter to select which agent type to use.
|
|
1475
|
+
|
|
1476
|
+
**When NOT to use the Task tool:**
|
|
1477
|
+
- If you want to read a specific file path, use the Read or Glob tool instead, to find the match more quickly
|
|
1478
|
+
- If you are searching for a specific class definition like "class Foo", use the Glob tool instead, to find the match more quickly
|
|
1479
|
+
- If you are searching for code within a specific file or set of 2-3 files, use the Read tool instead, to find the match more quickly
|
|
1480
|
+
- Other tasks that are not related to the available agent types
|
|
1481
|
+
|
|
1482
|
+
**Usage notes:**
|
|
1483
|
+
- Always include a short description (3-5 words) summarizing what the agent will do
|
|
1484
|
+
- Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses
|
|
1485
|
+
- When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.
|
|
1486
|
+
- Provide clear, detailed prompts so the agent can work autonomously and return exactly the information you need.
|
|
1487
|
+
- The agent's outputs should generally be trusted
|
|
1488
|
+
- Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user's intent
|
|
1489
|
+
- If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement.`;
|
|
1490
|
+
var eventCounter = 0;
|
|
1491
|
+
function generateEventId() {
|
|
1492
|
+
return `subagent-${Date.now()}-${++eventCounter}`;
|
|
1493
|
+
}
|
|
1152
1494
|
function filterTools(allTools, allowedTools) {
|
|
1153
1495
|
if (!allowedTools)
|
|
1154
1496
|
return allTools;
|
|
@@ -1165,13 +1507,12 @@ function createTaskTool(config) {
|
|
|
1165
1507
|
model: defaultModel,
|
|
1166
1508
|
tools: allTools,
|
|
1167
1509
|
subagentTypes = {},
|
|
1168
|
-
costPerInputToken = 0.000003,
|
|
1169
|
-
costPerOutputToken = 0.000015,
|
|
1170
1510
|
defaultStopWhen,
|
|
1171
|
-
defaultOnStepFinish
|
|
1511
|
+
defaultOnStepFinish,
|
|
1512
|
+
streamWriter
|
|
1172
1513
|
} = config;
|
|
1173
1514
|
return tool13({
|
|
1174
|
-
description:
|
|
1515
|
+
description: TASK_DESCRIPTION,
|
|
1175
1516
|
inputSchema: zodSchema13(taskInputSchema),
|
|
1176
1517
|
execute: async ({
|
|
1177
1518
|
description,
|
|
@@ -1184,13 +1525,88 @@ function createTaskTool(config) {
|
|
|
1184
1525
|
const model = typeConfig.model || defaultModel;
|
|
1185
1526
|
const tools = filterTools(allTools, typeConfig.tools);
|
|
1186
1527
|
const systemPrompt = typeConfig.systemPrompt;
|
|
1187
|
-
const
|
|
1528
|
+
const commonOptions = {
|
|
1188
1529
|
model,
|
|
1189
1530
|
tools,
|
|
1190
1531
|
system: systemPrompt,
|
|
1191
1532
|
prompt,
|
|
1192
1533
|
stopWhen: typeConfig.stopWhen ?? defaultStopWhen ?? stepCountIs(15),
|
|
1193
|
-
prepareStep: typeConfig.prepareStep
|
|
1534
|
+
prepareStep: typeConfig.prepareStep
|
|
1535
|
+
};
|
|
1536
|
+
if (streamWriter) {
|
|
1537
|
+
const startId = generateEventId();
|
|
1538
|
+
streamWriter.write({
|
|
1539
|
+
type: "data-subagent",
|
|
1540
|
+
id: startId,
|
|
1541
|
+
data: {
|
|
1542
|
+
event: "start",
|
|
1543
|
+
subagent: subagent_type,
|
|
1544
|
+
description
|
|
1545
|
+
}
|
|
1546
|
+
});
|
|
1547
|
+
const result2 = streamText({
|
|
1548
|
+
...commonOptions,
|
|
1549
|
+
onStepFinish: async (step) => {
|
|
1550
|
+
if (step.toolCalls?.length) {
|
|
1551
|
+
for (const tc of step.toolCalls) {
|
|
1552
|
+
const eventId = generateEventId();
|
|
1553
|
+
streamWriter.write({
|
|
1554
|
+
type: "data-subagent",
|
|
1555
|
+
id: eventId,
|
|
1556
|
+
data: {
|
|
1557
|
+
event: "tool-call",
|
|
1558
|
+
subagent: subagent_type,
|
|
1559
|
+
description,
|
|
1560
|
+
toolName: tc.toolName,
|
|
1561
|
+
args: tc.input
|
|
1562
|
+
}
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
await typeConfig.onStepFinish?.(step);
|
|
1567
|
+
await defaultOnStepFinish?.({
|
|
1568
|
+
subagentType: subagent_type,
|
|
1569
|
+
description,
|
|
1570
|
+
step
|
|
1571
|
+
});
|
|
1572
|
+
}
|
|
1573
|
+
});
|
|
1574
|
+
const text = await result2.text;
|
|
1575
|
+
const usage2 = await result2.usage;
|
|
1576
|
+
const response = await result2.response;
|
|
1577
|
+
streamWriter.write({
|
|
1578
|
+
type: "data-subagent",
|
|
1579
|
+
id: generateEventId(),
|
|
1580
|
+
data: {
|
|
1581
|
+
event: "done",
|
|
1582
|
+
subagent: subagent_type,
|
|
1583
|
+
description
|
|
1584
|
+
}
|
|
1585
|
+
});
|
|
1586
|
+
streamWriter.write({
|
|
1587
|
+
type: "data-subagent",
|
|
1588
|
+
id: generateEventId(),
|
|
1589
|
+
data: {
|
|
1590
|
+
event: "complete",
|
|
1591
|
+
subagent: subagent_type,
|
|
1592
|
+
description,
|
|
1593
|
+
messages: response.messages
|
|
1594
|
+
}
|
|
1595
|
+
});
|
|
1596
|
+
const durationMs2 = Math.round(performance.now() - startTime);
|
|
1597
|
+
return {
|
|
1598
|
+
result: text,
|
|
1599
|
+
usage: usage2.inputTokens !== undefined && usage2.outputTokens !== undefined ? {
|
|
1600
|
+
input_tokens: usage2.inputTokens,
|
|
1601
|
+
output_tokens: usage2.outputTokens
|
|
1602
|
+
} : undefined,
|
|
1603
|
+
duration_ms: durationMs2,
|
|
1604
|
+
subagent: subagent_type,
|
|
1605
|
+
description
|
|
1606
|
+
};
|
|
1607
|
+
}
|
|
1608
|
+
const result = await generateText2({
|
|
1609
|
+
...commonOptions,
|
|
1194
1610
|
onStepFinish: async (step) => {
|
|
1195
1611
|
await typeConfig.onStepFinish?.(step);
|
|
1196
1612
|
await defaultOnStepFinish?.({
|
|
@@ -1205,20 +1621,16 @@ function createTaskTool(config) {
|
|
|
1205
1621
|
input_tokens: result.usage.inputTokens,
|
|
1206
1622
|
output_tokens: result.usage.outputTokens
|
|
1207
1623
|
} : undefined;
|
|
1208
|
-
let totalCostUsd;
|
|
1209
|
-
if (usage) {
|
|
1210
|
-
totalCostUsd = usage.input_tokens * costPerInputToken + usage.output_tokens * costPerOutputToken;
|
|
1211
|
-
}
|
|
1212
1624
|
return {
|
|
1213
1625
|
result: result.text,
|
|
1214
1626
|
usage,
|
|
1215
|
-
|
|
1216
|
-
|
|
1627
|
+
duration_ms: durationMs,
|
|
1628
|
+
subagent: subagent_type,
|
|
1629
|
+
description
|
|
1217
1630
|
};
|
|
1218
1631
|
} catch (error) {
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
};
|
|
1632
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
1633
|
+
return { error: errorMessage };
|
|
1222
1634
|
}
|
|
1223
1635
|
}
|
|
1224
1636
|
});
|
|
@@ -1233,9 +1645,41 @@ var todoWriteInputSchema = z14.object({
|
|
|
1233
1645
|
activeForm: z14.string().describe("Active form of the task description")
|
|
1234
1646
|
})).describe("The updated todo list")
|
|
1235
1647
|
});
|
|
1648
|
+
var TODO_WRITE_DESCRIPTION = `Use this tool to create and manage a structured task list for tracking progress. This helps organize complex tasks and gives the user visibility into your work.
|
|
1649
|
+
|
|
1650
|
+
**When to use this tool proactively:**
|
|
1651
|
+
1. Complex multi-step tasks - When a task requires 3 or more distinct steps
|
|
1652
|
+
2. Non-trivial tasks - Tasks requiring careful planning or multiple operations
|
|
1653
|
+
3. User explicitly requests a todo list
|
|
1654
|
+
4. User provides multiple tasks - Numbered lists or comma-separated items
|
|
1655
|
+
5. After receiving new instructions - Immediately capture requirements as todos
|
|
1656
|
+
6. When starting work - Mark task as in_progress BEFORE beginning
|
|
1657
|
+
7. After completing - Mark as completed and add any follow-up tasks discovered
|
|
1658
|
+
|
|
1659
|
+
**When NOT to use:**
|
|
1660
|
+
1. Single, straightforward tasks
|
|
1661
|
+
2. Trivial tasks with no organizational benefit
|
|
1662
|
+
3. Tasks completable in less than 3 trivial steps
|
|
1663
|
+
4. Purely conversational or informational requests
|
|
1664
|
+
|
|
1665
|
+
**Task states:**
|
|
1666
|
+
- pending: Not yet started
|
|
1667
|
+
- in_progress: Currently working on (limit to ONE at a time)
|
|
1668
|
+
- completed: Finished successfully
|
|
1669
|
+
|
|
1670
|
+
**Task format (both required):**
|
|
1671
|
+
- content: Imperative form ("Run tests", "Analyze data")
|
|
1672
|
+
- activeForm: Present continuous form ("Running tests", "Analyzing data")
|
|
1673
|
+
|
|
1674
|
+
**Task management rules:**
|
|
1675
|
+
- Update status in real-time as you work
|
|
1676
|
+
- Mark complete IMMEDIATELY after finishing (don't batch)
|
|
1677
|
+
- Keep exactly ONE task in_progress at any time
|
|
1678
|
+
- ONLY mark completed when FULLY accomplished
|
|
1679
|
+
- If blocked/errors, keep in_progress and create new task for the blocker`;
|
|
1236
1680
|
function createTodoWriteTool(state, config, onUpdate) {
|
|
1237
1681
|
return tool14({
|
|
1238
|
-
description:
|
|
1682
|
+
description: TODO_WRITE_DESCRIPTION,
|
|
1239
1683
|
inputSchema: zodSchema14(todoWriteInputSchema),
|
|
1240
1684
|
execute: async ({
|
|
1241
1685
|
todos
|
package/dist/tools/ask-user.d.ts
CHANGED
|
@@ -1,23 +1,53 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface QuestionOption {
|
|
2
|
+
label: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface StructuredQuestion {
|
|
6
|
+
header?: string;
|
|
7
|
+
question: string;
|
|
8
|
+
options?: QuestionOption[];
|
|
9
|
+
multiSelect?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface AskUserSimpleOutput {
|
|
2
12
|
question: string;
|
|
3
13
|
awaiting_response: true;
|
|
4
14
|
}
|
|
15
|
+
export interface AskUserStructuredOutput {
|
|
16
|
+
questions: StructuredQuestion[];
|
|
17
|
+
awaiting_response: true;
|
|
18
|
+
}
|
|
19
|
+
export type AskUserOutput = AskUserSimpleOutput | AskUserStructuredOutput;
|
|
5
20
|
export interface AskUserError {
|
|
6
21
|
error: string;
|
|
7
22
|
}
|
|
23
|
+
export interface AskUserAnswerOutput {
|
|
24
|
+
answer: string;
|
|
25
|
+
answers?: Record<string, string | string[]>;
|
|
26
|
+
}
|
|
8
27
|
export type AskUserResponseHandler = (question: string) => Promise<string> | string;
|
|
28
|
+
export type AskUserStructuredHandler = (questions: StructuredQuestion[]) => Promise<Record<string, string | string[]>> | Record<string, string | string[]>;
|
|
29
|
+
export interface AskUserToolConfig {
|
|
30
|
+
/** Handler for simple string questions */
|
|
31
|
+
onQuestion?: AskUserResponseHandler;
|
|
32
|
+
/** Handler for structured questions with options */
|
|
33
|
+
onStructuredQuestions?: AskUserStructuredHandler;
|
|
34
|
+
}
|
|
9
35
|
/**
|
|
10
36
|
* Creates a tool for asking the user clarifying questions.
|
|
11
37
|
*
|
|
12
|
-
*
|
|
13
|
-
* - Synchronous: returns the answer immediately
|
|
14
|
-
* - Async: waits for user input (e.g., from a UI)
|
|
15
|
-
* - Undefined: tool returns awaiting_response flag for external handling
|
|
38
|
+
* Supports both simple string questions and structured multi-choice questions.
|
|
16
39
|
*
|
|
17
|
-
* @param
|
|
40
|
+
* @param config - Configuration with optional handlers for questions
|
|
18
41
|
*/
|
|
19
|
-
export declare function createAskUserTool(
|
|
20
|
-
question
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
42
|
+
export declare function createAskUserTool(config?: AskUserToolConfig | AskUserResponseHandler): import("ai").Tool<{
|
|
43
|
+
question?: string | undefined;
|
|
44
|
+
questions?: {
|
|
45
|
+
question: string;
|
|
46
|
+
header?: string | undefined;
|
|
47
|
+
options?: {
|
|
48
|
+
label: string;
|
|
49
|
+
description?: string | undefined;
|
|
50
|
+
}[] | undefined;
|
|
51
|
+
multiSelect?: boolean | undefined;
|
|
52
|
+
}[] | undefined;
|
|
53
|
+
}, AskUserOutput | AskUserError | AskUserAnswerOutput>;
|
package/dist/tools/grep.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Sandbox } from "../sandbox/interface";
|
|
2
|
-
import type {
|
|
2
|
+
import type { GrepToolConfig } from "../types";
|
|
3
3
|
export interface GrepMatch {
|
|
4
4
|
file: string;
|
|
5
5
|
line_number?: number;
|
|
@@ -26,7 +26,7 @@ export interface GrepError {
|
|
|
26
26
|
error: string;
|
|
27
27
|
}
|
|
28
28
|
export type GrepOutput = GrepContentOutput | GrepFilesOutput | GrepCountOutput | GrepError;
|
|
29
|
-
export declare function createGrepTool(sandbox: Sandbox, config?:
|
|
29
|
+
export declare function createGrepTool(sandbox: Sandbox, config?: GrepToolConfig): import("ai").Tool<{
|
|
30
30
|
pattern: string;
|
|
31
31
|
path?: string | undefined;
|
|
32
32
|
glob?: string | undefined;
|
|
@@ -38,5 +38,6 @@ export declare function createGrepTool(sandbox: Sandbox, config?: ToolConfig): i
|
|
|
38
38
|
"-A"?: number | undefined;
|
|
39
39
|
"-C"?: number | undefined;
|
|
40
40
|
head_limit?: number | undefined;
|
|
41
|
+
offset?: number | undefined;
|
|
41
42
|
multiline?: boolean | undefined;
|
|
42
43
|
}, GrepOutput>;
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -65,7 +65,7 @@ export type { ReadDirectoryOutput, ReadError, ReadOutput, ReadTextOutput, } from
|
|
|
65
65
|
export { createReadTool } from "./read";
|
|
66
66
|
export type { SkillError, SkillOutput, SkillToolConfig } from "./skill";
|
|
67
67
|
export { createSkillTool } from "./skill";
|
|
68
|
-
export type { SubagentStepEvent, SubagentTypeConfig, TaskError, TaskOutput, TaskToolConfig, } from "./task";
|
|
68
|
+
export type { SubagentEventData, SubagentStepEvent, SubagentTypeConfig, TaskError, TaskOutput, TaskToolConfig, } from "./task";
|
|
69
69
|
export { createTaskTool } from "./task";
|
|
70
70
|
export type { TodoItem, TodoState, TodoWriteError, TodoWriteOutput, } from "./todo-write";
|
|
71
71
|
export { createTodoWriteTool } from "./todo-write";
|
package/dist/tools/task.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { type LanguageModel, type PrepareStepFunction, type StepResult, type StopCondition, type Tool, type ToolSet } from "ai";
|
|
1
|
+
import { type ModelMessage, type LanguageModel, type PrepareStepFunction, type StepResult, type StopCondition, type UIMessageStreamWriter, type Tool, type ToolSet } from "ai";
|
|
2
2
|
export interface TaskOutput {
|
|
3
3
|
result: string;
|
|
4
4
|
usage?: {
|
|
5
5
|
input_tokens: number;
|
|
6
6
|
output_tokens: number;
|
|
7
7
|
};
|
|
8
|
-
total_cost_usd?: number;
|
|
9
8
|
duration_ms?: number;
|
|
9
|
+
subagent?: string;
|
|
10
|
+
description?: string;
|
|
10
11
|
}
|
|
11
12
|
export interface TaskError {
|
|
12
13
|
error: string;
|
|
@@ -17,6 +18,15 @@ export interface SubagentStepEvent {
|
|
|
17
18
|
description: string;
|
|
18
19
|
step: StepResult<ToolSet>;
|
|
19
20
|
}
|
|
21
|
+
/** Data format for streamed subagent events (appears in message.parts as type: "data-subagent") */
|
|
22
|
+
export interface SubagentEventData {
|
|
23
|
+
event: "start" | "tool-call" | "done" | "complete";
|
|
24
|
+
subagent: string;
|
|
25
|
+
description: string;
|
|
26
|
+
toolName?: string;
|
|
27
|
+
args?: Record<string, unknown>;
|
|
28
|
+
messages?: ModelMessage[];
|
|
29
|
+
}
|
|
20
30
|
export interface SubagentTypeConfig {
|
|
21
31
|
/** Model to use for this subagent type */
|
|
22
32
|
model?: LanguageModel;
|
|
@@ -38,13 +48,11 @@ export interface TaskToolConfig {
|
|
|
38
48
|
tools: ToolSet;
|
|
39
49
|
/** Configuration for each subagent type */
|
|
40
50
|
subagentTypes?: Record<string, SubagentTypeConfig>;
|
|
41
|
-
/** Cost per input token for usage tracking */
|
|
42
|
-
costPerInputToken?: number;
|
|
43
|
-
/** Cost per output token for usage tracking */
|
|
44
|
-
costPerOutputToken?: number;
|
|
45
51
|
/** Default stop condition for subagents (default: stepCountIs(15)) */
|
|
46
52
|
defaultStopWhen?: StopCondition<ToolSet>;
|
|
47
53
|
/** Default callback for each step any subagent takes */
|
|
48
54
|
defaultOnStepFinish?: (event: SubagentStepEvent) => void | Promise<void>;
|
|
55
|
+
/** Optional stream writer for real-time subagent activity (uses streamText instead of generateText) */
|
|
56
|
+
streamWriter?: UIMessageStreamWriter;
|
|
49
57
|
}
|
|
50
58
|
export declare function createTaskTool(config: TaskToolConfig): Tool;
|
package/dist/types.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ export type ToolConfig = {
|
|
|
7
7
|
allowedPaths?: string[];
|
|
8
8
|
blockedCommands?: string[];
|
|
9
9
|
};
|
|
10
|
+
export type GrepToolConfig = ToolConfig & {
|
|
11
|
+
/** Use ripgrep (rg) instead of grep. Requires ripgrep to be installed. Default: false */
|
|
12
|
+
useRipgrep?: boolean;
|
|
13
|
+
};
|
|
10
14
|
export type WebSearchConfig = {
|
|
11
15
|
apiKey: string;
|
|
12
16
|
};
|
|
@@ -31,7 +35,7 @@ export type AgentConfig = {
|
|
|
31
35
|
Write?: ToolConfig;
|
|
32
36
|
Edit?: ToolConfig;
|
|
33
37
|
Glob?: ToolConfig;
|
|
34
|
-
Grep?:
|
|
38
|
+
Grep?: GrepToolConfig;
|
|
35
39
|
};
|
|
36
40
|
/** Include AskUser tool for user clarification */
|
|
37
41
|
askUser?: AskUserConfig;
|
package/package.json
CHANGED
package/dist/tools/lsp.d.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A diagnostic (error/warning) from the language server.
|
|
3
|
-
*/
|
|
4
|
-
export interface LspDiagnostic {
|
|
5
|
-
file: string;
|
|
6
|
-
line: number;
|
|
7
|
-
column: number;
|
|
8
|
-
endLine?: number;
|
|
9
|
-
endColumn?: number;
|
|
10
|
-
severity: "error" | "warning" | "info" | "hint";
|
|
11
|
-
message: string;
|
|
12
|
-
source?: string;
|
|
13
|
-
code?: string | number;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* A location in the codebase (for go-to-definition, references, etc.)
|
|
17
|
-
*/
|
|
18
|
-
export interface LspLocation {
|
|
19
|
-
file: string;
|
|
20
|
-
line: number;
|
|
21
|
-
column: number;
|
|
22
|
-
endLine?: number;
|
|
23
|
-
endColumn?: number;
|
|
24
|
-
preview?: string;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Hover information for a symbol.
|
|
28
|
-
*/
|
|
29
|
-
export interface LspHoverInfo {
|
|
30
|
-
contents: string;
|
|
31
|
-
range?: {
|
|
32
|
-
startLine: number;
|
|
33
|
-
startColumn: number;
|
|
34
|
-
endLine: number;
|
|
35
|
-
endColumn: number;
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Interface that LSP providers must implement.
|
|
40
|
-
* This abstracts over different LSP implementations (vscode, standalone servers, etc.)
|
|
41
|
-
*/
|
|
42
|
-
export interface LspProvider {
|
|
43
|
-
/** Get diagnostics for a file or the entire workspace */
|
|
44
|
-
getDiagnostics(file?: string): Promise<LspDiagnostic[]>;
|
|
45
|
-
/** Go to definition of symbol at position */
|
|
46
|
-
getDefinition(file: string, line: number, column: number): Promise<LspLocation[]>;
|
|
47
|
-
/** Find all references to symbol at position */
|
|
48
|
-
getReferences(file: string, line: number, column: number): Promise<LspLocation[]>;
|
|
49
|
-
/** Get hover information for symbol at position */
|
|
50
|
-
getHover(file: string, line: number, column: number): Promise<LspHoverInfo | null>;
|
|
51
|
-
/** Get available actions at position (optional) */
|
|
52
|
-
getCodeActions?(file: string, line: number, column: number): Promise<Array<{
|
|
53
|
-
title: string;
|
|
54
|
-
kind?: string;
|
|
55
|
-
}>>;
|
|
56
|
-
}
|
|
57
|
-
export interface LspDiagnosticsOutput {
|
|
58
|
-
type: "diagnostics";
|
|
59
|
-
diagnostics: LspDiagnostic[];
|
|
60
|
-
counts: {
|
|
61
|
-
errors: number;
|
|
62
|
-
warnings: number;
|
|
63
|
-
info: number;
|
|
64
|
-
hints: number;
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
export interface LspDefinitionOutput {
|
|
68
|
-
type: "definition";
|
|
69
|
-
locations: LspLocation[];
|
|
70
|
-
}
|
|
71
|
-
export interface LspReferencesOutput {
|
|
72
|
-
type: "references";
|
|
73
|
-
locations: LspLocation[];
|
|
74
|
-
count: number;
|
|
75
|
-
}
|
|
76
|
-
export interface LspHoverOutput {
|
|
77
|
-
type: "hover";
|
|
78
|
-
info: LspHoverInfo | null;
|
|
79
|
-
}
|
|
80
|
-
export interface LspError {
|
|
81
|
-
error: string;
|
|
82
|
-
}
|
|
83
|
-
export type LspOutput = LspDiagnosticsOutput | LspDefinitionOutput | LspReferencesOutput | LspHoverOutput | LspError;
|
|
84
|
-
/**
|
|
85
|
-
* Creates an LSP tool for code intelligence operations.
|
|
86
|
-
*
|
|
87
|
-
* @param provider - An implementation of LspProvider that interfaces with language servers
|
|
88
|
-
*/
|
|
89
|
-
export declare function createLspTool(provider: LspProvider): import("ai").Tool<{
|
|
90
|
-
action: "diagnostics" | "definition" | "references" | "hover";
|
|
91
|
-
file?: string | undefined;
|
|
92
|
-
line?: number | undefined;
|
|
93
|
-
column?: number | undefined;
|
|
94
|
-
}, LspOutput>;
|