@ai-zen/agents-sdk 0.4.0 → 0.5.1

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 (91) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +19 -15
  3. package/dist/capabilities/discovery/builtin.d.ts +7 -6
  4. package/dist/capabilities/discovery/builtin.js +10 -9
  5. package/dist/capabilities/implements/builtin/BatchEditTool.d.ts +15 -0
  6. package/dist/capabilities/implements/builtin/BatchEditTool.js +82 -0
  7. package/dist/capabilities/implements/builtin/CopyTool.d.ts +10 -0
  8. package/dist/capabilities/implements/builtin/CopyTool.js +43 -0
  9. package/dist/capabilities/implements/builtin/CwdTool.d.ts +6 -0
  10. package/dist/capabilities/implements/builtin/CwdTool.js +20 -0
  11. package/dist/capabilities/implements/builtin/DownloadFileTool.d.ts +9 -0
  12. package/dist/capabilities/implements/builtin/{downloadFile.js → DownloadFileTool.js} +29 -24
  13. package/dist/capabilities/implements/builtin/EditTool.d.ts +11 -0
  14. package/dist/capabilities/implements/builtin/EditTool.js +84 -0
  15. package/dist/capabilities/implements/builtin/ExecAsyncTool.d.ts +10 -0
  16. package/dist/capabilities/implements/builtin/{execAsync.js → ExecAsyncTool.js} +32 -34
  17. package/dist/capabilities/implements/builtin/ExecTool.d.ts +9 -0
  18. package/dist/capabilities/implements/builtin/ExecTool.js +46 -0
  19. package/dist/capabilities/implements/builtin/ExistTool.d.ts +8 -0
  20. package/dist/capabilities/implements/builtin/ExistTool.js +30 -0
  21. package/dist/capabilities/implements/builtin/FindTextTool.d.ts +12 -0
  22. package/dist/capabilities/implements/builtin/{findText.js → FindTextTool.js} +43 -37
  23. package/dist/capabilities/implements/builtin/GenerateImageTool.d.ts +21 -0
  24. package/dist/capabilities/implements/builtin/GenerateImageTool.js +121 -0
  25. package/dist/capabilities/implements/builtin/GlobTool.d.ts +10 -0
  26. package/dist/capabilities/implements/builtin/GlobTool.js +51 -0
  27. package/dist/capabilities/implements/builtin/LsTool.d.ts +8 -0
  28. package/dist/capabilities/implements/builtin/LsTool.js +33 -0
  29. package/dist/capabilities/implements/builtin/MkdirTool.d.ts +9 -0
  30. package/dist/capabilities/implements/builtin/MkdirTool.js +39 -0
  31. package/dist/capabilities/implements/builtin/ReadFileTool.d.ts +8 -0
  32. package/dist/capabilities/implements/builtin/ReadFileTool.js +37 -0
  33. package/dist/capabilities/implements/builtin/RenameTool.d.ts +9 -0
  34. package/dist/capabilities/implements/builtin/RenameTool.js +37 -0
  35. package/dist/capabilities/implements/builtin/RmTool.d.ts +9 -0
  36. package/dist/capabilities/implements/builtin/RmTool.js +39 -0
  37. package/dist/capabilities/implements/builtin/SleepTool.d.ts +8 -0
  38. package/dist/capabilities/implements/builtin/SleepTool.js +46 -0
  39. package/dist/capabilities/implements/builtin/WriteFileTool.d.ts +9 -0
  40. package/dist/capabilities/implements/builtin/WriteFileTool.js +40 -0
  41. package/dist/capabilities/implements/builtin/index.d.ts +29 -21
  42. package/dist/capabilities/implements/builtin/index.js +44 -37
  43. package/dist/capabilities/implements/builtin/test-helpers.d.ts +3 -0
  44. package/dist/capabilities/implements/builtin/test-helpers.js +4 -0
  45. package/dist/index.d.ts +5 -9
  46. package/dist/index.js +6 -9
  47. package/dist/runtime/Provider.d.ts +9 -1
  48. package/dist/runtime/Provider.js +7 -1
  49. package/dist/runtime/SdkCallbackTool.d.ts +28 -0
  50. package/dist/runtime/SdkCallbackTool.js +33 -0
  51. package/dist/types/index.d.ts +12 -20
  52. package/package.json +2 -2
  53. package/dist/capabilities/implements/builtin/batchEdit.d.ts +0 -2
  54. package/dist/capabilities/implements/builtin/batchEdit.js +0 -76
  55. package/dist/capabilities/implements/builtin/copy.d.ts +0 -2
  56. package/dist/capabilities/implements/builtin/copy.js +0 -38
  57. package/dist/capabilities/implements/builtin/cwd.d.ts +0 -2
  58. package/dist/capabilities/implements/builtin/cwd.js +0 -15
  59. package/dist/capabilities/implements/builtin/downloadFile.d.ts +0 -2
  60. package/dist/capabilities/implements/builtin/edit.d.ts +0 -2
  61. package/dist/capabilities/implements/builtin/edit.js +0 -79
  62. package/dist/capabilities/implements/builtin/exec.d.ts +0 -2
  63. package/dist/capabilities/implements/builtin/exec.js +0 -38
  64. package/dist/capabilities/implements/builtin/execAsync.d.ts +0 -2
  65. package/dist/capabilities/implements/builtin/exist.d.ts +0 -2
  66. package/dist/capabilities/implements/builtin/exist.js +0 -25
  67. package/dist/capabilities/implements/builtin/findText.d.ts +0 -2
  68. package/dist/capabilities/implements/builtin/generateImage.d.ts +0 -9
  69. package/dist/capabilities/implements/builtin/generateImage.js +0 -112
  70. package/dist/capabilities/implements/builtin/glob.d.ts +0 -2
  71. package/dist/capabilities/implements/builtin/glob.js +0 -45
  72. package/dist/capabilities/implements/builtin/ls.d.ts +0 -2
  73. package/dist/capabilities/implements/builtin/ls.js +0 -28
  74. package/dist/capabilities/implements/builtin/mkdir.d.ts +0 -2
  75. package/dist/capabilities/implements/builtin/mkdir.js +0 -34
  76. package/dist/capabilities/implements/builtin/readFile.d.ts +0 -2
  77. package/dist/capabilities/implements/builtin/readFile.js +0 -31
  78. package/dist/capabilities/implements/builtin/rename.d.ts +0 -2
  79. package/dist/capabilities/implements/builtin/rename.js +0 -32
  80. package/dist/capabilities/implements/builtin/rm.d.ts +0 -2
  81. package/dist/capabilities/implements/builtin/rm.js +0 -34
  82. package/dist/capabilities/implements/builtin/sleep.d.ts +0 -2
  83. package/dist/capabilities/implements/builtin/sleep.js +0 -41
  84. package/dist/capabilities/implements/builtin/writeFile.d.ts +0 -2
  85. package/dist/capabilities/implements/builtin/writeFile.js +0 -34
  86. package/dist/crud/ConversationRepository.d.ts +0 -9
  87. package/dist/crud/ConversationRepository.js +0 -10
  88. package/dist/crud/DraftRepository.d.ts +0 -15
  89. package/dist/crud/DraftRepository.js +0 -52
  90. package/dist/plugin/AutoDraftPlugin.d.ts +0 -26
  91. package/dist/plugin/AutoDraftPlugin.js +0 -62
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.1] - 2026-08-03
4
+
5
+ ### 🛠 优化
6
+
7
+ - **依赖 `@ai-zen/agents-core` 升级并改为范围版本** — 从 `workspace:*`(发布时替换为精确版本 `3.0.1`)改为 `workspace:^`(发布为 `^3.1.0`)。core 3.1.0 起 `Message` 构造自动生成 `id`,SDK 透传的消息随之携带稳定 id;范围版本使 core 后续 minor/patch 升级不再需要 SDK 单独发版跟进
8
+
9
+ ## [0.5.0] - 2026-07-29
10
+
11
+ ### 💥 破坏性变更
12
+
13
+ - **内置工具全部类化** — 17 个内置工具从单例 `CallbackTool` 实例改为类(`CwdTool`、`ReadFileTool`、`WriteFileTool`、`ExecTool` 等,PascalCase 命名),继承新抽象基类 `SdkCallbackTool`。`BUILTIN_TOOLS` 单例注册表替换为 `BUILTIN_TOOL_CLASSES` 类注册表(`Array<new (env: ToolEnv) => SdkCallbackTool>`)
14
+ - **`generateImage` 类化为 `GenerateImageTool`** — 删除工厂函数 `createGenerateImageTool(config)`,构造签名与其它内置工具统一为 `(env: ToolEnv)`。仍按 `config.defaultImageModel` 条件注册,不进入 `BUILTIN_TOOL_CLASSES` 静态注册表
15
+ - **`discoverBuiltinTools` 签名变更** — 从 `discoverBuiltinTools(config: AppConfig)` 改为 `discoverBuiltinTools(env: ToolEnv)`,用 `env` 实例化工具类
16
+ - **`Provider` 新增 `cwd` 与 `env`** — `cwd` 默认 `process.cwd()`,是相对路径解析的基准;`env: ToolEnv`(`{ cwd, config }`)在构造时建立,`refresh()` 用它实例化内置工具。**工具不再依赖全局 `process.cwd()`**,每个 Provider 可绑定不同工作目录
17
+ - **删除会话/草稿产品层** — `Conversation` / `Draft` 类型、`ConversationRepository`、`DraftRepository`、`AutoDraftPlugin` 及其测试全部移除。会话、草稿持久化下放给各端(CLI/Desktop)自行实现(可复用 `EntityRepository`)
18
+ - **`index.ts` 导出变更** — 移除 `Conversation`/`Draft`/`ConversationRepository`/`DraftRepository`/`AutoDraftPlugin`/`BUILTIN_TOOLS`/`execAsyncTool`/`sleepTool`/`createGenerateImageTool`;新增 `ToolEnv`、`SdkCallbackTool`、`BUILTIN_TOOL_CLASSES`、`GenerateImageTool` 及 17 个工具类
19
+
20
+ ### 🚀 新功能
21
+
22
+ - **`ToolEnv` 接口** — 工具环境 `{ cwd, config }`,在工具构造时注入,作为相对路径解析与配置读取的基准
23
+ - **`SdkCallbackTool` 抽象基类** — `env` 构造注入 + 子类实现 `call()` + `exec()` 桥接 + `resolve()` 相对路径解析(public,便于测试直调)
24
+
25
+ ### 🎯 优化
26
+
27
+ - **多会话并行支持** — `cwd` 下沉到 Provider(`ToolEnv.cwd`),多个 Provider 可并行服务不同工作目录的会话,互不干扰
28
+ - **工具实例 per-Provider** — 每个 Provider 通过 `discoverBuiltinTools(env)` 实例化自己的一套工具,消除全局单例状态
29
+
3
30
  ## [0.4.0] - 2026-07-29
