Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions apps/tools/migrations/internal_tool.sql
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def langsearch(query, apikey):
raise Exception(f"API请求失败: {response.status_code}, 错误信息: {response.text}")
return (response.text)', '[{"name": "query", "type": "string", "source": "reference", "is_required": true}]', '[{"attrs": {"type": "password", "maxlength": 200, "minlength": 1, "show-password": true, "show-word-limit": true}, "field": "apikey", "label": "API Key", "required": true, "input_type": "PasswordInput", "props_info": {"rules": [{"message": "API Key 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "API Key 长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}]', './tool/langsearch/icon.png', true, 'INTERNAL', 'INTERNAL', null, 'None', '', 'f0dd8f71-e4ee-11ee-8c84-a8a1595801ab', 'default');
INSERT INTO tool (create_time, update_time, id, name, label, "desc", code, input_field_list, init_field_list, icon, is_active, scope, tool_type, template_id, workspace_id, init_params, user_id, folder_id) VALUES ('2025-03-17 08:16:32.626245 +00:00', '2025-03-17 08:16:32.626308 +00:00', '22c21b76-0308-11f0-9694-5618c4394482', 'MySQL 查询','database_search', '一个连接MySQL数据库执行SQL查询的工具', e'
def query_mysql(host,port, user, password, database, sql):
def query_mysql(host, port, user, password, database, sql: str, to_json_str: boolean):
import pymysql
import json
from pymysql.cursors import DictCursor
Expand All @@ -76,6 +76,7 @@ def query_mysql(host,port, user, password, database, sql):
return float(obj) # 将 Decimal 转换为 float
raise TypeError(f"Type {type(obj)} not serializable")

db = None
try:
# 创建连接
db = pymysql.connect(
Expand All @@ -102,16 +103,20 @@ def query_mysql(host,port, user, password, database, sql):
if isinstance(value, bytes):
row[key] = value.decode("utf-8") # 转换为字符串

# 将数据序列化为 JSON
json_data = json.dumps(data, default=default_serializer, ensure_ascii=False)
return json_data

# 关闭数据库连接
db.close()
Copy link
Copy Markdown
Contributor Author

@wangliang181230 wangliang181230 May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

其他优化2:代码 db.close()return 之后了,成了无效代码,根本就不会执行该代码。所以 db.close() 放到 finally: 中执行

if to_json_str is None or to_json_str is True:
# 将数据序列化为 JSON
return json.dumps(data, default=default_serializer, ensure_ascii=False)
else:
# 直接输出数组(list)对象
return data
Copy link
Copy Markdown
Contributor Author

@wangliang181230 wangliang181230 May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

其他优化1. MySQL 查询 工具,添加 to_json_str 参数,用于控制查询结果是否转为JSON字符串(默认值:1=会转为JSON字符串)

在部分情况下,可设置该参数为0,输出结果不转为JSON字符串,可通过其他工具来处理数据。

同时,input_field_list 字段中添加了 , {"name": "to_json_str", "desc": "结果是否转换为JSON字符串:1=是 | 0=否", "type": "boolean", "source": "custom", "is_required": false, "default_value": "1"}。默认值为 1


except Exception as e:
print(f"Error while connecting to MySQL: {e}")
raise e', '[{"name": "sql", "type": "string", "source": "reference", "is_required": true}]', '[{"attrs": {"maxlength": 200, "minlength": 1, "show-word-limit": true}, "field": "host", "label": "host", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "host 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "host长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}, {"attrs": {"maxlength": 20, "minlength": 1, "show-word-limit": true}, "field": "port", "label": "port", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "port 为必填属性", "required": true}, {"max": 20, "min": 1, "message": "port长度在 1 到 20 个字符", "trigger": "blur"}]}, "default_value": "3306", "show_default_value": false}, {"attrs": {"maxlength": 200, "minlength": 1, "show-word-limit": true}, "field": "user", "label": "user", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "user 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "user长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "root", "show_default_value": false}, {"attrs": {"type": "password", "maxlength": 200, "minlength": 1, "show-password": true, "show-word-limit": true}, "field": "password", "label": "password", "required": true, "input_type": "PasswordInput", "props_info": {"rules": [{"message": "password 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "password长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}, {"attrs": {"maxlength": 200, "minlength": 1, "show-word-limit": true}, "field": "database", "label": "database", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "database 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "database长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}]', './tool/mysql/icon.png', true, 'INTERNAL', 'INTERNAL', null, 'None', null, 'f0dd8f71-e4ee-11ee-8c84-a8a1595801ab', 'default');
raise e

finally:
if db:
db.close()', '[{"name": "sql", "type": "string", "source": "reference", "is_required": true}, {"name": "to_json_str", "desc": "结果是否转换为JSON字符串:1=是 | 0=否", "type": "boolean", "source": "custom", "is_required": false, "default_value": "1"}]', '[{"attrs": {"maxlength": 200, "minlength": 1, "show-word-limit": true}, "field": "host", "label": "host", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "host 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "host长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}, {"attrs": {"maxlength": 20, "minlength": 1, "show-word-limit": true}, "field": "port", "label": "port", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "port 为必填属性", "required": true}, {"max": 20, "min": 1, "message": "port长度在 1 到 20 个字符", "trigger": "blur"}]}, "default_value": "3306", "show_default_value": true}, {"attrs": {"maxlength": 200, "minlength": 1, "show-word-limit": true}, "field": "user", "label": "user", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "user 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "user长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "root", "show_default_value": true}, {"attrs": {"type": "password", "maxlength": 200, "minlength": 1, "show-password": true, "show-word-limit": true}, "field": "password", "label": "password", "required": true, "input_type": "PasswordInput", "props_info": {"rules": [{"message": "password 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "password长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}, {"attrs": {"maxlength": 200, "minlength": 1, "show-word-limit": true}, "field": "database", "label": "database", "required": true, "input_type": "TextInput", "props_info": {"rules": [{"message": "database 为必填属性", "required": true}, {"max": 200, "min": 1, "message": "database长度在 1 到 200 个字符", "trigger": "blur"}]}, "default_value": "x", "show_default_value": false}]', './tool/mysql/icon.png', true, 'INTERNAL', 'INTERNAL', null, 'None', null, 'f0dd8f71-e4ee-11ee-8c84-a8a1595801ab', 'default');
INSERT INTO tool (create_time, update_time, id, name, label, "desc", code, input_field_list, init_field_list, icon, is_active, scope, tool_type, template_id, workspace_id, init_params, user_id, folder_id) VALUES ('2025-03-17 07:37:54.620836 +00:00', '2025-03-17 07:37:54.620887 +00:00', 'bd1e8b88-0302-11f0-87bb-5618c4394482', 'PostgreSQL 查询','database_search', '一个连接PostgreSQL数据库执行SQL查询的工具', e'
def queryPgSQL(database, user, password, host, port, query):
import psycopg2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ function clickNodes(item: any, data?: any, type?: string) {
tool_lib_id: data.id,
input_field_list: data.input_field_list.map((field: any) => ({
...field,
value: field.source == 'reference' ? [] : '',
value: field.source === 'reference' ? [] : (field.default_value || ''),
})),
}
}
Expand All @@ -239,7 +239,7 @@ function onmousedown(item: any, data?: any, type?: string) {
tool_lib_id: data.id,
input_field_list: data.input_field_list.map((field: any) => ({
...field,
value: field.source == 'reference' ? [] : '',
value: field.source === 'reference' ? [] : (field.default_value || ''),
})),
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ function clickNodes(item: any, data?: any) {
tool_lib_id: data.id,
input_field_list: data.input_field_list.map((field: any) => ({
...field,
value: field.source == 'reference' ? [] : '',
value: field.source === 'reference' ? [] : (field.default_value || ''),
})),
}
}
Expand All @@ -203,7 +203,7 @@ function onmousedown(item: any, data?: any) {
tool_lib_id: data.id,
input_field_list: data.input_field_list.map((field: any) => ({
...field,
value: field.source == 'reference' ? [] : '',
value: field.source === 'reference' ? [] : (field.default_value || ''),
})),
}
}
Expand Down
4 changes: 2 additions & 2 deletions ui/src/components/workflow-dropdown-menu/knowledge/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ function clickNodes(item: any, data?: any) {
tool_lib_id: data.id,
input_field_list: data.input_field_list.map((field: any) => ({
...field,
value: field.source == 'reference' ? [] : '',
value: field.source === 'reference' ? [] : (field.default_value || ''),
})),
}
}
Expand All @@ -224,7 +224,7 @@ function onmousedown(item: any, data?: any) {
tool_lib_id: data.id,
input_field_list: data.input_field_list.map((field: any) => ({
...field,
value: field.source == 'reference' ? [] : '',
value: field.source === 'reference' ? [] : (field.default_value || ''),
})),
}
}
Expand Down
4 changes: 2 additions & 2 deletions ui/src/components/workflow-dropdown-menu/tool/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ function clickNodes(item: any, data?: any) {
tool_lib_id: data.id,
input_field_list: data.input_field_list.map((field: any) => ({
...field,
value: field.source == 'reference' ? [] : '',
value: field.source === 'reference' ? [] : (field.default_value || ''),
})),
}
}
Expand All @@ -202,7 +202,7 @@ function onmousedown(item: any, data?: any) {
tool_lib_id: data.id,
input_field_list: data.input_field_list.map((field: any) => ({
...field,
value: field.source == 'reference' ? [] : '',
value: field.source === 'reference' ? [] : (field.default_value || ''),
})),
}
}
Expand Down
4 changes: 4 additions & 0 deletions ui/src/locales/lang/en-US/dynamics-form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export default {
label: 'description',
placeholder: 'Please enter a description',
},
default_value: {
label: 'Default Value',
placeholder: 'Please enter a default value',
},
},
TreeSelect: {
label: 'Tree Select',
Expand Down
4 changes: 4 additions & 0 deletions ui/src/locales/lang/zh-CN/dynamics-form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ export default {
label: '描述',
placeholder: '请输入描述',
},
default_value: {
label: '默认值',
placeholder: '请输入默认值',
},
},
TreeSelect: {
label: '树形选择器',
Expand Down
4 changes: 4 additions & 0 deletions ui/src/locales/lang/zh-Hant/dynamics-form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export default {
label: '描述',
placeholder: '請輸入描述',
},
default_value: {
label: '默認值',
placeholder: '請輸入默認值',
},
},
TreeSelect: {
label: '樹狀選擇器',
Expand Down
13 changes: 12 additions & 1 deletion ui/src/views/tool/ToolDebugDrawer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@
<div class="flex">
<span
>{{ item.name }}
<el-tooltip
v-if="item.desc"
effect="dark"
placement="right"
popper-class="max-w-200"
>
<template #content>
{{ item.desc }}
</template>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
</el-tooltip>
Copy link
Copy Markdown
Contributor Author

@wangliang181230 wangliang181230 May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

其他优化3:工具调试界面,展示 desc 参数提示说明

图片

<span class="color-danger" v-if="item.is_required">*</span></span
>
<el-tag size="small" type="info" class="info-tag ml-4">{{ item.type }}</el-tag>
Expand Down Expand Up @@ -182,7 +193,7 @@ const open = (data: any) => {
if (data.input_field_list.length > 0) {
data.input_field_list.forEach((item: any) => {
form.value.debug_field_list.push({
value: '',
value: (item.default_value || ''),
...item,
})
})
Expand Down
10 changes: 10 additions & 0 deletions ui/src/views/tool/component/FieldFormDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@
<el-option :label="$t('common.custom')" value="custom" />
</el-select>
</el-form-item>
<el-form-item v-if="form.source === 'custom'" :label="$t('dynamicsForm.paramForm.default_value.label')">
<el-input
v-model="form.default_value"
:placeholder="$t('dynamicsForm.paramForm.default_value.placeholder')"
:maxlength="1024"
show-word-limit
@blur="form.default_value = form.default_value?.trim()"
/>
</el-form-item>
<el-form-item :label="$t('dynamicsForm.paramForm.required.label')" @click.prevent>
<el-switch size="small" v-model="form.is_required"></el-switch>
</el-form-item>
Expand Down Expand Up @@ -97,6 +106,7 @@ watch(dialogVisible, (bool) => {
type: typeOptions[0],
desc: '',
source: 'reference',
default_value: '',
is_required: true,
}
isEdit.value = false
Expand Down
2 changes: 1 addition & 1 deletion ui/src/workflow/nodes/tool-lib-node/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ const update_field = () => {
if (find_field && find_field.source == item.source) {
return { ...item, value: JSON.parse(JSON.stringify(find_field.value)) }
}
return { ...item, value: item.source == 'reference' ? [] : '' }
return { ...item, value: item.source === 'reference' ? [] : (item.default_value || '') }
})
set(props.nodeModel.properties.node_data, 'input_field_list', merge_input_field_list)
set(props.nodeModel.properties, 'status', ok.data.is_active ? 200 : 500)
Expand Down
2 changes: 1 addition & 1 deletion ui/src/workflow/nodes/tool-node/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ function refreshFieldList(data: any) {
const list = cloneDeep(props.nodeModel.properties.node_data.input_field_list)
const obj = {
...data,
value: data.source === 'reference' ? [] : '',
value: data.source === 'reference' ? [] : (data.default_value || ''),
}
if (currentIndex.value !== null) {
list.splice(currentIndex.value, 1, obj)
Expand Down
Loading