deepfish-ai 1.0.29 → 2.0.3
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 +195 -344
- package/dist/generate-skill.md +104 -0
- package/dist/generate-tool.md +88 -0
- package/dist/index.js +26831 -0
- package/dist/serve/client/assets/index-DUHYC91l.js +1 -0
- package/dist/serve/client/assets/index-zcrdNLZs.css +1 -0
- package/dist/serve/client/index.html +14 -0
- package/dist/serve/pm2-server.js +24405 -0
- package/dist/serve/server/entry-server.mjs +224 -0
- package/dist/view-learn-cache.md +65 -0
- package/package.json +77 -83
- package/LICENSE +0 -21
- package/README_CN.md +0 -460
- package/src/AgentRobot/AgentRobotFactory/MainAgentRobot.js +0 -88
- package/src/AgentRobot/AgentRobotFactory/SubAgentRobot.js +0 -45
- package/src/AgentRobot/AgentRobotFactory/SubSkillAgentRobot.js +0 -45
- package/src/AgentRobot/AgentRobotFactory/index.js +0 -48
- package/src/AgentRobot/BaseAgentRobot/Brain.js +0 -210
- package/src/AgentRobot/BaseAgentRobot/BrainEvent.js +0 -17
- package/src/AgentRobot/BaseAgentRobot/Hand.js +0 -119
- package/src/AgentRobot/BaseAgentRobot/Heart.js +0 -0
- package/src/AgentRobot/BaseAgentRobot/Logger.js +0 -114
- package/src/AgentRobot/BaseAgentRobot/ScreenPrinter.js +0 -49
- package/src/AgentRobot/BaseAgentRobot/index.js +0 -266
- package/src/AgentRobot/BaseAgentRobot/lazy-tools/AliBailian.js +0 -997
- package/src/AgentRobot/BaseAgentRobot/lazy-tools/doc-transform.js +0 -204
- package/src/AgentRobot/BaseAgentRobot/lazy-tools/docx.js +0 -1286
- package/src/AgentRobot/BaseAgentRobot/lazy-tools/img.js +0 -765
- package/src/AgentRobot/BaseAgentRobot/lazy-tools/pdf.js +0 -736
- package/src/AgentRobot/BaseAgentRobot/lazy-tools/pptx.js +0 -567
- package/src/AgentRobot/BaseAgentRobot/lazy-tools/video.js +0 -36
- package/src/AgentRobot/BaseAgentRobot/lazy-tools/xlsx.js +0 -611
- package/src/AgentRobot/BaseAgentRobot/tools/BaseTools.js +0 -13
- package/src/AgentRobot/BaseAgentRobot/tools/CreateAgentTools.js +0 -158
- package/src/AgentRobot/BaseAgentRobot/tools/FileTools.js +0 -768
- package/src/AgentRobot/BaseAgentRobot/tools/GenerateTools.js +0 -441
- package/src/AgentRobot/BaseAgentRobot/tools/InquirerTools.js +0 -244
- package/src/AgentRobot/BaseAgentRobot/tools/SystemTools.js +0 -424
- package/src/AgentRobot/BaseAgentRobot/tools/TaskTools.js +0 -211
- package/src/AgentRobot/BaseAgentRobot/tools/TestTools.js +0 -100
- package/src/AgentRobot/BaseAgentRobot/tools/UserTool.js +0 -87
- package/src/AgentRobot/BaseAgentRobot/tools/WebTools.js +0 -257
- package/src/AgentRobot/BaseAgentRobot/utils/AIRequest.js +0 -297
- package/src/AgentRobot/BaseAgentRobot/utils/AIToolManager.js +0 -131
- package/src/AgentRobot/BaseAgentRobot/utils/AgentTree.js +0 -66
- package/src/AgentRobot/BaseAgentRobot/utils/AttachmentToolScanner.js +0 -235
- package/src/AgentRobot/BaseAgentRobot/utils/MessageCompresser.js +0 -236
- package/src/AgentRobot/BaseAgentRobot/utils/aiConsole.js +0 -74
- package/src/AgentRobot/BaseAgentRobot/utils/aiInquirer.js +0 -78
- package/src/AgentRobot/BaseAgentRobot/utils/analyzeReturn.test.js +0 -104
- package/src/AgentRobot/BaseAgentRobot/utils/copilot.js +0 -117
- package/src/AgentRobot/BaseAgentRobot/utils/node-root.js +0 -138
- package/src/AgentRobot/BaseAgentRobot/utils/normal.js +0 -399
- package/src/cli/ConfigManager.js +0 -283
- package/src/cli/DefaultConfig.js +0 -98
- package/src/cli/GlobalVariable.js +0 -8
- package/src/cli/MemoryManager.js +0 -53
- package/src/cli/SkillConfigManager.js +0 -354
- package/src/cli/SkillParser.js +0 -58
- package/src/cli/ai-auth.js +0 -231
- package/src/cli/ai-config.js +0 -225
- package/src/cli/ai-memory.js +0 -22
- package/src/cli/ai-skill.js +0 -65
- package/src/cli/index.js +0 -77
- package/src/index.js +0 -54
|
@@ -1,441 +0,0 @@
|
|
|
1
|
-
const fs = require('fs-extra')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
|
|
4
|
-
const descriptions = [
|
|
5
|
-
{
|
|
6
|
-
type: 'function',
|
|
7
|
-
function: {
|
|
8
|
-
name: 'getGenerateSkillRules',
|
|
9
|
-
description:
|
|
10
|
-
'根据用户目标生成扩展工具的完整开发规则与提示词,返回可直接执行的规则文本。注意是扩展工具,并非ClawSkill工具包。',
|
|
11
|
-
parameters: {
|
|
12
|
-
type: 'object',
|
|
13
|
-
properties: {
|
|
14
|
-
goal: { type: 'string' },
|
|
15
|
-
},
|
|
16
|
-
required: ['goal'],
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
type: 'function',
|
|
22
|
-
function: {
|
|
23
|
-
name: 'generateSkill',
|
|
24
|
-
description:
|
|
25
|
-
'基于已准备好的扩展工具规则文本执行任务清单,自动生成扩展工具项目文件。调用前应先通过 getGenerateSkillRules 获取规则。',
|
|
26
|
-
parameters: {
|
|
27
|
-
type: 'object',
|
|
28
|
-
properties: {
|
|
29
|
-
rules: { type: 'string' },
|
|
30
|
-
},
|
|
31
|
-
required: ['rules'],
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
type: 'function',
|
|
37
|
-
function: {
|
|
38
|
-
name: 'getGenerateClawSkillRules',
|
|
39
|
-
description:
|
|
40
|
-
'根据用户目标生成兼容 OpenClaw 规范的 Skill 工具包开发规则与提示词,返回可直接执行的规则文本。注意是ClawSkill工具包,与扩展工具不同。',
|
|
41
|
-
parameters: {
|
|
42
|
-
type: 'object',
|
|
43
|
-
properties: {
|
|
44
|
-
goal: { type: 'string' },
|
|
45
|
-
},
|
|
46
|
-
required: ['goal'],
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
type: 'function',
|
|
52
|
-
function: {
|
|
53
|
-
name: 'generateClawSkill',
|
|
54
|
-
description:
|
|
55
|
-
'基于已准备好的 OpenClaw Skill 规则文本执行任务清单,自动生成 Skill 工具包文件。调用前应先通过 getGenerateClawSkillRules 获取规则。',
|
|
56
|
-
parameters: {
|
|
57
|
-
type: 'object',
|
|
58
|
-
properties: {
|
|
59
|
-
rules: { type: 'string' },
|
|
60
|
-
},
|
|
61
|
-
required: ['rules'],
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
type: 'function',
|
|
67
|
-
function: {
|
|
68
|
-
name: 'generateClawSkillByHistory',
|
|
69
|
-
description:
|
|
70
|
-
'根据用户目标与对话历史日志或指定日志文件自动生成 OpenClaw Skill 工具包。logfile参数为日志文件名称,默认从日志目录中查找,如果不存在则从当前目录查找;若未设置该参数,则使用最新日志文件;该参数也可设置为绝对路径。',
|
|
71
|
-
parameters: {
|
|
72
|
-
type: 'object',
|
|
73
|
-
properties: {
|
|
74
|
-
goal: { type: 'string' },
|
|
75
|
-
logfile: { type: 'string' },
|
|
76
|
-
},
|
|
77
|
-
required: ['goal'],
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
type: 'function',
|
|
83
|
-
function: {
|
|
84
|
-
name: 'getSessionHistoryFile',
|
|
85
|
-
description:
|
|
86
|
-
'获取最后一次会话历史日志文件路径,用于生成Skill时引用会话历史。',
|
|
87
|
-
parameters: {
|
|
88
|
-
type: 'object',
|
|
89
|
-
properties: {},
|
|
90
|
-
required: [],
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
]
|
|
95
|
-
|
|
96
|
-
async function getGenerateSkillRules(goal) {
|
|
97
|
-
const newGoal = `
|
|
98
|
-
## 任务目标
|
|
99
|
-
基于指定规则创建一个标准化的Node.js NPM项目,实现用户目标:${goal},最终输出符合AI工作流调用规范的函数模块,并配套中英文说明文档。
|
|
100
|
-
|
|
101
|
-
## 任务步骤
|
|
102
|
-
|
|
103
|
-
### 第一步:项目初始化
|
|
104
|
-
1. 目录创建:新建目录,目录名称以"deepfish-ai-"开头,如"deepfish-ai-「项目功能名称」",作为NPM项目根目录,并作为当前项目的名称
|
|
105
|
-
2. package.json配置:
|
|
106
|
-
- name字段值:与项目名称一致,即"deepfish-ai-「项目功能名称」"
|
|
107
|
-
- version字段值:初始版本设置为1.0.0
|
|
108
|
-
- description字段值:用专业英文简要描述该项目的核心功能和价值, 以"A DeepFish AI extension tool for"开头
|
|
109
|
-
- git仓库地址:固定为 https://github.com/qq306863030/deepfish-extensions.git
|
|
110
|
-
- author设置为"DeepFish AI"
|
|
111
|
-
- type字段设置为"commonjs",确保模块系统兼容
|
|
112
|
-
- main字段设置为"index.js",指定入口文件
|
|
113
|
-
3. 文件结构
|
|
114
|
-
- 主文件:项目入口文件必须命名为index.js
|
|
115
|
-
- 子文件:复杂的逻辑可以拆分到其他.js文件中;将descriptions、functions拆分到子文件;
|
|
116
|
-
- 文档文件:项目根目录需新增2个文档文件:
|
|
117
|
-
- README_CN.md(中文说明文档)
|
|
118
|
-
- README.md(英文说明文档)
|
|
119
|
-
|
|
120
|
-
### 第二步:工具函数开发规则
|
|
121
|
-
#### 2.1 核心输出要求
|
|
122
|
-
文件需输出四个核心字段,且代码逻辑清晰、可运行:
|
|
123
|
-
- name:字符串类型,扩展的名称标识
|
|
124
|
-
- description:字符串类型,扩展功能的简要描述,说明该扩展提供的核心能力
|
|
125
|
-
- descriptions:数组类型,每个元素为OpenAI可识别的函数描述对象
|
|
126
|
-
- platform:字符串类型,扩展支持的平台(process.platform),all或空表示所有平台, win32表示仅支持Windows, darwin表示仅支持MacOS, linux表示仅支持Linux:
|
|
127
|
-
- functions:对象类型,key为函数名称,value为函数方法体
|
|
128
|
-
|
|
129
|
-
#### 2.2 开发强制规则
|
|
130
|
-
1. 参数一致性:functions中函数的入参,必须与descriptions中对应函数声明的parameters完全一致
|
|
131
|
-
2. 命名规范:
|
|
132
|
-
- 函数名称前缀:「领域用途+分隔符」(如systemFileManagement_)
|
|
133
|
-
- 函数描述开头:统一格式「领域用途+分隔符+功能描述」(如系统文件管理:重命名文件)
|
|
134
|
-
3. 内置工具函数调用:函数内可以使用内置工具函数requestAI来获取AI请求结果,在环境中通过this.Tools注入,必要时也可以使用其他函数,示例:
|
|
135
|
-
- this.Tools.requestAI(systemDescription, prompt, temperature)
|
|
136
|
-
- this.Tools.executeCommand(command)
|
|
137
|
-
4. 函数数量:至少包含1个可被AI工作流调用的函数
|
|
138
|
-
5. 对于大于3个函数拆分成多个文件,保持文件结构清晰
|
|
139
|
-
6. 对于大于3个函数的扩展功能,需要在functions中输出一个说明函数,只需返回一个markdown类型的英文字符串,专门用于解释当前扩展工具的使用方法、参数说明、示例等内容,函数名称为「readme」,如「systemFileManagement_readme」;函数描述需要强调调用该扩展模块前必须先阅读该规则文档。
|
|
140
|
-
7. 仅输出代码,不需要测试。
|
|
141
|
-
|
|
142
|
-
#### 2.3 基础代码模板(必须遵循)
|
|
143
|
-
const descriptions = []
|
|
144
|
-
const functions = {}
|
|
145
|
-
module.exports = {
|
|
146
|
-
name: '扩展名称',
|
|
147
|
-
description: '扩展功能的简要描述',
|
|
148
|
-
platform: "all",
|
|
149
|
-
descriptions,
|
|
150
|
-
functions,
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
#### 2.4 参考示例(可参考格式,展示多文件拆分结构)
|
|
154
|
-
|
|
155
|
-
##### index.js(主文件)
|
|
156
|
-
const descriptions = require('./descriptions')
|
|
157
|
-
const functions = require('./functions')
|
|
158
|
-
module.exports = {
|
|
159
|
-
name: 'systemFileManagement',
|
|
160
|
-
description: '提供文件管理相关功能,包括文件重命名、复制等操作',
|
|
161
|
-
platform: "all",
|
|
162
|
-
descriptions,
|
|
163
|
-
functions,
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
##### descriptions.js(描述子文件)
|
|
167
|
-
const descriptions = [
|
|
168
|
-
{
|
|
169
|
-
name: 'systemFileManagement_renameFile',
|
|
170
|
-
description: '系统文件管理:重命名文件',
|
|
171
|
-
parameters: {
|
|
172
|
-
type: 'object',
|
|
173
|
-
properties: {
|
|
174
|
-
oldPath: { type: 'string', description: '旧文件路径' },
|
|
175
|
-
newPath: { type: 'string', description: '新文件路径' },
|
|
176
|
-
},
|
|
177
|
-
},
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
name: 'systemFileManagement_copyFile',
|
|
181
|
-
description: '系统文件管理:复制文件',
|
|
182
|
-
parameters: {
|
|
183
|
-
type: 'object',
|
|
184
|
-
properties: {
|
|
185
|
-
srcPath: { type: 'string', description: '源文件路径' },
|
|
186
|
-
destPath: { type: 'string', description: '目标文件路径' },
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
|
-
},
|
|
190
|
-
]
|
|
191
|
-
module.exports = descriptions
|
|
192
|
-
|
|
193
|
-
##### functions.js(函数子文件)
|
|
194
|
-
const functions = {
|
|
195
|
-
systemFileManagement_renameFile: function(oldPath, newPath) {
|
|
196
|
-
try {
|
|
197
|
-
const fullOldPath = path.resolve(process.cwd(), oldPath)
|
|
198
|
-
const fullNewPath = path.resolve(process.cwd(), newPath)
|
|
199
|
-
|
|
200
|
-
if (fs.existsSync(fullOldPath)) {
|
|
201
|
-
fs.renameSync(fullOldPath, fullNewPath)
|
|
202
|
-
}
|
|
203
|
-
return true
|
|
204
|
-
} catch (error) {
|
|
205
|
-
return false
|
|
206
|
-
}
|
|
207
|
-
},
|
|
208
|
-
systemFileManagement_copyFile: function(srcPath, destPath) {
|
|
209
|
-
try {
|
|
210
|
-
const fullSourcePath = path.resolve(process.cwd(), srcPath)
|
|
211
|
-
const fullDestPath = path.resolve(process.cwd(), destPath)
|
|
212
|
-
const destDirPath = path.dirname(fullDestPath)
|
|
213
|
-
|
|
214
|
-
fs.ensureDirSync(destDirPath)
|
|
215
|
-
|
|
216
|
-
if (fs.existsSync(fullSourcePath)) {
|
|
217
|
-
fs.copyFileSync(fullSourcePath, fullDestPath)
|
|
218
|
-
} else {
|
|
219
|
-
return 'Source file does not exist'
|
|
220
|
-
}
|
|
221
|
-
return true
|
|
222
|
-
} catch (error) {
|
|
223
|
-
return false
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
module.exports = functions
|
|
228
|
-
|
|
229
|
-
### 第三步:输出README文档
|
|
230
|
-
#### 3.1 通用要求
|
|
231
|
-
- 两个文档需在标题下方包含「中英文切换标签」(如文档顶部标注「English | 中文」/「中文 | English」)
|
|
232
|
-
- 结构保持一致,仅语言不同,核心模块顺序不可调整
|
|
233
|
-
- 文件名称README_CN.md(中文)、README.md(英文)
|
|
234
|
-
- 链接使用相对路径,如[中文](./README_CN.md)
|
|
235
|
-
|
|
236
|
-
#### 3.2 核心模块
|
|
237
|
-
1. 总体功能描述:
|
|
238
|
-
- 清晰说明当前NPM包的核心定位、整体功能价值、适用场景
|
|
239
|
-
- 语言简洁易懂,无需技术细节,聚焦「做什么」而非「怎么做」
|
|
240
|
-
2. 快速开始:
|
|
241
|
-
- 明确说明安装步骤:
|
|
242
|
-
① 全局安装deepfish-ai:npm install deepfish-ai -g
|
|
243
|
-
② 全局安装当前项目:npm install deepfish-ai-「项目功能名称」 -g
|
|
244
|
-
③ 在命令行中输入:ai 「扩展的某一个功能」。如:添加了一个查询天气的扩展。则输入:ai 查询一下今天的天气
|
|
245
|
-
3. 函数列表及功能描述:
|
|
246
|
-
- 列出当前项目中所有函数名称
|
|
247
|
-
- 对应说明每个函数的核心功能
|
|
248
|
-
- 无需编写各个函数的具体使用方法
|
|
249
|
-
`
|
|
250
|
-
return newGoal
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// 生成一个Skill工具包
|
|
254
|
-
async function generateSkill(rules) {
|
|
255
|
-
await this.Tools.createTaskList(rules)
|
|
256
|
-
return this.Tools.executeTaskList(rules)
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
async function getGenerateClawSkillRules(goal) {
|
|
260
|
-
const newGoal = `
|
|
261
|
-
## 任务目标
|
|
262
|
-
基于OpenClaw Skill规范创建一个标准化的Skill工具包,实现用户目标:${goal},最终输出可被你直接加载使用。
|
|
263
|
-
|
|
264
|
-
## 任务步骤
|
|
265
|
-
|
|
266
|
-
### 第一步:项目初始化
|
|
267
|
-
1. 目录创建:在当前工作目录下新建一个子目录,目录名称应简洁明了地反映Skill功能(如"web-scraper"、"code-reviewer"、"image-optimizer"等)
|
|
268
|
-
2. 核心文件:目录中必须包含 SKILL.md 文件(文件名大小写敏感,必须为 SKILL.md)
|
|
269
|
-
3. 文档文件:目录中需新增2个说明文档:
|
|
270
|
-
- README_CN.md(中文说明文档)
|
|
271
|
-
- README.md(英文说明文档)
|
|
272
|
-
4. 辅助文件:如果Skill涉及复杂逻辑,可在目录中创建辅助脚本文件(如 .js、.sh、.py 等),并在 SKILL.md 中说明其用途和调用方式;如果是js文件,可以在函数中通过this.Tools调用内置函数,如直接使用this.Tools.createSubAgent(workGoal)。
|
|
273
|
-
|
|
274
|
-
#### 标准目录结构
|
|
275
|
-
\`\`\`
|
|
276
|
-
<skill-name>/
|
|
277
|
-
├── SKILL.md # [必需] 核心文件:YAML元数据 + AI执行指令
|
|
278
|
-
├── README.md # [必需] 英文说明文档
|
|
279
|
-
├── README_CN.md # [必需] 中文说明文档
|
|
280
|
-
├── scripts/ # [可选] 辅助脚本目录(复杂Skill适用)
|
|
281
|
-
│ ├── helper.js # Node.js辅助脚本
|
|
282
|
-
│ ├── process.sh # Shell辅助脚本
|
|
283
|
-
│ └── ...
|
|
284
|
-
└── assets/ # [可选] 资源文件目录(模板、配置等)
|
|
285
|
-
├── template.txt # 模板文件
|
|
286
|
-
└── ...
|
|
287
|
-
\`\`\`
|
|
288
|
-
|
|
289
|
-
### 第二步:SKILL.md 完整开发规范
|
|
290
|
-
#### 2.1 文件结构
|
|
291
|
-
SKILL.md 由两部分组成:
|
|
292
|
-
- **YAML Frontmatter**(元数据区):位于文件顶部,用 \`---\` 包裹
|
|
293
|
-
- **Markdown Body**(指令正文区):Frontmatter之后的所有内容,是AI执行Skill的核心指令
|
|
294
|
-
|
|
295
|
-
#### 2.2 YAML Frontmatter 规范(必须遵循)
|
|
296
|
-
\`\`\`yaml
|
|
297
|
-
---
|
|
298
|
-
name: "skill-name"
|
|
299
|
-
description: "简要描述该Skill的核心功能和适用场景(建议20-50字)"
|
|
300
|
-
homepage: "https://github.com/your-repo/skill-name"
|
|
301
|
-
---
|
|
302
|
-
\`\`\`
|
|
303
|
-
|
|
304
|
-
字段说明:
|
|
305
|
-
- name:Skill的唯一标识名称,使用小写字母和连字符,与目录名保持一致
|
|
306
|
-
- description:Skill功能的简要描述,用于在Skill列表中展示,帮助AI判断何时匹配使用该Skill
|
|
307
|
-
- homepage:Skill的主页或仓库地址,可留空
|
|
308
|
-
|
|
309
|
-
#### 2.3 Markdown Body 指令正文规范
|
|
310
|
-
指令正文是Skill的核心,AI在加载Skill后会仔细阅读此部分内容来学习如何使用该Skill。正文需包含以下模块:
|
|
311
|
-
|
|
312
|
-
**模块一:概述**
|
|
313
|
-
- 清晰说明该Skill的核心功能、适用场景、能解决的问题
|
|
314
|
-
- 列出Skill的能力边界(能做什么、不能做什么)
|
|
315
|
-
|
|
316
|
-
**模块二:环境依赖(如有)**
|
|
317
|
-
- 列出Skill运行所需的外部依赖(如Node.js包、Python库、系统工具等)
|
|
318
|
-
- 说明依赖的安装方式和版本要求
|
|
319
|
-
- 如果无外部依赖,可省略此模块
|
|
320
|
-
|
|
321
|
-
**模块三:使用指令**
|
|
322
|
-
- 这是AI执行Skill时的核心参考,必须详细、精确、可操作
|
|
323
|
-
- 以步骤化的方式描述Skill的使用流程
|
|
324
|
-
- 每个步骤需说明:输入是什么、执行什么操作、输出是什么
|
|
325
|
-
- 如果涉及命令行操作,提供完整的命令示例
|
|
326
|
-
- 如果涉及代码调用,提供完整的代码示例
|
|
327
|
-
- 如果有多种使用场景,分场景给出说明
|
|
328
|
-
|
|
329
|
-
**模块四:输入输出规范**
|
|
330
|
-
- 定义Skill接受的输入格式和参数说明
|
|
331
|
-
- 定义Skill输出的结果格式和内容说明
|
|
332
|
-
- 提供输入输出的示例
|
|
333
|
-
|
|
334
|
-
**模块五:注意事项与限制**
|
|
335
|
-
- 说明使用过程中需要注意的关键点
|
|
336
|
-
- 列出已知限制和边界条件
|
|
337
|
-
- 提供常见问题的处理建议
|
|
338
|
-
|
|
339
|
-
### 第三步:输出README文档
|
|
340
|
-
#### 3.1 通用要求
|
|
341
|
-
- 两个文档需在标题下方包含「中英文切换标签」(如文档顶部标注「English | 中文」/「中文 | English」)
|
|
342
|
-
- 结构保持一致,仅语言不同,核心模块顺序不可调整
|
|
343
|
-
- 文件名称README_CN.md(中文)、README.md(英文)
|
|
344
|
-
- 链接使用相对路径,如[中文](./README_CN.md)
|
|
345
|
-
|
|
346
|
-
#### 3.2 核心模块
|
|
347
|
-
1. 总体功能描述:
|
|
348
|
-
- 清晰说明当前SKILL包的核心定位、整体功能价值、适用场景
|
|
349
|
-
- 语言简洁易懂,无需技术细节,聚焦「做什么」而非「怎么做」
|
|
350
|
-
2. 快速开始:
|
|
351
|
-
- 明确说明安装步骤:
|
|
352
|
-
① 全局安装deepfish-ai:npm install deepfish-ai -g
|
|
353
|
-
② 全局安装当前项目:ai skill add <skill-name>;ai skill ls;ai skill enable <skill-name|skill-index>
|
|
354
|
-
③ 在命令行中输入:ai 「skill功能」。如:添加了一个查询天气的扩展。则输入:ai 查询一下今天的天气
|
|
355
|
-
`
|
|
356
|
-
return newGoal
|
|
357
|
-
}
|
|
358
|
-
// 生成一个Skill工具包
|
|
359
|
-
async function generateClawSkill(rules) {
|
|
360
|
-
await this.Tools.createTaskList(rules)
|
|
361
|
-
return this.Tools.executeTaskList(rules)
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// 根据对话历史生成一个skill工具包
|
|
365
|
-
async function generateClawSkillByHistory(goal, logfile) {
|
|
366
|
-
const logDirPath = this.agentRobot.logDirPath
|
|
367
|
-
const workspace = this.agentRobot.workspace
|
|
368
|
-
let logFilePath
|
|
369
|
-
if (!logfile) {
|
|
370
|
-
// 如果没有明确提出对话历史文件,则从最新的对话日志中获取skill生成所需的对话历史内容
|
|
371
|
-
let logFiles = fs.readdirSync(logDirPath)
|
|
372
|
-
logFiles = logFiles.filter((file) => file.startsWith(`log-messeage-`))
|
|
373
|
-
if (logFiles.length === 0) {
|
|
374
|
-
throw new Error('No log file found for generating skill by history')
|
|
375
|
-
}
|
|
376
|
-
// 根据文件名称排序,获取最新的日志文件 log-messeage-{logId}.txt
|
|
377
|
-
let latestLogFile = logFiles[0]
|
|
378
|
-
if (logFiles.length > 1) {
|
|
379
|
-
latestLogFile = logFiles.sort((a, b) => {
|
|
380
|
-
const aTime = parseInt(a.slice(12, -4))
|
|
381
|
-
const bTime = parseInt(b.slice(12, -4))
|
|
382
|
-
return bTime - aTime
|
|
383
|
-
})[1]
|
|
384
|
-
}
|
|
385
|
-
logFilePath = path.join(logDirPath, latestLogFile)
|
|
386
|
-
} else {
|
|
387
|
-
logFilePath = path.join(logDirPath, logfile)
|
|
388
|
-
if (!fs.existsSync(logFilePath)) {
|
|
389
|
-
// 如果在日志目录中没有找到,则尝试在当前目录中查找
|
|
390
|
-
logFilePath = path.resolve(workspace, logfile)
|
|
391
|
-
if (!fs.existsSync(logFilePath)) {
|
|
392
|
-
throw new Error(`Log file not found: ${logfile}`)
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
const rules = await this.Tools.getGenerateClawSkillRules(
|
|
397
|
-
`基于用户的任务目标和会话历史日志中的有效信息和,生成一个OpenClaw兼容的Skill工具包。用户目标: ${goal}, 会话历史路径: ${logFilePath}`,
|
|
398
|
-
)
|
|
399
|
-
return await this.Tools.generateClawSkill(rules)
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// 获取会话历史文件
|
|
403
|
-
function getSessionHistoryFile() {
|
|
404
|
-
const logDirPath = this.agentRobot.logDirPath
|
|
405
|
-
let logFiles = fs.readdirSync(logDirPath)
|
|
406
|
-
logFiles = logFiles.filter((file) => file.startsWith(`log-messeage-`))
|
|
407
|
-
if (logFiles.length === 0) {
|
|
408
|
-
throw new Error('No log file found for generating skill by history')
|
|
409
|
-
}
|
|
410
|
-
// 根据文件名称排序,获取最新的日志文件 log-messeage-{logId}.txt
|
|
411
|
-
let latestLogFile = logFiles[0]
|
|
412
|
-
if (logFiles.length > 1) {
|
|
413
|
-
latestLogFile = logFiles.sort((a, b) => {
|
|
414
|
-
const aTime = parseInt(a.slice(12, -4))
|
|
415
|
-
const bTime = parseInt(b.slice(12, -4))
|
|
416
|
-
return aTime - bTime
|
|
417
|
-
})[1]
|
|
418
|
-
}
|
|
419
|
-
const logFilePath = path.join(logDirPath, latestLogFile)
|
|
420
|
-
return logFilePath
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
const functions = {
|
|
424
|
-
getGenerateClawSkillRules,
|
|
425
|
-
getGenerateSkillRules,
|
|
426
|
-
generateClawSkill,
|
|
427
|
-
generateSkill,
|
|
428
|
-
generateClawSkillByHistory,
|
|
429
|
-
getSessionHistoryFile,
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
const GenerateTools = {
|
|
433
|
-
name: 'GenerateTools',
|
|
434
|
-
description:
|
|
435
|
-
'提供扩展工具与Skill工具包生成规则能力,用于辅助AI构建标准化扩展项目模板',
|
|
436
|
-
descriptions,
|
|
437
|
-
functions,
|
|
438
|
-
isSystem: true,
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
module.exports = GenerateTools
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
const aiInquirer = require("../utils/aiInquirer.js")
|
|
2
|
-
|
|
3
|
-
// 判断问答
|
|
4
|
-
async function inquirerConfirm(message, defaultVal = true, opt = {}) {
|
|
5
|
-
return aiInquirer.askConfirm(message, defaultVal = true, opt = {})
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
// 选择问答
|
|
9
|
-
function inquirerList(message, choices, defaultVal = 0, opt = {}) {
|
|
10
|
-
return aiInquirer.askList(message, choices, defaultVal = 0, opt = {})
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// 输入问答
|
|
14
|
-
async function inquirerInput(message, defaultVal = '', opt = {}) {
|
|
15
|
-
return aiInquirer.askInput(message, defaultVal = '', opt = {})
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// 输入数字
|
|
19
|
-
async function inquirerNumber(message, defaultVal = 0, opt = {}) {
|
|
20
|
-
return aiInquirer.askNumber(message, defaultVal = 0, opt = {})
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// 输入任何
|
|
24
|
-
function inquirerAny(questions) {
|
|
25
|
-
return aiInquirer.askAny(questions)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const descriptions = [
|
|
29
|
-
{
|
|
30
|
-
type: 'function',
|
|
31
|
-
function: {
|
|
32
|
-
name: 'inquirerConfirm',
|
|
33
|
-
description:
|
|
34
|
-
'用户交互:提示用户确认问题,用户输入Y/N后返回布尔值(true/false)。message-显示给用户的问题文本;defaultVal-默认布尔值(默认true);opt-inquirer额外配置选项对象(可选)。',
|
|
35
|
-
parameters: {
|
|
36
|
-
type: 'object',
|
|
37
|
-
properties: {
|
|
38
|
-
message: {
|
|
39
|
-
type: 'string',
|
|
40
|
-
description:
|
|
41
|
-
"显示给用户的确认问题文本,例如 '是否确认删除?'、'你同意继续吗?'",
|
|
42
|
-
},
|
|
43
|
-
defaultVal: {
|
|
44
|
-
type: 'boolean',
|
|
45
|
-
description:
|
|
46
|
-
'用户直接按回车时的默认值,true表示默认确认,false表示默认拒绝,默认为true',
|
|
47
|
-
},
|
|
48
|
-
opt: {
|
|
49
|
-
type: 'object',
|
|
50
|
-
description:
|
|
51
|
-
'inquirer额外配置选项对象,可选。支持的字段包括:when(条件函数)、prefix(问题前缀符号)、suffix(问题后缀符号)等',
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
required: ['message'],
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
type: 'function',
|
|
60
|
-
function: {
|
|
61
|
-
name: 'inquirerList',
|
|
62
|
-
description:
|
|
63
|
-
'用户交互:提示用户从列表中选择一项,返回用户选中的值。message-显示给用户的提示文本;choices-选项数组(字符串或{name,value,short}对象);defaultVal-默认选中索引(默认0);opt-inquirer额外配置选项对象(可选)。',
|
|
64
|
-
parameters: {
|
|
65
|
-
type: 'object',
|
|
66
|
-
properties: {
|
|
67
|
-
message: {
|
|
68
|
-
type: 'string',
|
|
69
|
-
description:
|
|
70
|
-
"显示给用户的选择提示文本,例如 '请选择编程语言:'、'请选择主题风格:'",
|
|
71
|
-
},
|
|
72
|
-
choices: {
|
|
73
|
-
type: 'array',
|
|
74
|
-
description:
|
|
75
|
-
"选项数组,每项可以是字符串(同时作为显示文本和值),也可以是对象 {name: '显示文本', value: '实际值', short: '选中后的简短显示'}。还支持 new inquirer.Separator() 作为分隔线",
|
|
76
|
-
items: {
|
|
77
|
-
type: 'object',
|
|
78
|
-
properties: {
|
|
79
|
-
name: { type: 'string', description: '选项的显示文本' },
|
|
80
|
-
value: {
|
|
81
|
-
type: 'string',
|
|
82
|
-
description: '选项被选中后的实际返回值',
|
|
83
|
-
},
|
|
84
|
-
short: {
|
|
85
|
-
type: 'string',
|
|
86
|
-
description: '选中后在提示行中显示的简短文本,可选',
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
defaultVal: {
|
|
92
|
-
type: 'number',
|
|
93
|
-
description:
|
|
94
|
-
'默认选中项的索引(从0开始),默认为0即选中第一项。例如传入2表示默认高亮第三个选项',
|
|
95
|
-
},
|
|
96
|
-
opt: {
|
|
97
|
-
type: 'object',
|
|
98
|
-
description:
|
|
99
|
-
'inquirer额外配置选项对象,可选。支持的字段包括:loop(布尔值,是否循环滚动列表,默认true)、pageSize(数字,一次显示的选项数量,超出则滚动)、when(条件函数)、filter(结果过滤函数)等',
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
required: ['message', 'choices'],
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
type: 'function',
|
|
108
|
-
function: {
|
|
109
|
-
name: 'inquirerInput',
|
|
110
|
-
description:
|
|
111
|
-
'用户交互:提示用户输入一段文本,返回用户输入的字符串。message-显示给用户的提示文本;defaultVal-默认输入值(默认空字符串);opt-inquirer额外配置选项对象(支持validate、filter等,可选)。',
|
|
112
|
-
parameters: {
|
|
113
|
-
type: 'object',
|
|
114
|
-
properties: {
|
|
115
|
-
message: {
|
|
116
|
-
type: 'string',
|
|
117
|
-
description:
|
|
118
|
-
"显示给用户的输入提示文本,例如 '请输入用户名:'、'请输入文件路径:'",
|
|
119
|
-
},
|
|
120
|
-
defaultVal: {
|
|
121
|
-
type: 'string',
|
|
122
|
-
description:
|
|
123
|
-
"用户直接按回车时的默认输入值,默认为空字符串。例如传入 './output' 表示默认路径",
|
|
124
|
-
},
|
|
125
|
-
opt: {
|
|
126
|
-
type: 'object',
|
|
127
|
-
description:
|
|
128
|
-
'inquirer额外配置选项对象,可选。支持的字段包括:validate(校验函数,接收输入值返回true或错误提示字符串)、filter(过滤函数)、transformer(显示转换函数)、when(条件函数)等',
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
required: ['message'],
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
type: 'function',
|
|
137
|
-
function: {
|
|
138
|
-
name: 'inquirerNumber',
|
|
139
|
-
description:
|
|
140
|
-
'用户交互:提示用户输入一个数字,返回Number类型值(非数字输入返回NaN)。message-显示给用户的提示文本;defaultVal-默认数字值(默认0);opt-inquirer额外配置选项对象(支持validate、filter等,可选)。',
|
|
141
|
-
parameters: {
|
|
142
|
-
type: 'object',
|
|
143
|
-
properties: {
|
|
144
|
-
message: {
|
|
145
|
-
type: 'string',
|
|
146
|
-
description:
|
|
147
|
-
"显示给用户的数字输入提示文本,例如 '请输入端口号:'、'请输入重试次数:'",
|
|
148
|
-
},
|
|
149
|
-
defaultVal: {
|
|
150
|
-
type: 'number',
|
|
151
|
-
description:
|
|
152
|
-
'用户直接按回车时的默认数字值,默认为0。例如传入8080表示默认端口号',
|
|
153
|
-
},
|
|
154
|
-
opt: {
|
|
155
|
-
type: 'object',
|
|
156
|
-
description:
|
|
157
|
-
'inquirer额外配置选项对象,可选。支持的字段包括:validate(校验函数,可用于限制数值范围)、filter(过滤函数)、when(条件函数)等',
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
required: ['message'],
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
type: 'function',
|
|
166
|
-
function: {
|
|
167
|
-
name: 'inquirerAny',
|
|
168
|
-
description:
|
|
169
|
-
'用户交互:直接调用inquirer.prompt()的通用封装,接受自定义问题对象数组,支持一次提出多个问题进行连续交互,返回包含所有答案的对象({问题name: 对应答案})。参数说明(不是对象参数):questions-inquirer问题对象数组,每个对象包含type(问题类型:input/confirm/list/checkbox/password/editor/rawlist/expand)、name(标识名称)、message(提示文本)及可选的default、choices、validate、filter、when等字段。',
|
|
170
|
-
parameters: {
|
|
171
|
-
type: 'object',
|
|
172
|
-
properties: {
|
|
173
|
-
questions: {
|
|
174
|
-
type: 'array',
|
|
175
|
-
description:
|
|
176
|
-
"inquirer问题对象数组,每个问题对象包含以下字段:type(问题类型,如'input'/'confirm'/'list'/'checkbox'/'password'/'editor'/'rawlist'/'expand')、name(问题标识名称)、message(提示文本)、default(默认值)、choices(选项数组,适用于list/checkbox/rawlist/expand类型)、validate(校验函数)、filter(过滤函数)、when(条件函数,控制是否显示该问题,接收前面的回答作为参数)、transformer(显示转换函数)等。多个问题会按数组顺序依次向用户提问",
|
|
177
|
-
items: {
|
|
178
|
-
type: 'object',
|
|
179
|
-
properties: {
|
|
180
|
-
type: {
|
|
181
|
-
type: 'string',
|
|
182
|
-
description:
|
|
183
|
-
"问题类型:'input'(文本输入)、'confirm'(是否确认)、'list'(单选列表)、'checkbox'(多选列表)、'password'(密码输入,输入内容隐藏)、'editor'(打开编辑器输入大段文本)、'rawlist'(带编号的列表选择)、'expand'(按键选择展开列表)",
|
|
184
|
-
},
|
|
185
|
-
name: {
|
|
186
|
-
type: 'string',
|
|
187
|
-
description:
|
|
188
|
-
'问题的唯一标识名称,用于在返回的答案对象中作为key提取对应答案',
|
|
189
|
-
},
|
|
190
|
-
message: {
|
|
191
|
-
type: 'string',
|
|
192
|
-
description: '显示给用户的问题提示文本',
|
|
193
|
-
},
|
|
194
|
-
default: {
|
|
195
|
-
type: 'string',
|
|
196
|
-
description: '默认值,类型根据问题类型而定',
|
|
197
|
-
},
|
|
198
|
-
choices: {
|
|
199
|
-
type: 'array',
|
|
200
|
-
description:
|
|
201
|
-
'选项数组,适用于list/checkbox/rawlist/expand类型',
|
|
202
|
-
items: {
|
|
203
|
-
type: 'object',
|
|
204
|
-
properties: {
|
|
205
|
-
name: { type: 'string' },
|
|
206
|
-
value: { type: 'string' },
|
|
207
|
-
short: { type: 'string' },
|
|
208
|
-
},
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
validate: {
|
|
212
|
-
type: 'string',
|
|
213
|
-
description:
|
|
214
|
-
'校验函数,接收用户输入返回true表示通过或返回错误字符串',
|
|
215
|
-
},
|
|
216
|
-
},
|
|
217
|
-
required: ['type', 'name', 'message'],
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
},
|
|
221
|
-
required: ['questions'],
|
|
222
|
-
},
|
|
223
|
-
},
|
|
224
|
-
},
|
|
225
|
-
]
|
|
226
|
-
|
|
227
|
-
const functions = {
|
|
228
|
-
inquirerConfirm,
|
|
229
|
-
inquirerList,
|
|
230
|
-
inquirerInput,
|
|
231
|
-
inquirerNumber,
|
|
232
|
-
inquirerAny,
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const InquirerTool = {
|
|
236
|
-
name: 'InquirerTool',
|
|
237
|
-
description:
|
|
238
|
-
'提供用户交互功能,支持确认、列表选择、文本输入、数字输入等多种交互方式',
|
|
239
|
-
descriptions,
|
|
240
|
-
functions,
|
|
241
|
-
isSystem: true
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
module.exports = InquirerTool
|