beth-copilot 1.0.18 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. package/CHANGELOG.md +41 -28
  2. package/README.md +87 -247
  3. package/bin/cli.js +158 -358
  4. package/dist/__tests__/smoke.test.d.ts +8 -0
  5. package/dist/__tests__/smoke.test.d.ts.map +1 -0
  6. package/dist/__tests__/smoke.test.js +49 -0
  7. package/dist/__tests__/smoke.test.js.map +1 -0
  8. package/dist/cli/commands/beads.e2e.test.d.ts +13 -0
  9. package/dist/cli/commands/beads.e2e.test.d.ts.map +1 -0
  10. package/dist/cli/commands/beads.e2e.test.js +526 -0
  11. package/dist/cli/commands/beads.e2e.test.js.map +1 -0
  12. package/dist/cli/commands/cli-edge-cases.e2e.test.d.ts +32 -0
  13. package/dist/cli/commands/cli-edge-cases.e2e.test.d.ts.map +1 -0
  14. package/dist/cli/commands/cli-edge-cases.e2e.test.js +162 -0
  15. package/dist/cli/commands/cli-edge-cases.e2e.test.js.map +1 -0
  16. package/dist/cli/commands/close.d.ts +89 -0
  17. package/dist/cli/commands/close.d.ts.map +1 -0
  18. package/dist/cli/commands/close.e2e.test.d.ts +27 -0
  19. package/dist/cli/commands/close.e2e.test.d.ts.map +1 -0
  20. package/dist/cli/commands/close.e2e.test.js +252 -0
  21. package/dist/cli/commands/close.e2e.test.js.map +1 -0
  22. package/dist/cli/commands/close.js +309 -0
  23. package/dist/cli/commands/close.js.map +1 -0
  24. package/dist/cli/commands/close.test.d.ts +15 -0
  25. package/dist/cli/commands/close.test.d.ts.map +1 -0
  26. package/dist/cli/commands/close.test.js +634 -0
  27. package/dist/cli/commands/close.test.js.map +1 -0
  28. package/dist/cli/commands/doctor.d.ts +23 -0
  29. package/dist/cli/commands/doctor.d.ts.map +1 -1
  30. package/dist/cli/commands/doctor.js +93 -0
  31. package/dist/cli/commands/doctor.js.map +1 -1
  32. package/dist/cli/commands/doctor.test.js +209 -0
  33. package/dist/cli/commands/doctor.test.js.map +1 -1
  34. package/dist/cli/commands/framework-isolation.test.d.ts +30 -0
  35. package/dist/cli/commands/framework-isolation.test.d.ts.map +1 -0
  36. package/dist/cli/commands/framework-isolation.test.js +119 -0
  37. package/dist/cli/commands/framework-isolation.test.js.map +1 -0
  38. package/dist/cli/commands/help.e2e.test.js +4 -4
  39. package/dist/cli/commands/help.e2e.test.js.map +1 -1
  40. package/dist/cli/commands/init-logic.e2e.test.d.ts +37 -0
  41. package/dist/cli/commands/init-logic.e2e.test.d.ts.map +1 -0
  42. package/dist/cli/commands/init-logic.e2e.test.js +305 -0
  43. package/dist/cli/commands/init-logic.e2e.test.js.map +1 -0
  44. package/dist/cli/commands/land.d.ts +142 -0
  45. package/dist/cli/commands/land.d.ts.map +1 -0
  46. package/dist/cli/commands/land.js +647 -0
  47. package/dist/cli/commands/land.js.map +1 -0
  48. package/dist/cli/commands/land.test.d.ts +20 -0
  49. package/dist/cli/commands/land.test.d.ts.map +1 -0
  50. package/dist/cli/commands/land.test.js +622 -0
  51. package/dist/cli/commands/land.test.js.map +1 -0
  52. package/dist/cli/commands/mcp.e2e.test.js +22 -29
  53. package/dist/cli/commands/mcp.e2e.test.js.map +1 -1
  54. package/dist/cli/commands/pipeline.e2e.test.js +20 -20
  55. package/dist/cli/commands/pipeline.e2e.test.js.map +1 -1
  56. package/dist/cli/commands/pre-push-guard.d.ts +84 -0
  57. package/dist/cli/commands/pre-push-guard.d.ts.map +1 -0
  58. package/dist/cli/commands/pre-push-guard.e2e.test.d.ts +24 -0
  59. package/dist/cli/commands/pre-push-guard.e2e.test.d.ts.map +1 -0
  60. package/dist/cli/commands/pre-push-guard.e2e.test.js +171 -0
  61. package/dist/cli/commands/pre-push-guard.e2e.test.js.map +1 -0
  62. package/dist/cli/commands/pre-push-guard.js +257 -0
  63. package/dist/cli/commands/pre-push-guard.js.map +1 -0
  64. package/dist/cli/commands/pre-push-guard.test.d.ts +15 -0
  65. package/dist/cli/commands/pre-push-guard.test.d.ts.map +1 -0
  66. package/dist/cli/commands/pre-push-guard.test.js +397 -0
  67. package/dist/cli/commands/pre-push-guard.test.js.map +1 -0
  68. package/dist/cli/commands/quickstart-expanded.e2e.test.d.ts +23 -0
  69. package/dist/cli/commands/quickstart-expanded.e2e.test.d.ts.map +1 -0
  70. package/dist/cli/commands/quickstart-expanded.e2e.test.js +179 -0
  71. package/dist/cli/commands/quickstart-expanded.e2e.test.js.map +1 -0
  72. package/dist/cli/commands/quickstart.d.ts.map +1 -1
  73. package/dist/cli/commands/quickstart.js +7 -23
  74. package/dist/cli/commands/quickstart.js.map +1 -1
  75. package/dist/cli/commands/quickstart.test.js +40 -67
  76. package/dist/cli/commands/quickstart.test.js.map +1 -1
  77. package/dist/core/agents/suite.test.js +4 -2
  78. package/dist/core/agents/suite.test.js.map +1 -1
  79. package/dist/core/agents/tools.test.js +5 -1
  80. package/dist/core/agents/tools.test.js.map +1 -1
  81. package/dist/index.d.ts +3 -10
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +5 -10
  84. package/dist/index.js.map +1 -1
  85. package/package.json +15 -9
  86. package/sbom.json +2011 -819
  87. package/templates/.github/agents/beth.agent.md +220 -66
  88. package/templates/.github/agents/developer.agent.md +53 -90
  89. package/templates/.github/agents/product-manager.agent.md +15 -68
  90. package/templates/.github/agents/researcher.agent.md +20 -71
  91. package/templates/.github/agents/security-reviewer.agent.md +29 -81
  92. package/templates/.github/agents/tester.agent.md +40 -69
  93. package/templates/.github/agents/ux-designer.agent.md +20 -74
  94. package/templates/.github/copilot-instructions.md +217 -225
  95. package/templates/AGENTS.md +108 -20
  96. package/templates/mcp.json.example +0 -3
  97. package/dist/cli/commands/client-config.d.ts +0 -31
  98. package/dist/cli/commands/client-config.d.ts.map +0 -1
  99. package/dist/cli/commands/client-config.e2e.test.d.ts +0 -15
  100. package/dist/cli/commands/client-config.e2e.test.d.ts.map +0 -1
  101. package/dist/cli/commands/client-config.e2e.test.js +0 -556
  102. package/dist/cli/commands/client-config.e2e.test.js.map +0 -1
  103. package/dist/cli/commands/client-config.js +0 -73
  104. package/dist/cli/commands/client-config.js.map +0 -1
  105. package/dist/cli/commands/client-config.test.d.ts +0 -6
  106. package/dist/cli/commands/client-config.test.d.ts.map +0 -1
  107. package/dist/cli/commands/client-config.test.js +0 -133
  108. package/dist/cli/commands/client-config.test.js.map +0 -1
  109. package/dist/cli/commands/init-quickstart.e2e.test.d.ts +0 -11
  110. package/dist/cli/commands/init-quickstart.e2e.test.d.ts.map +0 -1
  111. package/dist/cli/commands/init-quickstart.e2e.test.js +0 -221
  112. package/dist/cli/commands/init-quickstart.e2e.test.js.map +0 -1
  113. package/dist/core/context.d.ts +0 -171
  114. package/dist/core/context.d.ts.map +0 -1
  115. package/dist/core/context.js +0 -353
  116. package/dist/core/context.js.map +0 -1
  117. package/dist/core/context.test.d.ts +0 -8
  118. package/dist/core/context.test.d.ts.map +0 -1
  119. package/dist/core/context.test.js +0 -253
  120. package/dist/core/context.test.js.map +0 -1
  121. package/dist/core/handoffs.d.ts +0 -151
  122. package/dist/core/handoffs.d.ts.map +0 -1
  123. package/dist/core/handoffs.js +0 -220
  124. package/dist/core/handoffs.js.map +0 -1
  125. package/dist/core/handoffs.test.d.ts +0 -8
  126. package/dist/core/handoffs.test.d.ts.map +0 -1
  127. package/dist/core/handoffs.test.js +0 -231
  128. package/dist/core/handoffs.test.js.map +0 -1
  129. package/dist/core/orchestrator.d.ts +0 -246
  130. package/dist/core/orchestrator.d.ts.map +0 -1
  131. package/dist/core/orchestrator.js +0 -514
  132. package/dist/core/orchestrator.js.map +0 -1
  133. package/dist/core/orchestrator.test.d.ts +0 -8
  134. package/dist/core/orchestrator.test.d.ts.map +0 -1
  135. package/dist/core/orchestrator.test.js +0 -517
  136. package/dist/core/orchestrator.test.js.map +0 -1
  137. package/dist/core/router.d.ts +0 -102
  138. package/dist/core/router.d.ts.map +0 -1
  139. package/dist/core/router.js +0 -178
  140. package/dist/core/router.js.map +0 -1
  141. package/dist/core/router.test.d.ts +0 -8
  142. package/dist/core/router.test.d.ts.map +0 -1
  143. package/dist/core/router.test.js +0 -215
  144. package/dist/core/router.test.js.map +0 -1
  145. package/dist/init.test.js +0 -288
  146. package/dist/providers/azure.d.ts +0 -147
  147. package/dist/providers/azure.d.ts.map +0 -1
  148. package/dist/providers/azure.js +0 -491
  149. package/dist/providers/azure.js.map +0 -1
  150. package/dist/providers/azure.test.d.ts +0 -11
  151. package/dist/providers/azure.test.d.ts.map +0 -1
  152. package/dist/providers/azure.test.js +0 -330
  153. package/dist/providers/azure.test.js.map +0 -1
  154. package/dist/providers/config.d.ts +0 -87
  155. package/dist/providers/config.d.ts.map +0 -1
  156. package/dist/providers/config.js +0 -193
  157. package/dist/providers/config.js.map +0 -1
  158. package/dist/providers/config.test.d.ts +0 -7
  159. package/dist/providers/config.test.d.ts.map +0 -1
  160. package/dist/providers/config.test.js +0 -370
  161. package/dist/providers/config.test.js.map +0 -1
  162. package/dist/providers/index.d.ts +0 -18
  163. package/dist/providers/index.d.ts.map +0 -1
  164. package/dist/providers/index.js +0 -14
  165. package/dist/providers/index.js.map +0 -1
  166. package/dist/providers/interface.d.ts +0 -191
  167. package/dist/providers/interface.d.ts.map +0 -1
  168. package/dist/providers/interface.js +0 -94
  169. package/dist/providers/interface.js.map +0 -1
  170. package/dist/providers/retry.d.ts +0 -128
  171. package/dist/providers/retry.d.ts.map +0 -1
  172. package/dist/providers/retry.js +0 -205
  173. package/dist/providers/retry.js.map +0 -1
  174. package/dist/providers/retry.test.d.ts +0 -7
  175. package/dist/providers/retry.test.d.ts.map +0 -1
  176. package/dist/providers/retry.test.js +0 -439
  177. package/dist/providers/retry.test.js.map +0 -1
  178. package/dist/providers/streaming.d.ts +0 -157
  179. package/dist/providers/streaming.d.ts.map +0 -1
  180. package/dist/providers/streaming.js +0 -233
  181. package/dist/providers/streaming.js.map +0 -1
  182. package/dist/providers/streaming.test.d.ts +0 -7
  183. package/dist/providers/streaming.test.d.ts.map +0 -1
  184. package/dist/providers/streaming.test.js +0 -372
  185. package/dist/providers/streaming.test.js.map +0 -1
  186. package/dist/providers/types.d.ts +0 -209
  187. package/dist/providers/types.d.ts.map +0 -1
  188. package/dist/providers/types.js +0 -53
  189. package/dist/providers/types.js.map +0 -1
  190. package/dist/providers/types.test.d.ts +0 -7
  191. package/dist/providers/types.test.d.ts.map +0 -1
  192. package/dist/providers/types.test.js +0 -141
  193. package/dist/providers/types.test.js.map +0 -1
  194. package/dist/tools/cli/beads.d.ts +0 -27
  195. package/dist/tools/cli/beads.d.ts.map +0 -1
  196. package/dist/tools/cli/beads.js +0 -172
  197. package/dist/tools/cli/beads.js.map +0 -1
  198. package/dist/tools/cli/beads.test.d.ts +0 -8
  199. package/dist/tools/cli/beads.test.d.ts.map +0 -1
  200. package/dist/tools/cli/beads.test.js +0 -264
  201. package/dist/tools/cli/beads.test.js.map +0 -1
  202. package/dist/tools/cli/editFile.d.ts +0 -17
  203. package/dist/tools/cli/editFile.d.ts.map +0 -1
  204. package/dist/tools/cli/editFile.js +0 -125
  205. package/dist/tools/cli/editFile.js.map +0 -1
  206. package/dist/tools/cli/editFile.test.d.ts +0 -8
  207. package/dist/tools/cli/editFile.test.d.ts.map +0 -1
  208. package/dist/tools/cli/editFile.test.js +0 -177
  209. package/dist/tools/cli/editFile.test.js.map +0 -1
  210. package/dist/tools/cli/readFile.d.ts +0 -25
  211. package/dist/tools/cli/readFile.d.ts.map +0 -1
  212. package/dist/tools/cli/readFile.js +0 -118
  213. package/dist/tools/cli/readFile.js.map +0 -1
  214. package/dist/tools/cli/readFile.test.d.ts +0 -8
  215. package/dist/tools/cli/readFile.test.d.ts.map +0 -1
  216. package/dist/tools/cli/readFile.test.js +0 -194
  217. package/dist/tools/cli/readFile.test.js.map +0 -1
  218. package/dist/tools/cli/search.d.ts +0 -16
  219. package/dist/tools/cli/search.d.ts.map +0 -1
  220. package/dist/tools/cli/search.js +0 -261
  221. package/dist/tools/cli/search.js.map +0 -1
  222. package/dist/tools/cli/search.test.d.ts +0 -8
  223. package/dist/tools/cli/search.test.d.ts.map +0 -1
  224. package/dist/tools/cli/search.test.js +0 -172
  225. package/dist/tools/cli/search.test.js.map +0 -1
  226. package/dist/tools/cli/subagent.d.ts +0 -43
  227. package/dist/tools/cli/subagent.d.ts.map +0 -1
  228. package/dist/tools/cli/subagent.js +0 -99
  229. package/dist/tools/cli/subagent.js.map +0 -1
  230. package/dist/tools/cli/subagent.test.d.ts +0 -8
  231. package/dist/tools/cli/subagent.test.d.ts.map +0 -1
  232. package/dist/tools/cli/subagent.test.js +0 -190
  233. package/dist/tools/cli/subagent.test.js.map +0 -1
  234. package/dist/tools/cli/terminal.d.ts +0 -19
  235. package/dist/tools/cli/terminal.d.ts.map +0 -1
  236. package/dist/tools/cli/terminal.js +0 -164
  237. package/dist/tools/cli/terminal.js.map +0 -1
  238. package/dist/tools/cli/terminal.test.d.ts +0 -8
  239. package/dist/tools/cli/terminal.test.d.ts.map +0 -1
  240. package/dist/tools/cli/terminal.test.js +0 -161
  241. package/dist/tools/cli/terminal.test.js.map +0 -1
  242. package/dist/tools/index.d.ts +0 -25
  243. package/dist/tools/index.d.ts.map +0 -1
  244. package/dist/tools/index.js +0 -41
  245. package/dist/tools/index.js.map +0 -1
  246. package/dist/tools/interface.d.ts +0 -64
  247. package/dist/tools/interface.d.ts.map +0 -1
  248. package/dist/tools/interface.js +0 -37
  249. package/dist/tools/interface.js.map +0 -1
  250. package/dist/tools/interface.test.d.ts +0 -7
  251. package/dist/tools/interface.test.d.ts.map +0 -1
  252. package/dist/tools/interface.test.js +0 -179
  253. package/dist/tools/interface.test.js.map +0 -1
  254. package/dist/tools/mcp/bridge.d.ts +0 -48
  255. package/dist/tools/mcp/bridge.d.ts.map +0 -1
  256. package/dist/tools/mcp/bridge.js +0 -128
  257. package/dist/tools/mcp/bridge.js.map +0 -1
  258. package/dist/tools/mcp/bridge.test.d.ts +0 -8
  259. package/dist/tools/mcp/bridge.test.d.ts.map +0 -1
  260. package/dist/tools/mcp/bridge.test.js +0 -300
  261. package/dist/tools/mcp/bridge.test.js.map +0 -1
  262. package/dist/tools/mcp/client.d.ts +0 -135
  263. package/dist/tools/mcp/client.d.ts.map +0 -1
  264. package/dist/tools/mcp/client.js +0 -263
  265. package/dist/tools/mcp/client.js.map +0 -1
  266. package/dist/tools/mcp/client.test.d.ts +0 -8
  267. package/dist/tools/mcp/client.test.d.ts.map +0 -1
  268. package/dist/tools/mcp/client.test.js +0 -390
  269. package/dist/tools/mcp/client.test.js.map +0 -1
  270. package/dist/tools/registry.d.ts +0 -82
  271. package/dist/tools/registry.d.ts.map +0 -1
  272. package/dist/tools/registry.js +0 -99
  273. package/dist/tools/registry.js.map +0 -1
  274. package/dist/tools/registry.test.d.ts +0 -7
  275. package/dist/tools/registry.test.d.ts.map +0 -1
  276. package/dist/tools/registry.test.js +0 -199
  277. package/dist/tools/registry.test.js.map +0 -1
  278. package/dist/tools/suite.test.d.ts +0 -11
  279. package/dist/tools/suite.test.d.ts.map +0 -1
  280. package/dist/tools/suite.test.js +0 -119
  281. package/dist/tools/suite.test.js.map +0 -1
  282. package/dist/tools/types.d.ts +0 -75
  283. package/dist/tools/types.d.ts.map +0 -1
  284. package/dist/tools/types.js +0 -30
  285. package/dist/tools/types.js.map +0 -1
  286. package/dist/tools/types.test.d.ts +0 -7
  287. package/dist/tools/types.test.d.ts.map +0 -1
  288. package/dist/tools/types.test.js +0 -178
  289. package/dist/tools/types.test.js.map +0 -1
  290. package/templates/.vscode/mcp.json +0 -20
  291. package/templates/CLAUDE.md +0 -129
