deepfish-ai 1.0.21 → 1.0.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepfish-ai",
3
- "version": "1.0.21",
3
+ "version": "1.0.22",
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
  "type": "commonjs",
@@ -1,20 +1,12 @@
1
1
  const path = require('path')
2
2
  const os = require('os')
3
3
  const fs = require('fs-extra')
4
- const FileTools = require('./tools/FileTools.js')
5
- const InquirerTools = require('./tools/InquirerTools.js')
6
- const SystemTools = require('./tools/SystemTools.js')
7
- const CreateAgentTools = require('./tools/CreateAgentTools.js')
8
4
  const lodash = require('lodash')
9
5
  const { Brain } = require('./Brain.js')
10
6
  const BrainEvent = require('./BrainEvent.js')
11
7
  const ScreenPrinter = require('./ScreenPrinter.js')
12
8
  const { HandEvent, Hand } = require('./Hand.js')
13
9
  const dayjs = require('dayjs')
14
- const Logger = require('./Logger.js')
15
- const GenerateTools = require('./tools/GenerateTools.js')
16
- const TaskTools = require('./tools/TaskTools.js')
17
- const TestTools = require('./tools/TestTools.js')
18
10
  const axios = require('axios')
19
11
  const echarts = require('echarts')
20
12
  const canvas = require('canvas')