4
31
 
5
32
  ### 💥 破坏性变更
package/README.md CHANGED
@@ -17,12 +17,12 @@ Desktop ──┘ │
17
17
  ## 模块分层
18
18
 
19
19
  ```
20
- types ← 纯类型,零业务依赖
20
+ types ← 纯类型,零业务依赖(含 ToolEnv 工具环境)
21
21
  config ← 读写 config.json + 迁移 + 内存缓存 + 原子写入
22
- crud ← 实体 CRUD(Endpoints / Models / Agents / Conversations / Draft)
22
+ crud ← 能力实体 CRUD(Agent 定义等;会话/草稿已下放给各端自行持久化)
23
23
  capabilities ← 能力发现与装配(内置 + 用户 + MCP + Skill + SubAgent)
24
- runtime ← Provider + 模型工厂 + Agent 组装 + MCP 连接管理 + 任务迁移
25
- plugin ← Agent 插件(autoMigrate、autoDraft、autoRefreshTools)
24
+ runtime ← Provider + 模型工厂 + Agent 组装 + MCP 连接管理 + 任务迁移 + SdkCallbackTool 工具基类
25
+ plugin ← Agent 插件(autoMigrate、autoRefreshTools)
26
26
  shared ← 日志、错误
27
27
  ```
28
28
 
