deepfish-ai 1.0.13 → 1.0.15

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.
@@ -1,3 +1,9 @@
1
+ const path = require('path')
2
+ const fs = require('fs-extra')
3
+ const chardet = require('chardet')
4
+ const os = require('os') // 用于判断系统类型
5
+ const { logError } = require('./log')
6
+
1
7
  // 对象字符串转对象
2
8
  function objStrToObj(str) {
3
9
  try {
@@ -15,7 +21,87 @@ function delay(ms) {
15
21
  return new Promise((resolve) => setTimeout(resolve, ms))
16
22
  }
17
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 { spawn } = require('child_process')
60
+ const platform = process.platform
61
+ let command
62
+ let args
63
+ const dir = dirPath
64
+ if (platform === 'darwin') {
65
+ command = 'open'
66
+ args = [dir]
67
+ } else if (platform === 'win32') {
68
+ command = 'explorer.exe'
69
+ args = [dir]
70
+ } else {
71
+ command = 'xdg-open'
72
+ args = [dir]
73
+ }
74
+ const child = spawn(command, args, {
75
+ detached: true,
76
+ stdio: 'ignore',
77
+ })
78
+ child.on('error', (error) => {
79
+ logError(`Error opening directory "${dirPath}": ${error.message}`)
80
+ })
81
+ child.unref()
82
+ }
83
+
84
+ // 判断编码类型
85
+ function detectEncoding(buffer) {
86
+ if (!buffer) {
87
+ const platform = os.platform()
88
+ return platform === 'win32' ? 'gbk' : 'utf-8'
89
+ }
90
+ const encoding = chardet.detect(buffer)
91
+ if (encoding?.toLowerCase() === 'utf-8') {
92
+ return 'utf-8'
93
+ } else if (['gbk', 'gb2312', 'gb18030'].includes(encoding?.toLowerCase())) {
94
+ return 'gbk'
95
+ } else {
96
+ const platform = os.platform()
97
+ return platform === 'win32' ? 'gbk' : 'utf-8'
98
+ }
99
+ }
100
+
18
101
  module.exports = {
19
102
  objStrToObj,
20
103
  delay,
104
+ traverseFiles,
105
+ openDirectory,
106
+ detectEncoding,
21
107
  }
@@ -1,90 +0,0 @@
1
- const path = require("path");
2
- const fs = require("fs-extra");
3
-
4
- const defaultConfig = {
5
- ai: [],
6
- currentAi: "",
7
- maxIterations: -1, // ai完成工作流的最大迭代次数
8
- maxMessagesLength: 50000, // 最大压缩长度
9
- maxMessagesCount: 40, // 最大压缩数量
10
- extensions: [],
11
- isRecordHistory: false, // 是否创建工作流执行记录文件,用于因意外终止恢复工作流
12
- isLog: false, // 是否创建工作流执行日志
13
- };
14
-
15
- const aiCliConfig = {
16
- DeepSeek: {
17
- baseUrl: "https://api.deepseek.com",
18
- model: {
19
- list: ["deepseek-chat", "deepseek-reasoner", "other"],
20
- defaultValue: "",
21
- },
22
- type: 'deepseek',
23
- apiKey: "",
24
- temperature: 0.7,
25
- maxTokens: 8192,
26
- stream: true,
27
- },
28
- Ollama: {
29
- baseUrl: "http://localhost:11434/v1",
30
- model: {
31
- list: [],
32
- defaultValue: "deepseek-v3.2:cloud",
33
- },
34
- type: 'ollama',
35
- apiKey: "ollama",
36
- temperature: 0.7,
37
- maxTokens: 8192,
38
- stream: true,
39
- },
40
- OpenAI: {
41
- baseUrl: "https://api.openai.com/v1",
42
- model: {
43
- list: [],
44
- defaultValue: "gpt-4",
45
- },
46
- type: "openai",
47
- apiKey: "",
48
- temperature: 0.7,
49
- maxTokens: 8192,
50
- stream: true,
51
- },
52
- };
53
-
54
- // 遍历目录和子目录下所有文件
55
- function traverseFiles() {
56
- try {
57
- const currentDir = process.cwd();
58
- const allFiles = [];
59
- const currentItems = fs.readdirSync(currentDir, { withFileTypes: true });
60
- for (const item of currentItems) {
61
- const itemPath = path.join(currentDir, item.name);
62
- if (item.isFile()) {
63
- allFiles.push(itemPath);
64
- continue;
65
- }
66
- if (item.isDirectory()) {
67
- try {
68
- const subItems = fs.readdirSync(itemPath, { withFileTypes: true });
69
- for (const subItem of subItems) {
70
- if (subItem.isFile()) {
71
- allFiles.push(path.join(itemPath, subItem.name));
72
- }
73
- }
74
- } catch (subErr) {
75
- console.warn(`读取子目录失败 ${itemPath}:${subErr.message}`);
76
- }
77
- }
78
- }
79
- return allFiles;
80
- } catch (err) {
81
- console.error(`遍历目录失败:${err.message}`);
82
- return [];
83
- }
84
- }
85
-
86
- module.exports = {
87
- aiCliConfig,
88
- defaultConfig,
89
- traverseFiles
90
- };
@@ -1,119 +0,0 @@
1
- /**
2
- * @Author: Roman 306863030@qq.com
3
- * @Date: 2026-03-16 09:18:05
4
- * @LastEditors: Roman 306863030@qq.com
5
- * @LastEditTime: 2026-03-17 10:01:45
6
- * @FilePath: \src\core\ai-services\AiWorker\AiRecorder.js
7
- * @Description: 对话历史记录、恢复
8
- * @
9
- */
10
- const fs = require("fs-extra");
11
- const path = require("path");
12
- const inquirer = require("inquirer");
13
- const dayjs = require("dayjs");
14
- const { GlobalVariable } = require("../../globalVariable");
15
-
16
- class AiRecorder {
17
- constructor(aiCli) {
18
- this.aiCli = aiCli;
19
- }
20
-
21
- record(messages) {
22
- if (!GlobalVariable.isRecordHistory) {
23
- return false;
24
- }
25
- const recordDir = path.join(process.cwd(), "ai-history");
26
- const recordFile = path.join(recordDir, "history.json");
27
-
28
- try {
29
- fs.ensureDirSync(recordDir);
30
- const recordData = {
31
- timestamp: dayjs().format("YYYY-MM-DD HH:mm:ss"),
32
- messages: messages,
33
- };
34
-
35
- fs.writeJSONSync(recordFile, recordData, { spaces: 2 });
36
- return true;
37
- } catch (error) {
38
- console.error("Failed to record:", error.message);
39
- return false;
40
- }
41
- }
42
-
43
- async recover() {
44
- if (!GlobalVariable.isRecordHistory) {
45
- return null;
46
- }
47
- const recordDir = path.join(process.cwd(), "ai-history");
48
- const recordFile = path.join(recordDir, "history.json");
49
-
50
- try {
51
- const exists = fs.pathExistsSync(recordFile);
52
- if (!exists) {
53
- return null;
54
- }
55
- const recordData = fs.readJSONSync(recordFile);
56
- const answer = await inquirer.default.prompt([
57
- {
58
- type: "confirm",
59
- name: "recover",
60
- message: "发现之前的任务记录,是否恢复?",
61
- default: true,
62
- },
63
- ]);
64
- if (answer.recover) {
65
- return {
66
- messages: recordData.messages,
67
- };
68
- } else {
69
- return null;
70
- }
71
- } catch (error) {
72
- console.error("Failed to recover:", error.message);
73
- return null;
74
- }
75
- }
76
-
77
- // 记录message以及压缩后的messages
78
- log(message) {
79
- if (GlobalVariable.isLog) {
80
- const time = dayjs();
81
- const logDir = path.join(
82
- process.cwd(),
83
- `ai-log/${time.format("YYYY-MM-DD")}`,
84
- );
85
- const logFile = path.join(logDir, `log-${time.format("HH")}.txt`);
86
-
87
- try {
88
- fs.ensureDirSync(logDir);
89
- if (typeof message === "object" && !Array.isArray(message)) {
90
- message = JSON.stringify(message);
91
- } else if (Array.isArray(message)) {
92
- message = '###压缩上下文###' + "\n" + JSON.stringify(message);
93
- }
94
- const logEntry = `[${new Date().toISOString()}] ${message}\n`;
95
- fs.appendFileSync(logFile, logEntry);
96
- return true;
97
- } catch (error) {
98
- console.error("Failed to log:", error.message);
99
- return false;
100
- }
101
- }
102
- }
103
-
104
- clear() {
105
- const recordDir = path.join(process.cwd(), "ai-history");
106
- try {
107
- const exists = fs.pathExistsSync(recordDir);
108
- if (exists) {
109
- fs.removeSync(recordDir);
110
- }
111
- return true;
112
- } catch (error) {
113
- console.error("Failed to clear:", error.message);
114
- return false;
115
- }
116
- }
117
- }
118
-
119
- module.exports = AiRecorder;