@@ -243,15 +235,17 @@ class BaseAgentRobot {
243
235
 
244
236
  // 获取原装工具
245
237
  _getOriginalTools() {
246
- return [
247
- FileTools,
248
- InquirerTools,
249
- SystemTools,
250
- CreateAgentTools,
251
- GenerateTools,
252
- TaskTools,
253
- TestTools,
254
- ]
238
+ // 自动扫描tools目录
239
+ const toolsPath = path.join(__dirname, './tools')
240
+ const toolFiles = fs.readdirSync(toolsPath).filter((file) => {
241
+ return file.endsWith('.js') || file.endsWith('.mjs')
242
+ })
243
+ const tools = []
244
+ toolFiles.forEach((file) => {
245
+ const tool = require(path.join(toolsPath, file))
246
+ tools.push(tool)
247
+ })
248
+ return tools
255
249
  }
256
250
 
257
251
  _getDefaultSystemPrompt(opt) {
@@ -0,0 +1,203 @@
1
+ /**
2
+ * @Author: Roman 306863030@qq.com
3
+ * @Description: 文档格式转换工具集(Markdown / HTML / PDF 互转)
4
+ * 依赖:puppeteer / fs-extra
5
+ * Word 相关转换(wordToPdf / wordToHtml / wordToMarkdown / markdownToWord / htmlToWord)已集成在 DocxTool 中
6
+ */
7
+ const path = require('path')
8
+ const fs = require('fs-extra')
9
+
10
+ // ─── 统一返回结构 ─────────────────────────────────────────────────────────────
11
+
12
+ function ok(data = null) {
13
+ return { success: true, data }
14
+ }
15
+
16
+ function fail(error, data = null) {
17
+ return { success: false, error: error?.message || String(error), data }
18
+ }
19
+
20
+ function resolvePath(filePath) {
21
+ return path.resolve(process.cwd(), filePath)
22
+ }
23
+
24
+ // ─── 内部辅助 ─────────────────────────────────────────────────────────────────
25
+
26
+ /**
27
+ * 使用 puppeteer 将 HTML 字符串渲染为 PDF 文件
28
+ */
29
+ async function htmlStringToPdf(html, outputPath) {
30
+ let puppeteer
31
+ try {
32
+ puppeteer = require('puppeteer')
33
+ } catch {
34
+ throw new Error('puppeteer 未安装,请先执行 npm install puppeteer')
35
+ }
36
+ const browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] })
37
+ try {
38
+ const page = await browser.newPage()
39
+ await page.setContent(html, { waitUntil: 'networkidle0' })
40
+ fs.ensureDirSync(path.dirname(outputPath))
41
+ await page.pdf({ path: outputPath, format: 'A4', printBackground: true })
42
+ } finally {
43
+ await browser.close()
44
+ }
45
+ }
46
+
47
+ function escapeHtml(str) {
48
+ return str
49
+ .replace(/&/g, '&')
50
+ .replace(/</g, '&lt;')
51
+ .replace(/>/g, '&gt;')
52
+ }
53
+
54
+ /**
55
+ * 将 Markdown 文本转换为 HTML 字符串(基础实现,无需额外依赖)
56
+ */
57
+ function markdownToHtmlString(md) {
58
+ let html = md
59
+ // 代码块
60
+ .replace(/```(\w*)\n([\s\S]*?)```/g, (_, lang, code) =>
61
+ `<pre><code class="language-${lang}">${escapeHtml(code.trimEnd())}</code></pre>`)
62
+ // 行内代码
63
+ .replace(/`([^`]+)`/g, (_, c) => `<code>${escapeHtml(c)}</code>`)
64
+ // 标题
65
+ .replace(/^###### (.+)$/gm, '<h6>$1</h6>')
66
+ .replace(/^##### (.+)$/gm, '<h5>$1</h5>')
67
+ .replace(/^#### (.+)$/gm, '<h4>$1</h4>')
68
+ .replace(/^### (.+)$/gm, '<h3>$1</h3>')
69
+ .replace(/^## (.+)$/gm, '<h2>$1</h2>')
70
+ .replace(/^# (.+)$/gm, '<h1>$1</h1>')
71
+ // 水平线
72
+ .replace(/^[-*_]{3,}$/gm, '<hr>')
73
+ // 粗斜体
74
+ .replace(/\*\*\*(.+?)\*\*\*/g, '<strong><em>$1</em></strong>')
75
+ // 粗体
76
+ .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
77
+ .replace(/__(.+?)__/g, '<strong>$1</strong>')
78
+ // 斜体
79
+ .replace(/\*(.+?)\*/g, '<em>$1</em>')
80
+ .replace(/_(.+?)_/g, '<em>$1</em>')
81
+ // 删除线
82
+ .replace(/~~(.+?)~~/g, '<del>$1</del>')
83
+ // 图片
84
+ .replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img alt="$1" src="$2">')
85
+ // 链接
86
+ .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>')
87
+ // 无序列表
88
+ .replace(/^[ \t]*[-*+] (.+)$/gm, '<li>$1</li>')
89
+ // 有序列表
90
+ .replace(/^[ \t]*\d+\. (.+)$/gm, '<li>$1</li>')
91
+ // 引用
92
+ .replace(/^> (.+)$/gm, '<blockquote>$1</blockquote>')
93
+
94
+ // 将连续 <li> 包裹进 <ul>
95
+ html = html.replace(/(<li>[\s\S]+?<\/li>)(\n(?!<li>)|$)/g, (_, items) => `<ul>${items}</ul>`)
96
+
97
+ // 段落:连续非标签行
98
+ html = html.replace(/^(?!<[a-z]|$)(.+)$/gm, '<p>$1</p>')
99
+
100
+ return `<!DOCTYPE html><html><head><meta charset="utf-8"><style>
101
+ body{font-family:sans-serif;line-height:1.7;max-width:900px;margin:40px auto;padding:0 20px;color:#333}
102
+ h1,h2,h3,h4,h5,h6{margin-top:1.2em}
103
+ pre{background:#f5f5f5;padding:12px;border-radius:4px;overflow:auto}
104
+ code{background:#f0f0f0;padding:2px 4px;border-radius:3px}
105
+ blockquote{border-left:4px solid #ddd;margin:0;padding-left:1em;color:#666}
106
+ table{border-collapse:collapse;width:100%}td,th{border:1px solid #ddd;padding:6px 10px}
107
+ </style></head><body>${html}</body></html>`
108
+ }
109
+
110
+ // ─── 工具函数 ─────────────────────────────────────────────────────────────────
111
+
112
+ /**
113
+ * Markdown 转 PDF
114
+ */
115
+ async function markdownToPdf(inputPath, outputPath) {
116
+ try {
117
+ const fullInput = resolvePath(inputPath)
118
+ const fullOutput = resolvePath(outputPath)
119
+ if (!fs.existsSync(fullInput)) {
120
+ return fail(`File does not exist: ${fullInput}`, { inputPath: fullInput })
121
+ }
122
+ const md = fs.readFileSync(fullInput, 'utf8')
123
+ const html = markdownToHtmlString(md)
124
+ await htmlStringToPdf(html, fullOutput)
125
+ return ok({ inputPath: fullInput, outputPath: fullOutput })
126
+ } catch (error) {
127
+ return fail(error, { inputPath, outputPath })
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Markdown 转 HTML
133
+ */
134
+ async function markdownToHtml(inputPath, outputPath) {
135
+ try {
136
+ const fullInput = resolvePath(inputPath)
137
+ const fullOutput = resolvePath(outputPath)
138
+ if (!fs.existsSync(fullInput)) {
139
+ return fail(`File does not exist: ${fullInput}`, { inputPath: fullInput })
140
+ }
141
+ const md = fs.readFileSync(fullInput, 'utf8')
142
+ const html = markdownToHtmlString(md)
143
+ fs.ensureDirSync(path.dirname(fullOutput))
144
+ fs.writeFileSync(fullOutput, html, 'utf8')
145
+ return ok({ inputPath: fullInput, outputPath: fullOutput })
146
+ } catch (error) {
147
+ return fail(error, { inputPath, outputPath })
148
+ }
149
+ }
150
+
151
+ // ─── 工具描述 ─────────────────────────────────────────────────────────────────
152
+
153
+ const descriptions = [
154
+ {
155
+ type: 'function',
156
+ function: {
157
+ name: 'markdownToPdf',
158
+ description:
159
+ '将 Markdown 文件(.md)转换为 PDF 文件。依赖 puppeteer,转换时应用默认样式。参数:inputPath 为源 .md 路径;outputPath 为输出 .pdf 路径。返回值:对象,包含 success、data(含 inputPath、outputPath)、error。',
160
+ parameters: {
161
+ type: 'object',
162
+ properties: {
163
+ inputPath: { type: 'string', description: '源 .md 文件路径。' },
164
+ outputPath: { type: 'string', description: '输出 .pdf 文件路径。' },
165
+ },
166
+ required: ['inputPath', 'outputPath'],
167
+ },
168
+ },
169
+ },
170
+ {
171
+ type: 'function',
172
+ function: {
173
+ name: 'markdownToHtml',
174
+ description:
175
+ '将 Markdown 文件(.md)转换为 HTML 文件,包含内联样式,可直接在浏览器中打开。参数:inputPath 为源 .md 路径;outputPath 为输出 .html 路径。返回值:对象,包含 success、data(含 inputPath、outputPath)、error。',
176
+ parameters: {
177
+ type: 'object',
178
+ properties: {
179
+ inputPath: { type: 'string', description: '源 .md 文件路径。' },
180
+ outputPath: { type: 'string', description: '输出 .html 文件路径。' },
181
+ },
182
+ required: ['inputPath', 'outputPath'],
183
+ },
184
+ },
185
+ },
186
+ ]
187
+
188
+ // ─── 导出 ──────────────────────────────────────────────────────────────────────
189
+
190
+ const functions = {
191
+ markdownToPdf,
192
+ markdownToHtml,
193
+ }
194
+
195
+ const DocTransformTool = {
196
+ name: 'DocTransformTool',
197
+ description: '提供 Markdown 与 HTML/PDF 之间的格式互转能力,支持 markdown转pdf、markdown转html。Word 相关转换请使用 DocxTool。',
198
+ platform: 'all',
199
+ descriptions,
200
+ functions,
201
+ }
202
+
203
+ module.exports = DocTransformTool