@@ -32,14 +32,14 @@ shared ← 日志、错误
32
32
 
33
33
  | 实体 | 说明 |
34
34
  |------|------|
35
- | **Provider** | 全局上下文 + 能力注册表,持有配置、路径、模型工厂、MCP 管理器,整合发现 → 过滤 → 实例化 |
35
+ | **Provider** | 全局上下文 + 能力注册表,持有配置、路径(含 `cwd`)、模型工厂、MCP 管理器,整合发现 → 过滤 → 实例化 |
36
+ | **ToolEnv** | 工具环境 `{ cwd, config }`,Provider 实例化内置工具时注入,作为相对路径解析与配置读取的基准 |
37
+ | **SdkCallbackTool** | 内置工具抽象基类:`env` 构造注入 + 子类实现 `call()` + `resolve()` 相对路径解析 |
36
38
  | **SdkAgent** | 继承 Core Agent,携带 SDK 元数据,支持 `use()` 插件注册 |
37
39
  | **AgentPlugin** | 插件接口(`onInit`, `onBeforeSend`, `onAfterSend`, `onInnerLoopStart`, `onInnerLoopEnd`) |
38
40
  | **Endpoint** | API 端点(baseUrl + apiKey) |
39
41
  | **Model** | 模型配置,绑定 Endpoint |
