@clinebot/core 0.0.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 +88 -0
- package/dist/account/cline-account-service.d.ts +34 -0
- package/dist/account/index.d.ts +3 -0
- package/dist/account/rpc.d.ts +38 -0
- package/dist/account/types.d.ts +74 -0
- package/dist/agents/agent-config-loader.d.ts +18 -0
- package/dist/agents/agent-config-parser.d.ts +25 -0
- package/dist/agents/hooks-config-loader.d.ts +23 -0
- package/dist/agents/index.d.ts +11 -0
- package/dist/agents/plugin-config-loader.d.ts +22 -0
- package/dist/agents/plugin-loader.d.ts +9 -0
- package/dist/agents/plugin-sandbox.d.ts +12 -0
- package/dist/agents/unified-config-file-watcher.d.ts +77 -0
- package/dist/agents/user-instruction-config-loader.d.ts +63 -0
- package/dist/auth/client.d.ts +11 -0
- package/dist/auth/cline.d.ts +41 -0
- package/dist/auth/codex.d.ts +39 -0
- package/dist/auth/oca.d.ts +22 -0
- package/dist/auth/server.d.ts +22 -0
- package/dist/auth/types.d.ts +72 -0
- package/dist/auth/utils.d.ts +32 -0
- package/dist/chat/chat-schema.d.ts +145 -0
- package/dist/default-tools/constants.d.ts +23 -0
- package/dist/default-tools/definitions.d.ts +96 -0
- package/dist/default-tools/executors/apply-patch-parser.d.ts +68 -0
- package/dist/default-tools/executors/apply-patch.d.ts +26 -0
- package/dist/default-tools/executors/bash.d.ts +49 -0
- package/dist/default-tools/executors/editor.d.ts +31 -0
- package/dist/default-tools/executors/file-read.d.ts +40 -0
- package/dist/default-tools/executors/index.d.ts +44 -0
- package/dist/default-tools/executors/search.d.ts +50 -0
- package/dist/default-tools/executors/web-fetch.d.ts +58 -0
- package/dist/default-tools/index.d.ts +57 -0
- package/dist/default-tools/presets.d.ts +124 -0
- package/dist/default-tools/schemas.d.ts +121 -0
- package/dist/default-tools/types.d.ts +237 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +220 -0
- package/dist/input/file-indexer.d.ts +5 -0
- package/dist/input/index.d.ts +4 -0
- package/dist/input/mention-enricher.d.ts +12 -0
- package/dist/mcp/config-loader.d.ts +15 -0
- package/dist/mcp/index.d.ts +4 -0
- package/dist/mcp/manager.d.ts +24 -0
- package/dist/mcp/types.d.ts +66 -0
- package/dist/runtime/hook-file-hooks.d.ts +18 -0
- package/dist/runtime/rules.d.ts +5 -0
- package/dist/runtime/runtime-builder.d.ts +5 -0
- package/dist/runtime/sandbox/subprocess-sandbox.d.ts +19 -0
- package/dist/runtime/session-runtime.d.ts +36 -0
- package/dist/runtime/tool-approval.d.ts +9 -0
- package/dist/runtime/workflows.d.ts +13 -0
- package/dist/server/index.d.ts +47 -0
- package/dist/server/index.js +641 -0
- package/dist/session/default-session-manager.d.ts +77 -0
- package/dist/session/rpc-session-service.d.ts +12 -0
- package/dist/session/runtime-oauth-token-manager.d.ts +28 -0
- package/dist/session/session-artifacts.d.ts +19 -0
- package/dist/session/session-graph.d.ts +15 -0
- package/dist/session/session-host.d.ts +21 -0
- package/dist/session/session-manager.d.ts +50 -0
- package/dist/session/session-manifest.d.ts +30 -0
- package/dist/session/session-service.d.ts +113 -0
- package/dist/session/sqlite-rpc-session-backend.d.ts +30 -0
- package/dist/session/unified-session-persistence-service.d.ts +93 -0
- package/dist/session/workspace-manager.d.ts +28 -0
- package/dist/session/workspace-manifest.d.ts +25 -0
- package/dist/storage/provider-settings-legacy-migration.d.ts +13 -0
- package/dist/storage/provider-settings-manager.d.ts +20 -0
- package/dist/storage/sqlite-session-store.d.ts +29 -0
- package/dist/storage/sqlite-team-store.d.ts +31 -0
- package/dist/storage/team-store.d.ts +2 -0
- package/dist/team/index.d.ts +1 -0
- package/dist/team/projections.d.ts +8 -0
- package/dist/types/common.d.ts +10 -0
- package/dist/types/config.d.ts +37 -0
- package/dist/types/events.d.ts +54 -0
- package/dist/types/provider-settings.d.ts +20 -0
- package/dist/types/sessions.d.ts +9 -0
- package/dist/types/storage.d.ts +37 -0
- package/dist/types/workspace.d.ts +7 -0
- package/dist/types.d.ts +26 -0
- package/package.json +63 -0
- package/src/account/cline-account-service.test.ts +101 -0
- package/src/account/cline-account-service.ts +267 -0
- package/src/account/index.ts +20 -0
- package/src/account/rpc.test.ts +62 -0
- package/src/account/rpc.ts +172 -0
- package/src/account/types.ts +80 -0
- package/src/agents/agent-config-loader.test.ts +234 -0
- package/src/agents/agent-config-loader.ts +107 -0
- package/src/agents/agent-config-parser.ts +191 -0
- package/src/agents/hooks-config-loader.ts +97 -0
- package/src/agents/index.ts +84 -0
- package/src/agents/plugin-config-loader.test.ts +91 -0
- package/src/agents/plugin-config-loader.ts +160 -0
- package/src/agents/plugin-loader.test.ts +102 -0
- package/src/agents/plugin-loader.ts +105 -0
- package/src/agents/plugin-sandbox.test.ts +120 -0
- package/src/agents/plugin-sandbox.ts +471 -0
- package/src/agents/unified-config-file-watcher.test.ts +196 -0
- package/src/agents/unified-config-file-watcher.ts +483 -0
- package/src/agents/user-instruction-config-loader.test.ts +158 -0
- package/src/agents/user-instruction-config-loader.ts +438 -0
- package/src/auth/client.test.ts +40 -0
- package/src/auth/client.ts +25 -0
- package/src/auth/cline.test.ts +130 -0
- package/src/auth/cline.ts +414 -0
- package/src/auth/codex.test.ts +170 -0
- package/src/auth/codex.ts +466 -0
- package/src/auth/oca.test.ts +215 -0
- package/src/auth/oca.ts +546 -0
- package/src/auth/server.ts +216 -0
- package/src/auth/types.ts +78 -0
- package/src/auth/utils.test.ts +128 -0
- package/src/auth/utils.ts +247 -0
- package/src/chat/chat-schema.ts +82 -0
- package/src/default-tools/constants.ts +35 -0
- package/src/default-tools/definitions.test.ts +233 -0
- package/src/default-tools/definitions.ts +632 -0
- package/src/default-tools/executors/apply-patch-parser.ts +520 -0
- package/src/default-tools/executors/apply-patch.ts +359 -0
- package/src/default-tools/executors/bash.ts +205 -0
- package/src/default-tools/executors/editor.ts +231 -0
- package/src/default-tools/executors/file-read.test.ts +25 -0
- package/src/default-tools/executors/file-read.ts +94 -0
- package/src/default-tools/executors/index.ts +75 -0
- package/src/default-tools/executors/search.ts +278 -0
- package/src/default-tools/executors/web-fetch.ts +259 -0
- package/src/default-tools/index.ts +161 -0
- package/src/default-tools/presets.test.ts +63 -0
- package/src/default-tools/presets.ts +168 -0
- package/src/default-tools/schemas.ts +228 -0
- package/src/default-tools/types.ts +324 -0
- package/src/index.ts +119 -0
- package/src/input/file-indexer.d.ts +11 -0
- package/src/input/file-indexer.test.ts +87 -0
- package/src/input/file-indexer.ts +280 -0
- package/src/input/index.ts +7 -0
- package/src/input/mention-enricher.test.ts +82 -0
- package/src/input/mention-enricher.ts +119 -0
- package/src/mcp/config-loader.test.ts +238 -0
- package/src/mcp/config-loader.ts +219 -0
- package/src/mcp/index.ts +26 -0
- package/src/mcp/manager.test.ts +106 -0
- package/src/mcp/manager.ts +262 -0
- package/src/mcp/types.ts +88 -0
- package/src/runtime/hook-file-hooks.test.ts +106 -0
- package/src/runtime/hook-file-hooks.ts +736 -0
- package/src/runtime/index.ts +27 -0
- package/src/runtime/rules.ts +34 -0
- package/src/runtime/runtime-builder.team-persistence.test.ts +203 -0
- package/src/runtime/runtime-builder.test.ts +215 -0
- package/src/runtime/runtime-builder.ts +515 -0
- package/src/runtime/runtime-parity.test.ts +132 -0
- package/src/runtime/sandbox/subprocess-sandbox.ts +207 -0
- package/src/runtime/session-runtime.ts +44 -0
- package/src/runtime/tool-approval.ts +104 -0
- package/src/runtime/workflows.test.ts +119 -0
- package/src/runtime/workflows.ts +54 -0
- package/src/server/index.ts +282 -0
- package/src/session/default-session-manager.e2e.test.ts +354 -0
- package/src/session/default-session-manager.test.ts +816 -0
- package/src/session/default-session-manager.ts +1286 -0
- package/src/session/index.ts +37 -0
- package/src/session/rpc-session-service.ts +189 -0
- package/src/session/runtime-oauth-token-manager.test.ts +137 -0
- package/src/session/runtime-oauth-token-manager.ts +265 -0
- package/src/session/session-artifacts.ts +106 -0
- package/src/session/session-graph.ts +90 -0
- package/src/session/session-host.ts +190 -0
- package/src/session/session-manager.ts +56 -0
- package/src/session/session-manifest.ts +29 -0
- package/src/session/session-service.team-persistence.test.ts +48 -0
- package/src/session/session-service.ts +610 -0
- package/src/session/sqlite-rpc-session-backend.ts +303 -0
- package/src/session/unified-session-persistence-service.ts +781 -0
- package/src/session/workspace-manager.ts +98 -0
- package/src/session/workspace-manifest.ts +100 -0
- package/src/storage/artifact-store.ts +1 -0
- package/src/storage/index.ts +11 -0
- package/src/storage/provider-settings-legacy-migration.test.ts +175 -0
- package/src/storage/provider-settings-legacy-migration.ts +637 -0
- package/src/storage/provider-settings-manager.test.ts +111 -0
- package/src/storage/provider-settings-manager.ts +129 -0
- package/src/storage/session-store.ts +1 -0
- package/src/storage/sqlite-session-store.ts +270 -0
- package/src/storage/sqlite-team-store.ts +443 -0
- package/src/storage/team-store.ts +5 -0
- package/src/team/index.ts +4 -0
- package/src/team/projections.ts +285 -0
- package/src/types/common.ts +14 -0
- package/src/types/config.ts +64 -0
- package/src/types/events.ts +46 -0
- package/src/types/index.ts +24 -0
- package/src/types/provider-settings.ts +43 -0
- package/src/types/sessions.ts +16 -0
- package/src/types/storage.ts +64 -0
- package/src/types/workspace.ts +7 -0
- package/src/types.ts +127 -0
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default Tool Definitions
|
|
3
|
+
*
|
|
4
|
+
* Factory functions for creating the default tools.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createTool, type Tool } from "@clinebot/agents";
|
|
8
|
+
import { validateWithZod, zodToJsonSchema } from "@clinebot/shared";
|
|
9
|
+
import {
|
|
10
|
+
type ApplyPatchInput,
|
|
11
|
+
ApplyPatchInputSchema,
|
|
12
|
+
ApplyPatchInputUnionSchema,
|
|
13
|
+
type AskQuestionInput,
|
|
14
|
+
AskQuestionInputSchema,
|
|
15
|
+
type EditFileInput,
|
|
16
|
+
EditFileInputSchema,
|
|
17
|
+
type FetchWebContentInput,
|
|
18
|
+
FetchWebContentInputSchema,
|
|
19
|
+
type ReadFilesInput,
|
|
20
|
+
ReadFilesInputSchema,
|
|
21
|
+
ReadFilesInputUnionSchema,
|
|
22
|
+
type RunCommandsInput,
|
|
23
|
+
RunCommandsInputSchema,
|
|
24
|
+
RunCommandsInputUnionSchema,
|
|
25
|
+
type SearchCodebaseInput,
|
|
26
|
+
SearchCodebaseInputSchema,
|
|
27
|
+
type SkillsInput,
|
|
28
|
+
SkillsInputSchema,
|
|
29
|
+
} from "./schemas.js";
|
|
30
|
+
import type {
|
|
31
|
+
ApplyPatchExecutor,
|
|
32
|
+
AskQuestionExecutor,
|
|
33
|
+
BashExecutor,
|
|
34
|
+
CreateDefaultToolsOptions,
|
|
35
|
+
DefaultToolsConfig,
|
|
36
|
+
EditorExecutor,
|
|
37
|
+
FileReadExecutor,
|
|
38
|
+
SearchExecutor,
|
|
39
|
+
SkillsExecutor,
|
|
40
|
+
ToolOperationResult,
|
|
41
|
+
WebFetchExecutor,
|
|
42
|
+
} from "./types.js";
|
|
43
|
+
|
|
44
|
+
// =============================================================================
|
|
45
|
+
// Helper Functions
|
|
46
|
+
// =============================================================================
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Format an error into a string message
|
|
50
|
+
*/
|
|
51
|
+
function formatError(error: unknown): string {
|
|
52
|
+
if (error instanceof Error) {
|
|
53
|
+
return error.message;
|
|
54
|
+
}
|
|
55
|
+
return String(error);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Create a timeout-wrapped promise
|
|
60
|
+
*/
|
|
61
|
+
function withTimeout<T>(
|
|
62
|
+
promise: Promise<T>,
|
|
63
|
+
ms: number,
|
|
64
|
+
message: string,
|
|
65
|
+
): Promise<T> {
|
|
66
|
+
return Promise.race([
|
|
67
|
+
promise,
|
|
68
|
+
new Promise<never>((_, reject) => {
|
|
69
|
+
setTimeout(() => reject(new Error(message)), ms);
|
|
70
|
+
}),
|
|
71
|
+
]);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const APPLY_PATCH_TOOL_DESC = `This is a custom utility that makes it more convenient to add, remove, move, or edit code in a single file. \`apply_patch\` effectively allows you to execute a diff/patch against a file, but the format of the diff specification is unique to this task, so pay careful attention to these instructions. To use the \`apply_patch\` command, you should pass a message of the following structure as "input":
|
|
75
|
+
|
|
76
|
+
%%bash
|
|
77
|
+
apply_patch <<"EOF"
|
|
78
|
+
*** Begin Patch
|
|
79
|
+
[YOUR_PATCH]
|
|
80
|
+
*** End Patch
|
|
81
|
+
EOF
|
|
82
|
+
|
|
83
|
+
Where [YOUR_PATCH] is the actual content of your patch, specified in the following V4A diff format.
|
|
84
|
+
|
|
85
|
+
*** [ACTION] File: [path/to/file] -> ACTION can be one of Add, Update, or Delete.
|
|
86
|
+
|
|
87
|
+
In a Add File section, every line of the new file (including blank/empty lines) MUST start with a \`+\` prefix. Do not include any unprefixed lines inside an Add section
|
|
88
|
+
In a Update/Delete section, repeat the following for each snippet of code that needs to be changed:
|
|
89
|
+
[context_before] -> See below for further instructions on context.
|
|
90
|
+
- [old_code] -> Precede the old code with a minus sign.
|
|
91
|
+
+ [new_code] -> Precede the new, replacement code with a plus sign.
|
|
92
|
+
[context_after] -> See below for further instructions on context.
|
|
93
|
+
|
|
94
|
+
For instructions on [context_before] and [context_after]:
|
|
95
|
+
- By default, show 3 lines of code immediately above and 3 lines immediately below each change. If a change is within 3 lines of a previous change, do NOT duplicate the first change’s [context_after] lines in the second change’s [context_before] lines.
|
|
96
|
+
- If 3 lines of context is insufficient to uniquely identify the snippet of code within the file, use the @@ operator to indicate the class or function to which the snippet belongs. For instance, we might have:
|
|
97
|
+
@@ class BaseClass
|
|
98
|
+
[3 lines of pre-context]
|
|
99
|
+
- [old_code]
|
|
100
|
+
+ [new_code]
|
|
101
|
+
[3 lines of post-context]
|
|
102
|
+
|
|
103
|
+
- If a code block is repeated so many times in a class or function such that even a single @@ statement and 3 lines of context cannot uniquely identify the snippet of code, you can use multiple \`@@\` statements to jump to the right context. For instance:
|
|
104
|
+
|
|
105
|
+
@@ class BaseClass
|
|
106
|
+
@@ def method():
|
|
107
|
+
[3 lines of pre-context]
|
|
108
|
+
- [old_code]
|
|
109
|
+
+ [new_code]
|
|
110
|
+
[3 lines of post-context]
|
|
111
|
+
|
|
112
|
+
Note, then, that we do not use line numbers in this diff format, as the context is enough to uniquely identify code. An example of a message that you might pass as "input" to this function, in order to apply a patch, is shown below.
|
|
113
|
+
|
|
114
|
+
%%bash
|
|
115
|
+
apply_patch <<"EOF"
|
|
116
|
+
*** Begin Patch
|
|
117
|
+
*** Update File: pygorithm/searching/binary_search.py
|
|
118
|
+
@@ class BaseClass
|
|
119
|
+
@@ def search():
|
|
120
|
+
- pass
|
|
121
|
+
+ raise NotImplementedError()
|
|
122
|
+
|
|
123
|
+
@@ class Subclass
|
|
124
|
+
@@ def search():
|
|
125
|
+
- pass
|
|
126
|
+
+ raise NotImplementedError()
|
|
127
|
+
|
|
128
|
+
*** End Patch
|
|
129
|
+
EOF`;
|
|
130
|
+
|
|
131
|
+
// =============================================================================
|
|
132
|
+
// Tool Factory Functions
|
|
133
|
+
// =============================================================================
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Create the read_files tool
|
|
137
|
+
*
|
|
138
|
+
* Reads the content of one or more files from the filesystem.
|
|
139
|
+
*/
|
|
140
|
+
export function createReadFilesTool(
|
|
141
|
+
executor: FileReadExecutor,
|
|
142
|
+
config: Pick<DefaultToolsConfig, "fileReadTimeoutMs"> = {},
|
|
143
|
+
): Tool<ReadFilesInput, ToolOperationResult[]> {
|
|
144
|
+
const timeoutMs = config.fileReadTimeoutMs ?? 10000;
|
|
145
|
+
|
|
146
|
+
return createTool<ReadFilesInput, ToolOperationResult[]>({
|
|
147
|
+
name: "read_files",
|
|
148
|
+
description:
|
|
149
|
+
"Read the FULL content of text file at the provided absolute paths. " +
|
|
150
|
+
"Returns file contents or error messages for each path. ",
|
|
151
|
+
inputSchema: zodToJsonSchema(ReadFilesInputSchema),
|
|
152
|
+
timeoutMs: timeoutMs * 2, // Account for multiple files
|
|
153
|
+
retryable: true,
|
|
154
|
+
maxRetries: 1,
|
|
155
|
+
execute: async (input, context) => {
|
|
156
|
+
// Validate input with Zod schema
|
|
157
|
+
const validate = validateWithZod(ReadFilesInputUnionSchema, input);
|
|
158
|
+
const filePaths = Array.isArray(validate)
|
|
159
|
+
? validate
|
|
160
|
+
: typeof validate === "object"
|
|
161
|
+
? validate.file_paths
|
|
162
|
+
: [validate];
|
|
163
|
+
|
|
164
|
+
return Promise.all(
|
|
165
|
+
filePaths.map(async (filePath): Promise<ToolOperationResult> => {
|
|
166
|
+
try {
|
|
167
|
+
const content = await withTimeout(
|
|
168
|
+
executor(filePath, context),
|
|
169
|
+
timeoutMs,
|
|
170
|
+
`File read timed out after ${timeoutMs}ms`,
|
|
171
|
+
);
|
|
172
|
+
return {
|
|
173
|
+
query: filePath,
|
|
174
|
+
result: content,
|
|
175
|
+
success: true,
|
|
176
|
+
};
|
|
177
|
+
} catch (error) {
|
|
178
|
+
const msg = formatError(error);
|
|
179
|
+
return {
|
|
180
|
+
query: filePath,
|
|
181
|
+
result: "",
|
|
182
|
+
error: `Error reading file: ${msg}`,
|
|
183
|
+
success: false,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}),
|
|
187
|
+
);
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Create the search_codebase tool
|
|
194
|
+
*
|
|
195
|
+
* Performs regex pattern searches across the codebase.
|
|
196
|
+
*/
|
|
197
|
+
export function createSearchTool(
|
|
198
|
+
executor: SearchExecutor,
|
|
199
|
+
config: Pick<DefaultToolsConfig, "cwd" | "searchTimeoutMs"> = {},
|
|
200
|
+
): Tool<SearchCodebaseInput, ToolOperationResult[]> {
|
|
201
|
+
const timeoutMs = config.searchTimeoutMs ?? 30000;
|
|
202
|
+
const cwd = config.cwd ?? process.cwd();
|
|
203
|
+
|
|
204
|
+
return createTool<SearchCodebaseInput, ToolOperationResult[]>({
|
|
205
|
+
name: "search_codebase",
|
|
206
|
+
description:
|
|
207
|
+
"Perform regex pattern searches across the codebase. " +
|
|
208
|
+
"Supports multiple parallel searches. " +
|
|
209
|
+
"Use for finding code patterns, function definitions, class names, imports, etc.",
|
|
210
|
+
inputSchema: zodToJsonSchema(SearchCodebaseInputSchema),
|
|
211
|
+
timeoutMs: timeoutMs * 2,
|
|
212
|
+
retryable: true,
|
|
213
|
+
maxRetries: 1,
|
|
214
|
+
execute: async (input, context) => {
|
|
215
|
+
// Validate input with Zod schema
|
|
216
|
+
const validatedInput = validateWithZod(SearchCodebaseInputSchema, input);
|
|
217
|
+
|
|
218
|
+
return Promise.all(
|
|
219
|
+
validatedInput.queries.map(
|
|
220
|
+
async (query): Promise<ToolOperationResult> => {
|
|
221
|
+
try {
|
|
222
|
+
const results = await withTimeout(
|
|
223
|
+
executor(query, cwd, context),
|
|
224
|
+
timeoutMs,
|
|
225
|
+
`Search timed out after ${timeoutMs}ms`,
|
|
226
|
+
);
|
|
227
|
+
// Check if results contain matches
|
|
228
|
+
const hasResults =
|
|
229
|
+
results.length > 0 && !results.includes("No results found");
|
|
230
|
+
return {
|
|
231
|
+
query,
|
|
232
|
+
result: results,
|
|
233
|
+
success: hasResults,
|
|
234
|
+
};
|
|
235
|
+
} catch (error) {
|
|
236
|
+
const msg = formatError(error);
|
|
237
|
+
return {
|
|
238
|
+
query,
|
|
239
|
+
result: "",
|
|
240
|
+
error: `Search failed: ${msg}`,
|
|
241
|
+
success: false,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
),
|
|
246
|
+
);
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Create the run_commands tool
|
|
253
|
+
*
|
|
254
|
+
* Executes shell commands in the project directory.
|
|
255
|
+
*/
|
|
256
|
+
export function createBashTool(
|
|
257
|
+
executor: BashExecutor,
|
|
258
|
+
config: Pick<DefaultToolsConfig, "cwd" | "bashTimeoutMs"> = {},
|
|
259
|
+
): Tool<RunCommandsInput, ToolOperationResult[]> {
|
|
260
|
+
const timeoutMs = config.bashTimeoutMs ?? 30000;
|
|
261
|
+
const cwd = config.cwd ?? process.cwd();
|
|
262
|
+
|
|
263
|
+
return createTool<RunCommandsInput, ToolOperationResult[]>({
|
|
264
|
+
name: "run_commands",
|
|
265
|
+
description:
|
|
266
|
+
"Run shell commands at the root of the project. " +
|
|
267
|
+
"Use for listing files, checking git status, running builds, executing tests, etc. " +
|
|
268
|
+
"Commands should be properly shell-escaped.",
|
|
269
|
+
inputSchema: zodToJsonSchema(RunCommandsInputSchema),
|
|
270
|
+
timeoutMs: timeoutMs * 2,
|
|
271
|
+
retryable: false, // Shell commands often have side effects
|
|
272
|
+
maxRetries: 0,
|
|
273
|
+
execute: async (input, context) => {
|
|
274
|
+
const validate = validateWithZod(RunCommandsInputUnionSchema, input);
|
|
275
|
+
const commands = Array.isArray(validate)
|
|
276
|
+
? validate
|
|
277
|
+
: typeof validate === "object"
|
|
278
|
+
? validate.commands
|
|
279
|
+
: [validate];
|
|
280
|
+
|
|
281
|
+
return Promise.all(
|
|
282
|
+
commands.map(async (command): Promise<ToolOperationResult> => {
|
|
283
|
+
try {
|
|
284
|
+
const output = await withTimeout(
|
|
285
|
+
executor(command, cwd, context),
|
|
286
|
+
timeoutMs,
|
|
287
|
+
`Command timed out after ${timeoutMs}ms`,
|
|
288
|
+
);
|
|
289
|
+
return {
|
|
290
|
+
query: command,
|
|
291
|
+
result: output,
|
|
292
|
+
success: true,
|
|
293
|
+
};
|
|
294
|
+
} catch (error) {
|
|
295
|
+
const msg = formatError(error);
|
|
296
|
+
return {
|
|
297
|
+
query: command,
|
|
298
|
+
result: "",
|
|
299
|
+
error: `Command failed: ${msg}`,
|
|
300
|
+
success: false,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
}),
|
|
304
|
+
);
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Create the fetch_web_content tool
|
|
311
|
+
*
|
|
312
|
+
* Fetches content from URLs and analyzes them using provided prompts.
|
|
313
|
+
*/
|
|
314
|
+
export function createWebFetchTool(
|
|
315
|
+
executor: WebFetchExecutor,
|
|
316
|
+
config: Pick<DefaultToolsConfig, "webFetchTimeoutMs"> = {},
|
|
317
|
+
): Tool<FetchWebContentInput, ToolOperationResult[]> {
|
|
318
|
+
const timeoutMs = config.webFetchTimeoutMs ?? 30000;
|
|
319
|
+
|
|
320
|
+
return createTool<FetchWebContentInput, ToolOperationResult[]>({
|
|
321
|
+
name: "fetch_web_content",
|
|
322
|
+
description:
|
|
323
|
+
"Fetch content from URLs and analyze them using the provided prompts. " +
|
|
324
|
+
"Use for retrieving documentation, API references, or any web content. " +
|
|
325
|
+
"Each request includes a URL and a prompt describing what information to extract.",
|
|
326
|
+
inputSchema: zodToJsonSchema(FetchWebContentInputSchema),
|
|
327
|
+
timeoutMs: timeoutMs * 2,
|
|
328
|
+
retryable: true,
|
|
329
|
+
maxRetries: 2,
|
|
330
|
+
execute: async (input, context) => {
|
|
331
|
+
// Validate input with Zod schema
|
|
332
|
+
const validatedInput = validateWithZod(FetchWebContentInputSchema, input);
|
|
333
|
+
|
|
334
|
+
return Promise.all(
|
|
335
|
+
validatedInput.requests.map(
|
|
336
|
+
async (request): Promise<ToolOperationResult> => {
|
|
337
|
+
try {
|
|
338
|
+
const content = await withTimeout(
|
|
339
|
+
executor(request.url, request.prompt, context),
|
|
340
|
+
timeoutMs,
|
|
341
|
+
`Web fetch timed out after ${timeoutMs}ms`,
|
|
342
|
+
);
|
|
343
|
+
return {
|
|
344
|
+
query: request.url,
|
|
345
|
+
result: content,
|
|
346
|
+
success: true,
|
|
347
|
+
};
|
|
348
|
+
} catch (error) {
|
|
349
|
+
const msg = formatError(error);
|
|
350
|
+
return {
|
|
351
|
+
query: request.url,
|
|
352
|
+
result: "",
|
|
353
|
+
error: `Error fetching web content: ${msg}`,
|
|
354
|
+
success: false,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
),
|
|
359
|
+
);
|
|
360
|
+
},
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Create the apply_patch tool
|
|
366
|
+
*
|
|
367
|
+
* Applies the legacy Cline patch format to one or more files.
|
|
368
|
+
*/
|
|
369
|
+
export function createApplyPatchTool(
|
|
370
|
+
executor: ApplyPatchExecutor,
|
|
371
|
+
config: Pick<DefaultToolsConfig, "cwd" | "applyPatchTimeoutMs"> = {},
|
|
372
|
+
): Tool<ApplyPatchInput, ToolOperationResult> {
|
|
373
|
+
const timeoutMs = config.applyPatchTimeoutMs ?? 30000;
|
|
374
|
+
const cwd = config.cwd ?? process.cwd();
|
|
375
|
+
|
|
376
|
+
return createTool<ApplyPatchInput, ToolOperationResult>({
|
|
377
|
+
name: "apply_patch",
|
|
378
|
+
description: APPLY_PATCH_TOOL_DESC,
|
|
379
|
+
inputSchema: zodToJsonSchema(ApplyPatchInputSchema),
|
|
380
|
+
timeoutMs,
|
|
381
|
+
retryable: false,
|
|
382
|
+
maxRetries: 0,
|
|
383
|
+
execute: async (input, context) => {
|
|
384
|
+
const validate = validateWithZod(ApplyPatchInputUnionSchema, input);
|
|
385
|
+
const patchInput =
|
|
386
|
+
typeof validate === "string" ? validate : validate.input;
|
|
387
|
+
|
|
388
|
+
try {
|
|
389
|
+
const result = await withTimeout(
|
|
390
|
+
executor({ input: patchInput }, cwd, context),
|
|
391
|
+
timeoutMs,
|
|
392
|
+
`apply_patch timed out after ${timeoutMs}ms`,
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
return {
|
|
396
|
+
query: "apply_patch",
|
|
397
|
+
result,
|
|
398
|
+
success: true,
|
|
399
|
+
};
|
|
400
|
+
} catch (error) {
|
|
401
|
+
const msg = formatError(error);
|
|
402
|
+
return {
|
|
403
|
+
query: "apply_patch",
|
|
404
|
+
result: "",
|
|
405
|
+
error: `apply_patch failed: ${msg}`,
|
|
406
|
+
success: false,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Create the editor tool
|
|
415
|
+
*
|
|
416
|
+
* Supports controlled filesystem edits with create, replace, and insert commands.
|
|
417
|
+
*/
|
|
418
|
+
export function createEditorTool(
|
|
419
|
+
executor: EditorExecutor,
|
|
420
|
+
config: Pick<DefaultToolsConfig, "cwd" | "editorTimeoutMs"> = {},
|
|
421
|
+
): Tool<EditFileInput, ToolOperationResult> {
|
|
422
|
+
const timeoutMs = config.editorTimeoutMs ?? 30000;
|
|
423
|
+
const cwd = config.cwd ?? process.cwd();
|
|
424
|
+
|
|
425
|
+
return createTool<EditFileInput, ToolOperationResult>({
|
|
426
|
+
name: "editor",
|
|
427
|
+
description:
|
|
428
|
+
"Edit file using absolute path with create, string replacement, and line insert operations. " +
|
|
429
|
+
"Supported commands: create, str_replace, insert, undo_edit.",
|
|
430
|
+
inputSchema: zodToJsonSchema(EditFileInputSchema),
|
|
431
|
+
timeoutMs,
|
|
432
|
+
retryable: false, // Editing operations are stateful and should not auto-retry
|
|
433
|
+
maxRetries: 0,
|
|
434
|
+
execute: async (input, context) => {
|
|
435
|
+
const validatedInput = validateWithZod(EditFileInputSchema, input);
|
|
436
|
+
|
|
437
|
+
try {
|
|
438
|
+
const result = await withTimeout(
|
|
439
|
+
executor(validatedInput, cwd, context),
|
|
440
|
+
timeoutMs,
|
|
441
|
+
`Editor operation timed out after ${timeoutMs}ms`,
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
return {
|
|
445
|
+
query: `${validatedInput.command}:${validatedInput.path}`,
|
|
446
|
+
result,
|
|
447
|
+
success: true,
|
|
448
|
+
};
|
|
449
|
+
} catch (error) {
|
|
450
|
+
const msg = formatError(error);
|
|
451
|
+
return {
|
|
452
|
+
query: `${validatedInput.command}:${validatedInput.path}`,
|
|
453
|
+
result: "",
|
|
454
|
+
error: `Editor operation failed: ${msg}`,
|
|
455
|
+
success: false,
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Create the skills tool
|
|
464
|
+
*
|
|
465
|
+
* Invokes a configured skill by name and optional arguments.
|
|
466
|
+
*/
|
|
467
|
+
export function createSkillsTool(
|
|
468
|
+
executor: SkillsExecutor,
|
|
469
|
+
config: Pick<DefaultToolsConfig, "skillsTimeoutMs"> = {},
|
|
470
|
+
): Tool<SkillsInput, string> {
|
|
471
|
+
const timeoutMs = config.skillsTimeoutMs ?? 15000;
|
|
472
|
+
|
|
473
|
+
return createTool<SkillsInput, string>({
|
|
474
|
+
name: "skills",
|
|
475
|
+
description:
|
|
476
|
+
"Execute a skill within the main conversation. " +
|
|
477
|
+
"When users ask you to perform tasks, check if any available skills match. " +
|
|
478
|
+
'When users reference a slash command (for example "/commit" or "/review-pr"), invoke this tool. ' +
|
|
479
|
+
'Input: `skill` (required) and optional `args`. Example: `skill: "pdf"`, `skill: "commit", args: "-m \\"Fix bug\\""`, `skill: "review-pr", args: "123"`, `skill: "ms-office-suite:pdf"`. ' +
|
|
480
|
+
"Available skills are listed in system-reminder messages in the conversation. " +
|
|
481
|
+
"When a skill matches the user's request, invoking this tool is a blocking requirement before any other response. " +
|
|
482
|
+
"Never mention a skill without invoking this tool.",
|
|
483
|
+
inputSchema: zodToJsonSchema(SkillsInputSchema),
|
|
484
|
+
timeoutMs,
|
|
485
|
+
retryable: false,
|
|
486
|
+
maxRetries: 0,
|
|
487
|
+
execute: async (input, context) => {
|
|
488
|
+
const validatedInput = validateWithZod(SkillsInputSchema, input);
|
|
489
|
+
return withTimeout(
|
|
490
|
+
executor(validatedInput.skill, validatedInput.args, context),
|
|
491
|
+
timeoutMs,
|
|
492
|
+
`Skills operation timed out after ${timeoutMs}ms`,
|
|
493
|
+
);
|
|
494
|
+
},
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Create the ask_question tool
|
|
500
|
+
*
|
|
501
|
+
* Asks the user a single clarifying question with 2-5 selectable options.
|
|
502
|
+
*/
|
|
503
|
+
export function createAskQuestionTool(
|
|
504
|
+
executor: AskQuestionExecutor,
|
|
505
|
+
config: Pick<DefaultToolsConfig, "askQuestionTimeoutMs"> = {},
|
|
506
|
+
): Tool<AskQuestionInput, string> {
|
|
507
|
+
const timeoutMs = config.askQuestionTimeoutMs ?? 15000;
|
|
508
|
+
|
|
509
|
+
return createTool<AskQuestionInput, string>({
|
|
510
|
+
name: "ask_question",
|
|
511
|
+
description:
|
|
512
|
+
"Ask user a question for clarifying or gathering information needed to complete the task. " +
|
|
513
|
+
"For example, ask the user clarifying questions about a key implementation decision. " +
|
|
514
|
+
"You should only ask one question. " +
|
|
515
|
+
"Provide an array of 2-5 options for the user to choose from. " +
|
|
516
|
+
"Never include an option to toggle to Act mode.",
|
|
517
|
+
inputSchema: zodToJsonSchema(AskQuestionInputSchema),
|
|
518
|
+
timeoutMs,
|
|
519
|
+
retryable: false,
|
|
520
|
+
maxRetries: 0,
|
|
521
|
+
execute: async (input, context) => {
|
|
522
|
+
const validatedInput = validateWithZod(AskQuestionInputSchema, input);
|
|
523
|
+
return withTimeout(
|
|
524
|
+
executor(validatedInput.question, validatedInput.options, context),
|
|
525
|
+
timeoutMs,
|
|
526
|
+
`ask_question timed out after ${timeoutMs}ms`,
|
|
527
|
+
);
|
|
528
|
+
},
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// =============================================================================
|
|
533
|
+
// Default Tools Factory
|
|
534
|
+
// =============================================================================
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Create a set of default tools for an agent
|
|
538
|
+
*
|
|
539
|
+
* This function creates the default tools based on the provided configuration
|
|
540
|
+
* and executors. Only tools that are enabled AND have an executor provided
|
|
541
|
+
* will be included in the returned array.
|
|
542
|
+
*
|
|
543
|
+
* @example
|
|
544
|
+
* ```typescript
|
|
545
|
+
* import { Agent } from "@clinebot/agents"
|
|
546
|
+
* import { createDefaultTools } from "@clinebot/core/server"
|
|
547
|
+
* import * as fs from "fs/promises"
|
|
548
|
+
* import { exec } from "child_process"
|
|
549
|
+
*
|
|
550
|
+
* const tools = createDefaultTools({
|
|
551
|
+
* executors: {
|
|
552
|
+
* readFile: async (path) => fs.readFile(path, "utf-8"),
|
|
553
|
+
* bash: async (cmd, cwd) => {
|
|
554
|
+
* return new Promise((resolve, reject) => {
|
|
555
|
+
* exec(cmd, { cwd }, (err, stdout, stderr) => {
|
|
556
|
+
* if (err) reject(new Error(stderr || err.message))
|
|
557
|
+
* else resolve(stdout)
|
|
558
|
+
* })
|
|
559
|
+
* })
|
|
560
|
+
* },
|
|
561
|
+
* },
|
|
562
|
+
* enableReadFiles: true,
|
|
563
|
+
* enableBash: true,
|
|
564
|
+
* enableSearch: false, // Disabled
|
|
565
|
+
* enableWebFetch: false, // Disabled
|
|
566
|
+
* cwd: "/path/to/project",
|
|
567
|
+
* })
|
|
568
|
+
*
|
|
569
|
+
* const agent = new Agent({
|
|
570
|
+
* // ... provider config
|
|
571
|
+
* tools,
|
|
572
|
+
* })
|
|
573
|
+
* ```
|
|
574
|
+
*/
|
|
575
|
+
export function createDefaultTools(options: CreateDefaultToolsOptions): Tool[] {
|
|
576
|
+
const {
|
|
577
|
+
executors,
|
|
578
|
+
enableReadFiles = true,
|
|
579
|
+
enableSearch = true,
|
|
580
|
+
enableBash = true,
|
|
581
|
+
enableWebFetch = true,
|
|
582
|
+
enableApplyPatch = false,
|
|
583
|
+
enableEditor = true,
|
|
584
|
+
enableSkills = true,
|
|
585
|
+
enableAskQuestion = true,
|
|
586
|
+
...config
|
|
587
|
+
} = options;
|
|
588
|
+
|
|
589
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
590
|
+
const tools: Tool<any, any>[] = [];
|
|
591
|
+
|
|
592
|
+
// Add read_files tool if enabled and executor provided
|
|
593
|
+
if (enableReadFiles && executors.readFile) {
|
|
594
|
+
tools.push(createReadFilesTool(executors.readFile, config));
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// Add search_codebase tool if enabled and executor provided
|
|
598
|
+
if (enableSearch && executors.search) {
|
|
599
|
+
tools.push(createSearchTool(executors.search, config));
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Add run_commands tool if enabled and executor provided
|
|
603
|
+
if (enableBash && executors.bash) {
|
|
604
|
+
tools.push(createBashTool(executors.bash, config));
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// Add fetch_web_content tool if enabled and executor provided
|
|
608
|
+
if (enableWebFetch && executors.webFetch) {
|
|
609
|
+
tools.push(createWebFetchTool(executors.webFetch, config));
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Add editor tool if enabled and executor provided,
|
|
613
|
+
// else check if apply_patch tool is enabled and executor provided
|
|
614
|
+
// NOTE: Do not enable two similar tools at the same time.
|
|
615
|
+
if (enableEditor && executors.editor) {
|
|
616
|
+
tools.push(createEditorTool(executors.editor, config));
|
|
617
|
+
} else if (enableApplyPatch && executors.applyPatch) {
|
|
618
|
+
tools.push(createApplyPatchTool(executors.applyPatch, config));
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// Add skills tool if enabled and executor provided
|
|
622
|
+
if (enableSkills && executors.skills) {
|
|
623
|
+
tools.push(createSkillsTool(executors.skills, config));
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// Add ask_question tool if enabled and executor provided
|
|
627
|
+
if (enableAskQuestion && executors.askQuestion) {
|
|
628
|
+
tools.push(createAskQuestionTool(executors.askQuestion, config));
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return tools;
|
|
632
|
+
}
|