deepfish-ai 1.0.15 → 1.0.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 +1 -0
- package/README_CN.md +1 -0
- package/package.json +1 -1
- package/src/cli/DefaultConfig.js +2 -1
- package/src/cli/index.js +1 -1
- package/src/core/ai-services/AiWorker/AiAgent.js +6 -5
- package/src/core/ai-services/AiWorker/AiPrompt.js +10 -7
- package/src/core/ai-services/AiWorker/AiTools.js +7 -5
- package/src/core/extension/InquirerExtension.js +177 -51
- package/src/core/extension/SystemExtension.js +49 -4
package/README.md
CHANGED
|
@@ -193,6 +193,7 @@ module.exports = {
|
|
|
193
193
|
maxMessagesCount: 100, // Maximum compression count, -1 for unlimited
|
|
194
194
|
maxHistoryExpireTime: 30, // Maximum session expiration time in days, -1 for unlimited, 0 to disable recording
|
|
195
195
|
maxLogExpireTime: 3, // Log expiration time in days, -1 for unlimited, 0 to disable recording
|
|
196
|
+
maxBlockFileSize: 20, // Maximum block file size in KB; files exceeding this size need to be processed in blocks
|
|
196
197
|
extensions: [], // List of extension file paths
|
|
197
198
|
skills: [], // List of skill configurations
|
|
198
199
|
encoding: "utf-8", // Command line encoding format, can be set to utf-8, gbk, etc., or auto/empty for auto-detection
|
package/README_CN.md
CHANGED
|
@@ -190,6 +190,7 @@ module.exports = {
|
|
|
190
190
|
maxMessagesCount: 100, // 最大压缩数量,-1表示无限制
|
|
191
191
|
maxHistoryExpireTime: 30, // 整个会话的最大过期时间,单位天,-1表示无限制,0表示不记录
|
|
192
192
|
maxLogExpireTime: 3, // 日志过期时间,单位天,-1表示无限制,0表示不记录
|
|
193
|
+
maxBlockFileSize: 20, // 最大分块文件大小,单位KB;超过该大小的文件需要分块处理
|
|
193
194
|
extensions: [], // 扩展文件路径列表
|
|
194
195
|
skills: [], // 技能配置列表
|
|
195
196
|
encoding: "utf-8", // 命令行编码格式,可设置为utf-8、gbk等,也可以设置成auto或空值自动判断
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deepfish-ai",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"description": "This is an AI-driven command-line tool built on Node.js, equipped with AI agent and workflow capabilities. It is compatible with a wide range of AI models, can convert natural language into cross-system terminal and file operation commands, and features high extensibility. It supports complex tasks such as translation, content creation, and format conversion, while allowing custom extensions to be automatically generated via AI.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
package/src/cli/DefaultConfig.js
CHANGED
|
@@ -6,9 +6,10 @@ const defaultConfig = {
|
|
|
6
6
|
maxMessagesCount: 100, // 最大压缩数量,-1表示无限制
|
|
7
7
|
maxHistoryExpireTime: 30, // 整个会话的最大过期时间,单位天,-1表示无限制, 0表示不记录
|
|
8
8
|
maxLogExpireTime: 3, // 日志过期时间,单位天,-1表示无限制,0表示不记录
|
|
9
|
+
maxBlockFileSize: 20, // 最大分块文件大小,单位KB;超过该大小的文件需要分块处理
|
|
9
10
|
extensions: [],
|
|
10
11
|
skills:[],
|
|
11
|
-
encoding: "
|
|
12
|
+
encoding: "auto", // 命令行编码格式, 可设置为utf-8、gbk等, 也可以设置成auto或空值自动判断
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
const aiCliConfig = {
|
package/src/cli/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @Author: Roman 306863030@qq.com
|
|
3
3
|
* @Date: 2026-03-16 09:18:05
|
|
4
|
-
* @LastEditors:
|
|
5
|
-
* @LastEditTime: 2026-03-
|
|
6
|
-
* @FilePath: \src\core\ai-services\AiWorker\AiAgent.js
|
|
4
|
+
* @LastEditors: roman_123 306863030@qq.com
|
|
5
|
+
* @LastEditTime: 2026-03-26 01:04:45
|
|
6
|
+
* @FilePath: \deepfish\src\core\ai-services\AiWorker\AiAgent.js
|
|
7
7
|
* @Description: 工作流循环
|
|
8
8
|
* @
|
|
9
9
|
*/
|
|
@@ -28,6 +28,7 @@ class AiAgent {
|
|
|
28
28
|
this.aiConfig = aiConfig
|
|
29
29
|
this.maxIterations =
|
|
30
30
|
config.maxIterations === -1 ? Infinity : config.maxIterations
|
|
31
|
+
this.maxBlockFileSize = this.config.maxBlockFileSize || 20 // 默认20KB
|
|
31
32
|
this.aiMessageManager = new AIMessageManager(aiClient, config, aiConfig, [])
|
|
32
33
|
this.extensionTools = extensionTools
|
|
33
34
|
this.name = config.name
|
|
@@ -97,7 +98,7 @@ class AiAgent {
|
|
|
97
98
|
const fileInfo = await this.extensionTools.functions['getFileInfo'](
|
|
98
99
|
parsedArgs.filePath,
|
|
99
100
|
)
|
|
100
|
-
if (fileInfo && fileInfo.isFile && fileInfo.size >
|
|
101
|
+
if (fileInfo && fileInfo.isFile && fileInfo.size > this.maxBlockFileSize * 1024) {
|
|
101
102
|
this.aiMessageManager.addTool(id, {
|
|
102
103
|
error:
|
|
103
104
|
'文件过大,请使用executeJSCode工具编写脚本分块读取和处理文件,避免一次性读取整个文件内容到对话中。建议使用fs.createReadStream逐行或分块读取,仅返回必要的结果或总结。',
|
|
@@ -110,7 +111,7 @@ class AiAgent {
|
|
|
110
111
|
let result = await toolFunction(...Object.values(parsedArgs))
|
|
111
112
|
let toolContent = JSON.stringify(result)
|
|
112
113
|
if (name !== 'requestAI') {
|
|
113
|
-
const MAX_CONTENT_SIZE =
|
|
114
|
+
const MAX_CONTENT_SIZE = this.maxBlockFileSize * 1024
|
|
114
115
|
if (toolContent.length > MAX_CONTENT_SIZE) {
|
|
115
116
|
if (
|
|
116
117
|
typeof result === 'string' &&
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @Author: Roman 306863030@qq.com
|
|
3
3
|
* @Date: 2026-03-17 09:12:22
|
|
4
|
-
* @LastEditors:
|
|
5
|
-
* @LastEditTime: 2026-03-
|
|
4
|
+
* @LastEditors: roman_123 306863030@qq.com
|
|
5
|
+
* @LastEditTime: 2026-03-26 02:12:44
|
|
6
6
|
* @FilePath: \deepfish\src\core\ai-services\AiWorker\AiPrompt.js
|
|
7
7
|
* @Description: AI请求提示词
|
|
8
8
|
* @
|
|
@@ -23,7 +23,7 @@ const AiAgentSystemPrompt = `
|
|
|
23
23
|
### 大文本文件处理规则(分步执行)
|
|
24
24
|
处理长文档等大文件(单文件>20KB)时,必须按以下步骤分块处理:
|
|
25
25
|
1. 预处理:先执行文件大小/结构检查(如通过命令行/JS 代码获取文件大小、判断文件格式),输出检查结果;
|
|
26
|
-
2. 分块规则:按5KB-10KB/块拆分文件,拆分后每个块生成独立临时文件(命名格式:{原文件名}_chunk{序号}.tmp);
|
|
26
|
+
2. 分块规则:按5KB-10KB/块拆分文件,拆分后每个块生成独立临时文件(命名格式:tmp_{原文件名}_chunk{序号}.tmp);
|
|
27
27
|
3. 处理逻辑:翻译/总结/分析类任务逐块处理,每块处理完成后记录结果,最后合并所有块的结果生成最终文件;
|
|
28
28
|
4. 合并校验:合并后需校验结果完整性(如总字符数匹配、无内容缺失),确保分块处理无遗漏。
|
|
29
29
|
|
|
@@ -31,7 +31,8 @@ const AiAgentSystemPrompt = `
|
|
|
31
31
|
1. 最优路径优先:执行前必须先规划最少步骤的操作路径,明确「先做什么、再做什么、哪些可省略」,避免重复操作和无效步骤;
|
|
32
32
|
2. 异常反馈:操作失败(如命令执行报错、文件不存在)时,需明确说明「失败原因+可尝试的解决方案」,而非仅提示“操作失败”;
|
|
33
33
|
3. 结果校验:任务完成后,需简单校验结果是否符合用户目标(如文件是否生成、内容是否完整),并向用户反馈校验结果。
|
|
34
|
-
4.
|
|
34
|
+
4. 如果执行任务过程中需要安装软件、工具或执行"npm install"命令,必须通过调用用户交互函数与用户交互,等待用户确认后再执行安装。
|
|
35
|
+
5. 任务执行过程中,产生的所有临时文件(如分块文件、测试文件等)必须以"tmp_"为前缀命名,并在任务完成后删除这些临时文件,确保工作目录整洁。
|
|
35
36
|
`
|
|
36
37
|
|
|
37
38
|
const SkillAiAgentSystemPrompt = `
|
|
@@ -47,7 +48,7 @@ const SkillAiAgentSystemPrompt = `
|
|
|
47
48
|
### 大文本文件处理规则(分步执行)
|
|
48
49
|
处理长文档等大文件(单文件>20KB)时,必须按以下步骤分块处理:
|
|
49
50
|
1. 预处理:先执行文件大小/结构检查(如通过命令行/JS 代码获取文件大小、判断文件格式),输出检查结果;
|
|
50
|
-
2. 分块规则:按5KB-10KB/块拆分文件,拆分后每个块生成独立临时文件(命名格式:{原文件名}_chunk{序号}.tmp);
|
|
51
|
+
2. 分块规则:按5KB-10KB/块拆分文件,拆分后每个块生成独立临时文件(命名格式:tmp_{原文件名}_chunk{序号}.tmp);
|
|
51
52
|
3. 处理逻辑:翻译/总结/分析类任务逐块处理,每块处理完成后记录结果,最后合并所有块的结果生成最终文件;
|
|
52
53
|
4. 合并校验:合并后需校验结果完整性(如总字符数匹配、无内容缺失),确保分块处理无遗漏。
|
|
53
54
|
|
|
@@ -58,6 +59,7 @@ const SkillAiAgentSystemPrompt = `
|
|
|
58
59
|
4. 如果发现不能使用Skill完成任务,则直接说明原因,不要尝试使用其他工具或技能来完成任务;
|
|
59
60
|
5. 如果需要安装软件或工具来完成任务,必须通过调用用户交互函数与用户交互,等待用户确认后再执行安装。
|
|
60
61
|
6. 任务完成后,反馈任务执行结果。
|
|
62
|
+
7. 任务执行过程中,产生的所有临时文件(如分块文件、测试文件等)必须以"tmp_"为前缀命名,并在任务完成后删除这些临时文件,确保工作目录整洁。
|
|
61
63
|
`
|
|
62
64
|
|
|
63
65
|
const TestAiAgentSystemPrompt = `
|
|
@@ -74,8 +76,9 @@ const TestAiAgentSystemPrompt = `
|
|
|
74
76
|
1. 仔细分析测试目标,确保完全理解测试需求和预期结果;
|
|
75
77
|
2. 在测试过程中可以通过创建前缀为"test_"的临时文件辅助测试,完成后需删除这些临时文件;
|
|
76
78
|
3. 在测试过程中随意不能修改原有的文件内容;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
4. 如果发现不能使用工具函数完成测试任务,则直接说明原因,不要做过多尝试;
|
|
80
|
+
5. 任务完成后,反馈测试执行结果。
|
|
81
|
+
6. 任务执行过程中,产生的所有临时文件(如分块文件、测试文件等)必须以"tmp_"为前缀命名,并在任务完成后删除这些临时文件,确保工作目录整洁。
|
|
79
82
|
`
|
|
80
83
|
|
|
81
84
|
module.exports = {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @Author: Roman 306863030@qq.com
|
|
3
3
|
* @Date: 2026-03-17 09:12:22
|
|
4
|
-
* @LastEditors:
|
|
5
|
-
* @LastEditTime: 2026-03-
|
|
4
|
+
* @LastEditors: roman_123 306863030@qq.com
|
|
5
|
+
* @LastEditTime: 2026-03-26 01:08:48
|
|
6
6
|
* @FilePath: \deepfish\src\core\ai-services\AiWorker\AiTools.js
|
|
7
7
|
* @Description: 对话初始化、对话请求
|
|
8
8
|
* @
|
|
@@ -36,15 +36,17 @@ function getInitialMessages(goal) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function getSystemPrompt() {
|
|
39
|
+
const config = GlobalVariable.aiCli.config
|
|
39
40
|
const skillPrompt = GlobalVariable.skillConfigManager.preLoadSkills()
|
|
40
|
-
const systemDescription = `${AiAgentSystemPrompt}\n\n${skillPrompt}`
|
|
41
|
+
const systemDescription = `${AiAgentSystemPrompt.replace('20KB', `${config.maxBlockFileSize}KB`)}\n\n${skillPrompt}`
|
|
41
42
|
return systemDescription
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
// 获取调用skill的初始message
|
|
45
46
|
function getInitialMessagesForSkill(skillContent, goal) {
|
|
47
|
+
const config = GlobalVariable.aiCli.config
|
|
46
48
|
const systemDescription = `
|
|
47
|
-
${SkillAiAgentSystemPrompt}
|
|
49
|
+
${SkillAiAgentSystemPrompt.replace('20KB', `${config.maxBlockFileSize}KB`)}
|
|
48
50
|
### 以下是加载完成的Skill.md文件的内容:
|
|
49
51
|
${skillContent}`
|
|
50
52
|
return [
|
|
@@ -63,7 +65,7 @@ function getInitialMessagesForTest(goal) {
|
|
|
63
65
|
return [
|
|
64
66
|
{
|
|
65
67
|
role: 'system',
|
|
66
|
-
content: TestAiAgentSystemPrompt,
|
|
68
|
+
content: TestAiAgentSystemPrompt.replace('20KB', `${GlobalVariable.aiCli.config.maxBlockFileSize}KB`),
|
|
67
69
|
},
|
|
68
70
|
{
|
|
69
71
|
role: 'user',
|
|
@@ -8,8 +8,8 @@ async function askConfirm(name, message, defaultVal = true, opt = {}) {
|
|
|
8
8
|
name,
|
|
9
9
|
message,
|
|
10
10
|
default: defaultVal,
|
|
11
|
-
...opt
|
|
12
|
-
}
|
|
11
|
+
...opt,
|
|
12
|
+
},
|
|
13
13
|
]
|
|
14
14
|
const answers = await inquirer.prompt(questions)
|
|
15
15
|
return answers[name]
|
|
@@ -24,8 +24,8 @@ function askList(name, message, choices, defaultVal = 0, opt = {}) {
|
|
|
24
24
|
message,
|
|
25
25
|
choices,
|
|
26
26
|
default: defaultVal,
|
|
27
|
-
...opt
|
|
28
|
-
}
|
|
27
|
+
...opt,
|
|
28
|
+
},
|
|
29
29
|
]
|
|
30
30
|
return inquirer.prompt(questions)
|
|
31
31
|
}
|
|
@@ -38,7 +38,7 @@ async function askInput(name, message, defaultVal = '', opt = {}) {
|
|
|
38
38
|
name,
|
|
39
39
|
message,
|
|
40
40
|
default: defaultVal,
|
|
41
|
-
...opt
|
|
41
|
+
...opt,
|
|
42
42
|
},
|
|
43
43
|
]
|
|
44
44
|
const answers = await inquirer.prompt(questions)
|
|
@@ -53,7 +53,7 @@ async function askNumber(name, message, defaultVal = 0, opt = {}) {
|
|
|
53
53
|
name,
|
|
54
54
|
message,
|
|
55
55
|
default: defaultVal,
|
|
56
|
-
...opt
|
|
56
|
+
...opt,
|
|
57
57
|
},
|
|
58
58
|
]
|
|
59
59
|
const answers = await inquirer.prompt(questions)
|
|
@@ -67,85 +67,210 @@ function askAny(questions) {
|
|
|
67
67
|
|
|
68
68
|
const descriptions = [
|
|
69
69
|
{
|
|
70
|
-
type:
|
|
70
|
+
type: 'function',
|
|
71
71
|
function: {
|
|
72
|
-
name:
|
|
73
|
-
description:
|
|
72
|
+
name: 'askConfirm',
|
|
73
|
+
description:
|
|
74
|
+
'用户交互:基于inquirer的confirm类型封装,提示用户确认问题,用户输入Y/N后返回布尔值(true/false)。参数说明(不是对象参数):name-问题标识名称;message-显示给用户的问题文本;defaultVal-默认布尔值(默认true);opt-inquirer额外配置选项对象。',
|
|
74
75
|
parameters: {
|
|
75
|
-
type:
|
|
76
|
+
type: 'object',
|
|
76
77
|
properties: {
|
|
77
|
-
name: {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
name: {
|
|
79
|
+
type: 'string',
|
|
80
|
+
description:
|
|
81
|
+
"问题的唯一标识名称,用于从返回结果中提取该问题的答案,例如 'confirmDelete'、'agreeLicense'",
|
|
82
|
+
},
|
|
83
|
+
message: {
|
|
84
|
+
type: 'string',
|
|
85
|
+
description:
|
|
86
|
+
"显示给用户的确认问题文本,例如 '是否确认删除?'、'你同意继续吗?'",
|
|
87
|
+
},
|
|
88
|
+
defaultVal: {
|
|
89
|
+
type: 'boolean',
|
|
90
|
+
description:
|
|
91
|
+
'用户直接按回车时的默认值,true表示默认确认,false表示默认拒绝,默认为true',
|
|
92
|
+
},
|
|
93
|
+
opt: {
|
|
94
|
+
type: 'object',
|
|
95
|
+
description:
|
|
96
|
+
'inquirer额外配置选项对象,可选。支持的字段包括:when(条件函数,控制是否显示此问题)、prefix(问题前缀符号)、suffix(问题后缀符号)、transformer(显示值转换函数)等',
|
|
97
|
+
},
|
|
81
98
|
},
|
|
82
|
-
required: [
|
|
99
|
+
required: ['name', 'message'],
|
|
83
100
|
},
|
|
84
101
|
},
|
|
85
102
|
},
|
|
86
103
|
{
|
|
87
|
-
type:
|
|
104
|
+
type: 'function',
|
|
88
105
|
function: {
|
|
89
|
-
name:
|
|
90
|
-
description:
|
|
106
|
+
name: 'askList',
|
|
107
|
+
description:
|
|
108
|
+
'用户交互:基于inquirer的list类型封装,提示用户从列表中选择一项,返回包含用户选择结果的对象({choices => items => name: 选中值})。参数说明(不是对象参数):name-问题标识名称;message-显示给用户的提示文本;choices-选项数组(字符串或{name,value,short}对象);defaultVal-默认选中索引(默认0);opt-inquirer额外配置选项对象。',
|
|
91
109
|
parameters: {
|
|
92
|
-
type:
|
|
110
|
+
type: 'object',
|
|
93
111
|
properties: {
|
|
94
|
-
name: {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
name: {
|
|
113
|
+
type: 'string',
|
|
114
|
+
description:
|
|
115
|
+
"问题的唯一标识名称,用于从返回对象中提取选择结果,例如 'language'、'theme'。返回值格式为 {[name]: 选中项的value}",
|
|
116
|
+
},
|
|
117
|
+
message: {
|
|
118
|
+
type: 'string',
|
|
119
|
+
description:
|
|
120
|
+
"显示给用户的选择提示文本,例如 '请选择编程语言:'、'请选择主题风格:'",
|
|
121
|
+
},
|
|
122
|
+
choices: {
|
|
123
|
+
type: 'array',
|
|
124
|
+
description:
|
|
125
|
+
"选项数组,每项可以是字符串(同时作为显示文本和值),也可以是对象 {name: '显示文本', value: '实际值', short: '选中后的简短显示'}。还支持 new inquirer.Separator() 作为分隔线",
|
|
126
|
+
items: {
|
|
127
|
+
type: 'object',
|
|
128
|
+
properties: {
|
|
129
|
+
name: { type: 'string', description: '选项的显示文本' },
|
|
130
|
+
value: {
|
|
131
|
+
type: 'string',
|
|
132
|
+
description: '选项被选中后的实际返回值',
|
|
133
|
+
},
|
|
134
|
+
short: {
|
|
135
|
+
type: 'string',
|
|
136
|
+
description: '选中后在提示行中显示的简短文本,可选',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
defaultVal: {
|
|
142
|
+
type: 'number',
|
|
143
|
+
description:
|
|
144
|
+
'默认选中项的索引(从0开始),默认为0即选中第一项。例如传入2表示默认高亮第三个选项',
|
|
145
|
+
},
|
|
146
|
+
opt: {
|
|
147
|
+
type: 'object',
|
|
148
|
+
description:
|
|
149
|
+
'inquirer额外配置选项对象,可选。支持的字段包括:loop(布尔值,是否循环滚动列表,默认true)、pageSize(数字,一次显示的选项数量,超出则滚动)、when(条件函数)、filter(结果过滤函数)等',
|
|
150
|
+
},
|
|
99
151
|
},
|
|
100
|
-
required: [
|
|
152
|
+
required: ['name', 'message', 'choices'],
|
|
101
153
|
},
|
|
102
154
|
},
|
|
103
155
|
},
|
|
104
156
|
{
|
|
105
|
-
type:
|
|
157
|
+
type: 'function',
|
|
106
158
|
function: {
|
|
107
|
-
name:
|
|
108
|
-
description:
|
|
159
|
+
name: 'askInput',
|
|
160
|
+
description:
|
|
161
|
+
'用户交互:基于inquirer的input类型封装,提示用户输入一段文本,返回用户输入的字符串。参数说明(不是对象参数):name-问题标识名称;message-显示给用户的提示文本;defaultVal-默认输入值(默认空字符串);opt-inquirer额外配置选项对象(支持validate、filter等)。',
|
|
109
162
|
parameters: {
|
|
110
|
-
type:
|
|
163
|
+
type: 'object',
|
|
111
164
|
properties: {
|
|
112
|
-
name: {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
165
|
+
name: {
|
|
166
|
+
type: 'string',
|
|
167
|
+
description:
|
|
168
|
+
"问题的唯一标识名称,用于从返回结果中提取输入内容,例如 'username'、'filePath'",
|
|
169
|
+
},
|
|
170
|
+
message: {
|
|
171
|
+
type: 'string',
|
|
172
|
+
description:
|
|
173
|
+
"显示给用户的输入提示文本,例如 '请输入用户名:'、'请输入文件路径:'",
|
|
174
|
+
},
|
|
175
|
+
defaultVal: {
|
|
176
|
+
type: 'string',
|
|
177
|
+
description:
|
|
178
|
+
"用户直接按回车时的默认输入值,默认为空字符串。例如传入 './output' 表示默认路径",
|
|
179
|
+
},
|
|
180
|
+
opt: {
|
|
181
|
+
type: 'object',
|
|
182
|
+
description:
|
|
183
|
+
'inquirer额外配置选项对象,可选。支持的字段包括:validate(校验函数,接收输入值返回true或错误提示字符串)、filter(过滤函数,对用户输入进行转换处理)、transformer(显示转换函数,不影响实际值)、when(条件函数)等',
|
|
184
|
+
},
|
|
116
185
|
},
|
|
117
|
-
required: [
|
|
186
|
+
required: ['name', 'message'],
|
|
118
187
|
},
|
|
119
188
|
},
|
|
120
189
|
},
|
|
121
190
|
{
|
|
122
|
-
type:
|
|
191
|
+
type: 'function',
|
|
123
192
|
function: {
|
|
124
|
-
name:
|
|
125
|
-
description:
|
|
193
|
+
name: 'askNumber',
|
|
194
|
+
description:
|
|
195
|
+
'用户交互:基于inquirer的number类型封装,提示用户输入一个数字,返回Number类型值(非数字输入返回NaN)。参数说明(不是对象参数):name-问题标识名称;message-显示给用户的提示文本;defaultVal-默认数字值(默认0);opt-inquirer额外配置选项对象(支持validate、filter等)。',
|
|
126
196
|
parameters: {
|
|
127
|
-
type:
|
|
197
|
+
type: 'object',
|
|
128
198
|
properties: {
|
|
129
|
-
name: {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
199
|
+
name: {
|
|
200
|
+
type: 'string',
|
|
201
|
+
description:
|
|
202
|
+
"问题的唯一标识名称,用于从返回结果中提取输入的数字,例如 'port'、'retryCount'",
|
|
203
|
+
},
|
|
204
|
+
message: {
|
|
205
|
+
type: 'string',
|
|
206
|
+
description:
|
|
207
|
+
"显示给用户的数字输入提示文本,例如 '请输入端口号:'、'请输入重试次数:'",
|
|
208
|
+
},
|
|
209
|
+
defaultVal: {
|
|
210
|
+
type: 'number',
|
|
211
|
+
description:
|
|
212
|
+
'用户直接按回车时的默认数字值,默认为0。例如传入8080表示默认端口号',
|
|
213
|
+
},
|
|
214
|
+
opt: {
|
|
215
|
+
type: 'object',
|
|
216
|
+
description:
|
|
217
|
+
'inquirer额外配置选项对象,可选。支持的字段包括:validate(校验函数,接收输入值返回true或错误提示字符串,可用于限制数值范围)、filter(过滤函数,对输入数字进行转换)、when(条件函数)等',
|
|
218
|
+
},
|
|
133
219
|
},
|
|
134
|
-
required: [
|
|
220
|
+
required: ['name', 'message'],
|
|
135
221
|
},
|
|
136
222
|
},
|
|
137
223
|
},
|
|
138
224
|
{
|
|
139
|
-
type:
|
|
225
|
+
type: 'function',
|
|
140
226
|
function: {
|
|
141
|
-
name:
|
|
142
|
-
description:
|
|
227
|
+
name: 'askAny',
|
|
228
|
+
description:
|
|
229
|
+
'用户交互:直接调用inquirer.prompt()的通用封装,接受自定义问题对象数组,支持一次提出多个问题进行连续交互,返回包含所有答案的对象({问题name: 对应答案})。参数说明(不是对象参数):questions-inquirer问题对象数组,每个对象包含type(问题类型:input/confirm/list/checkbox/password/editor/rawlist/expand)、name(标识名称)、message(提示文本)及可选的default、choices、validate、filter、when等字段。',
|
|
143
230
|
parameters: {
|
|
144
|
-
type:
|
|
231
|
+
type: 'object',
|
|
145
232
|
properties: {
|
|
146
|
-
questions: {
|
|
233
|
+
questions: {
|
|
234
|
+
type: 'array',
|
|
235
|
+
description:
|
|
236
|
+
"inquirer问题对象数组,每个问题对象包含以下字段:type(问题类型,如'input'/'confirm'/'list'/'checkbox'/'password'/'editor'/'rawlist'/'expand')、name(问题标识名称)、message(提示文本)、default(默认值)、choices(选项数组,适用于list/checkbox/rawlist/expand类型)、validate(校验函数)、filter(过滤函数)、when(条件函数,控制是否显示该问题,接收前面的回答作为参数)、transformer(显示转换函数)等。多个问题会按数组顺序依次向用户提问",
|
|
237
|
+
items: {
|
|
238
|
+
type: 'object',
|
|
239
|
+
properties: {
|
|
240
|
+
type: {
|
|
241
|
+
type: 'string',
|
|
242
|
+
description:
|
|
243
|
+
"问题类型:'input'(文本输入)、'confirm'(是否确认)、'list'(单选列表)、'checkbox'(多选列表)、'password'(密码输入,输入内容隐藏)、'editor'(打开编辑器输入大段文本)、'rawlist'(带编号的列表选择)、'expand'(按键选择展开列表)",
|
|
244
|
+
},
|
|
245
|
+
name: {
|
|
246
|
+
type: 'string',
|
|
247
|
+
description:
|
|
248
|
+
'问题的唯一标识名称,用于在返回的答案对象中作为key提取对应答案',
|
|
249
|
+
},
|
|
250
|
+
message: {
|
|
251
|
+
type: 'string',
|
|
252
|
+
description: '显示给用户的问题提示文本',
|
|
253
|
+
},
|
|
254
|
+
default: {
|
|
255
|
+
type: 'string',
|
|
256
|
+
description: '默认值,类型根据问题类型而定',
|
|
257
|
+
},
|
|
258
|
+
choices: {
|
|
259
|
+
type: 'array',
|
|
260
|
+
description:
|
|
261
|
+
'选项数组,适用于list/checkbox/rawlist/expand类型',
|
|
262
|
+
},
|
|
263
|
+
validate: {
|
|
264
|
+
type: 'string',
|
|
265
|
+
description:
|
|
266
|
+
'校验函数,接收用户输入返回true表示通过或返回错误字符串',
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
required: ['type', 'name', 'message'],
|
|
270
|
+
},
|
|
271
|
+
},
|
|
147
272
|
},
|
|
148
|
-
required: [
|
|
273
|
+
required: ['questions'],
|
|
149
274
|
},
|
|
150
275
|
},
|
|
151
276
|
},
|
|
@@ -161,7 +286,8 @@ const functions = {
|
|
|
161
286
|
|
|
162
287
|
module.exports = {
|
|
163
288
|
name: 'InquirerExtension',
|
|
164
|
-
extensionDescription:
|
|
289
|
+
extensionDescription:
|
|
290
|
+
'提供用户交互功能,支持确认、列表选择、文本输入、数字输入等多种交互方式',
|
|
165
291
|
descriptions,
|
|
166
292
|
functions,
|
|
167
|
-
}
|
|
293
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @Author: Roman 306863030@qq.com
|
|
3
3
|
* @Date: 2026-03-17 11:59:19
|
|
4
|
-
* @LastEditors:
|
|
5
|
-
* @LastEditTime: 2026-03-
|
|
4
|
+
* @LastEditors: roman_123 306863030@qq.com
|
|
5
|
+
* @LastEditTime: 2026-03-26 00:54:25
|
|
6
6
|
* @FilePath: \deepfish\src\core\extension\SystemExtension.js
|
|
7
7
|
* @Description: 默认扩展函数
|
|
8
8
|
* @
|
|
@@ -132,7 +132,7 @@ async function getExtensionFileRule(goal) {
|
|
|
132
132
|
基于指定规则创建一个标准化的Node.js NPM项目,实现用户目标:${goal},最终输出符合AI工作流调用规范的函数模块,并配套中英文说明文档。
|
|
133
133
|
|
|
134
134
|
### 第一步:项目初始化
|
|
135
|
-
1.
|
|
135
|
+
1. 目录创建:新建目录,目录名称以"deepfish-"开头,如"deepfish-「项目功能名称」",作为NPM项目根目录
|
|
136
136
|
2. package.json配置:
|
|
137
137
|
- name字段值:@deepfish-ai/项目功能名称(替换「项目功能名称」为实际功能名)
|
|
138
138
|
- git仓库地址:固定为 https://github.com/qq306863030/deepfish-extensions.git
|
|
@@ -155,11 +155,14 @@ async function getExtensionFileRule(goal) {
|
|
|
155
155
|
2. 命名规范:
|
|
156
156
|
- 函数名称前缀:「领域用途+分隔符」(如systemFileManagement_)
|
|
157
157
|
- 函数描述开头:统一格式「领域用途+分隔符+功能描述」(如系统文件管理:重命名文件)
|
|
158
|
-
3.
|
|
158
|
+
3. 内置工具函数调用:函数内部会自动注入所有内置工具函数,可以通过this.Tools获取,示例:
|
|
159
159
|
- this.Tools.requestAI(systemDescription, prompt, temperature)
|
|
160
160
|
- this.Tools.readFile(filePath)
|
|
161
161
|
- 其他文件处理类内置函数(运行时自动注入)
|
|
162
162
|
4. 函数数量:至少包含1个可被AI工作流调用的函数
|
|
163
|
+
5. 函数中的this在运行时指向DeepFish AI的运行时环境,可以通过this访问到AI配置、工具函数等资源,因此在创建扩展时需要注意this的指向
|
|
164
|
+
6. 尽量保持代码思路清晰,避免过度复杂的逻辑嵌套,必要时可以适当拆分函数、添加注释说明或拆分成多个文件
|
|
165
|
+
7. 需要创建的是DeepFish AI的扩展工具,并非创建Skill工具包,因此不需要编写SKILL.md文件
|
|
163
166
|
|
|
164
167
|
#### 2.3 基础代码模板(必须遵循)
|
|
165
168
|
const descriptions = []
|
|
@@ -240,6 +243,34 @@ function executeSkill(skillFilePath, subGoalPrompt = '') {
|
|
|
240
243
|
return this.aiService.subSkillWorkflow(skillContent, subGoalPrompt)
|
|
241
244
|
}
|
|
242
245
|
|
|
246
|
+
// 了解自己
|
|
247
|
+
function getSelfInfo() {
|
|
248
|
+
// 返回自己的代码路径、package.json路径、readme路径等基本信息,供AI有选择的了解自己,回答用户的问题
|
|
249
|
+
const homeDir = path.resolve(__dirname, '../../../')
|
|
250
|
+
return {
|
|
251
|
+
codePath: {
|
|
252
|
+
description: 'DeepFish AI程序代码路径',
|
|
253
|
+
value: homeDir,
|
|
254
|
+
},
|
|
255
|
+
packageJsonPath: {
|
|
256
|
+
description: 'DeepFish AI程序package.json文件路径',
|
|
257
|
+
value: path.resolve(homeDir, 'package.json'),
|
|
258
|
+
},
|
|
259
|
+
readmeCNPath: {
|
|
260
|
+
description: 'DeepFish AI程序中文文档路径',
|
|
261
|
+
value: path.resolve(homeDir, 'README_CN.md'),
|
|
262
|
+
},
|
|
263
|
+
readmeENPath: {
|
|
264
|
+
description: 'DeepFish AI程序英文文档路径',
|
|
265
|
+
value: path.resolve(homeDir, 'README.md'),
|
|
266
|
+
},
|
|
267
|
+
version: {
|
|
268
|
+
description: 'DeepFish AI程序版本',
|
|
269
|
+
value: "v" + require(path.resolve(homeDir, 'package.json')).version,
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
243
274
|
const descriptions = [
|
|
244
275
|
{
|
|
245
276
|
type: 'function',
|
|
@@ -351,6 +382,19 @@ const descriptions = [
|
|
|
351
382
|
},
|
|
352
383
|
},
|
|
353
384
|
},
|
|
385
|
+
{
|
|
386
|
+
type: 'function',
|
|
387
|
+
function: {
|
|
388
|
+
name: 'getSelfInfo',
|
|
389
|
+
description:
|
|
390
|
+
'获取DeepFish AI程序的基本信息、命令行等,供AI有选择的了解自己,回答用户的问题。',
|
|
391
|
+
parameters: {
|
|
392
|
+
type: 'object',
|
|
393
|
+
properties: {},
|
|
394
|
+
required: [],
|
|
395
|
+
},
|
|
396
|
+
}
|
|
397
|
+
}
|
|
354
398
|
]
|
|
355
399
|
const functions = {
|
|
356
400
|
executeCommand,
|
|
@@ -360,6 +404,7 @@ const functions = {
|
|
|
360
404
|
getAiConfig,
|
|
361
405
|
getAiConfigPath,
|
|
362
406
|
executeSkill,
|
|
407
|
+
getSelfInfo,
|
|
363
408
|
}
|
|
364
409
|
|
|
365
410
|
module.exports = {
|