byterover-cli 1.7.2 → 1.8.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/README.md +17 -3
- package/dist/agent/core/domain/tools/constants.d.ts +0 -15
- package/dist/agent/core/domain/tools/constants.js +0 -15
- package/dist/agent/core/interfaces/i-cipher-agent.d.ts +6 -0
- package/dist/agent/core/interfaces/i-curate-service.d.ts +12 -0
- package/dist/agent/infra/llm/internal-llm-service.d.ts +13 -0
- package/dist/agent/infra/llm/internal-llm-service.js +61 -21
- package/dist/agent/infra/tools/implementations/curate-tool.d.ts +133 -0
- package/dist/agent/infra/tools/implementations/curate-tool.js +14 -0
- package/dist/agent/infra/tools/implementations/search-knowledge-service.js +91 -14
- package/dist/agent/infra/tools/index.d.ts +0 -4
- package/dist/agent/infra/tools/index.js +0 -4
- package/dist/agent/infra/tools/tool-registry.js +0 -113
- package/dist/agent/resources/prompts/curate-detail-preservation.yml +73 -0
- package/dist/agent/resources/prompts/system-prompt.yml +69 -3
- package/dist/server/core/domain/knowledge/markdown-writer.d.ts +13 -0
- package/dist/server/core/domain/knowledge/markdown-writer.js +116 -8
- package/dist/server/infra/executor/curate-executor.js +1 -1
- package/dist/server/infra/executor/direct-search-responder.d.ts +45 -0
- package/dist/server/infra/executor/direct-search-responder.js +86 -0
- package/dist/server/infra/executor/folder-pack-executor.d.ts +13 -5
- package/dist/server/infra/executor/folder-pack-executor.js +739 -39
- package/dist/server/infra/executor/query-executor.d.ts +49 -3
- package/dist/server/infra/executor/query-executor.js +194 -9
- package/dist/server/infra/executor/query-result-cache.d.ts +87 -0
- package/dist/server/infra/executor/query-result-cache.js +127 -0
- package/dist/server/infra/executor/query-similarity.d.ts +28 -0
- package/dist/server/infra/executor/query-similarity.js +41 -0
- package/dist/server/infra/process/agent-worker.js +9 -2
- package/dist/server/infra/process/inline-agent-executor.js +16 -5
- package/dist/server/infra/usecase/curate-use-case.js +6 -1
- package/dist/server/infra/usecase/query-use-case.js +10 -0
- package/dist/server/utils/file-validator.js +78 -1
- package/dist/tui/hooks/use-slash-completion.js +25 -4
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
- package/dist/agent/infra/tools/implementations/bash-exec-tool.d.ts +0 -13
- package/dist/agent/infra/tools/implementations/bash-exec-tool.js +0 -110
- package/dist/agent/infra/tools/implementations/bash-output-tool.d.ts +0 -12
- package/dist/agent/infra/tools/implementations/bash-output-tool.js +0 -43
- package/dist/agent/infra/tools/implementations/batch-tool.d.ts +0 -12
- package/dist/agent/infra/tools/implementations/batch-tool.js +0 -142
- package/dist/agent/infra/tools/implementations/create-knowledge-topic-tool.d.ts +0 -11
- package/dist/agent/infra/tools/implementations/create-knowledge-topic-tool.js +0 -149
- package/dist/agent/infra/tools/implementations/delete-memory-tool.d.ts +0 -12
- package/dist/agent/infra/tools/implementations/delete-memory-tool.js +0 -37
- package/dist/agent/infra/tools/implementations/edit-file-tool.d.ts +0 -13
- package/dist/agent/infra/tools/implementations/edit-file-tool.js +0 -50
- package/dist/agent/infra/tools/implementations/edit-memory-tool.d.ts +0 -13
- package/dist/agent/infra/tools/implementations/edit-memory-tool.js +0 -53
- package/dist/agent/infra/tools/implementations/kill-process-tool.d.ts +0 -12
- package/dist/agent/infra/tools/implementations/kill-process-tool.js +0 -55
- package/dist/agent/infra/tools/implementations/list-memories-tool.d.ts +0 -12
- package/dist/agent/infra/tools/implementations/list-memories-tool.js +0 -63
- package/dist/agent/infra/tools/implementations/read-memory-tool.d.ts +0 -12
- package/dist/agent/infra/tools/implementations/read-memory-tool.js +0 -39
- package/dist/agent/infra/tools/implementations/read-todos-tool.d.ts +0 -11
- package/dist/agent/infra/tools/implementations/read-todos-tool.js +0 -39
- package/dist/agent/infra/tools/implementations/search-history-tool.d.ts +0 -10
- package/dist/agent/infra/tools/implementations/search-history-tool.js +0 -36
- package/dist/agent/infra/tools/implementations/spec-analyze-tool.d.ts +0 -7
- package/dist/agent/infra/tools/implementations/spec-analyze-tool.js +0 -78
- package/dist/agent/infra/tools/implementations/write-memory-tool.d.ts +0 -13
- package/dist/agent/infra/tools/implementations/write-memory-tool.js +0 -52
- package/dist/agent/infra/tools/implementations/write-todos-tool.d.ts +0 -13
- package/dist/agent/infra/tools/implementations/write-todos-tool.js +0 -121
|
@@ -47,7 +47,12 @@ export class CurateUseCase {
|
|
|
47
47
|
}
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
// Provide default context for folder packing when none is provided
|
|
51
|
+
const resolvedContent = context?.trim()
|
|
52
|
+
? context
|
|
53
|
+
: hasFolders
|
|
54
|
+
? 'Analyze this folder and extract all relevant knowledge, patterns, and documentation.'
|
|
55
|
+
: '';
|
|
51
56
|
let client;
|
|
52
57
|
try {
|
|
53
58
|
client = await this.createClient({ headless, verbose });
|
|
@@ -371,6 +371,16 @@ export class QueryUseCase {
|
|
|
371
371
|
if (payload.taskId === taskId && !completed) {
|
|
372
372
|
completed = true;
|
|
373
373
|
cleanup();
|
|
374
|
+
// Fallback: use payload.result when llmservice:response wasn't received
|
|
375
|
+
// (e.g., Tier 2 direct search responses that bypass the LLM)
|
|
376
|
+
if (!resultPrinted && payload.result) {
|
|
377
|
+
finalResult = payload.result;
|
|
378
|
+
resultPrinted = true;
|
|
379
|
+
if (format === 'text') {
|
|
380
|
+
this.terminal.log('\nResult:');
|
|
381
|
+
this.terminal.log(payload.result);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
374
384
|
if (format === 'json') {
|
|
375
385
|
this.outputJsonResult({
|
|
376
386
|
result: finalResult,
|
|
@@ -1,7 +1,74 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import { isBinaryFile, isImageFile, isPdfFile } from '../../agent/infra/file-system/binary-utils.js';
|
|
4
|
+
import { isBinaryFile, isImageFile, isOfficeFile, isPdfFile } from '../../agent/infra/file-system/binary-utils.js';
|
|
5
|
+
/**
|
|
6
|
+
* Known text file extensions that should always be treated as text,
|
|
7
|
+
* bypassing binary content inspection. This prevents false positives
|
|
8
|
+
* from files with unusual encodings (e.g., UTF-16) or embedded
|
|
9
|
+
* special characters (e.g., box-drawing characters in .md files).
|
|
10
|
+
*/
|
|
11
|
+
const KNOWN_TEXT_EXTENSIONS = new Set([
|
|
12
|
+
'.adoc',
|
|
13
|
+
'.c',
|
|
14
|
+
'.cfg',
|
|
15
|
+
'.clj',
|
|
16
|
+
'.cmake',
|
|
17
|
+
'.conf',
|
|
18
|
+
'.cpp',
|
|
19
|
+
'.cs',
|
|
20
|
+
'.css',
|
|
21
|
+
'.csv',
|
|
22
|
+
'.dart',
|
|
23
|
+
'.dockerfile',
|
|
24
|
+
'.env',
|
|
25
|
+
'.erl',
|
|
26
|
+
'.ex',
|
|
27
|
+
'.go',
|
|
28
|
+
'.graphql',
|
|
29
|
+
'.groovy',
|
|
30
|
+
'.h',
|
|
31
|
+
'.hpp',
|
|
32
|
+
'.html',
|
|
33
|
+
'.ini',
|
|
34
|
+
'.java',
|
|
35
|
+
'.js',
|
|
36
|
+
'.json',
|
|
37
|
+
'.jsonc',
|
|
38
|
+
'.jsx',
|
|
39
|
+
'.kt',
|
|
40
|
+
'.less',
|
|
41
|
+
'.lua',
|
|
42
|
+
'.makefile',
|
|
43
|
+
'.markdown',
|
|
44
|
+
'.md',
|
|
45
|
+
'.php',
|
|
46
|
+
'.pl',
|
|
47
|
+
'.proto',
|
|
48
|
+
'.py',
|
|
49
|
+
'.r',
|
|
50
|
+
'.rb',
|
|
51
|
+
'.rs',
|
|
52
|
+
'.rst',
|
|
53
|
+
'.sass',
|
|
54
|
+
'.scala',
|
|
55
|
+
'.scss',
|
|
56
|
+
'.sh',
|
|
57
|
+
'.sql',
|
|
58
|
+
'.svelte',
|
|
59
|
+
'.svg',
|
|
60
|
+
'.swift',
|
|
61
|
+
'.tf',
|
|
62
|
+
'.toml',
|
|
63
|
+
'.ts',
|
|
64
|
+
'.tsx',
|
|
65
|
+
'.txt',
|
|
66
|
+
'.vue',
|
|
67
|
+
'.xml',
|
|
68
|
+
'.yaml',
|
|
69
|
+
'.yml',
|
|
70
|
+
'.zsh',
|
|
71
|
+
]);
|
|
5
72
|
/**
|
|
6
73
|
* Normalize file path - handles relative, absolute, tilde, symlinks
|
|
7
74
|
* Returns absolute canonical path
|
|
@@ -65,6 +132,12 @@ export function validateFileForCurate(filePath, projectRoot) {
|
|
|
65
132
|
return { error: `Cannot read file: ${filePath}`, valid: false };
|
|
66
133
|
}
|
|
67
134
|
const sampleBuffer = buffer.subarray(0, bytesRead);
|
|
135
|
+
const ext = path.extname(normalized).toLowerCase();
|
|
136
|
+
// Fast path: known text extensions bypass binary content inspection.
|
|
137
|
+
// This prevents false positives from files with unusual encodings (e.g., UTF-16 .md files)
|
|
138
|
+
if (KNOWN_TEXT_EXTENSIONS.has(ext)) {
|
|
139
|
+
return { normalizedPath: normalized, valid: true };
|
|
140
|
+
}
|
|
68
141
|
// Check file type using binary-utils (same logic as read_file tool)
|
|
69
142
|
// Allow image files - read_file returns them as base64 attachments
|
|
70
143
|
if (isImageFile(normalized)) {
|
|
@@ -75,6 +148,10 @@ export function validateFileForCurate(filePath, projectRoot) {
|
|
|
75
148
|
if (isPdfFile(normalized, sampleBuffer)) {
|
|
76
149
|
return { normalizedPath: normalized, valid: true };
|
|
77
150
|
}
|
|
151
|
+
// Allow Office documents - FileContentReader can parse these for text extraction
|
|
152
|
+
if (isOfficeFile(normalized)) {
|
|
153
|
+
return { normalizedPath: normalized, valid: true };
|
|
154
|
+
}
|
|
78
155
|
// Check if it's a binary file (using same logic as read_file tool)
|
|
79
156
|
if (isBinaryFile(normalized, sampleBuffer)) {
|
|
80
157
|
return { error: `File type not supported: ${filePath}`, valid: false };
|
|
@@ -9,6 +9,20 @@ import { useCommands } from '../contexts/commands-context.js';
|
|
|
9
9
|
function generateFileSuggestions(searchPattern) {
|
|
10
10
|
try {
|
|
11
11
|
const cwd = process.cwd();
|
|
12
|
+
const suggestions = [];
|
|
13
|
+
// Special case: Always suggest ./ as the first option when appropriate
|
|
14
|
+
// This allows users to curate the entire current directory
|
|
15
|
+
const normalizedPattern = searchPattern.toLowerCase();
|
|
16
|
+
const shouldShowCurrentDir = !searchPattern || // Just typed @
|
|
17
|
+
normalizedPattern === '.' || // Typing @.
|
|
18
|
+
'./'.startsWith(normalizedPattern); // Typing @. (partial match)
|
|
19
|
+
if (shouldShowCurrentDir) {
|
|
20
|
+
suggestions.push({
|
|
21
|
+
description: 'Current directory (will pack all contents)',
|
|
22
|
+
label: './',
|
|
23
|
+
value: '@./',
|
|
24
|
+
});
|
|
25
|
+
}
|
|
12
26
|
// If pattern ends with /, list contents of that directory
|
|
13
27
|
let searchDir;
|
|
14
28
|
let searchPrefix;
|
|
@@ -23,10 +37,9 @@ function generateFileSuggestions(searchPattern) {
|
|
|
23
37
|
const fullSearchDir = path.resolve(cwd, searchDir);
|
|
24
38
|
// Check if search directory exists and is within cwd
|
|
25
39
|
if (!fs.existsSync(fullSearchDir) || !fullSearchDir.startsWith(cwd)) {
|
|
26
|
-
return
|
|
40
|
+
return suggestions;
|
|
27
41
|
}
|
|
28
42
|
const entries = fs.readdirSync(fullSearchDir, { withFileTypes: true });
|
|
29
|
-
const suggestions = [];
|
|
30
43
|
for (const entry of entries) {
|
|
31
44
|
// Skip hidden files
|
|
32
45
|
if (entry.name.startsWith('.'))
|
|
@@ -43,14 +56,22 @@ function generateFileSuggestions(searchPattern) {
|
|
|
43
56
|
}
|
|
44
57
|
}
|
|
45
58
|
// Sort: directories first, then alphabetically
|
|
46
|
-
|
|
59
|
+
// Note: ./ is already at the front, so we sort from index 1
|
|
60
|
+
const hasCurrentDir = suggestions[0]?.label === './';
|
|
61
|
+
const startIndex = hasCurrentDir ? 1 : 0;
|
|
62
|
+
const toSort = suggestions.slice(startIndex);
|
|
63
|
+
toSort.sort((a, b) => {
|
|
47
64
|
const aIsDir = a.label.endsWith('/');
|
|
48
65
|
const bIsDir = b.label.endsWith('/');
|
|
49
66
|
if (aIsDir !== bIsDir)
|
|
50
67
|
return aIsDir ? -1 : 1;
|
|
51
68
|
return a.label.localeCompare(b.label);
|
|
52
69
|
});
|
|
53
|
-
|
|
70
|
+
// Recombine: ./ stays at front, rest are sorted
|
|
71
|
+
const finalSuggestions = hasCurrentDir
|
|
72
|
+
? [suggestions[0], ...toSort]
|
|
73
|
+
: toSort;
|
|
74
|
+
return finalSuggestions.slice(0, 20); // Limit to 20 suggestions
|
|
54
75
|
}
|
|
55
76
|
catch {
|
|
56
77
|
return [];
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Tool } from '../../../core/domain/tools/types.js';
|
|
2
|
-
import type { IProcessService } from '../../../core/interfaces/i-process-service.js';
|
|
3
|
-
/**
|
|
4
|
-
* Create bash_exec tool.
|
|
5
|
-
*
|
|
6
|
-
* Executes shell commands with security validation and approval for dangerous commands.
|
|
7
|
-
* Supports both foreground (wait for completion) and background (return immediately) execution.
|
|
8
|
-
* When a metadata callback is provided, streams output updates in real-time.
|
|
9
|
-
*
|
|
10
|
-
* @param processService - Process service for command execution
|
|
11
|
-
* @returns bash_exec tool instance
|
|
12
|
-
*/
|
|
13
|
-
export declare function createBashExecTool(processService: IProcessService): Tool;
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { ToolName } from '../../../core/domain/tools/constants.js';
|
|
3
|
-
/**
|
|
4
|
-
* Input schema for bash_exec tool.
|
|
5
|
-
*/
|
|
6
|
-
const BashExecInputSchema = z
|
|
7
|
-
.object({
|
|
8
|
-
/**
|
|
9
|
-
* Shell command to execute.
|
|
10
|
-
*/
|
|
11
|
-
command: z.string().describe('Shell command to execute'),
|
|
12
|
-
/**
|
|
13
|
-
* Working directory for command execution (relative to configured base directory).
|
|
14
|
-
*/
|
|
15
|
-
cwd: z.string().optional().describe('Working directory for command execution'),
|
|
16
|
-
/**
|
|
17
|
-
* Human-readable description of what the command does (5-10 words).
|
|
18
|
-
*/
|
|
19
|
-
description: z.string().optional().describe('Description of what the command does (5-10 words)'),
|
|
20
|
-
/**
|
|
21
|
-
* Execute command in background (returns immediately with process handle).
|
|
22
|
-
*/
|
|
23
|
-
runInBackground: z
|
|
24
|
-
.boolean()
|
|
25
|
-
.optional()
|
|
26
|
-
.default(false)
|
|
27
|
-
.describe('Execute command in background'),
|
|
28
|
-
/**
|
|
29
|
-
* Timeout in milliseconds (max: 600000, default: 300000 = 5 minutes).
|
|
30
|
-
*/
|
|
31
|
-
timeout: z
|
|
32
|
-
.number()
|
|
33
|
-
.int()
|
|
34
|
-
.positive()
|
|
35
|
-
.max(600_000)
|
|
36
|
-
.optional()
|
|
37
|
-
.default(300_000)
|
|
38
|
-
.describe('Timeout in milliseconds (default: 5 minutes)'),
|
|
39
|
-
})
|
|
40
|
-
.strict();
|
|
41
|
-
/**
|
|
42
|
-
* Create bash_exec tool.
|
|
43
|
-
*
|
|
44
|
-
* Executes shell commands with security validation and approval for dangerous commands.
|
|
45
|
-
* Supports both foreground (wait for completion) and background (return immediately) execution.
|
|
46
|
-
* When a metadata callback is provided, streams output updates in real-time.
|
|
47
|
-
*
|
|
48
|
-
* @param processService - Process service for command execution
|
|
49
|
-
* @returns bash_exec tool instance
|
|
50
|
-
*/
|
|
51
|
-
export function createBashExecTool(processService) {
|
|
52
|
-
return {
|
|
53
|
-
description: `Execute a shell command and return its output.`,
|
|
54
|
-
async execute(input, context) {
|
|
55
|
-
const { command, cwd, description, runInBackground, timeout } = input;
|
|
56
|
-
// Stream initial status via metadata callback if available
|
|
57
|
-
if (context?.metadata) {
|
|
58
|
-
context.metadata({
|
|
59
|
-
description: description ?? `Executing: ${command.slice(0, 50)}${command.length > 50 ? '...' : ''}`,
|
|
60
|
-
output: '',
|
|
61
|
-
progress: 0,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
// Execute command via process service
|
|
65
|
-
const result = await processService.executeCommand(command, {
|
|
66
|
-
cwd,
|
|
67
|
-
description,
|
|
68
|
-
runInBackground,
|
|
69
|
-
timeout,
|
|
70
|
-
});
|
|
71
|
-
// Return based on execution mode
|
|
72
|
-
if ('stdout' in result) {
|
|
73
|
-
// Stream final output via metadata callback if available
|
|
74
|
-
if (context?.metadata) {
|
|
75
|
-
context.metadata({
|
|
76
|
-
description: description ?? 'Command completed',
|
|
77
|
-
output: result.stdout + (result.stderr ? `\n[stderr]\n${result.stderr}` : ''),
|
|
78
|
-
progress: 100,
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
// Foreground execution result
|
|
82
|
-
return {
|
|
83
|
-
duration: result.duration,
|
|
84
|
-
exitCode: result.exitCode,
|
|
85
|
-
stderr: result.stderr,
|
|
86
|
-
stdout: result.stdout,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
// Stream background process info via metadata callback if available
|
|
90
|
-
if (context?.metadata) {
|
|
91
|
-
context.metadata({
|
|
92
|
-
description: `Background process started: ${result.processId}`,
|
|
93
|
-
output: `Process started with PID ${result.pid}`,
|
|
94
|
-
progress: 100,
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
// Background execution handle
|
|
98
|
-
return {
|
|
99
|
-
command: result.command,
|
|
100
|
-
description: result.description,
|
|
101
|
-
message: `Process started in background. Use bash_output with processId="${result.processId}" to retrieve output.`,
|
|
102
|
-
pid: result.pid,
|
|
103
|
-
processId: result.processId,
|
|
104
|
-
startedAt: result.startedAt.toISOString(),
|
|
105
|
-
};
|
|
106
|
-
},
|
|
107
|
-
id: ToolName.BASH_EXEC,
|
|
108
|
-
inputSchema: BashExecInputSchema,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Tool } from '../../../core/domain/tools/types.js';
|
|
2
|
-
import type { IProcessService } from '../../../core/interfaces/i-process-service.js';
|
|
3
|
-
/**
|
|
4
|
-
* Create bash_output tool.
|
|
5
|
-
*
|
|
6
|
-
* Retrieves output from a background process started by bash_exec.
|
|
7
|
-
* Reading output clears the buffer (destructive read), so output is only returned once.
|
|
8
|
-
*
|
|
9
|
-
* @param processService - Process service for retrieving output
|
|
10
|
-
* @returns bash_output tool instance
|
|
11
|
-
*/
|
|
12
|
-
export declare function createBashOutputTool(processService: IProcessService): Tool;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { ToolName } from '../../../core/domain/tools/constants.js';
|
|
3
|
-
/**
|
|
4
|
-
* Input schema for bash_output tool.
|
|
5
|
-
*/
|
|
6
|
-
const BashOutputInputSchema = z
|
|
7
|
-
.object({
|
|
8
|
-
/**
|
|
9
|
-
* Unique process identifier from bash_exec.
|
|
10
|
-
*/
|
|
11
|
-
processId: z.string().describe('Unique process identifier from bash_exec'),
|
|
12
|
-
})
|
|
13
|
-
.strict();
|
|
14
|
-
/**
|
|
15
|
-
* Create bash_output tool.
|
|
16
|
-
*
|
|
17
|
-
* Retrieves output from a background process started by bash_exec.
|
|
18
|
-
* Reading output clears the buffer (destructive read), so output is only returned once.
|
|
19
|
-
*
|
|
20
|
-
* @param processService - Process service for retrieving output
|
|
21
|
-
* @returns bash_output tool instance
|
|
22
|
-
*/
|
|
23
|
-
export function createBashOutputTool(processService) {
|
|
24
|
-
return {
|
|
25
|
-
description: `Retrieve output from a background process started by bash_exec.`,
|
|
26
|
-
async execute(input, _context) {
|
|
27
|
-
const { processId } = input;
|
|
28
|
-
// Get output from process service
|
|
29
|
-
const output = await processService.getProcessOutput(processId);
|
|
30
|
-
// Return output with status
|
|
31
|
-
return {
|
|
32
|
-
duration: output.duration,
|
|
33
|
-
exitCode: output.exitCode,
|
|
34
|
-
processId,
|
|
35
|
-
status: output.status,
|
|
36
|
-
stderr: output.stderr,
|
|
37
|
-
stdout: output.stdout,
|
|
38
|
-
};
|
|
39
|
-
},
|
|
40
|
-
id: ToolName.BASH_OUTPUT,
|
|
41
|
-
inputSchema: BashOutputInputSchema,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Tool } from '../../../core/domain/tools/types.js';
|
|
2
|
-
import type { ToolProviderGetter } from '../tool-provider-getter.js';
|
|
3
|
-
/**
|
|
4
|
-
* Create batch tool.
|
|
5
|
-
*
|
|
6
|
-
* Executes multiple independent tool calls concurrently to reduce latency.
|
|
7
|
-
* Best used for gathering context (reads, searches, listings).
|
|
8
|
-
*
|
|
9
|
-
* @param getToolProvider - Lazy getter for tool provider (avoids circular dependency)
|
|
10
|
-
* @returns batch tool instance
|
|
11
|
-
*/
|
|
12
|
-
export declare function createBatchTool(getToolProvider: ToolProviderGetter): Tool;
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { ToolName } from '../../../core/domain/tools/constants.js';
|
|
3
|
-
/**
|
|
4
|
-
* Tools that are not allowed in batch execution.
|
|
5
|
-
* - batch: No nesting of batch calls
|
|
6
|
-
* - edit_file: Sequential edits for proper conflict handling
|
|
7
|
-
* - write_todos: Lightweight, call directly
|
|
8
|
-
*/
|
|
9
|
-
const DISALLOWED_TOOLS = new Set(['batch', 'edit_file', 'write_todos']);
|
|
10
|
-
/**
|
|
11
|
-
* Maximum number of tool calls allowed in a single batch.
|
|
12
|
-
*/
|
|
13
|
-
const MAX_BATCH_SIZE = 10;
|
|
14
|
-
/**
|
|
15
|
-
* Input schema for batch tool.
|
|
16
|
-
*/
|
|
17
|
-
const BatchInputSchema = z
|
|
18
|
-
.object({
|
|
19
|
-
/**
|
|
20
|
-
* Array of tool calls to execute in parallel.
|
|
21
|
-
*/
|
|
22
|
-
toolCalls: z
|
|
23
|
-
.array(z.object({
|
|
24
|
-
/**
|
|
25
|
-
* Parameters for the tool.
|
|
26
|
-
*/
|
|
27
|
-
parameters: z.record(z.unknown()).describe('Parameters for the tool'),
|
|
28
|
-
/**
|
|
29
|
-
* The name of the tool to execute.
|
|
30
|
-
*/
|
|
31
|
-
tool: z.string().describe('The name of the tool to execute'),
|
|
32
|
-
}))
|
|
33
|
-
.min(1, 'Provide at least one tool call')
|
|
34
|
-
.describe('Array of tool calls to execute in parallel'),
|
|
35
|
-
})
|
|
36
|
-
.strict();
|
|
37
|
-
/**
|
|
38
|
-
* Create batch tool.
|
|
39
|
-
*
|
|
40
|
-
* Executes multiple independent tool calls concurrently to reduce latency.
|
|
41
|
-
* Best used for gathering context (reads, searches, listings).
|
|
42
|
-
*
|
|
43
|
-
* @param getToolProvider - Lazy getter for tool provider (avoids circular dependency)
|
|
44
|
-
* @returns batch tool instance
|
|
45
|
-
*/
|
|
46
|
-
export function createBatchTool(getToolProvider) {
|
|
47
|
-
return {
|
|
48
|
-
description: 'Execute multiple independent tool calls concurrently.',
|
|
49
|
-
async execute(input, context) {
|
|
50
|
-
const { toolCalls } = input;
|
|
51
|
-
const toolProvider = getToolProvider();
|
|
52
|
-
// Limit to MAX_BATCH_SIZE
|
|
53
|
-
const activeCalls = toolCalls.slice(0, MAX_BATCH_SIZE);
|
|
54
|
-
const discardedCalls = toolCalls.slice(MAX_BATCH_SIZE);
|
|
55
|
-
/**
|
|
56
|
-
* Execute a single tool call and return the result.
|
|
57
|
-
*/
|
|
58
|
-
const executeCall = async (call) => {
|
|
59
|
-
const startTime = Date.now();
|
|
60
|
-
// Check if tool is disallowed in batch
|
|
61
|
-
if (DISALLOWED_TOOLS.has(call.tool)) {
|
|
62
|
-
return {
|
|
63
|
-
durationMs: Date.now() - startTime,
|
|
64
|
-
error: `Tool '${call.tool}' is not allowed in batch. Disallowed tools: ${[...DISALLOWED_TOOLS].join(', ')}`,
|
|
65
|
-
success: false,
|
|
66
|
-
tool: call.tool,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
// Check if tool exists
|
|
70
|
-
if (!toolProvider.hasTool(call.tool)) {
|
|
71
|
-
const availableTools = toolProvider.getToolNames().filter((name) => !DISALLOWED_TOOLS.has(name));
|
|
72
|
-
return {
|
|
73
|
-
durationMs: Date.now() - startTime,
|
|
74
|
-
error: `Tool '${call.tool}' not found. Available tools: ${availableTools.join(', ')}`,
|
|
75
|
-
success: false,
|
|
76
|
-
tool: call.tool,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
try {
|
|
80
|
-
const result = await toolProvider.executeTool(call.tool, call.parameters, context?.sessionId, context);
|
|
81
|
-
return {
|
|
82
|
-
durationMs: Date.now() - startTime,
|
|
83
|
-
result,
|
|
84
|
-
success: true,
|
|
85
|
-
tool: call.tool,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
return {
|
|
90
|
-
durationMs: Date.now() - startTime,
|
|
91
|
-
error: error instanceof Error ? error.message : String(error),
|
|
92
|
-
success: false,
|
|
93
|
-
tool: call.tool,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
// Execute all calls in parallel
|
|
98
|
-
const results = await Promise.all(activeCalls.map((call) => executeCall(call)));
|
|
99
|
-
// Add discarded calls as errors
|
|
100
|
-
for (const call of discardedCalls) {
|
|
101
|
-
results.push({
|
|
102
|
-
durationMs: 0,
|
|
103
|
-
error: `Maximum of ${MAX_BATCH_SIZE} tools allowed in batch`,
|
|
104
|
-
success: false,
|
|
105
|
-
tool: call.tool,
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
const successful = results.filter((r) => r.success).length;
|
|
109
|
-
const failed = results.length - successful;
|
|
110
|
-
// Stream progress update
|
|
111
|
-
if (context?.metadata) {
|
|
112
|
-
context.metadata({
|
|
113
|
-
description: 'Batch execution complete',
|
|
114
|
-
output: `${successful}/${results.length} tools executed successfully`,
|
|
115
|
-
progress: 100,
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
// Build output message
|
|
119
|
-
const outputMessage = failed > 0
|
|
120
|
-
? `Executed ${successful}/${results.length} tools successfully. ${failed} failed.`
|
|
121
|
-
: `All ${successful} tools executed successfully.\n\nKeep using the batch tool for optimal performance!`;
|
|
122
|
-
return {
|
|
123
|
-
metadata: {
|
|
124
|
-
details: results.map((r) => ({ success: r.success, tool: r.tool })),
|
|
125
|
-
failed,
|
|
126
|
-
successful,
|
|
127
|
-
tools: toolCalls.map((c) => c.tool),
|
|
128
|
-
totalCalls: results.length,
|
|
129
|
-
},
|
|
130
|
-
results: results.map((r) => ({
|
|
131
|
-
durationMs: r.durationMs,
|
|
132
|
-
success: r.success,
|
|
133
|
-
tool: r.tool,
|
|
134
|
-
...(r.success ? { result: r.result } : { error: r.error }),
|
|
135
|
-
})),
|
|
136
|
-
summary: outputMessage,
|
|
137
|
-
};
|
|
138
|
-
},
|
|
139
|
-
id: ToolName.BATCH,
|
|
140
|
-
inputSchema: BatchInputSchema,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { Tool } from '../../../core/domain/tools/types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Creates the create knowledge topic tool.
|
|
4
|
-
*
|
|
5
|
-
* Creates organized knowledge topics within domain folders, where each topic and subtopic
|
|
6
|
-
* has its own folder containing a context.md file with relevant snippets. This tool should
|
|
7
|
-
* be used after detecting domains to organize the extracted knowledge into a structured hierarchy.
|
|
8
|
-
*
|
|
9
|
-
* @returns Configured create knowledge topic tool
|
|
10
|
-
*/
|
|
11
|
-
export declare function createCreateKnowledgeTopicTool(): Tool;
|