@clinebot/core 0.0.22 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/dist/ClineCore.d.ts +110 -0
  2. package/dist/ClineCore.d.ts.map +1 -0
  3. package/dist/account/cline-account-service.d.ts +2 -1
  4. package/dist/account/cline-account-service.d.ts.map +1 -1
  5. package/dist/account/index.d.ts +1 -1
  6. package/dist/account/index.d.ts.map +1 -1
  7. package/dist/account/rpc.d.ts +3 -1
  8. package/dist/account/rpc.d.ts.map +1 -1
  9. package/dist/account/types.d.ts +3 -0
  10. package/dist/account/types.d.ts.map +1 -1
  11. package/dist/agents/plugin-loader.d.ts.map +1 -1
  12. package/dist/agents/plugin-sandbox-bootstrap.js +17 -17
  13. package/dist/auth/client.d.ts +1 -1
  14. package/dist/auth/client.d.ts.map +1 -1
  15. package/dist/auth/cline.d.ts +1 -1
  16. package/dist/auth/cline.d.ts.map +1 -1
  17. package/dist/auth/codex.d.ts +1 -1
  18. package/dist/auth/codex.d.ts.map +1 -1
  19. package/dist/auth/oca.d.ts +1 -1
  20. package/dist/auth/oca.d.ts.map +1 -1
  21. package/dist/auth/utils.d.ts +2 -2
  22. package/dist/auth/utils.d.ts.map +1 -1
  23. package/dist/index.d.ts +50 -5
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +949 -0
  26. package/dist/providers/local-provider-service.d.ts +4 -4
  27. package/dist/providers/local-provider-service.d.ts.map +1 -1
  28. package/dist/runtime/runtime-builder.d.ts +1 -0
  29. package/dist/runtime/runtime-builder.d.ts.map +1 -1
  30. package/dist/runtime/session-runtime.d.ts +2 -1
  31. package/dist/runtime/session-runtime.d.ts.map +1 -1
  32. package/dist/runtime/team-runtime-registry.d.ts +13 -0
  33. package/dist/runtime/team-runtime-registry.d.ts.map +1 -0
  34. package/dist/session/default-session-manager.d.ts +2 -2
  35. package/dist/session/default-session-manager.d.ts.map +1 -1
  36. package/dist/session/rpc-runtime-ensure.d.ts +53 -0
  37. package/dist/session/rpc-runtime-ensure.d.ts.map +1 -0
  38. package/dist/session/session-config-builder.d.ts +2 -3
  39. package/dist/session/session-config-builder.d.ts.map +1 -1
  40. package/dist/session/session-host.d.ts +8 -18
  41. package/dist/session/session-host.d.ts.map +1 -1
  42. package/dist/session/session-manager.d.ts +1 -1
  43. package/dist/session/session-manager.d.ts.map +1 -1
  44. package/dist/session/session-manifest.d.ts +1 -2
  45. package/dist/session/session-manifest.d.ts.map +1 -1
  46. package/dist/session/unified-session-persistence-service.d.ts +2 -2
  47. package/dist/session/unified-session-persistence-service.d.ts.map +1 -1
  48. package/dist/session/utils/helpers.d.ts +1 -1
  49. package/dist/session/utils/helpers.d.ts.map +1 -1
  50. package/dist/session/utils/types.d.ts +1 -1
  51. package/dist/session/utils/types.d.ts.map +1 -1
  52. package/dist/storage/provider-settings-legacy-migration.d.ts.map +1 -1
  53. package/dist/telemetry/OpenTelemetryProvider.d.ts.map +1 -1
  54. package/dist/telemetry/distinct-id.d.ts +2 -0
  55. package/dist/telemetry/distinct-id.d.ts.map +1 -0
  56. package/dist/telemetry/{opentelemetry.d.ts → index.d.ts} +1 -1
  57. package/dist/telemetry/index.d.ts.map +1 -0
  58. package/dist/telemetry/index.js +28 -0
  59. package/dist/tools/constants.d.ts +1 -1
  60. package/dist/tools/constants.d.ts.map +1 -1
  61. package/dist/tools/definitions.d.ts +3 -3
  62. package/dist/tools/definitions.d.ts.map +1 -1
  63. package/dist/tools/executors/apply-patch.d.ts +1 -1
  64. package/dist/tools/executors/apply-patch.d.ts.map +1 -1
  65. package/dist/tools/executors/bash.d.ts +1 -1
  66. package/dist/tools/executors/bash.d.ts.map +1 -1
  67. package/dist/tools/executors/editor.d.ts +1 -1
  68. package/dist/tools/executors/editor.d.ts.map +1 -1
  69. package/dist/tools/executors/file-read.d.ts +1 -1
  70. package/dist/tools/executors/file-read.d.ts.map +1 -1
  71. package/dist/tools/executors/index.d.ts +14 -14
  72. package/dist/tools/executors/index.d.ts.map +1 -1
  73. package/dist/tools/executors/search.d.ts +1 -1
  74. package/dist/tools/executors/search.d.ts.map +1 -1
  75. package/dist/tools/executors/web-fetch.d.ts +1 -1
  76. package/dist/tools/executors/web-fetch.d.ts.map +1 -1
  77. package/dist/tools/helpers.d.ts +1 -1
  78. package/dist/tools/helpers.d.ts.map +1 -1
  79. package/dist/tools/index.d.ts +10 -10
  80. package/dist/tools/index.d.ts.map +1 -1
  81. package/dist/tools/model-tool-routing.d.ts +1 -1
  82. package/dist/tools/model-tool-routing.d.ts.map +1 -1
  83. package/dist/tools/presets.d.ts +1 -1
  84. package/dist/tools/presets.d.ts.map +1 -1
  85. package/dist/types/common.d.ts +17 -8
  86. package/dist/types/common.d.ts.map +1 -1
  87. package/dist/types/config.d.ts +4 -3
  88. package/dist/types/config.d.ts.map +1 -1
  89. package/dist/types/provider-settings.d.ts +1 -1
  90. package/dist/types/provider-settings.d.ts.map +1 -1
  91. package/dist/types.d.ts +5 -2
  92. package/dist/types.d.ts.map +1 -1
  93. package/dist/version.d.ts +2 -0
  94. package/dist/version.d.ts.map +1 -0
  95. package/package.json +44 -38
  96. package/src/ClineCore.ts +137 -0
  97. package/src/account/cline-account-service.test.ts +101 -0
  98. package/src/account/cline-account-service.ts +300 -0
  99. package/src/account/featurebase-token.test.ts +175 -0
  100. package/src/account/index.ts +23 -0
  101. package/src/account/rpc.test.ts +63 -0
  102. package/src/account/rpc.ts +185 -0
  103. package/src/account/types.ts +102 -0
  104. package/src/agents/agent-config-loader.test.ts +236 -0
  105. package/src/agents/agent-config-loader.ts +108 -0
  106. package/src/agents/agent-config-parser.ts +198 -0
  107. package/src/agents/hooks-config-loader.test.ts +20 -0
  108. package/src/agents/hooks-config-loader.ts +118 -0
  109. package/src/agents/index.ts +85 -0
  110. package/src/agents/plugin-config-loader.test.ts +140 -0
  111. package/src/agents/plugin-config-loader.ts +97 -0
  112. package/src/agents/plugin-loader.test.ts +210 -0
  113. package/src/agents/plugin-loader.ts +175 -0
  114. package/src/agents/plugin-sandbox-bootstrap.ts +448 -0
  115. package/src/agents/plugin-sandbox.test.ts +296 -0
  116. package/src/agents/plugin-sandbox.ts +341 -0
  117. package/src/agents/unified-config-file-watcher.test.ts +196 -0
  118. package/src/agents/unified-config-file-watcher.ts +483 -0
  119. package/src/agents/user-instruction-config-loader.test.ts +158 -0
  120. package/src/agents/user-instruction-config-loader.ts +438 -0
  121. package/src/auth/client.test.ts +40 -0
  122. package/src/auth/client.ts +25 -0
  123. package/src/auth/cline.test.ts +130 -0
  124. package/src/auth/cline.ts +420 -0
  125. package/src/auth/codex.test.ts +170 -0
  126. package/src/auth/codex.ts +491 -0
  127. package/src/auth/oca.test.ts +215 -0
  128. package/src/auth/oca.ts +573 -0
  129. package/src/auth/server.ts +216 -0
  130. package/src/auth/types.ts +81 -0
  131. package/src/auth/utils.test.ts +128 -0
  132. package/src/auth/utils.ts +247 -0
  133. package/src/chat/chat-schema.ts +82 -0
  134. package/src/index.ts +479 -0
  135. package/src/input/file-indexer.d.ts +11 -0
  136. package/src/input/file-indexer.test.ts +127 -0
  137. package/src/input/file-indexer.ts +327 -0
  138. package/src/input/index.ts +7 -0
  139. package/src/input/mention-enricher.test.ts +85 -0
  140. package/src/input/mention-enricher.ts +122 -0
  141. package/src/mcp/config-loader.test.ts +238 -0
  142. package/src/mcp/config-loader.ts +219 -0
  143. package/src/mcp/index.ts +26 -0
  144. package/src/mcp/manager.test.ts +106 -0
  145. package/src/mcp/manager.ts +262 -0
  146. package/src/mcp/types.ts +88 -0
  147. package/src/providers/local-provider-registry.ts +232 -0
  148. package/src/providers/local-provider-service.test.ts +783 -0
  149. package/src/providers/local-provider-service.ts +471 -0
  150. package/src/runtime/commands.test.ts +98 -0
  151. package/src/runtime/commands.ts +83 -0
  152. package/src/runtime/hook-file-hooks.test.ts +237 -0
  153. package/src/runtime/hook-file-hooks.ts +859 -0
  154. package/src/runtime/index.ts +37 -0
  155. package/src/runtime/rules.ts +34 -0
  156. package/src/runtime/runtime-builder.team-persistence.test.ts +245 -0
  157. package/src/runtime/runtime-builder.test.ts +371 -0
  158. package/src/runtime/runtime-builder.ts +631 -0
  159. package/src/runtime/runtime-parity.test.ts +143 -0
  160. package/src/runtime/sandbox/subprocess-sandbox.ts +231 -0
  161. package/src/runtime/session-runtime.ts +49 -0
  162. package/src/runtime/skills.ts +44 -0
  163. package/src/runtime/team-runtime-registry.ts +46 -0
  164. package/src/runtime/tool-approval.ts +104 -0
  165. package/src/runtime/workflows.test.ts +119 -0
  166. package/src/runtime/workflows.ts +45 -0
  167. package/src/session/default-session-manager.e2e.test.ts +384 -0
  168. package/src/session/default-session-manager.test.ts +1931 -0
  169. package/src/session/default-session-manager.ts +1422 -0
  170. package/src/session/file-session-service.ts +280 -0
  171. package/src/session/index.ts +45 -0
  172. package/src/session/rpc-runtime-ensure.ts +521 -0
  173. package/src/session/rpc-session-service.ts +107 -0
  174. package/src/session/rpc-spawn-lease.test.ts +49 -0
  175. package/src/session/rpc-spawn-lease.ts +122 -0
  176. package/src/session/runtime-oauth-token-manager.test.ts +137 -0
  177. package/src/session/runtime-oauth-token-manager.ts +272 -0
  178. package/src/session/session-agent-events.ts +248 -0
  179. package/src/session/session-artifacts.ts +106 -0
  180. package/src/session/session-config-builder.ts +113 -0
  181. package/src/session/session-graph.ts +92 -0
  182. package/src/session/session-host.test.ts +89 -0
  183. package/src/session/session-host.ts +205 -0
  184. package/src/session/session-manager.ts +69 -0
  185. package/src/session/session-manifest.ts +29 -0
  186. package/src/session/session-service.team-persistence.test.ts +48 -0
  187. package/src/session/session-service.ts +673 -0
  188. package/src/session/session-team-coordination.ts +229 -0
  189. package/src/session/session-telemetry.ts +100 -0
  190. package/src/session/sqlite-rpc-session-backend.ts +303 -0
  191. package/src/session/unified-session-persistence-service.test.ts +85 -0
  192. package/src/session/unified-session-persistence-service.ts +994 -0
  193. package/src/session/utils/helpers.ts +139 -0
  194. package/src/session/utils/types.ts +57 -0
  195. package/src/session/utils/usage.ts +32 -0
  196. package/src/session/workspace-manager.ts +98 -0
  197. package/src/session/workspace-manifest.ts +100 -0
  198. package/src/storage/artifact-store.ts +1 -0
  199. package/src/storage/file-team-store.ts +257 -0
  200. package/src/storage/index.ts +11 -0
  201. package/src/storage/provider-settings-legacy-migration.test.ts +424 -0
  202. package/src/storage/provider-settings-legacy-migration.ts +826 -0
  203. package/src/storage/provider-settings-manager.test.ts +191 -0
  204. package/src/storage/provider-settings-manager.ts +152 -0
  205. package/src/storage/session-store.ts +1 -0
  206. package/src/storage/sqlite-session-store.ts +275 -0
  207. package/src/storage/sqlite-team-store.ts +454 -0
  208. package/src/storage/team-store.ts +40 -0
  209. package/src/team/index.ts +4 -0
  210. package/src/team/projections.ts +285 -0
  211. package/src/telemetry/ITelemetryAdapter.ts +94 -0
  212. package/src/telemetry/LoggerTelemetryAdapter.test.ts +42 -0
  213. package/src/telemetry/LoggerTelemetryAdapter.ts +114 -0
  214. package/src/telemetry/OpenTelemetryAdapter.test.ts +157 -0
  215. package/src/telemetry/OpenTelemetryAdapter.ts +348 -0
  216. package/src/telemetry/OpenTelemetryProvider.test.ts +113 -0
  217. package/src/telemetry/OpenTelemetryProvider.ts +325 -0
  218. package/src/telemetry/TelemetryService.test.ts +134 -0
  219. package/src/telemetry/TelemetryService.ts +141 -0
  220. package/src/telemetry/core-events.ts +400 -0
  221. package/src/telemetry/distinct-id.test.ts +57 -0
  222. package/src/telemetry/distinct-id.ts +58 -0
  223. package/src/telemetry/index.ts +20 -0
  224. package/src/tools/constants.ts +35 -0
  225. package/src/tools/definitions.test.ts +704 -0
  226. package/src/tools/definitions.ts +709 -0
  227. package/src/tools/executors/apply-patch-parser.ts +520 -0
  228. package/src/tools/executors/apply-patch.ts +359 -0
  229. package/src/tools/executors/bash.test.ts +87 -0
  230. package/src/tools/executors/bash.ts +207 -0
  231. package/src/tools/executors/editor.test.ts +35 -0
  232. package/src/tools/executors/editor.ts +219 -0
  233. package/src/tools/executors/file-read.test.ts +49 -0
  234. package/src/tools/executors/file-read.ts +110 -0
  235. package/src/tools/executors/index.ts +87 -0
  236. package/src/tools/executors/search.ts +278 -0
  237. package/src/tools/executors/web-fetch.ts +259 -0
  238. package/src/tools/helpers.ts +130 -0
  239. package/src/tools/index.ts +169 -0
  240. package/src/tools/model-tool-routing.test.ts +86 -0
  241. package/src/tools/model-tool-routing.ts +132 -0
  242. package/src/tools/presets.test.ts +62 -0
  243. package/src/tools/presets.ts +168 -0
  244. package/src/tools/schemas.ts +327 -0
  245. package/src/tools/types.ts +329 -0
  246. package/src/types/common.ts +26 -0
  247. package/src/types/config.ts +86 -0
  248. package/src/types/events.ts +74 -0
  249. package/src/types/index.ts +24 -0
  250. package/src/types/provider-settings.ts +43 -0
  251. package/src/types/sessions.ts +16 -0
  252. package/src/types/storage.ts +64 -0
  253. package/src/types/workspace.ts +7 -0
  254. package/src/types.ts +132 -0
  255. package/src/version.ts +3 -0
  256. package/dist/index.node.d.ts +0 -47
  257. package/dist/index.node.d.ts.map +0 -1
  258. package/dist/index.node.js +0 -948
  259. package/dist/telemetry/opentelemetry.d.ts.map +0 -1
  260. package/dist/telemetry/opentelemetry.js +0 -27
