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
15 changes: 7 additions & 8 deletions packages/global/core/app/httpTools/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import { i18nT } from '../../../../web/i18n/utils';
export const getHTTPToolSetRuntimeNode = ({
name,
avatar,
baseUrl = '',
customHeaders = '',
apiSchemaStr = '',
baseUrl,
customHeaders,
apiSchemaStr,
toolList = [],
headerSecret
}: {
Expand All @@ -34,12 +34,11 @@ export const getHTTPToolSetRuntimeNode = ({
intro: 'HTTP Tools',
toolConfig: {
httpToolSet: {
baseUrl,
toolList,
headerSecret,
customHeaders,
apiSchemaStr,
toolId: ''
...(baseUrl !== undefined && { baseUrl }),
...(apiSchemaStr !== undefined && { apiSchemaStr }),
...(customHeaders !== undefined && { customHeaders }),
...(headerSecret !== undefined && { headerSecret })
}
},
inputs: [],
Expand Down
11 changes: 11 additions & 0 deletions packages/global/core/app/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { FlowNodeTemplateType, StoreNodeItemType } from '../workflow/type/n
import type { AppTypeEnum } from './constants';
import { PermissionTypeEnum } from '../../support/permission/constant';
import type {
ContentTypes,
NodeInputKeyEnum,
VariableInputEnum,
WorkflowIOValueTypeEnum
Expand Down Expand Up @@ -127,6 +128,16 @@ export type HttpToolConfigType = {
outputSchema: JSONSchemaOutputType;
path: string;
method: string;

// manual
staticParams?: Array<{ key: string; value: string }>;
staticHeaders?: Array<{ key: string; value: string }>;
staticBody?: {
type: ContentTypes;
content?: string;
formData?: Array<{ key: string; value: string }>;
};
headerSecret?: StoreSecretValueType;
};

/* app chat config type */
Expand Down
13 changes: 13 additions & 0 deletions packages/global/core/workflow/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,19 @@ export enum ContentTypes {
raw = 'raw-text'
}

export const contentTypeMap = {
[ContentTypes.none]: '',
[ContentTypes.formData]: '',
[ContentTypes.xWwwFormUrlencoded]: 'application/x-www-form-urlencoded',
[ContentTypes.json]: 'application/json',
[ContentTypes.xml]: 'application/xml',
[ContentTypes.raw]: 'text/plain'
};

// http request methods
export const HTTP_METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] as const;
export type HttpMethod = (typeof HTTP_METHODS)[number];

export const ArrayTypeMap: Record<WorkflowIOValueTypeEnum, WorkflowIOValueTypeEnum> = {
[WorkflowIOValueTypeEnum.string]: WorkflowIOValueTypeEnum.arrayString,
[WorkflowIOValueTypeEnum.number]: WorkflowIOValueTypeEnum.arrayNumber,
Expand Down
7 changes: 3 additions & 4 deletions packages/global/core/workflow/type/node.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,10 @@ export type NodeToolConfigType = {
}[];
};
httpToolSet?: {
toolId: string;
baseUrl: string;
toolList: HttpToolConfigType[];
apiSchemaStr: string;
customHeaders: string;
baseUrl?: string;
apiSchemaStr?: string;
customHeaders?: string;
headerSecret?: StoreSecretValueType;
};
httpTool?: {
Expand Down
130 changes: 112 additions & 18 deletions packages/service/core/app/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { getSecretValue } from '../../common/secret/utils';
import axios from 'axios';
import { getErrText } from '@fastgpt/global/common/error/utils';
import type { RequireOnlyOne } from '@fastgpt/global/common/type/utils';
import type { HttpToolConfigType } from '@fastgpt/global/core/app/type';
import { contentTypeMap, ContentTypes } from '@fastgpt/global/core/workflow/constants';

export type RunHTTPToolParams = {
baseUrl: string;
Expand All @@ -11,48 +13,140 @@ export type RunHTTPToolParams = {
params: Record<string, any>;
headerSecret?: StoreSecretValueType;
customHeaders?: Record<string, string>;
staticParams?: HttpToolConfigType['staticParams'];
staticHeaders?: HttpToolConfigType['staticHeaders'];
staticBody?: HttpToolConfigType['staticBody'];
};

export type RunHTTPToolResult = RequireOnlyOne<{
data?: any;
errorMsg?: string;
}>;

export async function runHTTPTool({
const buildHttpRequest = ({
method,
params,
headerSecret,
customHeaders,
staticParams,
staticHeaders,
staticBody
}: Omit<RunHTTPToolParams, 'baseUrl' | 'toolPath'>) => {
const body = (() => {
if (!staticBody || staticBody.type === ContentTypes.none) {
return ['POST', 'PUT', 'PATCH'].includes(method.toUpperCase()) ? params : undefined;
}

if (staticBody.type === ContentTypes.json) {
const staticContent = staticBody.content ? JSON.parse(staticBody.content) : {};
return { ...staticContent, ...params };
}

if (staticBody.type === ContentTypes.formData) {
const formData = new (require('form-data'))();
staticBody.formData?.forEach(({ key, value }) => {
formData.append(key, value);
});
Object.entries(params).forEach(([key, value]) => {
formData.append(key, value);
});
return formData;
}

if (staticBody.type === ContentTypes.xWwwFormUrlencoded) {
const urlencoded = new URLSearchParams();
staticBody.formData?.forEach(({ key, value }) => {
urlencoded.append(key, value);
});
Object.entries(params).forEach(([key, value]) => {
urlencoded.append(key, String(value));
});
return urlencoded.toString();
}

if (staticBody.type === ContentTypes.xml || staticBody.type === ContentTypes.raw) {
return staticBody.content || '';
}

return undefined;
})();

const contentType = contentTypeMap[staticBody?.type || ContentTypes.none];
const headers = {
...(contentType && { 'Content-Type': contentType }),
...(customHeaders || {}),
...(headerSecret ? getSecretValue({ storeSecret: headerSecret }) : {}),
...(staticHeaders?.reduce(
(acc, { key, value }) => {
acc[key] = value;
return acc;
},
{} as Record<string, string>
) || {})
};

const queryParams = (() => {
const staticParamsObj =
staticParams?.reduce(
(acc, { key, value }) => {
acc[key] = value;
return acc;
},
{} as Record<string, any>
) || {};

const mergedParams =
method.toUpperCase() === 'GET' || staticParams
? { ...staticParamsObj, ...params }
: staticParamsObj;

return Object.keys(mergedParams).length > 0 ? mergedParams : undefined;
})();

return {
headers,
body,
queryParams
};
};

export const runHTTPTool = async ({
baseUrl,
toolPath,
method = 'POST',
params,
headerSecret,
customHeaders
}: RunHTTPToolParams): Promise<RunHTTPToolResult> {
customHeaders,
staticParams,
staticHeaders,
staticBody
}: RunHTTPToolParams): Promise<RunHTTPToolResult> => {
try {
const headers = {
'Content-Type': 'application/json',
...(customHeaders || {}),
...(headerSecret ? getSecretValue({ storeSecret: headerSecret }) : {})
};
const { headers, body, queryParams } = buildHttpRequest({
method,
params,
headerSecret,
customHeaders,
staticParams,
staticHeaders,
staticBody
});

const { data } = await axios({
method: method.toUpperCase(),
baseURL: baseUrl.startsWith('https://') ? baseUrl : `https://${baseUrl}`,
url: toolPath,
headers,
data: params,
params,
data: body,
params: queryParams,
timeout: 300000,
httpsAgent: new (require('https').Agent)({
rejectUnauthorized: false
})
});

return {
data
};
return { data };
} catch (error: any) {
console.log(error);
return {
errorMsg: getErrText(error)
};
return { errorMsg: getErrText(error) };
}
}
};
9 changes: 6 additions & 3 deletions packages/service/core/workflow/dispatch/child/runTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,16 +236,19 @@ export const dispatchRunTool = async (props: RunToolProps): Promise<RunToolRespo
}

const { data, errorMsg } = await runHTTPTool({
baseUrl: baseUrl,
baseUrl: baseUrl || '',
toolPath: httpTool.path,
method: httpTool.method,
params,
headerSecret,
headerSecret: httpTool.headerSecret || headerSecret,
customHeaders: customHeaders
? typeof customHeaders === 'string'
? JSON.parse(customHeaders)
: customHeaders
: undefined
: undefined,
staticParams: httpTool.staticParams,
staticHeaders: httpTool.staticHeaders,
staticBody: httpTool.staticBody
});

if (errorMsg) {
Expand Down
10 changes: 1 addition & 9 deletions packages/service/core/workflow/dispatch/tools/http468.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { getErrText } from '@fastgpt/global/common/error/utils';
import {
contentTypeMap,
ContentTypes,
NodeInputKeyEnum,
NodeOutputKeyEnum,
Expand Down Expand Up @@ -59,15 +60,6 @@ type HttpResponse = DispatchNodeResultType<

const UNDEFINED_SIGN = 'UNDEFINED_SIGN';

const contentTypeMap = {
[ContentTypes.none]: '',
[ContentTypes.formData]: '',
[ContentTypes.xWwwFormUrlencoded]: 'application/x-www-form-urlencoded',
[ContentTypes.json]: 'application/json',
[ContentTypes.xml]: 'application/xml',
[ContentTypes.raw]: 'text/plain'
};

export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<HttpResponse> => {
let {
runningAppInfo: { id: appId, teamId, tmbId },
Expand Down
5 changes: 3 additions & 2 deletions packages/web/components/common/Radio/LeftRadio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const LeftRadio = <T = any,>({
align = 'center',
px = 3.5,
py = 4,
gridGap = [3, 5],
defaultBg = 'myGray.50',
activeBg = 'primary.50',
onChange,
Expand Down Expand Up @@ -75,7 +76,7 @@ const LeftRadio = <T = any,>({
);

return (
<Grid gridGap={[3, 5]} fontSize={['sm', 'md']} {...props}>
<Grid gridGap={gridGap} fontSize={['sm', 'md']} {...props}>
{list.map((item) => {
const isActive = value === item.value;
return (
Expand Down Expand Up @@ -131,7 +132,7 @@ const LeftRadio = <T = any,>({
lineHeight={1}
color={'myGray.900'}
>
<Box>{t(item.title as any)}</Box>
<Box mb={1}>{t(item.title as any)}</Box>
{!!item.tooltip && <QuestionTip label={item.tooltip} color={'myGray.600'} />}
</HStack>
) : (
Expand Down
7 changes: 7 additions & 0 deletions packages/web/i18n/en/app.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"Add_tool": "Add tool",
"AutoOptimize": "Automatic optimization",
"Click_to_delete_this_field": "Click to delete this field",
"Custom_params": "Custom parameters",
"Edit_tool": "Edit tool",
"Filed_is_deprecated": "This field is deprecated",
"HTTPTools_Create_Type": "Create Type",
"HTTPTools_Create_Type_Tip": "Modification is not supported after selection",
"HTTP_tools_list_with_number": "Tool list: {{total}}",
"Index": "Index",
"MCP_tools_debug": "debug",
Expand Down Expand Up @@ -30,6 +35,7 @@
"Selected": "Selected",
"Start_config": "Start configuration",
"Team_Tags": "Team tags",
"Tool_name": "Tool name",
"ai_point_price": "Billing",
"ai_settings": "AI Configuration",
"all_apps": "All Applications",
Expand Down Expand Up @@ -283,6 +289,7 @@
"tool_detail": "Tool details",
"tool_input_param_tip": "This plugin requires configuration of related information to run properly.",
"tool_not_active": "This tool has not been activated yet",
"tool_params_description_tips": "The description of parameter functions, if used as tool invocation parameters, affects the model tool invocation effect.",
"tool_run_free": "This tool runs without points consumption",
"tool_tip": "When executed as a tool, is this field used as a tool response result?",
"tool_type_tools": "tool",
Expand Down
9 changes: 9 additions & 0 deletions packages/web/i18n/zh-CN/app.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"Add_tool": "添加工具",
"AutoOptimize": "自动优化",
"Click_to_delete_this_field": "点击删除该字段",
"Custom_params": "自定义参数",
"Edit_tool": "编辑工具",
"Filed_is_deprecated": "该字段已弃用",
"HTTPTools_Create_Type": "创建方式",
"HTTPTools_Create_Type_Tip": "选择后不支持修改",
"HTTP_tools_detail": "查看详情",
"HTTP_tools_list_with_number": "工具列表: {{total}}",
"Index": "索引",
Expand Down Expand Up @@ -31,6 +36,8 @@
"Selected": "已选择",
"Start_config": "开始配置",
"Team_Tags": "团队标签",
"Tool_description": "工具描述",
"Tool_name": "工具名称",
"ai_point_price": "AI积分计费",
"ai_settings": "AI 配置",
"all_apps": "全部应用",
Expand Down Expand Up @@ -90,6 +97,7 @@
"document_upload": "文档上传",
"edit_app": "应用详情",
"edit_info": "编辑信息",
"edit_param": "编辑参数",
"execute_time": "执行时间",
"export_config_successful": "已复制配置,自动过滤部分敏感信息,请注意检查是否仍有敏感数据",
"export_configs": "导出配置",
Expand Down Expand Up @@ -297,6 +305,7 @@
"tool_detail": "工具详情",
"tool_input_param_tip": "该插件正常运行需要配置相关信息",
"tool_not_active": "该工具尚未激活",
"tool_params_description_tips": "参数功能的描述,若作为工具调用参数,影响模型工具调用效果",
"tool_run_free": "该工具运行无积分消耗",
"tool_tip": "作为工具执行时,该字段是否作为工具响应结果",
"tool_type_tools": "工具",
Expand Down
Loading
Loading