Skip to content

Commit 17708a7

Browse files
authored
feat: new tool docDiff (#279)
* feat(docDiff): new tool doc diff * chore: logo * chore: html * fix: s3 upload prefix * fix: fix test
1 parent 7192351 commit 17708a7

File tree

11 files changed

+1856
-5
lines changed

11 files changed

+1856
-5
lines changed

.claude/CLAUDE.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,15 +180,22 @@ bun run install:plugins
180180
bun run build:pkg
181181
```
182182

183-
### 3. 生产部署
183+
### 3. 测试和部署
184184
```bash
185+
# 运行测试
186+
bun run test
187+
185188
# 构建生产版本
186189
bun run build:runtime
187190

188191
# 启动生产服务
189192
bun run start
190193
```
191194

195+
**⚠️ 重要**:
196+
- 测试命令使用 `bun run test` 而不是 `bun test`
197+
- 测试环境使用 Vitest 运行器,支持 mock 和覆盖率
198+
192199
## 快速适配指南
193200

194201
### 1. 工具适配步骤

lib/s3/controller.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,11 @@ export class S3Service {
249249

250250
// const fileId = this.generateFileId();
251251
const prefix = input.prefix
252-
? input.prefix?.endsWith('/')
253-
? input.prefix
254-
: input.prefix + '/'
252+
? !input.prefix?.endsWith('/')
253+
? input.prefix + '/'
254+
: input.prefix
255255
: PluginBaseS3Prefix;
256-
const objectName = `${prefix}${input.keepRawFilename ? '' : this.generateFileId() + '-'}${originalFilename}`;
256+
const objectName = `${prefix}/${input.keepRawFilename ? '' : this.generateFileId() + '-'}${originalFilename}`;
257257
if (input.expireMins) {
258258
await MongoS3TTL.create({
259259
bucketName: this.config.bucket,
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# DocDiff 系统工具
2+
3+
输入:两个 markdown 格式的纯文本内容
4+
输出:一个 html 文件
5+
6+
提供一个 html 模版文件, 对两个文本内容进行对比,逐段对比,分析其中的差异,高亮显示差异。
7+
8+
描述工具集名称,以及子工具,子工具需要包含 ID,名字,哪些输入输出,例如:
9+
10+
---
11+
12+
下面由 AI 生成完整的设计文档
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# DocDiff 文档对比工具
2+
3+
一个用于对比两个 Markdown 文档差异的 FastGPT 工具,生成可视化的 HTML 对比报告。
4+
5+
## 功能特性
6+
7+
- 📝 **行级对比**: 逐行分析文档差异,精确识别变更
8+
- 🎨 **可视化报告**: 生成美观的双栏 HTML 对比报告
9+
- 🔄 **导航功能**: 支持按钮和键盘快捷键在变更间跳转
10+
- 📊 **统计信息**: 显示新增、删除、修改、未修改的行数
11+
- 🔒 **安全防护**: 自动转义 HTML 字符,防止 XSS 攻击
12+
- 📱 **响应式设计**: 支持移动端浏览
13+
-**高性能**: 基于相似度算法的智能对比
14+
15+
## 使用方法
16+
17+
### 输入参数
18+
19+
- **originalText** (必需): 原始的 Markdown 文档内容
20+
- **modifiedText** (必需): 修改后的 Markdown 文档内容
21+
- **title** (可选): 对比报告的标题,默认为"文档对比报告"
22+
23+
### 输出
24+
25+
返回 HTML 文件访问 URL,包含:
26+
- 文档标题和生成时间
27+
- 变更统计信息
28+
- 双栏对比视图(左为原始文档,右为修改后文档)
29+
- 导航控制按钮
30+
- 响应式设计支持
31+
32+
## 对比算法
33+
34+
工具使用智能的相似度算法来识别文档变化:
35+
36+
1. **行级分割**: 将文档按换行符分割为行
37+
2. **相似度计算**: 基于字符级别的相似度匹配
38+
3. **变更分类**:
39+
- 未修改 (>80% 相似度)
40+
- 修改 (10%-80% 相似度)
41+
- 新增 (仅在修改后文档中存在)
42+
- 删除 (仅在原始文档中存在)
43+
4. **最佳匹配**: 寻找最相似的行配对
44+
45+
## 使用示例
46+
47+
```typescript
48+
const result = await tool({
49+
originalText: `# 项目文档
50+
51+
## 功能介绍
52+
这是一个测试功能。
53+
54+
## 安装步骤
55+
1. 下载代码
56+
2. 运行安装命令`,
57+
58+
modifiedText: `# 项目文档
59+
60+
## 功能介绍
61+
这是一个更新的测试功能。
62+
63+
## 安装步骤
64+
1. 下载代码
65+
2. 运行安装命令
66+
3. 配置环境变量`,
67+
68+
title: "项目文档变更记录"
69+
});
70+
71+
console.log(result.htmlUrl); // 输出 HTML 对比报告 URL
72+
```
73+
74+
## HTML 报告特性
75+
76+
- 🎨 **现代化设计**: 渐变背景、卡片布局、阴影效果
77+
- 📈 **统计仪表板**: 直观显示各类变更数量
78+
- 🔄 **双栏对比**: 左右并排显示原始和修改内容
79+
- 🎯 **导航功能**: 点击按钮或使用键盘快捷键在变更间跳转
80+
- 🏷️ **状态标签**: 不同颜色标识变更类型
81+
-**高亮效果**: 柔和的高亮提示,自动消失
82+
- 📝 **代码显示**: 使用等宽字体保持格式
83+
- 📱 **响应式布局**: 自适应不同屏幕尺寸
84+
85+
## 技术实现
86+
87+
- **TypeScript**: 类型安全的实现
88+
- **Zod 验证**: 输入参数验证
89+
- **纯函数设计**: 无副作用的处理逻辑
90+
- **HTML 安全**: 自动转义特殊字符
91+
92+
## 适用场景
93+
94+
- 📄 **文档版本对比**: 比较文档的不同版本
95+
- 📝 **内容审核**: 查看内容修改记录
96+
- 🔄 **变更追踪**: 跟踪文档变化
97+
- 📊 **差异分析**: 分析文档变更模式
98+
99+
## 开发和测试
100+
101+
```bash
102+
# 安装依赖
103+
bun install
104+
105+
# 运行测试
106+
bun test
107+
108+
# 类型检查
109+
bun run tsc --noEmit
110+
111+
# 构建
112+
bun run build
113+
```
114+
115+
## 测试覆盖
116+
117+
- ✅ 输入验证测试
118+
- ✅ 文档对比逻辑测试
119+
- ✅ HTML 输出质量测试
120+
- ✅ 边界情况测试
121+
- ✅ 安全性测试
122+
123+
## 版本信息
124+
125+
- **当前版本**: 1.0.0
126+
- **FastGPT 兼容性**: 完全兼容
127+
- **依赖**: 仅依赖 Zod,无外部 API 调用
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"lockfileVersion": 1,
3+
"workspaces": {
4+
"": {
5+
"name": "@fastgpt-plugins/tool-doc-diff",
6+
"dependencies": {
7+
"zod": "^3.25.76",
8+
},
9+
"devDependencies": {
10+
"@types/bun": "latest",
11+
},
12+
"peerDependencies": {
13+
"typescript": "^5.0.0",
14+
},
15+
},
16+
},
17+
"packages": {
18+
"@types/bun": ["@types/bun@1.3.1", "", { "dependencies": { "bun-types": "1.3.1" } }, "sha512-4jNMk2/K9YJtfqwoAa28c8wK+T7nvJFOjxI4h/7sORWcypRNxBpr+TPNaCfVWq70tLCJsqoFwcf0oI0JU/fvMQ=="],
19+
20+
"@types/node": ["@types/node@24.10.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A=="],
21+
22+
"@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="],
23+
24+
"bun-types": ["bun-types@1.3.1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="],
25+
26+
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
27+
28+
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
29+
30+
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
31+
32+
"zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
33+
}
34+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { defineTool } from '@tool/type';
2+
import { FlowNodeInputTypeEnum, WorkflowIOValueTypeEnum } from '@tool/type/fastgpt';
3+
import { ToolTagEnum } from '@tool/type/tags';
4+
5+
export default defineTool({
6+
name: {
7+
'zh-CN': '文档对比工具',
8+
en: 'DocDiff'
9+
},
10+
tags: [ToolTagEnum.enum.tools],
11+
description: {
12+
'zh-CN': '对比两个 Markdown 文档的差异,生成可视化的 HTML 对比报告',
13+
en: 'Compare differences between two Markdown documents and generate visual HTML comparison report'
14+
},
15+
toolDescription:
16+
'A tool that compares two markdown documents and generates a visual HTML diff report showing differences section by section',
17+
18+
versionList: [
19+
{
20+
value: '1.0.0',
21+
description: 'Initial version',
22+
inputs: [
23+
{
24+
key: 'originalText',
25+
label: '原始文档',
26+
description: '原始的 Markdown 格式文档内容',
27+
required: true,
28+
valueType: WorkflowIOValueTypeEnum.string,
29+
renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference],
30+
toolDescription: 'The original markdown document content to compare'
31+
},
32+
{
33+
key: 'modifiedText',
34+
label: '修改后文档',
35+
description: '修改后的 Markdown 格式文档内容',
36+
required: true,
37+
valueType: WorkflowIOValueTypeEnum.string,
38+
renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference],
39+
toolDescription: 'The modified markdown document content to compare'
40+
},
41+
{
42+
key: 'title',
43+
label: '对比报告标题',
44+
description: '生成的 HTML 对比报告的标题',
45+
required: false,
46+
valueType: WorkflowIOValueTypeEnum.string,
47+
renderTypeList: [FlowNodeInputTypeEnum.input],
48+
defaultValue: '文档对比报告'
49+
}
50+
],
51+
outputs: [
52+
{
53+
valueType: WorkflowIOValueTypeEnum.string,
54+
key: 'htmlUrl',
55+
label: 'HTML 对比报告连接',
56+
description: '生成的 HTML 对比报告的访问连接'
57+
},
58+
{
59+
valueType: WorkflowIOValueTypeEnum.arrayObject,
60+
key: 'diffs',
61+
label: '差异结果数组',
62+
description: '过滤后的文档差异数组,包含新增、删除、修改的变更'
63+
}
64+
]
65+
}
66+
]
67+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import config from './config';
2+
import { InputType, OutputType, tool as toolCb } from './src';
3+
import { exportTool } from '@tool/utils/tool';
4+
5+
export default exportTool({
6+
toolCb,
7+
InputType,
8+
OutputType,
9+
config
10+
});
Lines changed: 20 additions & 0 deletions
Loading
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "@fastgpt-plugins/tool-doc-diff",
3+
"module": "index.ts",
4+
"type": "module",
5+
"scripts": {
6+
"build": "bun ../../../../scripts/build.ts"
7+
},
8+
"devDependencies": {
9+
"@types/bun": "latest"
10+
},
11+
"peerDependencies": {
12+
"typescript": "^5.0.0"
13+
},
14+
"dependencies": {
15+
"zod": "^3.25.76"
16+
}
17+
}

0 commit comments

Comments
 (0)