@zhin.js/agent 0.1.14 → 0.1.16

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 (198) hide show
  1. package/README.md +80 -43
  2. package/lib/builtin/activate-skill-tool.d.ts +21 -0
  3. package/lib/builtin/activate-skill-tool.d.ts.map +1 -0
  4. package/lib/builtin/activate-skill-tool.js +57 -0
  5. package/lib/builtin/activate-skill-tool.js.map +1 -0
  6. package/lib/builtin/ask-user-tool.d.ts +28 -0
  7. package/lib/builtin/ask-user-tool.d.ts.map +1 -0
  8. package/lib/builtin/ask-user-tool.js +182 -0
  9. package/lib/builtin/ask-user-tool.js.map +1 -0
  10. package/lib/builtin/bash-tool.d.ts +23 -0
  11. package/lib/builtin/bash-tool.d.ts.map +1 -0
  12. package/lib/builtin/bash-tool.js +64 -0
  13. package/lib/builtin/bash-tool.js.map +1 -0
  14. package/lib/builtin/bing-search-html.d.ts +37 -0
  15. package/lib/builtin/bing-search-html.d.ts.map +1 -0
  16. package/lib/builtin/bing-search-html.js +116 -0
  17. package/lib/builtin/bing-search-html.js.map +1 -0
  18. package/lib/builtin/builtin-base-tool.d.ts +25 -0
  19. package/lib/builtin/builtin-base-tool.d.ts.map +1 -0
  20. package/lib/builtin/builtin-base-tool.js +30 -0
  21. package/lib/builtin/builtin-base-tool.js.map +1 -0
  22. package/lib/builtin/edit-file-tool.d.ts +13 -0
  23. package/lib/builtin/edit-file-tool.d.ts.map +1 -0
  24. package/lib/builtin/edit-file-tool.js +81 -0
  25. package/lib/builtin/edit-file-tool.js.map +1 -0
  26. package/lib/builtin/file-edit-quote-utils.d.ts +24 -0
  27. package/lib/builtin/file-edit-quote-utils.d.ts.map +1 -0
  28. package/lib/builtin/file-edit-quote-utils.js +81 -0
  29. package/lib/builtin/file-edit-quote-utils.js.map +1 -0
  30. package/lib/builtin/glob-tool.d.ts +23 -0
  31. package/lib/builtin/glob-tool.d.ts.map +1 -0
  32. package/lib/builtin/glob-tool.js +54 -0
  33. package/lib/builtin/glob-tool.js.map +1 -0
  34. package/lib/builtin/grep-tool.d.ts +23 -0
  35. package/lib/builtin/grep-tool.d.ts.map +1 -0
  36. package/lib/builtin/grep-tool.js +118 -0
  37. package/lib/builtin/grep-tool.js.map +1 -0
  38. package/lib/builtin/install-skill-tool.d.ts +24 -0
  39. package/lib/builtin/install-skill-tool.d.ts.map +1 -0
  40. package/lib/builtin/install-skill-tool.js +76 -0
  41. package/lib/builtin/install-skill-tool.js.map +1 -0
  42. package/lib/builtin/list-dir-tool.d.ts +13 -0
  43. package/lib/builtin/list-dir-tool.d.ts.map +1 -0
  44. package/lib/builtin/list-dir-tool.js +59 -0
  45. package/lib/builtin/list-dir-tool.js.map +1 -0
  46. package/lib/builtin/read-file-tool.d.ts +14 -0
  47. package/lib/builtin/read-file-tool.d.ts.map +1 -0
  48. package/lib/builtin/read-file-tool.js +77 -0
  49. package/lib/builtin/read-file-tool.js.map +1 -0
  50. package/lib/builtin/read-memory-tool.d.ts +14 -0
  51. package/lib/builtin/read-memory-tool.d.ts.map +1 -0
  52. package/lib/builtin/read-memory-tool.js +49 -0
  53. package/lib/builtin/read-memory-tool.js.map +1 -0
  54. package/lib/builtin/spawn-task-tool.d.ts +20 -0
  55. package/lib/builtin/spawn-task-tool.d.ts.map +1 -0
  56. package/lib/builtin/spawn-task-tool.js +57 -0
  57. package/lib/builtin/spawn-task-tool.js.map +1 -0
  58. package/lib/builtin/todo-read-tool.d.ts +14 -0
  59. package/lib/builtin/todo-read-tool.d.ts.map +1 -0
  60. package/lib/builtin/todo-read-tool.js +56 -0
  61. package/lib/builtin/todo-read-tool.js.map +1 -0
  62. package/lib/builtin/todo-write-tool.d.ts +14 -0
  63. package/lib/builtin/todo-write-tool.d.ts.map +1 -0
  64. package/lib/builtin/todo-write-tool.js +54 -0
  65. package/lib/builtin/todo-write-tool.js.map +1 -0
  66. package/lib/builtin/web-fetch-tool.d.ts +19 -0
  67. package/lib/builtin/web-fetch-tool.d.ts.map +1 -0
  68. package/lib/builtin/web-fetch-tool.js +89 -0
  69. package/lib/builtin/web-fetch-tool.js.map +1 -0
  70. package/lib/builtin/web-search-locale.d.ts +16 -0
  71. package/lib/builtin/web-search-locale.d.ts.map +1 -0
  72. package/lib/builtin/web-search-locale.js +73 -0
  73. package/lib/builtin/web-search-locale.js.map +1 -0
  74. package/lib/builtin/web-search-tool.d.ts +20 -0
  75. package/lib/builtin/web-search-tool.d.ts.map +1 -0
  76. package/lib/builtin/web-search-tool.js +105 -0
  77. package/lib/builtin/web-search-tool.js.map +1 -0
  78. package/lib/builtin/web-tool-utils.d.ts +4 -0
  79. package/lib/builtin/web-tool-utils.d.ts.map +1 -0
  80. package/lib/builtin/web-tool-utils.js +4 -0
  81. package/lib/builtin/web-tool-utils.js.map +1 -0
  82. package/lib/builtin/write-file-tool.d.ts +13 -0
  83. package/lib/builtin/write-file-tool.d.ts.map +1 -0
  84. package/lib/builtin/write-file-tool.js +51 -0
  85. package/lib/builtin/write-file-tool.js.map +1 -0
  86. package/lib/builtin/write-memory-tool.d.ts +14 -0
  87. package/lib/builtin/write-memory-tool.d.ts.map +1 -0
  88. package/lib/builtin/write-memory-tool.js +50 -0
  89. package/lib/builtin/write-memory-tool.js.map +1 -0
  90. package/lib/builtin-tools.d.ts +10 -11
  91. package/lib/builtin-tools.d.ts.map +1 -1
  92. package/lib/builtin-tools.js +44 -862
  93. package/lib/builtin-tools.js.map +1 -1
  94. package/lib/defaults/tools.d.ts +3 -6
  95. package/lib/defaults/tools.d.ts.map +1 -1
  96. package/lib/defaults/tools.js +3 -11
  97. package/lib/defaults/tools.js.map +1 -1
  98. package/lib/index.d.ts +25 -3
  99. package/lib/index.d.ts.map +1 -1
  100. package/lib/index.js +24 -3
  101. package/lib/index.js.map +1 -1
  102. package/lib/init/create-zhin-agent.d.ts.map +1 -1
  103. package/lib/init/create-zhin-agent.js +4 -3
  104. package/lib/init/create-zhin-agent.js.map +1 -1
  105. package/lib/init/message-media.d.ts +8 -0
  106. package/lib/init/message-media.d.ts.map +1 -0
  107. package/lib/init/message-media.js +75 -0
  108. package/lib/init/message-media.js.map +1 -0
  109. package/lib/init/output-renderer.d.ts +3 -0
  110. package/lib/init/output-renderer.d.ts.map +1 -0
  111. package/lib/init/output-renderer.js +38 -0
  112. package/lib/init/output-renderer.js.map +1 -0
  113. package/lib/init/register-ai-trigger.d.ts +1 -1
  114. package/lib/init/register-ai-trigger.d.ts.map +1 -1
  115. package/lib/init/register-ai-trigger.js +35 -159
  116. package/lib/init/register-ai-trigger.js.map +1 -1
  117. package/lib/init/register-builtin-tools.d.ts.map +1 -1
  118. package/lib/init/register-builtin-tools.js +9 -5
  119. package/lib/init/register-builtin-tools.js.map +1 -1
  120. package/lib/orchestrator/index.d.ts +2 -0
  121. package/lib/orchestrator/index.d.ts.map +1 -1
  122. package/lib/orchestrator/index.js +1 -0
  123. package/lib/orchestrator/index.js.map +1 -1
  124. package/lib/orchestrator/resource-registry.d.ts +1 -0
  125. package/lib/orchestrator/resource-registry.d.ts.map +1 -1
  126. package/lib/orchestrator/resource-registry.js +6 -0
  127. package/lib/orchestrator/resource-registry.js.map +1 -1
  128. package/lib/orchestrator/tool-registry.d.ts +5 -11
  129. package/lib/orchestrator/tool-registry.d.ts.map +1 -1
  130. package/lib/orchestrator/tool-registry.js +30 -75
  131. package/lib/orchestrator/tool-registry.js.map +1 -1
  132. package/lib/orchestrator/tool-selection.d.ts +39 -0
  133. package/lib/orchestrator/tool-selection.d.ts.map +1 -0
  134. package/lib/orchestrator/tool-selection.js +319 -0
  135. package/lib/orchestrator/tool-selection.js.map +1 -0
  136. package/lib/orchestrator/types.d.ts +2 -0
  137. package/lib/orchestrator/types.d.ts.map +1 -1
  138. package/lib/reserved-tools.d.ts +3 -0
  139. package/lib/reserved-tools.d.ts.map +1 -0
  140. package/lib/reserved-tools.js +30 -0
  141. package/lib/reserved-tools.js.map +1 -0
  142. package/lib/service.d.ts +9 -5
  143. package/lib/service.d.ts.map +1 -1
  144. package/lib/service.js +42 -36
  145. package/lib/service.js.map +1 -1
  146. package/lib/subagent.d.ts +6 -0
  147. package/lib/subagent.d.ts.map +1 -1
  148. package/lib/subagent.js +33 -15
  149. package/lib/subagent.js.map +1 -1
  150. package/lib/task-executor.d.ts +1 -0
  151. package/lib/task-executor.d.ts.map +1 -1
  152. package/lib/task-executor.js +15 -8
  153. package/lib/task-executor.js.map +1 -1
  154. package/lib/zhin-agent/builtin-tools.d.ts +1 -3
  155. package/lib/zhin-agent/builtin-tools.d.ts.map +1 -1
  156. package/lib/zhin-agent/builtin-tools.js +4 -41
  157. package/lib/zhin-agent/builtin-tools.js.map +1 -1
  158. package/lib/zhin-agent/config.d.ts +7 -0
  159. package/lib/zhin-agent/config.d.ts.map +1 -1
  160. package/lib/zhin-agent/config.js +12 -7
  161. package/lib/zhin-agent/config.js.map +1 -1
  162. package/lib/zhin-agent/context-budget.d.ts +27 -0
  163. package/lib/zhin-agent/context-budget.d.ts.map +1 -0
  164. package/lib/zhin-agent/context-budget.js +50 -0
  165. package/lib/zhin-agent/context-budget.js.map +1 -0
  166. package/lib/zhin-agent/index.d.ts +10 -0
  167. package/lib/zhin-agent/index.d.ts.map +1 -1
  168. package/lib/zhin-agent/index.js +120 -84
  169. package/lib/zhin-agent/index.js.map +1 -1
  170. package/lib/zhin-agent/model-harness.d.ts +29 -0
  171. package/lib/zhin-agent/model-harness.d.ts.map +1 -0
  172. package/lib/zhin-agent/model-harness.js +67 -0
  173. package/lib/zhin-agent/model-harness.js.map +1 -0
  174. package/lib/zhin-agent/pre-exec.d.ts +7 -0
  175. package/lib/zhin-agent/pre-exec.d.ts.map +1 -0
  176. package/lib/zhin-agent/pre-exec.js +25 -0
  177. package/lib/zhin-agent/pre-exec.js.map +1 -0
  178. package/lib/zhin-agent/prompt.d.ts +10 -8
  179. package/lib/zhin-agent/prompt.d.ts.map +1 -1
  180. package/lib/zhin-agent/prompt.js +37 -30
  181. package/lib/zhin-agent/prompt.js.map +1 -1
  182. package/lib/zhin-agent/text-sanitize.d.ts +8 -0
  183. package/lib/zhin-agent/text-sanitize.d.ts.map +1 -0
  184. package/lib/zhin-agent/text-sanitize.js +19 -0
  185. package/lib/zhin-agent/text-sanitize.js.map +1 -0
  186. package/lib/zhin-agent/tool-runtime.d.ts +31 -0
  187. package/lib/zhin-agent/tool-runtime.d.ts.map +1 -0
  188. package/lib/zhin-agent/tool-runtime.js +49 -0
  189. package/lib/zhin-agent/tool-runtime.js.map +1 -0
  190. package/package.json +8 -6
  191. package/lib/tools.d.ts +0 -45
  192. package/lib/tools.d.ts.map +0 -1
  193. package/lib/tools.js +0 -205
  194. package/lib/tools.js.map +0 -1
  195. package/lib/zhin-agent/tool-collector.d.ts +0 -22
  196. package/lib/zhin-agent/tool-collector.d.ts.map +0 -1
  197. package/lib/zhin-agent/tool-collector.js +0 -225
  198. package/lib/zhin-agent/tool-collector.js.map +0 -1
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Bing 搜索结果 HTML 解析(参考 claude-code-best/claude-code WebSearchTool bingAdapter)
3
+ * https://github.com/claude-code-best/claude-code/blob/main/packages/builtin-tools/src/tools/WebSearchTool/adapters/bingAdapter.ts
4
+ */
5
+ import he from 'he';
6
+ import { acceptLanguageForMarket, DEFAULT_WEB_SEARCH_MARKET } from './web-search-locale.js';
7
+ export const decodeHtmlEntities = (s) => he.decode(s);
8
+ /**
9
+ * 从 Bing 结果页 HTML 提取有机结果。
10
+ * 结果位于 <ol id="b_results"> 内 <li class="b_algo"> 块中。
11
+ */
12
+ export function extractBingResults(html) {
13
+ const results = [];
14
+ const algoBlockRegex = /<li\s+class="b_algo"[^>]*>([\s\S]*?)<\/li>/gi;
15
+ let blockMatch;
16
+ while ((blockMatch = algoBlockRegex.exec(html)) !== null) {
17
+ const block = blockMatch[1];
18
+ const h2LinkRegex = /<h2[^>]*>\s*<a[^>]+href="([^"]+)"[^>]*>([\s\S]*?)<\/a>/i;
19
+ const linkMatch = h2LinkRegex.exec(block);
20
+ if (!linkMatch)
21
+ continue;
22
+ const rawUrl = decodeHtmlEntities(linkMatch[1]);
23
+ const titleHtml = linkMatch[2];
24
+ const url = resolveBingUrl(rawUrl);
25
+ if (!url)
26
+ continue;
27
+ const title = decodeHtmlEntities(titleHtml.replace(/<[^>]+>/g, '').trim());
28
+ const snippet = extractSnippet(block);
29
+ results.push({ title, url, snippet });
30
+ }
31
+ return results;
32
+ }
33
+ function extractSnippet(block) {
34
+ const lineclampRegex = /<p[^>]*class="b_lineclamp[^"]*"[^>]*>([\s\S]*?)<\/p>/i;
35
+ let match = lineclampRegex.exec(block);
36
+ if (match) {
37
+ return decodeHtmlEntities(match[1].replace(/<[^>]+>/g, '').trim());
38
+ }
39
+ const captionPRegex = /<div[^>]*class="b_caption[^"]*"[^>]*>[\s\S]*?<p[^>]*>([\s\S]*?)<\/p>/i;
40
+ match = captionPRegex.exec(block);
41
+ if (match) {
42
+ return decodeHtmlEntities(match[1].replace(/<[^>]+>/g, '').trim());
43
+ }
44
+ const fallbackRegex = /<div[^>]*class="b_caption[^"]*"[^>]*>([\s\S]*?)<\/div>/i;
45
+ const fallbackMatch = fallbackRegex.exec(block);
46
+ if (fallbackMatch) {
47
+ const text = fallbackMatch[1].replace(/<[^>]+>/g, '').trim();
48
+ if (text)
49
+ return decodeHtmlEntities(text);
50
+ }
51
+ return undefined;
52
+ }
53
+ /**
54
+ * 将 Bing 跳转链接解析为真实 URL(/ck/a?...&u=a1aHR0cHM6Ly9...)
55
+ */
56
+ export function resolveBingUrl(rawUrl) {
57
+ if (rawUrl.startsWith('/') || rawUrl.startsWith('#'))
58
+ return undefined;
59
+ const uMatch = rawUrl.match(/[?&]u=([a-zA-Z0-9+/_=-]+)/);
60
+ if (uMatch) {
61
+ const encoded = uMatch[1];
62
+ if (encoded.length >= 3) {
63
+ const b64 = encoded.slice(2);
64
+ try {
65
+ const padded = b64.replace(/-/g, '+').replace(/_/g, '/');
66
+ const decoded = Buffer.from(padded, 'base64').toString('utf-8');
67
+ if (decoded.startsWith('http'))
68
+ return decoded;
69
+ }
70
+ catch {
71
+ /* fall through */
72
+ }
73
+ }
74
+ }
75
+ if (!rawUrl.includes('bing.com'))
76
+ return rawUrl;
77
+ return undefined;
78
+ }
79
+ /** 与 bingAdapter 一致:浏览器风格请求头(不含 Accept-Language,由 {@link bingSearchFetchHeaders} 按市场注入) */
80
+ const BING_SEARCH_BROWSER_HEADERS_BASE = {
81
+ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0',
82
+ Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
83
+ 'Accept-Encoding': 'gzip, deflate, br',
84
+ 'Cache-Control': 'no-cache',
85
+ Pragma: 'no-cache',
86
+ 'Sec-Ch-Ua': '"Microsoft Edge";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
87
+ 'Sec-Ch-Ua-Mobile': '?0',
88
+ 'Sec-Ch-Ua-Platform': '"macOS"',
89
+ 'Sec-Fetch-Dest': 'document',
90
+ 'Sec-Fetch-Mode': 'navigate',
91
+ 'Sec-Fetch-Site': 'none',
92
+ 'Sec-Fetch-User': '?1',
93
+ 'Upgrade-Insecure-Requests': '1',
94
+ };
95
+ /** @deprecated 单测兼容:请用 {@link bingSearchFetchHeaders};默认语言为 en-US 旧行为已弃用 */
96
+ export const BING_SEARCH_BROWSER_HEADERS = {
97
+ ...BING_SEARCH_BROWSER_HEADERS_BASE,
98
+ 'Accept-Language': 'en-US,en;q=0.9',
99
+ };
100
+ export function bingSearchFetchHeaders(market) {
101
+ return {
102
+ ...BING_SEARCH_BROWSER_HEADERS_BASE,
103
+ 'Accept-Language': acceptLanguageForMarket(market),
104
+ };
105
+ }
106
+ export const BING_SEARCH_FETCH_TIMEOUT_MS = 30_000;
107
+ export function buildBingSearchUrl(query, market = DEFAULT_WEB_SEARCH_MARKET) {
108
+ const mkt = encodeURIComponent(market);
109
+ return `https://www.bing.com/search?q=${encodeURIComponent(query)}&setmkt=${mkt}`;
110
+ }
111
+ export function hostnameMatchesList(hostname, domain) {
112
+ const h = hostname.toLowerCase();
113
+ const d = domain.toLowerCase().replace(/^\.+/, '');
114
+ return h === d || h.endsWith(`.${d}`);
115
+ }
116
+ //# sourceMappingURL=bing-search-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bing-search-html.js","sourceRoot":"","sources":["../../src/builtin/bing-search-html.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 内置系统工具基类 — 产出与 {@link ToolFeature} / {@link normalizeTool} 兼容的 {@link Tool},
3
+ * 便于将核心逻辑写在可单测的 `run` 中(见 PRD #389 / issue #390)。
4
+ */
5
+ import type { Tool, ToolContext, ToolParametersSchema, ToolResult } from '@zhin.js/core';
6
+ export declare abstract class BuiltinBaseTool {
7
+ abstract readonly name: string;
8
+ abstract readonly description: string;
9
+ abstract readonly parameters: ToolParametersSchema;
10
+ /** 与 ZhinTool 链式 API 对齐 */
11
+ readonly tags: string[];
12
+ readonly keywords: string[];
13
+ readonly kind?: string;
14
+ /** 仅当为 true 时写入 Tool */
15
+ readonly preExecutable?: boolean;
16
+ /**
17
+ * 核心执行逻辑(单测优先覆盖此处)。
18
+ */
19
+ abstract run(args: Record<string, unknown>, context?: ToolContext): Promise<ToolResult>;
20
+ /**
21
+ * 注册到 ToolFeature;带 `source` 以便 `normalizeTool` 识别为 IM 工具形态并绑定 context。
22
+ */
23
+ toTool(): Tool;
24
+ }
25
+ //# sourceMappingURL=builtin-base-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtin-base-tool.d.ts","sourceRoot":"","sources":["../../src/builtin/builtin-base-tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEzF,8BAAsB,eAAe;IACnC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC;IAEnD,2BAA2B;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAM;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAM;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,wBAAwB;IACxB,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAEjC;;OAEG;IACH,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAEvF;;OAEG;IACH,MAAM,IAAI,IAAI;CAcf"}
@@ -0,0 +1,30 @@
1
+ export class BuiltinBaseTool {
2
+ /** 与 ZhinTool 链式 API 对齐 */
3
+ tags = [];
4
+ keywords = [];
5
+ kind;
6
+ /** 仅当为 true 时写入 Tool */
7
+ preExecutable;
8
+ /**
9
+ * 注册到 ToolFeature;带 `source` 以便 `normalizeTool` 识别为 IM 工具形态并绑定 context。
10
+ */
11
+ toTool() {
12
+ const tool = {
13
+ name: this.name,
14
+ description: this.description,
15
+ parameters: this.parameters,
16
+ source: 'builtin:agent',
17
+ execute: async (args, ctx) => this.run(args, ctx),
18
+ };
19
+ if (this.tags.length)
20
+ tool.tags = [...this.tags];
21
+ if (this.keywords.length)
22
+ tool.keywords = [...this.keywords];
23
+ if (this.kind)
24
+ tool.kind = this.kind;
25
+ if (this.preExecutable)
26
+ tool.preExecutable = true;
27
+ return tool;
28
+ }
29
+ }
30
+ //# sourceMappingURL=builtin-base-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtin-base-tool.js","sourceRoot":"","sources":["../../src/builtin/builtin-base-tool.ts"],"names":[],"mappings":"AAMA,MAAM,OAAgB,eAAe;IAKnC,2BAA2B;IAClB,IAAI,GAAa,EAAE,CAAC;IACpB,QAAQ,GAAa,EAAE,CAAC;IACxB,IAAI,CAAU;IACvB,wBAAwB;IACf,aAAa,CAAW;IAOjC;;OAEG;IACH,MAAM;QACJ,MAAM,IAAI,GAAS;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,MAAM,EAAE,eAAe;YACvB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAA+B,EAAE,GAAG,CAAC;SAC7E,CAAC;QACF,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM;YAAE,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7D,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACrC,IAAI,IAAI,CAAC,aAAa;YAAE,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import type { Tool, ToolContext, ToolParametersSchema, ToolResult } from '@zhin.js/core';
2
+ import { BuiltinBaseTool } from './builtin-base-tool.js';
3
+ export declare const EDIT_FILE_PARAMETERS: ToolParametersSchema;
4
+ export declare class EditFileBuiltinTool extends BuiltinBaseTool {
5
+ readonly name = "edit_file";
6
+ readonly description = "\u5728\u6587\u4EF6\u4E2D\u67E5\u627E\u5E76\u66FF\u6362\u4E00\u6BB5\u6587\u672C\u3002old_string \u5FC5\u987B\u5728\u6587\u4EF6\u4E2D\u7CBE\u786E\u5B58\u5728\u4E14\u552F\u4E00\uFF1B\u5EFA\u8BAE\u5305\u542B\u5B8C\u6574\u884C\u6216\u8DB3\u591F\u4E0A\u4E0B\u6587\u4EE5\u907F\u514D\u91CD\u590D\u5339\u914D\u3002\u652F\u6301\u5F2F\u5F15\u53F7/\u76F4\u5F15\u53F7\u81EA\u52A8\u5F52\u4E00\u5316\u3002";
7
+ readonly parameters: ToolParametersSchema<Record<string, any>>;
8
+ readonly kind = "file";
9
+ constructor();
10
+ run(args: Record<string, unknown>, _context?: ToolContext): Promise<ToolResult>;
11
+ }
12
+ export declare function createEditFileTool(): Tool;
13
+ //# sourceMappingURL=edit-file-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-file-tool.d.ts","sourceRoot":"","sources":["../../src/builtin/edit-file-tool.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAOzF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAMzD,eAAO,MAAM,oBAAoB,EAAE,oBAWlC,CAAC;AAEF,qBAAa,mBAAoB,SAAQ,eAAe;IACtD,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,WAAW,4YAC4D;IAChF,QAAQ,CAAC,UAAU,4CAAwB;IAC3C,QAAQ,CAAC,IAAI,UAAU;;IAiBjB,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;CAkDtF;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * edit_file — 内置查找替换编辑
3
+ */
4
+ import * as fs from 'node:fs/promises';
5
+ import { assertFileAccess, MAX_EDIT_FILE_SIZE, isFileStale, } from '../security/file-policy.js';
6
+ import { expandHome, nodeErrToFileMessage } from '../discovery/utils.js';
7
+ import { BuiltinBaseTool } from './builtin-base-tool.js';
8
+ import { findActualStringInFile, preserveQuoteStyleInEdit, } from './file-edit-quote-utils.js';
9
+ export const EDIT_FILE_PARAMETERS = {
10
+ type: 'object',
11
+ properties: {
12
+ file_path: { type: 'string', description: '要编辑的文件路径' },
13
+ old_string: {
14
+ type: 'string',
15
+ description: '文件中要替换的原文(必须与文件内容完全一致)',
16
+ },
17
+ new_string: { type: 'string', description: '替换后的新文本' },
18
+ },
19
+ required: ['file_path', 'old_string', 'new_string'],
20
+ };
21
+ export class EditFileBuiltinTool extends BuiltinBaseTool {
22
+ name = 'edit_file';
23
+ description = '在文件中查找并替换一段文本。old_string 必须在文件中精确存在且唯一;建议包含完整行或足够上下文以避免重复匹配。支持弯引号/直引号自动归一化。';
24
+ parameters = EDIT_FILE_PARAMETERS;
25
+ kind = 'file';
26
+ constructor() {
27
+ super();
28
+ this.tags.push('file', 'edit');
29
+ this.keywords.push('编辑文件', '修改文件', '替换内容', '查找替换', 'edit file', 'edit', '修改', '替换');
30
+ }
31
+ async run(args, _context) {
32
+ const filePathArg = args.file_path;
33
+ const oldStringArg = args.old_string;
34
+ const newStringArg = args.new_string;
35
+ if (typeof filePathArg !== 'string' || !filePathArg.trim()) {
36
+ return 'Error: file_path is required';
37
+ }
38
+ if (typeof oldStringArg !== 'string') {
39
+ return 'Error: old_string is required';
40
+ }
41
+ if (typeof newStringArg !== 'string') {
42
+ return 'Error: new_string is required';
43
+ }
44
+ try {
45
+ const fp = expandHome(filePathArg);
46
+ assertFileAccess(fp);
47
+ const stat = await fs.stat(fp);
48
+ if (stat.size > MAX_EDIT_FILE_SIZE) {
49
+ return `Error: 文件过大 (${(stat.size / 1024 / 1024).toFixed(1)} MiB),超过 ${MAX_EDIT_FILE_SIZE / 1024 / 1024} MiB 限制。`;
50
+ }
51
+ const mtimeBefore = stat.mtimeMs;
52
+ const content = await fs.readFile(fp, 'utf-8');
53
+ const matchResult = findActualStringInFile(content, oldStringArg);
54
+ if (!matchResult) {
55
+ return 'Error: old_string not found in file. Make sure it matches exactly (also tried quote normalization).';
56
+ }
57
+ if (matchResult.count > 1) {
58
+ return `Warning: old_string appears ${matchResult.count} times. Please provide more context to make it unique.`;
59
+ }
60
+ const effectiveNew = matchResult.wasNormalized
61
+ ? preserveQuoteStyleInEdit(oldStringArg, matchResult.actual, newStringArg)
62
+ : newStringArg;
63
+ const newContent = content.replace(matchResult.actual, effectiveNew);
64
+ const currentStat = await fs.stat(fp);
65
+ if (isFileStale(mtimeBefore, currentStat.mtimeMs)) {
66
+ return `Error: 文件 ${fp} 在读取后被外部修改。请重新读取文件后再编辑,避免覆盖他人的修改。`;
67
+ }
68
+ await fs.writeFile(fp, newContent, 'utf-8');
69
+ const oldLines = oldStringArg.split('\n');
70
+ const newLines = newStringArg.split('\n');
71
+ return `✅ Edited ${fp}\n--- before ---\n${oldLines.slice(0, 5).join('\n')}${oldLines.length > 5 ? '\n...' : ''}\n--- after ---\n${newLines.slice(0, 5).join('\n')}${newLines.length > 5 ? '\n...' : ''}`;
72
+ }
73
+ catch (e) {
74
+ return nodeErrToFileMessage(e, String(filePathArg), 'edit');
75
+ }
76
+ }
77
+ }
78
+ export function createEditFileTool() {
79
+ return new EditFileBuiltinTool().toTool();
80
+ }
81
+ //# sourceMappingURL=edit-file-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-file-tool.js","sourceRoot":"","sources":["../../src/builtin/edit-file-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * 引号归一化 + 模糊匹配(参考 Claude Code FileEditTool/utils.ts),供 edit_file 使用。
3
+ */
4
+ /** 将弯引号归一化为直引号 */
5
+ export declare function normalizeQuotes(str: string): string;
6
+ export interface FuzzyMatchResult {
7
+ /** 文件中实际匹配到的字符串 */
8
+ actual: string;
9
+ /** 匹配次数 */
10
+ count: number;
11
+ /** 是否通过引号归一化匹配 */
12
+ wasNormalized: boolean;
13
+ }
14
+ /**
15
+ * 在文件内容中查找字符串,支持精确匹配和引号归一化模糊匹配。
16
+ * 参考 Claude Code `findActualString`。
17
+ */
18
+ export declare function findActualStringInFile(fileContent: string, searchString: string): FuzzyMatchResult | null;
19
+ /**
20
+ * 将 new_string 中的直引号替换为文件中原始的弯引号风格。
21
+ * 参考 Claude Code `preserveQuoteStyle`。
22
+ */
23
+ export declare function preserveQuoteStyleInEdit(oldString: string, actualOldString: string, newString: string): string;
24
+ //# sourceMappingURL=file-edit-quote-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-edit-quote-utils.d.ts","sourceRoot":"","sources":["../../src/builtin/file-edit-quote-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,kBAAkB;AAClB,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMnD;AAED,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAgBzG;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CA0C9G"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * 引号归一化 + 模糊匹配(参考 Claude Code FileEditTool/utils.ts),供 edit_file 使用。
3
+ */
4
+ /** 将弯引号归一化为直引号 */
5
+ export function normalizeQuotes(str) {
6
+ return str
7
+ .replace(/\u2018/g, "'") // '
8
+ .replace(/\u2019/g, "'") // '
9
+ .replace(/\u201C/g, '"') // "
10
+ .replace(/\u201D/g, '"'); // "
11
+ }
12
+ /**
13
+ * 在文件内容中查找字符串,支持精确匹配和引号归一化模糊匹配。
14
+ * 参考 Claude Code `findActualString`。
15
+ */
16
+ export function findActualStringInFile(fileContent, searchString) {
17
+ const exactCount = fileContent.split(searchString).length - 1;
18
+ if (exactCount > 0) {
19
+ return { actual: searchString, count: exactCount, wasNormalized: false };
20
+ }
21
+ const normalizedSearch = normalizeQuotes(searchString);
22
+ const normalizedFile = normalizeQuotes(fileContent);
23
+ const idx = normalizedFile.indexOf(normalizedSearch);
24
+ if (idx !== -1) {
25
+ const actual = fileContent.substring(idx, idx + searchString.length);
26
+ const normalizedCount = normalizedFile.split(normalizedSearch).length - 1;
27
+ return { actual, count: normalizedCount, wasNormalized: true };
28
+ }
29
+ return null;
30
+ }
31
+ /**
32
+ * 将 new_string 中的直引号替换为文件中原始的弯引号风格。
33
+ * 参考 Claude Code `preserveQuoteStyle`。
34
+ */
35
+ export function preserveQuoteStyleInEdit(oldString, actualOldString, newString) {
36
+ if (oldString === actualOldString)
37
+ return newString;
38
+ const hasDouble = actualOldString.includes('\u201C') || actualOldString.includes('\u201D');
39
+ const hasSingle = actualOldString.includes('\u2018') || actualOldString.includes('\u2019');
40
+ if (!hasDouble && !hasSingle)
41
+ return newString;
42
+ let result = newString;
43
+ if (hasDouble) {
44
+ const chars = [...result];
45
+ const out = [];
46
+ for (let i = 0; i < chars.length; i++) {
47
+ if (chars[i] === '"') {
48
+ const prev = i > 0 ? chars[i - 1] : ' ';
49
+ const isOpening = /[\s(\[{]/.test(prev) || i === 0;
50
+ out.push(isOpening ? '\u201C' : '\u201D');
51
+ }
52
+ else {
53
+ out.push(chars[i]);
54
+ }
55
+ }
56
+ result = out.join('');
57
+ }
58
+ if (hasSingle) {
59
+ const chars = [...result];
60
+ const out = [];
61
+ for (let i = 0; i < chars.length; i++) {
62
+ if (chars[i] === "'") {
63
+ const prev = i > 0 ? chars[i - 1] : ' ';
64
+ const next = i < chars.length - 1 ? chars[i + 1] : ' ';
65
+ if (/\p{L}/u.test(prev) && /\p{L}/u.test(next)) {
66
+ out.push('\u2019');
67
+ }
68
+ else {
69
+ const isOpening = /[\s(\[{]/.test(prev) || i === 0;
70
+ out.push(isOpening ? '\u2018' : '\u2019');
71
+ }
72
+ }
73
+ else {
74
+ out.push(chars[i]);
75
+ }
76
+ }
77
+ result = out.join('');
78
+ }
79
+ return result;
80
+ }
81
+ //# sourceMappingURL=file-edit-quote-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-edit-quote-utils.js","sourceRoot":"","sources":["../../src/builtin/file-edit-quote-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * glob — 按 glob 模式查找文件
3
+ */
4
+ import { type ExecOptions } from 'node:child_process';
5
+ import type { Tool, ToolContext, ToolParametersSchema, ToolResult } from '@zhin.js/core';
6
+ import { BuiltinBaseTool } from './builtin-base-tool.js';
7
+ /** 可注入以便单测(默认 `promisify(exec)`) */
8
+ export type GlobExecAsync = (command: string, options?: ExecOptions) => Promise<{
9
+ stdout: string;
10
+ stderr: string;
11
+ }>;
12
+ export declare const GLOB_PARAMETERS: ToolParametersSchema;
13
+ export declare class GlobBuiltinTool extends BuiltinBaseTool {
14
+ private readonly execAsync;
15
+ readonly name = "glob";
16
+ readonly description = "\u6309 glob \u6A21\u5F0F\u67E5\u627E\u5339\u914D\u7684\u6587\u4EF6\u8DEF\u5F84\uFF08\u5982 **/*.ts\uFF09\u3002\u7528\u4E8E\u6309\u6A21\u5F0F\u627E\u6587\u4EF6\uFF0C\u800C\u975E\u5217\u51FA\u76EE\u5F55\u3002";
17
+ readonly parameters: ToolParametersSchema<Record<string, any>>;
18
+ readonly kind = "file";
19
+ constructor(execAsync?: GlobExecAsync);
20
+ run(args: Record<string, unknown>, _context?: ToolContext): Promise<ToolResult>;
21
+ }
22
+ export declare function createGlobTool(): Tool;
23
+ //# sourceMappingURL=glob-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob-tool.d.ts","sourceRoot":"","sources":["../../src/builtin/glob-tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAQ,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGzF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAIzD,oCAAoC;AACpC,MAAM,MAAM,aAAa,GAAG,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,KAClB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEjD,eAAO,MAAM,eAAe,EAAE,oBAO7B,CAAC;AAEF,qBAAa,eAAgB,SAAQ,eAAe;IAOtC,OAAO,CAAC,QAAQ,CAAC,SAAS;IANtC,QAAQ,CAAC,IAAI,UAAU;IACvB,QAAQ,CAAC,WAAW,oNAC+B;IACnD,QAAQ,CAAC,UAAU,4CAAmB;IACtC,QAAQ,CAAC,IAAI,UAAU;gBAEM,SAAS,GAAE,aAAgC;IAMlE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;CAsBtF;AAED,wBAAgB,cAAc,IAAI,IAAI,CAErC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * glob — 按 glob 模式查找文件
3
+ */
4
+ import { exec } from 'node:child_process';
5
+ import { promisify } from 'node:util';
6
+ import { assertFileAccess, shellEscape } from '../security/file-policy.js';
7
+ import { errMsg } from '../discovery/utils.js';
8
+ import { BuiltinBaseTool } from './builtin-base-tool.js';
9
+ const defaultExecAsync = promisify(exec);
10
+ export const GLOB_PARAMETERS = {
11
+ type: 'object',
12
+ properties: {
13
+ pattern: { type: 'string', description: 'Glob 模式(如 **/*.ts)' },
14
+ cwd: { type: 'string', description: '工作目录(默认项目根目录)' },
15
+ },
16
+ required: ['pattern'],
17
+ };
18
+ export class GlobBuiltinTool extends BuiltinBaseTool {
19
+ execAsync;
20
+ name = 'glob';
21
+ description = '按 glob 模式查找匹配的文件路径(如 **/*.ts)。用于按模式找文件,而非列出目录。';
22
+ parameters = GLOB_PARAMETERS;
23
+ kind = 'file';
24
+ constructor(execAsync = defaultExecAsync) {
25
+ super();
26
+ this.execAsync = execAsync;
27
+ this.tags.push('file', 'search');
28
+ this.keywords.push('glob', '查找文件', '按模式找文件', 'find', '匹配文件');
29
+ }
30
+ async run(args, _context) {
31
+ const patternArg = args.pattern;
32
+ if (typeof patternArg !== 'string' || !patternArg.trim()) {
33
+ return 'Error: pattern is required';
34
+ }
35
+ try {
36
+ const cwdRaw = args.cwd;
37
+ const cwd = typeof cwdRaw === 'string' && cwdRaw.trim() ? cwdRaw : process.cwd();
38
+ assertFileAccess(cwd);
39
+ const safePattern = shellEscape(patternArg);
40
+ const { stdout } = await this.execAsync(`find . -path ./${safePattern} -type f 2>/dev/null | head -100`, { cwd });
41
+ const files = stdout.trim().split('\n').filter(Boolean);
42
+ return files.length === 0
43
+ ? `No files matching '${patternArg}'`
44
+ : `Found ${files.length} files:\n${files.join('\n')}`;
45
+ }
46
+ catch (e) {
47
+ return `Error: ${errMsg(e)}`;
48
+ }
49
+ }
50
+ }
51
+ export function createGlobTool() {
52
+ return new GlobBuiltinTool().toTool();
53
+ }
54
+ //# sourceMappingURL=glob-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob-tool.js","sourceRoot":"","sources":["../../src/builtin/glob-tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,IAAI,EAAoB,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,gBAAgB,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAQzC,MAAM,CAAC,MAAM,eAAe,GAAyB;IACnD,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE;QAC9D,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;KACtD;IACD,QAAQ,EAAE,CAAC,SAAS,CAAC;CACtB,CAAC;AAEF,MAAM,OAAO,eAAgB,SAAQ,eAAe;IAOrB;IANpB,IAAI,GAAG,MAAM,CAAC;IACd,WAAW,GAClB,gDAAgD,CAAC;IAC1C,UAAU,GAAG,eAAe,CAAC;IAC7B,IAAI,GAAG,MAAM,CAAC;IAEvB,YAA6B,YAA2B,gBAAgB;QACtE,KAAK,EAAE,CAAC;QADmB,cAAS,GAAT,SAAS,CAAkC;QAEtE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACjC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAA6B,EAAE,QAAsB;QAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC;QAChC,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;YACzD,OAAO,4BAA4B,CAAC;QACtC,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC;YACxB,MAAM,GAAG,GAAG,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACjF,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACtB,MAAM,WAAW,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;YAC5C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,SAAS,CACrC,kBAAkB,WAAW,kCAAkC,EAC/D,EAAE,GAAG,EAAE,CACR,CAAC;YACF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACxD,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;gBACvB,CAAC,CAAC,sBAAsB,UAAU,GAAG;gBACrC,CAAC,CAAC,SAAS,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1D,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,OAAO,UAAU,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;CACF;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,eAAe,EAAE,CAAC,MAAM,EAAE,CAAC;AACxC,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * grep — 按正则搜索文件内容(ripgrep 优先,grep 回退)
3
+ */
4
+ import { type ExecOptions } from 'node:child_process';
5
+ import type { Tool, ToolContext, ToolParametersSchema, ToolResult } from '@zhin.js/core';
6
+ import { BuiltinBaseTool } from './builtin-base-tool.js';
7
+ /** 可注入以便单测(默认 `promisify(exec)`) */
8
+ export type GrepExecAsync = (command: string, options?: ExecOptions) => Promise<{
9
+ stdout: string;
10
+ stderr: string;
11
+ }>;
12
+ export declare const GREP_PARAMETERS: ToolParametersSchema;
13
+ export declare class GrepBuiltinTool extends BuiltinBaseTool {
14
+ private readonly execAsync;
15
+ readonly name = "grep";
16
+ readonly description = "\u6309\u6B63\u5219\u641C\u7D22\u6587\u4EF6\u5185\u5BB9\uFF0C\u8FD4\u56DE\u5339\u914D\u884C\u548C\u884C\u53F7\u3002\u4F18\u5148\u4F7F\u7528 ripgrep (rg)\uFF0C\u56DE\u9000\u5230 grep\u3002";
17
+ readonly parameters: ToolParametersSchema<Record<string, any>>;
18
+ readonly kind = "file";
19
+ constructor(execAsync?: GrepExecAsync);
20
+ run(args: Record<string, unknown>, _context?: ToolContext): Promise<ToolResult>;
21
+ }
22
+ export declare function createGrepTool(): Tool;
23
+ //# sourceMappingURL=grep-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep-tool.d.ts","sourceRoot":"","sources":["../../src/builtin/grep-tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAQ,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAG5D,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGzF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAIzD,oCAAoC;AACpC,MAAM,MAAM,aAAa,GAAG,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,KAClB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEjD,eAAO,MAAM,eAAe,EAAE,oBAc7B,CAAC;AAEF,qBAAa,eAAgB,SAAQ,eAAe;IAOtC,OAAO,CAAC,QAAQ,CAAC,SAAS;IANtC,QAAQ,CAAC,IAAI,UAAU;IACvB,QAAQ,CAAC,WAAW,gMAC+B;IACnD,QAAQ,CAAC,UAAU,4CAAmB;IACtC,QAAQ,CAAC,IAAI,UAAU;gBAEM,SAAS,GAAE,aAAgC;IAMlE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;CAuEtF;AAED,wBAAgB,cAAc,IAAI,IAAI,CAErC"}