@zhin.js/agent 0.1.15 → 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.
- package/README.md +80 -43
- package/lib/builtin/activate-skill-tool.d.ts +21 -0
- package/lib/builtin/activate-skill-tool.d.ts.map +1 -0
- package/lib/builtin/activate-skill-tool.js +57 -0
- package/lib/builtin/activate-skill-tool.js.map +1 -0
- package/lib/builtin/ask-user-tool.d.ts +28 -0
- package/lib/builtin/ask-user-tool.d.ts.map +1 -0
- package/lib/builtin/ask-user-tool.js +182 -0
- package/lib/builtin/ask-user-tool.js.map +1 -0
- package/lib/builtin/bash-tool.d.ts +23 -0
- package/lib/builtin/bash-tool.d.ts.map +1 -0
- package/lib/builtin/bash-tool.js +64 -0
- package/lib/builtin/bash-tool.js.map +1 -0
- package/lib/builtin/bing-search-html.d.ts +37 -0
- package/lib/builtin/bing-search-html.d.ts.map +1 -0
- package/lib/builtin/bing-search-html.js +116 -0
- package/lib/builtin/bing-search-html.js.map +1 -0
- package/lib/builtin/builtin-base-tool.d.ts +25 -0
- package/lib/builtin/builtin-base-tool.d.ts.map +1 -0
- package/lib/builtin/builtin-base-tool.js +30 -0
- package/lib/builtin/builtin-base-tool.js.map +1 -0
- package/lib/builtin/edit-file-tool.d.ts +13 -0
- package/lib/builtin/edit-file-tool.d.ts.map +1 -0
- package/lib/builtin/edit-file-tool.js +81 -0
- package/lib/builtin/edit-file-tool.js.map +1 -0
- package/lib/builtin/file-edit-quote-utils.d.ts +24 -0
- package/lib/builtin/file-edit-quote-utils.d.ts.map +1 -0
- package/lib/builtin/file-edit-quote-utils.js +81 -0
- package/lib/builtin/file-edit-quote-utils.js.map +1 -0
- package/lib/builtin/glob-tool.d.ts +23 -0
- package/lib/builtin/glob-tool.d.ts.map +1 -0
- package/lib/builtin/glob-tool.js +54 -0
- package/lib/builtin/glob-tool.js.map +1 -0
- package/lib/builtin/grep-tool.d.ts +23 -0
- package/lib/builtin/grep-tool.d.ts.map +1 -0
- package/lib/builtin/grep-tool.js +118 -0
- package/lib/builtin/grep-tool.js.map +1 -0
- package/lib/builtin/install-skill-tool.d.ts +24 -0
- package/lib/builtin/install-skill-tool.d.ts.map +1 -0
- package/lib/builtin/install-skill-tool.js +76 -0
- package/lib/builtin/install-skill-tool.js.map +1 -0
- package/lib/builtin/list-dir-tool.d.ts +13 -0
- package/lib/builtin/list-dir-tool.d.ts.map +1 -0
- package/lib/builtin/list-dir-tool.js +59 -0
- package/lib/builtin/list-dir-tool.js.map +1 -0
- package/lib/builtin/read-file-tool.d.ts +14 -0
- package/lib/builtin/read-file-tool.d.ts.map +1 -0
- package/lib/builtin/read-file-tool.js +77 -0
- package/lib/builtin/read-file-tool.js.map +1 -0
- package/lib/builtin/read-memory-tool.d.ts +14 -0
- package/lib/builtin/read-memory-tool.d.ts.map +1 -0
- package/lib/builtin/read-memory-tool.js +49 -0
- package/lib/builtin/read-memory-tool.js.map +1 -0
- package/lib/builtin/spawn-task-tool.d.ts +20 -0
- package/lib/builtin/spawn-task-tool.d.ts.map +1 -0
- package/lib/builtin/spawn-task-tool.js +57 -0
- package/lib/builtin/spawn-task-tool.js.map +1 -0
- package/lib/builtin/todo-read-tool.d.ts +14 -0
- package/lib/builtin/todo-read-tool.d.ts.map +1 -0
- package/lib/builtin/todo-read-tool.js +56 -0
- package/lib/builtin/todo-read-tool.js.map +1 -0
- package/lib/builtin/todo-write-tool.d.ts +14 -0
- package/lib/builtin/todo-write-tool.d.ts.map +1 -0
- package/lib/builtin/todo-write-tool.js +54 -0
- package/lib/builtin/todo-write-tool.js.map +1 -0
- package/lib/builtin/web-fetch-tool.d.ts +19 -0
- package/lib/builtin/web-fetch-tool.d.ts.map +1 -0
- package/lib/builtin/web-fetch-tool.js +89 -0
- package/lib/builtin/web-fetch-tool.js.map +1 -0
- package/lib/builtin/web-search-locale.d.ts +16 -0
- package/lib/builtin/web-search-locale.d.ts.map +1 -0
- package/lib/builtin/web-search-locale.js +73 -0
- package/lib/builtin/web-search-locale.js.map +1 -0
- package/lib/builtin/web-search-tool.d.ts +20 -0
- package/lib/builtin/web-search-tool.d.ts.map +1 -0
- package/lib/builtin/web-search-tool.js +105 -0
- package/lib/builtin/web-search-tool.js.map +1 -0
- package/lib/builtin/web-tool-utils.d.ts +4 -0
- package/lib/builtin/web-tool-utils.d.ts.map +1 -0
- package/lib/builtin/web-tool-utils.js +4 -0
- package/lib/builtin/web-tool-utils.js.map +1 -0
- package/lib/builtin/write-file-tool.d.ts +13 -0
- package/lib/builtin/write-file-tool.d.ts.map +1 -0
- package/lib/builtin/write-file-tool.js +51 -0
- package/lib/builtin/write-file-tool.js.map +1 -0
- package/lib/builtin/write-memory-tool.d.ts +14 -0
- package/lib/builtin/write-memory-tool.d.ts.map +1 -0
- package/lib/builtin/write-memory-tool.js +50 -0
- package/lib/builtin/write-memory-tool.js.map +1 -0
- package/lib/builtin-tools.d.ts +10 -11
- package/lib/builtin-tools.d.ts.map +1 -1
- package/lib/builtin-tools.js +44 -862
- package/lib/builtin-tools.js.map +1 -1
- package/lib/defaults/tools.d.ts +3 -6
- package/lib/defaults/tools.d.ts.map +1 -1
- package/lib/defaults/tools.js +3 -11
- package/lib/defaults/tools.js.map +1 -1
- package/lib/index.d.ts +25 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +24 -3
- package/lib/index.js.map +1 -1
- package/lib/init/create-zhin-agent.d.ts.map +1 -1
- package/lib/init/create-zhin-agent.js +4 -3
- package/lib/init/create-zhin-agent.js.map +1 -1
- package/lib/init/message-media.d.ts +8 -0
- package/lib/init/message-media.d.ts.map +1 -0
- package/lib/init/message-media.js +75 -0
- package/lib/init/message-media.js.map +1 -0
- package/lib/init/output-renderer.d.ts +3 -0
- package/lib/init/output-renderer.d.ts.map +1 -0
- package/lib/init/output-renderer.js +38 -0
- package/lib/init/output-renderer.js.map +1 -0
- package/lib/init/register-ai-trigger.d.ts +1 -1
- package/lib/init/register-ai-trigger.d.ts.map +1 -1
- package/lib/init/register-ai-trigger.js +35 -159
- package/lib/init/register-ai-trigger.js.map +1 -1
- package/lib/init/register-builtin-tools.d.ts.map +1 -1
- package/lib/init/register-builtin-tools.js +9 -5
- package/lib/init/register-builtin-tools.js.map +1 -1
- package/lib/orchestrator/index.d.ts +2 -0
- package/lib/orchestrator/index.d.ts.map +1 -1
- package/lib/orchestrator/index.js +1 -0
- package/lib/orchestrator/index.js.map +1 -1
- package/lib/orchestrator/resource-registry.d.ts +1 -0
- package/lib/orchestrator/resource-registry.d.ts.map +1 -1
- package/lib/orchestrator/resource-registry.js +6 -0
- package/lib/orchestrator/resource-registry.js.map +1 -1
- package/lib/orchestrator/tool-registry.d.ts +5 -11
- package/lib/orchestrator/tool-registry.d.ts.map +1 -1
- package/lib/orchestrator/tool-registry.js +30 -75
- package/lib/orchestrator/tool-registry.js.map +1 -1
- package/lib/orchestrator/tool-selection.d.ts +39 -0
- package/lib/orchestrator/tool-selection.d.ts.map +1 -0
- package/lib/orchestrator/tool-selection.js +319 -0
- package/lib/orchestrator/tool-selection.js.map +1 -0
- package/lib/orchestrator/types.d.ts +2 -0
- package/lib/orchestrator/types.d.ts.map +1 -1
- package/lib/reserved-tools.d.ts +3 -0
- package/lib/reserved-tools.d.ts.map +1 -0
- package/lib/reserved-tools.js +30 -0
- package/lib/reserved-tools.js.map +1 -0
- package/lib/service.d.ts +9 -5
- package/lib/service.d.ts.map +1 -1
- package/lib/service.js +42 -36
- package/lib/service.js.map +1 -1
- package/lib/subagent.d.ts +6 -0
- package/lib/subagent.d.ts.map +1 -1
- package/lib/subagent.js +33 -15
- package/lib/subagent.js.map +1 -1
- package/lib/task-executor.d.ts +1 -0
- package/lib/task-executor.d.ts.map +1 -1
- package/lib/task-executor.js +15 -8
- package/lib/task-executor.js.map +1 -1
- package/lib/zhin-agent/builtin-tools.d.ts +1 -3
- package/lib/zhin-agent/builtin-tools.d.ts.map +1 -1
- package/lib/zhin-agent/builtin-tools.js +4 -41
- package/lib/zhin-agent/builtin-tools.js.map +1 -1
- package/lib/zhin-agent/config.d.ts +7 -0
- package/lib/zhin-agent/config.d.ts.map +1 -1
- package/lib/zhin-agent/config.js +12 -7
- package/lib/zhin-agent/config.js.map +1 -1
- package/lib/zhin-agent/context-budget.d.ts +27 -0
- package/lib/zhin-agent/context-budget.d.ts.map +1 -0
- package/lib/zhin-agent/context-budget.js +50 -0
- package/lib/zhin-agent/context-budget.js.map +1 -0
- package/lib/zhin-agent/index.d.ts +10 -0
- package/lib/zhin-agent/index.d.ts.map +1 -1
- package/lib/zhin-agent/index.js +120 -88
- package/lib/zhin-agent/index.js.map +1 -1
- package/lib/zhin-agent/model-harness.d.ts +29 -0
- package/lib/zhin-agent/model-harness.d.ts.map +1 -0
- package/lib/zhin-agent/model-harness.js +67 -0
- package/lib/zhin-agent/model-harness.js.map +1 -0
- package/lib/zhin-agent/pre-exec.d.ts +7 -0
- package/lib/zhin-agent/pre-exec.d.ts.map +1 -0
- package/lib/zhin-agent/pre-exec.js +25 -0
- package/lib/zhin-agent/pre-exec.js.map +1 -0
- package/lib/zhin-agent/prompt.d.ts +10 -8
- package/lib/zhin-agent/prompt.d.ts.map +1 -1
- package/lib/zhin-agent/prompt.js +37 -30
- package/lib/zhin-agent/prompt.js.map +1 -1
- package/lib/zhin-agent/text-sanitize.d.ts +8 -0
- package/lib/zhin-agent/text-sanitize.d.ts.map +1 -0
- package/lib/zhin-agent/text-sanitize.js +19 -0
- package/lib/zhin-agent/text-sanitize.js.map +1 -0
- package/lib/zhin-agent/tool-runtime.d.ts +31 -0
- package/lib/zhin-agent/tool-runtime.d.ts.map +1 -0
- package/lib/zhin-agent/tool-runtime.js +49 -0
- package/lib/zhin-agent/tool-runtime.js.map +1 -0
- package/package.json +8 -6
- package/lib/tools.d.ts +0 -45
- package/lib/tools.d.ts.map +0 -1
- package/lib/tools.js +0 -205
- package/lib/tools.js.map +0 -1
- package/lib/zhin-agent/tool-collector.d.ts +0 -22
- package/lib/zhin-agent/tool-collector.d.ts.map +0 -1
- package/lib/zhin-agent/tool-collector.js +0 -225
- package/lib/zhin-agent/tool-collector.js.map +0 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* grep — 按正则搜索文件内容(ripgrep 优先,grep 回退)
|
|
3
|
+
*/
|
|
4
|
+
import { exec } from 'node:child_process';
|
|
5
|
+
import { promisify } from 'node:util';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
import { assertFileAccess, shellEscape } from '../security/file-policy.js';
|
|
8
|
+
import { errMsg } from '../discovery/utils.js';
|
|
9
|
+
import { BuiltinBaseTool } from './builtin-base-tool.js';
|
|
10
|
+
const defaultExecAsync = promisify(exec);
|
|
11
|
+
export const GREP_PARAMETERS = {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
pattern: { type: 'string', description: '正则表达式' },
|
|
15
|
+
path: { type: 'string', description: '搜索路径(默认 .)' },
|
|
16
|
+
include: { type: 'string', description: '文件类型过滤(如 *.ts)' },
|
|
17
|
+
context: { type: 'number', description: '匹配行上下文行数(-C 参数)' },
|
|
18
|
+
before: { type: 'number', description: '匹配行之前显示行数(-B 参数)' },
|
|
19
|
+
after: { type: 'number', description: '匹配行之后显示行数(-A 参数)' },
|
|
20
|
+
ignore_case: { type: 'boolean', description: '大小写不敏感搜索(-i 参数)' },
|
|
21
|
+
multiline: { type: 'boolean', description: '多行模式,. 匹配换行(仅 ripgrep 支持)' },
|
|
22
|
+
limit: { type: 'number', description: '最多返回结果行数(默认 50)' },
|
|
23
|
+
},
|
|
24
|
+
required: ['pattern'],
|
|
25
|
+
};
|
|
26
|
+
export class GrepBuiltinTool extends BuiltinBaseTool {
|
|
27
|
+
execAsync;
|
|
28
|
+
name = 'grep';
|
|
29
|
+
description = '按正则搜索文件内容,返回匹配行和行号。优先使用 ripgrep (rg),回退到 grep。';
|
|
30
|
+
parameters = GREP_PARAMETERS;
|
|
31
|
+
kind = 'file';
|
|
32
|
+
constructor(execAsync = defaultExecAsync) {
|
|
33
|
+
super();
|
|
34
|
+
this.execAsync = execAsync;
|
|
35
|
+
this.tags.push('search', 'regex');
|
|
36
|
+
this.keywords.push('搜索', '查找内容', 'grep', '正则', 'rg', 'ripgrep');
|
|
37
|
+
}
|
|
38
|
+
async run(args, _context) {
|
|
39
|
+
const patternArg = args.pattern;
|
|
40
|
+
if (typeof patternArg !== 'string' || !patternArg.trim()) {
|
|
41
|
+
return 'Error: pattern is required';
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const searchPath = typeof args.path === 'string' && args.path.trim() ? args.path : '.';
|
|
45
|
+
assertFileAccess(path.resolve(process.cwd(), searchPath));
|
|
46
|
+
const safePattern = shellEscape(patternArg);
|
|
47
|
+
const safePath = shellEscape(searchPath);
|
|
48
|
+
const limit = typeof args.limit === 'number' && Number.isFinite(args.limit) ? args.limit : 50;
|
|
49
|
+
let useRipgrep = false;
|
|
50
|
+
try {
|
|
51
|
+
await this.execAsync('rg --version', { timeout: 3000 });
|
|
52
|
+
useRipgrep = true;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
/* ripgrep 不可用,回退到 grep */
|
|
56
|
+
}
|
|
57
|
+
let cmd;
|
|
58
|
+
if (useRipgrep) {
|
|
59
|
+
const rgFlags = ['-n'];
|
|
60
|
+
if (args.ignore_case === true)
|
|
61
|
+
rgFlags.push('-i');
|
|
62
|
+
if (args.multiline === true)
|
|
63
|
+
rgFlags.push('-U', '--multiline-dotall');
|
|
64
|
+
if (typeof args.context === 'number' && Number.isFinite(args.context)) {
|
|
65
|
+
rgFlags.push(`-C${args.context}`);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
if (typeof args.before === 'number' && Number.isFinite(args.before)) {
|
|
69
|
+
rgFlags.push(`-B${args.before}`);
|
|
70
|
+
}
|
|
71
|
+
if (typeof args.after === 'number' && Number.isFinite(args.after)) {
|
|
72
|
+
rgFlags.push(`-A${args.after}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (typeof args.include === 'string' && args.include.trim()) {
|
|
76
|
+
rgFlags.push(`--glob=${shellEscape(args.include)}`);
|
|
77
|
+
}
|
|
78
|
+
cmd = `rg ${rgFlags.join(' ')} ${safePattern} ${safePath} 2>/dev/null | head -${limit}`;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
const grepFlags = ['-rn'];
|
|
82
|
+
if (args.ignore_case === true)
|
|
83
|
+
grepFlags.push('-i');
|
|
84
|
+
if (typeof args.context === 'number' && Number.isFinite(args.context)) {
|
|
85
|
+
grepFlags.push(`-C${args.context}`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
if (typeof args.before === 'number' && Number.isFinite(args.before)) {
|
|
89
|
+
grepFlags.push(`-B${args.before}`);
|
|
90
|
+
}
|
|
91
|
+
if (typeof args.after === 'number' && Number.isFinite(args.after)) {
|
|
92
|
+
grepFlags.push(`-A${args.after}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const includeFlag = typeof args.include === 'string' && args.include.trim()
|
|
96
|
+
? `--include=${shellEscape(args.include)}`
|
|
97
|
+
: '';
|
|
98
|
+
cmd = `grep ${grepFlags.join(' ')} ${includeFlag} ${safePattern} ${safePath} 2>/dev/null | head -${limit}`;
|
|
99
|
+
}
|
|
100
|
+
const { stdout } = await this.execAsync(cmd, { cwd: process.cwd() });
|
|
101
|
+
const engine = useRipgrep ? '(ripgrep)' : '(grep)';
|
|
102
|
+
return stdout.trim()
|
|
103
|
+
? `${engine}\n${stdout.trim()}`
|
|
104
|
+
: `No matches for '${patternArg}' ${engine}`;
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
const err = e;
|
|
108
|
+
// rg/grep:无匹配时常为 exit code 1;Node 也可能以 number 或 string 形式携带
|
|
109
|
+
if (Number(err.code) === 1)
|
|
110
|
+
return `No matches for '${patternArg}'`;
|
|
111
|
+
return `Error: ${errMsg(e)}`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export function createGrepTool() {
|
|
116
|
+
return new GrepBuiltinTool().toTool();
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=grep-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grep-tool.js","sourceRoot":"","sources":["../../src/builtin/grep-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type Tool, type ToolContext, type ToolParametersSchema, type ToolResult } from '@zhin.js/core';
|
|
2
|
+
import { BuiltinBaseTool } from './builtin-base-tool.js';
|
|
3
|
+
export interface InstallSkillToolOptions {
|
|
4
|
+
/**
|
|
5
|
+
* 安装根目录:将创建 `<skillName>/SKILL.md`。
|
|
6
|
+
* 默认 `join(process.cwd(), 'skills')`(与历史行为一致)。
|
|
7
|
+
*/
|
|
8
|
+
skillsInstallRoot?: string;
|
|
9
|
+
/** 可注入以便单测 mock */
|
|
10
|
+
fetchImpl?: typeof fetch;
|
|
11
|
+
}
|
|
12
|
+
export declare const INSTALL_SKILL_PARAMETERS: ToolParametersSchema;
|
|
13
|
+
export declare class InstallSkillBuiltinTool extends BuiltinBaseTool {
|
|
14
|
+
private readonly opts;
|
|
15
|
+
readonly name = "install_skill";
|
|
16
|
+
readonly description = "\u4ECE URL \u4E0B\u8F7D SKILL.md \u5E76\u5B89\u88C5\u5230\u672C\u5730 skills/ \u76EE\u5F55\u3002\u7528\u6237\u8981\u6C42\u52A0\u5165/\u5B89\u88C5/\u4E0B\u8F7D\u67D0\u4E2A\u6280\u80FD\u65F6\u4F7F\u7528";
|
|
17
|
+
readonly parameters: ToolParametersSchema<Record<string, any>>;
|
|
18
|
+
readonly kind = "skill";
|
|
19
|
+
constructor(opts?: InstallSkillToolOptions);
|
|
20
|
+
private skillsRoot;
|
|
21
|
+
run(args: Record<string, unknown>, _context?: ToolContext): Promise<ToolResult>;
|
|
22
|
+
}
|
|
23
|
+
export declare function createInstallSkillTool(opts?: InstallSkillToolOptions): Tool;
|
|
24
|
+
//# sourceMappingURL=install-skill-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-skill-tool.d.ts","sourceRoot":"","sources":["../../src/builtin/install-skill-tool.ts"],"names":[],"mappings":"AAKA,OAAO,EAAU,KAAK,IAAI,EAAE,KAAK,WAAW,EAAE,KAAK,oBAAoB,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,eAAO,MAAM,wBAAwB,EAAE,oBAStC,CAAC;AAIF,qBAAa,uBAAwB,SAAQ,eAAe;IAO9C,OAAO,CAAC,QAAQ,CAAC,IAAI;IANjC,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,WAAW,8MACwC;IAC5D,QAAQ,CAAC,UAAU,4CAA4B;IAC/C,QAAQ,CAAC,IAAI,WAAW;gBAEK,IAAI,GAAE,uBAA4B;IAgB/D,OAAO,CAAC,UAAU;IAIZ,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;CAoCtF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAE3E"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* install_skill — 从 URL 下载 SKILL.md 并安装到本地 skills/ 目录
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'node:fs/promises';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
import { Logger } from '@zhin.js/core';
|
|
7
|
+
import { errMsg } from '../discovery/utils.js';
|
|
8
|
+
import { BuiltinBaseTool } from './builtin-base-tool.js';
|
|
9
|
+
export const INSTALL_SKILL_PARAMETERS = {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
url: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: 'SKILL.md 文件的完整 URL(如 https://example.com/skill.md)',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
required: ['url'],
|
|
18
|
+
};
|
|
19
|
+
const logger = new Logger(null, 'install-skill-tool');
|
|
20
|
+
export class InstallSkillBuiltinTool extends BuiltinBaseTool {
|
|
21
|
+
opts;
|
|
22
|
+
name = 'install_skill';
|
|
23
|
+
description = '从 URL 下载 SKILL.md 并安装到本地 skills/ 目录。用户要求加入/安装/下载某个技能时使用';
|
|
24
|
+
parameters = INSTALL_SKILL_PARAMETERS;
|
|
25
|
+
kind = 'skill';
|
|
26
|
+
constructor(opts = {}) {
|
|
27
|
+
super();
|
|
28
|
+
this.opts = opts;
|
|
29
|
+
this.tags.push('skill', 'install');
|
|
30
|
+
this.keywords.push('安装技能', '下载技能', '加入', '添加技能', 'install', 'skill', 'join', '学会', '学习技能');
|
|
31
|
+
}
|
|
32
|
+
skillsRoot() {
|
|
33
|
+
return this.opts.skillsInstallRoot ?? path.join(process.cwd(), 'skills');
|
|
34
|
+
}
|
|
35
|
+
async run(args, _context) {
|
|
36
|
+
const fetchFn = this.opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetchFn(args.url, {
|
|
39
|
+
headers: { 'User-Agent': 'Mozilla/5.0 (compatible; ZhinBot/1.0)' },
|
|
40
|
+
signal: AbortSignal.timeout(15000),
|
|
41
|
+
});
|
|
42
|
+
if (!response.ok)
|
|
43
|
+
return `Error: HTTP ${response.status} ${response.statusText}`;
|
|
44
|
+
const content = await response.text();
|
|
45
|
+
const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
46
|
+
if (!fmMatch)
|
|
47
|
+
return 'Error: 无效的 SKILL.md 文件(缺少 frontmatter)';
|
|
48
|
+
let jsYaml;
|
|
49
|
+
try {
|
|
50
|
+
jsYaml = await import('js-yaml');
|
|
51
|
+
if (jsYaml.default)
|
|
52
|
+
jsYaml = jsYaml.default;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return 'Error: 无法加载 yaml 解析器';
|
|
56
|
+
}
|
|
57
|
+
const metadata = jsYaml.load(fmMatch[1]);
|
|
58
|
+
if (!metadata?.name)
|
|
59
|
+
return 'Error: SKILL.md 缺少 name 字段';
|
|
60
|
+
const skillName = metadata.name;
|
|
61
|
+
const skillDir = path.join(this.skillsRoot(), skillName);
|
|
62
|
+
await fs.mkdir(skillDir, { recursive: true });
|
|
63
|
+
const skillPath = path.join(skillDir, 'SKILL.md');
|
|
64
|
+
await fs.writeFile(skillPath, content, 'utf-8');
|
|
65
|
+
logger.info(`技能已安装: ${skillName} → ${skillPath}`);
|
|
66
|
+
return `✅ 技能「${skillName}」已安装到 ${skillPath}。现在可以用 activate_skill("${skillName}") 激活它。`;
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
return `Error: ${errMsg(e)}`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export function createInstallSkillTool(opts) {
|
|
74
|
+
return new InstallSkillBuiltinTool(opts).toTool();
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=install-skill-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-skill-tool.js","sourceRoot":"","sources":["../../src/builtin/install-skill-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -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 LIST_DIR_PARAMETERS: ToolParametersSchema;
|
|
4
|
+
export declare class ListDirBuiltinTool extends BuiltinBaseTool {
|
|
5
|
+
readonly name = "list_dir";
|
|
6
|
+
readonly description = "\u5217\u51FA\u6307\u5B9A\u76EE\u5F55\u4E0B\u7684\u6587\u4EF6\u548C\u5B50\u76EE\u5F55\u540D\u79F0\u3002\u7528\u4E8E\u67E5\u770B\u76EE\u5F55\u7ED3\u6784\u3001\u6709\u54EA\u4E9B\u6587\u4EF6\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 createListDirTool(): Tool;
|
|
13
|
+
//# sourceMappingURL=list-dir-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-dir-tool.d.ts","sourceRoot":"","sources":["../../src/builtin/list-dir-tool.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGzF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,eAAO,MAAM,mBAAmB,EAAE,oBASjC,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,eAAe;IACrD,QAAQ,CAAC,IAAI,cAAc;IAC3B,QAAQ,CAAC,WAAW,sMACiB;IACrC,QAAQ,CAAC,UAAU,4CAAuB;IAC1C,QAAQ,CAAC,IAAI,UAAU;;IAmBjB,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;CAyBtF;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* list_dir — 列出目录内容
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'node:fs/promises';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
import { assertFileAccess } from '../security/file-policy.js';
|
|
7
|
+
import { expandHome, nodeErrToFileMessage } from '../discovery/utils.js';
|
|
8
|
+
import { BuiltinBaseTool } from './builtin-base-tool.js';
|
|
9
|
+
export const LIST_DIR_PARAMETERS = {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
path: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: '要列出的目录路径(绝对或相对项目根目录)',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
required: ['path'],
|
|
18
|
+
};
|
|
19
|
+
export class ListDirBuiltinTool extends BuiltinBaseTool {
|
|
20
|
+
name = 'list_dir';
|
|
21
|
+
description = '列出指定目录下的文件和子目录名称。用于查看目录结构、有哪些文件。';
|
|
22
|
+
parameters = LIST_DIR_PARAMETERS;
|
|
23
|
+
kind = 'file';
|
|
24
|
+
constructor() {
|
|
25
|
+
super();
|
|
26
|
+
this.tags.push('file', 'list');
|
|
27
|
+
this.keywords.push('列目录', '列出目录', '目录列表', '查看目录', 'list directory', 'list dir', 'ls', 'dir', '目录内容', '有哪些文件');
|
|
28
|
+
}
|
|
29
|
+
async run(args, _context) {
|
|
30
|
+
const pathArg = args.path;
|
|
31
|
+
if (typeof pathArg !== 'string' || !pathArg.trim()) {
|
|
32
|
+
return 'Error: path is required';
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const dirPath = path.resolve(process.cwd(), expandHome(pathArg));
|
|
36
|
+
assertFileAccess(dirPath);
|
|
37
|
+
const stat = await fs.stat(dirPath);
|
|
38
|
+
if (!stat.isDirectory()) {
|
|
39
|
+
return `Error: Not a directory: ${pathArg}`;
|
|
40
|
+
}
|
|
41
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
42
|
+
if (entries.length === 0) {
|
|
43
|
+
return `Directory ${pathArg} is empty`;
|
|
44
|
+
}
|
|
45
|
+
const lines = [];
|
|
46
|
+
for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
47
|
+
lines.push((e.isDirectory() ? '[DIR] ' : ' ') + e.name);
|
|
48
|
+
}
|
|
49
|
+
return lines.join('\n');
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
return nodeErrToFileMessage(e, pathArg, 'list');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function createListDirTool() {
|
|
57
|
+
return new ListDirBuiltinTool().toTool();
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=list-dir-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-dir-tool.js","sourceRoot":"","sources":["../../src/builtin/list-dir-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Tool, ToolContext, ToolParametersSchema, ToolResult } from '@zhin.js/core';
|
|
2
|
+
import { BuiltinBaseTool } from './builtin-base-tool.js';
|
|
3
|
+
export declare const READ_FILE_PARAMETERS: ToolParametersSchema;
|
|
4
|
+
export declare class ReadFileBuiltinTool extends BuiltinBaseTool {
|
|
5
|
+
readonly name = "read_file";
|
|
6
|
+
readonly description = "\u8BFB\u53D6\u6307\u5B9A\u8DEF\u5F84\u7684\u6587\u4EF6\u5185\u5BB9\u3002\u7528\u4E8E\u67E5\u770B\u3001\u6253\u5F00\u6216\u8BFB\u53D6\u4EFB\u610F\u6587\u672C\u6587\u4EF6\u3002\u56FE\u7247\u6587\u4EF6\u8FD4\u56DE Base64 \u6570\u636E\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
|
+
/** 工厂:供 createBuiltinTools 与其它入口使用 */
|
|
13
|
+
export declare function createReadFileTool(): Tool;
|
|
14
|
+
//# sourceMappingURL=read-file-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-file-tool.d.ts","sourceRoot":"","sources":["../../src/builtin/read-file-tool.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAOzF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAUzD,eAAO,MAAM,oBAAoB,EAAE,oBAWlC,CAAC;AAEF,qBAAa,mBAAoB,SAAQ,eAAe;IACtD,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,WAAW,kPAC+B;IACnD,QAAQ,CAAC,UAAU,4CAAwB;IAC3C,QAAQ,CAAC,IAAI,UAAU;;IAmBjB,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;CAoCtF;AAED,sCAAsC;AACtC,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* read_file — 内置文件读取(PRD #389 竖切1)
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'node:fs/promises';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
import { assertFileAccess, isBlockedDevicePath, MAX_READ_FILE_SIZE, } from '../security/file-policy.js';
|
|
7
|
+
import { expandHome, nodeErrToFileMessage } from '../discovery/utils.js';
|
|
8
|
+
import { BuiltinBaseTool } from './builtin-base-tool.js';
|
|
9
|
+
const IMAGE_EXTENSIONS = new Set([
|
|
10
|
+
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.svg', '.ico',
|
|
11
|
+
]);
|
|
12
|
+
function isImageFile(filePath) {
|
|
13
|
+
return IMAGE_EXTENSIONS.has(path.extname(filePath).toLowerCase());
|
|
14
|
+
}
|
|
15
|
+
export const READ_FILE_PARAMETERS = {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
file_path: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: '要读取的文件路径(绝对路径或相对项目根目录)',
|
|
21
|
+
},
|
|
22
|
+
offset: { type: 'number', description: '起始行号(0-based,可选,默认从第 1 行开始)' },
|
|
23
|
+
limit: { type: 'number', description: '最多读取行数(可选,默认全部)' },
|
|
24
|
+
},
|
|
25
|
+
required: ['file_path'],
|
|
26
|
+
};
|
|
27
|
+
export class ReadFileBuiltinTool extends BuiltinBaseTool {
|
|
28
|
+
name = 'read_file';
|
|
29
|
+
description = '读取指定路径的文件内容。用于查看、打开或读取任意文本文件。图片文件返回 Base64 数据。';
|
|
30
|
+
parameters = READ_FILE_PARAMETERS;
|
|
31
|
+
kind = 'file';
|
|
32
|
+
constructor() {
|
|
33
|
+
super();
|
|
34
|
+
this.tags.push('file', 'read');
|
|
35
|
+
this.keywords.push('读文件', '读取文件', '查看文件', '打开文件', '文件内容', 'read file', 'read', 'cat', '查看', '打开');
|
|
36
|
+
}
|
|
37
|
+
async run(args, _context) {
|
|
38
|
+
const filePathArg = args.file_path;
|
|
39
|
+
if (typeof filePathArg !== 'string' || !filePathArg.trim()) {
|
|
40
|
+
return 'Error: file_path is required';
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const fp = expandHome(filePathArg);
|
|
44
|
+
if (isBlockedDevicePath(fp)) {
|
|
45
|
+
return `Error: 禁止读取设备文件 ${fp}(会导致进程挂起或注入攻击)`;
|
|
46
|
+
}
|
|
47
|
+
assertFileAccess(fp);
|
|
48
|
+
const stat = await fs.stat(fp);
|
|
49
|
+
if (stat.size > MAX_READ_FILE_SIZE) {
|
|
50
|
+
return `Error: 文件过大 (${(stat.size / 1024 / 1024).toFixed(1)} MiB),超过 ${MAX_READ_FILE_SIZE / 1024 / 1024} MiB 限制。请使用 offset/limit 分段读取。`;
|
|
51
|
+
}
|
|
52
|
+
if (isImageFile(fp)) {
|
|
53
|
+
const buffer = await fs.readFile(fp);
|
|
54
|
+
const ext = path.extname(fp).toLowerCase().replace('.', '');
|
|
55
|
+
const mimeType = ext === 'jpg' ? 'jpeg' : ext === 'svg' ? 'svg+xml' : ext;
|
|
56
|
+
const b64 = buffer.toString('base64');
|
|
57
|
+
const sizeKb = (buffer.length / 1024).toFixed(1);
|
|
58
|
+
return `[Image: ${path.basename(fp)}, ${sizeKb} KB, type: image/${mimeType}]\ndata:image/${mimeType};base64,${b64.slice(0, 200)}...(total ${b64.length} chars)`;
|
|
59
|
+
}
|
|
60
|
+
const content = await fs.readFile(fp, 'utf-8');
|
|
61
|
+
const lines = content.split('\n');
|
|
62
|
+
const offset = typeof args.offset === 'number' ? args.offset : 0;
|
|
63
|
+
const limit = typeof args.limit === 'number' ? args.limit : lines.length;
|
|
64
|
+
const sliced = lines.slice(offset, offset + limit);
|
|
65
|
+
const numbered = sliced.map((line, i) => `${offset + i + 1} | ${line}`).join('\n');
|
|
66
|
+
return `File: ${fp} (${lines.length} lines, showing ${offset + 1}-${Math.min(offset + limit, lines.length)})\n${numbered}`;
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
return nodeErrToFileMessage(e, String(filePathArg), 'read');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** 工厂:供 createBuiltinTools 与其它入口使用 */
|
|
74
|
+
export function createReadFileTool() {
|
|
75
|
+
return new ReadFileBuiltinTool().toTool();
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=read-file-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-file-tool.js","sourceRoot":"","sources":["../../src/builtin/read-file-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Tool, ToolContext, ToolParametersSchema, ToolResult } from '@zhin.js/core';
|
|
2
|
+
import { BuiltinBaseTool } from './builtin-base-tool.js';
|
|
3
|
+
export declare const READ_MEMORY_PARAMETERS: ToolParametersSchema;
|
|
4
|
+
export declare class ReadMemoryBuiltinTool extends BuiltinBaseTool {
|
|
5
|
+
private readonly dataDir;
|
|
6
|
+
readonly name = "read_memory";
|
|
7
|
+
readonly description = "\u8BFB\u53D6\u6301\u4E45\u5316\u8BB0\u5FC6\uFF08AGENTS.md\uFF09\u3002\u8BB0\u5FC6\u8DE8\u4F1A\u8BDD\u4FDD\u6301\u3002scope: global\uFF08\u5171\u4EAB\uFF09\u6216 chat\uFF08\u6309\u804A\u5929\u9694\u79BB\uFF09";
|
|
8
|
+
readonly parameters: ToolParametersSchema<Record<string, any>>;
|
|
9
|
+
readonly kind = "memory";
|
|
10
|
+
constructor(dataDir: string);
|
|
11
|
+
run(args: Record<string, unknown>, _context?: ToolContext): Promise<ToolResult>;
|
|
12
|
+
}
|
|
13
|
+
export declare function createReadMemoryTool(dataDir: string): Tool;
|
|
14
|
+
//# sourceMappingURL=read-memory-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-memory-tool.d.ts","sourceRoot":"","sources":["../../src/builtin/read-memory-tool.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEzF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,eAAO,MAAM,sBAAsB,EAAE,oBAWpC,CAAC;AAEF,qBAAa,qBAAsB,SAAQ,eAAe;IAO5C,OAAO,CAAC,QAAQ,CAAC,OAAO;IANpC,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,qNAC0C;IAC9D,QAAQ,CAAC,UAAU,4CAA0B;IAC7C,QAAQ,CAAC,IAAI,YAAY;gBAEI,OAAO,EAAE,MAAM;IAMtC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;CAWtF;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1D"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* read_memory — 读取持久化记忆(AGENTS.md)
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'node:fs';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
import { errMsg } from '../discovery/utils.js';
|
|
7
|
+
import { BuiltinBaseTool } from './builtin-base-tool.js';
|
|
8
|
+
export const READ_MEMORY_PARAMETERS = {
|
|
9
|
+
type: 'object',
|
|
10
|
+
properties: {
|
|
11
|
+
scope: {
|
|
12
|
+
type: 'string',
|
|
13
|
+
description: "'global' 或 'chat'(默认 chat)",
|
|
14
|
+
enum: ['global', 'chat'],
|
|
15
|
+
},
|
|
16
|
+
chat_id: { type: 'string', description: '聊天 ID(chat scope 时使用)' },
|
|
17
|
+
},
|
|
18
|
+
required: ['scope'],
|
|
19
|
+
};
|
|
20
|
+
export class ReadMemoryBuiltinTool extends BuiltinBaseTool {
|
|
21
|
+
dataDir;
|
|
22
|
+
name = 'read_memory';
|
|
23
|
+
description = '读取持久化记忆(AGENTS.md)。记忆跨会话保持。scope: global(共享)或 chat(按聊天隔离)';
|
|
24
|
+
parameters = READ_MEMORY_PARAMETERS;
|
|
25
|
+
kind = 'memory';
|
|
26
|
+
constructor(dataDir) {
|
|
27
|
+
super();
|
|
28
|
+
this.dataDir = dataDir;
|
|
29
|
+
this.tags.push('memory', 'agents');
|
|
30
|
+
this.keywords.push('记忆', '记住', '回忆', '之前', '上次', 'memory');
|
|
31
|
+
}
|
|
32
|
+
async run(args, _context) {
|
|
33
|
+
try {
|
|
34
|
+
const memPath = args.scope === 'global'
|
|
35
|
+
? path.join(this.dataDir, 'AGENTS.md')
|
|
36
|
+
: path.join(this.dataDir, 'groups', args.chat_id || 'default', 'AGENTS.md');
|
|
37
|
+
if (!fs.existsSync(memPath))
|
|
38
|
+
return 'No memory stored yet.';
|
|
39
|
+
return await fs.promises.readFile(memPath, 'utf-8');
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
return `Error: ${errMsg(e)}`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function createReadMemoryTool(dataDir) {
|
|
47
|
+
return new ReadMemoryBuiltinTool(dataDir).toTool();
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=read-memory-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-memory-tool.js","sourceRoot":"","sources":["../../src/builtin/read-memory-tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,CAAC,MAAM,sBAAsB,GAAyB;IAC1D,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,4BAA4B;YACzC,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC;SACzB;QACD,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE;KAClE;IACD,QAAQ,EAAE,CAAC,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,OAAO,qBAAsB,SAAQ,eAAe;IAO3B;IANpB,IAAI,GAAG,aAAa,CAAC;IACrB,WAAW,GAClB,2DAA2D,CAAC;IACrD,UAAU,GAAG,sBAAsB,CAAC;IACpC,IAAI,GAAG,QAAQ,CAAC;IAEzB,YAA6B,OAAe;QAC1C,KAAK,EAAE,CAAC;QADmB,YAAO,GAAP,OAAO,CAAQ;QAE1C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAA6B,EAAE,QAAsB;QAC7D,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,KAAK,QAAQ;gBACrC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC;gBACtC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAG,IAAI,CAAC,OAAkB,IAAI,SAAS,EAAE,WAAW,CAAC,CAAC;YAC1F,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;gBAAE,OAAO,uBAAuB,CAAC;YAC5D,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACtD,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,OAAO,UAAU,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;CACF;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,OAAO,IAAI,qBAAqB,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spawn_task — 主会话将耗时任务派给后台子 agent(与 issue #396 对齐)
|
|
3
|
+
*/
|
|
4
|
+
import type { AgentTool, Tool, ToolContext, ToolParametersSchema, ToolResult } from '@zhin.js/core';
|
|
5
|
+
import type { SubagentManager, SubagentOrigin } from '../subagent.js';
|
|
6
|
+
import { BuiltinBaseTool } from './builtin-base-tool.js';
|
|
7
|
+
export declare const SPAWN_TASK_PARAMETERS: ToolParametersSchema;
|
|
8
|
+
export declare function originFromToolContext(context: ToolContext): SubagentOrigin;
|
|
9
|
+
export declare class SpawnTaskBuiltinTool extends BuiltinBaseTool {
|
|
10
|
+
private readonly sessionContext;
|
|
11
|
+
private readonly manager;
|
|
12
|
+
readonly name = "spawn_task";
|
|
13
|
+
readonly description = "\u5C06\u590D\u6742\u6216\u8017\u65F6\u7684\u4EFB\u52A1\u4EA4\u7ED9\u540E\u53F0\u5B50 agent \u5F02\u6B65\u5904\u7406\u3002\u5B50 agent \u62E5\u6709\u6587\u4EF6\u8BFB\u5199\u3001Shell\u3001\u7F51\u7EDC\u641C\u7D22\u7B49\u80FD\u529B\uFF0C\u5B8C\u6210\u540E\u4F1A\u81EA\u52A8\u901A\u77E5\u7528\u6237\u3002\u9002\u7528\u4E8E\u9700\u8981\u591A\u6B65\u64CD\u4F5C\u7684\u6587\u4EF6\u5904\u7406\u3001\u4EE3\u7801\u5206\u6790\u3001\u6570\u636E\u6536\u96C6\u7B49\u4EFB\u52A1\u3002";
|
|
14
|
+
readonly parameters: ToolParametersSchema<Record<string, any>>;
|
|
15
|
+
constructor(sessionContext: ToolContext, manager: SubagentManager);
|
|
16
|
+
toTool(): Tool;
|
|
17
|
+
run(args: Record<string, unknown>, _context?: ToolContext): Promise<ToolResult>;
|
|
18
|
+
}
|
|
19
|
+
export declare function createSpawnTaskTool(context: ToolContext, manager: SubagentManager): AgentTool;
|
|
20
|
+
//# sourceMappingURL=spawn-task-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawn-task-tool.d.ts","sourceRoot":"","sources":["../../src/builtin/spawn-task-tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACpG,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,eAAO,MAAM,qBAAqB,EAAE,oBAanC,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,GAAG,cAAc,CAQ1E;AAED,qBAAa,oBAAqB,SAAQ,eAAe;IAOrD,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAP1B,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,QAAQ,CAAC,WAAW,2dAC+E;IACnG,QAAQ,CAAC,UAAU,4CAAyB;gBAGzB,cAAc,EAAE,WAAW,EAC3B,OAAO,EAAE,eAAe;IAO3C,MAAM,IAAI,IAAI;IAMR,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;CAYtF;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,GAAG,SAAS,CAE7F"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { BuiltinBaseTool } from './builtin-base-tool.js';
|
|
2
|
+
export const SPAWN_TASK_PARAMETERS = {
|
|
3
|
+
type: 'object',
|
|
4
|
+
properties: {
|
|
5
|
+
task: {
|
|
6
|
+
type: 'string',
|
|
7
|
+
description: '要交给子 agent 完成的任务描述(尽量详细,包含目标、范围、期望输出)',
|
|
8
|
+
},
|
|
9
|
+
label: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
description: '任务的简短标签(用于显示,可选)',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
required: ['task'],
|
|
15
|
+
};
|
|
16
|
+
export function originFromToolContext(context) {
|
|
17
|
+
return {
|
|
18
|
+
platform: context.platform || '',
|
|
19
|
+
botId: context.botId || '',
|
|
20
|
+
senderId: context.senderId || '',
|
|
21
|
+
sceneId: context.sceneId || '',
|
|
22
|
+
sceneType: context.message?.$channel?.type || 'private',
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export class SpawnTaskBuiltinTool extends BuiltinBaseTool {
|
|
26
|
+
sessionContext;
|
|
27
|
+
manager;
|
|
28
|
+
name = 'spawn_task';
|
|
29
|
+
description = '将复杂或耗时的任务交给后台子 agent 异步处理。子 agent 拥有文件读写、Shell、网络搜索等能力,完成后会自动通知用户。适用于需要多步操作的文件处理、代码分析、数据收集等任务。';
|
|
30
|
+
parameters = SPAWN_TASK_PARAMETERS;
|
|
31
|
+
constructor(sessionContext, manager) {
|
|
32
|
+
super();
|
|
33
|
+
this.sessionContext = sessionContext;
|
|
34
|
+
this.manager = manager;
|
|
35
|
+
this.tags.push('agent', 'async', 'task', '后台', '子任务');
|
|
36
|
+
this.keywords.push('后台', '异步', '子任务', 'spawn', 'background', '并行', '独立处理');
|
|
37
|
+
}
|
|
38
|
+
toTool() {
|
|
39
|
+
const tool = super.toTool();
|
|
40
|
+
tool.source = 'builtin:context';
|
|
41
|
+
return tool;
|
|
42
|
+
}
|
|
43
|
+
async run(args, _context) {
|
|
44
|
+
const task = args.task;
|
|
45
|
+
const label = args.label;
|
|
46
|
+
if (typeof task !== 'string' || !task) {
|
|
47
|
+
return '请提供任务描述';
|
|
48
|
+
}
|
|
49
|
+
const origin = originFromToolContext(this.sessionContext);
|
|
50
|
+
const labelStr = typeof label === 'string' ? label : undefined;
|
|
51
|
+
return this.manager.spawn({ task, label: labelStr, origin });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export function createSpawnTaskTool(context, manager) {
|
|
55
|
+
return new SpawnTaskBuiltinTool(context, manager).toTool();
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=spawn-task-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawn-task-tool.js","sourceRoot":"","sources":["../../src/builtin/spawn-task-tool.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,CAAC,MAAM,qBAAqB,GAAyB;IACzD,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,uCAAuC;SACrD;QACD,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,kBAAkB;SAChC;KACF;IACD,QAAQ,EAAE,CAAC,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,UAAU,qBAAqB,CAAC,OAAoB;IACxD,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE;QAChC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;QAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE;QAChC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;QAC9B,SAAS,EAAE,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,IAAI,SAAS;KACxD,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,oBAAqB,SAAQ,eAAe;IAOpC;IACA;IAPV,IAAI,GAAG,YAAY,CAAC;IACpB,WAAW,GAClB,gGAAgG,CAAC;IAC1F,UAAU,GAAG,qBAAqB,CAAC;IAE5C,YACmB,cAA2B,EAC3B,OAAwB;QAEzC,KAAK,EAAE,CAAC;QAHS,mBAAc,GAAd,cAAc,CAAa;QAC3B,YAAO,GAAP,OAAO,CAAiB;QAGzC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7E,CAAC;IAED,MAAM;QACJ,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,iBAAiB,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAA6B,EAAE,QAAsB;QAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YACtC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,MAAM,GAAG,qBAAqB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC1D,MAAM,QAAQ,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QAE/D,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;CACF;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAoB,EAAE,OAAwB;IAChF,OAAO,IAAI,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,MAAM,EAAe,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Tool, ToolContext, ToolParametersSchema, ToolResult } from '@zhin.js/core';
|
|
2
|
+
import { BuiltinBaseTool } from './builtin-base-tool.js';
|
|
3
|
+
export declare const TODO_READ_PARAMETERS: ToolParametersSchema;
|
|
4
|
+
export declare class TodoReadBuiltinTool extends BuiltinBaseTool {
|
|
5
|
+
private readonly dataDir;
|
|
6
|
+
readonly name = "todo_read";
|
|
7
|
+
readonly description = "\u8BFB\u53D6\u5F53\u524D\u4EFB\u52A1\u8BA1\u5212\u5217\u8868\uFF0C\u7528\u4E8E\u67E5\u770B\u8FDB\u5EA6\u548C\u5F85\u529E\u4E8B\u9879";
|
|
8
|
+
readonly parameters: ToolParametersSchema<Record<string, any>>;
|
|
9
|
+
readonly kind = "plan";
|
|
10
|
+
constructor(dataDir: string);
|
|
11
|
+
run(args: Record<string, unknown>, _context?: ToolContext): Promise<ToolResult>;
|
|
12
|
+
}
|
|
13
|
+
export declare function createTodoReadTool(dataDir: string): Tool;
|
|
14
|
+
//# sourceMappingURL=todo-read-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todo-read-tool.d.ts","sourceRoot":"","sources":["../../src/builtin/todo-read-tool.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEzF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,eAAO,MAAM,oBAAoB,EAAE,oBASlC,CAAC;AAEF,qBAAa,mBAAoB,SAAQ,eAAe;IAM1C,OAAO,CAAC,QAAQ,CAAC,OAAO;IALpC,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,WAAW,0IAA4B;IAChD,QAAQ,CAAC,UAAU,4CAAwB;IAC3C,QAAQ,CAAC,IAAI,UAAU;gBAEM,OAAO,EAAE,MAAM;IAMtC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;CAoBtF;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAExD"}
|