40
42
  | **SubAgent** | 有 `function` 字段的 Agent,可被其他 Agent 作为工具调用 |
41
- | **Conversation** | 对话记录 |
42
- | **Draft** | 当前会话自动保存 |
43
43
 
44
44
  ## 权限模型
45
45
 
@@ -56,10 +56,13 @@ Agent.permissions
56
56
  ## 消费模式
57
57
 
58
58
  ```typescript
59
- const provider = await Provider.create({ config, ...paths });
59
+ const provider = await Provider.create({
60
+ config,
61
+ cwd: "/path/to/workspace", // 每个 Provider 一个工作目录,多会话并行互不干扰
62
+ ...paths,
63
+ });
60
64
  const agent = createAgent(provider, "my-agent");
61
- agent.use(new AutoMigratePlugin({ maxTokens, migrationAgent, onHandoff }));
62
- agent.use(new AutoDraftPlugin({ draftsDir, agentId, modelId }));
65
+ agent.use(new AutoMigratePlugin({ maxTokens, migrationAgent, onMigrated }));
63
66
  agent.use(new AutoRefreshToolsPlugin());
64
67
  await agent.init();
65
68
  await agent.send("你好");
@@ -71,15 +74,17 @@ await agent.send("你好");
71
74
  |------|------|
72
75
  | `types` | ✅ 已实现 — 核心实体、权限模型、MCP 类型完整 |
73
76
  | `config` | ✅ 已实现 — ConfigManager + 出厂默认配置 + 一键 bootstrap |
74
- | `crud` | ✅ 已实现 — Agent / Conversation / Draft 完整 CRUD |
77
+ | `crud` | ✅ 已实现 — Agent 等能力实体 CRUD(会话/草稿由各端自行持久化) |
75
78
  | `capabilities` | ✅ 已实现 — 发现 + 权限过滤 + 安全预过滤 + 枚举披露 |
76
79
  | `runtime` | ✅ 已实现 — Provider、Capabilities、createAgent、MCP 连接管理、任务迁移 |
77
- | `plugin` | ✅ 已实现 — AutoMigratePlugin / AutoDraftPlugin / AutoRefreshToolsPlugin |
80
+ | `plugin` | ✅ 已实现 — AutoMigratePlugin / AutoRefreshToolsPlugin |
78
81
  | `shared` | ✅ 已实现 — SdkError + 可注入 Logger |
79
- | 测试 | ✅ 593 个测试,68 个文件,全通过(含真实 API 聊天 e2e) |
82
+ | 测试 | ✅ 409 个测试,47 个文件,全通过(含真实 API 聊天 e2e) |
80
83
 
81
84
  ## 内置工具
82
85
 
86
+ 内置工具全部类化(继承 `SdkCallbackTool`),由 Provider 用 `ToolEnv` 实例化——每个 Provider 一套实例,`cwd` 注入,相对路径以 `Provider.cwd` 为基准,不依赖全局 `process.cwd()`。
87
+
83
88
  | 工具 | 说明 |
84
89
  |------|------|
85
90
  | `cwd` | 获取当前工作目录 |
@@ -100,7 +105,7 @@ await agent.send("你好");
100
105
  | `edit` | 编辑文件中的文本 |
101
106
  | `sleep` | 等待指定毫秒数后继续 |
102
107
 
103
- 条件注入(需配置 `imageModels`):
108
+ 条件注入(`GenerateImageTool` 需配置 `defaultImageModel` 才注册):
104
109
 
105
110
  | 工具 | 说明 |
106
111
  |------|------|
@@ -111,7 +116,6 @@ await agent.send("你好");
111
116
  | 插件 | 说明 |
112
117
  |------|------|
113
118
  | `AutoMigratePlugin` | 上下文超限时自动触发任务迁移,生成交接文档,透明替换 Agent |
114
- | `AutoDraftPlugin` | 每次 `send()` 后自动保存当前消息历史到 draft 文件 |
115
119
  | `AutoRefreshToolsPlugin` | 每次 `send()` 前重新扫描文件系统,刷新工具列表 |
116
120
 
117
121
  ## 设计原则
@@ -1,8 +1,9 @@
1
- import { Tool } from "@ai-zen/agents-core";
2
- import type { AppConfig } from "../../types/index.js";
1
+ import type { Tool } from "@ai-zen/agents-core";
2
+ import type { ToolEnv } from "../../types/index.js";
3
3
  /**
4
- * 发现内置工具。直接返回 BUILTIN_TOOLS 实例。
5
- * 如果配置了 defaultImageModel,额外包含 generateImage 工具。
6
- * 与 discoverUserTools 保持对称:都返回 Tool[]。
4
+ * 发现内置工具:用 ToolEnv 实例化全部内置工具类。
5
+ *
6
+ * generateImage 依赖图片模型配置(defaultImageModel),未配置时不注册,
7
+ * 因此不进入 BUILTIN_TOOL_CLASSES 静态注册表,在此按条件实例化。
7
8
  */
8
- export declare function discoverBuiltinTools(config: AppConfig): Tool[];
9
+ export declare function discoverBuiltinTools(env: ToolEnv): Tool[];
@@ -1,16 +1,17 @@
1
- import { BUILTIN_TOOLS } from "../implements/builtin/index.js";
2
- import { createGenerateImageTool } from "../implements/builtin/generateImage.js";
1
+ import { BUILTIN_TOOL_CLASSES } from "../implements/builtin/index.js";
2
+ import { GenerateImageTool } from "../implements/builtin/GenerateImageTool.js";
3
3
  /**
4
- * 发现内置工具。直接返回 BUILTIN_TOOLS 实例。
5
- * 如果配置了 defaultImageModel,额外包含 generateImage 工具。
6
- * 与 discoverUserTools 保持对称:都返回 Tool[]。
4
+ * 发现内置工具:用 ToolEnv 实例化全部内置工具类。
5
+ *
6
+ * generateImage 依赖图片模型配置(defaultImageModel),未配置时不注册,
7
+ * 因此不进入 BUILTIN_TOOL_CLASSES 静态注册表,在此按条件实例化。
7
8
  */
8
- export function discoverBuiltinTools(config) {
9
- const tools = [...BUILTIN_TOOLS];
10
- if (config.defaultImageModel) {
9
+ export function discoverBuiltinTools(env) {
10
+ const tools = BUILTIN_TOOL_CLASSES.map((Cls) => new Cls(env));
11
+ if (env.config.defaultImageModel) {
11
12
  const existingNames = new Set(tools.map((t) => t.function.name));
12
13
  if (!existingNames.has("generateImage")) {
13
- tools.push(createGenerateImageTool(config));
14
+ tools.push(new GenerateImageTool(env));
14
15
  }
15
16
  }
16
17
  return tools;
@@ -0,0 +1,15 @@
1
+ import { SdkCallbackTool } from "../../../runtime/SdkCallbackTool.js";
2
+ import type { ToolEnv } from "../../../types/index.js";
3
+ interface Replacement {
4
+ oldText: string;
5
+ newText: string;
6
+ isReplaceAll?: boolean;
7
+ }
8
+ export declare class BatchEditTool extends SdkCallbackTool {
9
+ constructor(env: ToolEnv);
10
+ call(input: {
11
+ path: string;
12
+ replacements: Replacement[];
13
+ }): Promise<string>;
14
+ }
15
+ export {};
@@ -0,0 +1,82 @@
1
+ import * as fsp from "fs/promises";
2
+ import { SdkCallbackTool } from "../../../runtime/SdkCallbackTool.js";
3
+ export class BatchEditTool extends SdkCallbackTool {
4
+ constructor(env) {
5
+ super({
6
+ function: {
7
+ name: "batchEdit",
8
+ description: "批量编辑文件文本,可以优先使用这个工具对文件进行编辑",
9
+ parameters: {
10
+ type: "object",
11
+ properties: {
12
+ path: {
13
+ type: "string",
14
+ description: "文件路径",
15
+ },
16
+ replacements: {
17
+ type: "array",
18
+ description: "要替换的文本数组",
19
+ items: {
20
+ type: "object",
21
+ properties: {
22
+ oldText: {
23
+ type: "string",
24
+ description: "要替换的文本",
25
+ },
26
+ newText: {
27
+ type: "string",
28
+ description: "替换后的文本",
29
+ },
30
+ isReplaceAll: {
31
+ type: "boolean",
32
+ description: "是否替换所有匹配的文本(默认仅替换首次匹配)。使用此功能前应确保你提供的 oldText 足够精确,避免误替换",
33
+ default: false,
34
+ },
35
+ },
36
+ required: ["oldText", "newText"],
37
+ additionalProperties: false,
38
+ },
39
+ },
40
+ },
41
+ required: ["path", "replacements"],
42
+ additionalProperties: false,
43
+ },
44
+ },
45
+ env,
46
+ });
47
+ }
48
+ async call(input) {
49
+ try {
50
+ const filePath = this.resolve(input.path);
51
+ const content = await fsp.readFile(filePath, "utf-8");
52
+ let newContent = content;
53
+ const results = [];
54
+ for (const replacement of input.replacements) {
55
+ if (!newContent.includes(replacement.oldText)) {
56
+ results.push({
57
+ oldText: replacement.oldText,
58
+ newText: replacement.newText,
59
+ result: "文件中未精确匹配到要替换的文本",
60
+ });
61
+ continue;
62
+ }
63
+ if (replacement.isReplaceAll) {
64
+ newContent = newContent.replaceAll(replacement.oldText, replacement.newText);
65
+ }
66
+ else {
67
+ newContent = newContent.replace(replacement.oldText, replacement.newText);
68
+ }
69
+ results.push({
70
+ oldText: replacement.oldText,
71
+ newText: replacement.newText,
72
+ result: "success",
73
+ });
74
+ }
75
+ await fsp.writeFile(filePath, newContent);
76
+ return JSON.stringify(results);
77
+ }
78
+ catch (error) {
79
+ return error?.message;
80
+ }
81
+ }
82
+ }
@@ -0,0 +1,10 @@
1
+ import { SdkCallbackTool } from "../../../runtime/SdkCallbackTool.js";
2
+ import type { ToolEnv } from "../../../types/index.js";
3
+ export declare class CopyTool extends SdkCallbackTool {
4
+ constructor(env: ToolEnv);
5
+ call(input: {
6
+ src: string;
7
+ dest: string;
8
+ recursive?: boolean;
9
+ }): Promise<string>;
10
+ }
@@ -0,0 +1,43 @@
1
+ import * as fsp from "fs/promises";
2
+ import { SdkCallbackTool } from "../../../runtime/SdkCallbackTool.js";
3
+ export class CopyTool extends SdkCallbackTool {
4
+ constructor(env) {
5
+ super({
6
+ function: {
7
+ name: "copy",
8
+ description: "复制文件或目录(相当于 cp 命令)",
9
+ parameters: {
10
+ type: "object",
11
+ properties: {
12
+ src: {
13
+ type: "string",
14
+ description: "源路径",
15
+ },
16
+ dest: {
17
+ type: "string",
18
+ description: "目标路径",
19
+ },
20
+ recursive: {
21
+ type: "boolean",
22
+ description: "是否递归复制目录,复制目录时需设为 true",
23
+ },
24
+ },
25
+ required: ["src", "dest"],
26
+ additionalProperties: false,
27
+ },
28
+ },
29
+ env,
30
+ });
31
+ }
32
+ async call(input) {
33
+ try {
34
+ await fsp.cp(this.resolve(input.src), this.resolve(input.dest), {
35
+ recursive: input.recursive ?? false,
36
+ });
37
+ return "success";
38
+ }
39
+ catch (error) {
40
+ return error?.message;
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,6 @@
1
+ import { SdkCallbackTool } from "../../../runtime/SdkCallbackTool.js";
2
+ import type { ToolEnv } from "../../../types/index.js";
3
+ export declare class CwdTool extends SdkCallbackTool {
4
+ constructor(env: ToolEnv);
5
+ call(): string;
6
+ }
@@ -0,0 +1,20 @@
1
+ import { SdkCallbackTool } from "../../../runtime/SdkCallbackTool.js";
2
+ export class CwdTool extends SdkCallbackTool {
3
+ constructor(env) {
4
+ super({
5
+ function: {
6
+ name: "cwd",
7
+ description: "获取当前工作目录 cwd",
8
+ parameters: {
9
+ type: "object",
10
+ properties: {},
11
+ required: [],
12
+ },
13
+ },
14
+ env,
15
+ });
16
+ }
17
+ call() {
18
+ return this.env.cwd;
19
+ }
20
+ }
@@ -0,0 +1,9 @@
1
+ import { SdkCallbackTool } from "../../../runtime/SdkCallbackTool.js";
2
+ import type { ToolEnv } from "../../../types/index.js";
3
+ export declare class DownloadFileTool extends SdkCallbackTool {
4
+ constructor(env: ToolEnv);
5
+ call(input: {
6
+ url: string;
7
+ outputPath?: string;
8
+ }): Promise<string>;
9
+ }
@@ -1,34 +1,39 @@
1
- import { CallbackTool } from "@ai-zen/agents-core";
2
1
  import * as fsp from "fs/promises";
3
2
  import * as path from "path";
4
- export const downloadFileTool = new CallbackTool({
5
- function: {
6
- name: "downloadFile",
7
- description: "从 URL 下载文件(图片、PDF 等二进制文件)并保存到本地磁盘。自动从 URL 推断文件名,也可指定保存路径。",
8
- parameters: {
9
- type: "object",
10
- properties: {
11
- url: {
12
- type: "string",
13
- description: "文件下载链接",
14
- },
15
- outputPath: {
16
- type: "string",
17
- description: "保存路径(可选)。可以是目录或完整文件路径。不指定则下载到当前工作目录,自动从 URL 推断文件名。",
3
+ import { SdkCallbackTool } from "../../../runtime/SdkCallbackTool.js";
4
+ export class DownloadFileTool extends SdkCallbackTool {
5
+ constructor(env) {
6
+ super({
7
+ function: {
8
+ name: "downloadFile",
9
+ description: "从 URL 下载文件(图片、PDF 等二进制文件)并保存到本地磁盘。自动从 URL 推断文件名,也可指定保存路径。",
10
+ parameters: {
11
+ type: "object",
12
+ properties: {
13
+ url: {
14
+ type: "string",
15
+ description: "文件下载链接",
16
+ },
17
+ outputPath: {
18
+ type: "string",
19
+ description: "保存路径(可选)。可以是目录或完整文件路径。不指定则下载到当前工作目录,自动从 URL 推断文件名。",
20
+ },
21
+ },
22
+ required: ["url"],
23
+ additionalProperties: false,
18
24
  },
19
25
  },
20
- required: ["url"],
21
- additionalProperties: false,
22
- },
23
- },
24
- async callback(input) {
26
+ env,
27
+ });
28
+ }
29
+ async call(input) {
25
30
  try {
26
31
  const url = input.url;
27
32
  if (!url)
28
33
  throw new Error("url 不能为空");
29
34
  let savePath;
30
35
  if (input.outputPath) {
31
- savePath = input.outputPath;
36
+ savePath = this.resolve(input.outputPath);
32
37
  const stat = await fsp.stat(savePath).catch(() => null);
33
38
  if (stat?.isDirectory()) {
34
39
  const urlPath = new URL(url).pathname;
@@ -39,7 +44,7 @@ export const downloadFileTool = new CallbackTool({
39
44
  else {
40
45
  const urlPath = new URL(url).pathname;
41
46
  const fileName = path.basename(urlPath) || `download_${Date.now()}`;
42
- savePath = path.join(process.cwd(), fileName);
47
+ savePath = path.join(this.env.cwd, fileName);
43
48
  }
44
49
  await fsp.mkdir(path.dirname(savePath), { recursive: true });
45
50
  const response = await fetch(url);
@@ -66,5 +71,5 @@ export const downloadFileTool = new CallbackTool({
66
71
  error: error?.message || "下载失败",
67
72
  });
68
73
  }
69
- },
70
- });
74
+ }
75
+ }
@@ -0,0 +1,11 @@
1
+ import { SdkCallbackTool } from "../../../runtime/SdkCallbackTool.js";
2
+ import type { ToolEnv } from "../../../types/index.js";
3
+ export declare class EditTool extends SdkCallbackTool {
4
+ constructor(env: ToolEnv);
5
+ call(input: {
6
+ path: string;
7
+ oldText: string;
8
+ newText: string;
9
+ isReplaceAll?: boolean;
10
+ }): Promise<string>;
11
+ }
@@ -0,0 +1,84 @@
1
+ import * as fsp from "fs/promises";
2
+ import { SdkCallbackTool } from "../../../runtime/SdkCallbackTool.js";
3
+ function countOccurrences(content, text) {
4
+ let count = 0;
5
+ let pos = 0;
6
+ while (true) {
7
+ pos = content.indexOf(text, pos);
8
+ if (pos === -1)
9
+ break;
10
+ count++;
11
+ pos += text.length;
12
+ }
13
+ return count;
14
+ }
15
+ export class EditTool extends SdkCallbackTool {
16
+ constructor(env) {
17
+ super({
18
+ function: {
19
+ name: "edit",
20
+ description: "编辑文件中的文本,支持精确替换或替换所有匹配项",
21
+ parameters: {
22
+ type: "object",
23
+ properties: {
24
+ path: {
25
+ type: "string",
26
+ description: "文件路径",
27
+ },
28
+ oldText: {
29
+ type: "string",
30
+ description: "要替换的文本",
31
+ },
32
+ newText: {
33
+ type: "string",
34
+ description: "替换后的文本",
35
+ },
36
+ isReplaceAll: {
37
+ type: "boolean",
38
+ description: "是否替换所有匹配的文本(默认 false,仅替换首次匹配)。使用此功能前应确保你提供的 oldText 足够精确,避免误替换",
39
+ default: false,
40
+ },
41
+ },
42
+ required: ["path", "oldText", "newText"],
43
+ additionalProperties: false,
44
+ },
45
+ },
46
+ env,
47
+ });
48
+ }
49
+ async call(input) {
50
+ try {
51
+ const filePath = this.resolve(input.path);
52
+ const oldText = input.oldText;
53
+ const newText = input.newText;
54
+ const isReplaceAll = input.isReplaceAll ?? false;
55
+ const content = await fsp.readFile(filePath, "utf-8");
56
+ const count = countOccurrences(content, oldText);
57
+ if (count === 0) {
58
+ return JSON.stringify({
59
+ result: "文件中未精确匹配到要替换的文本",
60
+ matchCount: 0,
61
+ });
62
+ }
63
+ const newContent = isReplaceAll
64
+ ? content.replaceAll(oldText, newText)
65
+ : content.replace(oldText, newText);
66
+ await fsp.writeFile(filePath, newContent);
67
+ if (!isReplaceAll && count > 1) {
68
+ return JSON.stringify({
69
+ result: `警告:未开启替换所有(isReplaceAll=false),但文本 "${oldText}" 在文件中出现了 ${count} 次,仅替换了首次匹配。如果希望替换所有匹配,请将 isReplaceAll 设为 true`,
70
+ matchCount: count,
71
+ replacedCount: 1,
72
+ });
73
+ }
74
+ return JSON.stringify({
75
+ result: "success",
76
+ matchCount: count,
77
+ replacedCount: isReplaceAll ? count : 1,
78
+ });
79
+ }
80
+ catch (error) {
81
+ return error?.message;
82
+ }
83
+ }
84
+ }
@@ -0,0 +1,10 @@
1
+ import { SdkCallbackTool } from "../../../runtime/SdkCallbackTool.js";
2
+ import type { ToolEnv } from "../../../types/index.js";
3
+ export declare class ExecAsyncTool extends SdkCallbackTool {
4
+ constructor(env: ToolEnv);
5
+ call(input: {
6
+ command: string;
7
+ cwd?: string;
8
+ detached?: boolean;
9
+ }): Promise<string>;
10
+ }