deepfish-ai 1.0.16 → 1.0.18
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 +26 -5
- package/README_CN.md +27 -5
- package/package.json +1 -1
- package/src/cli/HistoryManager.js +94 -18
- package/src/cli/SkillConfigManager.js +6 -3
- package/src/cli/ai-history.js +3 -1
- package/src/core/AICLI.js +13 -1
- package/src/core/ai-services/AiWorker/AIMessageManager.js +6 -5
- package/src/core/ai-services/AiWorker/AiAgent.js +14 -12
- package/src/core/ai-services/AiWorker/AiPrompt.js +71 -18
- package/src/core/ai-services/AiWorker/AiTools.js +127 -25
- package/src/core/ai-services/AiWorker/index.js +48 -5
- package/src/core/ai-services/index.js +4 -0
- package/src/core/extension/ExtensionManager.js +14 -10
- package/src/core/extension/FileExtension.js +157 -158
- package/src/core/extension/GenerateExtension.js +360 -0
- package/src/core/extension/InquirerExtension.js +32 -92
- package/src/core/extension/SystemExtension.js +10 -125
- package/src/core/extension/TaskExtension.js +169 -0
- package/src/core/extension/TestExtension.js +1 -1
- package/src/core/utils/log.js +13 -12
package/README.md
CHANGED
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
alt="WeChat"
|
|
11
11
|
src="https://img.shields.io/badge/WeChat-MrRoman_123-green.svg"
|
|
12
12
|
/>
|
|
13
|
-
<a href="https://github.com/qq306863030/deepfish">
|
|
13
|
+
<a href="https://github.com/qq306863030/deepfish-ai">
|
|
14
14
|
<img
|
|
15
15
|
alt="GitHub"
|
|
16
|
-
src="https://img.shields.io/badge/GitHub-DeepFish-blue.svg"
|
|
16
|
+
src="https://img.shields.io/badge/GitHub-DeepFish AI-blue.svg"
|
|
17
17
|
/></a>
|
|
18
|
-
<a href="https://www.npmjs.com/package/deepfish">
|
|
19
|
-
<img alt="NPM" src="https://img.shields.io/badge/NPM-DeepFish-blue.svg"
|
|
18
|
+
<a href="https://www.npmjs.com/package/deepfish-ai">
|
|
19
|
+
<img alt="NPM" src="https://img.shields.io/badge/NPM-DeepFish AI-blue.svg"
|
|
20
20
|
/></a>
|
|
21
21
|
<img
|
|
22
22
|
alt="Code License"
|
|
@@ -258,7 +258,18 @@ ai ext add weather.js
|
|
|
258
258
|
|
|
259
259
|
```bash
|
|
260
260
|
ai skill install https://clawhub.ai/TheSethRose/agent-browser
|
|
261
|
+
ai skill install https://clawhub.ai/steipete/weather
|
|
261
262
|
ai skill ls
|
|
263
|
+
ai skill enable 1
|
|
264
|
+
ai skill disable 0
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**OpenClaw Skill Generation:**
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
ai "Create a weather query skill"
|
|
271
|
+
ai skill add weather-query
|
|
272
|
+
ai skill enable weather-query
|
|
262
273
|
```
|
|
263
274
|
|
|
264
275
|
**Media Processing:**
|
|
@@ -273,6 +284,16 @@ ai "I have ffmpeg5 installed on my system, help me convert all MP4 files in the
|
|
|
273
284
|
ai "Classify all files under the 'model' directory into the 'model2' directory by month, date format YYYY-MM"
|
|
274
285
|
```
|
|
275
286
|
|
|
287
|
+
**Task List Execution:**
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
ai "Create a task list: 1.xxxx; 2.xxxx; ..."
|
|
291
|
+
ai "Execute task list" # Start execution
|
|
292
|
+
|
|
293
|
+
ai "I want to implement an extension tool for long-form novel writing that supports large-scale writing, maintains contextual logic coherence, and avoids AI context explosion issues. This extension tool may be a bit complex to implement. You need to carefully read the extension tool generation rules first, then create a task list"
|
|
294
|
+
ai "Execute task list" # Start execution
|
|
295
|
+
```
|
|
296
|
+
|
|
276
297
|
## 6. Extension Development
|
|
277
298
|
|
|
278
299
|
Extensions allow you to add custom functions that AI can use in its workflows. For complex processes, you can develop them yourself or try generating extensions using this program, then register the extension with the program and use the command line to complete tasks.
|
|
@@ -346,7 +367,7 @@ module.exports = {
|
|
|
346
367
|
Rules for automatic scanning of extension modules upon program startup:
|
|
347
368
|
|
|
348
369
|
1. Scanning locations:
|
|
349
|
-
- node_modules in the root directory
|
|
370
|
+
- node_modules in the npm root directory
|
|
350
371
|
- node_modules in the command execution directory
|
|
351
372
|
- the command execution directory itself
|
|
352
373
|
|
package/README_CN.md
CHANGED
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
alt="WeChat"
|
|
11
11
|
src="https://img.shields.io/badge/WeChat-MrRoman_123-green.svg"
|
|
12
12
|
/>
|
|
13
|
-
<a href="https://github.com/qq306863030/deepfish">
|
|
13
|
+
<a href="https://github.com/qq306863030/deepfish-ai">
|
|
14
14
|
<img
|
|
15
15
|
alt="GitHub"
|
|
16
|
-
src="https://img.shields.io/badge/GitHub-DeepFish-blue.svg"
|
|
16
|
+
src="https://img.shields.io/badge/GitHub-DeepFish AI-blue.svg"
|
|
17
17
|
/></a>
|
|
18
|
-
<a href="https://www.npmjs.com/package/deepfish">
|
|
19
|
-
<img alt="NPM" src="https://img.shields.io/badge/NPM-DeepFish-blue.svg"
|
|
18
|
+
<a href="https://www.npmjs.com/package/deepfish-ai">
|
|
19
|
+
<img alt="NPM" src="https://img.shields.io/badge/NPM-DeepFish AI-blue.svg"
|
|
20
20
|
/></a>
|
|
21
21
|
<img
|
|
22
22
|
alt="Code License"
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
- [AI服务选择](#ai服务选择)
|
|
56
56
|
- [8. 使用说明](#8-使用说明)
|
|
57
57
|
- [使用相对路径](#使用相对路径)
|
|
58
|
+
- [对话历史](#对话历史)
|
|
58
59
|
- [9. 故障排除](#9-故障排除)
|
|
59
60
|
- [配置问题](#配置问题)
|
|
60
61
|
- [AI服务连接](#ai服务连接)
|
|
@@ -255,7 +256,18 @@ ai ext add weather.js
|
|
|
255
256
|
|
|
256
257
|
```bash
|
|
257
258
|
ai skill install https://clawhub.ai/TheSethRose/agent-browser
|
|
259
|
+
ai skill install https://clawhub.ai/steipete/weather
|
|
258
260
|
ai skill ls
|
|
261
|
+
ai skill enable 1
|
|
262
|
+
ai skill disable 0
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**OpenClaw Skill 生成:**
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
ai "创建一个查询天气的skill"
|
|
269
|
+
ai skill add weather-query
|
|
270
|
+
ai skill enable weather-query
|
|
259
271
|
```
|
|
260
272
|
|
|
261
273
|
**媒体处理:**
|
|
@@ -270,6 +282,16 @@ ai "我的系统上安装了ffmpeg5,帮我将目录中的所有MP4文件转换
|
|
|
270
282
|
ai "将model目录下的所有文件按月份分类到model2目录中,日期格式为YYYY-MM"
|
|
271
283
|
```
|
|
272
284
|
|
|
285
|
+
**任务列表执行:**
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
ai "创建一个任务列表,1.xxxx;2.xxxx;..."
|
|
289
|
+
ai "执行任务列表" # 开始执行
|
|
290
|
+
|
|
291
|
+
ai "我要实现一个用于长篇小说创作的扩展工具,支持大篇幅写作,保持上下文逻辑连贯,避免AI上下文爆炸问题。这个扩展工具实现起来可能有点复杂,你需要先仔细阅读扩展工具生成规则,然后创建一个任务列表"
|
|
292
|
+
ai "执行任务列表" # 开始执行
|
|
293
|
+
```
|
|
294
|
+
|
|
273
295
|
## 6. 扩展开发
|
|
274
296
|
|
|
275
297
|
扩展允许您添加AI可以在其工作流中使用的自定义函数, 对于复杂的流程也可以自行开发或尝试使用本程序生成扩展,然后将扩展注册到程序中,在使用命令行来完成任务。
|
|
@@ -342,7 +364,7 @@ module.exports = {
|
|
|
342
364
|
|
|
343
365
|
程序启动时自动扫描扩展模块的规则:
|
|
344
366
|
1. 扫描位置:
|
|
345
|
-
- 根目录的node_modules
|
|
367
|
+
- npm根目录的node_modules
|
|
346
368
|
- 命令执行目录的node_modules
|
|
347
369
|
- 命令执行目录
|
|
348
370
|
2. 扫描文件:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deepfish-ai",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.18",
|
|
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": {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: Roman 306863030@qq.com
|
|
3
3
|
* @Date: 2026-03-16 09:18:05
|
|
4
4
|
* @LastEditors: Roman 306863030@qq.com
|
|
5
|
-
* @LastEditTime: 2026-03-
|
|
5
|
+
* @LastEditTime: 2026-03-26 15:19:36
|
|
6
6
|
* @FilePath: \deepfish\src\cli\HistoryManager.js
|
|
7
7
|
* @Description: 对话历史记录、恢复
|
|
8
8
|
* @
|
|
@@ -15,12 +15,16 @@ const { v4: uuidv4 } = require('uuid')
|
|
|
15
15
|
const { logSuccess, logError } = require('../core/utils/log')
|
|
16
16
|
const { openDirectory } = require('../core/utils/normal')
|
|
17
17
|
// cache => [history.json, id => [message.json, logs => [log.txt]]]
|
|
18
|
+
// messageType:1.主会话 2.子会话(每次开始前自动清空上下文) 3.子任务会话(任务开始前,自动加载会话历史,或加载主会话历史)
|
|
18
19
|
class HistoryManager {
|
|
19
20
|
constructor() {
|
|
20
21
|
this.configManager = GlobalVariable.configManager
|
|
21
22
|
this.cacheDir = null
|
|
22
23
|
this.historyFilePath = null
|
|
23
24
|
this.history = null
|
|
25
|
+
this.messagePath = null // 主会话历史记录
|
|
26
|
+
this.subMessagePath = null // 子会话历史记录
|
|
27
|
+
this.taskMessagePath = null // 任务会话历史记录
|
|
24
28
|
this.id = null
|
|
25
29
|
this.logDir = null
|
|
26
30
|
GlobalVariable.historyManager = this
|
|
@@ -55,15 +59,21 @@ class HistoryManager {
|
|
|
55
59
|
}
|
|
56
60
|
// 根据id创建目录,再创建一个message.json文件
|
|
57
61
|
const recordDir = path.join(this.cacheDir, id)
|
|
58
|
-
|
|
62
|
+
this.messagePath = path.join(recordDir, 'message.json')
|
|
63
|
+
this.subMessagePath = path.join(recordDir,'subMessage.json')
|
|
64
|
+
this.taskMessagePath = path.join(recordDir,'taskMessage.json')
|
|
59
65
|
fs.ensureDirSync(recordDir)
|
|
60
|
-
fs.writeJsonSync(
|
|
66
|
+
fs.writeJsonSync(this.messagePath, [], { spaces: 2 })
|
|
61
67
|
this.history.push(newHistoryItem)
|
|
62
68
|
this.updateHistory(this.history)
|
|
63
69
|
this.id = newHistoryItem.id
|
|
64
70
|
} else {
|
|
65
71
|
historyItem.execTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
|
|
66
72
|
this.id = historyItem.id
|
|
73
|
+
const recordDir = path.join(this.cacheDir, this.id)
|
|
74
|
+
this.messagePath = path.join(recordDir, 'message.json')
|
|
75
|
+
this.subMessagePath = path.join(recordDir,'subMessage.json')
|
|
76
|
+
this.taskMessagePath = path.join(recordDir,'taskMessage.json')
|
|
67
77
|
}
|
|
68
78
|
const logDir = path.join(this.cacheDir, this.id, 'logs')
|
|
69
79
|
fs.ensureDirSync(logDir)
|
|
@@ -125,25 +135,86 @@ class HistoryManager {
|
|
|
125
135
|
}
|
|
126
136
|
}
|
|
127
137
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (fs.existsSync(
|
|
131
|
-
fs.writeJsonSync(
|
|
138
|
+
// 清除主会话
|
|
139
|
+
clearMainMessage() {
|
|
140
|
+
if (fs.existsSync(this.messagePath)) {
|
|
141
|
+
fs.writeJsonSync(this.messagePath, [], { spaces: 2 })
|
|
132
142
|
logSuccess('History messages have been cleared.')
|
|
133
143
|
return
|
|
134
144
|
}
|
|
135
145
|
logError('No history messages found to clear.')
|
|
136
146
|
}
|
|
147
|
+
|
|
137
148
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (fs.
|
|
141
|
-
fs.writeJsonSync(
|
|
149
|
+
// 清除子会话
|
|
150
|
+
clearSubMessage() {
|
|
151
|
+
if (fs.existsSync(this.subMessagePath)) {
|
|
152
|
+
fs.writeJsonSync(this.subMessagePath, [], { spaces: 2 })
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// 清除任务会话
|
|
158
|
+
clearTaskMessage() {
|
|
159
|
+
if (fs.existsSync(this.taskMessagePath)) {
|
|
160
|
+
fs.writeJsonSync(this.taskMessagePath, [], { spaces: 2 })
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// 更新主会话
|
|
166
|
+
updateMainMessage(message) {
|
|
167
|
+
if (fs.pathExistsSync(this.messagePath)) {
|
|
168
|
+
fs.writeJsonSync(this.messagePath, message, { spaces: 2 })
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// 更新子会话
|
|
173
|
+
updateSubMessage(message) {
|
|
174
|
+
fs.writeJsonSync(this.subMessagePath, message, { spaces: 2 })
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 更新任务会话
|
|
178
|
+
updateTaskMessage(message) {
|
|
179
|
+
fs.writeJsonSync(this.taskMessagePath, message, { spaces: 2 })
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
clearMessage(messageType = 1) {
|
|
184
|
+
switch (messageType) {
|
|
185
|
+
case 1:
|
|
186
|
+
this.clearMainMessage()
|
|
187
|
+
break
|
|
188
|
+
case 2:
|
|
189
|
+
this.clearSubMessage()
|
|
190
|
+
break
|
|
191
|
+
case 3:
|
|
192
|
+
this.clearTaskMessage()
|
|
193
|
+
break
|
|
142
194
|
}
|
|
143
195
|
}
|
|
144
196
|
|
|
145
|
-
|
|
146
|
-
|
|
197
|
+
updateMessage(messageType = 1, message) {
|
|
198
|
+
switch (messageType) {
|
|
199
|
+
case 1:
|
|
200
|
+
this.updateMainMessage(message)
|
|
201
|
+
break
|
|
202
|
+
case 2:
|
|
203
|
+
this.updateSubMessage(message)
|
|
204
|
+
break
|
|
205
|
+
case 3:
|
|
206
|
+
this.updateTaskMessage(message)
|
|
207
|
+
break
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
getMessage(messageType = 1) {
|
|
212
|
+
let messageFile = this.messagePath
|
|
213
|
+
if (messageType === 2) {
|
|
214
|
+
messageFile = this.subMessagePath
|
|
215
|
+
} else if (messageType === 3) {
|
|
216
|
+
messageFile = this.taskMessagePath
|
|
217
|
+
}
|
|
147
218
|
if (!fs.pathExistsSync(messageFile)) {
|
|
148
219
|
return []
|
|
149
220
|
}
|
|
@@ -174,13 +245,14 @@ class HistoryManager {
|
|
|
174
245
|
fs.writeJsonSync(this.historyFilePath, this.history, { spaces: 2 })
|
|
175
246
|
}
|
|
176
247
|
|
|
177
|
-
|
|
248
|
+
|
|
249
|
+
record(messages, messageType = 1) {
|
|
178
250
|
try {
|
|
179
251
|
const config = this.configManager.getConfig()
|
|
180
252
|
if (config.maxHistoryExpireTime === 0) {
|
|
181
253
|
return false
|
|
182
254
|
}
|
|
183
|
-
this.updateMessage(messages)
|
|
255
|
+
this.updateMessage(messageType, messages)
|
|
184
256
|
return true
|
|
185
257
|
} catch (error) {
|
|
186
258
|
console.error('Failed to record:', error.message)
|
|
@@ -200,10 +272,14 @@ class HistoryManager {
|
|
|
200
272
|
)
|
|
201
273
|
try {
|
|
202
274
|
let logEntry = ''
|
|
203
|
-
if (
|
|
204
|
-
logEntry = `[${new Date().toISOString()}][
|
|
275
|
+
if (typeof message === 'string') {
|
|
276
|
+
logEntry = `[${new Date().toISOString()}][###############] ${message}\n`
|
|
205
277
|
} else {
|
|
206
|
-
|
|
278
|
+
if (isCompress) {
|
|
279
|
+
logEntry = `[${new Date().toISOString()}][***compress***] ${message.content}\n`
|
|
280
|
+
} else {
|
|
281
|
+
logEntry = `[${new Date().toISOString()}][${message.role}] ${message.content}\n`
|
|
282
|
+
}
|
|
207
283
|
}
|
|
208
284
|
fs.appendFileSync(logFile, logEntry)
|
|
209
285
|
return true
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: Roman 306863030@qq.com
|
|
3
3
|
* @Date: 2026-03-23 15:23:42
|
|
4
4
|
* @LastEditors: Roman 306863030@qq.com
|
|
5
|
-
* @LastEditTime: 2026-03-
|
|
5
|
+
* @LastEditTime: 2026-03-27 10:30:40
|
|
6
6
|
* @FilePath: \deepfish\src\cli\SkillConfigManager.js
|
|
7
7
|
* @Description: Skill configuration manager
|
|
8
8
|
*/
|
|
@@ -46,7 +46,7 @@ class SkillConfigManager {
|
|
|
46
46
|
preLoadSkills() {
|
|
47
47
|
const skills = this.configManager.config.skills.filter((skill) => skill.enable)
|
|
48
48
|
if (skills.length === 0) {
|
|
49
|
-
return ''
|
|
49
|
+
return '### 暂无可以使用的Skill'
|
|
50
50
|
}
|
|
51
51
|
const table = skills
|
|
52
52
|
.map((s) => `| ${s.name} | ${s.description} | ${s.location} | ${s.skillFilePath} |`)
|
|
@@ -268,7 +268,10 @@ ${table}
|
|
|
268
268
|
return
|
|
269
269
|
}
|
|
270
270
|
const { skill, index } = skillObj
|
|
271
|
-
|
|
271
|
+
let skillPath = skill.location
|
|
272
|
+
if (!skillPath) {
|
|
273
|
+
skillPath = path.join(this.skillDir, skill.skillDirName)
|
|
274
|
+
}
|
|
272
275
|
userConfig.skills = userConfig.skills.filter((_, i) => i !== index)
|
|
273
276
|
this.configManager.writeConfig(userConfig)
|
|
274
277
|
if (fs.existsSync(skillPath)) {
|
package/src/cli/ai-history.js
CHANGED
|
@@ -9,7 +9,9 @@ extCommand
|
|
|
9
9
|
.command("clear")
|
|
10
10
|
.description("Clear the history messages for the current directory")
|
|
11
11
|
.action(() => {
|
|
12
|
-
historyManager.clearMessage();
|
|
12
|
+
historyManager.clearMessage(1);
|
|
13
|
+
historyManager.clearMessage(2);
|
|
14
|
+
historyManager.clearMessage(3);
|
|
13
15
|
});
|
|
14
16
|
|
|
15
17
|
extCommand
|
package/src/core/AICLI.js
CHANGED
|
@@ -3,10 +3,22 @@ const readline = require('readline')
|
|
|
3
3
|
const { logError } = require('./utils/log')
|
|
4
4
|
const { GlobalVariable } = require('./globalVariable')
|
|
5
5
|
const AIService = require('./ai-services')
|
|
6
|
+
const ConfigManager = require('../cli/ConfigManager')
|
|
7
|
+
const SkillConfigManager = require('../cli/SkillConfigManager')
|
|
8
|
+
const HistoryManager = require('../cli/HistoryManager')
|
|
6
9
|
|
|
7
10
|
class AICLI {
|
|
8
11
|
constructor(config) {
|
|
9
|
-
|
|
12
|
+
if (!GlobalVariable.configManager) {
|
|
13
|
+
GlobalVariable.configManager = new ConfigManager()
|
|
14
|
+
}
|
|
15
|
+
if (!GlobalVariable.skillConfigManager) {
|
|
16
|
+
GlobalVariable.skillConfigManager = new SkillConfigManager()
|
|
17
|
+
}
|
|
18
|
+
if (!GlobalVariable.historyManager) {
|
|
19
|
+
GlobalVariable.historyManager = new HistoryManager()
|
|
20
|
+
}
|
|
21
|
+
this.config = config || GlobalVariable.configManager.getConfig()
|
|
10
22
|
this.aiConfig = GlobalVariable.configManager.getCurrentAiConfig()
|
|
11
23
|
this.skillConfigManager = GlobalVariable.skillConfigManager
|
|
12
24
|
this.historyManager = GlobalVariable.historyManager
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: Roman 306863030@qq.com
|
|
3
3
|
* @Date: 2026-03-16 09:18:05
|
|
4
4
|
* @LastEditors: Roman 306863030@qq.com
|
|
5
|
-
* @LastEditTime: 2026-03-
|
|
5
|
+
* @LastEditTime: 2026-03-26 10:17:59
|
|
6
6
|
* @FilePath: \deepfish\src\core\ai-services\AiWorker\AIMessageManager.js
|
|
7
7
|
* @Description: 上下文管理-添加、自动压缩
|
|
8
8
|
* @
|
|
@@ -15,11 +15,12 @@ class AIMessageManager {
|
|
|
15
15
|
aiClient
|
|
16
16
|
aiConfig
|
|
17
17
|
config
|
|
18
|
-
constructor(aiClient, config, aiConfig, messages) {
|
|
18
|
+
constructor(aiClient, config, aiConfig, messages, messageType = 1) {
|
|
19
19
|
this.aiClient = aiClient
|
|
20
20
|
this.aiConfig = aiConfig
|
|
21
21
|
this.config = config
|
|
22
22
|
this.messages = messages
|
|
23
|
+
this.messageType = messageType
|
|
23
24
|
}
|
|
24
25
|
reLinkMsgs(messages) {
|
|
25
26
|
this.messages = messages
|
|
@@ -27,7 +28,7 @@ class AIMessageManager {
|
|
|
27
28
|
// 添加消息
|
|
28
29
|
addMsg(message) {
|
|
29
30
|
this.messages.push(message)
|
|
30
|
-
GlobalVariable.historyManager.record(this.messages)
|
|
31
|
+
GlobalVariable.historyManager.record(this.messages, this.messageType)
|
|
31
32
|
GlobalVariable.historyManager.log(message)
|
|
32
33
|
}
|
|
33
34
|
// 添加tool
|
|
@@ -41,7 +42,7 @@ class AIMessageManager {
|
|
|
41
42
|
content: content,
|
|
42
43
|
}
|
|
43
44
|
this.messages.push(message)
|
|
44
|
-
GlobalVariable.historyManager.record(this.messages)
|
|
45
|
+
GlobalVariable.historyManager.record(this.messages, this.messageType)
|
|
45
46
|
GlobalVariable.historyManager.log(message)
|
|
46
47
|
}
|
|
47
48
|
/**
|
|
@@ -91,7 +92,7 @@ class AIMessageManager {
|
|
|
91
92
|
} else if (lastUserMessageIndex === messages.length - 1) {
|
|
92
93
|
newMessages.push(messages[lastUserMessageIndex])
|
|
93
94
|
}
|
|
94
|
-
GlobalVariable.historyManager.record(newMessages)
|
|
95
|
+
GlobalVariable.historyManager.record(newMessages, this.messageType)
|
|
95
96
|
} else if (messages.length === 2) {
|
|
96
97
|
const summary = await this._getSummary([messages[1]])
|
|
97
98
|
newMessages.push([messages[0], summary])
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @Author: Roman 306863030@qq.com
|
|
3
3
|
* @Date: 2026-03-16 09:18:05
|
|
4
|
-
* @LastEditors:
|
|
5
|
-
* @LastEditTime: 2026-03-26
|
|
4
|
+
* @LastEditors: Roman 306863030@qq.com
|
|
5
|
+
* @LastEditTime: 2026-03-26 19:32:11
|
|
6
6
|
* @FilePath: \deepfish\src\core\ai-services\AiWorker\AiAgent.js
|
|
7
7
|
* @Description: 工作流循环
|
|
8
8
|
* @
|
|
@@ -22,6 +22,7 @@ class AiAgent {
|
|
|
22
22
|
config,
|
|
23
23
|
aiConfig,
|
|
24
24
|
extensionTools = { descriptions: [], functions: {} },
|
|
25
|
+
messageType = 1
|
|
25
26
|
) {
|
|
26
27
|
this.aiClient = aiClient
|
|
27
28
|
this.config = config
|
|
@@ -29,7 +30,8 @@ class AiAgent {
|
|
|
29
30
|
this.maxIterations =
|
|
30
31
|
config.maxIterations === -1 ? Infinity : config.maxIterations
|
|
31
32
|
this.maxBlockFileSize = this.config.maxBlockFileSize || 20 // 默认20KB
|
|
32
|
-
this.aiMessageManager = new AIMessageManager(aiClient, config, aiConfig, [])
|
|
33
|
+
this.aiMessageManager = new AIMessageManager(aiClient, config, aiConfig, [], messageType)
|
|
34
|
+
this.messageType = messageType
|
|
33
35
|
this.extensionTools = extensionTools
|
|
34
36
|
this.name = config.name
|
|
35
37
|
}
|
|
@@ -60,12 +62,16 @@ class AiAgent {
|
|
|
60
62
|
loadingStop(`${this.name} have finished thinking.`)
|
|
61
63
|
loadingStop = null
|
|
62
64
|
}
|
|
63
|
-
logInfo(content)
|
|
64
65
|
// 检查是否是任务完成的总结响应(没有工具调用且有内容)
|
|
65
66
|
if (tool_calls) {
|
|
66
67
|
// 执行函数
|
|
68
|
+
logInfo(content)
|
|
67
69
|
await this.execTools(tool_calls)
|
|
68
70
|
} else {
|
|
71
|
+
if (this.messageType === 1) {
|
|
72
|
+
// 只有主任务输出最后总结
|
|
73
|
+
logInfo(content)
|
|
74
|
+
}
|
|
69
75
|
// 没有工具调用,结束
|
|
70
76
|
break
|
|
71
77
|
}
|
|
@@ -89,15 +95,12 @@ class AiAgent {
|
|
|
89
95
|
for (const toolCall of tool_calls) {
|
|
90
96
|
const { id, function: func } = toolCall
|
|
91
97
|
const { name, arguments: args } = func
|
|
92
|
-
|
|
98
|
+
const toolFunctions = this.extensionTools.functions
|
|
93
99
|
logInfo(`Calling tool ${toolCall.function.name}`)
|
|
94
|
-
if (
|
|
100
|
+
if (toolFunctions[name]) {
|
|
95
101
|
try {
|
|
96
102
|
const parsedArgs = typeof args === 'string' ? JSON.parse(args) : args
|
|
97
|
-
|
|
98
|
-
const fileInfo = await this.extensionTools.functions['getFileInfo'](
|
|
99
|
-
parsedArgs.filePath,
|
|
100
|
-
)
|
|
103
|
+
const fileInfo = await toolFunctions['getFileInfo'](parsedArgs.filePath)
|
|
101
104
|
if (fileInfo && fileInfo.isFile && fileInfo.size > this.maxBlockFileSize * 1024) {
|
|
102
105
|
this.aiMessageManager.addTool(id, {
|
|
103
106
|
error:
|
|
@@ -107,8 +110,7 @@ class AiAgent {
|
|
|
107
110
|
})
|
|
108
111
|
continue
|
|
109
112
|
}
|
|
110
|
-
|
|
111
|
-
let result = await toolFunction(...Object.values(parsedArgs))
|
|
113
|
+
let result = await toolFunctions[name](...Object.values(parsedArgs))
|
|
112
114
|
let toolContent = JSON.stringify(result)
|
|
113
115
|
if (name !== 'requestAI') {
|
|
114
116
|
const MAX_CONTENT_SIZE = this.maxBlockFileSize * 1024
|