Skip to content

Commit 41a936c

Browse files
committed
perf: import tools
1 parent 1d10f21 commit 41a936c

File tree

60 files changed

+1338
-1425
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1338
-1425
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"build:main": "bun build --env=disable --outfile=dist/index.js --target=node --minify ./src/index.ts",
99
"build:worker": "bun build --outfile=dist/worker.js --target=node --minify ./src/worker/worker.ts",
1010
"start": "NODE_ENV=production node --env-file-if-exists=.env.local dist/index.js",
11-
"dev": "bun run --watch src/index.ts",
11+
"dev": "bun run ./scripts/dev.ts && bun run --watch src/index.ts",
1212
"test": "vitest",
1313
"lint": "bun eslint --fix",
1414
"prettier": "prettier --write \"./**/*.{ts,js,json}\"",

packages/tool/.gitignore

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/tool/api/run.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const runToolHandler = s.route(contract.tool.run, async (args) => {
2525
return {
2626
status: 500,
2727
body: {
28-
error: getErrText(result.error)
28+
error: getErrText(result.error) || 'unknown error'
2929
}
3030
};
3131
} else {

packages/tool/contract.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import z from 'zod';
22
import { c } from '@/contract/init';
3-
import { ToolListItemSchema, type ToolListItemType } from './type/tool';
3+
import { ToolListItemSchema, type ToolListItemType } from './type/api';
44
import type { InputType } from './type/fastgpt';
55
import { SystemVarSchema } from './type';
66

packages/tool/init.ts

Lines changed: 63 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import path from 'path';
22
import { isProd } from '@/constants';
3-
import type { ToolType, ToolSetType } from './type';
3+
import type { ToolType, ToolConfigWithCbType, ToolSetConfigType } from './type';
44
import { tools } from './constants';
55
import { findToolIcon } from './utils/icon';
66
import fs from 'fs';
77
import { addLog } from '@/utils/log';
8+
import { ToolTypeEnum } from './type/tool';
89

910
const saveFile = async (url: string, path: string) => {
1011
const response = await fetch(url);
@@ -16,92 +17,81 @@ const saveFile = async (url: string, path: string) => {
1617
return buffer;
1718
};
1819

19-
export const LoadTool = (mod: ToolType | ToolSetType, filename: string) => {
20-
const tmpTools: ToolType[] = [];
21-
const defaultToolId = filename.split('.').shift() as string;
22-
const toolId = mod.toolId || defaultToolId;
23-
const defaultToolImg = findToolIcon(defaultToolId);
20+
// Load tool or toolset and its children
21+
export const LoadToolsByFilename = async (
22+
basePath: string,
23+
filename: string
24+
): Promise<ToolType[]> => {
25+
const tools: ToolType[] = [];
2426

25-
if ('children' in mod) {
26-
const children = mod.children as ToolType[];
27-
tmpTools.push({
28-
...mod,
29-
icon: mod.icon || defaultToolImg,
30-
toolFile: filename,
31-
toolId,
32-
inputs: [],
33-
outputs: [],
34-
cb: () => Promise.resolve({})
35-
});
36-
tmpTools.push(...children.map((child) => ({ ...child, toolFile: filename })));
37-
} else {
38-
tmpTools.push({
39-
...mod,
40-
icon: mod.icon || defaultToolImg,
41-
toolId,
42-
toolFile: filename
27+
const toolRootPath = path.join(basePath, filename);
28+
const childrenPath = path.join(toolRootPath, 'children');
29+
const isToolSet = fs.existsSync(childrenPath);
30+
31+
const defaultIcon = findToolIcon(filename);
32+
33+
if (isToolSet) {
34+
const toolset = (await import(toolRootPath)).default as ToolSetConfigType;
35+
const toolsetId = toolset.toolId || filename;
36+
const icon = toolset.icon || defaultIcon;
37+
38+
tools.push({
39+
...toolset,
40+
toolId: toolsetId,
41+
icon,
42+
toolDirName: filename,
43+
cb: () => Promise.resolve({}),
44+
versionList: []
4345
});
44-
}
46+
// Push children
47+
// 1. Read children
48+
const children = fs.readdirSync(childrenPath);
4549

46-
return tmpTools;
47-
};
50+
for await (const child of children) {
51+
const childPath = path.join(childrenPath, child);
52+
const childMod = (await import(childPath)).default as ToolConfigWithCbType;
4853

49-
const LoadToolsProd = async () => {
50-
const toolsDir = process.env.TOOLS_DIR || path.join(process.cwd(), 'dist', 'tools');
51-
// 两种方式:
52-
// 1. 读取 tools 目录下所有目录的 index.js 文件作为 tool
53-
const files = fs.readdirSync(toolsDir);
54-
for (const file of files) {
55-
const filePath = path.join(toolsDir, file);
56-
const mod = (await import(filePath)).default as ToolType;
57-
tools.push(...LoadTool(mod, file));
58-
}
59-
// 2. 读取 tools.json 文件中的配置(通过网络挂载)
60-
const toolConfigPath = path.join(process.cwd(), 'dist', 'tools.json');
61-
if (fs.existsSync(toolConfigPath)) {
62-
const toolConfig = JSON.parse(fs.readFileSync(toolConfigPath, 'utf-8')) as {
63-
toolId: string;
64-
url: string;
65-
}[];
66-
// every string is a url to get a .js file
67-
for (const tool of toolConfig) {
68-
await saveFile(tool.url, path.join(toolsDir, tool.toolId + '.js'));
69-
const mod = (await import(path.join(toolsDir, tool.toolId + '.js'))).default as ToolType;
70-
tools.push(...LoadTool(mod, tool.toolId));
54+
const toolId = childMod.toolId || `${toolsetId}/${child}`;
55+
56+
tools.push({
57+
...childMod,
58+
toolId,
59+
parentId: toolsetId,
60+
type: toolset.type,
61+
icon,
62+
toolDirName: filename
63+
});
7164
}
65+
} else {
66+
const tool = (await import(toolRootPath)).default as ToolConfigWithCbType;
67+
68+
tools.push({
69+
...tool,
70+
type: tool.type || ToolTypeEnum.tools,
71+
icon: tool.icon || defaultIcon,
72+
toolId: tool.toolId || filename,
73+
toolDirName: filename
74+
});
7275
}
73-
addLog.info(`\
7476

75-
=================
76-
reading tools in prod mode
77-
tools:\n[ ${tools.map((tool) => tool.toolId).join(', ')} ]
78-
amount: ${tools.length}
79-
=================
80-
`);
77+
return tools;
8178
};
8279

83-
async function LoadToolsDev() {
84-
const toolsPath = path.join(__dirname, 'packages');
85-
const toolDirs = fs.readdirSync(toolsPath);
80+
export async function initTool() {
81+
const basePath = isProd
82+
? process.env.TOOLS_DIR || path.join(process.cwd(), 'dist', 'tools')
83+
: path.join(__dirname, 'packages');
84+
85+
const toolDirs = fs.readdirSync(basePath);
8686
for (const tool of toolDirs) {
87-
const toolPath = path.join(toolsPath, tool);
88-
const mod = (await import(toolPath)).default as ToolType | ToolSetType;
89-
tools.push(...LoadTool(mod, tool));
87+
const tmpTools = await LoadToolsByFilename(basePath, tool);
88+
tools.push(...tmpTools);
9089
}
91-
addLog.info(`\
9290

91+
addLog.info(`
9392
=================
94-
reading tools in dev mode
95-
tools:\n[ ${tools.map((tool) => tool.toolId).join(', ')} ]
93+
Load tools in prod mode
9694
amount: ${tools.length}
9795
=================
9896
`);
9997
}
100-
101-
export async function initTool() {
102-
if (isProd) {
103-
await LoadToolsProd();
104-
} else {
105-
await LoadToolsDev();
106-
}
107-
}

packages/tool/packages/DingTalkWebhook/config.ts

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,6 @@ import { ToolTypeEnum } from '@tool/type/tool';
44

55
export default defineTool({
66
toolId: 'community-DingTalkWebhook',
7-
versionList: [
8-
{
9-
value: '0.1.0',
10-
description: 'Default version'
11-
}
12-
],
137
type: ToolTypeEnum.communication,
148
name: {
159
'zh-CN': '钉钉 webhook',
@@ -21,57 +15,63 @@ export default defineTool({
2115
},
2216
icon: 'plugins/dingding',
2317
courseUrl: 'https://open.dingtalk.com/document/robots/custom-robot-access',
24-
inputs: [
25-
{
26-
valueType: WorkflowIOValueTypeEnum.string,
27-
key: 'webhookUrl',
28-
label: '钉钉机器人地址',
29-
description: '',
30-
defaultValue: '',
31-
renderTypeList: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference],
32-
required: true,
33-
value: ''
34-
},
18+
versionList: [
3519
{
36-
renderTypeList: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference],
37-
selectedTypeIndex: 0,
38-
valueType: WorkflowIOValueTypeEnum.string,
39-
key: 'secret',
40-
label: '加签值',
41-
description: '钉钉机器人加签值',
42-
defaultValue: '',
43-
list: [
20+
value: '0.1.0',
21+
description: 'Default version',
22+
inputs: [
4423
{
45-
label: '',
24+
valueType: WorkflowIOValueTypeEnum.string,
25+
key: 'webhookUrl',
26+
label: '钉钉机器人地址',
27+
description: '',
28+
defaultValue: '',
29+
renderTypeList: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference],
30+
required: true,
4631
value: ''
47-
}
48-
],
49-
maxFiles: 5,
50-
canSelectFile: true,
51-
canSelectImg: true,
52-
required: true
53-
},
54-
{
55-
renderTypeList: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference],
56-
selectedTypeIndex: 0,
57-
valueType: WorkflowIOValueTypeEnum.string,
58-
key: 'message',
59-
60-
label: '发送的消息',
61-
description: '发送的消息',
62-
defaultValue: '',
63-
list: [
32+
},
6433
{
65-
label: '',
66-
value: ''
34+
renderTypeList: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference],
35+
selectedTypeIndex: 0,
36+
valueType: WorkflowIOValueTypeEnum.string,
37+
key: 'secret',
38+
label: '加签值',
39+
description: '钉钉机器人加签值',
40+
defaultValue: '',
41+
list: [
42+
{
43+
label: '',
44+
value: ''
45+
}
46+
],
47+
maxFiles: 5,
48+
canSelectFile: true,
49+
canSelectImg: true,
50+
required: true
51+
},
52+
{
53+
renderTypeList: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference],
54+
selectedTypeIndex: 0,
55+
valueType: WorkflowIOValueTypeEnum.string,
56+
key: 'message',
57+
58+
label: '发送的消息',
59+
description: '发送的消息',
60+
defaultValue: '',
61+
list: [
62+
{
63+
label: '',
64+
value: ''
65+
}
66+
],
67+
maxFiles: 5,
68+
canSelectFile: true,
69+
canSelectImg: true,
70+
required: true,
71+
toolDescription: '发送的消息'
6772
}
6873
],
69-
maxFiles: 5,
70-
canSelectFile: true,
71-
canSelectImg: true,
72-
required: true,
73-
toolDescription: '发送的消息'
74+
outputs: []
7475
}
75-
],
76-
outputs: []
76+
]
7777
});

0 commit comments

Comments
 (0)