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.
Files changed (65) hide show
  1. package/README.md +195 -344
  2. package/dist/generate-skill.md +104 -0
  3. package/dist/generate-tool.md +88 -0
  4. package/dist/index.js +26831 -0
  5. package/dist/serve/client/assets/index-DUHYC91l.js +1 -0
  6. package/dist/serve/client/assets/index-zcrdNLZs.css +1 -0
  7. package/dist/serve/client/index.html +14 -0
  8. package/dist/serve/pm2-server.js +24405 -0
  9. package/dist/serve/server/entry-server.mjs +224 -0
  10. package/dist/view-learn-cache.md +65 -0
  11. package/package.json +77 -83
  12. package/LICENSE +0 -21
  13. package/README_CN.md +0 -460
  14. package/src/AgentRobot/AgentRobotFactory/MainAgentRobot.js +0 -88
  15. package/src/AgentRobot/AgentRobotFactory/SubAgentRobot.js +0 -45
  16. package/src/AgentRobot/AgentRobotFactory/SubSkillAgentRobot.js +0 -45
  17. package/src/AgentRobot/AgentRobotFactory/index.js +0 -48
  18. package/src/AgentRobot/BaseAgentRobot/Brain.js +0 -210
  19. package/src/AgentRobot/BaseAgentRobot/BrainEvent.js +0 -17
  20. package/src/AgentRobot/BaseAgentRobot/Hand.js +0 -119
  21. package/src/AgentRobot/BaseAgentRobot/Heart.js +0 -0
  22. package/src/AgentRobot/BaseAgentRobot/Logger.js +0 -114
  23. package/src/AgentRobot/BaseAgentRobot/ScreenPrinter.js +0 -49
  24. package/src/AgentRobot/BaseAgentRobot/index.js +0 -266
  25. package/src/AgentRobot/BaseAgentRobot/lazy-tools/AliBailian.js +0 -997
  26. package/src/AgentRobot/BaseAgentRobot/lazy-tools/doc-transform.js +0 -204
  27. package/src/AgentRobot/BaseAgentRobot/lazy-tools/docx.js +0 -1286
  28. package/src/AgentRobot/BaseAgentRobot/lazy-tools/img.js +0 -765
  29. package/src/AgentRobot/BaseAgentRobot/lazy-tools/pdf.js +0 -736
  30. package/src/AgentRobot/BaseAgentRobot/lazy-tools/pptx.js +0 -567
  31. package/src/AgentRobot/BaseAgentRobot/lazy-tools/video.js +0 -36
  32. package/src/AgentRobot/BaseAgentRobot/lazy-tools/xlsx.js +0 -611
  33. package/src/AgentRobot/BaseAgentRobot/tools/BaseTools.js +0 -13
  34. package/src/AgentRobot/BaseAgentRobot/tools/CreateAgentTools.js +0 -158
  35. package/src/AgentRobot/BaseAgentRobot/tools/FileTools.js +0 -768
  36. package/src/AgentRobot/BaseAgentRobot/tools/GenerateTools.js +0 -441
  37. package/src/AgentRobot/BaseAgentRobot/tools/InquirerTools.js +0 -244
  38. package/src/AgentRobot/BaseAgentRobot/tools/SystemTools.js +0 -424
  39. package/src/AgentRobot/BaseAgentRobot/tools/TaskTools.js +0 -211
  40. package/src/AgentRobot/BaseAgentRobot/tools/TestTools.js +0 -100
  41. package/src/AgentRobot/BaseAgentRobot/tools/UserTool.js +0 -87
  42. package/src/AgentRobot/BaseAgentRobot/tools/WebTools.js +0 -257
  43. package/src/AgentRobot/BaseAgentRobot/utils/AIRequest.js +0 -297
  44. package/src/AgentRobot/BaseAgentRobot/utils/AIToolManager.js +0 -131
  45. package/src/AgentRobot/BaseAgentRobot/utils/AgentTree.js +0 -66
  46. package/src/AgentRobot/BaseAgentRobot/utils/AttachmentToolScanner.js +0 -235
  47. package/src/AgentRobot/BaseAgentRobot/utils/MessageCompresser.js +0 -236
  48. package/src/AgentRobot/BaseAgentRobot/utils/aiConsole.js +0 -74
  49. package/src/AgentRobot/BaseAgentRobot/utils/aiInquirer.js +0 -78
  50. package/src/AgentRobot/BaseAgentRobot/utils/analyzeReturn.test.js +0 -104
  51. package/src/AgentRobot/BaseAgentRobot/utils/copilot.js +0 -117
  52. package/src/AgentRobot/BaseAgentRobot/utils/node-root.js +0 -138
  53. package/src/AgentRobot/BaseAgentRobot/utils/normal.js +0 -399
  54. package/src/cli/ConfigManager.js +0 -283
  55. package/src/cli/DefaultConfig.js +0 -98
  56. package/src/cli/GlobalVariable.js +0 -8
  57. package/src/cli/MemoryManager.js +0 -53
  58. package/src/cli/SkillConfigManager.js +0 -354
  59. package/src/cli/SkillParser.js +0 -58
  60. package/src/cli/ai-auth.js +0 -231
  61. package/src/cli/ai-config.js +0 -225
  62. package/src/cli/ai-memory.js +0 -22
  63. package/src/cli/ai-skill.js +0 -65
  64. package/src/cli/index.js +0 -77
  65. package/src/index.js +0 -54
