balibabu
commited on
Commit
·
79cd49c
1
Parent(s):
6fd4084
feat: Add component Invoke #2908 (#3067)
Browse files### What problem does this PR solve?
feat: Add component Invoke #2908
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
- web/package-lock.json +36 -0
- web/package.json +1 -0
- web/src/assets/svg/invoke-ai.svg +15 -0
- web/src/locales/en.ts +8 -0
- web/src/locales/zh-traditional.ts +8 -0
- web/src/locales/zh.ts +8 -0
- web/src/pages/flow/constant.tsx +22 -0
- web/src/pages/flow/flow-drawer/index.tsx +4 -0
- web/src/pages/flow/form/invoke-form/dynamic-variables.tsx +119 -0
- web/src/pages/flow/form/invoke-form/hooks.ts +87 -0
- web/src/pages/flow/form/invoke-form/index.less +21 -0
- web/src/pages/flow/form/invoke-form/index.tsx +72 -0
- web/src/pages/flow/hooks.ts +2 -0
- web/src/pages/flow/interface.ts +4 -0
web/package-lock.json
CHANGED
@@ -11,6 +11,7 @@
|
|
11 |
"@ant-design/pro-layout": "^7.17.16",
|
12 |
"@antv/g6": "^5.0.10",
|
13 |
"@js-preview/excel": "^1.7.8",
|
|
|
14 |
"@tanstack/react-query": "^5.40.0",
|
15 |
"@tanstack/react-query-devtools": "^5.51.5",
|
16 |
"ahooks": "^3.7.10",
|
@@ -3843,6 +3844,30 @@
|
|
3843 |
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz",
|
3844 |
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
3845 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3846 |
"node_modules/@mrmlnc/readdir-enhanced": {
|
3847 |
"version": "2.2.1",
|
3848 |
"resolved": "https://registry.npmmirror.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
@@ -19956,6 +19981,12 @@
|
|
19956 |
"node": "*"
|
19957 |
}
|
19958 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
19959 |
"node_modules/mri": {
|
19960 |
"version": "1.2.0",
|
19961 |
"resolved": "https://registry.npmmirror.com/mri/-/mri-1.2.0.tgz",
|
@@ -25827,6 +25858,11 @@
|
|
25827 |
"resolved": "https://registry.npmmirror.com/stackframe/-/stackframe-1.3.4.tgz",
|
25828 |
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
|
25829 |
},
|
|
|
|
|
|
|
|
|
|
|
25830 |
"node_modules/static-extend": {
|
25831 |
"version": "0.1.2",
|
25832 |
"resolved": "https://registry.npmmirror.com/static-extend/-/static-extend-0.1.2.tgz",
|
|
|
11 |
"@ant-design/pro-layout": "^7.17.16",
|
12 |
"@antv/g6": "^5.0.10",
|
13 |
"@js-preview/excel": "^1.7.8",
|
14 |
+
"@monaco-editor/react": "^4.6.0",
|
15 |
"@tanstack/react-query": "^5.40.0",
|
16 |
"@tanstack/react-query-devtools": "^5.51.5",
|
17 |
"ahooks": "^3.7.10",
|
|
|
3844 |
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz",
|
3845 |
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
3846 |
},
|
3847 |
+
"node_modules/@monaco-editor/loader": {
|
3848 |
+
"version": "1.4.0",
|
3849 |
+
"resolved": "https://registry.npmmirror.com/@monaco-editor/loader/-/loader-1.4.0.tgz",
|
3850 |
+
"integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==",
|
3851 |
+
"dependencies": {
|
3852 |
+
"state-local": "^1.0.6"
|
3853 |
+
},
|
3854 |
+
"peerDependencies": {
|
3855 |
+
"monaco-editor": ">= 0.21.0 < 1"
|
3856 |
+
}
|
3857 |
+
},
|
3858 |
+
"node_modules/@monaco-editor/react": {
|
3859 |
+
"version": "4.6.0",
|
3860 |
+
"resolved": "https://registry.npmmirror.com/@monaco-editor/react/-/react-4.6.0.tgz",
|
3861 |
+
"integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==",
|
3862 |
+
"dependencies": {
|
3863 |
+
"@monaco-editor/loader": "^1.4.0"
|
3864 |
+
},
|
3865 |
+
"peerDependencies": {
|
3866 |
+
"monaco-editor": ">= 0.25.0 < 1",
|
3867 |
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
3868 |
+
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
3869 |
+
}
|
3870 |
+
},
|
3871 |
"node_modules/@mrmlnc/readdir-enhanced": {
|
3872 |
"version": "2.2.1",
|
3873 |
"resolved": "https://registry.npmmirror.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
|
|
19981 |
"node": "*"
|
19982 |
}
|
19983 |
},
|
19984 |
+
"node_modules/monaco-editor": {
|
19985 |
+
"version": "0.52.0",
|
19986 |
+
"resolved": "https://registry.npmmirror.com/monaco-editor/-/monaco-editor-0.52.0.tgz",
|
19987 |
+
"integrity": "sha512-OeWhNpABLCeTqubfqLMXGsqf6OmPU6pHM85kF3dhy6kq5hnhuVS1p3VrEW/XhWHc71P2tHyS5JFySD8mgs1crw==",
|
19988 |
+
"peer": true
|
19989 |
+
},
|
19990 |
"node_modules/mri": {
|
19991 |
"version": "1.2.0",
|
19992 |
"resolved": "https://registry.npmmirror.com/mri/-/mri-1.2.0.tgz",
|
|
|
25858 |
"resolved": "https://registry.npmmirror.com/stackframe/-/stackframe-1.3.4.tgz",
|
25859 |
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
|
25860 |
},
|
25861 |
+
"node_modules/state-local": {
|
25862 |
+
"version": "1.0.7",
|
25863 |
+
"resolved": "https://registry.npmmirror.com/state-local/-/state-local-1.0.7.tgz",
|
25864 |
+
"integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="
|
25865 |
+
},
|
25866 |
"node_modules/static-extend": {
|
25867 |
"version": "0.1.2",
|
25868 |
"resolved": "https://registry.npmmirror.com/static-extend/-/static-extend-0.1.2.tgz",
|
web/package.json
CHANGED
@@ -22,6 +22,7 @@
|
|
22 |
"@ant-design/pro-layout": "^7.17.16",
|
23 |
"@antv/g6": "^5.0.10",
|
24 |
"@js-preview/excel": "^1.7.8",
|
|
|
25 |
"@tanstack/react-query": "^5.40.0",
|
26 |
"@tanstack/react-query-devtools": "^5.51.5",
|
27 |
"ahooks": "^3.7.10",
|
|
|
22 |
"@ant-design/pro-layout": "^7.17.16",
|
23 |
"@antv/g6": "^5.0.10",
|
24 |
"@js-preview/excel": "^1.7.8",
|
25 |
+
"@monaco-editor/react": "^4.6.0",
|
26 |
"@tanstack/react-query": "^5.40.0",
|
27 |
"@tanstack/react-query-devtools": "^5.51.5",
|
28 |
"ahooks": "^3.7.10",
|
web/src/assets/svg/invoke-ai.svg
ADDED
|
web/src/locales/en.ts
CHANGED
@@ -29,6 +29,7 @@ export default {
|
|
29 |
move: 'Move',
|
30 |
warn: 'Warn',
|
31 |
action: 'Action',
|
|
|
32 |
},
|
33 |
login: {
|
34 |
login: 'Sign in',
|
@@ -1016,6 +1017,13 @@ The above is the content you need to summarize.`,
|
|
1016 |
note: 'Note',
|
1017 |
noteDescription: 'Note',
|
1018 |
notePlaceholder: 'Please enter a note',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1019 |
},
|
1020 |
footer: {
|
1021 |
profile: 'All rights reserved @ React',
|
|
|
29 |
move: 'Move',
|
30 |
warn: 'Warn',
|
31 |
action: 'Action',
|
32 |
+
s: 'S',
|
33 |
},
|
34 |
login: {
|
35 |
login: 'Sign in',
|
|
|
1017 |
note: 'Note',
|
1018 |
noteDescription: 'Note',
|
1019 |
notePlaceholder: 'Please enter a note',
|
1020 |
+
invoke: 'Invoke',
|
1021 |
+
invokeDescription:
|
1022 |
+
'This component can invoke remote end point call. Put the output of other components as parameters or set constant parameters to call remote functions.',
|
1023 |
+
url: 'Url',
|
1024 |
+
method: 'Method',
|
1025 |
+
timeout: 'Timeout',
|
1026 |
+
headers: 'Headers',
|
1027 |
},
|
1028 |
footer: {
|
1029 |
profile: 'All rights reserved @ React',
|
web/src/locales/zh-traditional.ts
CHANGED
@@ -29,6 +29,7 @@ export default {
|
|
29 |
move: '移動',
|
30 |
warn: '提醒',
|
31 |
action: '操作',
|
|
|
32 |
},
|
33 |
login: {
|
34 |
login: '登入',
|
@@ -965,6 +966,13 @@ export default {
|
|
965 |
note: '註解',
|
966 |
noteDescription: '註解',
|
967 |
notePlaceholder: '請輸入註釋',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
968 |
},
|
969 |
footer: {
|
970 |
profile: '“保留所有權利 @ react”',
|
|
|
29 |
move: '移動',
|
30 |
warn: '提醒',
|
31 |
action: '操作',
|
32 |
+
s: '秒',
|
33 |
},
|
34 |
login: {
|
35 |
login: '登入',
|
|
|
966 |
note: '註解',
|
967 |
noteDescription: '註解',
|
968 |
notePlaceholder: '請輸入註釋',
|
969 |
+
invoke: 'Invoke',
|
970 |
+
invokeDescription:
|
971 |
+
'此元件可以呼叫遠端端點呼叫。將其他元件的輸出作為參數或設定常數參數來呼叫遠端函數。',
|
972 |
+
url: '網址',
|
973 |
+
method: '方法',
|
974 |
+
timeout: '超時',
|
975 |
+
headers: '請求頭',
|
976 |
},
|
977 |
footer: {
|
978 |
profile: '“保留所有權利 @ react”',
|
web/src/locales/zh.ts
CHANGED
@@ -29,6 +29,7 @@ export default {
|
|
29 |
move: '移动',
|
30 |
warn: '提醒',
|
31 |
action: '操作',
|
|
|
32 |
},
|
33 |
login: {
|
34 |
login: '登录',
|
@@ -985,6 +986,13 @@ export default {
|
|
985 |
note: '注释',
|
986 |
noteDescription: '注释',
|
987 |
notePlaceholder: '请输入注释',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
988 |
},
|
989 |
footer: {
|
990 |
profile: 'All rights reserved @ React',
|
|
|
29 |
move: '移动',
|
30 |
warn: '提醒',
|
31 |
action: '操作',
|
32 |
+
s: '秒',
|
33 |
},
|
34 |
login: {
|
35 |
login: '登录',
|
|
|
986 |
note: '注释',
|
987 |
noteDescription: '注释',
|
988 |
notePlaceholder: '请输入注释',
|
989 |
+
invoke: 'Invoke',
|
990 |
+
invokeDescription:
|
991 |
+
'该组件可以调用远程端点调用。将其他组件的输出作为参数或设置常量参数来调用远程函数。',
|
992 |
+
url: 'Url',
|
993 |
+
method: '方法',
|
994 |
+
timeout: '超时',
|
995 |
+
headers: '请求头',
|
996 |
},
|
997 |
footer: {
|
998 |
profile: 'All rights reserved @ React',
|
web/src/pages/flow/constant.tsx
CHANGED
@@ -12,6 +12,7 @@ import { ReactComponent as ExeSqlIcon } from '@/assets/svg/exesql.svg';
|
|
12 |
import { ReactComponent as GithubIcon } from '@/assets/svg/github.svg';
|
13 |
import { ReactComponent as GoogleScholarIcon } from '@/assets/svg/google-scholar.svg';
|
14 |
import { ReactComponent as GoogleIcon } from '@/assets/svg/google.svg';
|
|
|
15 |
import { ReactComponent as Jin10Icon } from '@/assets/svg/jin10.svg';
|
16 |
import { ReactComponent as KeywordIcon } from '@/assets/svg/keyword.svg';
|
17 |
import { ReactComponent as NoteIcon } from '@/assets/svg/note.svg';
|
@@ -75,6 +76,7 @@ export enum Operator {
|
|
75 |
TuShare = 'TuShare',
|
76 |
Note = 'Note',
|
77 |
Crawler = 'Crawler',
|
|
|
78 |
}
|
79 |
|
80 |
export const CommonOperatorList = Object.values(Operator).filter(
|
@@ -113,6 +115,7 @@ export const operatorIconMap = {
|
|
113 |
[Operator.TuShare]: TuShareIcon,
|
114 |
[Operator.Note]: NoteIcon,
|
115 |
[Operator.Crawler]: CrawlerIcon,
|
|
|
116 |
};
|
117 |
|
118 |
export const operatorMap: Record<
|
@@ -239,6 +242,9 @@ export const operatorMap: Record<
|
|
239 |
[Operator.Crawler]: {
|
240 |
backgroundColor: '#dee0e2',
|
241 |
},
|
|
|
|
|
|
|
242 |
};
|
243 |
|
244 |
export const componentMenuList = [
|
@@ -332,6 +338,9 @@ export const componentMenuList = [
|
|
332 |
{
|
333 |
name: Operator.Crawler,
|
334 |
},
|
|
|
|
|
|
|
335 |
];
|
336 |
|
337 |
export const initialRetrievalValues = {
|
@@ -509,6 +518,18 @@ export const initialCrawlerValues = {
|
|
509 |
extract_type: 'markdown',
|
510 |
};
|
511 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
512 |
export const CategorizeAnchorPointPositions = [
|
513 |
{ top: 1, right: 34 },
|
514 |
{ top: 8, right: 18 },
|
@@ -621,6 +642,7 @@ export const NodeMap = {
|
|
621 |
[Operator.TuShare]: 'ragNode',
|
622 |
[Operator.Note]: 'noteNode',
|
623 |
[Operator.Crawler]: 'ragNode',
|
|
|
624 |
};
|
625 |
|
626 |
export const LanguageOptions = [
|
|
|
12 |
import { ReactComponent as GithubIcon } from '@/assets/svg/github.svg';
|
13 |
import { ReactComponent as GoogleScholarIcon } from '@/assets/svg/google-scholar.svg';
|
14 |
import { ReactComponent as GoogleIcon } from '@/assets/svg/google.svg';
|
15 |
+
import { ReactComponent as InvokeIcon } from '@/assets/svg/invoke-ai.svg';
|
16 |
import { ReactComponent as Jin10Icon } from '@/assets/svg/jin10.svg';
|
17 |
import { ReactComponent as KeywordIcon } from '@/assets/svg/keyword.svg';
|
18 |
import { ReactComponent as NoteIcon } from '@/assets/svg/note.svg';
|
|
|
76 |
TuShare = 'TuShare',
|
77 |
Note = 'Note',
|
78 |
Crawler = 'Crawler',
|
79 |
+
Invoke = 'Invoke',
|
80 |
}
|
81 |
|
82 |
export const CommonOperatorList = Object.values(Operator).filter(
|
|
|
115 |
[Operator.TuShare]: TuShareIcon,
|
116 |
[Operator.Note]: NoteIcon,
|
117 |
[Operator.Crawler]: CrawlerIcon,
|
118 |
+
[Operator.Invoke]: InvokeIcon,
|
119 |
};
|
120 |
|
121 |
export const operatorMap: Record<
|
|
|
242 |
[Operator.Crawler]: {
|
243 |
backgroundColor: '#dee0e2',
|
244 |
},
|
245 |
+
[Operator.Invoke]: {
|
246 |
+
backgroundColor: '#dee0e2',
|
247 |
+
},
|
248 |
};
|
249 |
|
250 |
export const componentMenuList = [
|
|
|
338 |
{
|
339 |
name: Operator.Crawler,
|
340 |
},
|
341 |
+
{
|
342 |
+
name: Operator.Invoke,
|
343 |
+
},
|
344 |
];
|
345 |
|
346 |
export const initialRetrievalValues = {
|
|
|
518 |
extract_type: 'markdown',
|
519 |
};
|
520 |
|
521 |
+
export const initialInvokeValues = {
|
522 |
+
url: 'http://',
|
523 |
+
method: 'GET',
|
524 |
+
timeout: 60,
|
525 |
+
headers: `{
|
526 |
+
"Accept": "*/*",
|
527 |
+
"Cache-Control": "no-cache",
|
528 |
+
"Connection": "keep-alive"
|
529 |
+
}`,
|
530 |
+
proxy: 'http://',
|
531 |
+
};
|
532 |
+
|
533 |
export const CategorizeAnchorPointPositions = [
|
534 |
{ top: 1, right: 34 },
|
535 |
{ top: 8, right: 18 },
|
|
|
642 |
[Operator.TuShare]: 'ragNode',
|
643 |
[Operator.Note]: 'noteNode',
|
644 |
[Operator.Crawler]: 'ragNode',
|
645 |
+
[Operator.Invoke]: 'ragNode',
|
646 |
};
|
647 |
|
648 |
export const LanguageOptions = [
|
web/src/pages/flow/flow-drawer/index.tsx
CHANGED
@@ -20,6 +20,7 @@ import GenerateForm from '../form/generate-form';
|
|
20 |
import GithubForm from '../form/github-form';
|
21 |
import GoogleForm from '../form/google-form';
|
22 |
import GoogleScholarForm from '../form/google-scholar-form';
|
|
|
23 |
import Jin10Form from '../form/jin10-form';
|
24 |
import KeywordExtractForm from '../form/keyword-extract-form';
|
25 |
import MessageForm from '../form/message-form';
|
@@ -74,6 +75,9 @@ const FormMap = {
|
|
74 |
[Operator.Jin10]: Jin10Form,
|
75 |
[Operator.TuShare]: TuShareForm,
|
76 |
[Operator.Crawler]: CrawlerForm,
|
|
|
|
|
|
|
77 |
};
|
78 |
|
79 |
const EmptyContent = () => <div></div>;
|
|
|
20 |
import GithubForm from '../form/github-form';
|
21 |
import GoogleForm from '../form/google-form';
|
22 |
import GoogleScholarForm from '../form/google-scholar-form';
|
23 |
+
import InvokeForm from '../form/invoke-form';
|
24 |
import Jin10Form from '../form/jin10-form';
|
25 |
import KeywordExtractForm from '../form/keyword-extract-form';
|
26 |
import MessageForm from '../form/message-form';
|
|
|
75 |
[Operator.Jin10]: Jin10Form,
|
76 |
[Operator.TuShare]: TuShareForm,
|
77 |
[Operator.Crawler]: CrawlerForm,
|
78 |
+
[Operator.Invoke]: InvokeForm,
|
79 |
+
[Operator.Concentrator]: <></>,
|
80 |
+
[Operator.Note]: <></>,
|
81 |
};
|
82 |
|
83 |
const EmptyContent = () => <div></div>;
|
web/src/pages/flow/form/invoke-form/dynamic-variables.tsx
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { EditableCell, EditableRow } from '@/components/editable-cell';
|
2 |
+
import { useTranslate } from '@/hooks/common-hooks';
|
3 |
+
import { DeleteOutlined } from '@ant-design/icons';
|
4 |
+
import { Button, Flex, Input, Select, Table, TableProps } from 'antd';
|
5 |
+
import { useBuildComponentIdSelectOptions } from '../../hooks';
|
6 |
+
import { IInvokeVariable } from '../../interface';
|
7 |
+
import { useHandleOperateParameters } from './hooks';
|
8 |
+
|
9 |
+
import { trim } from 'lodash';
|
10 |
+
import styles from './index.less';
|
11 |
+
|
12 |
+
interface IProps {
|
13 |
+
nodeId?: string;
|
14 |
+
}
|
15 |
+
|
16 |
+
const components = {
|
17 |
+
body: {
|
18 |
+
row: EditableRow,
|
19 |
+
cell: EditableCell,
|
20 |
+
},
|
21 |
+
};
|
22 |
+
|
23 |
+
const DynamicVariables = ({ nodeId }: IProps) => {
|
24 |
+
const { t } = useTranslate('flow');
|
25 |
+
|
26 |
+
const options = useBuildComponentIdSelectOptions(nodeId);
|
27 |
+
const {
|
28 |
+
dataSource,
|
29 |
+
handleAdd,
|
30 |
+
handleRemove,
|
31 |
+
handleSave,
|
32 |
+
handleComponentIdChange,
|
33 |
+
handleValueChange,
|
34 |
+
} = useHandleOperateParameters(nodeId!);
|
35 |
+
|
36 |
+
const columns: TableProps<IInvokeVariable>['columns'] = [
|
37 |
+
{
|
38 |
+
title: t('key'),
|
39 |
+
dataIndex: 'key',
|
40 |
+
key: 'key',
|
41 |
+
// width: 40,
|
42 |
+
onCell: (record: IInvokeVariable) => ({
|
43 |
+
record,
|
44 |
+
editable: true,
|
45 |
+
dataIndex: 'key',
|
46 |
+
title: 'key',
|
47 |
+
handleSave,
|
48 |
+
}),
|
49 |
+
},
|
50 |
+
{
|
51 |
+
title: t('componentId'),
|
52 |
+
dataIndex: 'component_id',
|
53 |
+
key: 'component_id',
|
54 |
+
align: 'center',
|
55 |
+
width: 140,
|
56 |
+
render(text, record) {
|
57 |
+
return (
|
58 |
+
<Select
|
59 |
+
style={{ width: '100%' }}
|
60 |
+
allowClear
|
61 |
+
options={options}
|
62 |
+
value={text}
|
63 |
+
disabled={trim(record.value) !== ''}
|
64 |
+
onChange={handleComponentIdChange(record)}
|
65 |
+
/>
|
66 |
+
);
|
67 |
+
},
|
68 |
+
},
|
69 |
+
{
|
70 |
+
title: t('value'),
|
71 |
+
dataIndex: 'value',
|
72 |
+
key: 'value',
|
73 |
+
align: 'center',
|
74 |
+
width: 140,
|
75 |
+
render(text, record) {
|
76 |
+
return (
|
77 |
+
<Input
|
78 |
+
value={text}
|
79 |
+
disabled={!!record.component_id}
|
80 |
+
onChange={handleValueChange(record)}
|
81 |
+
/>
|
82 |
+
);
|
83 |
+
},
|
84 |
+
},
|
85 |
+
{
|
86 |
+
title: t('operation'),
|
87 |
+
dataIndex: 'operation',
|
88 |
+
width: 20,
|
89 |
+
key: 'operation',
|
90 |
+
align: 'center',
|
91 |
+
fixed: 'right',
|
92 |
+
render(_, record) {
|
93 |
+
return <DeleteOutlined onClick={handleRemove(record.id)} />;
|
94 |
+
},
|
95 |
+
},
|
96 |
+
];
|
97 |
+
|
98 |
+
return (
|
99 |
+
<section>
|
100 |
+
<Flex justify="end">
|
101 |
+
<Button size="small" onClick={handleAdd}>
|
102 |
+
{t('add')}
|
103 |
+
</Button>
|
104 |
+
</Flex>
|
105 |
+
<Table
|
106 |
+
dataSource={dataSource}
|
107 |
+
columns={columns}
|
108 |
+
rowKey={'id'}
|
109 |
+
className={styles.variableTable}
|
110 |
+
components={components}
|
111 |
+
rowClassName={() => styles.editableRow}
|
112 |
+
scroll={{ x: true }}
|
113 |
+
bordered
|
114 |
+
/>
|
115 |
+
</section>
|
116 |
+
);
|
117 |
+
};
|
118 |
+
|
119 |
+
export default DynamicVariables;
|
web/src/pages/flow/form/invoke-form/hooks.ts
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import get from 'lodash/get';
|
2 |
+
import { ChangeEventHandler, useCallback, useMemo } from 'react';
|
3 |
+
import { v4 as uuid } from 'uuid';
|
4 |
+
import { IGenerateParameter, IInvokeVariable } from '../../interface';
|
5 |
+
import useGraphStore from '../../store';
|
6 |
+
|
7 |
+
export const useHandleOperateParameters = (nodeId: string) => {
|
8 |
+
const { getNode, updateNodeForm } = useGraphStore((state) => state);
|
9 |
+
const node = getNode(nodeId);
|
10 |
+
const dataSource: IGenerateParameter[] = useMemo(
|
11 |
+
() => get(node, 'data.form.variables', []) as IGenerateParameter[],
|
12 |
+
[node],
|
13 |
+
);
|
14 |
+
|
15 |
+
const changeValue = useCallback(
|
16 |
+
(row: IInvokeVariable, field: string, value: string) => {
|
17 |
+
const newData = [...dataSource];
|
18 |
+
const index = newData.findIndex((item) => row.id === item.id);
|
19 |
+
const item = newData[index];
|
20 |
+
newData.splice(index, 1, {
|
21 |
+
...item,
|
22 |
+
[field]: value,
|
23 |
+
});
|
24 |
+
|
25 |
+
updateNodeForm(nodeId, { variables: newData });
|
26 |
+
},
|
27 |
+
[dataSource, nodeId, updateNodeForm],
|
28 |
+
);
|
29 |
+
|
30 |
+
const handleComponentIdChange = useCallback(
|
31 |
+
(row: IInvokeVariable) => (value: string) => {
|
32 |
+
changeValue(row, 'component_id', value);
|
33 |
+
},
|
34 |
+
[changeValue],
|
35 |
+
);
|
36 |
+
|
37 |
+
const handleValueChange = useCallback(
|
38 |
+
(row: IInvokeVariable): ChangeEventHandler<HTMLInputElement> =>
|
39 |
+
(e) => {
|
40 |
+
changeValue(row, 'value', e.target.value);
|
41 |
+
},
|
42 |
+
[changeValue],
|
43 |
+
);
|
44 |
+
|
45 |
+
const handleRemove = useCallback(
|
46 |
+
(id?: string) => () => {
|
47 |
+
const newData = dataSource.filter((item) => item.id !== id);
|
48 |
+
updateNodeForm(nodeId, { variables: newData });
|
49 |
+
},
|
50 |
+
[updateNodeForm, nodeId, dataSource],
|
51 |
+
);
|
52 |
+
|
53 |
+
const handleAdd = useCallback(() => {
|
54 |
+
updateNodeForm(nodeId, {
|
55 |
+
variables: [
|
56 |
+
...dataSource,
|
57 |
+
{
|
58 |
+
id: uuid(),
|
59 |
+
key: '',
|
60 |
+
component_id: undefined,
|
61 |
+
value: '',
|
62 |
+
},
|
63 |
+
],
|
64 |
+
});
|
65 |
+
}, [dataSource, nodeId, updateNodeForm]);
|
66 |
+
|
67 |
+
const handleSave = (row: IGenerateParameter) => {
|
68 |
+
const newData = [...dataSource];
|
69 |
+
const index = newData.findIndex((item) => row.id === item.id);
|
70 |
+
const item = newData[index];
|
71 |
+
newData.splice(index, 1, {
|
72 |
+
...item,
|
73 |
+
...row,
|
74 |
+
});
|
75 |
+
|
76 |
+
updateNodeForm(nodeId, { variables: newData });
|
77 |
+
};
|
78 |
+
|
79 |
+
return {
|
80 |
+
handleAdd,
|
81 |
+
handleRemove,
|
82 |
+
handleComponentIdChange,
|
83 |
+
handleValueChange,
|
84 |
+
handleSave,
|
85 |
+
dataSource,
|
86 |
+
};
|
87 |
+
};
|
web/src/pages/flow/form/invoke-form/index.less
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.variableTable {
|
2 |
+
margin-top: 14px;
|
3 |
+
}
|
4 |
+
.editableRow {
|
5 |
+
:global(.editable-cell) {
|
6 |
+
position: relative;
|
7 |
+
}
|
8 |
+
|
9 |
+
:global(.editable-cell-value-wrap) {
|
10 |
+
padding: 5px 12px;
|
11 |
+
cursor: pointer;
|
12 |
+
height: 30px !important;
|
13 |
+
}
|
14 |
+
&:hover {
|
15 |
+
:global(.editable-cell-value-wrap) {
|
16 |
+
padding: 4px 11px;
|
17 |
+
border: 1px solid #d9d9d9;
|
18 |
+
border-radius: 2px;
|
19 |
+
}
|
20 |
+
}
|
21 |
+
}
|
web/src/pages/flow/form/invoke-form/index.tsx
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import Editor from '@monaco-editor/react';
|
2 |
+
import { Form, Input, InputNumber, Select, Space } from 'antd';
|
3 |
+
import { useTranslation } from 'react-i18next';
|
4 |
+
import { useSetLlmSetting } from '../../hooks';
|
5 |
+
import { IOperatorForm } from '../../interface';
|
6 |
+
import DynamicVariables from './dynamic-variables';
|
7 |
+
|
8 |
+
enum Method {
|
9 |
+
GET = 'GET',
|
10 |
+
POST = 'POST',
|
11 |
+
PUT = 'PUT',
|
12 |
+
}
|
13 |
+
|
14 |
+
const MethodOptions = [Method.GET, Method.POST, Method.PUT].map((x) => ({
|
15 |
+
label: x,
|
16 |
+
value: x,
|
17 |
+
}));
|
18 |
+
|
19 |
+
interface TimeoutInputProps {
|
20 |
+
value?: number;
|
21 |
+
onChange?: (value: number | null) => void;
|
22 |
+
}
|
23 |
+
|
24 |
+
const TimeoutInput = ({ value, onChange }: TimeoutInputProps) => {
|
25 |
+
const { t } = useTranslation();
|
26 |
+
return (
|
27 |
+
<Space>
|
28 |
+
<InputNumber value={value} onChange={onChange} /> {t('common.s')}
|
29 |
+
</Space>
|
30 |
+
);
|
31 |
+
};
|
32 |
+
|
33 |
+
const InvokeForm = ({ onValuesChange, form, node }: IOperatorForm) => {
|
34 |
+
const { t } = useTranslation();
|
35 |
+
|
36 |
+
useSetLlmSetting(form);
|
37 |
+
|
38 |
+
return (
|
39 |
+
<>
|
40 |
+
<Form
|
41 |
+
name="basic"
|
42 |
+
autoComplete="off"
|
43 |
+
form={form}
|
44 |
+
onValuesChange={onValuesChange}
|
45 |
+
layout={'vertical'}
|
46 |
+
>
|
47 |
+
<Form.Item name={'url'} label={t('flow.url')}>
|
48 |
+
<Input />
|
49 |
+
</Form.Item>
|
50 |
+
<Form.Item
|
51 |
+
name={'method'}
|
52 |
+
label={t('flow.method')}
|
53 |
+
initialValue={Method.GET}
|
54 |
+
>
|
55 |
+
<Select options={MethodOptions} />
|
56 |
+
</Form.Item>
|
57 |
+
<Form.Item name={'timeout'} label={t('flow.timeout')}>
|
58 |
+
<TimeoutInput></TimeoutInput>
|
59 |
+
</Form.Item>
|
60 |
+
<Form.Item name={'headers'} label={t('flow.headers')}>
|
61 |
+
<Editor height={200} defaultLanguage="json" theme="vs-dark" />
|
62 |
+
</Form.Item>
|
63 |
+
<Form.Item name={'proxy'} label={t('flow.proxy')}>
|
64 |
+
<Input />
|
65 |
+
</Form.Item>
|
66 |
+
<DynamicVariables nodeId={node?.id}></DynamicVariables>
|
67 |
+
</Form>
|
68 |
+
</>
|
69 |
+
);
|
70 |
+
};
|
71 |
+
|
72 |
+
export default InvokeForm;
|
web/src/pages/flow/hooks.ts
CHANGED
@@ -49,6 +49,7 @@ import {
|
|
49 |
initialGithubValues,
|
50 |
initialGoogleScholarValues,
|
51 |
initialGoogleValues,
|
|
|
52 |
initialJin10Values,
|
53 |
initialKeywordExtractValues,
|
54 |
initialMessageValues,
|
@@ -132,6 +133,7 @@ export const useInitializeOperatorParams = () => {
|
|
132 |
[Operator.TuShare]: initialTuShareValues,
|
133 |
[Operator.Note]: initialNoteValues,
|
134 |
[Operator.Crawler]: initialCrawlerValues,
|
|
|
135 |
};
|
136 |
}, [llmId]);
|
137 |
|
|
|
49 |
initialGithubValues,
|
50 |
initialGoogleScholarValues,
|
51 |
initialGoogleValues,
|
52 |
+
initialInvokeValues,
|
53 |
initialJin10Values,
|
54 |
initialKeywordExtractValues,
|
55 |
initialMessageValues,
|
|
|
133 |
[Operator.TuShare]: initialTuShareValues,
|
134 |
[Operator.Note]: initialNoteValues,
|
135 |
[Operator.Crawler]: initialCrawlerValues,
|
136 |
+
[Operator.Invoke]: initialInvokeValues,
|
137 |
};
|
138 |
}, [llmId]);
|
139 |
|
web/src/pages/flow/interface.ts
CHANGED
@@ -51,6 +51,10 @@ export interface IGenerateParameter {
|
|
51 |
component_id?: string;
|
52 |
}
|
53 |
|
|
|
|
|
|
|
|
|
54 |
export type ICategorizeItemResult = Record<
|
55 |
string,
|
56 |
Omit<ICategorizeItem, 'name'>
|
|
|
51 |
component_id?: string;
|
52 |
}
|
53 |
|
54 |
+
export interface IInvokeVariable extends IGenerateParameter {
|
55 |
+
value?: string;
|
56 |
+
}
|
57 |
+
|
58 |
export type ICategorizeItemResult = Record<
|
59 |
string,
|
60 |
Omit<ICategorizeItem, 'name'>
|