@@ -0,0 +1,709 @@
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
+ formatError,
11
+ formatReadFileQuery,
12
+ formatRunCommandQuery,
13
+ getEditorSizeError,
14
+ normalizeReadFileRequests,
15
+ normalizeRunCommandsInput,
16
+ withTimeout,
17
+ } from "./helpers";
18
+ import {
19
+ type ApplyPatchInput,
20
+ ApplyPatchInputSchema,
21
+ ApplyPatchInputUnionSchema,
22
+ type AskQuestionInput,
23
+ AskQuestionInputSchema,
24
+ type EditFileInput,
25
+ EditFileInputSchema,
26
+ type FetchWebContentInput,
27
+ FetchWebContentInputSchema,
28
+ type ReadFilesInput,
29
+ ReadFilesInputSchema,
30
+ type RunCommandsInput,
31
+ RunCommandsInputSchema,
32
+ RunCommandsInputUnionSchema,
33
+ type SearchCodebaseInput,
34
+ SearchCodebaseInputSchema,
35
+ SearchCodebaseUnionInputSchema,
36
+ type SkillsInput,
37
+ SkillsInputSchema,
38
+ type StructuredCommandInput,
39
+ StructuredCommandsInputUnionSchema,
40
+ } from "./schemas";
41
+ import type {
42
+ ApplyPatchExecutor,
43
+ AskQuestionExecutor,
44
+ BashExecutor,
45
+ CreateDefaultToolsOptions,
46
+ DefaultToolsConfig,
47
+ EditorExecutor,
48
+ FileReadExecutor,
49
+ SearchExecutor,
50
+ SkillsExecutorWithMetadata,
51
+ ToolOperationResult,
52
+ WebFetchExecutor,
53
+ } from "./types";
54
+
55
+ // =============================================================================
56
+ // Helper Functions
57
+ // =============================================================================
58
+
59
+ // =============================================================================
60
+ // Tool Factory Functions
61
+ // =============================================================================
62
+
63
+ /**
64
+ * Create the read_files tool
65
+ *
66
+ * Reads the content of one or more files from the filesystem.
67
+ */
68
+ export function createReadFilesTool(
69
+ executor: FileReadExecutor,
70
+ config: Pick<DefaultToolsConfig, "fileReadTimeoutMs"> = {},
71
+ ): Tool<ReadFilesInput, ToolOperationResult[]> {
72
+ const timeoutMs = config.fileReadTimeoutMs ?? 10000;
73
+
74
+ return createTool<ReadFilesInput, ToolOperationResult[]>({
75
+ name: "read_files",
76
+ description:
77
+ "Read the full content of text files at the provided absolute paths, or return only an inclusive one-based line range when start_line/end_line are provided. " +
78
+ "Returns file contents or error messages for each path.",
79
+ inputSchema: zodToJsonSchema(ReadFilesInputSchema),
80
+ timeoutMs: timeoutMs * 2, // Account for multiple files
81
+ retryable: true,
82
+ maxRetries: 1,
83
+ execute: async (input, context) => {
84
+ const requests = normalizeReadFileRequests(input);
85
+
86
+ return Promise.all(
87
+ requests.map(async (request): Promise<ToolOperationResult> => {
88
+ try {
89
+ const content = await withTimeout(
90
+ executor(request, context),
91
+ timeoutMs,
92
+ `File read timed out after ${timeoutMs}ms`,
93
+ );
94
+ return {
95
+ query: formatReadFileQuery(request),
96
+ result: content,
97
+ success: true,
98
+ };
99
+ } catch (error) {
100
+ const msg = formatError(error);
101
+ return {
102
+ query: formatReadFileQuery(request),
103
+ result: "",
104
+ error: `Error reading file: ${msg}`,
105
+ success: false,
106
+ };
107
+ }
108
+ }),
109
+ );
110
+ },
111
+ });
112
+ }
113
+
114
+ /**
115
+ * Create the search_codebase tool
116
+ *
117
+ * Performs regex pattern searches across the codebase.
118
+ */
119
+ export function createSearchTool(
120
+ executor: SearchExecutor,
121
+ config: Pick<DefaultToolsConfig, "cwd" | "searchTimeoutMs"> = {},
122
+ ): Tool<SearchCodebaseInput, ToolOperationResult[]> {
123
+ const timeoutMs = config.searchTimeoutMs ?? 30000;
124
+ const cwd = config.cwd ?? process.cwd();
125
+
126
+ return createTool<SearchCodebaseInput, ToolOperationResult[]>({
127
+ name: "search_codebase",
128
+ description:
129
+ "Perform regex pattern searches across the codebase. " +
130
+ "Supports multiple parallel searches. " +
131
+ "Use for finding code patterns, function definitions, class names, imports, etc.",
132
+ inputSchema: zodToJsonSchema(SearchCodebaseInputSchema),
133
+ timeoutMs: timeoutMs * 2,
134
+ retryable: true,
135
+ maxRetries: 1,
136
+ execute: async (input, context) => {
137
+ // Validate input with Zod schema
138
+ const validate = validateWithZod(SearchCodebaseUnionInputSchema, input);
139
+ const queries = Array.isArray(validate)
140
+ ? validate
141
+ : typeof validate === "object"
142
+ ? Array.isArray(validate.queries)
143
+ ? validate.queries
144
+ : [validate.queries]
145
+ : [validate];
146
+
147
+ return Promise.all(
148
+ queries.map(async (query): Promise<ToolOperationResult> => {
149
+ try {
150
+ const results = await withTimeout(
151
+ executor(query, cwd, context),
152
+ timeoutMs,
153
+ `Search timed out after ${timeoutMs}ms`,
154
+ );
155
+ // Check if results contain matches
156
+ const hasResults =
157
+ results.length > 0 && !results.includes("No results found");
158
+ return {
159
+ query,
160
+ result: results,
161
+ success: hasResults,
162
+ };
163
+ } catch (error) {
164
+ const msg = formatError(error);
165
+ return {
166
+ query,
167
+ result: "",
168
+ error: `Search failed: ${msg}`,
169
+ success: false,
170
+ };
171
+ }
172
+ }),
173
+ );
174
+ },
175
+ });
176
+ }
177
+
178
+ /**
179
+ * Create the run_commands tool
180
+ *
181
+ * Executes shell commands in the project directory.
182
+ */
183
+ export function createBashTool(
184
+ executor: BashExecutor,
185
+ config: Pick<DefaultToolsConfig, "cwd" | "bashTimeoutMs"> = {},
186
+ ): Tool<RunCommandsInput, ToolOperationResult[]> {
187
+ const timeoutMs = config.bashTimeoutMs ?? 30000;
188
+ const cwd = config.cwd ?? process.cwd();
189
+
190
+ return createTool<RunCommandsInput, ToolOperationResult[]>({
191
+ name: "run_commands",
192
+ description:
193
+ "Run shell commands from the root of the workspace. " +
194
+ "Use for listing files, checking git status, running builds, executing tests, etc. " +
195
+ "Commands should be properly shell-escaped.",
196
+ inputSchema: zodToJsonSchema(RunCommandsInputSchema),
197
+ timeoutMs: timeoutMs * 2,
198
+ retryable: false, // Shell commands often have side effects
199
+ maxRetries: 0,
200
+ execute: async (input, context) => {
201
+ const validate = validateWithZod(RunCommandsInputUnionSchema, input);
202
+ const commands = Array.isArray(validate)
203
+ ? validate
204
+ : typeof validate === "object"
205
+ ? Array.isArray(validate.commands)
206
+ ? validate.commands
207
+ : [validate.commands]
208
+ : [validate];
209
+
210
+ return Promise.all(
211
+ commands.map(async (command): Promise<ToolOperationResult> => {
212
+ try {
213
+ const output = await withTimeout(
214
+ executor(command, cwd, context),
215
+ timeoutMs,
216
+ `Command timed out after ${timeoutMs}ms`,
217
+ );
218
+ return {
219
+ query: command,
220
+ result: output,
221
+ success: true,
222
+ };
223
+ } catch (error) {
224
+ const msg = formatError(error);
225
+ return {
226
+ query: command,
227
+ result: "",
228
+ error: `Command failed: ${msg}`,
229
+ success: false,
230
+ };
231
+ }
232
+ }),
233
+ );
234
+ },
235
+ });
236
+ }
237
+
238
+ /**
239
+ * Create the run_commands tool
240
+ *
241
+ * Executes shell commands in the project directory.
242
+ */
243
+ export function createWindowsShellTool(
244
+ executor: BashExecutor,
245
+ config: Pick<DefaultToolsConfig, "cwd" | "bashTimeoutMs"> = {},
246
+ ): Tool<StructuredCommandInput, ToolOperationResult[]> {
247
+ const timeoutMs = config.bashTimeoutMs ?? 30000;
248
+ const cwd = config.cwd ?? process.cwd();
249
+
250
+ return createTool<StructuredCommandInput, ToolOperationResult[]>({
251
+ name: "run_commands",
252
+ description:
253
+ "Run shell commands from the root of the workspacein Windows environment. " +
254
+ "Use for listing files, checking git status, running builds, executing tests, etc. " +
255
+ "Prefer structured { command, args } entries for portability; plain string commands should be properly shell-escaped.",
256
+ inputSchema: zodToJsonSchema(StructuredCommandsInputUnionSchema),
257
+ timeoutMs: timeoutMs * 2,
258
+ retryable: false, // Shell commands often have side effects
259
+ maxRetries: 0,
260
+ execute: async (input, context) => {
261
+ const commands = normalizeRunCommandsInput(input);
262
+
263
+ return Promise.all(
264
+ commands.map(async (command): Promise<ToolOperationResult> => {
265
+ try {
266
+ const output = await withTimeout(
267
+ executor(command, cwd, context),
268
+ timeoutMs,
269
+ `Command timed out after ${timeoutMs}ms`,
270
+ );
271
+ return {
272
+ query: formatRunCommandQuery(command),
273
+ result: output,
274
+ success: true,
275
+ };
276
+ } catch (error) {
277
+ const msg = formatError(error);
278
+ return {
279
+ query: formatRunCommandQuery(command),
280
+ result: "",
281
+ error: `Command failed: ${msg}`,
282
+ success: false,
283
+ };
284
+ }
285
+ }),
286
+ );
287
+ },
288
+ });
289
+ }
290
+
291
+ /**
292
+ * Create the fetch_web_content tool
293
+ *
294
+ * Fetches content from URLs and analyzes them using provided prompts.
295
+ */
296
+ export function createWebFetchTool(
297
+ executor: WebFetchExecutor,
298
+ config: Pick<DefaultToolsConfig, "webFetchTimeoutMs"> = {},
299
+ ): Tool<FetchWebContentInput, ToolOperationResult[]> {
300
+ const timeoutMs = config.webFetchTimeoutMs ?? 30000;
301
+
302
+ return createTool<FetchWebContentInput, ToolOperationResult[]>({
303
+ name: "fetch_web_content",
304
+ description:
305
+ "Fetch content from URLs and analyze them using the provided prompts. " +
306
+ "Use for retrieving documentation, API references, or any web content. " +
307
+ "Each request includes a URL and a prompt describing what information to extract.",
308
+ inputSchema: zodToJsonSchema(FetchWebContentInputSchema),
309
+ timeoutMs: timeoutMs * 2,
310
+ retryable: true,
311
+ maxRetries: 2,
312
+ execute: async (input, context) => {
313
+ // Validate input with Zod schema
314
+ const validatedInput = validateWithZod(FetchWebContentInputSchema, input);
315
+
316
+ return Promise.all(
317
+ validatedInput.requests.map(
318
+ async (request): Promise<ToolOperationResult> => {
319
+ try {
320
+ const content = await withTimeout(
321
+ executor(request.url, request.prompt, context),
322
+ timeoutMs,
323
+ `Web fetch timed out after ${timeoutMs}ms`,
324
+ );
325
+ return {
326
+ query: request.url,
327
+ result: content,
328
+ success: true,
329
+ };
330
+ } catch (error) {
331
+ const msg = formatError(error);
332
+ return {
333
+ query: request.url,
334
+ result: "",
335
+ error: `Error fetching web content: ${msg}`,
336
+ success: false,
337
+ };
338
+ }
339
+ },
340
+ ),
341
+ );
342
+ },
343
+ });
344
+ }
345
+
346
+ 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":
347
+
348
+ %%bash
349
+ apply_patch <<"EOF"
350
+ *** Begin Patch
351
+ [YOUR_PATCH]
352
+ *** End Patch
353
+ EOF
354
+
355
+ Where [YOUR_PATCH] is the actual content of your patch, specified in the following V4A diff format.
356
+
357
+ *** [ACTION] File: [path/to/file] -> ACTION can be one of Add, Update, or Delete.
358
+
359
+ 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
360
+ In a Update/Delete section, repeat the following for each snippet of code that needs to be changed:
361
+ [context_before] -> See below for further instructions on context.
362
+ - [old_code] -> Precede the old code with a minus sign.
363
+ + [new_code] -> Precede the new, replacement code with a plus sign.
364
+ [context_after] -> See below for further instructions on context.
365
+
366
+ For instructions on [context_before] and [context_after]:
367
+ - 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.
368
+ - 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:
369
+ @@ class BaseClass
370
+ [3 lines of pre-context]
371
+ - [old_code]
372
+ + [new_code]
373
+ [3 lines of post-context]
374
+
375
+ - 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:
376
+
377
+ @@ class BaseClass
378
+ @@ def method():
379
+ [3 lines of pre-context]
380
+ - [old_code]
381
+ + [new_code]
382
+ [3 lines of post-context]
383
+
384
+ 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.
385
+
386
+ %%bash
387
+ apply_patch <<"EOF"
388
+ *** Begin Patch
389
+ *** Update File: pygorithm/searching/binary_search.py
390
+ @@ class BaseClass
391
+ @@ def search():
392
+ - pass
393
+ + raise NotImplementedError()
394
+
395
+ @@ class Subclass
396
+ @@ def search():
397
+ - pass
398
+ + raise NotImplementedError()
399
+
400
+ *** End Patch
401
+ EOF`;
402
+
403
+ /**
404
+ * Create the apply_patch tool
405
+ *
406
+ * Applies the legacy Cline patch format to one or more files.
407
+ */
408
+ export function createApplyPatchTool(
409
+ executor: ApplyPatchExecutor,
410
+ config: Pick<DefaultToolsConfig, "cwd" | "applyPatchTimeoutMs"> = {},
411
+ ): Tool<ApplyPatchInput, ToolOperationResult> {
412
+ const timeoutMs = config.applyPatchTimeoutMs ?? 30000;
413
+ const cwd = config.cwd ?? process.cwd();
414
+
415
+ return createTool<ApplyPatchInput, ToolOperationResult>({
416
+ name: "apply_patch",
417
+ description: APPLY_PATCH_TOOL_DESC,
418
+ inputSchema: zodToJsonSchema(ApplyPatchInputSchema),
419
+ timeoutMs,
420
+ retryable: false,
421
+ maxRetries: 0,
422
+ execute: async (input, context) => {
423
+ const validate = validateWithZod(ApplyPatchInputUnionSchema, input);
424
+ const patchInput =
425
+ typeof validate === "string" ? validate : validate.input;
426
+
427
+ try {
428
+ const result = await withTimeout(
429
+ executor({ input: patchInput }, cwd, context),
430
+ timeoutMs,
431
+ `apply_patch timed out after ${timeoutMs}ms`,
432
+ );
433
+
434
+ return {
435
+ query: "apply_patch",
436
+ result,
437
+ success: true,
438
+ };
439
+ } catch (error) {
440
+ const msg = formatError(error);
441
+ return {
442
+ query: "apply_patch",
443
+ result: "",
444
+ error: `apply_patch failed: ${msg}`,
445
+ success: false,
446
+ };
447
+ }
448
+ },
449
+ });
450
+ }
451
+
452
+ /**
453
+ * Create the editor tool
454
+ *
455
+ * Supports controlled filesystem edits with create, replace, and insert commands.
456
+ */
457
+ export function createEditorTool(
458
+ executor: EditorExecutor,
459
+ config: Pick<DefaultToolsConfig, "cwd" | "editorTimeoutMs"> = {},
460
+ ): Tool<EditFileInput, ToolOperationResult> {
461
+ const timeoutMs = config.editorTimeoutMs ?? 30000;
462
+ const cwd = config.cwd ?? process.cwd();
463
+
464
+ return createTool<EditFileInput, ToolOperationResult>({
465
+ name: "editor",
466
+ description:
467
+ "An editor for controlled filesystem edits on the text file at the provided path. " +
468
+ "Provide `insert_line` to insert `new_text` at a specific line number. " +
469
+ "Otherwise, the tool replaces `old_text` with `new_text`, or creates the file with `new_text` if file does not exist. " +
470
+ "Use this tools for making small, precise edits to existing files or creating new files over shell commands.",
471
+
472
+ inputSchema: zodToJsonSchema(EditFileInputSchema),
473
+ timeoutMs,
474
+ retryable: false, // Editing operations are stateful and should not auto-retry
475
+ maxRetries: 0,
476
+ execute: async (input, context) => {
477
+ const validatedInput = validateWithZod(EditFileInputSchema, input);
478
+ const operation = validatedInput.insert_line == null ? "edit" : "insert";
479
+ const sizeError = getEditorSizeError(validatedInput);
480
+
481
+ if (sizeError) {
482
+ return {
483
+ query: `${operation}:${validatedInput.path}`,
484
+ result: "",
485
+ error: sizeError,
486
+ success: false,
487
+ };
488
+ }
489
+
490
+ try {
491
+ const result = await withTimeout(
492
+ executor(validatedInput, cwd, context),
493
+ timeoutMs,
494
+ `Editor operation timed out after ${timeoutMs}ms`,
495
+ );
496
+
497
+ return {
498
+ query: `${operation}:${validatedInput.path}`,
499
+ result,
500
+ success: true,
501
+ };
502
+ } catch (error) {
503
+ const msg = formatError(error);
504
+ return {
505
+ query: `${operation}:${validatedInput.path}`,
506
+ result: "",
507
+ error: `Editor operation failed: ${msg}`,
508
+ success: false,
509
+ };
510
+ }
511
+ },
512
+ });
513
+ }
514
+
515
+ /**
516
+ * Create the skills tool
517
+ *
518
+ * Invokes a configured skill by name and optional arguments.
519
+ */
520
+ export function createSkillsTool(
521
+ executor: SkillsExecutorWithMetadata,
522
+ config: Pick<DefaultToolsConfig, "skillsTimeoutMs"> = {},
523
+ ): Tool<SkillsInput, string> {
524
+ const timeoutMs = config.skillsTimeoutMs ?? 15000;
525
+
526
+ const baseDescription =
527
+ "Execute a skill within the main conversation. " +
528
+ "When users ask you to perform tasks, check if any available skills match. " +
529
+ "When users reference a slash command, invoke it with this tool. " +
530
+ '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"`. ' +
531
+ "When a skill matches the user's request, invoking this tool is a blocking requirement before any other response. " +
532
+ "Never mention a skill without invoking this tool.";
533
+
534
+ const tool = createTool<SkillsInput, string>({
535
+ name: "skills",
536
+ description: baseDescription,
537
+ inputSchema: zodToJsonSchema(SkillsInputSchema),
538
+ timeoutMs,
539
+ retryable: false,
540
+ maxRetries: 0,
541
+ execute: async (input, context) => {
542
+ const validatedInput = validateWithZod(SkillsInputSchema, input);
543
+ return withTimeout(
544
+ executor(
545
+ validatedInput.skill,
546
+ validatedInput.args || undefined,
547
+ context,
548
+ ),
549
+ timeoutMs,
550
+ `Skills operation timed out after ${timeoutMs}ms`,
551
+ );
552
+ },
553
+ });
554
+
555
+ Object.defineProperty(tool, "description", {
556
+ get() {
557
+ const skills = executor.configuredSkills
558
+ ?.filter((s) => !s.disabled)
559
+ .map((s) => s.name);
560
+ if (skills && skills.length > 0) {
561
+ return `${baseDescription} Available skills: ${skills.join(", ")}.`;
562
+ }
563
+ return baseDescription;
564
+ },
565
+ enumerable: true,
566
+ configurable: true,
567
+ });
568
+
569
+ return tool;
570
+ }
571
+
572
+ /**
573
+ * Create the ask_question tool
574
+ *
575
+ * Asks the user a single clarifying question with 2-5 selectable options.
576
+ */
577
+ export function createAskQuestionTool(
578
+ executor: AskQuestionExecutor,
579
+ config: Pick<DefaultToolsConfig, "askQuestionTimeoutMs"> = {},
580
+ ): Tool<AskQuestionInput, string> {
581
+ const timeoutMs = config.askQuestionTimeoutMs ?? 15000;
582
+
583
+ return createTool<AskQuestionInput, string>({
584
+ name: "ask_question",
585
+ description:
586
+ "Ask user a question for clarifying or gathering information needed to complete the task. " +
587
+ "For example, ask the user clarifying questions about a key implementation decision. " +
588
+ "You should only ask one question. " +
589
+ "Provide an array of 2-5 options for the user to choose from. " +
590
+ "Never include an option to toggle to Act mode.",
591
+ inputSchema: zodToJsonSchema(AskQuestionInputSchema),
592
+ timeoutMs,
593
+ retryable: false,
594
+ maxRetries: 0,
595
+ execute: async (input, context) => {
596
+ const validatedInput = validateWithZod(AskQuestionInputSchema, input);
597
+ return withTimeout(
598
+ executor(validatedInput.question, validatedInput.options, context),
599
+ timeoutMs,
600
+ `ask_question timed out after ${timeoutMs}ms`,
601
+ );
602
+ },
603
+ });
604
+ }
605
+
606
+ // =============================================================================
607
+ // Default Tools Factory
608
+ // =============================================================================
609
+
610
+ /**
611
+ * Create a set of default tools for an agent
612
+ *
613
+ * This function creates the default tools based on the provided configuration
614
+ * and executors. Only tools that are enabled AND have an executor provided
615
+ * will be included in the returned array.
616
+ *
617
+ * @example
618
+ * ```typescript
619
+ * import { Agent } from "@clinebot/agents"
620
+ * import { createDefaultTools } from "@clinebot/core"
621
+ * import * as fs from "fs/promises"
622
+ * import { exec } from "child_process"
623
+ *
624
+ * const tools = createDefaultTools({
625
+ * executors: {
626
+ * readFile: async ({ path }) => fs.readFile(path, "utf-8"),
627
+ * bash: async (cmd, cwd) => {
628
+ * return new Promise((resolve, reject) => {
629
+ * exec(cmd, { cwd }, (err, stdout, stderr) => {
630
+ * if (err) reject(new Error(stderr || err.message))
631
+ * else resolve(stdout)
632
+ * })
633
+ * })
634
+ * },
635
+ * },
636
+ * enableReadFiles: true,
637
+ * enableBash: true,
638
+ * enableSearch: false, // Disabled
639
+ * enableWebFetch: false, // Disabled
640
+ * cwd: "/path/to/project",
641
+ * })
642
+ *
643
+ * const agent = new Agent({
644
+ * // ... provider config
645
+ * tools,
646
+ * })
647
+ * ```
648
+ */
649
+ export function createDefaultTools(options: CreateDefaultToolsOptions): Tool[] {
650
+ const {
651
+ executors,
652
+ enableReadFiles = true,
653
+ enableSearch = true,
654
+ enableBash = true,
655
+ enableWebFetch = true,
656
+ enableApplyPatch = false,
657
+ enableEditor = true,
658
+ enableSkills = true,
659
+ enableAskQuestion = true,
660
+ ...config
661
+ } = options;
662
+
663
+ const tools: Tool<any>[] = [];
664
+
665
+ // Add read_files tool if enabled and executor provided
666
+ if (enableReadFiles && executors.readFile) {
667
+ tools.push(createReadFilesTool(executors.readFile, config));
668
+ }
669
+
670
+ // Add search_codebase tool if enabled and executor provided
671
+ if (enableSearch && executors.search) {
672
+ tools.push(createSearchTool(executors.search, config));
673
+ }
674
+
675
+ // Add run_commands tool if enabled and executor provided
676
+ if (enableBash && executors.bash) {
677
+ if (process.platform === "win32") {
678
+ tools.push(createWindowsShellTool(executors.bash, config));
679
+ } else {
680
+ tools.push(createBashTool(executors.bash, config));
681
+ }
682
+ }
683
+
684
+ // Add fetch_web_content tool if enabled and executor provided
685
+ if (enableWebFetch && executors.webFetch) {
686
+ tools.push(createWebFetchTool(executors.webFetch, config));
687
+ }
688
+
689
+ // Add editor tool if enabled and executor provided,
690
+ // else check if apply_patch tool is enabled and executor provided
691
+ // NOTE: Do not enable two similar tools at the same time.
692
+ if (enableEditor && executors.editor) {
693
+ tools.push(createEditorTool(executors.editor, config));
694
+ } else if (enableApplyPatch && executors.applyPatch) {
695
+ tools.push(createApplyPatchTool(executors.applyPatch, config));
696
+ }
697
+
698
+ // Add skills tool if enabled and executor provided
699
+ if (enableSkills && executors.skills) {
700
+ tools.push(createSkillsTool(executors.skills, config));
701
+ }
702
+
703
+ // Add ask_question tool if enabled and executor provided
704
+ if (enableAskQuestion && executors.askQuestion) {
705
+ tools.push(createAskQuestionTool(executors.askQuestion, config));
706
+ }
707
+
708
+ return tools;
709
+ }