@@ -1,261 +0,0 @@
1
- /**
2
- * Search Tool
3
- *
4
- * Searches file contents using ripgrep (preferred) or a Node.js fallback.
5
- * Validates search paths against traversal attacks and checks permissions
6
- * before reading any files.
7
- */
8
- import { execFile } from 'node:child_process';
9
- import { readdir, readFile } from 'node:fs/promises';
10
- import { join, resolve, relative } from 'node:path';
11
- import { containsTraversal } from '../../lib/pathValidation.js';
12
- import { ToolError } from '../types.js';
13
- /** Default maximum number of results to return */
14
- const DEFAULT_MAX_RESULTS = 50;
15
- /** Input schema for the search tool */
16
- const inputSchema = {
17
- type: 'object',
18
- properties: {
19
- query: {
20
- type: 'string',
21
- description: 'Search pattern (plain text or regex)',
22
- },
23
- isRegexp: {
24
- type: 'boolean',
25
- description: 'Whether query is a regular expression (default: false)',
26
- },
27
- includePattern: {
28
- type: 'string',
29
- description: 'Glob pattern to filter files (e.g., "**/*.ts")',
30
- },
31
- path: {
32
- type: 'string',
33
- description: 'Directory to search in (defaults to working directory)',
34
- },
35
- maxResults: {
36
- type: 'number',
37
- description: 'Maximum number of results to return (default: 50)',
38
- },
39
- },
40
- required: ['query'],
41
- };
42
- /**
43
- * Validate and resolve the search path, ensuring it stays within workingDir.
44
- *
45
- * @param searchPath - User-provided search path (may be relative or absolute)
46
- * @param workingDir - The allowed root directory
47
- * @param toolName - Name of the calling tool (for error reporting)
48
- * @returns The resolved absolute path
49
- * @throws {ToolError} If the path escapes workingDir or contains traversal
50
- */
51
- function validateSearchPath(searchPath, workingDir, toolName) {
52
- if (containsTraversal(searchPath)) {
53
- throw new ToolError('Search path contains directory traversal sequences', 'INVALID_INPUT', toolName);
54
- }
55
- const resolved = resolve(workingDir, searchPath);
56
- const normalizedWorking = resolve(workingDir);
57
- if (!resolved.startsWith(normalizedWorking)) {
58
- throw new ToolError('Search path is outside the working directory', 'INVALID_INPUT', toolName);
59
- }
60
- return resolved;
61
- }
62
- /**
63
- * Attempt to search using ripgrep (rg).
64
- *
65
- * @returns Search output string, or null if rg is not available
66
- */
67
- function searchWithRipgrep(query, isRegexp, includePattern, searchPath, maxResults, signal) {
68
- return new Promise((resolvePromise) => {
69
- const args = [
70
- '--no-heading',
71
- '--line-number',
72
- '--max-count', String(maxResults),
73
- ];
74
- if (isRegexp) {
75
- args.push('-e', query);
76
- }
77
- else {
78
- args.push('--fixed-strings', query);
79
- }
80
- if (includePattern) {
81
- args.push('--glob', includePattern);
82
- }
83
- args.push(searchPath);
84
- const child = execFile('rg', args, { maxBuffer: 1024 * 1024, signal }, (error, stdout) => {
85
- if (error) {
86
- const nodeErr = error;
87
- // Exit code 1 means no matches — that's fine
88
- if (nodeErr.code === 'ENOENT' || nodeErr.message?.includes('ENOENT')) {
89
- // rg not found
90
- resolvePromise(null);
91
- return;
92
- }
93
- if ('code' in error && error.code === 1) {
94
- // rg exit code 1 = no matches
95
- resolvePromise('');
96
- return;
97
- }
98
- // Other errors: treat as rg not available
99
- resolvePromise(null);
100
- return;
101
- }
102
- resolvePromise(stdout);
103
- });
104
- // Handle abort to clean up child process
105
- if (signal) {
106
- signal.addEventListener('abort', () => {
107
- child.kill();
108
- }, { once: true });
109
- }
110
- });
111
- }
112
- /**
113
- * Check whether a filename matches a simple glob pattern.
114
- * Supports patterns like "*.ts", "**\/*.ts", "*.{ts,js}".
115
- */
116
- function matchesGlob(filePath, pattern) {
117
- // Convert glob to regex
118
- let regexStr = pattern
119
- .replace(/\*\*\//g, '(.+/)?') // **/ matches any directory depth
120
- .replace(/\*/g, '[^/]*') // * matches anything except /
121
- .replace(/\?/g, '[^/]') // ? matches single char
122
- .replace(/\{([^}]+)\}/g, (_match, group) => {
123
- // {ts,js} => (ts|js)
124
- return '(' + group.split(',').join('|') + ')';
125
- });
126
- regexStr = '^' + regexStr + '$';
127
- try {
128
- const regex = new RegExp(regexStr);
129
- return regex.test(filePath);
130
- }
131
- catch {
132
- return false;
133
- }
134
- }
135
- /**
136
- * Recursively collect all files under a directory.
137
- */
138
- async function collectFiles(dir) {
139
- const files = [];
140
- const entries = await readdir(dir, { withFileTypes: true });
141
- for (const entry of entries) {
142
- const fullPath = join(dir, entry.name);
143
- if (entry.isDirectory()) {
144
- // Skip hidden directories and node_modules
145
- if (entry.name.startsWith('.') || entry.name === 'node_modules') {
146
- continue;
147
- }
148
- const subFiles = await collectFiles(fullPath);
149
- files.push(...subFiles);
150
- }
151
- else if (entry.isFile()) {
152
- files.push(fullPath);
153
- }
154
- }
155
- return files;
156
- }
157
- /**
158
- * Fallback Node.js search when ripgrep is not available.
159
- */
160
- async function searchWithNode(query, isRegexp, includePattern, searchPath, maxResults) {
161
- const files = await collectFiles(searchPath);
162
- const results = [];
163
- let pattern;
164
- if (isRegexp) {
165
- pattern = new RegExp(query);
166
- }
167
- else {
168
- // Escape special regex characters for literal search
169
- const escaped = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
170
- pattern = new RegExp(escaped);
171
- }
172
- for (const filePath of files) {
173
- if (results.length >= maxResults)
174
- break;
175
- // Apply include pattern filter
176
- if (includePattern) {
177
- const relPath = relative(searchPath, filePath);
178
- if (!matchesGlob(relPath, includePattern)) {
179
- continue;
180
- }
181
- }
182
- let contents;
183
- try {
184
- contents = await readFile(filePath, 'utf-8');
185
- }
186
- catch {
187
- // Skip files we can't read (binary, permission denied, etc.)
188
- continue;
189
- }
190
- const lines = contents.split('\n');
191
- for (let i = 0; i < lines.length; i++) {
192
- if (results.length >= maxResults)
193
- break;
194
- if (pattern.test(lines[i])) {
195
- results.push(`${filePath}:${i + 1}:${lines[i]}`);
196
- }
197
- }
198
- }
199
- return results.join('\n');
200
- }
201
- /**
202
- * Search tool implementation.
203
- *
204
- * Searches file contents using ripgrep when available, falling back to
205
- * a recursive Node.js search. Results are returned in `filepath:line:content` format.
206
- */
207
- export const searchTool = {
208
- name: 'search',
209
- description: 'Search file contents using grep/ripgrep. Returns matches in filepath:line:content format.',
210
- inputSchema,
211
- async execute(input, context) {
212
- // Check permission
213
- if (!context.permissions.allowFileRead) {
214
- throw new ToolError('File read permission denied', 'PERMISSION_DENIED', 'search');
215
- }
216
- // Validate query
217
- const query = input.query;
218
- if (typeof query !== 'string' || query.trim().length === 0) {
219
- throw new ToolError('query is required and must be a non-empty string', 'INVALID_INPUT', 'search');
220
- }
221
- const isRegexp = typeof input.isRegexp === 'boolean' ? input.isRegexp : false;
222
- const includePattern = typeof input.includePattern === 'string' ? input.includePattern : undefined;
223
- const maxResults = typeof input.maxResults === 'number' && input.maxResults > 0
224
- ? input.maxResults
225
- : DEFAULT_MAX_RESULTS;
226
- // Validate and resolve search path
227
- const rawPath = typeof input.path === 'string' ? input.path : context.workingDir;
228
- const searchPath = validateSearchPath(rawPath, context.workingDir, 'search');
229
- // Try ripgrep first, fall back to Node.js search
230
- let output = await searchWithRipgrep(query, isRegexp, includePattern, searchPath, maxResults, context.signal);
231
- let usedRipgrep = true;
232
- if (output === null) {
233
- // rg not available, use Node.js fallback
234
- usedRipgrep = false;
235
- try {
236
- output = await searchWithNode(query, isRegexp, includePattern, searchPath, maxResults);
237
- }
238
- catch (err) {
239
- const message = err instanceof Error ? err.message : 'Unknown error';
240
- throw new ToolError(`Search failed: ${message}`, 'EXECUTION_FAILED', 'search', {
241
- cause: err instanceof Error ? err : undefined,
242
- });
243
- }
244
- }
245
- // Trim trailing newline
246
- const trimmed = output.trim();
247
- // Count matches
248
- const matchCount = trimmed.length === 0 ? 0 : trimmed.split('\n').length;
249
- return {
250
- success: true,
251
- output: trimmed,
252
- metadata: {
253
- matchCount,
254
- maxResults,
255
- searchPath,
256
- engine: usedRipgrep ? 'ripgrep' : 'node',
257
- },
258
- };
259
- },
260
- };
261
- //# sourceMappingURL=search.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/tools/cli/search.ts"],"names":[],"mappings":"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"}
@@ -1,8 +0,0 @@
1
- /**
2
- * Search Tool Tests
3
- *
4
- * Tests for the search tool implementation.
5
- * Uses node:test and node:assert with real file I/O via tmpdir.
6
- */
7
- export {};
8
- //# sourceMappingURL=search.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"search.test.d.ts","sourceRoot":"","sources":["../../../src/tools/cli/search.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -1,172 +0,0 @@
1
- /**
2
- * Search Tool Tests
3
- *
4
- * Tests for the search tool implementation.
5
- * Uses node:test and node:assert with real file I/O via tmpdir.
6
- */
7
- import { describe, it, beforeEach, afterEach } from 'node:test';
8
- import assert from 'node:assert';
9
- import { mkdtempSync, writeFileSync, mkdirSync, rmSync } from 'node:fs';
10
- import { join } from 'node:path';
11
- import { tmpdir } from 'node:os';
12
- import { searchTool } from './search.js';
13
- import { ToolError } from '../types.js';
14
- /** Create a ToolContext with sensible defaults */
15
- function createContext(overrides) {
16
- return {
17
- workingDir: overrides?.workingDir ?? '/tmp',
18
- permissions: overrides?.permissions ?? {
19
- allowFileRead: true,
20
- allowFileWrite: false,
21
- allowTerminal: false,
22
- allowNetwork: false,
23
- },
24
- signal: overrides?.signal,
25
- };
26
- }
27
- describe('search tool', () => {
28
- let tempDir;
29
- beforeEach(() => {
30
- tempDir = mkdtempSync(join(tmpdir(), 'beth-search-'));
31
- });
32
- afterEach(() => {
33
- rmSync(tempDir, { recursive: true, force: true });
34
- });
35
- describe('metadata', () => {
36
- it('should have name "search"', () => {
37
- assert.strictEqual(searchTool.name, 'search');
38
- });
39
- it('should have a description', () => {
40
- assert.ok(searchTool.description.length > 0);
41
- });
42
- it('should have an inputSchema with query required', () => {
43
- assert.strictEqual(searchTool.inputSchema.type, 'object');
44
- assert.ok(Array.isArray(searchTool.inputSchema.required));
45
- assert.ok(searchTool.inputSchema.required.includes('query'));
46
- });
47
- });
48
- describe('finding matches', () => {
49
- it('should find matches in files', async () => {
50
- writeFileSync(join(tempDir, 'file1.txt'), 'hello world\ngoodbye world');
51
- writeFileSync(join(tempDir, 'file2.txt'), 'hello there');
52
- const result = await searchTool.execute({ query: 'hello' }, createContext({ workingDir: tempDir }));
53
- assert.strictEqual(result.success, true);
54
- assert.ok(result.output.includes('hello'));
55
- assert.ok(result.metadata?.matchCount >= 2);
56
- });
57
- it('should return empty output for no matches (success=true)', async () => {
58
- writeFileSync(join(tempDir, 'file.txt'), 'nothing relevant here');
59
- const result = await searchTool.execute({ query: 'zzz_no_match_zzz' }, createContext({ workingDir: tempDir }));
60
- assert.strictEqual(result.success, true);
61
- assert.strictEqual(result.output, '');
62
- assert.strictEqual(result.metadata?.matchCount, 0);
63
- });
64
- it('should return results in filepath:line:content format', async () => {
65
- writeFileSync(join(tempDir, 'formatted.txt'), 'line one\nfind me here\nline three');
66
- const result = await searchTool.execute({ query: 'find me' }, createContext({ workingDir: tempDir }));
67
- assert.strictEqual(result.success, true);
68
- // Output should contain the file path, line number, and content
69
- assert.ok(result.output.includes('formatted.txt'));
70
- assert.ok(result.output.includes('find me here'));
71
- });
72
- });
73
- describe('maxResults', () => {
74
- it('should respect maxResults limit', async () => {
75
- // Create a file with many matching lines
76
- const lines = Array.from({ length: 20 }, (_, i) => `match line ${i}`);
77
- writeFileSync(join(tempDir, 'many.txt'), lines.join('\n'));
78
- const result = await searchTool.execute({ query: 'match line', maxResults: 5 }, createContext({ workingDir: tempDir }));
79
- assert.strictEqual(result.success, true);
80
- const matchCount = result.metadata?.matchCount;
81
- assert.ok(matchCount <= 5, `Expected at most 5 matches, got ${matchCount}`);
82
- });
83
- });
84
- describe('regex patterns', () => {
85
- it('should handle regex patterns', async () => {
86
- writeFileSync(join(tempDir, 'regex.txt'), 'foo123bar\nfoo456bar\nhello world');
87
- const result = await searchTool.execute({ query: 'foo\\d+bar', isRegexp: true }, createContext({ workingDir: tempDir }));
88
- assert.strictEqual(result.success, true);
89
- assert.ok(result.output.includes('foo123bar'));
90
- assert.ok(result.output.includes('foo456bar'));
91
- assert.ok(!result.output.includes('hello world'));
92
- });
93
- });
94
- describe('include pattern filtering', () => {
95
- it('should filter by include pattern', async () => {
96
- writeFileSync(join(tempDir, 'code.ts'), 'const x = matchword;');
97
- writeFileSync(join(tempDir, 'notes.md'), 'matchword in docs');
98
- const result = await searchTool.execute({ query: 'matchword', includePattern: '*.ts' }, createContext({ workingDir: tempDir }));
99
- assert.strictEqual(result.success, true);
100
- assert.ok(result.output.includes('code.ts'));
101
- // The md file may or may not appear depending on rg vs node
102
- // Just verify the ts file was found
103
- });
104
- });
105
- describe('permissions', () => {
106
- it('should return PERMISSION_DENIED when allowFileRead is false', async () => {
107
- const ctx = createContext({
108
- workingDir: tempDir,
109
- permissions: {
110
- allowFileRead: false,
111
- allowFileWrite: false,
112
- allowTerminal: false,
113
- allowNetwork: false,
114
- },
115
- });
116
- await assert.rejects(() => searchTool.execute({ query: 'test' }, ctx), (err) => {
117
- assert.ok(err instanceof ToolError);
118
- assert.strictEqual(err.code, 'PERMISSION_DENIED');
119
- return true;
120
- });
121
- });
122
- });
123
- describe('path validation', () => {
124
- it('should reject search paths with traversal', async () => {
125
- await assert.rejects(() => searchTool.execute({ query: 'test', path: '../../../etc' }, createContext({ workingDir: tempDir })), (err) => {
126
- assert.ok(err instanceof ToolError);
127
- assert.strictEqual(err.code, 'INVALID_INPUT');
128
- assert.ok(err.message.includes('traversal'));
129
- return true;
130
- });
131
- });
132
- it('should default path to workingDir', async () => {
133
- writeFileSync(join(tempDir, 'default.txt'), 'find_default_marker');
134
- const result = await searchTool.execute({ query: 'find_default_marker' }, createContext({ workingDir: tempDir }));
135
- assert.strictEqual(result.success, true);
136
- assert.ok(result.output.includes('find_default_marker'));
137
- });
138
- });
139
- describe('input validation', () => {
140
- it('should reject empty query', async () => {
141
- await assert.rejects(() => searchTool.execute({ query: '' }, createContext({ workingDir: tempDir })), (err) => {
142
- assert.ok(err instanceof ToolError);
143
- assert.strictEqual(err.code, 'INVALID_INPUT');
144
- return true;
145
- });
146
- });
147
- it('should reject non-string query', async () => {
148
- await assert.rejects(() => searchTool.execute({ query: 123 }, createContext({ workingDir: tempDir })), (err) => {
149
- assert.ok(err instanceof ToolError);
150
- assert.strictEqual(err.code, 'INVALID_INPUT');
151
- return true;
152
- });
153
- });
154
- });
155
- describe('node fallback', () => {
156
- it('should search subdirectories', async () => {
157
- const subDir = join(tempDir, 'subdir');
158
- mkdirSync(subDir);
159
- writeFileSync(join(subDir, 'deep.txt'), 'deep_search_marker');
160
- const result = await searchTool.execute({ query: 'deep_search_marker' }, createContext({ workingDir: tempDir }));
161
- assert.strictEqual(result.success, true);
162
- assert.ok(result.output.includes('deep_search_marker'));
163
- });
164
- it('should report which engine was used', async () => {
165
- writeFileSync(join(tempDir, 'engine.txt'), 'engine_test_marker');
166
- const result = await searchTool.execute({ query: 'engine_test_marker' }, createContext({ workingDir: tempDir }));
167
- assert.strictEqual(result.success, true);
168
- assert.ok(result.metadata?.engine === 'ripgrep' || result.metadata?.engine === 'node', `Expected engine to be 'ripgrep' or 'node', got '${result.metadata?.engine}'`);
169
- });
170
- });
171
- });
172
- //# sourceMappingURL=search.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"search.test.js","sourceRoot":"","sources":["../../../src/tools/cli/search.test.ts"],"names":[],"mappings":"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"}
@@ -1,43 +0,0 @@
1
- /**
2
- * Subagent Tool
3
- *
4
- * Spawns a new agent conversation by preparing a subagent invocation request.
5
- *
6
- * **This is intentionally a stub/placeholder.** The actual agent conversation
7
- * loop requires the orchestrator (Phase 4). For now, `execute` validates input
8
- * and returns a ToolResult with `status: 'pending'` metadata. The orchestrator
9
- * will inspect tool results using `isSubagentRequest()` and handle the real
10
- * invocation.
11
- *
12
- * @example
13
- * ```typescript
14
- * const result = await subagentTool.execute(
15
- * { agentName: 'developer', prompt: 'Implement the login page', description: 'Login UI' },
16
- * context,
17
- * );
18
- * if (isSubagentRequest(result)) {
19
- * // Phase 4 orchestrator handles this
20
- * }
21
- * ```
22
- */
23
- import type { Tool } from '../interface.js';
24
- import type { ToolResult } from '../types.js';
25
- /**
26
- * Check whether a ToolResult represents a pending subagent invocation.
27
- *
28
- * Used by the orchestrator (Phase 4) to detect subagent requests in
29
- * tool execution results and route them to the appropriate agent.
30
- *
31
- * @param result - A ToolResult to inspect
32
- * @returns true if the result contains a pending subagent request
33
- */
34
- export declare function isSubagentRequest(result: ToolResult): boolean;
35
- /**
36
- * Subagent tool implementation.
37
- *
38
- * **Stub for Phase 3** — validates input and returns a pending subagent request.
39
- * The Phase 4 orchestrator will call this tool, detect the pending result via
40
- * `isSubagentRequest()`, and execute the actual agent conversation.
41
- */
42
- export declare const subagentTool: Tool;
43
- //# sourceMappingURL=subagent.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subagent.d.ts","sourceRoot":"","sources":["../../../src/tools/cli/subagent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAgC,UAAU,EAAE,MAAM,aAAa,CAAC;AA+B5E;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAQ7D;AAED;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,IAsC1B,CAAC"}
@@ -1,99 +0,0 @@
1
- /**
2
- * Subagent Tool
3
- *
4
- * Spawns a new agent conversation by preparing a subagent invocation request.
5
- *
6
- * **This is intentionally a stub/placeholder.** The actual agent conversation
7
- * loop requires the orchestrator (Phase 4). For now, `execute` validates input
8
- * and returns a ToolResult with `status: 'pending'` metadata. The orchestrator
9
- * will inspect tool results using `isSubagentRequest()` and handle the real
10
- * invocation.
11
- *
12
- * @example
13
- * ```typescript
14
- * const result = await subagentTool.execute(
15
- * { agentName: 'developer', prompt: 'Implement the login page', description: 'Login UI' },
16
- * context,
17
- * );
18
- * if (isSubagentRequest(result)) {
19
- * // Phase 4 orchestrator handles this
20
- * }
21
- * ```
22
- */
23
- import { ToolError } from '../types.js';
24
- /** Input schema for the subagent tool */
25
- const inputSchema = {
26
- type: 'object',
27
- properties: {
28
- agentName: {
29
- type: 'string',
30
- description: 'Name of the agent to invoke (e.g., "developer", "tester")',
31
- },
32
- prompt: {
33
- type: 'string',
34
- description: 'The task prompt to send to the subagent',
35
- },
36
- description: {
37
- type: 'string',
38
- description: 'Short description of the task (optional)',
39
- },
40
- },
41
- required: ['agentName', 'prompt'],
42
- };
43
- /**
44
- * Check whether a ToolResult represents a pending subagent invocation.
45
- *
46
- * Used by the orchestrator (Phase 4) to detect subagent requests in
47
- * tool execution results and route them to the appropriate agent.
48
- *
49
- * @param result - A ToolResult to inspect
50
- * @returns true if the result contains a pending subagent request
51
- */
52
- export function isSubagentRequest(result) {
53
- return (result.success === true &&
54
- result.metadata !== undefined &&
55
- result.metadata.status === 'pending' &&
56
- typeof result.metadata.agentName === 'string' &&
57
- typeof result.metadata.prompt === 'string');
58
- }
59
- /**
60
- * Subagent tool implementation.
61
- *
62
- * **Stub for Phase 3** — validates input and returns a pending subagent request.
63
- * The Phase 4 orchestrator will call this tool, detect the pending result via
64
- * `isSubagentRequest()`, and execute the actual agent conversation.
65
- */
66
- export const subagentTool = {
67
- name: 'subagent',
68
- description: 'Spawn a subagent to perform a task. Returns a pending request for the orchestrator.',
69
- inputSchema,
70
- async execute(input, context) {
71
- // Check permission — subagent calls use LLM API (network)
72
- if (!context.permissions.allowNetwork) {
73
- throw new ToolError('Network permission denied', 'PERMISSION_DENIED', 'subagent');
74
- }
75
- // Validate agentName
76
- const agentName = input.agentName;
77
- if (typeof agentName !== 'string' || agentName.trim().length === 0) {
78
- throw new ToolError('agentName is required and must be a non-empty string', 'INVALID_INPUT', 'subagent');
79
- }
80
- // Validate prompt
81
- const prompt = input.prompt;
82
- if (typeof prompt !== 'string' || prompt.trim().length === 0) {
83
- throw new ToolError('prompt is required and must be a non-empty string', 'INVALID_INPUT', 'subagent');
84
- }
85
- const description = typeof input.description === 'string' ? input.description : undefined;
86
- const metadata = {
87
- agentName: agentName.trim(),
88
- prompt: prompt.trim(),
89
- description,
90
- status: 'pending',
91
- };
92
- return {
93
- success: true,
94
- output: `Subagent request prepared: ${agentName} — ${description ?? 'no description'}`,
95
- metadata,
96
- };
97
- },
98
- };
99
- //# sourceMappingURL=subagent.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subagent.js","sourceRoot":"","sources":["../../../src/tools/cli/subagent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAUxC,yCAAyC;AACzC,MAAM,WAAW,GAAoB;IACnC,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,SAAS,EAAE;YACT,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,2DAA2D;SACzE;QACD,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,yCAAyC;SACvD;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,0CAA0C;SACxD;KACF;IACD,QAAQ,EAAE,CAAC,WAAW,EAAE,QAAQ,CAAC;CAClC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAkB;IAClD,OAAO,CACL,MAAM,CAAC,OAAO,KAAK,IAAI;QACvB,MAAM,CAAC,QAAQ,KAAK,SAAS;QAC7B,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,SAAS;QACpC,OAAO,MAAM,CAAC,QAAQ,CAAC,SAAS,KAAK,QAAQ;QAC7C,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAC3C,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAS;IAChC,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,qFAAqF;IAClG,WAAW;IAEX,KAAK,CAAC,OAAO,CAAC,KAA8B,EAAE,OAAoB;QAChE,0DAA0D;QAC1D,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;YACtC,MAAM,IAAI,SAAS,CAAC,2BAA2B,EAAE,mBAAmB,EAAE,UAAU,CAAC,CAAC;QACpF,CAAC;QAED,qBAAqB;QACrB,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;QAClC,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnE,MAAM,IAAI,SAAS,CAAC,sDAAsD,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;QAC3G,CAAC;QAED,kBAAkB;QAClB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC5B,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,SAAS,CAAC,mDAAmD,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;QACxG,CAAC;QAED,MAAM,WAAW,GAAG,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;QAE1F,MAAM,QAAQ,GAA4B;YACxC,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE;YAC3B,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;YACrB,WAAW;YACX,MAAM,EAAE,SAAS;SACS,CAAC;QAE7B,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,8BAA8B,SAAS,MAAM,WAAW,IAAI,gBAAgB,EAAE;YACtF,QAAQ;SACT,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -1,8 +0,0 @@
1
- /**
2
- * Subagent Tool Tests
3
- *
4
- * Tests for the subagent tool (Phase 3 stub).
5
- * Uses node:test and node:assert.
6
- */
7
- export {};
8
- //# sourceMappingURL=subagent.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subagent.test.d.ts","sourceRoot":"","sources":["../../../src/tools/cli/subagent.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}