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 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'>