@@ -1,399 +0,0 @@
1
- const path = require('path')
2
- const fs = require('fs-extra')
3
- const chardet = require('chardet')
4
- const os = require('os')
5
- const { spawn } = require('child_process')
6
-
7
- // 对象字符串转对象
8
- function objStrToObj(str) {
9
- try {
10
- if (typeof str === 'string') {
11
- return eval(`(${str})`)
12
- } else {
13
- return str
14
- }
15
- } catch (error) {
16
- throw new Error(`对象转换失败:${error.message}`)
17
- }
18
- }
19
-
20
- function delay(ms) {
21
- return new Promise((resolve) => setTimeout(resolve, ms))
22
- }
23
-
24
- // 遍历目录和子目录下所有文件
25
- function traverseFiles() {
26
- try {
27
- const currentDir = process.cwd()
28
- const allFiles = []
29
- const currentItems = fs.readdirSync(currentDir, { withFileTypes: true })
30
- for (const item of currentItems) {
31
- const itemPath = path.join(currentDir, item.name)
32
- if (item.isFile()) {
33
- allFiles.push(itemPath)
34
- continue
35
- }
36
- if (item.isDirectory()) {
37
- try {
38
- const subItems = fs.readdirSync(itemPath, { withFileTypes: true })
39
- for (const subItem of subItems) {
40
- if (subItem.isFile()) {
41
- allFiles.push(path.join(itemPath, subItem.name))
42
- }
43
- }
44
- } catch (subErr) {
45
- console.warn(`读取子目录失败 ${itemPath}:${subErr.message}`)
46
- }
47
- }
48
- }
49
- return allFiles
50
- } catch (err) {
51
- console.error(`遍历目录失败:${err.message}`)
52
- return []
53
- }
54
- }
55
-
56
- // 打开目录
57
- function openDirectory(dirPath) {
58
- // 打开目录
59
- const platform = process.platform
60
- let command
61
- let args
62
- const dir = dirPath
63
- if (platform === 'darwin') {
64
- command = 'open'
65
- args = [dir]
66
- } else if (platform === 'win32') {
67
- command = 'explorer.exe'
68
- args = [dir]
69
- } else {
70
- command = 'xdg-open'
71
- args = [dir]
72
- }
73
- const child = spawn(command, args, {
74
- detached: true,
75
- stdio: 'ignore',
76
- })
77
- child.on('error', (error) => {
78
- console.error(`Error opening directory "${dirPath}": ${error.message}`)
79
- })
80
- child.unref()
81
- }
82
-
83
- // 判断编码类型
84
- function detectEncoding(buffer) {
85
- if (!buffer) {
86
- const platform = os.platform()
87
- return platform === 'win32' ? 'gbk' : 'utf-8'
88
- }
89
- const encoding = chardet.detect(buffer)
90
- if (encoding?.toLowerCase() === 'utf-8') {
91
- return 'utf-8'
92
- } else if (['gbk', 'gb2312', 'gb18030'].includes(encoding?.toLowerCase())) {
93
- return 'gbk'
94
- } else {
95
- const platform = os.platform()
96
- return platform === 'win32' ? 'gbk' : 'utf-8'
97
- }
98
- }
99
-
100
- function sleep(ms) {
101
- return new Promise((resolve) => setTimeout(resolve, ms))
102
- }
103
-
104
- // 判断代码是否有返回值
105
- function analyzeReturn(code) {
106
- if (typeof code !== 'string' || !code.trim()) {
107
- return {
108
- hasReturn: false,
109
- hasReturnValue: false,
110
- }
111
- }
112
-
113
- // 移除字符串和注释,避免把文本中的 return 误判为代码关键字。
114
- function stripStringsAndComments(input) {
115
- const chars = input.split('')
116
- let i = 0
117
- let state = 'normal'
118
-
119
- while (i < chars.length) {
120
- const ch = chars[i]
121
- const next = chars[i + 1]
122
-
123
- if (state === 'normal') {
124
- if (ch === '/' && next === '/') {
125
- state = 'line-comment'
126
- chars[i] = ' '
127
- chars[i + 1] = ' '
128
- i += 2
129
- continue
130
- }
131
- if (ch === '/' && next === '*') {
132
- state = 'block-comment'
133
- chars[i] = ' '
134
- chars[i + 1] = ' '
135
- i += 2
136
- continue
137
- }
138
- if (ch === "'") {
139
- state = 'single-quote'
140
- chars[i] = ' '
141
- i += 1
142
- continue
143
- }
144
- if (ch === '"') {
145
- state = 'double-quote'
146
- chars[i] = ' '
147
- i += 1
148
- continue
149
- }
150
- if (ch === '`') {
151
- state = 'template'
152
- chars[i] = ' '
153
- i += 1
154
- continue
155
- }
156
- i += 1
157
- continue
158
- }
159
-
160
- if (state === 'line-comment') {
161
- if (ch === '\n') {
162
- state = 'normal'
163
- } else {
164
- chars[i] = ' '
165
- }
166
- i += 1
167
- continue
168
- }
169
-
170
- if (state === 'block-comment') {
171
- if (ch === '*' && next === '/') {
172
- chars[i] = ' '
173
- chars[i + 1] = ' '
174
- state = 'normal'
175
- i += 2
176
- } else {
177
- if (ch !== '\n') {
178
- chars[i] = ' '
179
- }
180
- i += 1
181
- }
182
- continue
183
- }
184
-
185
- if (state === 'single-quote') {
186
- if (ch === '\\') {
187
- chars[i] = ' '
188
- if (i + 1 < chars.length) {
189
- chars[i + 1] = ' '
190
- }
191
- i += 2
192
- continue
193
- }
194
- chars[i] = ch === '\n' ? '\n' : ' '
195
- if (ch === "'") {
196
- state = 'normal'
197
- }
198
- i += 1
199
- continue
200
- }
201
-
202
- if (state === 'double-quote') {
203
- if (ch === '\\') {
204
- chars[i] = ' '
205
- if (i + 1 < chars.length) {
206
- chars[i + 1] = ' '
207
- }
208
- i += 2
209
- continue
210
- }
211
- chars[i] = ch === '\n' ? '\n' : ' '
212
- if (ch === '"') {
213
- state = 'normal'
214
- }
215
- i += 1
216
- continue
217
- }
218
-
219
- if (state === 'template') {
220
- if (ch === '\\') {
221
- chars[i] = ' '
222
- if (i + 1 < chars.length) {
223
- chars[i + 1] = ' '
224
- }
225
- i += 2
226
- continue
227
- }
228
- chars[i] = ch === '\n' ? '\n' : ' '
229
- if (ch === '`') {
230
- state = 'normal'
231
- }
232
- i += 1
233
- }
234
- }
235
-
236
- return chars.join('')
237
- }
238
-
239
- function isReturnWithValue(input, startIndex) {
240
- let i = startIndex
241
- while (i < input.length) {
242
- const ch = input[i]
243
- const next = input[i + 1]
244
- if (ch === ' ' || ch === '\t' || ch === '\r') {
245
- i += 1
246
- continue
247
- }
248
-
249
- if (ch === '/' && next === '/') {
250
- i += 2
251
- while (i < input.length && input[i] !== '\n') {
252
- i += 1
253
- }
254
- continue
255
- }
256
-
257
- if (ch === '/' && next === '*') {
258
- i += 2
259
- while (i < input.length) {
260
- if (input[i] === '*' && input[i + 1] === '/') {
261
- i += 2
262
- break
263
- }
264
- i += 1
265
- }
266
- continue
267
- }
268
-
269
- if (ch === '\n' || ch === ';' || ch === '}' || ch === ')') {
270
- return false
271
- }
272
- return true
273
- }
274
- return false
275
- }
276
-
277
- function isControlKeyword(token) {
278
- return ['if', 'for', 'while', 'switch', 'catch', 'with'].includes(token)
279
- }
280
-
281
- const cleaned = stripStringsAndComments(code)
282
- const tokenRegex = /[A-Za-z_$][\w$]*|=>|[{}()\[\]]/g
283
- const blockStack = []
284
- const parenStack = []
285
- let functionDepth = 0
286
- let pendingFunctionBlock = 0
287
- let pendingArrow = false
288
- let hasReturn = false
289
- let hasReturnValue = false
290
- let lastToken = ''
291
- let recentClosedParen = null
292
- let match
293
-
294
- while ((match = tokenRegex.exec(cleaned)) !== null) {
295
- const token = match[0]
296
- const index = match.index
297
-
298
- if (token === '(') {
299
- parenStack.push({
300
- beforeToken: lastToken,
301
- })
302
- lastToken = token
303
- continue
304
- }
305
-
306
- if (token === ')') {
307
- recentClosedParen = parenStack.pop() || null
308
- lastToken = token
309
- continue
310
- }
311
-
312
- if (token === 'function') {
313
- pendingFunctionBlock += 1
314
- pendingArrow = false
315
- lastToken = token
316
- recentClosedParen = null
317
- continue
318
- }
319
-
320
- if (token === '=>') {
321
- pendingArrow = true
322
- lastToken = token
323
- recentClosedParen = null
324
- continue
325
- }
326
-
327
- if (token === '{') {
328
- let isFunctionBlock = false
329
- if (pendingFunctionBlock > 0 || pendingArrow) {
330
- isFunctionBlock = true
331
- } else if (lastToken === ')' && recentClosedParen) {
332
- const beforeToken = recentClosedParen.beforeToken
333
- if (beforeToken && !isControlKeyword(beforeToken)) {
334
- // 识别 class/object method 这类无 function 关键字的方法体。
335
- isFunctionBlock = true
336
- }
337
- }
338
-
339
- if (isFunctionBlock) {
340
- blockStack.push('function')
341
- functionDepth += 1
342
- if (pendingFunctionBlock > 0) {
343
- pendingFunctionBlock -= 1
344
- }
345
- } else {
346
- blockStack.push('block')
347
- }
348
-
349
- pendingArrow = false
350
- lastToken = token
351
- recentClosedParen = null
352
- continue
353
- }
354
-
355
- if (token === '}') {
356
- const top = blockStack.pop()
357
- if (top === 'function' && functionDepth > 0) {
358
- functionDepth -= 1
359
- }
360
- pendingArrow = false
361
- lastToken = token
362
- recentClosedParen = null
363
- continue
364
- }
365
-
366
- if (token === 'return' && functionDepth === 0) {
367
- hasReturn = true
368
- if (isReturnWithValue(code, index + token.length)) {
369
- hasReturnValue = true
370
- }
371
- if (hasReturn && hasReturnValue) {
372
- break
373
- }
374
- }
375
-
376
- if (pendingArrow) {
377
- // 箭头函数表达式体不带 {} 时,不会有 return 关键字参与判断。
378
- pendingArrow = false
379
- }
380
-
381
- lastToken = token
382
- recentClosedParen = null
383
- }
384
-
385
- return {
386
- hasReturn,
387
- hasReturnValue,
388
- }
389
- }
390
-
391
- module.exports = {
392
- objStrToObj,
393
- delay,
394
- traverseFiles,
395
- openDirectory,
396
- detectEncoding,
397
- sleep,
398
- analyzeReturn,
399
- }
@@ -1,283 +0,0 @@
1
- const path = require('path')
2
- const os = require('os')
3
- const fs = require('fs-extra')
4
- const { exec } = require('child_process')
5
- const lodash = require('lodash')
6
- const { defaultConfig } = require('./DefaultConfig.js')
7
- const { GlobalVariable } = require('./GlobalVariable.js')
8
- const { openDirectory } = require('../AgentRobot/BaseAgentRobot/utils/normal.js')
9
- const aiConsole = require('../AgentRobot/BaseAgentRobot/utils/aiConsole.js')
10
-
11
- class ConfigManager {
12
- config = null
13
- configDir = path.join(os.homedir(), './.deepfish-ai')
14
- configPath = path.join(this.configDir, './config.js')
15
- constructor() {
16
- this.initConfig()
17
- GlobalVariable.configManager = this
18
- }
19
- // 初始化config
20
- initConfig() {
21
- fs.ensureDirSync(this.configDir)
22
- // 判断之前版本的配置文件是否存在,如果存在则迁移到新目录
23
- const isConfigExists = this.checkConfigExists()
24
- if (
25
- !isConfigExists &&
26
- fs.pathExistsSync(path.join(os.homedir(), '.ai-cmd.config.js'))
27
- ) {
28
- fs.moveSync(path.join(os.homedir(), '.ai-cmd.config.js'), this.configPath)
29
- } else if (!isConfigExists) {
30
- this.writeConfig()
31
- }
32
- this.config = this.getConfig()
33
- this.writeConfig(this.config)
34
- }
35
-
36
- dir() {
37
- openDirectory(this.configDir)
38
- }
39
-
40
- edit() {
41
- const platform = process.platform
42
-
43
- let openCommand
44
- if (process.env.EDITOR) {
45
- openCommand = `${process.env.EDITOR} "${this.configPath}"`
46
- } else if (platform === 'darwin') {
47
- openCommand = `open -e "${this.configPath}"`
48
- } else if (platform === 'win32') {
49
- openCommand = `notepad "${this.configPath}"`
50
- } else {
51
- openCommand = `xdg-open "${this.configPath}"`
52
- }
53
- exec(openCommand, (error) => {
54
- if (error) {
55
- aiConsole.logError('Error opening configuration file:', error.message)
56
- }
57
- })
58
- }
59
-
60
- // 判断config是否存在
61
- checkConfigExists() {
62
- return fs.pathExistsSync(this.configPath)
63
- }
64
-
65
- // 重名验证
66
- checkName(aiName) {
67
- const existingIndex = this.config.ai.findIndex(
68
- (item) => item.name === aiName,
69
- )
70
- return existingIndex !== -1
71
- }
72
-
73
- isAiListEmpty() {
74
- return this.config.ai && this.config.ai.length === 0
75
- }
76
-
77
- // 添加一个aiConfig
78
- addAiConfig(aiConfig) {
79
- this.config.ai.push(aiConfig)
80
- this.writeConfig(this.config)
81
- aiConsole.logSuccess(`AI configuration "${aiConfig.name}" added successfully!`)
82
- return aiConfig
83
- }
84
-
85
- // 删除一个aiConfig
86
- delAiConfig(aiName) {
87
- const existingIndex = this.config.ai.findIndex(
88
- (item) => item.name === aiName,
89
- )
90
- if (existingIndex === -1) {
91
- aiConsole.logError(`Configuration with name "${aiName}" not found.`)
92
- return
93
- }
94
- const currentAi = this.config.currentAi
95
- // Check if it's the current configuration
96
- if (currentAi === aiName) {
97
- aiConsole.logError(`Cannot delete current configuration "${aiName}".`)
98
- return
99
- }
100
- // Remove the configuration
101
- this.config.ai.splice(existingIndex, 1)
102
- this.writeConfig(this.config)
103
- aiConsole.logSuccess(`AI configuration "${aiName}" deleted successfully!`)
104
- }
105
-
106
- // 设置当前Ai
107
- setCurrentAi(aiName) {
108
- // 查看列表中是否存在
109
- const existingIndex = this.config.ai.findIndex(
110
- (item) => item.name === aiName,
111
- )
112
- if (existingIndex === -1) {
113
- aiConsole.logError(`Configuration with name "${aiName}" not found.`)
114
- return
115
- }
116
- this.config.currentAi = aiName
117
- this.writeConfig(this.config)
118
- aiConsole.logSuccess(`Current AI configuration set to "${aiName}" successfully!`)
119
- }
120
-
121
- getCurrentAiConfig() {
122
- return this.config.ai.find((item) => item.name === this.config.currentAi)
123
- }
124
-
125
- getCurrentAi() {
126
- return this.config.currentAi
127
- }
128
-
129
- _getAiConfig(aiName) {
130
- return this.config.ai.find((item) => item.name === aiName)
131
- }
132
-
133
- getAiConfig(aiName) {
134
- return this._getAiConfig(aiName)
135
- }
136
-
137
- updateAiConfigByName(aiName, updater) {
138
- const existingIndex = this.config.ai.findIndex(
139
- (item) => item.name === aiName,
140
- )
141
- if (existingIndex === -1) {
142
- aiConsole.logError(`Configuration with name "${aiName}" not found.`)
143
- return null
144
- }
145
-
146
- const current = this.config.ai[existingIndex]
147
- const next = typeof updater === 'function'
148
- ? updater(lodash.cloneDeep(current))
149
- : lodash.merge(lodash.cloneDeep(current), updater)
150
-
151
- this.config.ai[existingIndex] = next
152
- this.writeConfig(this.config)
153
- return next
154
- }
155
-
156
- // 获取Ai列表
157
- getAiList() {
158
- console.log('AI Configurations')
159
- console.log('='.repeat(50))
160
- if (this.config.ai && Array.isArray(this.config.ai)) {
161
- if (this.config.ai.length === 0) {
162
- aiConsole.logError('No AI configurations found.')
163
- } else {
164
- this.config.ai.forEach((config, index) => {
165
- const isCurrent = this.config.currentAi === config.name
166
- aiConsole.logInfo(`${config.name} ${isCurrent ? '(current)' : ''}`)
167
- })
168
- }
169
- } else {
170
- aiConsole.logError('No AI configurations found.')
171
- }
172
- console.log('='.repeat(50))
173
- }
174
-
175
- // 重置config
176
- resetConfig() {
177
- console.log('Resetting configuration file:', this.configPath)
178
- this.writeConfig()
179
- this.config = this.getConfig()
180
- aiConsole.logSuccess('Configuration file has been reset to default settings.')
181
- }
182
-
183
- // 查看ai详情
184
- viewAiConfigDetail(aiName) {
185
- if (this.isAiListEmpty()) {
186
- aiConsole.logError(
187
- 'No AI configurations found. Please add an AI configuration first.',
188
- )
189
- return
190
- }
191
- if (!aiName) {
192
- aiName = this.config.currentAi
193
- if (!aiName) {
194
- aiConsole.logError(
195
- 'No current AI configuration set. Please input "ai config use <name>" to set a current configuration.',
196
- )
197
- return
198
- }
199
- }
200
- const aiConfig = this._getAiConfig(aiName)
201
- if (!aiConfig) {
202
- aiConsole.logError(
203
- 'AI configuration not found. Please check the name and try again.',
204
- )
205
- return
206
- }
207
- aiConsole.logSuccess('AI Configuration Details')
208
- aiConsole.logSuccess('='.repeat(50))
209
- aiConsole.logInfo(`Name: ${aiConfig.name}`)
210
- aiConsole.logInfo(`Type: ${aiConfig.type}`)
211
- aiConsole.logInfo(`API Base URL: ${aiConfig.baseUrl}`)
212
- aiConsole.logInfo(`Model: ${aiConfig.model}`)
213
- if (aiConfig.apiKey) {
214
- const maskPrefix = String(aiConfig.apiKey).slice(0, 6)
215
- aiConsole.logInfo(`API Key: ${maskPrefix}... (masked)`)
216
- }
217
- aiConsole.logInfo(`Temperature: ${aiConfig.temperature}`)
218
- aiConsole.logInfo(`Max Tokens: ${aiConfig.maxTokens}`)
219
- aiConsole.logInfo(`Streaming Output: ${aiConfig.stream ? 'Enabled' : 'Disabled'}`)
220
- aiConsole.logInfo(
221
- `Is Current: ${this.config.currentAi === aiConfig.name ? 'Yes' : 'No'}`,
222
- )
223
- aiConsole.logInfo(`File Path: ${this.configPath}`)
224
- aiConsole.logSuccess('='.repeat(50))
225
- }
226
-
227
- // 更新扩展
228
- updateExtensions(extensions) {
229
- this.config.extensions = extensions
230
- this.writeConfig(this.config)
231
- aiConsole.logSuccess('Extensions updated successfully!')
232
- }
233
-
234
- // 删除扩展
235
- removeExtensionByIndex(extIndex) {
236
- const filePath = this.config.extensions.splice(extIndex, 1)
237
- this.writeConfig(this.config)
238
- aiConsole.logSuccess(
239
- `Extension removed from config: ${filePath}.You can run 'ai ext ls' to view the changes.`,
240
- )
241
- }
242
-
243
- removeExtensionByPath(filePath) {
244
- this.config.extensions = this.config.extensions.filter(
245
- (ext) => ext !== filePath,
246
- )
247
- this.writeConfig(this.config)
248
- aiConsole.logSuccess(
249
- `Extension removed from config: ${filePath}.You can run 'ai ext ls' to view the changes.`,
250
- )
251
- }
252
-
253
- getConfig() {
254
- const config = require(this.configPath)
255
- return lodash.merge(lodash.cloneDeep(defaultConfig), config)
256
- }
257
-
258
- getAppConfig() {
259
- const config = require(this.configPath)
260
- const mergedConfig = lodash.merge(lodash.cloneDeep(defaultConfig), config)
261
- if (mergedConfig.currentAi) {
262
- const aiConfig = mergedConfig.ai.find(
263
- (item) => item.name === mergedConfig.currentAi,
264
- )
265
- mergedConfig.aiConfig = aiConfig
266
- }
267
- return mergedConfig
268
- }
269
-
270
- // 写入配置
271
- writeConfig(config) {
272
- if (!config) {
273
- config = lodash.cloneDeep(defaultConfig)
274
- }
275
- fs.writeFileSync(
276
- this.configPath,
277
- `module.exports = ${JSON.stringify(config, null, 2)}`,
278
- )
279
- this.config = config
280
- }
281
- }
282
-
283
- module.exports = ConfigManager