From c25cc9d5897345967a203131a887a36d2ccff176 Mon Sep 17 00:00:00 2001
From: "yukun.wyk"
Date: Tue, 27 Aug 2024 13:17:19 +0800
Subject: [PATCH 01/78] chore(flow): initialize
---
web/packages/magent-flow/.eslintrc.mjs | 3 +
web/packages/magent-flow/.fatherrc.ts | 9 +
web/packages/magent-flow/.gitignore | 1 +
web/packages/magent-flow/.stylelintignore | 1 +
web/packages/magent-flow/CHANGELOG.md | 402 ++++++++++++++++++
web/packages/magent-flow/README.md | 280 ++++++++++++
web/packages/magent-flow/babel.config.json | 20 +
web/packages/magent-flow/jest.config.mjs | 6 +
web/packages/magent-flow/package.json | 78 ++++
.../magent-flow/src/FormSchema/index.ts | 331 ++++++++++++++
web/packages/magent-flow/src/RefForm/index.md | 31 ++
.../magent-flow/src/RefForm/index.tsx | 292 +++++++++++++
.../magent-flow/src/SchemaConfigForm/index.md | 29 ++
.../src/SchemaConfigForm/index.tsx | 369 ++++++++++++++++
web/packages/magent-flow/src/common/icons.ts | 3 +
.../AIBasic/CascaderInNode/index.tsx | 14 +
.../AIBasic/CollapseWrapper/index.tsx | 30 ++
.../OutputVariable/index.tsx | 14 +
.../AIBasic/PromptEditor/constants.tsx | 3 +
.../components/AIBasic/PromptEditor/hooks.ts | 58 +++
.../components/AIBasic/PromptEditor/index.tsx | 127 ++++++
.../plugins/component-picker-block/hooks.tsx | 185 ++++++++
.../plugins/component-picker-block/index.tsx | 168 ++++++++
.../plugins/component-picker-block/menu.tsx | 33 ++
.../component-picker-block/prompt-option.tsx | 53 +++
.../variable-option.tsx | 61 +++
.../PromptEditor/plugins/custom-text/node.tsx | 53 +++
.../plugins/on-blur-or-focus-block.tsx | 53 +++
.../PromptEditor/plugins/placeholder.tsx | 26 ++
.../PromptEditor/plugins/update-block.tsx | 45 ++
.../plugins/variable-block/index.tsx | 46 ++
.../plugins/variable-value-block/index.tsx | 55 +++
.../plugins/variable-value-block/node.tsx | 65 +++
.../plugins/variable-value-block/utils.ts | 5 +
.../components/AIBasic/PromptEditor/types.ts | 28 ++
.../components/AIBasic/PromptEditor/utils.ts | 260 +++++++++++
.../components/AIBasic/SelectInNode/index.tsx | 13 +
.../src/components/CustomEdge/index.tsx | 61 +++
.../magent-flow/src/components/Flow/index.tsx | 168 ++++++++
.../magent-flow/src/components/Flow/keys.ts | 116 +++++
.../src/components/FlowController/index.tsx | 18 +
.../src/components/FlowWithPanel/index.tsx | 242 +++++++++++
.../FlowWithPanel/nodeTemplate.yaml | 171 ++++++++
.../src/components/Node/AgentNode/index.tsx | 53 +++
.../src/components/Node/CommonNode/index.tsx | 34 ++
.../src/components/Node/EndNode/index.tsx | 34 ++
.../src/components/Node/IfElseNode/index.tsx | 76 ++++
.../components/Node/KnowledgeNode/index.tsx | 84 ++++
.../src/components/Node/LLMNode/index.tsx | 120 ++++++
.../Node/NodeWrapper/Header/index.tsx | 18 +
.../Node/NodeWrapper/Status/index.tsx | 73 ++++
.../src/components/Node/NodeWrapper/index.tsx | 91 ++++
.../src/components/Node/StartNode/index.tsx | 34 ++
.../magent-flow/src/components/Node/index.tsx | 0
.../src/components/NodePanel/index.tsx | 70 +++
.../src/components/RefForm/index.md | 31 ++
.../src/components/ReferenceForm/index.tsx | 117 +++++
.../src/components/ReferenceSelect/index.tsx | 61 +++
.../src/components/VariableForm/index.tsx | 148 +++++++
.../magent-flow/src/constants/constant.ts | 96 +++++
.../magent-flow/src/context/event-emitter.tsx | 30 ++
web/packages/magent-flow/src/index.ts | 8 +
.../magent-flow/src/interfaces/flow.ts | 108 +++++
.../magent-flow/src/spec/FormSchema/index.ts | 328 ++++++++++++++
.../src/spec/__snapshots__/node.test.ts.snap | 65 +++
.../magent-flow/src/spec/node.test.ts | 199 +++++++++
web/packages/magent-flow/src/spec/node.ts | 82 ++++
.../magent-flow/src/spec/test-jsonschema.json | 87 ++++
web/packages/magent-flow/src/spec/uuid.ts | 21 +
.../magent-flow/src/stores/useFlowStore.ts | 324 ++++++++++++++
.../src/stores/useKnowledgeStore.ts | 19 +
.../magent-flow/src/stores/useModelStore.ts | 33 ++
.../src/stores/useShortcutsStore.ts | 86 ++++
.../src/stores/useUndoRedoStore.ts | 101 +++++
web/packages/magent-flow/src/tailwind.css | 4 +
web/packages/magent-flow/src/utils/basic.ts | 8 +
web/packages/magent-flow/src/utils/index.tsx | 2 +
.../magent-flow/src/utils/reactflowUtils.ts | 13 +
.../magent-flow/src/utils/wrappedClass.ts | 4 +
web/packages/magent-flow/tailwind.config.js | 7 +
web/packages/magent-flow/tsconfig.json | 14 +
81 files changed, 6709 insertions(+)
create mode 100644 web/packages/magent-flow/.eslintrc.mjs
create mode 100644 web/packages/magent-flow/.fatherrc.ts
create mode 100644 web/packages/magent-flow/.gitignore
create mode 100644 web/packages/magent-flow/.stylelintignore
create mode 100644 web/packages/magent-flow/CHANGELOG.md
create mode 100644 web/packages/magent-flow/README.md
create mode 100644 web/packages/magent-flow/babel.config.json
create mode 100644 web/packages/magent-flow/jest.config.mjs
create mode 100644 web/packages/magent-flow/package.json
create mode 100644 web/packages/magent-flow/src/FormSchema/index.ts
create mode 100644 web/packages/magent-flow/src/RefForm/index.md
create mode 100644 web/packages/magent-flow/src/RefForm/index.tsx
create mode 100644 web/packages/magent-flow/src/SchemaConfigForm/index.md
create mode 100644 web/packages/magent-flow/src/SchemaConfigForm/index.tsx
create mode 100644 web/packages/magent-flow/src/common/icons.ts
create mode 100644 web/packages/magent-flow/src/components/AIBasic/CascaderInNode/index.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/CollapseWrapper/index.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/OutputVariableTree/OutputVariable/index.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/constants.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/hooks.ts
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/index.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/hooks.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/index.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/menu.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/prompt-option.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/variable-option.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/custom-text/node.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/on-blur-or-focus-block.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/placeholder.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/update-block.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-block/index.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-value-block/index.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-value-block/node.tsx
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-value-block/utils.ts
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/types.ts
create mode 100644 web/packages/magent-flow/src/components/AIBasic/PromptEditor/utils.ts
create mode 100644 web/packages/magent-flow/src/components/AIBasic/SelectInNode/index.tsx
create mode 100644 web/packages/magent-flow/src/components/CustomEdge/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Flow/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Flow/keys.ts
create mode 100644 web/packages/magent-flow/src/components/FlowController/index.tsx
create mode 100644 web/packages/magent-flow/src/components/FlowWithPanel/index.tsx
create mode 100644 web/packages/magent-flow/src/components/FlowWithPanel/nodeTemplate.yaml
create mode 100644 web/packages/magent-flow/src/components/Node/AgentNode/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Node/CommonNode/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Node/EndNode/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Node/IfElseNode/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Node/LLMNode/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Node/NodeWrapper/Header/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Node/NodeWrapper/Status/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Node/NodeWrapper/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Node/StartNode/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Node/index.tsx
create mode 100644 web/packages/magent-flow/src/components/NodePanel/index.tsx
create mode 100644 web/packages/magent-flow/src/components/RefForm/index.md
create mode 100644 web/packages/magent-flow/src/components/ReferenceForm/index.tsx
create mode 100644 web/packages/magent-flow/src/components/ReferenceSelect/index.tsx
create mode 100644 web/packages/magent-flow/src/components/VariableForm/index.tsx
create mode 100644 web/packages/magent-flow/src/constants/constant.ts
create mode 100644 web/packages/magent-flow/src/context/event-emitter.tsx
create mode 100644 web/packages/magent-flow/src/index.ts
create mode 100644 web/packages/magent-flow/src/interfaces/flow.ts
create mode 100644 web/packages/magent-flow/src/spec/FormSchema/index.ts
create mode 100644 web/packages/magent-flow/src/spec/__snapshots__/node.test.ts.snap
create mode 100644 web/packages/magent-flow/src/spec/node.test.ts
create mode 100644 web/packages/magent-flow/src/spec/node.ts
create mode 100644 web/packages/magent-flow/src/spec/test-jsonschema.json
create mode 100644 web/packages/magent-flow/src/spec/uuid.ts
create mode 100644 web/packages/magent-flow/src/stores/useFlowStore.ts
create mode 100644 web/packages/magent-flow/src/stores/useKnowledgeStore.ts
create mode 100644 web/packages/magent-flow/src/stores/useModelStore.ts
create mode 100644 web/packages/magent-flow/src/stores/useShortcutsStore.ts
create mode 100644 web/packages/magent-flow/src/stores/useUndoRedoStore.ts
create mode 100644 web/packages/magent-flow/src/tailwind.css
create mode 100644 web/packages/magent-flow/src/utils/basic.ts
create mode 100644 web/packages/magent-flow/src/utils/index.tsx
create mode 100644 web/packages/magent-flow/src/utils/reactflowUtils.ts
create mode 100644 web/packages/magent-flow/src/utils/wrappedClass.ts
create mode 100644 web/packages/magent-flow/tailwind.config.js
create mode 100644 web/packages/magent-flow/tsconfig.json
diff --git a/web/packages/magent-flow/.eslintrc.mjs b/web/packages/magent-flow/.eslintrc.mjs
new file mode 100644
index 0000000..ffd7daa
--- /dev/null
+++ b/web/packages/magent-flow/.eslintrc.mjs
@@ -0,0 +1,3 @@
+module.exports = {
+ extends: require.resolve('../../.eslintrc.js'),
+};
diff --git a/web/packages/magent-flow/.fatherrc.ts b/web/packages/magent-flow/.fatherrc.ts
new file mode 100644
index 0000000..a24475c
--- /dev/null
+++ b/web/packages/magent-flow/.fatherrc.ts
@@ -0,0 +1,9 @@
+import babelConfig from './babel.config.json';
+export default {
+ platform: 'browser',
+ esm: {
+ output: 'es',
+ },
+ extraBabelPlugins: babelConfig.plugins,
+ extraBabelPresets: [['@babel/preset-typescript', { onlyRemoveTypeImports: true }]],
+};
diff --git a/web/packages/magent-flow/.gitignore b/web/packages/magent-flow/.gitignore
new file mode 100644
index 0000000..bc61e82
--- /dev/null
+++ b/web/packages/magent-flow/.gitignore
@@ -0,0 +1 @@
+tailwind.out.css
diff --git a/web/packages/magent-flow/.stylelintignore b/web/packages/magent-flow/.stylelintignore
new file mode 100644
index 0000000..bc61e82
--- /dev/null
+++ b/web/packages/magent-flow/.stylelintignore
@@ -0,0 +1 @@
+tailwind.out.css
diff --git a/web/packages/magent-flow/CHANGELOG.md b/web/packages/magent-flow/CHANGELOG.md
new file mode 100644
index 0000000..1ed2e86
--- /dev/null
+++ b/web/packages/magent-flow/CHANGELOG.md
@@ -0,0 +1,402 @@
+# @difizen/libro-core
+
+## 0.1.33
+
+### Patch Changes
+
+- 4811299: fix dark theme style
+- Updated dependencies [4811299]
+ - @difizen/libro-code-editor@0.1.33
+ - @difizen/libro-common@0.1.33
+ - @difizen/libro-shared-model@0.1.33
+ - @difizen/libro-virtualized@0.1.33
+
+## 0.1.32
+
+### Patch Changes
+
+- 2d90b29: fix(core): add deprecated
+- Updated dependencies [2d90b29]
+ - @difizen/libro-code-editor@0.1.32
+ - @difizen/libro-common@0.1.32
+ - @difizen/libro-shared-model@0.1.32
+ - @difizen/libro-virtualized@0.1.32
+
+## 0.1.31
+
+### Patch Changes
+
+- 3a07805: use modelId for modelCache
+- 5b23c6d: Jupyter: integrate jupyter-widgets
+- Updated dependencies [3a07805]
+- Updated dependencies [5b23c6d]
+ - @difizen/libro-code-editor@0.1.31
+ - @difizen/libro-common@0.1.31
+ - @difizen/libro-shared-model@0.1.31
+ - @difizen/libro-virtualized@0.1.31
+
+## 0.1.30
+
+### Patch Changes
+
+- 3c95a2c: improve keybind panel style
+- Updated dependencies [3c95a2c]
+ - @difizen/libro-code-editor@0.1.30
+ - @difizen/libro-common@0.1.30
+ - @difizen/libro-shared-model@0.1.30
+ - @difizen/libro-virtualized@0.1.30
+
+## 0.1.29
+
+### Patch Changes
+
+- d81dd35: Prompt: Migrate libro_server to libro_ai
+- d661508: Lab: open file after creation
+- Updated dependencies [d81dd35]
+- Updated dependencies [d661508]
+ - @difizen/libro-shared-model@0.1.29
+ - @difizen/libro-code-editor@0.1.29
+ - @difizen/libro-virtualized@0.1.29
+ - @difizen/libro-common@0.1.29
+
+## 0.1.28
+
+### Patch Changes
+
+- cc94f1d: 1.refactor(jupyter): use ContentSaveContribution
+- Updated dependencies [cc94f1d]
+ - @difizen/libro-code-editor@0.1.28
+ - @difizen/libro-common@0.1.28
+ - @difizen/libro-shared-model@0.1.28
+ - @difizen/libro-virtualized@0.1.28
+
+## 0.1.27
+
+### Patch Changes
+
+- 5341bd6: feat: go to definition
+ feat: signature help
+- Updated dependencies [5341bd6]
+ - @difizen/libro-code-editor@0.1.27
+ - @difizen/libro-common@0.1.27
+ - @difizen/libro-shared-model@0.1.27
+ - @difizen/libro-virtualized@0.1.27
+
+## 0.1.26
+
+### Patch Changes
+
+- 6a520ad: fix: add import file extension
+- Updated dependencies [6a520ad]
+ - @difizen/libro-code-editor@0.1.26
+ - @difizen/libro-virtualized@0.1.26
+ - @difizen/libro-common@0.1.26
+ - @difizen/libro-shared-model@0.1.26
+
+## 0.1.24
+
+### Patch Changes
+
+- 1bcfbee: 1.fix: get correct url when create notebook file 2.chore: update the peerDependencies about react
+- Updated dependencies [1bcfbee]
+ - @difizen/libro-code-editor@0.1.24
+ - @difizen/libro-virtualized@0.1.24
+ - @difizen/libro-common@0.1.24
+
+## 0.1.23
+
+### Patch Changes
+
+- e37f319: fix: remove useless code about format button
+- Updated dependencies [e37f319]
+ - @difizen/libro-code-editor@0.1.23
+ - @difizen/libro-common@0.1.23
+ - @difizen/libro-shared-model@0.1.23
+ - @difizen/libro-virtualized@0.1.23
+
+## 0.1.22
+
+### Patch Changes
+
+- 669e05b: fix: valid notebook
+ feat(jupyter): add restart kernel
+ fix: poll kernelSpec after serverManager ready
+- Updated dependencies [669e05b]
+ - @difizen/libro-code-editor@0.1.22
+ - @difizen/libro-common@0.1.22
+ - @difizen/libro-shared-model@0.1.22
+ - @difizen/libro-virtualized@0.1.22
+
+## 0.1.21
+
+### Patch Changes
+
+- 9da4081: 1.fix: search view hide not focus libro view
+- Updated dependencies [9da4081]
+ - @difizen/libro-code-editor@0.1.21
+ - @difizen/libro-common@0.1.21
+ - @difizen/libro-shared-model@0.1.21
+ - @difizen/libro-virtualized@0.1.21
+
+## 0.1.20
+
+### Patch Changes
+
+- f3924d3: 1.fix search scroll on large cell 2.add libroModel in VirtualizedManager
+- Updated dependencies [f3924d3]
+ - @difizen/libro-code-editor@0.1.20
+ - @difizen/libro-common@0.1.20
+ - @difizen/libro-shared-model@0.1.20
+ - @difizen/libro-virtualized@0.1.20
+
+## 0.1.19
+
+### Patch Changes
+
+- fe3ee51: fix:poll kernels when serverManager ready
+- Updated dependencies [fe3ee51]
+ - @difizen/libro-code-editor@0.1.19
+ - @difizen/libro-common@0.1.19
+ - @difizen/libro-shared-model@0.1.19
+ - @difizen/libro-virtualized@0.1.19
+
+## 0.1.18
+
+### Patch Changes
+
+- f7c6839: File uploads can now be triggered by right-clicking on the file tree.
+- 0f9e69d: Lab supports saving of all code files.
+- 0f9e69d: More user-friendly prompt cell setting operation.
+- Updated dependencies [f7c6839]
+- Updated dependencies [0f9e69d]
+- Updated dependencies [0f9e69d]
+ - @difizen/libro-shared-model@0.1.18
+ - @difizen/libro-code-editor@0.1.18
+ - @difizen/libro-virtualized@0.1.18
+ - @difizen/libro-common@0.1.18
+
+## 0.1.17
+
+### Patch Changes
+
+- b159277: insert and execute output in a cell
+- 9ff1bf9: Support file download.
+- Updated dependencies [b159277]
+- Updated dependencies [9ff1bf9]
+ - @difizen/libro-code-editor@0.1.17
+ - @difizen/libro-common@0.1.17
+ - @difizen/libro-shared-model@0.1.17
+ - @difizen/libro-virtualized@0.1.17
+
+## 0.1.16
+
+### Patch Changes
+
+- 7d1edf3: Fix: Make Terminals opened from left panel same as the one you created, instead of creating a new terminal view.
+- 90f6f8e: Fix: Cancel observing outputs height change'
+- Updated dependencies [7d1edf3]
+- Updated dependencies [90f6f8e]
+ - @difizen/libro-code-editor@0.1.16
+ - @difizen/libro-common@0.1.16
+ - @difizen/libro-shared-model@0.1.16
+ - @difizen/libro-virtualized@0.1.16
+
+## 0.1.15
+
+### Patch Changes
+
+- 1b88a16: Feature: Better Prompt cell! Now based on better prompt magic support, you can use prompt cells to chat directly with OpenAI models. And you can put chats in context and create exciting workflows.
+- Updated dependencies [1b88a16]
+ - @difizen/libro-shared-model@0.1.15
+ - @difizen/libro-code-editor@0.1.15
+ - @difizen/libro-virtualized@0.1.15
+ - @difizen/libro-common@0.1.15
+
+## 0.1.14
+
+### Patch Changes
+
+- 0b882d3: 1. prompt cell adapt to the api of libro-server 2.fix the editor in CodeEditorView is undefined
+- Updated dependencies [0b882d3]
+ - @difizen/libro-code-editor@0.1.14
+ - @difizen/libro-common@0.1.14
+ - @difizen/libro-shared-model@0.1.14
+ - @difizen/libro-virtualized@0.1.14
+
+## 0.1.13
+
+### Patch Changes
+
+- 262ba79: 1. fix the editor in CodeEditorView is undefined
+- Updated dependencies [262ba79]
+ - @difizen/libro-code-editor@0.1.13
+ - @difizen/libro-common@0.1.13
+ - @difizen/libro-shared-model@0.1.13
+ - @difizen/libro-virtualized@0.1.13
+
+## 0.1.12
+
+### Patch Changes
+
+- bf45fa2: 1. fix:close the open tab when delete the file 2. stop propagation when focus cell right toolbar
+- Updated dependencies [bf45fa2]
+ - @difizen/libro-code-editor@0.1.12
+ - @difizen/libro-common@0.1.12
+ - @difizen/libro-shared-model@0.1.12
+ - @difizen/libro-virtualized@0.1.12
+
+## 0.1.11
+
+### Patch Changes
+
+- 236634d: 1.libro keybind not work when switching tabs
+ 2.auto focus when input file name.
+ 3.editor resize when CodeEditorViewer resize
+ 4.add file size warning
+ 5.add UI for file formats not supported for viewing
+ 6.file name error when select other format
+- Updated dependencies [236634d]
+ - @difizen/libro-code-editor@0.1.11
+ - @difizen/libro-common@0.1.11
+ - @difizen/libro-shared-model@0.1.11
+ - @difizen/libro-virtualized@0.1.11
+
+## 0.1.10
+
+### Patch Changes
+
+- ccdd12d: 1. add remove action in file tree menu
+- Updated dependencies [ccdd12d]
+ - @difizen/libro-code-editor@0.1.10
+ - @difizen/libro-common@0.1.10
+ - @difizen/libro-shared-model@0.1.10
+ - @difizen/libro-virtualized@0.1.10
+
+## 0.1.9
+
+### Patch Changes
+
+- ad803e2: 1. use codeEditorViewer as the last resort file viewer. 2. fix terminal
+- Updated dependencies [ad803e2]
+ - @difizen/libro-code-editor@0.1.9
+ - @difizen/libro-common@0.1.9
+ - @difizen/libro-shared-model@0.1.9
+ - @difizen/libro-virtualized@0.1.9
+
+## 0.1.8
+
+### Patch Changes
+
+- 1. Support json and other file formats.
+ 2. Dynamic shortcut keys and menus when switching tabs.
+- Updated dependencies
+ - @difizen/libro-code-editor@0.1.8
+ - @difizen/libro-common@0.1.8
+ - @difizen/libro-shared-model@0.1.8
+ - @difizen/libro-virtualized@0.1.8
+
+## 0.1.7
+
+### Patch Changes
+
+- Clean lab modules.
+- Updated dependencies
+ - @difizen/libro-code-editor@0.1.7
+ - @difizen/libro-common@0.1.7
+ - @difizen/libro-shared-model@0.1.7
+ - @difizen/libro-virtualized@0.1.7
+
+## 0.1.6
+
+### Patch Changes
+
+- Support code file editing.
+- Updated dependencies
+ - @difizen/libro-code-editor@0.1.6
+ - @difizen/libro-common@0.1.6
+ - @difizen/libro-shared-model@0.1.6
+ - @difizen/libro-virtualized@0.1.6
+
+## 0.1.5
+
+### Patch Changes
+
+- 1. Support image preview.
+ 2. Export the definition and implementation of the libro lab module.
+- Updated dependencies
+ - @difizen/libro-code-editor@0.1.5
+ - @difizen/libro-common@0.1.5
+ - @difizen/libro-shared-model@0.1.5
+ - @difizen/libro-virtualized@0.1.5
+
+## 0.1.4
+
+### Patch Changes
+
+- Fix issues with lsp and virtual list.
+- Updated dependencies
+ - @difizen/libro-code-editor@0.1.4
+ - @difizen/libro-virtualized@0.1.4
+ - @difizen/libro-common@0.1.4
+ - @difizen/libro-shared-model@0.1.4
+
+## 0.1.3
+
+### Patch Changes
+
+- Fix the content format issue of prompt cell
+- Updated dependencies
+ - @difizen/libro-code-editor@0.1.3
+ - @difizen/libro-common@0.1.3
+ - @difizen/libro-shared-model@0.1.3
+ - @difizen/libro-virtualized@0.1.3
+
+## 0.1.2
+
+### Patch Changes
+
+- 1. Support monaco editor, code cell is migrated to monaco editor by default.
+ 2. Support virtual lists to improve performance.
+ 3. libro lab can now use terminal.
+- Updated dependencies
+ - @difizen/libro-code-editor@0.1.2
+ - @difizen/libro-common@0.1.2
+ - @difizen/libro-shared-model@0.1.2
+ - @difizen/libro-virtualized@0.1.2
+
+## 0.1.1
+
+### Patch Changes
+
+- 1. Prompt cell is now available 🎉.
+ 2. Better lab UI.
+- Updated dependencies
+ - @difizen/libro-code-editor@0.1.1
+ - @difizen/libro-common@0.1.1
+ - @difizen/libro-shared-model@0.1.1
+
+## 0.1.0
+
+### Minor Changes
+
+- 1. All modules used to support the notebook editor.
+ 2. Support lab products.
+
+### Patch Changes
+
+- 127cb35: Initia version
+- Updated dependencies [127cb35]
+- Updated dependencies
+ - @difizen/libro-code-editor@0.1.0
+ - @difizen/libro-common@0.1.0
+ - @difizen/libro-shared-model@0.1.0
+
+## 0.0.2-alpha.0
+
+### Patch Changes
+
+- Initia version
+- Updated dependencies
+ - @difizen/libro-code-editor@0.0.2-alpha.0
+ - @difizen/libro-common@0.0.2-alpha.0
+ - @difizen/libro-shared-model@0.0.2-alpha.0
diff --git a/web/packages/magent-flow/README.md b/web/packages/magent-flow/README.md
new file mode 100644
index 0000000..07ecaf3
--- /dev/null
+++ b/web/packages/magent-flow/README.md
@@ -0,0 +1,280 @@
+# libro-core
+
+## Token/API
+
+### LibroService
+
+LibroService 管理 libro 实例,libro view 创建、活跃 libro view 的监听等能力。
+
+```typescript
+// 组件内引入
+const service = useInject(LibroService);
+
+// 属性引入
+@inject(LibroService) service:LibroService;
+
+// 事件监听
+service.getOrCreateView(options);
+service.onActiveChanged(callback);
+service.onFocusChanged(callback);
+service.onNotebookViewCreated(callback);
+```
+
+## 扩展点
+
+### 单元格扩展
+
+使用单元格扩展可以增加自定义的单元格类型,内置的单元格类型也均基于该扩展定义实现。
+
+单元格定义分为 model 和 view 两部分,model 定义单元格的数据结构,view 定义单元格的渲染方式和提供交互能力。每种单元格都需要对创建时接收到的参数返回优先级,按照最高优先级的单元格类型创建单元格。
+
+```typescript
+export interface CellModelContribution {
+ cellMeta: CellMeta;
+ canHandle: (options: CellOptions, libroType?: string) => number;
+ createModel: (options: CellOptions) => MaybePromise;
+ getDefaultCellOption?: () => CellOptions;
+}
+export interface CellViewContribution {
+ canHandle: (options: CellOptions) => number;
+ view: Newable;
+}
+```
+
+### 输出扩展
+
+使用输出扩展可以增加自定义的输出类型,内置的输出类型也均基于该扩展定义实现。在 jupyter 场景下,用户一般不需要增加输出类型的扩展,而仅需要增加 mime 渲染器,mime 渲染器扩展由 output 实现。
+
+```typescript
+export interface OutputContribution {
+ canHandle: (output: IOutput) => number;
+ factory: OutputModelFactory;
+}
+```
+
+### 内容加载扩展
+
+用户有时候从自定义存储中读取 notebook 数据,可以通过内容加载扩展来实现,这里要求用户的返回数据符合 notebook 的数据结构。
+
+```typescript
+export interface ContentContribution {
+ canHandle: (options: Record, model: any) => number;
+ loadContent: (options: Record, model: any) => Promise;
+}
+```
+
+### 视图插槽
+
+如果希望在编辑器内部增加一些自定义的渲染像,除了可以覆盖内置的渲染器外,还可以通过视图插槽的方式来实现。
+
+内置插槽位置如下:
+
+- container
+- content
+- list
+- right
+
+```typescript
+export interface LibroExtensionSlotContribution {
+ factory: LibroExtensionSlotFactory;
+ slot: LibroSlot;
+ viewOpenOption?: {
+ order?: string;
+ reveal?: boolean;
+ };
+}
+```
+
+## 命令 & 快捷键
+
+### 文档命令
+
+| 命令 | 快捷键 | 命令模式 | 说明 |
+| ------------------ | ----------- | -------- | -------- |
+| `document:save` | `ctrlcmd+s` | | 保存文档 |
+| `document:setting` | | | 打开配置 |
+
+### kernel 命令
+
+| 命令 | 快捷键 | 命令模式 | 说明 |
+| ------------------------------ | ------ | -------- | ------------------- |
+| `notebook:change-kernel` | | | Change Kernel |
+| `notebook:get-kernel` | | | Get Kernel |
+| `notebook:interrupt-kernel` | | | Interrupt Kernel |
+| `notebook:reconnect-to-kernel` | | | Reconnect to Kernel |
+| `notebook:restart-kernel` | | | Restart Kernel |
+| `notebook:shutdown-kernel` | | | Shutdown Kernel |
+
+### notebook 命令
+
+| 命令 | 快捷键 | 命令模式 | 说明 |
+| ------------------------------------------------ | ---------------------- | -------- | ----------------------------------------------- |
+| `notebook:interrupt` | | | Interrupt |
+| `notebook:change-cell-to` | | | |
+| `notebook:change-cell-to-code` | `Y` | ✓ | Change to Code Cell Type |
+| `notebook:change-cell-to-heading-1` | `1` | ✓ | Change to Heading 1 |
+| `notebook:change-cell-to-heading-2` | `2` | ✓ | Change to Heading 2 |
+| `notebook:change-cell-to-heading-3` | `3` | ✓ | Change to Heading 3 |
+| `notebook:change-cell-to-heading-4` | `4` | ✓ | Change to Heading 4 |
+| `notebook:change-cell-to-heading-5` | `5` | ✓ | Change to Heading 5 |
+| `notebook:change-cell-to-heading-6` | `6` | ✓ | Change to Heading 6 |
+| `notebook:change-cell-to-markdown` | `M` | ✓ | Change to Markdown Cell Type |
+| `notebook:change-cell-to-raw` | `R` | ✓ | Change to Raw Cell Type |
+| `notebook:clear-all-cell-outputs` | | | Clear Outputs of All Cells |
+| `notebook:clear-cell-outputs` | | | Clear Cell Output |
+| `notebook:close-and-shutdown` | | | Close editor and shut down kernel |
+| `notebook:collapse-all-headings` | `ctrlcmd+shift+left` | | Collapse All Headings |
+| `notebook:copy-cell` | `C` | ✓ | Copy Cells |
+| `notebook:cut-cell` | `X` | ✓ | Cut Cells |
+| `notebook:delete-cell` | `D D` | ✓ | Delete Cells |
+| `notebook:deselect-all` | | | Deselect All Cells |
+| `notebook:disable-output-scrolling` | | | Disable Scrolling for Outputs |
+| `notebook:duplicate-below` | | | Duplicate Cells Below |
+| `notebook:enable-output-scrolling` | | | Enable Scrolling for Outputs |
+| `notebook:enter-command-mode` | `esc` | | Enter Command Mode |
+| `notebook:enter-edit-mode` | `enter` | | Enter Edit Mode |
+| `notebook:expand-all-headings` | `ctrlcmd+shift+right` | | Expand All Headings |
+| `notebook:export-to-format` | | | Save and Export Notebook to the given format |
+| `notebook:extend-marked-cells-above` | `shift+up` `shift+K` | | Extend Selection Above |
+| `notebook:extend-marked-cells-below` | `shift+down` `shift+J` | | Extend Selection Below |
+| `notebook:extend-marked-cells-bottom` | `shift+end` | | Extend Selection to Bottom |
+| `notebook:extend-marked-cells-top` | `shift+home` | | Extend Selection to Top |
+| `notebook:hide-all-cell` | | | |
+| `notebook:hide-all-cell-code` | | | Collapse All Code |
+| `notebook:hide-all-cell-output` | | | Collapse All Outputs |
+| `notebook:hide-cell-code` | | | Collapse Selected Code |
+| `notebook:hide-or-show-cell-code` | `ctrlcmd+'` | | Hide or show Selected Code |
+| `notebook:hide-cell-outputs` | | | Collapse Selected Outputs |
+| `notebook:hide-or-show-outputs` | `ctrlcmd+o` | | Hide or show Selected outputs |
+| `notebook:insert-cell-above` | `A` | ✓ | Insert Cell Above |
+| `notebook:insert-cell-below` | `B` | ✓ | Insert Cell Below |
+| `notebook:insert-heading-above` | `shift+A` | ✓ | Insert Heading Above Current Heading |
+| `notebook:insert-heading-below` | `shift+B` | ✓ | Insert Heading Below Current Heading |
+| `notebook:merge-cell-above` | `ctrlcmd+backspace` | ✓ | Merge Cell Above |
+| `notebook:merge-cell-below` | `ctrlcmd+shift+M` | ✓ | Merge Cell Below |
+| `notebook:merge-cells` | `shift+M` | ✓ | Merge Selected Cells |
+| `notebook:move-cell-down` | `ctrlcmd+shift+down` | ✓ | Move Cells Down |
+| `notebook:move-cell-up` | `ctrlcmd+shift+up` | ✓ | Move Cells Up |
+| `notebook:move-cursor-down` | `down` `J` | ✓ | Select Cell Below |
+| `notebook:move-cursor-up` | `up` `K` | ✓ | Select Cell Up |
+| `notebook:move-cursor-heading-above-or-collapse` | `left` | ✓ | Select Heading Above or Collapse Heading |
+| `notebook:move-cursor-heading-below-or-expand` | `right` | ✓ | Select Heading Below or Collapse Heading |
+| `notebook:paste-and-replace-cell` | | | Paste Cells and Replace |
+| `notebook:paste-cell-above` | | | Paste Cells Above |
+| `notebook:paste-cell-below` | `V` | ✓ | Paste Cells Below |
+| `notebook:redo` | | | Redo |
+| `notebook:redo-cell-action` | `shift+Z` | ✓ | Redo Cell Operation |
+| `notebook:render-all-markdown` | | | Render All Markdown Cells |
+| `notebook:replace-selection` | | | Replace Selection in Notebook Cell |
+| `notebook:restart-and-run-to-selected` | | | Restart and Run up to Selected Cell |
+| `notebook:restart-clear-output` | | | Restart and Clear Outputs of All Cells |
+| `notebook:restart-run-all` | | | Restart and Run All Cells |
+| `notebook:run-all-above` | | | Run All Above Selected Cell |
+| `notebook:run-all-below` | | | Run All Below Selected Cell |
+| `notebook:run-all-cells` | | | Run All Cells |
+| `notebook:run-cell` | `ctrlcmd+enter` | | Run Selected Cells and Don't Advance |
+| `notebook:run-cell-and-insert-below` | `alt+enter` | | Run Selected Cells and Insert Below |
+| `notebook:run-cell-and-select-next` | `shift+enter` | | Run Selected Cells and Select Below |
+| `notebook:run-in-console` | | | Run Selected Text or Current Line in Console |
+| `notebook:select-all` | `ctrlcmd+A` | ✓ | Select All Cells |
+| `notebook:select-last-run-cell` | | | Select current running or last run cell |
+| `notebook:set-side-by-side-ratio` | | | Set Side by Side Ratio |
+| `notebook:show-all-cell` | | | Expand All Cell |
+| `notebook:show-all-cell-code` | | | Expand All Code |
+| `notebook:show-all-cell-outputs` | | | Expand All Outputs |
+| `notebook:show-cell-code` | | | Expand Selected Code |
+| `notebook:show-cell-outputs` | | | Expand Selected Outputs |
+| `notebook:split-cell-at-cursor` | `ctrlcmd+shift+-` | | Split Cell |
+| `notebook:toggle-all-cell-line-numbers` | `shift+L` | | Show Line Numbers |
+| `notebook:toggle-autoclosing-brackets` | | | Auto Close Brackets for All Notebook Cell Types |
+| `notebook:toggle-heading-collapse` | | | Toggle Collapse Notebook Heading |
+| `notebook:toggle-render-side-by-side-current` | `shift+R` | ✓ | Render Side-by-Side |
+| `notebook:trust` | | | Trust Notebook |
+| `notebook:undo` | | | Undo |
+| `notebook:undo-cell-action` | `Z` | ✓ | Undo Cell Operation |
+| `notebook:insert-cell-bottom` | | | |
+
+## 配置 & 主题
+
+libro 内置了一些配置项和主题设置,用户可以是用 mana 的配置模块和主题模块来消费或变更。
+
+| 配置项 | 说明 | 默认值 |
+| ----------------------------------------------- | --------------------------------------- | ------- |
+| `libro.header.toolbar` | 是否显示 libro 顶部工具栏 | `true` |
+| `libro.cell.top-toolbar` | 是否显示单元格顶部工具栏 | `true` |
+| `libro.cell.side-toolbar` | 是否显示单元格侧边工具栏 | `true` |
+| `libro.command.insert-cell-below` | 没有单元格时是否默认创建单元格 | `true` |
+| `libro.command.enter-edit-mode-when-add-cell` | 增加单元格操作默认进入编辑态 | `true` |
+| `libro.command.collapser-active` | 点击左侧长条是否可以隐藏与显示单元格 | `true` |
+| `libro.command.multiselection-when-shift-click` | 按住 shift 键并点击拖拽区域可以进行多选 | `true` |
+| `libro.right.content.fixed` | libro view 的右边栏是否相对固定 | `false` |
+
+| 颜色 | css 变量 | 暗色主题 | 亮色主题 | 高对比主题 | 说明 |
+| -------------------------------------------- | -------- | ----------- | ----------- | ---------- | ---- |
+| `libro.warning.background` | | `#A9611466` | `#FFFBE6` | | |
+| `libro.drag.hover.line.color` | | `#467DB0` | `#BFE0FF` | | |
+| `libro.background` | | `#1F2022` | `#FFFFFF` | | |
+| `libro.popover.background.color` | | `#2F3032` | `#FFFFFF` | | |
+| `libro.menu.hover.color` | | `#515359` | `#EBF6FF` | | |
+| `libro.dropdown.icon.color` | | `#FFFFFF4D` | `#00000033` | | |
+| `libro.input.background` | | `#19191B` | `#F4F6FB` | | |
+| `libro.text.default.color` | | `#E3E4E6` | `#000000` | | |
+| `libro.text.tertiary.color` | | `#BDC0C4` | `#B8BABA` | | |
+| `libro.output.background` | | `#292A2D` | `#FFFFFF` | | |
+| `libro.toptoolbar.border.color` | | `#FFFFFF1A` | `#0000001A` | | |
+| `libro.toptoolbar.icon.color` | | `#BFBFBF` | `#7B7B7B` | | |
+| `libro.toptoolbar.disabled.icon.color` | | `#FFFFFF4D` | `#00000040` | | |
+| `libro.toptoolbar.text.color` | | `#F5F5F5` | `#000000` | | |
+| `libro.bottom.btn.background.color` | | `#FFFFFF0A` | `#FFFFFF` | | |
+| `libro.bottom.btn.border.color` | | `#505559` | `#000A1A29` | | |
+| `libro.bottom.btn.icon.color` | | `#505559` | `#525964D9` | | |
+| `libro.bottom.btn.text.color` | | `#E3E4E6` | `#000A1AAD` | | |
+| `libro.default.btn.background.color` | | `#FFFFFF1A` | `#FFFFFF` | | |
+| `libro.default.btn.text.color` | | `#E3E4E6` | `#000A1AAD` | | |
+| `libro.primary.btn.background.color` | | `#2A97FD` | `#1890FF` | | |
+| `libro.default.btn.border.color` | | `#BDC0C4` | `#D6D8DA` | | |
+| `libro.toolbar.menu.label.color` | | `#BDC0C4` | `#000000A6` | | |
+| `libro.toolbar.menu.disabled.label.color` | | `#878C93` | `#00000040` | | |
+| `libro.toolbar.menu.keybind.color` | | `#878C93` | `#00000073` | | |
+| `libro.sidetoolbar.icon.color` | | `#BFBFBF` | `#6982A9` | | |
+| `libro.sidetoolbar.border.color` | | `#FFFFFF14` | `#0000001A` | | |
+| `libro.close.color` | | `#FFFFFF73` | `#00000073` | | |
+| `libro.modal.title.color` | | `#EDEEEF` | `#000000D9` | | |
+| `libro.modal.content.color` | | `#E3E4E6` | `#000A1A` | | |
+| `libro.btn.primary.background.color` | | `#2A97FD` | `#1890FF` | | |
+| `libro.execution.count.color` | | `#8694A9` | `#6A83AA` | | |
+| `libro.tip.font.color` | | `#D6D8DA` | `#00000080` | | |
+| `libro.execution.tip.success.color` | | `#48A918` | `#0DC54E` | | |
+| `libro.link.color` | | `#177DDC` | `#1890FF` | | |
+| `libro.error.color` | | `#CF4C52` | `#ED1345` | | |
+| `libro.cell.border.color` | | `#3B3C42` | `#D6DEE6` | | |
+| `libro.cell.active.border.color` | | `#378EDF` | `#3490ED` | | |
+| `libro.cell.active.border.shadow.color` | | `#49A2FA40` | `#3592EE40` | | |
+| `libro.cell.header.content` | | `#E3E4E6` | `#545B66` | | |
+| `libro.cell.header.title` | | `#D6D8DA` | `#000A1A` | | |
+| `libro.code.border.color` | | `#353638` | `#DCE4EC` | | |
+| `libro.input.border.color` | | `#505559` | `#00000026` | | |
+| `libro.input.background.color` | | `#FFFFFF0A` | `#FFFFFF` | | |
+| `libro.input.group.btn.background.color` | | `#00000005` | `#00000005` | | |
+| `libro.table.innner.border.color` | | `#1AFFFF` | `#E5EBF1` | | |
+| `libro.table.bottom.border.color` | | `#424242` | `#E2E7EC` | | |
+| `libro.editor.keyword.color` | | `#109B67` | `#098658` | | |
+| `libro.editor.number.color` | | `#109B67` | `#098658` | | |
+| `libro.editor.variable.2.color` | | `#5DA4EA` | `#2060A0` | | |
+| `libro.editor.punctuation.color` | | `#5DA4EA` | `#2060A0` | | |
+| `libro.editor.property.color` | | `#5DA4EA` | `#2060A0` | | |
+| `libro.editor.operator.color` | | `#E12EE1` | `#C700C7` | | |
+| `libro.editor.meta.color` | | `#E12EE1` | `#C700C7` | | |
+| `libro.editor.builtin.color` | | `#109B67` | `#098658` | | |
+| `libro.editor.variable.color` | | `#E3E4E6` | `#212121` | | |
+| `libro.editor.def.color` | | `#187DFF` | `#003CFF` | | |
+| `libro.editor.comment.color` | | `#618961` | `#406040` | | |
+| `libro.editor.string.color` | | `#FF5B48` | `#C03030` | | |
+| `libro.editor.activeline.color` | | `#E5E8F01A` | `#E5E8F080` | | |
+| `libro.editor.selectionMatch.color` | | `#99FF7780` | `#DDE6FF` | | |
+| `libro.editor.selection.color` | | `#B4CEFF` | `#B4CEFF` | | |
+| `libro.editor.gutter.number.color` | | `#A8EABF` | `#A4AECB` | | |
+| `libro.editor.line.color` | | `#565C6D` | `#A4AECB` | | |
+| `libro.editor.cursor.color` | | `#FFFFFF` | `#000000` | | |
+| `libro.editor.indent.marker.bg.color` | | `#42444D` | `#D6DBEB` | | |
+| `libro.editor.indent.marker.active.bg.color` | | `#788491` | `#9f9f9f` | | |
diff --git a/web/packages/magent-flow/babel.config.json b/web/packages/magent-flow/babel.config.json
new file mode 100644
index 0000000..efd1224
--- /dev/null
+++ b/web/packages/magent-flow/babel.config.json
@@ -0,0 +1,20 @@
+{
+ "presets": [
+ "@babel/preset-env",
+ [
+ "@babel/preset-react",
+ {
+ "runtime": "automatic"
+ }
+ ],
+ "@babel/preset-typescript"
+ ],
+ "plugins": [
+ ["@babel/plugin-proposal-decorators", { "legacy": true }],
+ ["@babel/plugin-transform-flow-strip-types", { "allowDeclareFields": true }],
+ ["@babel/plugin-transform-private-methods", { "loose": true }],
+ ["@babel/plugin-transform-private-property-in-object", { "loose": true }],
+ ["@babel/plugin-transform-class-properties", { "loose": true }],
+ "babel-plugin-parameter-decorator"
+ ]
+}
diff --git a/web/packages/magent-flow/jest.config.mjs b/web/packages/magent-flow/jest.config.mjs
new file mode 100644
index 0000000..e698bd5
--- /dev/null
+++ b/web/packages/magent-flow/jest.config.mjs
@@ -0,0 +1,6 @@
+import configs from '../../../jest.config.mjs';
+
+export default {
+ ...configs,
+ transformIgnorePatterns: ['^/node_modules/(?!react-dnd|dnd-core|@react-dnd)'],
+};
diff --git a/web/packages/magent-flow/package.json b/web/packages/magent-flow/package.json
new file mode 100644
index 0000000..397fd69
--- /dev/null
+++ b/web/packages/magent-flow/package.json
@@ -0,0 +1,78 @@
+{
+ "name": "@difizen/magent-flow",
+ "version": "0.0.1",
+ "description": "",
+ "keywords": [
+ "flow",
+ "ai",
+ "workflow"
+ ],
+ "type": "module",
+ "repository": "git@github.com:difizen/magent.git",
+ "license": "MIT",
+ "exports": {
+ ".": {
+ "typings": "./es/index.d.ts",
+ "default": "./es/index.js"
+ },
+ "./mock": {
+ "typings": "./es/mock/index.d.ts",
+ "default": "./es/mock/index.js"
+ },
+ "./es/mock": {
+ "typings": "./es/mock/index.d.ts",
+ "default": "./es/mock/index.js"
+ },
+ "./package.json": "./package.json"
+ },
+ "main": "es/index.js",
+ "module": "es/index.js",
+ "typings": "es/index.d.ts",
+ "files": [
+ "es",
+ "src"
+ ],
+ "scripts": {
+ "setup": "father build",
+ "build": "father build",
+ "test": ": Note: lint task is delegated to test:* scripts",
+ "test:vitest": "vitest run",
+ "test:jest": "jest",
+ "coverage": ": Note: lint task is delegated to coverage:* scripts",
+ "coverage:vitest": "vitest run --coverage",
+ "coverage:jest": "jest --coverage",
+ "lint": ": Note: lint task is delegated to lint:* scripts",
+ "lint:eslint": "eslint src",
+ "tailwind": "tailwindcss -i ./src/tailwind.css -o ./src/tailwind.out.css --watch",
+ "typecheck:tsc": "tsc --noEmit"
+ },
+ "dependencies": {
+ "@ant-design/icons": "^5.1.0",
+ "@babel/runtime": "^7.18.0",
+ "@floating-ui/react": "^0.26.22",
+ "@lexical/react": "^0.17.0",
+ "@types/json-schema": "^7.0.15",
+ "@xyflow/react": "^12.0.2",
+ "antd": "^5.19.2",
+ "ajv": "^8.17.1",
+ "js-yaml": "^4.1.0",
+ "lexical": "^0.17.0",
+ "lodash": "^4.17.21",
+ "react-hotkeys-hook": "^4.5.0",
+ "short-unique-id": "^5.2.0",
+ "styled-components": "^6.0.7",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0",
+ "uuid": "^10.0.0",
+ "zustand": "^4.5.4"
+ },
+ "devDependencies": {
+ "@types/react": "^18.2.25",
+ "@types/uuid": "^10.0.0",
+ "tailwindcss": "^3"
+ },
+ "peerDependencies": {
+ "antd": "^5.8.6",
+ "react": ">=16"
+ }
+}
diff --git a/web/packages/magent-flow/src/FormSchema/index.ts b/web/packages/magent-flow/src/FormSchema/index.ts
new file mode 100644
index 0000000..e1ac908
--- /dev/null
+++ b/web/packages/magent-flow/src/FormSchema/index.ts
@@ -0,0 +1,331 @@
+import { message } from 'antd';
+import type {
+ JSONSchema7,
+ JSONSchema7Definition,
+ JSONSchema7TypeName,
+} from 'json-schema';
+
+import { UUID } from '@/spec/uuid';
+
+export type OrderJSONSchema7 = JSONSchema7 & {
+ order: number;
+};
+
+export interface CascaderOptions {
+ value: string;
+ label: string;
+ children?: CascaderOptions[];
+}
+
+/**
+ * 声明输入的表单数据格式
+ * 表单内容
+ */
+export class FormSchema {
+ uuid = UUID.getInstance().uniqueID();
+
+ jsonschema: JSONSchema7 = {
+ $id: this.uuid,
+ type: 'object',
+ properties: {},
+ required: [],
+ };
+
+ constructor(schema: JSONSchema7) {
+ Object.assign(this.jsonschema, schema);
+ }
+ /**
+ * 获取指定路径的属性
+ * 方便添加属性
+ * /a/b/c/
+ * @param pointer
+ * @returns
+ */
+ getSchemaByPoint(pointer: string) {
+ if (pointer === '/' || pointer === '') {
+ return this.jsonschema;
+ }
+
+ let pointers = pointer.split('/');
+ if (pointers[0] !== '') {
+ throw new Error('invalid pointer');
+ }
+ pointers = pointers.slice(1);
+
+ // base是一个object模式
+ let schema = this.jsonschema;
+ while (pointers.length > 0) {
+ const pointer = pointers.shift();
+ if (pointer === undefined) {
+ throw new Error('invalid pointer');
+ }
+ if (schema) {
+ if (schema.type === 'object') {
+ if (schema?.properties?.[pointer]) {
+ // 有就递归下沉
+ schema = schema.properties[pointer] as JSONSchema7;
+ } else {
+ // 没有属性就添加
+ schema!.properties![pointer] = {};
+ return schema!.properties![pointer];
+ }
+ } else if (schema?.type === 'array') {
+ if (schema?.items) {
+ const index = parseInt(pointer);
+ if (Array.isArray(schema.items)) {
+ schema = schema.items[index] as JSONSchema7;
+ } else {
+ schema = schema.items as JSONSchema7;
+ }
+ }
+ }
+ }
+ }
+ return schema;
+ }
+
+ private randommName = () => {
+ return (
+ 'RandaomName__-' +
+ Math.random().toString(36).substring(2, 15) +
+ Math.random().toString(36).substring(2, 15)
+ );
+ };
+
+ isRandomName = (name: string) => {
+ return name.startsWith('RandaomName__-');
+ };
+
+ /**
+ * 动态表单添加属性
+ * @param property
+ * @returns
+ */
+ addField = (options: {
+ pointer: string; // 指定属性路径,如 /a/b
+ name?: string;
+ type: JSONSchema7TypeName;
+ description: string;
+ required: boolean;
+ }) => {
+ const { pointer, name = this.randommName(), type, description, required } = options;
+ if (typeof this.jsonschema !== 'boolean') {
+ const schema = this.getSchemaByPoint(pointer);
+ if (schema.type === 'array') {
+ // 如果存在属性
+ if (!schema?.items) {
+ schema.items = {
+ type: type,
+ description,
+ };
+ } else if (!Array.isArray(schema?.items)) {
+ const items = schema.items as JSONSchema7Definition;
+ schema.items = [
+ items,
+ {
+ type: type,
+ description,
+ },
+ ];
+ } else if (Array.isArray(schema?.items)) {
+ schema.items.push({
+ type: type,
+ description,
+ });
+ }
+ } else if (schema?.type === 'object') {
+ // 使用order 记录顺序
+ let order = 0;
+ Object.entries(schema.properties || {}).forEach(([, val]) => {
+ const v = val as OrderJSONSchema7;
+ if (v?.order) {
+ order = v?.order > order ? v?.order : order;
+ }
+ });
+
+ (schema.properties![name] as OrderJSONSchema7) = {
+ type: type,
+ description,
+ order: order + 1,
+ };
+ if (type === 'object') {
+ schema.properties![name].properties = {};
+ }
+ } else {
+ schema.type = type;
+ schema.description = description;
+ }
+ if (required) {
+ // 如果是object的话,require在当前位置添加
+ if (schema.type === 'object') {
+ if (!schema.required) {
+ schema.required = [];
+ }
+ schema.required = [...schema.required, name];
+ } else {
+ // 在父级添加
+ const parentPointer = pointer.split('/').slice(0, -1).join('/');
+ const parentSchema = this.getSchemaByPoint(parentPointer);
+
+ if (!parentSchema.required) {
+ parentSchema.required = [];
+ }
+ parentSchema.required = [...parentSchema.required, name];
+ }
+ }
+ }
+ return false;
+ };
+
+ /**
+ * 动态表单更新属性
+ * @param property
+ * @returns
+ */
+ updateField = (options: {
+ pointer: string; // 指定属性路径,如 /a/b
+ key: 'variableName' | 'variableType' | 'description' | 'required';
+ value: any;
+ currentVariableName: string;
+ }) => {
+ const { pointer, key, value, currentVariableName } = options;
+ if (typeof this.jsonschema !== 'boolean') {
+ const schema = this.getSchemaByPoint(pointer);
+ if (schema.type === 'object') {
+ if (schema.properties) {
+ if (key === 'variableName') {
+ const old = schema.properties?.[currentVariableName];
+ if (value !== currentVariableName) {
+ schema.properties[value] = old;
+ delete schema.properties[currentVariableName];
+ } else {
+ message.info('变量名不能和已有变量名相同');
+ return false;
+ }
+ return true;
+ }
+ if (key === 'variableType') {
+ if ((schema.properties[currentVariableName] as JSONSchema7).type) {
+ // 处理数组类型
+ if (value.startsWith('Array<')) {
+ const t = (
+ value.replace('Array<', '').replace('>', '') as string
+ ).toLocaleLowerCase();
+ schema.properties[currentVariableName].type = 'array';
+ schema.properties[currentVariableName].items = {
+ type: t,
+ };
+ if (t === 'object') {
+ schema.properties[currentVariableName].items.properties = {};
+ }
+ return true;
+ }
+ if (value === 'object') {
+ schema.properties[currentVariableName].type = value;
+ schema.properties[currentVariableName].properties = {};
+ return true;
+ }
+
+ // 基础类型
+ schema.properties[currentVariableName].type = value;
+ delete schema.properties[currentVariableName].items;
+ delete schema.properties[currentVariableName].properties;
+
+ return true;
+ }
+ }
+ if (key === 'description') {
+ if (schema.properties[currentVariableName] as JSONSchema7) {
+ schema.properties[currentVariableName].description = value;
+ return true;
+ }
+ }
+ if (key === 'required') {
+ if (!this.isRandomName(currentVariableName)) {
+ if (schema.properties[currentVariableName]) {
+ if (!schema.required) {
+ schema.required = [];
+ }
+ if (value) {
+ if (!schema.required?.includes(value)) {
+ schema.required?.push(currentVariableName);
+ }
+ } else {
+ if (schema.required?.includes(currentVariableName)) {
+ schema.required = schema.required.filter(
+ (item) => item !== currentVariableName,
+ );
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ };
+
+ updateSchema(schema: JSONSchema7) {
+ Object.assign(this.jsonschema, schema);
+ }
+
+ log() {
+ return JSON.stringify(this.jsonschema, null, 4);
+ }
+}
+
+export const variableTypeOptions: {
+ label: string;
+ value:
+ | JSONSchema7TypeName
+ | 'Array'
+ | 'Array'
+ | 'Array'
+ | 'Array'
+ | 'Array
,
+ },
+ ]}
+ />
+ )}
+ >
+
+ );
+};
diff --git a/web/packages/magent-flow/src/components/Node/EndNode/index.tsx b/web/packages/magent-flow/src/components/Node/EndNode/index.tsx
new file mode 100644
index 0000000..8b3cf8f
--- /dev/null
+++ b/web/packages/magent-flow/src/components/Node/EndNode/index.tsx
@@ -0,0 +1,34 @@
+import { ReferenceForm } from '@/components/ReferenceForm';
+import { NodeDataType } from '@/interfaces/flow';
+import { useFlowStore } from '@/stores/useFlowStore';
+import { Collapse } from 'antd';
+import React from 'react';
+import { NodeWrapper } from '../NodeWrapper';
+
+type Props = {
+ data: NodeDataType;
+ selected: boolean;
+ xPos: number;
+ yPos: number;
+};
+
+export const EndNode = (props: Props) => {
+ const { data } = props;
+ const { findUpstreamNodes } = useFlowStore();
+ const upstreamNode = findUpstreamNodes(data.id.toString());
+
+ return (
+
+
+ {
+ console.log('ReferenceForm', values);
+ }}
+ />
+
+
+ );
+};
diff --git a/web/packages/magent-flow/src/components/Node/IfElseNode/index.tsx b/web/packages/magent-flow/src/components/Node/IfElseNode/index.tsx
new file mode 100644
index 0000000..e9c3924
--- /dev/null
+++ b/web/packages/magent-flow/src/components/Node/IfElseNode/index.tsx
@@ -0,0 +1,76 @@
+import { SelectInNode } from '@/components/AIBasic/SelectInNode';
+import { ReferenceSelect } from '@/components/ReferenceSelect';
+import { NodeDataType } from '@/interfaces/flow';
+import { useFlowStore } from '@/stores/useFlowStore';
+import { Form } from 'antd';
+import React from 'react';
+import { NodeWrapper } from '../NodeWrapper';
+
+type Props = {
+ data: NodeDataType;
+ selected: boolean;
+ xPos: number;
+ yPos: number;
+};
+
+export const IfElseNode = (props: Props) => {
+ const { data } = props;
+ const [form] = Form.useForm();
+ const compare = Form.useWatch('compare', form);
+ const { findUpstreamNodes } = useFlowStore();
+ const upstreamNode = findUpstreamNodes(data.id.toString());
+ const options = upstreamNode.map((node) => {
+ return {
+ label: node.data.name,
+ value: node.data.id,
+ children:
+ node.data?.config?.outputs?.map((output) => {
+ return {
+ label: output.name,
+ value: output.name,
+ };
+ }) || [],
+ };
+ });
+ return (
+
+ <>
+
+
+
如果
+
+
+
+
+
+
+ {compare !== 'blank' && (
+
+
+
+ )}
+
+
+
+
+ >
+
+ );
+};
diff --git a/web/packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx b/web/packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx
new file mode 100644
index 0000000..8a9a027
--- /dev/null
+++ b/web/packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx
@@ -0,0 +1,84 @@
+import { CollapseWrapper } from '@/components/AIBasic/CollapseWrapper';
+import { OutputVariable } from '@/components/AIBasic/OutputVariableTree/OutputVariable';
+import { ReferenceForm } from '@/components/ReferenceForm';
+import { NodeDataType } from '@/interfaces/flow';
+import { useFlowStore } from '@/stores/useFlowStore';
+import { useKnowledgeStore } from '@/stores/useKnowledgeStore';
+import { PlusOutlined } from '@ant-design/icons';
+import { Button, Modal } from 'antd';
+import React from 'react';
+import { NodeWrapper } from '../NodeWrapper';
+
+type Props = {
+ data: NodeDataType;
+ selected: boolean;
+ xPos: number;
+ yPos: number;
+};
+
+export const KnowledgeNode = (props: Props) => {
+ const { data } = props;
+ // const { config } = data;
+ const { findUpstreamNodes } = useFlowStore();
+
+ const { knowledges } = useKnowledgeStore();
+ const upstreamNode = findUpstreamNodes(data.id.toString());
+
+ return (
+
+
+
{
+ console.log('ReferenceForm', values);
+ }}
+ />
+
+ 知识库配置
+ }
+ className="ml-2"
+ onClick={(e) => {
+ e.stopPropagation();
+ Modal.confirm({
+ title: '导入知识库',
+ icon: null,
+ content: <>>,
+ onOk: () => {
+ console.log('knowledges', knowledges);
+ },
+ });
+ }}
+ >
+ 导入
+
+
+ }
+ content={<>List>}
+ />
+
+ {(data.config?.outputs || []).map((output) => (
+
+ ))}
+ >
+ }
+ />
+
+
+ );
+};
diff --git a/web/packages/magent-flow/src/components/Node/LLMNode/index.tsx b/web/packages/magent-flow/src/components/Node/LLMNode/index.tsx
new file mode 100644
index 0000000..f736768
--- /dev/null
+++ b/web/packages/magent-flow/src/components/Node/LLMNode/index.tsx
@@ -0,0 +1,120 @@
+import { CollapseWrapper } from '@/components/AIBasic/CollapseWrapper';
+import { OutputVariable } from '@/components/AIBasic/OutputVariableTree/OutputVariable';
+import PromptEditor from '@/components/AIBasic/PromptEditor';
+import { SelectInNode } from '@/components/AIBasic/SelectInNode';
+import { ReferenceForm } from '@/components/ReferenceForm';
+import { NodeDataType } from '@/interfaces/flow';
+import { useFlowStore } from '@/stores/useFlowStore';
+import { useModelStore } from '@/stores/useModelStore';
+import { BarsOutlined } from '@ant-design/icons';
+import { Button, InputNumber, Popover } from 'antd';
+import React, { useState } from 'react';
+import { NodeWrapper } from '../NodeWrapper';
+
+type Props = {
+ data: NodeDataType;
+ selected: boolean;
+ xPos: number;
+ yPos: number;
+};
+
+export const LLMNode = (props: Props) => {
+ const { data } = props;
+ // console.log('🚀 ~ LLMNode ~ data:', data);
+ // const { config } = data;
+
+ const { findUpstreamNodes } = useFlowStore();
+ const upstreamNode = findUpstreamNodes(data.id.toString());
+
+ const { models, modelConfig } = useModelStore();
+
+ const [value, setValue] = useState('hello');
+ return (
+
+
+ {/* Part1 model selector & model config */}
+
+ ({
+ label: model.name,
+ value: model.id,
+ }))}
+ className="w-full mr-2"
+ />
+
+ {Object.entries(modelConfig).map(([key, value]) => (
+ <>
+ {key}
+ >
+ ))}
+
+ }
+ >
+ {Object.entries(modelConfig).length > 0 && (
+ }>
+ )}
+
+
+ }
+ />
+ {/* Part2 Ref Form */}
+
+ {
+ console.log('ReferenceForm', values);
+ }}
+ />
+ {/* Part3 PromptEditor */}
+
+ setValue(val)}
+ variableBlock={{
+ show: true,
+ variables: data.config?.inputs?.input_param.map((input) => {
+ return {
+ name: input.name!,
+ value: input.name!,
+ };
+ }),
+ }}
+ />
+
+ }
+ />
+ {/* Part4 Outputer */}
+
+ {(data.config?.outputs || []).map((output) => (
+
+ ))}
+ >
+ }
+ />
+
+
+ );
+};
diff --git a/web/packages/magent-flow/src/components/Node/NodeWrapper/Header/index.tsx b/web/packages/magent-flow/src/components/Node/NodeWrapper/Header/index.tsx
new file mode 100644
index 0000000..41c7f5a
--- /dev/null
+++ b/web/packages/magent-flow/src/components/Node/NodeWrapper/Header/index.tsx
@@ -0,0 +1,18 @@
+import { EllipsisOutlined, PlayCircleFilled } from '@ant-design/icons';
+import React from 'react';
+
+export const NodeHeader = (props: { icon: React.JSX.Element; name: string }) => {
+ const { icon, name } = props;
+ return (
+
+ );
+};
diff --git a/web/packages/magent-flow/src/components/Node/NodeWrapper/Status/index.tsx b/web/packages/magent-flow/src/components/Node/NodeWrapper/Status/index.tsx
new file mode 100644
index 0000000..e85322e
--- /dev/null
+++ b/web/packages/magent-flow/src/components/Node/NodeWrapper/Status/index.tsx
@@ -0,0 +1,73 @@
+import { classNames } from '@/utils/basic';
+import { Popover, Tag } from 'antd';
+import React from 'react';
+
+export enum RunStatusEnum {
+ Success = 'success',
+ Processing = 'processing',
+ Warning = 'warning',
+ Error = 'error',
+}
+
+export const RunStatusMap = {
+ [RunStatusEnum.Success]: {
+ Label: '运行成功',
+ Color: 'green',
+ Cssclsname: 'bg-green-50',
+ },
+ [RunStatusEnum.Processing]: {
+ Label: '运行中',
+ Color: 'blue',
+ Cssclsname: 'bg-blue-50',
+ },
+ [RunStatusEnum.Warning]: {
+ Label: '警告',
+ Color: 'yellow',
+ Cssclsname: 'bg-yellow-50',
+ },
+ [RunStatusEnum.Error]: {
+ Label: '运行失败',
+ Color: 'red',
+ Cssclsname: 'bg-red-50',
+ },
+};
+
+export interface RunResStatus {
+ status: RunStatusEnum;
+ runDuration: number;
+ runInput?: Record;
+ runOutput?: Record;
+}
+
+export const NodeStatus = (props: RunResStatus) => {
+ const { status, runDuration } = props;
+
+ const StatusInfo = RunStatusMap[status];
+ return (
+
+
+ {StatusInfo.Label}
+
+ {`${runDuration}s`}
+
+
+ 输入:
+ 输出:
+ >
+ }
+ >
+ 运行结果
+
+
+ );
+};
diff --git a/web/packages/magent-flow/src/components/Node/NodeWrapper/index.tsx b/web/packages/magent-flow/src/components/Node/NodeWrapper/index.tsx
new file mode 100644
index 0000000..2d6381b
--- /dev/null
+++ b/web/packages/magent-flow/src/components/Node/NodeWrapper/index.tsx
@@ -0,0 +1,91 @@
+import { Handle, Position } from '@xyflow/react';
+import { Space } from 'antd';
+import React from 'react';
+
+import type { NodeDataType } from '@/interfaces/flow';
+import { classNames } from '@/utils';
+
+type Props = {
+ data: NodeDataType;
+ selected: boolean;
+ xPos: number;
+ yPos: number;
+};
+
+export const NodeWrapper = (props: {
+ nodeProps: Props;
+ children: React.ReactElement;
+ leftHandler?: boolean;
+ rightHandler?: boolean;
+ rightHandlerConfig?: {
+ id: string;
+ style: Record;
+ }[];
+}) => {
+ const {
+ nodeProps,
+ children,
+ leftHandler = true,
+ rightHandler = true,
+ rightHandlerConfig,
+ } = props;
+ const { name, description, icon } = nodeProps.data;
+ console.log('🚀 ~ nodeProps.selected:', nodeProps.selected);
+ // const runRes = {};
+ // const validationStatus = true;
+
+ return (
+
+ {/*
*/}
+
+
+ {icon && }
+ {name}
+
+
+ {leftHandler && (
+
+ )}
+ {rightHandler &&
+ (rightHandlerConfig ? (
+ <>
+ {rightHandlerConfig.map((item) => (
+
+ ))}
+ >
+ ) : (
+
+ ))}
+
+
+
{children}
+
+ );
+};
diff --git a/web/packages/magent-flow/src/components/Node/StartNode/index.tsx b/web/packages/magent-flow/src/components/Node/StartNode/index.tsx
new file mode 100644
index 0000000..555da9c
--- /dev/null
+++ b/web/packages/magent-flow/src/components/Node/StartNode/index.tsx
@@ -0,0 +1,34 @@
+import { VariableForm } from '@/components/VariableForm';
+import { NodeDataType } from '@/interfaces/flow';
+import { Collapse } from 'antd';
+import React from 'react';
+import { NodeWrapper } from '../NodeWrapper';
+
+type Props = {
+ data: NodeDataType;
+ selected: boolean;
+ xPos: number;
+ yPos: number;
+};
+
+export const StartNode = (props: Props) => {
+ const { data } = props;
+
+ return (
+
+
+ {/* */}
+
+ {
+ console.log('qianyan', values);
+ }}
+ />
+
+
+ );
+};
diff --git a/web/packages/magent-flow/src/components/Node/index.tsx b/web/packages/magent-flow/src/components/Node/index.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/web/packages/magent-flow/src/components/NodePanel/index.tsx b/web/packages/magent-flow/src/components/NodePanel/index.tsx
new file mode 100644
index 0000000..d97e01b
--- /dev/null
+++ b/web/packages/magent-flow/src/components/NodePanel/index.tsx
@@ -0,0 +1,70 @@
+import { NodeDataType } from '@/interfaces/flow';
+import { Input } from 'antd';
+import React from 'react';
+
+interface NodesPanelProps {
+ /**
+ * @title 模板节点配置
+ */
+ className?: string;
+ nodes: NodeDataType[];
+ // allowfold?: boolean;
+ allowSearch?: boolean;
+ // grouped?: boolean;
+}
+
+export const NodesPanel = (props: NodesPanelProps) => {
+ const { nodes, allowSearch = false, className = '' } = props;
+
+ function onDragStart(
+ event: React.DragEvent,
+ data: { type: string; node?: NodeDataType },
+ ): void {
+ //start drag event
+ // eslint-disable-next-line no-var
+ var crt = event.currentTarget.cloneNode(true);
+
+ crt.style.position = 'absolute';
+ crt.style.top = '-500px';
+ crt.style.right = '-500px';
+ crt.classList.add('cursor-grabbing');
+ document.body.appendChild(crt);
+ event.dataTransfer.setDragImage(crt, 0, 0);
+ event.dataTransfer.setData('nodedata', JSON.stringify(data));
+ }
+
+ return (
+
+ {allowSearch && (
+
{
+ nodes.filter((node) => node.name.includes(e.target.value));
+ }}
+ />
+ )}
+ {nodes.sort().map((node) => (
+
+ onDragStart(event, {
+ type: node.type,
+ node: node,
+ })
+ }
+ onDragEnd={() => {
+ document.body.removeChild(
+ document.getElementsByClassName('cursor-grabbing')[0],
+ );
+ }}
+ >
+ {node.icon &&
}
+
{node.name}
+
+ ))}
+ <>>
+
+ );
+};
diff --git a/web/packages/magent-flow/src/components/RefForm/index.md b/web/packages/magent-flow/src/components/RefForm/index.md
new file mode 100644
index 0000000..5be9d1e
--- /dev/null
+++ b/web/packages/magent-flow/src/components/RefForm/index.md
@@ -0,0 +1,31 @@
+---
+title: RefForm
+group: { title: 'Schema', order: 2 }
+toc: menu
+order: 1
+demo: { cols: 2 }
+---
+
+## 基本用法
+
+> 渲染输入参数表单,支持传入节点引用数据
+
+```jsx
+import React from 'react';
+import { RefForm, FormSchema, StartNode } from '@alipay/ai-workflow';
+
+const startNode = new StartNode();
+startNode.input.updateSchema({
+ type: 'object',
+ properties: {
+ name: {
+ type: 'string',
+ title: '姓名',
+ },
+ },
+});
+
+export default () => Hi, bigfish;
+```
+
+
diff --git a/web/packages/magent-flow/src/components/ReferenceForm/index.tsx b/web/packages/magent-flow/src/components/ReferenceForm/index.tsx
new file mode 100644
index 0000000..e68591f
--- /dev/null
+++ b/web/packages/magent-flow/src/components/ReferenceForm/index.tsx
@@ -0,0 +1,117 @@
+import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
+import { Button, Form, Input, Space } from 'antd';
+import React, { useEffect } from 'react';
+
+import type { BasicSchema, NodeType } from '@/interfaces/flow';
+
+import { CollapseWrapper } from '../AIBasic/CollapseWrapper';
+import { ReferenceSelect } from '../ReferenceSelect';
+
+export interface RefrenceFormProps {
+ label: string;
+ values: BasicSchema[];
+ onChange: (values: []) => void;
+ nodes: NodeType[];
+ dynamic?: boolean;
+}
+
+export const ReferenceForm = (props: RefrenceFormProps) => {
+ const { label, values, onChange, nodes, dynamic = false } = props;
+
+ const [form] = Form.useForm();
+
+ useEffect(() => {
+ form.setFieldValue('variables', values);
+ }, []);
+ console.log('🚀 ~ useEffect ~ values:', values);
+
+ const options = nodes.map((node) => {
+ return {
+ label: node.data.name,
+ value: node.data.id,
+ children: node.data?.config?.outputs?.map((output) => {
+ return {
+ label: output.name,
+ value: output.name,
+ };
+ }),
+ };
+ });
+
+ return (
+ {
+ console.log('🚀 ~ form.validateFields ~ allFields:', allFields);
+ form.validateFields().then(() => {
+ if (allFields.variables) {
+ onChange(allFields.variables.filter((item: any) => item !== undefined));
+ }
+ });
+ }}
+ >
+
+
+ {() => (
+ <>
+
+ 参数名
+ 变量值
+
+ >
+ )}
+
+
+
+ {(fields, { add, remove }) => (
+ <>
+ {fields.map(({ key, name, ...restField }) => (
+
+
+
+
+
+
+
+
+ {dynamic && (
+ remove(name)}
+ />
+ )}
+
+ ))}
+ {dynamic && (
+
+
+
+ )}
+ >
+ )}
+
+
+ }
+ />
+ );
+};
diff --git a/web/packages/magent-flow/src/components/ReferenceSelect/index.tsx b/web/packages/magent-flow/src/components/ReferenceSelect/index.tsx
new file mode 100644
index 0000000..04c1991
--- /dev/null
+++ b/web/packages/magent-flow/src/components/ReferenceSelect/index.tsx
@@ -0,0 +1,61 @@
+import { Input } from 'antd';
+import React from 'react';
+import { CascaderInNode } from '../AIBasic/CascaderInNode';
+import { SelectInNode } from '../AIBasic/SelectInNode';
+
+export const ReferenceSelect = (props: {
+ value?: {
+ type: 'reference' | 'value';
+ content?: string | [string, string];
+ };
+ onChange?: (value: {
+ type: 'reference' | 'value';
+ content?: string | [string, string];
+ }) => void;
+ refOptions: { label: string; content: string }[];
+}) => {
+ const { value, onChange, refOptions } = props;
+ console.log('🚀 ~ value:', value);
+
+ return (
+
+
+ onChange?.({
+ type: val,
+ })
+ }
+ options={[
+ { label: '引用', value: 'reference' },
+ { label: '值', value: 'value' },
+ ]}
+ />
+
+ {value?.type === 'value' ? (
+
+ onChange?.({
+ type: value.type,
+ content: e.target.value,
+ })
+ }
+ />
+ ) : (
+
+ onChange?.({
+ type: value?.type,
+ content: val,
+ })
+ }
+ options={refOptions}
+ />
+ )}
+
+ );
+};
diff --git a/web/packages/magent-flow/src/components/VariableForm/index.tsx b/web/packages/magent-flow/src/components/VariableForm/index.tsx
new file mode 100644
index 0000000..94a783e
--- /dev/null
+++ b/web/packages/magent-flow/src/components/VariableForm/index.tsx
@@ -0,0 +1,148 @@
+import {
+ CaretRightOutlined,
+ MinusCircleOutlined,
+ PlusOutlined,
+} from '@ant-design/icons';
+import { Button, Checkbox, Collapse, Form, Input, Space } from 'antd';
+import React, { useEffect } from 'react';
+
+import type { BasicSchema } from '@/interfaces/flow';
+
+import { SelectInNode } from '../AIBasic/SelectInNode';
+
+export interface VariableFormProps {
+ label: string;
+ values: BasicSchema[];
+ onChange: (values: BasicSchema[]) => void;
+ dynamic?: boolean;
+ showRequired?: boolean;
+}
+
+export const VariableForm = (props: VariableFormProps) => {
+ const { label, values, onChange, dynamic = true, showRequired = true } = props;
+ const onFinish = (values: any) => {
+ console.log('Received values of form:', values);
+ };
+ const [form] = Form.useForm();
+
+ useEffect(() => {
+ form.setFieldValue('variables', values);
+ }, []);
+
+ return (
+ }
+ items={[
+ {
+ key: '1',
+ label: label,
+ children: (
+
+ {(fields, { add, remove }) => (
+ <>
+ {fields.map(({ key, name, ...restField }) => (
+
+
+
+
+
+ ',
+ value: 'Array',
+ },
+ ]}
+ placeholder=""
+ />
+
+ {/*
+
+ */}
+ {showRequired && (
+
+
+
+ )}
+ {dynamic && (
+ remove(name)}
+ />
+ )}
+
+ ))}
+ {dynamic && (
+
+
+
+ )}
+ >
+ )}
+
+
+ ),
+ },
+ ]}
+ />
+ );
+};
diff --git a/web/packages/magent-flow/src/constants/constant.ts b/web/packages/magent-flow/src/constants/constant.ts
new file mode 100644
index 0000000..2f67d19
--- /dev/null
+++ b/web/packages/magent-flow/src/constants/constant.ts
@@ -0,0 +1,96 @@
+export const IS_MAC = navigator.userAgent.toUpperCase().includes('MAC');
+
+export const defaultShortcuts = [
+ {
+ name: 'Advanced Settings',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + Shift + A`,
+ },
+ {
+ name: 'Minimize',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + Q`,
+ },
+ {
+ name: 'Code',
+ shortcut: `Space`,
+ },
+ {
+ name: 'Copy',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + C`,
+ },
+ {
+ name: 'Duplicate',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + D`,
+ },
+ {
+ name: 'Component Share',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + Shift + S`,
+ },
+ {
+ name: 'Docs',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + Shift + D`,
+ },
+ {
+ name: 'Save',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + S`,
+ },
+ {
+ name: 'Delete',
+ shortcut: 'Backspace',
+ },
+ {
+ name: 'Open playground',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + K`,
+ },
+ {
+ name: 'Undo',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + Z`,
+ },
+ {
+ name: 'Redo',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + Y`,
+ },
+ {
+ name: 'Group',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + G`,
+ },
+ {
+ name: 'Cut',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + X`,
+ },
+ {
+ name: 'Paste',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + V`,
+ },
+ {
+ name: 'API',
+ shortcut: `R`,
+ },
+ {
+ name: 'Download',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + J`,
+ },
+ {
+ name: 'Update',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + U`,
+ },
+ {
+ name: 'Freeze',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + F`,
+ },
+ {
+ name: 'Freeze Path',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + Shift + F`,
+ },
+ {
+ name: 'Flow Share',
+ shortcut: `${IS_MAC ? 'Cmd' : 'Ctrl'} + B`,
+ },
+ {
+ name: 'Play',
+ shortcut: `P`,
+ },
+ {
+ name: 'Output Inspection',
+ shortcut: `O`,
+ },
+];
diff --git a/web/packages/magent-flow/src/context/event-emitter.tsx b/web/packages/magent-flow/src/context/event-emitter.tsx
new file mode 100644
index 0000000..9ac57dc
--- /dev/null
+++ b/web/packages/magent-flow/src/context/event-emitter.tsx
@@ -0,0 +1,30 @@
+'use client';
+import { useEventEmitter } from 'ahooks';
+import type { EventEmitter } from 'ahooks/lib/useEventEmitter';
+import React, { createContext, useContext } from 'react';
+// import { createContext, useContext } from 'use-context-selector';
+
+const EventEmitterContext = createContext<{
+ eventEmitter: EventEmitter | null;
+}>({
+ eventEmitter: null,
+});
+
+export const useEventEmitterContextContext = () => useContext(EventEmitterContext);
+
+type EventEmitterContextProviderProps = {
+ children: React.ReactNode;
+};
+export const EventEmitterContextProvider = ({
+ children,
+}: EventEmitterContextProviderProps) => {
+ const eventEmitter = useEventEmitter();
+
+ return (
+
+ {children}
+
+ );
+};
+
+export default EventEmitterContext;
diff --git a/web/packages/magent-flow/src/index.ts b/web/packages/magent-flow/src/index.ts
new file mode 100644
index 0000000..dc5c313
--- /dev/null
+++ b/web/packages/magent-flow/src/index.ts
@@ -0,0 +1,8 @@
+export { default as Flow } from './components/Flow';
+export { FlowWithPanel } from './components/FlowWithPanel';
+export { FormSchema } from './FormSchema';
+export { RefForm } from './RefForm';
+export { SchemaConfigForm } from './SchemaConfigForm';
+export { StartNode } from './spec/node';
+export * from './utils/index.js';
+import './tailwind.out.css';
diff --git a/web/packages/magent-flow/src/interfaces/flow.ts b/web/packages/magent-flow/src/interfaces/flow.ts
new file mode 100644
index 0000000..c6e1f96
--- /dev/null
+++ b/web/packages/magent-flow/src/interfaces/flow.ts
@@ -0,0 +1,108 @@
+import { ReactFlowJsonObject, XYPosition } from '@xyflow/react';
+
+export enum NodeTypeEnum {
+ 'Start' = 'start',
+ 'End' = 'end',
+ 'LLM' = 'llm',
+ 'Knowledge' = 'knowledge',
+ 'Agent' = 'agent',
+
+ // 'Plugin' = 'plugin',
+ 'Tool' = 'tool',
+ 'IfElse' = 'ifelse',
+}
+
+export enum IfElseNodeCompareType {
+ Equal = 'equal',
+ NotEqual = 'notequal',
+ Blank = 'blank',
+}
+
+export interface LiteralValueType {
+ type: 'value';
+ content?: string | number | boolean | string[] | number[] | boolean[];
+}
+
+export interface RefValueType {
+ type: 'reference';
+ content?: {
+ source: string;
+ blockID: string;
+ name: string;
+ };
+}
+
+export interface BasicSchema {
+ type: string;
+ name?: string;
+ value?: LiteralValueType | RefValueType;
+ required?: boolean;
+ // BasicSchema 对应 type = list,BasicSchema[] 对应 type = object
+ schema?: BasicSchema | BasicSchema[];
+ description?: string;
+}
+
+export interface NodeDataConfigType {
+ inputs?: {
+ input_param: BasicSchema[];
+ [key: string]: BasicSchema[];
+ };
+ outputs?: BasicSchema[];
+}
+
+// export interface NodeDataMetaType {
+// name: string;
+// icon?: string;
+// description?: string;
+// }
+
+export interface NodeDataType {
+ id: string | number;
+ type: NodeTypeEnum;
+ runResult?: {
+ status: string;
+ result?: any;
+ };
+ name: string;
+ icon?: string;
+ description?: string;
+ config?: NodeDataConfigType;
+}
+
+export interface NodeType {
+ id: string;
+ position: XYPosition;
+ type: string;
+ data: NodeDataType;
+ selected?: boolean;
+}
+
+export type FlowType = {
+ id: string;
+ name: string;
+ icon?: string;
+ description: string;
+ data: ReactFlowJsonObject | null;
+ //
+ updated_at?: string;
+ date_created?: string;
+ user_id?: string;
+};
+
+// right side
+export type sourceHandleType = {
+ dataType: string;
+ id: string;
+ output_types: string[];
+ conditionalPath?: string | null;
+ name: string;
+};
+
+//left side
+export type targetHandleType = {
+ inputTypes?: string[];
+ type: string;
+ fieldName: string;
+ id: string;
+ proxy?: { field: string; id: string };
+};
diff --git a/web/packages/magent-flow/src/spec/FormSchema/index.ts b/web/packages/magent-flow/src/spec/FormSchema/index.ts
new file mode 100644
index 0000000..3bc0582
--- /dev/null
+++ b/web/packages/magent-flow/src/spec/FormSchema/index.ts
@@ -0,0 +1,328 @@
+import { message } from 'antd';
+import type {
+ JSONSchema7,
+ JSONSchema7Definition,
+ JSONSchema7TypeName,
+} from 'json-schema';
+
+import { UUID } from '../uuid.js';
+
+export type OrderJSONSchema7 = JSONSchema7 & {
+ order: number;
+};
+
+export interface CascaderOptions {
+ value: string;
+ label: string;
+ children?: CascaderOptions[];
+}
+
+/**
+ * 声明输入的表单数据格式
+ * 表单内容
+ */
+export class FormSchema {
+ uuid = UUID.getInstance().uniqueID();
+
+ jsonschema: JSONSchema7 = {
+ $id: this.uuid,
+ type: 'object',
+ properties: {},
+ required: [],
+ };
+
+ /**
+ * 获取指定路径的属性
+ * 方便添加属性
+ * /a/b/c/
+ * @param pointer
+ * @returns
+ */
+ getSchemaByPoint(pointer: string) {
+ if (pointer === '/' || pointer === '') {
+ return this.jsonschema;
+ }
+
+ let pointers = pointer.split('/');
+ if (pointers[0] !== '') {
+ throw new Error('invalid pointer');
+ }
+ pointers = pointers.slice(1);
+
+ // base是一个object模式
+ let schema = this.jsonschema;
+ while (pointers.length > 0) {
+ const pointer = pointers.shift();
+ if (pointer === undefined) {
+ throw new Error('invalid pointer');
+ }
+ if (schema) {
+ if (schema.type === 'object') {
+ if (schema?.properties?.[pointer]) {
+ // 有就递归下沉
+ schema = schema.properties[pointer] as JSONSchema7;
+ } else {
+ // 没有属性就添加
+ schema!.properties![pointer] = {};
+ return schema!.properties![pointer];
+ }
+ } else if (schema?.type === 'array') {
+ if (schema?.items) {
+ const index = parseInt(pointer);
+ if (Array.isArray(schema.items)) {
+ schema = schema.items[index] as JSONSchema7;
+ } else {
+ schema = schema.items as JSONSchema7;
+ }
+ }
+ }
+ }
+ }
+ return schema;
+ }
+
+ private randommName = () => {
+ return (
+ 'RandaomName__-' +
+ Math.random().toString(36).substring(2, 15) +
+ Math.random().toString(36).substring(2, 15)
+ );
+ };
+
+ isRandomName = (name: string) => {
+ return name.startsWith('RandaomName__-');
+ };
+
+ /**
+ * 动态表单添加属性
+ * @param property
+ * @returns
+ */
+ addField = (options: {
+ pointer: string; // 指定属性路径,如 /a/b
+ name?: string;
+ type: JSONSchema7TypeName;
+ description: string;
+ required: boolean;
+ }) => {
+ const { pointer, name = this.randommName(), type, description, required } = options;
+ if (typeof this.jsonschema !== 'boolean') {
+ const schema = this.getSchemaByPoint(pointer);
+ if (schema.type === 'array') {
+ // 如果存在属性
+ if (!schema?.items) {
+ schema.items = {
+ type: type,
+ description,
+ };
+ } else if (!Array.isArray(schema?.items)) {
+ const items = schema.items as JSONSchema7Definition;
+ schema.items = [
+ items,
+ {
+ type: type,
+ description,
+ },
+ ];
+ } else if (Array.isArray(schema?.items)) {
+ schema.items.push({
+ type: type,
+ description,
+ });
+ }
+ } else if (schema?.type === 'object') {
+ // 使用order 记录顺序
+ let order = 0;
+ Object.entries(schema.properties || {}).forEach(([, val]) => {
+ const v = val as OrderJSONSchema7;
+ if (v?.order) {
+ order = v?.order > order ? v?.order : order;
+ }
+ });
+
+ (schema.properties![name] as OrderJSONSchema7) = {
+ type: type,
+ description,
+ order: order + 1,
+ };
+ if (type === 'object') {
+ schema.properties![name].properties = {};
+ }
+ } else {
+ schema.type = type;
+ schema.description = description;
+ }
+ if (required) {
+ // 如果是object的话,require在当前位置添加
+ if (schema.type === 'object') {
+ if (!schema.required) {
+ schema.required = [];
+ }
+ schema.required = [...schema.required, name];
+ } else {
+ // 在父级添加
+ const parentPointer = pointer.split('/').slice(0, -1).join('/');
+ const parentSchema = this.getSchemaByPoint(parentPointer);
+
+ if (!parentSchema.required) {
+ parentSchema.required = [];
+ }
+ parentSchema.required = [...parentSchema.required, name];
+ }
+ }
+ }
+ return false;
+ };
+
+ /**
+ * 动态表单更新属性
+ * @param property
+ * @returns
+ */
+ updateField = (options: {
+ pointer: string; // 指定属性路径,如 /a/b
+ key: 'variableName' | 'variableType' | 'description' | 'required';
+ value: any;
+ currentVariableName: string;
+ }) => {
+ const { pointer, key, value, currentVariableName } = options;
+ if (typeof this.jsonschema !== 'boolean') {
+ const schema = this.getSchemaByPoint(pointer);
+ if (schema.type === 'object') {
+ if (schema.properties) {
+ if (key === 'variableName') {
+ const old = schema.properties?.[currentVariableName];
+ if (value !== currentVariableName) {
+ schema.properties[value] = old;
+ delete schema.properties[currentVariableName];
+ } else {
+ message.info('变量名不能和已有变量名相同');
+ return false;
+ }
+ return true;
+ }
+ if (key === 'variableType') {
+ if ((schema.properties[currentVariableName] as JSONSchema7).type) {
+ // 处理数组类型
+ if (value.startsWith('Array<')) {
+ const t = (
+ value.replace('Array<', '').replace('>', '') as string
+ ).toLocaleLowerCase();
+ schema.properties[currentVariableName].type = 'array';
+ schema.properties[currentVariableName].items = {
+ type: t,
+ };
+ if (t === 'object') {
+ schema.properties[currentVariableName].items.properties = {};
+ }
+ return true;
+ }
+ if (value === 'object') {
+ schema.properties[currentVariableName].type = value;
+ schema.properties[currentVariableName].properties = {};
+ return true;
+ }
+
+ // 基础类型
+ schema.properties[currentVariableName].type = value;
+ delete schema.properties[currentVariableName].items;
+ delete schema.properties[currentVariableName].properties;
+
+ return true;
+ }
+ }
+ if (key === 'description') {
+ if (schema.properties[currentVariableName] as JSONSchema7) {
+ schema.properties[currentVariableName].description = value;
+ return true;
+ }
+ }
+ if (key === 'required') {
+ if (!this.isRandomName(currentVariableName)) {
+ if (schema.properties[currentVariableName]) {
+ if (!schema.required) {
+ schema.required = [];
+ }
+ if (value) {
+ if (!schema.required?.includes(value)) {
+ schema.required?.push(currentVariableName);
+ }
+ } else {
+ if (schema.required?.includes(currentVariableName)) {
+ schema.required = schema.required.filter(
+ (item) => item !== currentVariableName,
+ );
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ };
+
+ updateSchema(schema: JSONSchema7) {
+ Object.assign(this.jsonschema, schema);
+ }
+
+ log() {
+ return JSON.stringify(this.jsonschema, null, 4);
+ }
+}
+
+export const variableTypeOptions: {
+ label: string;
+ value:
+ | JSONSchema7TypeName
+ | 'Array'
+ | 'Array'
+ | 'Array'
+ | 'Array'
+ | 'Array';
+}[] = [
+ {
+ label: 'String',
+ value: 'string',
+ },
+ {
+ label: 'Integer',
+ value: 'integer',
+ },
+ {
+ label: 'Boolean',
+ value: 'boolean',
+ },
+ {
+ label: 'Number',
+ value: 'number',
+ },
+ {
+ label: 'Object',
+ value: 'object',
+ },
+
+ {
+ label: 'Array',
+ value: 'Array',
+ },
+ {
+ label: 'Array',
+ value: 'Array',
+ },
+ {
+ label: 'Array',
+ value: 'Array',
+ },
+ {
+ label: 'Array',
+ value: 'Array',
+ },
+ {
+ label: 'Array',
+ value: 'Array',
+ },
+];
diff --git a/web/packages/magent-flow/src/spec/__snapshots__/node.test.ts.snap b/web/packages/magent-flow/src/spec/__snapshots__/node.test.ts.snap
new file mode 100644
index 0000000..6729cd7
--- /dev/null
+++ b/web/packages/magent-flow/src/spec/__snapshots__/node.test.ts.snap
@@ -0,0 +1,65 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`addField 添加表单field 1`] = `
+"{
+ "$id": "5",
+ "type": "object",
+ "properties": {
+ "a": {
+ "type": "object",
+ "description": "this is a",
+ "order": 1,
+ "properties": {}
+ }
+ },
+ "required": []
+}"
+`;
+
+exports[`addField 添加表单field1 1`] = `
+"{
+ "$id": "6",
+ "type": "object",
+ "properties": {
+ "a": {
+ "type": "object",
+ "description": "this is a",
+ "order": 1,
+ "properties": {
+ "b": {
+ "type": "string",
+ "description": "this is desc"
+ },
+ "subA": {
+ "type": "object",
+ "description": "this is desc",
+ "order": 1,
+ "properties": {
+ "aryC": {
+ "type": "array",
+ "description": "this is desc",
+ "order": 1
+ }
+ },
+ "required": [
+ "aryC"
+ ]
+ }
+ },
+ "required": [
+ "b",
+ "subA"
+ ]
+ },
+ "first": {
+ "type": "object",
+ "description": "this is a",
+ "order": 2,
+ "properties": {}
+ }
+ },
+ "required": [
+ "first"
+ ]
+}"
+`;
diff --git a/web/packages/magent-flow/src/spec/node.test.ts b/web/packages/magent-flow/src/spec/node.test.ts
new file mode 100644
index 0000000..02375ee
--- /dev/null
+++ b/web/packages/magent-flow/src/spec/node.test.ts
@@ -0,0 +1,199 @@
+import { FormSchema } from './FormSchema';
+
+describe('getSchemaByPoint', () => {
+ it('基础路径 /', () => {
+ const input = new FormSchema();
+ input.jsonschema = {
+ type: 'object',
+ properties: {
+ a: {
+ type: 'string',
+ description: 'this is a',
+ },
+ b: {
+ type: 'object',
+ properties: {
+ c: {
+ type: 'array',
+ items: {
+ type: 'string',
+ },
+ },
+ },
+ },
+ },
+ };
+
+ expect(input.getSchemaByPoint('/')).toEqual({
+ type: 'object',
+ properties: {
+ a: {
+ type: 'string',
+ description: 'this is a',
+ },
+ b: {
+ type: 'object',
+ properties: {
+ c: {
+ type: 'array',
+ items: {
+ type: 'string',
+ },
+ },
+ },
+ },
+ },
+ });
+ });
+
+ it('如果对应路径没有参数,应该创建一个properties对象,并且返回该对象', () => {
+ const input = new FormSchema();
+ input.jsonschema = {
+ type: 'object',
+ properties: {},
+ };
+
+ const got = input.getSchemaByPoint('/a');
+ // 没有对应的属性
+ expect(got).toEqual({});
+
+ expect(input.jsonschema).toEqual({
+ type: 'object',
+ properties: {
+ a: {},
+ },
+ });
+ });
+
+ it('获取对应的schema', () => {
+ const input = new FormSchema();
+ input.jsonschema = {
+ type: 'object',
+ properties: {
+ a: {
+ type: 'string',
+ description: 'this is a',
+ },
+ b: {
+ type: 'object',
+ properties: {
+ c: {
+ type: 'array',
+ items: {
+ type: 'string',
+ },
+ },
+ },
+ },
+ },
+ };
+ expect(input.getSchemaByPoint('/a')).toEqual({
+ type: 'string',
+ description: 'this is a',
+ });
+
+ expect(input.getSchemaByPoint('/b')).toEqual({
+ type: 'object',
+ properties: {
+ c: {
+ type: 'array',
+ items: {
+ type: 'string',
+ },
+ },
+ },
+ });
+ });
+
+ it('数组则返回对应的数组对象', () => {
+ const input = new FormSchema();
+ input.jsonschema = {
+ type: 'object',
+ properties: {
+ a: {
+ type: 'string',
+ description: 'this is a',
+ },
+ b: {
+ type: 'object',
+ properties: {
+ c: {
+ type: 'array',
+ items: {
+ type: 'string',
+ },
+ },
+ },
+ },
+ },
+ };
+
+ // 数组则返回对应的对象
+ expect(input.getSchemaByPoint('/b/c')).toEqual({
+ type: 'array',
+ items: {
+ type: 'string',
+ },
+ });
+ });
+});
+
+describe('addField', () => {
+ it('添加表单field', () => {
+ const input = new FormSchema();
+ input.addField({
+ pointer: '/', // 指定属性路径,如 /a/b
+ name: 'a',
+ type: 'object',
+ description: 'this is a',
+ required: false,
+ });
+ const got = input.log();
+ console.log(got, '==got');
+ expect(got).toMatchSnapshot();
+ // expect(1).toBe(0);
+ });
+
+ it('添加表单field1', () => {
+ const input = new FormSchema();
+ input.addField({
+ pointer: '/', // 指定属性路径,如 /a/b
+ name: 'a',
+ type: 'object',
+ description: 'this is a',
+ required: false,
+ });
+ console.log(input.log(), 'log1');
+ input.addField({
+ pointer: '/a/b', // 指定属性路径,如 /a/b
+ name: 'b',
+ type: 'string',
+ description: 'this is desc',
+ required: true,
+ });
+ input.addField({
+ pointer: '/a', // 指定属性路径,如 /a/b
+ name: 'subA',
+ type: 'object',
+ description: 'this is desc',
+ required: true,
+ });
+ input.addField({
+ pointer: '/a/subA', // 指定属性路径,如 /a/b
+ name: 'aryC',
+ type: 'array',
+ description: 'this is desc',
+ required: true,
+ });
+ input.addField({
+ pointer: '/', // 指定属性路径,如 /a/b
+ name: 'first',
+ type: 'object',
+ description: 'this is a',
+ required: true,
+ });
+ const got = input.log();
+ console.log(got);
+ expect(got).toMatchSnapshot();
+ });
+});
diff --git a/web/packages/magent-flow/src/spec/node.ts b/web/packages/magent-flow/src/spec/node.ts
new file mode 100644
index 0000000..3994e02
--- /dev/null
+++ b/web/packages/magent-flow/src/spec/node.ts
@@ -0,0 +1,82 @@
+import {
+ NodeDataConfigType,
+ NodeDataMetaType,
+ NodeDataType,
+ NodeTypeEnum,
+} from '@/interfaces/flow';
+import { FormSchema } from './FormSchema';
+import { UUID } from './uuid';
+
+// 不同类型的节点的基础类
+//
+
+/**
+ * 开始节点
+ * 只设置输入
+ * 输出和输入一致
+ */
+export class StartNode implements NodeDataType {
+ id: string = UUID.getInstance().uniqueID();
+
+ type: NodeTypeEnum = NodeTypeEnum.Start;
+
+ config: NodeDataConfigType | undefined = {
+ params: undefined,
+ inputs: new FormSchema(),
+ outputs: new FormSchema(),
+ };
+
+ nodeMeta: NodeDataMetaType = {
+ title: '开始节点',
+ description: '开始节点',
+ };
+
+ toJson() {
+ const node: NodeDataType = {
+ id: this.id,
+ nodeType: this.nodeType,
+ nodeMeta: this.nodeMeta,
+ config: this.config,
+ };
+ return JSON.stringify(node);
+ }
+
+ fromJson(json: string) {
+ try {
+ const node: NodeDataType = JSON.parse(json);
+
+ this.id = node.id;
+ this.nodeType = node.nodeType;
+ this.nodeMeta = node.nodeMeta;
+ this.config = node.config;
+ } catch (error) {}
+ }
+
+ toXYFlowJson() {}
+}
+
+// /**
+// * 插件节点
+// */
+// export class PluginNode implements FlowNode {
+// extend(e) {}
+// }
+// class BingPluginNode extends PluginNode {}
+
+// new BingPluginNode().extend({
+// inpot: (JSONSchema = {
+// type: 'object',
+// properties: {
+// count: {
+// type: 'integer',
+// },
+// offset: {
+// type: 'integer',
+// },
+// query: {
+// type: 'string',
+// },
+// },
+// required: ['a'],
+// }),
+// });
diff --git a/web/packages/magent-flow/src/spec/test-jsonschema.json b/web/packages/magent-flow/src/spec/test-jsonschema.json
new file mode 100644
index 0000000..6a3b36f
--- /dev/null
+++ b/web/packages/magent-flow/src/spec/test-jsonschema.json
@@ -0,0 +1,87 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "type": "object",
+ "properties": {
+ "a": {
+ "type": "integer"
+ },
+ "b": {
+ "type": "string"
+ },
+ "c": {
+ "type": "boolean"
+ },
+ "e": {
+ "type": "object",
+ "properties": {
+ "f": {
+ "type": "integer"
+ },
+ "g": {
+ "type": "string"
+ },
+ "h": {
+ "type": "boolean"
+ },
+ "j": {
+ "type": "object",
+ "properties": {
+ "k": {
+ "type": "integer"
+ },
+ "l": {
+ "type": "string"
+ },
+ "m": {
+ "type": "boolean"
+ }
+ },
+ "required": ["k", "l", "m", "n"]
+ }
+ },
+ "required": ["f", "g", "h", "i", "j"]
+ },
+ "f": {
+ "type": "array",
+ "items": [
+ {
+ "type": "integer"
+ }
+ ]
+ },
+ "g": {
+ "type": "array",
+ "items": [
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "h": {
+ "type": "array",
+ "items": [
+ {
+ "type": "object",
+ "properties": {
+ "i": {
+ "type": "integer"
+ },
+ "j": {
+ "type": "string"
+ },
+ "k": {
+ "type": "array",
+ "items": [
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "required": ["i", "j", "k"]
+ }
+ ]
+ }
+ },
+ "required": ["a", "b", "c", "d", "e", "f", "g", "h"]
+}
diff --git a/web/packages/magent-flow/src/spec/uuid.ts b/web/packages/magent-flow/src/spec/uuid.ts
new file mode 100644
index 0000000..107c8f1
--- /dev/null
+++ b/web/packages/magent-flow/src/spec/uuid.ts
@@ -0,0 +1,21 @@
+export class UUID {
+ private static instance: UUID;
+
+ static getInstance() {
+ if (!UUID.instance) {
+ UUID.instance = new UUID();
+ }
+ return UUID.instance;
+ }
+
+ private _id = 0;
+
+ /**
+ * 返回一个数字id
+ * @returns
+ */
+ uniqueID() {
+ this._id += 1;
+ return this._id.toString();
+ }
+}
diff --git a/web/packages/magent-flow/src/stores/useFlowStore.ts b/web/packages/magent-flow/src/stores/useFlowStore.ts
new file mode 100644
index 0000000..f175086
--- /dev/null
+++ b/web/packages/magent-flow/src/stores/useFlowStore.ts
@@ -0,0 +1,324 @@
+import type {
+ Connection,
+ Edge,
+ EdgeChange,
+ Node,
+ NodeChange,
+ OnEdgesChange,
+ OnNodesChange,
+ ReactFlowInstance,
+ Viewport,
+ XYPosition,
+} from '@xyflow/react';
+import { addEdge, applyEdgeChanges, applyNodeChanges } from '@xyflow/react';
+import { cloneDeep } from 'lodash';
+import { create } from 'zustand';
+
+import type { NodeType } from '@/interfaces/flow';
+import { cleanEdges, getNodeId } from '@/utils/reactflowUtils';
+
+interface AdjacencyList {
+ [key: number]: number[];
+}
+
+interface FlowStoreType {
+ nodes: Node[];
+ edges: Edge[];
+ onNodesChange: OnNodesChange;
+ onEdgesChange: OnEdgesChange;
+
+ reactFlowInstance: ReactFlowInstance | null;
+ setReactFlowInstance: (newState: ReactFlowInstance) => void;
+ setNodes: (
+ update: Node[] | ((oldState: Node[]) => Node[]),
+ skipSave?: boolean,
+ ) => void;
+ setEdges: (
+ update: Edge[] | ((oldState: Edge[]) => Edge[]),
+ skipSave?: boolean,
+ ) => void;
+ setNode: (id: string, update: Node | ((oldState: Node) => Node)) => void;
+ getNode: (id: string) => Node | undefined;
+ deleteNode: (nodeId: string | Array) => void;
+ deleteEdge: (edgeId: string | Array) => void;
+ onConnect: (connection: Connection) => void;
+ getFlow: () => { nodes: Node[]; edges: Edge[]; viewport: Viewport };
+ paste: any;
+
+ findUpstreamNodes: (id: string) => Node[];
+}
+
+export const useFlowStore = create((set, get) => {
+ // DFS 查找上游节点
+ const findUpstreamNodes = (
+ nodes: Node[],
+ edges: Edge[],
+ targetNode: string,
+ ): Node[] => {
+ const adjList: AdjacencyList = {};
+ nodes.forEach((node) => {
+ adjList[node.id] = [];
+ });
+ edges.forEach((edge) => {
+ adjList[edge.source].push(edge.target);
+ });
+
+ const visited = new Set();
+ const result = new Set();
+
+ const dfs = (node: string) => {
+ if (visited.has(node)) {
+ return;
+ }
+ visited.add(node);
+
+ if (adjList[node]) {
+ adjList[node].forEach((upstreamNode) => {
+ result.add(upstreamNode);
+ dfs(upstreamNode);
+ });
+ }
+ };
+
+ console.log('🚀 ~ useFlowStore ~ nodes:', nodes, edges, targetNode);
+ console.log('🚀 ~ adjList', adjList);
+
+ dfs(targetNode);
+ console.log('🚀 ~ result', result);
+ return get().nodes.filter((node) => Array.from(result).includes(node.id));
+ };
+
+ return {
+ nodes: [],
+ edges: [],
+ reactFlowInstance: null,
+ setReactFlowInstance: (newState) => {
+ set({ reactFlowInstance: newState });
+ },
+ getFlow: () => {
+ return {
+ nodes: get().nodes,
+ edges: get().edges,
+ viewport: get().reactFlowInstance?.getViewport() ?? {
+ x: 0,
+ y: 0,
+ zoom: 1,
+ },
+ };
+ },
+ onNodesChange: (changes: NodeChange[]) => {
+ set({
+ nodes: applyNodeChanges(changes, get().nodes),
+ });
+ },
+ onEdgesChange: (changes: EdgeChange[]) => {
+ set({
+ edges: applyEdgeChanges(changes, get().edges),
+ });
+ },
+ setNode: (id: string, change: Node | ((oldState: Node) => Node)) => {
+ const newChange =
+ typeof change === 'function'
+ ? change(get().nodes.find((node) => node.id === id)!)
+ : change;
+ get().setNodes((oldNodes) =>
+ oldNodes.map((node) => {
+ if (node.id === id) {
+ // if ((node.data as NodeDataType).node?.frozen) {
+ // (newChange.data as NodeDataType).node!.frozen = false;
+ // }
+ return newChange;
+ }
+ return node;
+ }),
+ );
+ },
+ setNodes: (change) => {
+ const newChange = typeof change === 'function' ? change(get().nodes) : change;
+ const newEdges = cleanEdges(newChange, get().edges);
+ // const { inputs, outputs } = getInputsAndOutputs(newChange);
+
+ set({
+ edges: newEdges,
+ nodes: newChange,
+ // flowState: undefined,
+ // inputs,
+ // outputs,
+ // hasIO: inputs.length > 0 || outputs.length > 0,
+ });
+
+ // const flowsManager = useFlowsManagerStore.getState();
+ // if (!get().isBuilding && !skipSave && get().onFlowPage) {
+ // flowsManager.autoSaveCurrentFlow(
+ // newChange,
+ // newEdges,
+ // get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 },
+ // );
+ // }
+ },
+
+ setEdges: (change) => {
+ const newChange = typeof change === 'function' ? change(get().edges) : change;
+ set({
+ edges: newChange,
+ // flowState: undefined,
+ });
+
+ // const flowsManager = useFlowsManagerStore.getState();
+ // if (!get().isBuilding && !skipSave && get().onFlowPage) {
+ // flowsManager.autoSaveCurrentFlow(
+ // get().nodes,
+ // newChange,
+ // get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 },
+ // );
+ // }
+ },
+ getNode: (id: string) => {
+ return get().nodes.find((node) => node.id === id);
+ },
+
+ onConnect: (connection) => {
+ let newEdges: Edge[] = [];
+ get().setEdges((oldEdges) => {
+ newEdges = addEdge(
+ {
+ ...connection,
+ data: {
+ targetHandle: connection.targetHandle!,
+ sourceHandle: connection.sourceHandle!,
+ },
+ // style: { stroke: "#555" },
+ type: 'custom',
+ // className: "stroke-foreground stroke-connection",
+ },
+ oldEdges,
+ );
+
+ console.log('🚀 ~ get ~ newEdges:', newEdges);
+ return newEdges;
+ });
+ },
+ deleteNode: (nodeId) => {
+ get().setNodes(
+ get().nodes.filter((node) =>
+ typeof nodeId === 'string' ? node.id !== nodeId : !nodeId.includes(node.id),
+ ),
+ );
+ },
+ deleteEdge: (edgeId) => {
+ get().setEdges(
+ get().edges.filter((edge) =>
+ typeof edgeId === 'string' ? edge.id !== edgeId : !edgeId.includes(edge.id),
+ ),
+ );
+ },
+ paste: (selection: { nodes: Node[]; edge: Edge[] }, position: XYPosition) => {
+ //TODO:页面唯一节点检测
+ // if (
+ // selection.nodes.some((node) => node.data.type === 'ChatInput') &&
+ // checkChatInput(get().nodes)
+ // ) {
+ // useAlertStore.getState().setErrorData({
+ // title: 'Error pasting components',
+ // list: ['You can only have one ChatInput component in the flow'],
+ // });
+ // return;
+ // }
+
+ let minimumX = Infinity;
+ let minimumY = Infinity;
+ // let idsMap = {};
+ let newNodes: Node[] = get().nodes;
+ // let newEdges = get().edges;
+ selection.nodes.forEach((node: Node) => {
+ if (node.position.y < minimumY) {
+ minimumY = node.position.y;
+ }
+ if (node.position.x < minimumX) {
+ minimumX = node.position.x;
+ }
+ });
+
+ const insidePosition = position.paneX
+ ? { x: position.paneX + position.x, y: position.paneY! + position.y }
+ : get().reactFlowInstance!.screenToFlowPosition({
+ x: position.x,
+ y: position.y,
+ });
+
+ selection.nodes.forEach((node: Node) => {
+ // Generate a unique node ID
+ const newId = getNodeId(node.data.type as string);
+
+ // idsMap[node.id] = newId;
+
+ // Create a new node object
+ const newNode: NodeType = {
+ id: newId,
+ type: node.data.type,
+ position: {
+ x: insidePosition.x + node.position!.x - minimumX,
+ y: insidePosition.y + node.position!.y - minimumY,
+ },
+ data: {
+ ...cloneDeep(node.data),
+ id: newId,
+ } as any,
+ };
+ // updateGroupRecursion(
+ // newNode,
+ // selection.edges,
+ // useGlobalVariablesStore.getState().unavaliableFields,
+ // useGlobalVariablesStore.getState().globalVariablesEntries,
+ // );
+
+ // Add the new node to the list of nodes in state
+ newNodes = newNodes
+ .map((node) => ({ ...node, selected: false }))
+ .concat({ ...newNode, selected: false });
+ });
+ get().setNodes(newNodes);
+
+ // selection.edges.forEach((edge: Edge) => {
+ // let source = idsMap[edge.source];
+ // let target = idsMap[edge.target];
+ // const sourceHandleObject: sourceHandleType = scapeJSONParse(
+ // edge.sourceHandle!,
+ // );
+ // let sourceHandle = scapedJSONStringfy({
+ // ...sourceHandleObject,
+ // id: source,
+ // });
+ // sourceHandleObject.id = source;
+
+ // edge.data.sourceHandle = sourceHandleObject;
+ // const targetHandleObject: targetHandleType = scapeJSONParse(
+ // edge.targetHandle!,
+ // );
+ // let targetHandle = scapedJSONStringfy({
+ // ...targetHandleObject,
+ // id: target,
+ // });
+ // targetHandleObject.id = target;
+ // edge.data.targetHandle = targetHandleObject;
+ // let id = getHandleId(source, sourceHandle, target, targetHandle);
+ // newEdges = addEdge(
+ // {
+ // source,
+ // target,
+ // sourceHandle,
+ // targetHandle,
+ // id,
+ // data: cloneDeep(edge.data),
+ // selected: false,
+ // },
+ // newEdges.map((edge) => ({ ...edge, selected: false })),
+ // );
+ // });
+ // get().setEdges(newEdges);
+ },
+ findUpstreamNodes: (id: string) => {
+ return findUpstreamNodes(get().nodes, get().edges, id);
+ },
+ };
+});
diff --git a/web/packages/magent-flow/src/stores/useKnowledgeStore.ts b/web/packages/magent-flow/src/stores/useKnowledgeStore.ts
new file mode 100644
index 0000000..908657a
--- /dev/null
+++ b/web/packages/magent-flow/src/stores/useKnowledgeStore.ts
@@ -0,0 +1,19 @@
+import { create } from 'zustand';
+
+export interface Knowledge {
+ name: string;
+ id: string;
+ description?: string;
+}
+
+export interface KnowledgeStoreType {
+ knowledges: Knowledge[];
+ setKnowledges: (knowledges: Knowledge[]) => void;
+}
+
+export const useKnowledgeStore = create((set, get) => ({
+ knowledges: [],
+ setKnowledges: (knowledges: Knowledge[]) => {
+ set({ knowledges });
+ },
+}));
diff --git a/web/packages/magent-flow/src/stores/useModelStore.ts b/web/packages/magent-flow/src/stores/useModelStore.ts
new file mode 100644
index 0000000..fa9a09e
--- /dev/null
+++ b/web/packages/magent-flow/src/stores/useModelStore.ts
@@ -0,0 +1,33 @@
+import { create } from 'zustand';
+
+export interface Model {
+ id: string;
+ name: string;
+ group?: string;
+ description?: string;
+}
+
+export interface ModelConfig {
+ temperature?: number;
+ top_p?: number;
+ max_tokens?: number;
+ [key: string]: number | undefined;
+}
+
+export interface ModelStoreType {
+ models: Model[];
+ setModels: (models: Model[]) => void;
+ modelConfig: ModelConfig;
+ setModelConfig: (config: ModelConfig) => void;
+}
+
+export const useModelStore = create((set, get) => ({
+ models: [],
+ setModels: (models: Model[]) => {
+ set({ models });
+ },
+ modelConfig: {},
+ setModelConfig: (modelConfig: ModelConfig) => {
+ set({ modelConfig });
+ },
+}));
diff --git a/web/packages/magent-flow/src/stores/useShortcutsStore.ts b/web/packages/magent-flow/src/stores/useShortcutsStore.ts
new file mode 100644
index 0000000..78e3a3f
--- /dev/null
+++ b/web/packages/magent-flow/src/stores/useShortcutsStore.ts
@@ -0,0 +1,86 @@
+import { create } from 'zustand';
+
+import { defaultShortcuts } from '@/constants/constant';
+
+export type shortcutsStoreType = {
+ updateUniqueShortcut: (name: string, combination: string) => void;
+ output: string;
+ play: string;
+ flow: string;
+ group: string;
+ cut: string;
+ paste: string;
+ api: string;
+ open: string;
+ undo: string;
+ redo: string;
+ advanced: string;
+ minimize: string;
+ code: string;
+ copy: string;
+ duplicate: string;
+ component: string;
+ docs: string;
+ save: string;
+ delete: string;
+ update: string;
+ download: string;
+ freeze: string;
+ FreezePath: string;
+ shortcuts: Array<{
+ name: string;
+ shortcut: string;
+ }>;
+ setShortcuts: (newShortcuts: Array<{ name: string; shortcut: string }>) => void;
+ getShortcutsFromStorage: () => void;
+};
+
+export const useShortcutsStore = create((set, get) => ({
+ shortcuts: defaultShortcuts,
+ setShortcuts: (newShortcuts) => {
+ set({ shortcuts: newShortcuts });
+ },
+ output: 'o',
+ play: 'p',
+ flow: 'mod+b',
+ undo: 'mod+z',
+ redo: 'mod+y',
+ open: 'mod+k',
+ advanced: 'mod+shift+a',
+ minimize: 'mod+shift+q',
+ code: 'space',
+ copy: 'mod+c',
+ duplicate: 'mod+d',
+ component: 'mod+shift+s',
+ docs: 'mod+shift+d',
+ save: 'mod+s',
+ delete: 'backspace',
+ group: 'mod+g',
+ cut: 'mod+x',
+ paste: 'mod+v',
+ api: 'r',
+ update: 'mod+u',
+ download: 'mod+j',
+ freeze: 'mod+f',
+ FreezePath: 'mod+shift+f',
+ updateUniqueShortcut: (name, combination) => {
+ set({
+ [name]: combination,
+ });
+ },
+ getShortcutsFromStorage: () => {
+ if (localStorage.getItem('langflow-shortcuts')) {
+ const savedShortcuts = localStorage.getItem('langflow-shortcuts');
+ const savedArr = JSON.parse(savedShortcuts!);
+ savedArr.forEach(({ name, shortcut }) => {
+ const shortcutName = name.split(' ')[0].toLowerCase();
+ set({
+ [shortcutName]: shortcut,
+ });
+ });
+ get().setShortcuts(JSON.parse(savedShortcuts!));
+ }
+ },
+}));
+
+useShortcutsStore.getState().getShortcutsFromStorage();
diff --git a/web/packages/magent-flow/src/stores/useUndoRedoStore.ts b/web/packages/magent-flow/src/stores/useUndoRedoStore.ts
new file mode 100644
index 0000000..401c90b
--- /dev/null
+++ b/web/packages/magent-flow/src/stores/useUndoRedoStore.ts
@@ -0,0 +1,101 @@
+import type { Edge, Node } from '@xyflow/react';
+import { cloneDeep } from 'lodash';
+import { create } from 'zustand';
+
+import { useFlowStore } from './useFlowStore';
+
+interface FlowRedoUndoStoreType {
+ undo: () => void;
+ redo: () => void;
+ takeSnapshot: () => void;
+}
+
+export type UseUndoRedoOptions = {
+ maxHistorySize: number;
+ enableShortcuts: boolean;
+};
+
+interface Snap {
+ nodes: Node[];
+ edges: Edge[];
+}
+
+const defaultOptions: UseUndoRedoOptions = {
+ maxHistorySize: 100,
+ enableShortcuts: true,
+};
+
+let past: Snap[] = [];
+
+let future: Snap[] = [];
+
+export const useUndoRedoStore = create(() => ({
+ takeSnapshot: () => {
+ // const currentFlowId = get().currentFlowId;
+ // push the current graph to the past state
+ const flowStore = useFlowStore.getState();
+ const newState = {
+ nodes: cloneDeep(flowStore.nodes),
+ edges: cloneDeep(flowStore.edges),
+ };
+ const pastLength = past?.length ?? 0;
+ if (
+ pastLength > 0 &&
+ JSON.stringify(past[pastLength - 1]) === JSON.stringify(newState)
+ ) {
+ return;
+ }
+ if (pastLength > 0) {
+ past = past.slice(pastLength - defaultOptions.maxHistorySize + 1, pastLength);
+
+ past.push(newState);
+ } else {
+ past = [newState];
+ }
+
+ future = [];
+ },
+ undo: () => {
+ console.log('🚀 ~ useUndoRedoStore ~ undo:');
+ const newState = useFlowStore.getState();
+
+ const pastLength = past?.length ?? 0;
+ const pastState = past?.[pastLength - 1] ?? null;
+
+ if (pastState) {
+ past = past.slice(0, pastLength - 1);
+
+ if (!future) {
+ future = [];
+ }
+ future.push({
+ nodes: newState.nodes,
+ edges: newState.edges,
+ });
+
+ newState.setNodes(pastState.nodes);
+ newState.setEdges(pastState.edges);
+ }
+ },
+ redo: () => {
+ const newState = useFlowStore.getState();
+
+ const futureLength = future?.length ?? 0;
+ const futureState = future?.[futureLength - 1] ?? null;
+
+ if (futureState) {
+ future = future.slice(0, futureLength - 1);
+
+ if (!past) {
+ past = [];
+ }
+ past.push({
+ nodes: newState.nodes,
+ edges: newState.edges,
+ });
+
+ newState.setNodes(futureState.nodes);
+ newState.setEdges(futureState.edges);
+ }
+ },
+}));
diff --git a/web/packages/magent-flow/src/tailwind.css b/web/packages/magent-flow/src/tailwind.css
new file mode 100644
index 0000000..41677bf
--- /dev/null
+++ b/web/packages/magent-flow/src/tailwind.css
@@ -0,0 +1,4 @@
+/* stylelint-disable at-rule-no-unknown */
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/web/packages/magent-flow/src/utils/basic.ts b/web/packages/magent-flow/src/utils/basic.ts
new file mode 100644
index 0000000..a1db376
--- /dev/null
+++ b/web/packages/magent-flow/src/utils/basic.ts
@@ -0,0 +1,8 @@
+export function classNames(...classes: Array): string {
+ return classes.filter(Boolean).join(' ');
+}
+
+export function capitalizeFirstLetter(s: string) {
+ if (!s) return '';
+ return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
+}
diff --git a/web/packages/magent-flow/src/utils/index.tsx b/web/packages/magent-flow/src/utils/index.tsx
new file mode 100644
index 0000000..e1ad5ae
--- /dev/null
+++ b/web/packages/magent-flow/src/utils/index.tsx
@@ -0,0 +1,2 @@
+export * from './basic';
+export * from './reactflowUtils';
diff --git a/web/packages/magent-flow/src/utils/reactflowUtils.ts b/web/packages/magent-flow/src/utils/reactflowUtils.ts
new file mode 100644
index 0000000..07816ba
--- /dev/null
+++ b/web/packages/magent-flow/src/utils/reactflowUtils.ts
@@ -0,0 +1,13 @@
+import { Edge } from '@xyflow/react';
+import { cloneDeep } from 'lodash';
+import { v4 } from 'uuid';
+
+export function cleanEdges(nodes: any[], edges: Edge[]) {
+ let newEdges = cloneDeep(edges);
+
+ return newEdges;
+}
+
+export function getNodeId(nodeType: string) {
+ return nodeType + '-' + v4();
+}
diff --git a/web/packages/magent-flow/src/utils/wrappedClass.ts b/web/packages/magent-flow/src/utils/wrappedClass.ts
new file mode 100644
index 0000000..eff34d3
--- /dev/null
+++ b/web/packages/magent-flow/src/utils/wrappedClass.ts
@@ -0,0 +1,4 @@
+const isWrappedWithClass = (event: any, className: string | undefined) =>
+ event.target.closest(`.${className}`);
+
+export default isWrappedWithClass;
diff --git a/web/packages/magent-flow/tailwind.config.js b/web/packages/magent-flow/tailwind.config.js
new file mode 100644
index 0000000..9cfd53f
--- /dev/null
+++ b/web/packages/magent-flow/tailwind.config.js
@@ -0,0 +1,7 @@
+module.exports = {
+ content: [
+ './src/pages/**/*.tsx',
+ './src/components/**/*.tsx',
+ './src/layouts/**/*.tsx',
+ ],
+};
diff --git a/web/packages/magent-flow/tsconfig.json b/web/packages/magent-flow/tsconfig.json
new file mode 100644
index 0000000..e7a514f
--- /dev/null
+++ b/web/packages/magent-flow/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "extends": "../../../tsconfig.base.json",
+ "compilerOptions": {
+ "rootDir": "./src",
+ "outDir": "es",
+ "declarationDir": "es",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "types": ["jest"],
+ "exclude": ["node_modules"],
+ "include": ["src"]
+}
From 2ae15d3f02ef10cc46937145817a59253f6d8475 Mon Sep 17 00:00:00 2001
From: "yukun.wyk"
Date: Tue, 27 Aug 2024 15:19:52 +0800
Subject: [PATCH 02/78] chore(flow): migrate to nodenext code style
---
web/packages/magent-flow/package.json | 12 ++++++---
.../magent-flow/src/FormSchema/index.ts | 2 +-
.../magent-flow/src/RefForm/index.tsx | 2 +-
.../src/SchemaConfigForm/index.tsx | 4 +--
.../AIBasic/CascaderInNode/index.tsx | 6 +++--
.../OutputVariable/index.tsx | 3 +--
.../components/AIBasic/PromptEditor/hooks.ts | 4 +--
.../components/AIBasic/PromptEditor/index.tsx | 25 +++++++++++--------
.../plugins/component-picker-block/hooks.tsx | 10 ++++----
.../plugins/component-picker-block/index.tsx | 14 +++++------
.../component-picker-block/prompt-option.tsx | 2 +-
.../variable-option.tsx | 2 +-
.../PromptEditor/plugins/custom-text/node.tsx | 12 ++++-----
.../plugins/on-blur-or-focus-block.tsx | 8 ++++--
.../PromptEditor/plugins/update-block.tsx | 6 ++---
.../plugins/variable-block/index.tsx | 2 +-
.../plugins/variable-value-block/index.tsx | 6 ++---
.../plugins/variable-value-block/node.tsx | 12 ++++-----
.../components/AIBasic/PromptEditor/utils.ts | 4 +--
.../components/AIBasic/SelectInNode/index.tsx | 7 +++---
.../src/components/CustomEdge/index.tsx | 4 +--
.../magent-flow/src/components/Flow/index.tsx | 16 ++++++------
.../magent-flow/src/components/Flow/keys.ts | 4 ++-
.../src/components/FlowController/index.tsx | 1 -
.../src/components/FlowWithPanel/index.tsx | 25 +++++++++++--------
.../src/components/Node/AgentNode/index.tsx | 14 +++++------
.../src/components/Node/CommonNode/index.tsx | 6 +++--
.../src/components/Node/EndNode/index.tsx | 11 ++++----
.../src/components/Node/IfElseNode/index.tsx | 13 +++++-----
.../components/Node/KnowledgeNode/index.tsx | 17 +++++++------
.../src/components/Node/LLMNode/index.tsx | 22 ++++++++--------
.../Node/NodeWrapper/Status/index.tsx | 3 ++-
.../src/components/Node/NodeWrapper/index.tsx | 4 +--
.../src/components/Node/StartNode/index.tsx | 9 ++++---
.../src/components/NodePanel/index.tsx | 3 ++-
.../src/components/ReferenceForm/index.tsx | 6 ++---
.../src/components/ReferenceSelect/index.tsx | 5 ++--
.../src/components/VariableForm/index.tsx | 4 +--
web/packages/magent-flow/src/index.ts | 12 ++++-----
web/packages/magent-flow/src/spec/node.ts | 11 ++++----
.../magent-flow/src/stores/useFlowStore.ts | 4 +--
.../src/stores/useShortcutsStore.ts | 2 +-
.../src/stores/useUndoRedoStore.ts | 2 +-
web/packages/magent-flow/src/utils/basic.ts | 4 ++-
web/packages/magent-flow/src/utils/index.tsx | 4 +--
.../magent-flow/src/utils/reactflowUtils.ts | 4 +--
46 files changed, 193 insertions(+), 160 deletions(-)
diff --git a/web/packages/magent-flow/package.json b/web/packages/magent-flow/package.json
index 397fd69..770776b 100644
--- a/web/packages/magent-flow/package.json
+++ b/web/packages/magent-flow/package.json
@@ -50,23 +50,29 @@
"@ant-design/icons": "^5.1.0",
"@babel/runtime": "^7.18.0",
"@floating-ui/react": "^0.26.22",
+ "@lexical/code": "^0.17.0",
"@lexical/react": "^0.17.0",
+ "@lexical/utils": "^0.17.0",
"@types/json-schema": "^7.0.15",
"@xyflow/react": "^12.0.2",
- "antd": "^5.19.2",
+ "ahooks": "^3.8.1",
"ajv": "^8.17.1",
+ "antd": "^5.19.2",
+ "classnames": "^2.3.2",
"js-yaml": "^4.1.0",
"lexical": "^0.17.0",
"lodash": "^4.17.21",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0",
"react-hotkeys-hook": "^4.5.0",
"short-unique-id": "^5.2.0",
"styled-components": "^6.0.7",
- "react": "^18.0.0",
- "react-dom": "^18.0.0",
"uuid": "^10.0.0",
"zustand": "^4.5.4"
},
"devDependencies": {
+ "@types/classnames": "^2.3.1",
+ "@types/lodash": "^4.17.7",
"@types/react": "^18.2.25",
"@types/uuid": "^10.0.0",
"tailwindcss": "^3"
diff --git a/web/packages/magent-flow/src/FormSchema/index.ts b/web/packages/magent-flow/src/FormSchema/index.ts
index e1ac908..51adf0b 100644
--- a/web/packages/magent-flow/src/FormSchema/index.ts
+++ b/web/packages/magent-flow/src/FormSchema/index.ts
@@ -5,7 +5,7 @@ import type {
JSONSchema7TypeName,
} from 'json-schema';
-import { UUID } from '@/spec/uuid';
+import { UUID } from '@/spec/uuid.js';
export type OrderJSONSchema7 = JSONSchema7 & {
order: number;
diff --git a/web/packages/magent-flow/src/RefForm/index.tsx b/web/packages/magent-flow/src/RefForm/index.tsx
index 2df74aa..0dbe097 100644
--- a/web/packages/magent-flow/src/RefForm/index.tsx
+++ b/web/packages/magent-flow/src/RefForm/index.tsx
@@ -2,7 +2,7 @@ import { CaretRightOutlined } from '@ant-design/icons';
import { Button, Cascader, Collapse, Flex, Input, Select, Space, theme } from 'antd';
import React, { useEffect, useMemo, useState } from 'react';
-import type { NodeDataType } from '@/interfaces/flow';
+import type { NodeDataType } from '@/interfaces/flow.js';
interface CascaderOptions {
value: string;
diff --git a/web/packages/magent-flow/src/SchemaConfigForm/index.tsx b/web/packages/magent-flow/src/SchemaConfigForm/index.tsx
index 6435a36..ad65dbf 100644
--- a/web/packages/magent-flow/src/SchemaConfigForm/index.tsx
+++ b/web/packages/magent-flow/src/SchemaConfigForm/index.tsx
@@ -11,8 +11,8 @@ import { Card, Checkbox, Collapse, Form, Input, Select, Space, theme } from 'ant
import type { JSONSchema7 } from 'json-schema';
import React, { useState } from 'react';
-import { variableTypeOptions } from '@/FormSchema';
-import type { FormSchema, OrderJSONSchema7 } from '@/FormSchema';
+import { variableTypeOptions } from '@/FormSchema/index.js';
+import type { FormSchema, OrderJSONSchema7 } from '@/FormSchema/index.js';
// import {
// FormSchema,
diff --git a/web/packages/magent-flow/src/components/AIBasic/CascaderInNode/index.tsx b/web/packages/magent-flow/src/components/AIBasic/CascaderInNode/index.tsx
index 05e606a..ae4b320 100644
--- a/web/packages/magent-flow/src/components/AIBasic/CascaderInNode/index.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/CascaderInNode/index.tsx
@@ -1,7 +1,9 @@
-import { classNames } from '@/utils';
-import { Cascader, CascaderProps } from 'antd';
+import type { CascaderProps } from 'antd';
+import { Cascader } from 'antd';
import React from 'react';
+import { classNames } from '@/utils/index.js';
+
export const CascaderInNode = (props: CascaderProps) => {
return (
{
const { name, type } = props;
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/hooks.ts b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/hooks.ts
index bdb0239..7644346 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/hooks.ts
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/hooks.ts
@@ -4,8 +4,8 @@ import { mergeRegister } from '@lexical/utils';
import type { Klass, LexicalEditor, TextNode } from 'lexical';
import { useCallback, useEffect } from 'react';
-import type { CustomTextNode } from './plugins/custom-text/node';
-import { registerLexicalTextEntity } from './utils';
+import type { CustomTextNode } from './plugins/custom-text/node.js';
+import { registerLexicalTextEntity } from './utils.js';
export function useLexicalTextEntity(
getMatch: (text: string) => null | EntityMatch,
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/index.tsx b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/index.tsx
index 06d12a8..8e97314 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/index.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/index.tsx
@@ -7,16 +7,17 @@ import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
import type { EditorState } from 'lexical';
import { $getRoot, TextNode } from 'lexical';
import React, { type FC } from 'react';
-import ComponentPickerBlock from './plugins/component-picker-block';
-import { CustomTextNode } from './plugins/custom-text/node';
-import OnBlurBlock from './plugins/on-blur-or-focus-block';
-import Placeholder from './plugins/placeholder';
-import UpdateBlock from './plugins/update-block';
-import VariableBlock from './plugins/variable-block';
-import VariableValueBlock from './plugins/variable-value-block';
-import { VariableValueBlockNode } from './plugins/variable-value-block/node';
-import type { ExternalToolBlockType, VariableBlockType } from './types';
-import { textToEditorState } from './utils';
+
+import ComponentPickerBlock from './plugins/component-picker-block/index.js';
+import { CustomTextNode } from './plugins/custom-text/node.js';
+import OnBlurBlock from './plugins/on-blur-or-focus-block.js';
+import Placeholder from './plugins/placeholder.js';
+import UpdateBlock from './plugins/update-block.js';
+import VariableBlock from './plugins/variable-block/index.js';
+import VariableValueBlock from './plugins/variable-value-block/index.js';
+import { VariableValueBlockNode } from './plugins/variable-value-block/node.js';
+import type { ExternalToolBlockType, VariableBlockType } from './types.js';
+import { textToEditorState } from './utils.js';
export type PromptEditorProps = {
instanceId?: string;
@@ -74,7 +75,9 @@ const PromptEditor: FC = ({
.join('\n');
});
- if (onChange) onChange(text);
+ if (onChange) {
+ onChange(text);
+ }
};
return (
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/hooks.tsx b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/hooks.tsx
index a48a7a0..7cc91c8 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/hooks.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/hooks.tsx
@@ -3,12 +3,12 @@ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext
import { $insertNodes } from 'lexical';
import React, { useMemo } from 'react';
-import type { ExternalToolBlockType, VariableBlockType } from '../../types';
-import { $createCustomTextNode } from '../custom-text/node';
-import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '../variable-block';
+import type { ExternalToolBlockType, VariableBlockType } from '../../types.js';
+import { $createCustomTextNode } from '../custom-text/node.js';
+import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '../variable-block/index.js';
-import { PickerBlockMenuOption } from './menu';
-import { VariableMenuItem } from './variable-option';
+import { PickerBlockMenuOption } from './menu.js';
+import { VariableMenuItem } from './variable-option.js';
export const useVariableOptions = (
variableBlock?: VariableBlockType,
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/index.tsx b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/index.tsx
index ddb64af..6d67748 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/index.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/index.tsx
@@ -6,15 +6,15 @@ import type { TextNode } from 'lexical';
import React, { Fragment, memo, useCallback, useState } from 'react';
import ReactDOM from 'react-dom';
-import { useEventEmitterContextContext } from '@/context/event-emitter';
+import { useEventEmitterContextContext } from '@/context/event-emitter.js';
-import { useBasicTypeaheadTriggerMatch } from '../../hooks';
-import type { ExternalToolBlockType, VariableBlockType } from '../../types';
-import { $splitNodeContainingQuery } from '../../utils';
-import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '../variable-block';
+import { useBasicTypeaheadTriggerMatch } from '../../hooks.js';
+import type { ExternalToolBlockType, VariableBlockType } from '../../types.js';
+import { $splitNodeContainingQuery } from '../../utils.js';
+import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '../variable-block/index.js';
-import { useOptions } from './hooks';
-import type { PickerBlockMenuOption } from './menu';
+import { useOptions } from './hooks.js';
+import type { PickerBlockMenuOption } from './menu.js';
type ComponentPickerProps = {
triggerString: string;
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/prompt-option.tsx b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/prompt-option.tsx
index 43ff4dc..632b688 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/prompt-option.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/prompt-option.tsx
@@ -1,4 +1,4 @@
-import React, { memo } from 'react';
+import { memo } from 'react';
type PromptMenuItemMenuItemProps = {
icon: JSX.Element;
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/variable-option.tsx b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/variable-option.tsx
index 2dce466..e59f3f3 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/variable-option.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/variable-option.tsx
@@ -1,4 +1,4 @@
-import React, { memo } from 'react';
+import { memo } from 'react';
type VariableMenuItemProps = {
title: string;
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/custom-text/node.tsx b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/custom-text/node.tsx
index b660ce8..bda0c4b 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/custom-text/node.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/custom-text/node.tsx
@@ -2,11 +2,11 @@ import type { EditorConfig, NodeKey, SerializedTextNode } from 'lexical';
import { $createTextNode, TextNode } from 'lexical';
export class CustomTextNode extends TextNode {
- static getType() {
+ static override getType() {
return 'custom-text';
}
- static clone(node: CustomTextNode) {
+ static override clone(node: CustomTextNode) {
return new CustomTextNode(node.__text, node.__key);
}
@@ -14,13 +14,13 @@ export class CustomTextNode extends TextNode {
super(text, key);
}
- createDOM(config: EditorConfig) {
+ override createDOM(config: EditorConfig) {
const dom = super.createDOM(config);
dom.classList.add('align-middle');
return dom;
}
- static importJSON(serializedNode: SerializedTextNode): TextNode {
+ static override importJSON(serializedNode: SerializedTextNode): TextNode {
const node = $createTextNode(serializedNode.text);
node.setFormat(serializedNode.format);
node.setDetail(serializedNode.detail);
@@ -29,7 +29,7 @@ export class CustomTextNode extends TextNode {
return node;
}
- exportJSON(): SerializedTextNode {
+ override exportJSON(): SerializedTextNode {
return {
detail: this.getDetail(),
format: this.getFormat(),
@@ -41,7 +41,7 @@ export class CustomTextNode extends TextNode {
};
}
- isSimpleText() {
+ override isSimpleText() {
return (
(this.__type === 'text' || this.__type === 'custom-text') && this.__mode === 0
);
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/on-blur-or-focus-block.tsx b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/on-blur-or-focus-block.tsx
index d7de68c..8aa4791 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/on-blur-or-focus-block.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/on-blur-or-focus-block.tsx
@@ -30,7 +30,9 @@ const OnBlurBlock: FC = ({ onBlur, onFocus }) => {
);
}, 200);
- if (onBlur) onBlur();
+ if (onBlur) {
+ onBlur();
+ }
return true;
},
@@ -39,7 +41,9 @@ const OnBlurBlock: FC = ({ onBlur, onFocus }) => {
editor.registerCommand(
FOCUS_COMMAND,
() => {
- if (onFocus) onFocus();
+ if (onFocus) {
+ onFocus();
+ }
return true;
},
COMMAND_PRIORITY_EDITOR,
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/update-block.tsx b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/update-block.tsx
index c7ca926..e1d5a5c 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/update-block.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/update-block.tsx
@@ -1,11 +1,11 @@
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { $insertNodes } from 'lexical';
-import { useEventEmitterContextContext } from '@/context/event-emitter';
+import { useEventEmitterContextContext } from '@/context/event-emitter.js';
-import { textToEditorState } from '../utils';
+import { textToEditorState } from '../utils.js';
-import { CustomTextNode } from './custom-text/node';
+import { CustomTextNode } from './custom-text/node.js';
export const PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER =
'PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER';
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-block/index.tsx b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-block/index.tsx
index b1dc0bd..2b3c0b9 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-block/index.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-block/index.tsx
@@ -3,7 +3,7 @@ import { mergeRegister } from '@lexical/utils';
import { $insertNodes, COMMAND_PRIORITY_EDITOR, createCommand } from 'lexical';
import { useEffect } from 'react';
-import { CustomTextNode } from '../custom-text/node';
+import { CustomTextNode } from '../custom-text/node.js';
export const INSERT_VARIABLE_BLOCK_COMMAND = createCommand(
'INSERT_VARIABLE_BLOCK_COMMAND',
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-value-block/index.tsx b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-value-block/index.tsx
index 51a4784..3baae5c 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-value-block/index.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-value-block/index.tsx
@@ -2,10 +2,10 @@ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext
import type { TextNode } from 'lexical';
import { useCallback, useEffect } from 'react';
-import { useLexicalTextEntity } from '../../hooks';
+import { useLexicalTextEntity } from '../../hooks.js';
-import { $createVariableValueBlockNode, VariableValueBlockNode } from './node';
-import { getHashtagRegexString } from './utils';
+import { $createVariableValueBlockNode, VariableValueBlockNode } from './node.js';
+import { getHashtagRegexString } from './utils.js';
const REGEX = new RegExp(getHashtagRegexString(), 'i');
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-value-block/node.tsx b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-value-block/node.tsx
index a53ebca..58ea90f 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-value-block/node.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/variable-value-block/node.tsx
@@ -2,11 +2,11 @@ import type { EditorConfig, LexicalNode, NodeKey, SerializedTextNode } from 'lex
import { $applyNodeReplacement, TextNode } from 'lexical';
export class VariableValueBlockNode extends TextNode {
- static getType(): string {
+ static override getType(): string {
return 'variable-value-block';
}
- static clone(node: VariableValueBlockNode): VariableValueBlockNode {
+ static override clone(node: VariableValueBlockNode): VariableValueBlockNode {
return new VariableValueBlockNode(node.__text, node.__key);
}
@@ -14,7 +14,7 @@ export class VariableValueBlockNode extends TextNode {
super(text, key);
}
- createDOM(config: EditorConfig): HTMLElement {
+ override createDOM(config: EditorConfig): HTMLElement {
const element = super.createDOM(config);
element.classList.add(
'inline-flex',
@@ -28,7 +28,7 @@ export class VariableValueBlockNode extends TextNode {
return element;
}
- static importJSON(serializedNode: SerializedTextNode): TextNode {
+ static override importJSON(serializedNode: SerializedTextNode): TextNode {
const node = $createVariableValueBlockNode(serializedNode.text);
node.setFormat(serializedNode.format);
node.setDetail(serializedNode.detail);
@@ -37,7 +37,7 @@ export class VariableValueBlockNode extends TextNode {
return node;
}
- exportJSON(): SerializedTextNode {
+ override exportJSON(): SerializedTextNode {
return {
detail: this.getDetail(),
format: this.getFormat(),
@@ -49,7 +49,7 @@ export class VariableValueBlockNode extends TextNode {
};
}
- canInsertTextBefore(): boolean {
+ override canInsertTextBefore(): boolean {
return false;
}
}
diff --git a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/utils.ts b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/utils.ts
index eb8a4bc..ca1f1cb 100644
--- a/web/packages/magent-flow/src/components/AIBasic/PromptEditor/utils.ts
+++ b/web/packages/magent-flow/src/components/AIBasic/PromptEditor/utils.ts
@@ -7,8 +7,8 @@ import {
$isTextNode,
} from 'lexical';
-import { CustomTextNode } from './plugins/custom-text/node';
-import type { MenuTextMatch } from './types';
+import { CustomTextNode } from './plugins/custom-text/node.js';
+import type { MenuTextMatch } from './types.js';
export function registerLexicalTextEntity(
editor: LexicalEditor,
diff --git a/web/packages/magent-flow/src/components/AIBasic/SelectInNode/index.tsx b/web/packages/magent-flow/src/components/AIBasic/SelectInNode/index.tsx
index 2890d07..26bebc4 100644
--- a/web/packages/magent-flow/src/components/AIBasic/SelectInNode/index.tsx
+++ b/web/packages/magent-flow/src/components/AIBasic/SelectInNode/index.tsx
@@ -1,6 +1,7 @@
-import { classNames } from '@/utils';
-import { Select, SelectProps } from 'antd';
-import React from 'react';
+import type { SelectProps } from 'antd';
+import { Select } from 'antd';
+
+import { classNames } from '@/utils/index.js';
export const SelectInNode = (props: SelectProps) => {
return (
diff --git a/web/packages/magent-flow/src/components/CustomEdge/index.tsx b/web/packages/magent-flow/src/components/CustomEdge/index.tsx
index a1baf20..a376b6c 100644
--- a/web/packages/magent-flow/src/components/CustomEdge/index.tsx
+++ b/web/packages/magent-flow/src/components/CustomEdge/index.tsx
@@ -1,5 +1,5 @@
-import { BaseEdge, EdgeProps, getBezierPath, MarkerType } from '@xyflow/react';
-import React from 'react';
+import type { EdgeProps } from '@xyflow/react';
+import { BaseEdge, getBezierPath, MarkerType } from '@xyflow/react';
export default function CustomEdge({
// id,
diff --git a/web/packages/magent-flow/src/components/Flow/index.tsx b/web/packages/magent-flow/src/components/Flow/index.tsx
index 7768021..e63b693 100644
--- a/web/packages/magent-flow/src/components/Flow/index.tsx
+++ b/web/packages/magent-flow/src/components/Flow/index.tsx
@@ -3,15 +3,14 @@ import { Background, ReactFlow } from '@xyflow/react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
-import type { NodeType } from '@/interfaces/flow';
-import { useFlowStore } from '@/stores/useFlowStore';
-import { useShortcutsStore } from '@/stores/useShortcutsStore';
-import { useUndoRedoStore } from '@/stores/useUndoRedoStore';
-import { getNodeId } from '@/utils/reactflowUtils';
+import type { NodeType } from '@/interfaces/flow.js';
+import { useFlowStore } from '@/stores/useFlowStore.js';
+import { useShortcutsStore } from '@/stores/useShortcutsStore.js';
+import { useUndoRedoStore } from '@/stores/useUndoRedoStore.js';
+import { getNodeId } from '@/utils/reactflowUtils.js';
import CustomEdge from '../CustomEdge/index.js';
import { FlowController } from '../FlowController/index.js';
-import '@xyflow/react/dist/style.css';
import {
handleCopy,
@@ -21,7 +20,8 @@ import {
handlePaste,
handleRedo,
handleUndo,
-} from './keys';
+} from './keys.js';
+import '@xyflow/react/dist/style.css';
const edgeTypes = {
custom: CustomEdge,
@@ -138,7 +138,7 @@ function Flow(props: FlowProps) {
return (
diff --git a/web/packages/magent-flow/src/components/Flow/keys.ts b/web/packages/magent-flow/src/components/Flow/keys.ts
index b7a0f2b..abf603c 100644
--- a/web/packages/magent-flow/src/components/Flow/keys.ts
+++ b/web/packages/magent-flow/src/components/Flow/keys.ts
@@ -1,5 +1,7 @@
-import isWrappedWithClass from '@/utils/wrappedClass';
import { cloneDeep } from 'lodash';
+
+import isWrappedWithClass from '@/utils/wrappedClass.js';
+
export function handleUndo(e: KeyboardEvent, undo: any) {
if (!isWrappedWithClass(e, 'noflow')) {
e.preventDefault();
diff --git a/web/packages/magent-flow/src/components/FlowController/index.tsx b/web/packages/magent-flow/src/components/FlowController/index.tsx
index e5ad6f7..3224b8b 100644
--- a/web/packages/magent-flow/src/components/FlowController/index.tsx
+++ b/web/packages/magent-flow/src/components/FlowController/index.tsx
@@ -1,5 +1,4 @@
import { Controls, MiniMap } from '@xyflow/react';
-import React from 'react';
export const FlowController = () => {
return (
diff --git a/web/packages/magent-flow/src/components/FlowWithPanel/index.tsx b/web/packages/magent-flow/src/components/FlowWithPanel/index.tsx
index f2b7e3b..8ed246c 100644
--- a/web/packages/magent-flow/src/components/FlowWithPanel/index.tsx
+++ b/web/packages/magent-flow/src/components/FlowWithPanel/index.tsx
@@ -1,15 +1,18 @@
-import { EventEmitterContextProvider } from '@/context/event-emitter';
-import { NodeDataType, NodeTypeEnum } from '@/interfaces/flow';
import yaml from 'js-yaml';
import React from 'react';
-import Flow from '../Flow';
-import { AgentNode } from '../Node/AgentNode';
-import { EndNode } from '../Node/EndNode';
-import { IfElseNode } from '../Node/IfElseNode';
-import { KnowledgeNode } from '../Node/KnowledgeNode';
-import { LLMNode } from '../Node/LLMNode';
-import { StartNode } from '../Node/StartNode';
-import { NodesPanel } from '../NodePanel';
+
+import { EventEmitterContextProvider } from '@/context/event-emitter.js';
+import type { NodeDataType } from '@/interfaces/flow.js';
+import { NodeTypeEnum } from '@/interfaces/flow.js';
+
+import Flow from '../Flow/index.js';
+import { AgentNode } from '../Node/AgentNode/index.js';
+import { EndNode } from '../Node/EndNode/index.js';
+import { IfElseNode } from '../Node/IfElseNode/index.js';
+import { KnowledgeNode } from '../Node/KnowledgeNode/index.js';
+import { LLMNode } from '../Node/LLMNode/index.js';
+import { StartNode } from '../Node/StartNode/index.js';
+import { NodesPanel } from '../NodePanel/index.js';
const yamlContent = `
- id: 1
@@ -233,7 +236,7 @@ export const FlowWithPanel = () => {
return (
-
+
diff --git a/web/packages/magent-flow/src/components/Node/AgentNode/index.tsx b/web/packages/magent-flow/src/components/Node/AgentNode/index.tsx
index 5e25a3f..5ae7932 100644
--- a/web/packages/magent-flow/src/components/Node/AgentNode/index.tsx
+++ b/web/packages/magent-flow/src/components/Node/AgentNode/index.tsx
@@ -1,10 +1,10 @@
-import { CollapseWrapper } from '@/components/AIBasic/CollapseWrapper';
-import { OutputVariable } from '@/components/AIBasic/OutputVariableTree/OutputVariable';
-import { ReferenceForm } from '@/components/ReferenceForm';
-import { NodeDataType } from '@/interfaces/flow';
-import { useFlowStore } from '@/stores/useFlowStore';
-import React from 'react';
-import { NodeWrapper } from '../NodeWrapper';
+import { CollapseWrapper } from '@/components/AIBasic/CollapseWrapper/index.js';
+import { OutputVariable } from '@/components/AIBasic/OutputVariableTree/OutputVariable/index.js';
+import { ReferenceForm } from '@/components/ReferenceForm/index.js';
+import type { NodeDataType } from '@/interfaces/flow.js';
+import { useFlowStore } from '@/stores/useFlowStore.js';
+
+import { NodeWrapper } from '../NodeWrapper/index.js';
type Props = {
data: NodeDataType;
diff --git a/web/packages/magent-flow/src/components/Node/CommonNode/index.tsx b/web/packages/magent-flow/src/components/Node/CommonNode/index.tsx
index 6377ffc..a2628f6 100644
--- a/web/packages/magent-flow/src/components/Node/CommonNode/index.tsx
+++ b/web/packages/magent-flow/src/components/Node/CommonNode/index.tsx
@@ -1,7 +1,9 @@
-import { NodeDataType } from '@/interfaces/flow';
import { Collapse } from 'antd';
import React from 'react';
-import { NodeWrapper } from '../NodeWrapper';
+
+import type { NodeDataType } from '@/interfaces/flow.js';
+
+import { NodeWrapper } from '../NodeWrapper/index.js';
type Props = {
data: NodeDataType;
diff --git a/web/packages/magent-flow/src/components/Node/EndNode/index.tsx b/web/packages/magent-flow/src/components/Node/EndNode/index.tsx
index 8b3cf8f..a80f0f7 100644
--- a/web/packages/magent-flow/src/components/Node/EndNode/index.tsx
+++ b/web/packages/magent-flow/src/components/Node/EndNode/index.tsx
@@ -1,9 +1,10 @@
-import { ReferenceForm } from '@/components/ReferenceForm';
-import { NodeDataType } from '@/interfaces/flow';
-import { useFlowStore } from '@/stores/useFlowStore';
import { Collapse } from 'antd';
-import React from 'react';
-import { NodeWrapper } from '../NodeWrapper';
+
+import { ReferenceForm } from '@/components/ReferenceForm/index.js';
+import type { NodeDataType } from '@/interfaces/flow.js';
+import { useFlowStore } from '@/stores/useFlowStore.js';
+
+import { NodeWrapper } from '../NodeWrapper/index.js';
type Props = {
data: NodeDataType;
diff --git a/web/packages/magent-flow/src/components/Node/IfElseNode/index.tsx b/web/packages/magent-flow/src/components/Node/IfElseNode/index.tsx
index e9c3924..06ae870 100644
--- a/web/packages/magent-flow/src/components/Node/IfElseNode/index.tsx
+++ b/web/packages/magent-flow/src/components/Node/IfElseNode/index.tsx
@@ -1,10 +1,11 @@
-import { SelectInNode } from '@/components/AIBasic/SelectInNode';
-import { ReferenceSelect } from '@/components/ReferenceSelect';
-import { NodeDataType } from '@/interfaces/flow';
-import { useFlowStore } from '@/stores/useFlowStore';
import { Form } from 'antd';
-import React from 'react';
-import { NodeWrapper } from '../NodeWrapper';
+
+import { SelectInNode } from '@/components/AIBasic/SelectInNode/index.js';
+import { ReferenceSelect } from '@/components/ReferenceSelect/index.js';
+import type { NodeDataType } from '@/interfaces/flow.js';
+import { useFlowStore } from '@/stores/useFlowStore.js';
+
+import { NodeWrapper } from '../NodeWrapper/index.js';
type Props = {
data: NodeDataType;
diff --git a/web/packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx b/web/packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx
index 8a9a027..076b3c9 100644
--- a/web/packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx
+++ b/web/packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx
@@ -1,13 +1,14 @@
-import { CollapseWrapper } from '@/components/AIBasic/CollapseWrapper';
-import { OutputVariable } from '@/components/AIBasic/OutputVariableTree/OutputVariable';
-import { ReferenceForm } from '@/components/ReferenceForm';
-import { NodeDataType } from '@/interfaces/flow';
-import { useFlowStore } from '@/stores/useFlowStore';
-import { useKnowledgeStore } from '@/stores/useKnowledgeStore';
import { PlusOutlined } from '@ant-design/icons';
import { Button, Modal } from 'antd';
-import React from 'react';
-import { NodeWrapper } from '../NodeWrapper';
+
+import { CollapseWrapper } from '@/components/AIBasic/CollapseWrapper/index.js';
+import { OutputVariable } from '@/components/AIBasic/OutputVariableTree/OutputVariable/index.js';
+import { ReferenceForm } from '@/components/ReferenceForm/index.js';
+import type { NodeDataType } from '@/interfaces/flow.js';
+import { useFlowStore } from '@/stores/useFlowStore.js';
+import { useKnowledgeStore } from '@/stores/useKnowledgeStore.js';
+
+import { NodeWrapper } from '../NodeWrapper/index.js';
type Props = {
data: NodeDataType;
diff --git a/web/packages/magent-flow/src/components/Node/LLMNode/index.tsx b/web/packages/magent-flow/src/components/Node/LLMNode/index.tsx
index f736768..d01e0f7 100644
--- a/web/packages/magent-flow/src/components/Node/LLMNode/index.tsx
+++ b/web/packages/magent-flow/src/components/Node/LLMNode/index.tsx
@@ -1,15 +1,17 @@
-import { CollapseWrapper } from '@/components/AIBasic/CollapseWrapper';
-import { OutputVariable } from '@/components/AIBasic/OutputVariableTree/OutputVariable';
-import PromptEditor from '@/components/AIBasic/PromptEditor';
-import { SelectInNode } from '@/components/AIBasic/SelectInNode';
-import { ReferenceForm } from '@/components/ReferenceForm';
-import { NodeDataType } from '@/interfaces/flow';
-import { useFlowStore } from '@/stores/useFlowStore';
-import { useModelStore } from '@/stores/useModelStore';
import { BarsOutlined } from '@ant-design/icons';
import { Button, InputNumber, Popover } from 'antd';
-import React, { useState } from 'react';
-import { NodeWrapper } from '../NodeWrapper';
+import { useState } from 'react';
+
+import { CollapseWrapper } from '@/components/AIBasic/CollapseWrapper/index.js';
+import { OutputVariable } from '@/components/AIBasic/OutputVariableTree/OutputVariable/index.js';
+import PromptEditor from '@/components/AIBasic/PromptEditor/index.js';
+import { SelectInNode } from '@/components/AIBasic/SelectInNode/index.js';
+import { ReferenceForm } from '@/components/ReferenceForm/index.js';
+import type { NodeDataType } from '@/interfaces/flow.js';
+import { useFlowStore } from '@/stores/useFlowStore.js';
+import { useModelStore } from '@/stores/useModelStore.js';
+
+import { NodeWrapper } from '../NodeWrapper/index.js';
type Props = {
data: NodeDataType;
diff --git a/web/packages/magent-flow/src/components/Node/NodeWrapper/Status/index.tsx b/web/packages/magent-flow/src/components/Node/NodeWrapper/Status/index.tsx
index e85322e..71d7168 100644
--- a/web/packages/magent-flow/src/components/Node/NodeWrapper/Status/index.tsx
+++ b/web/packages/magent-flow/src/components/Node/NodeWrapper/Status/index.tsx
@@ -1,7 +1,8 @@
-import { classNames } from '@/utils/basic';
import { Popover, Tag } from 'antd';
import React from 'react';
+import { classNames } from '@/utils/basic.js';
+
export enum RunStatusEnum {
Success = 'success',
Processing = 'processing',
diff --git a/web/packages/magent-flow/src/components/Node/NodeWrapper/index.tsx b/web/packages/magent-flow/src/components/Node/NodeWrapper/index.tsx
index 2d6381b..5800c27 100644
--- a/web/packages/magent-flow/src/components/Node/NodeWrapper/index.tsx
+++ b/web/packages/magent-flow/src/components/Node/NodeWrapper/index.tsx
@@ -2,8 +2,8 @@ import { Handle, Position } from '@xyflow/react';
import { Space } from 'antd';
import React from 'react';
-import type { NodeDataType } from '@/interfaces/flow';
-import { classNames } from '@/utils';
+import type { NodeDataType } from '@/interfaces/flow.js';
+import { classNames } from '@/utils/index.js';
type Props = {
data: NodeDataType;
diff --git a/web/packages/magent-flow/src/components/Node/StartNode/index.tsx b/web/packages/magent-flow/src/components/Node/StartNode/index.tsx
index 555da9c..4c6a425 100644
--- a/web/packages/magent-flow/src/components/Node/StartNode/index.tsx
+++ b/web/packages/magent-flow/src/components/Node/StartNode/index.tsx
@@ -1,8 +1,9 @@
-import { VariableForm } from '@/components/VariableForm';
-import { NodeDataType } from '@/interfaces/flow';
import { Collapse } from 'antd';
-import React from 'react';
-import { NodeWrapper } from '../NodeWrapper';
+
+import { VariableForm } from '@/components/VariableForm/index.js';
+import type { NodeDataType } from '@/interfaces/flow.js';
+
+import { NodeWrapper } from '../NodeWrapper/index.js';
type Props = {
data: NodeDataType;
diff --git a/web/packages/magent-flow/src/components/NodePanel/index.tsx b/web/packages/magent-flow/src/components/NodePanel/index.tsx
index d97e01b..b7eece2 100644
--- a/web/packages/magent-flow/src/components/NodePanel/index.tsx
+++ b/web/packages/magent-flow/src/components/NodePanel/index.tsx
@@ -1,7 +1,8 @@
-import { NodeDataType } from '@/interfaces/flow';
import { Input } from 'antd';
import React from 'react';
+import type { NodeDataType } from '@/interfaces/flow.js';
+
interface NodesPanelProps {
/**
* @title 模板节点配置
diff --git a/web/packages/magent-flow/src/components/ReferenceForm/index.tsx b/web/packages/magent-flow/src/components/ReferenceForm/index.tsx
index e68591f..d2a1aa5 100644
--- a/web/packages/magent-flow/src/components/ReferenceForm/index.tsx
+++ b/web/packages/magent-flow/src/components/ReferenceForm/index.tsx
@@ -2,10 +2,10 @@ import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { Button, Form, Input, Space } from 'antd';
import React, { useEffect } from 'react';
-import type { BasicSchema, NodeType } from '@/interfaces/flow';
+import type { BasicSchema, NodeType } from '@/interfaces/flow.js';
-import { CollapseWrapper } from '../AIBasic/CollapseWrapper';
-import { ReferenceSelect } from '../ReferenceSelect';
+import { CollapseWrapper } from '../AIBasic/CollapseWrapper/index.js';
+import { ReferenceSelect } from '../ReferenceSelect/index.js';
export interface RefrenceFormProps {
label: string;
diff --git a/web/packages/magent-flow/src/components/ReferenceSelect/index.tsx b/web/packages/magent-flow/src/components/ReferenceSelect/index.tsx
index 04c1991..28540cc 100644
--- a/web/packages/magent-flow/src/components/ReferenceSelect/index.tsx
+++ b/web/packages/magent-flow/src/components/ReferenceSelect/index.tsx
@@ -1,7 +1,8 @@
import { Input } from 'antd';
import React from 'react';
-import { CascaderInNode } from '../AIBasic/CascaderInNode';
-import { SelectInNode } from '../AIBasic/SelectInNode';
+
+import { CascaderInNode } from '../AIBasic/CascaderInNode/index.js';
+import { SelectInNode } from '../AIBasic/SelectInNode/index.js';
export const ReferenceSelect = (props: {
value?: {
diff --git a/web/packages/magent-flow/src/components/VariableForm/index.tsx b/web/packages/magent-flow/src/components/VariableForm/index.tsx
index 94a783e..eb70954 100644
--- a/web/packages/magent-flow/src/components/VariableForm/index.tsx
+++ b/web/packages/magent-flow/src/components/VariableForm/index.tsx
@@ -6,9 +6,9 @@ import {
import { Button, Checkbox, Collapse, Form, Input, Space } from 'antd';
import React, { useEffect } from 'react';
-import type { BasicSchema } from '@/interfaces/flow';
+import type { BasicSchema } from '@/interfaces/flow.js';
-import { SelectInNode } from '../AIBasic/SelectInNode';
+import { SelectInNode } from '../AIBasic/SelectInNode/index.js';
export interface VariableFormProps {
label: string;
diff --git a/web/packages/magent-flow/src/index.ts b/web/packages/magent-flow/src/index.ts
index dc5c313..e6d7f38 100644
--- a/web/packages/magent-flow/src/index.ts
+++ b/web/packages/magent-flow/src/index.ts
@@ -1,8 +1,8 @@
-export { default as Flow } from './components/Flow';
-export { FlowWithPanel } from './components/FlowWithPanel';
-export { FormSchema } from './FormSchema';
-export { RefForm } from './RefForm';
-export { SchemaConfigForm } from './SchemaConfigForm';
-export { StartNode } from './spec/node';
+export { default as Flow } from './components/Flow/index.js';
+export { FlowWithPanel } from './components/FlowWithPanel/index.js';
+export { FormSchema } from './FormSchema/index.js';
+export { RefForm } from './RefForm/index.js';
+export { SchemaConfigForm } from './SchemaConfigForm/index.js';
+export { StartNode } from './spec/node.js';
export * from './utils/index.js';
import './tailwind.out.css';
diff --git a/web/packages/magent-flow/src/spec/node.ts b/web/packages/magent-flow/src/spec/node.ts
index 3994e02..5b01977 100644
--- a/web/packages/magent-flow/src/spec/node.ts
+++ b/web/packages/magent-flow/src/spec/node.ts
@@ -1,11 +1,12 @@
-import {
+import type {
NodeDataConfigType,
NodeDataMetaType,
NodeDataType,
- NodeTypeEnum,
-} from '@/interfaces/flow';
-import { FormSchema } from './FormSchema';
-import { UUID } from './uuid';
+} from '@/interfaces/flow.js';
+import { NodeTypeEnum } from '@/interfaces/flow.js';
+
+import { FormSchema } from './FormSchema/index.js';
+import { UUID } from './uuid.js';
// 不同类型的节点的基础类
//
diff --git a/web/packages/magent-flow/src/stores/useFlowStore.ts b/web/packages/magent-flow/src/stores/useFlowStore.ts
index f175086..0a7839e 100644
--- a/web/packages/magent-flow/src/stores/useFlowStore.ts
+++ b/web/packages/magent-flow/src/stores/useFlowStore.ts
@@ -14,8 +14,8 @@ import { addEdge, applyEdgeChanges, applyNodeChanges } from '@xyflow/react';
import { cloneDeep } from 'lodash';
import { create } from 'zustand';
-import type { NodeType } from '@/interfaces/flow';
-import { cleanEdges, getNodeId } from '@/utils/reactflowUtils';
+import type { NodeType } from '@/interfaces/flow.js';
+import { cleanEdges, getNodeId } from '@/utils/reactflowUtils.js';
interface AdjacencyList {
[key: number]: number[];
diff --git a/web/packages/magent-flow/src/stores/useShortcutsStore.ts b/web/packages/magent-flow/src/stores/useShortcutsStore.ts
index 78e3a3f..a7044ab 100644
--- a/web/packages/magent-flow/src/stores/useShortcutsStore.ts
+++ b/web/packages/magent-flow/src/stores/useShortcutsStore.ts
@@ -1,6 +1,6 @@
import { create } from 'zustand';
-import { defaultShortcuts } from '@/constants/constant';
+import { defaultShortcuts } from '@/constants/constant.js';
export type shortcutsStoreType = {
updateUniqueShortcut: (name: string, combination: string) => void;
diff --git a/web/packages/magent-flow/src/stores/useUndoRedoStore.ts b/web/packages/magent-flow/src/stores/useUndoRedoStore.ts
index 401c90b..5e9da9a 100644
--- a/web/packages/magent-flow/src/stores/useUndoRedoStore.ts
+++ b/web/packages/magent-flow/src/stores/useUndoRedoStore.ts
@@ -2,7 +2,7 @@ import type { Edge, Node } from '@xyflow/react';
import { cloneDeep } from 'lodash';
import { create } from 'zustand';
-import { useFlowStore } from './useFlowStore';
+import { useFlowStore } from './useFlowStore.js';
interface FlowRedoUndoStoreType {
undo: () => void;
diff --git a/web/packages/magent-flow/src/utils/basic.ts b/web/packages/magent-flow/src/utils/basic.ts
index a1db376..439133f 100644
--- a/web/packages/magent-flow/src/utils/basic.ts
+++ b/web/packages/magent-flow/src/utils/basic.ts
@@ -3,6 +3,8 @@ export function classNames(...classes: Array
): string {
}
export function capitalizeFirstLetter(s: string) {
- if (!s) return '';
+ if (!s) {
+ return '';
+ }
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
}
diff --git a/web/packages/magent-flow/src/utils/index.tsx b/web/packages/magent-flow/src/utils/index.tsx
index e1ad5ae..ec0f1b7 100644
--- a/web/packages/magent-flow/src/utils/index.tsx
+++ b/web/packages/magent-flow/src/utils/index.tsx
@@ -1,2 +1,2 @@
-export * from './basic';
-export * from './reactflowUtils';
+export * from './basic.js';
+export * from './reactflowUtils.js';
diff --git a/web/packages/magent-flow/src/utils/reactflowUtils.ts b/web/packages/magent-flow/src/utils/reactflowUtils.ts
index 07816ba..4760dbc 100644
--- a/web/packages/magent-flow/src/utils/reactflowUtils.ts
+++ b/web/packages/magent-flow/src/utils/reactflowUtils.ts
@@ -1,9 +1,9 @@
-import { Edge } from '@xyflow/react';
+import type { Edge } from '@xyflow/react';
import { cloneDeep } from 'lodash';
import { v4 } from 'uuid';
export function cleanEdges(nodes: any[], edges: Edge[]) {
- let newEdges = cloneDeep(edges);
+ const newEdges = cloneDeep(edges);
return newEdges;
}
From 134e1f8b1192fb0694527d57477587adb80e8992 Mon Sep 17 00:00:00 2001
From: "yukun.wyk"
Date: Tue, 27 Aug 2024 15:20:15 +0800
Subject: [PATCH 03/78] feat(ui): add flow page
---
.npmrc | 2 +
web/ui/config/routes.ts | 4 +
web/ui/package.json | 1 +
web/ui/src/modules/app.module.ts | 2 +
...bution.ts => debug-drawer-contribution.ts} | 2 +-
web/ui/src/views/agent-dev/module.ts | 4 +-
.../src/views/agent-flow/agent-flow-view.tsx | 77 ++++++++++
web/ui/src/views/agent-flow/flow-dev-view.tsx | 72 ++++++++++
web/ui/src/views/agent-flow/index.less | 131 ++++++++++++++++++
web/ui/src/views/agent-flow/index.tsx | 1 +
web/ui/src/views/agent-flow/module.ts | 17 +++
web/ui/src/views/agent-flow/protocol.ts | 5 +
web/ui/src/views/agent-flow/utils.ts | 34 +++++
web/ui/src/views/agents/view.tsx | 6 +-
14 files changed, 352 insertions(+), 6 deletions(-)
rename web/ui/src/views/agent-dev/{debug-contribution.ts => debug-drawer-contribution.ts} (75%)
create mode 100644 web/ui/src/views/agent-flow/agent-flow-view.tsx
create mode 100644 web/ui/src/views/agent-flow/flow-dev-view.tsx
create mode 100644 web/ui/src/views/agent-flow/index.less
create mode 100644 web/ui/src/views/agent-flow/index.tsx
create mode 100644 web/ui/src/views/agent-flow/module.ts
create mode 100644 web/ui/src/views/agent-flow/protocol.ts
create mode 100644 web/ui/src/views/agent-flow/utils.ts
diff --git a/.npmrc b/.npmrc
index 4b9b305..0730e0d 100644
--- a/.npmrc
+++ b/.npmrc
@@ -4,3 +4,5 @@ save-workspace-protocol=rolling
# pnpm deploy workaround https://github.com/pnpm/pnpm/issues/6437#issuecomment-1549409913
dedupe-peer-dependents=false
+
+link-workspace-packages=deep
diff --git a/web/ui/config/routes.ts b/web/ui/config/routes.ts
index a7753ac..e28e0db 100644
--- a/web/ui/config/routes.ts
+++ b/web/ui/config/routes.ts
@@ -30,6 +30,10 @@ export default [
path: '/agent/:agentId/dev',
slot: 'magent-agent-dev-slot',
},
+ {
+ path: '/agent/:agentId/flow',
+ slot: 'magent-agent-flow-dev-slot',
+ },
],
},
];
diff --git a/web/ui/package.json b/web/ui/package.json
index 4d215ea..45fc42a 100644
--- a/web/ui/package.json
+++ b/web/ui/package.json
@@ -26,6 +26,7 @@
"@difizen/libro-jupyter": "^0.2.1",
"@difizen/libro-lab": "^0.2.1",
"@difizen/libro-markdown": "^0.2.1",
+ "@difizen/magent-flow": "workspace:^",
"@difizen/mana-app": "^0.1.8",
"@difizen/mana-react": "^0.1.8",
"@rjsf/antd": "^5.18.2",
diff --git a/web/ui/src/modules/app.module.ts b/web/ui/src/modules/app.module.ts
index 8e58b42..61bcbeb 100644
--- a/web/ui/src/modules/app.module.ts
+++ b/web/ui/src/modules/app.module.ts
@@ -2,6 +2,7 @@ import { ManaModule } from '@difizen/mana-app';
import { AgentConfigViewModule } from '../views/agent-config/index.js';
import { AgentChatModule } from '../views/agent-dev/index.js';
+import { AgentFlowModule } from '../views/agent-flow/module.js';
import { AgentsPageModule } from '../views/agents/index.js';
import { ChatViewModule } from '../views/chat/module.js';
import { KnowledgePageModule } from '../views/knowledge/module.js';
@@ -39,6 +40,7 @@ export const AppBaseModule = new ManaModule()
KnowledgePageModule,
AgentConfigViewModule,
PortalsModule,
+ AgentFlowModule,
);
export default AppBaseModule;
diff --git a/web/ui/src/views/agent-dev/debug-contribution.ts b/web/ui/src/views/agent-dev/debug-drawer-contribution.ts
similarity index 75%
rename from web/ui/src/views/agent-dev/debug-contribution.ts
rename to web/ui/src/views/agent-dev/debug-drawer-contribution.ts
index 8fd6553..60e2843 100644
--- a/web/ui/src/views/agent-dev/debug-contribution.ts
+++ b/web/ui/src/views/agent-dev/debug-drawer-contribution.ts
@@ -3,7 +3,7 @@ import { ModalContribution, singleton } from '@difizen/mana-app';
import { DebugModal } from './debug-modal.js';
@singleton({ contrib: [ModalContribution] })
-export class DebugContribution implements ModalContribution {
+export class DebugDrawerContribution implements ModalContribution {
registerModal() {
return DebugModal;
}
diff --git a/web/ui/src/views/agent-dev/module.ts b/web/ui/src/views/agent-dev/module.ts
index c03a39f..e62c2b7 100644
--- a/web/ui/src/views/agent-dev/module.ts
+++ b/web/ui/src/views/agent-dev/module.ts
@@ -3,13 +3,13 @@ import { createSlotPreference, ManaModule } from '@difizen/mana-app';
import { AgentConfigViewModule } from '../agent-config/module.js';
import { AgentView, slot as ChatSlot } from './chat-view.js';
-import { DebugContribution } from './debug-contribution.js';
+import { DebugDrawerContribution } from './debug-drawer-contribution.js';
import { AgentDevView, slot as DevSlot } from './dev-view.js';
export const AgentChatModule = ManaModule.create()
.register(
AgentView,
- DebugContribution,
+ DebugDrawerContribution,
createSlotPreference({
slot: ChatSlot,
view: AgentView,
diff --git a/web/ui/src/views/agent-flow/agent-flow-view.tsx b/web/ui/src/views/agent-flow/agent-flow-view.tsx
new file mode 100644
index 0000000..d0f82f6
--- /dev/null
+++ b/web/ui/src/views/agent-flow/agent-flow-view.tsx
@@ -0,0 +1,77 @@
+import { SaveOutlined } from '@ant-design/icons';
+import { FlowWithPanel } from '@difizen/magent-flow';
+import {
+ BaseView,
+ ViewInstance,
+ inject,
+ prop,
+ useInject,
+ view,
+ ViewOption,
+ transient,
+} from '@difizen/mana-app';
+import { Flex } from 'antd';
+import { forwardRef } from 'react';
+
+import { AgentManager } from '../../modules/agent/index.js';
+import type { AgentModel } from '../../modules/agent/index.js';
+
+import './index.less';
+
+const viewId = 'magent-agent-flow';
+
+const AgentFlowComponent = forwardRef(
+ function AgentConfigViewComponent(props, ref) {
+ const instance = useInject(ViewInstance);
+
+ return (
+
+
+
+ );
+ },
+);
+
+export interface AgentConfigViewOption {
+ agentId: string;
+}
+@transient()
+@view(viewId)
+export class AgentFlowView extends BaseView {
+ agentId: string;
+ override view = AgentFlowComponent;
+
+ @prop() agent: AgentModel;
+ protected agentManager: AgentManager;
+ constructor(
+ @inject(ViewOption) option: AgentConfigViewOption,
+ @inject(AgentManager) agentManager: AgentManager,
+ ) {
+ super();
+ this.agentId = option.agentId;
+ this.agentManager = agentManager;
+ this.initAgent(option.agentId);
+ }
+
+ get modelOptions() {
+ // TODO 大模型optios列表和对应存取值要怎么取?
+ return (
+ this.agent?.llm?.model_name?.map((item) => {
+ return {
+ label: item,
+ value: item,
+ };
+ }) || []
+ );
+ }
+
+ protected initAgent = (agentId = this.agentId) => {
+ if (agentId) {
+ const agent = this.agentManager.getOrCreateAgent({ id: agentId });
+ agent.fetchInfo();
+ this.agent = agent;
+ return agent;
+ }
+ return undefined;
+ };
+}
diff --git a/web/ui/src/views/agent-flow/flow-dev-view.tsx b/web/ui/src/views/agent-flow/flow-dev-view.tsx
new file mode 100644
index 0000000..a892ac4
--- /dev/null
+++ b/web/ui/src/views/agent-flow/flow-dev-view.tsx
@@ -0,0 +1,72 @@
+import { ViewRender } from '@difizen/mana-app';
+import { ViewInstance, singleton, useInject, view } from '@difizen/mana-app';
+import { BoxPanel } from '@difizen/mana-react';
+import { forwardRef, useEffect } from 'react';
+import { useMatch } from 'react-router-dom';
+
+import type { AgentConfigManager } from '../../modules/agent/agent-config-manager.js';
+import { AgentView } from '../agent-dev/chat-view.js';
+
+import { AgentFlowView } from './agent-flow-view.js';
+
+import './index.less';
+
+const viewId = 'magent-agent-flow-dev';
+export const slot = `${viewId}-slot`;
+
+const AgentFlowDevComponent = forwardRef(
+ function AgentsViewComponent(props, ref) {
+ const instance = useInject(ViewInstance);
+ const match = useMatch('/agent/:agentId/flow');
+ const agentId = match?.params?.agentId;
+ instance.agentId = agentId;
+
+ useEffect(() => {
+ instance.openChat(instance.sessions?.active);
+ }, [instance, instance.sessions?.active]);
+
+ return (
+
+
+ {instance.agentFlow && }
+ {/*
+ {instance.agentFlow && }
+
+
+
+
预览
+
+
+ {instance.chat && }
+
+ */}
+
+
+ );
+ },
+);
+
+@singleton()
+@view(viewId)
+export class AgentFlowDevView extends AgentView {
+ protected agentConfigManager: AgentConfigManager;
+
+ agentFlow?: AgentFlowView;
+
+ override view = AgentFlowDevComponent;
+
+ protected override initialize() {
+ super.initialize();
+ this.initAgentFlowView();
+ }
+
+ protected initAgentFlowView = async () => {
+ if (!this.agentId) {
+ return;
+ }
+ const agentFlow = await this.viewManager.getOrCreateView(AgentFlowView, {
+ agentId: this.agentId,
+ });
+ this.agentFlow = agentFlow;
+ };
+}
diff --git a/web/ui/src/views/agent-flow/index.less b/web/ui/src/views/agent-flow/index.less
new file mode 100644
index 0000000..e7c505e
--- /dev/null
+++ b/web/ui/src/views/agent-flow/index.less
@@ -0,0 +1,131 @@
+.magent-agent-chat-layout {
+ height: 100%;
+
+ &-container {
+ gap: 16px;
+ box-sizing: border-box;
+ padding: 12px 24px;
+ }
+
+ &-history {
+ width: 260px;
+ }
+
+ &-chat {
+ max-width: calc(100% - 276px);
+ }
+}
+
+.magent-agent-flow-dev-layout {
+ height: 100%;
+ width: 100%;
+}
+
+.magent-agent-dev-layout {
+ height: 100%;
+
+ &-container {
+ gap: 16px;
+ box-sizing: border-box;
+ padding: 12px 24px;
+ }
+
+ &-config {
+ width: 55%;
+ }
+
+ &-chat-dev {
+ height: 100%;
+ min-width: 520px;
+ width: 520px;
+ background-color: var(--mana-color-bg-container);
+ border-radius: 8px;
+
+ &-header {
+ padding: 0 24px;
+ height: 64px;
+ border-bottom: 1px solid var(--mana-color-border);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ h3 {
+ margin: 0;
+ }
+ }
+
+ &-content {
+ height: calc(100% - 64px);
+ }
+ }
+}
+
+.magent-debug {
+ width: 622px;
+}
+
+.magent-debug-header {
+ background-color: #f7f7fa;
+ border-bottom: 1px solid rgba(29, 28, 35, 8%);
+ padding: 16px 24px;
+}
+
+.magent-select-container {
+ padding: 24px 24px 4px;
+ width: 100%;
+
+ :global {
+ background-color: rgba(139, 139, 149, 15%);
+ color: rgba(75, 74, 88, 100%);
+ }
+}
+
+.magent-summary-container {
+ padding: 16px 24px 24px;
+ position: relative;
+ width: 100%;
+}
+
+.magent-summary-title-container {
+ margin-bottom: 16px;
+}
+
+.magent-summary-title-data {
+ color: #1d1c23;
+ font-size: 14px;
+ font-weight: 600;
+ margin-right: 8px;
+}
+
+.magent-des-item {
+ display: flex;
+ font-size: 13px;
+ line-height: 22px;
+ text-align: left;
+}
+
+.magent-des-key {
+ color: rgba(29, 28, 35, 35%);
+ margin-right: 4px;
+}
+
+.magent-des-value {
+ color: rgba(29, 28, 35, 80%);
+}
+
+.magent-des-icon {
+ margin-left: 6px;
+ cursor: pointer;
+}
+
+.magent-agent-flow {
+ height: 100%;
+ width: 100%;
+ overflow-y: auto;
+ display: flex;
+ justify-items: center;
+ flex-direction: column;
+ background-color: var(--mana-color-bg-container);
+ box-sizing: border-box;
+ border-radius: 8px;
+}
diff --git a/web/ui/src/views/agent-flow/index.tsx b/web/ui/src/views/agent-flow/index.tsx
new file mode 100644
index 0000000..fd3c604
--- /dev/null
+++ b/web/ui/src/views/agent-flow/index.tsx
@@ -0,0 +1 @@
+export * from './module.js';
diff --git a/web/ui/src/views/agent-flow/module.ts b/web/ui/src/views/agent-flow/module.ts
new file mode 100644
index 0000000..75d6ef5
--- /dev/null
+++ b/web/ui/src/views/agent-flow/module.ts
@@ -0,0 +1,17 @@
+import { createSlotPreference, ManaModule } from '@difizen/mana-app';
+
+import { AgentConfigViewModule } from '../agent-config/module.js';
+
+import { AgentFlowView } from './agent-flow-view.js';
+import { AgentFlowDevView, slot } from './flow-dev-view.js';
+
+export const AgentFlowModule = ManaModule.create()
+ .register(
+ AgentFlowView,
+ AgentFlowDevView,
+ createSlotPreference({
+ slot: slot,
+ view: AgentFlowDevView,
+ }),
+ )
+ .dependOn(AgentConfigViewModule);
diff --git a/web/ui/src/views/agent-flow/protocol.ts b/web/ui/src/views/agent-flow/protocol.ts
new file mode 100644
index 0000000..d33e96b
--- /dev/null
+++ b/web/ui/src/views/agent-flow/protocol.ts
@@ -0,0 +1,5 @@
+export const AgentLayoutSlots = {
+ history: 'magent-agent-chat-history',
+ config: 'magent-agent-dev-config',
+ chat: 'magent-agent-chat',
+};
diff --git a/web/ui/src/views/agent-flow/utils.ts b/web/ui/src/views/agent-flow/utils.ts
new file mode 100644
index 0000000..e05cbde
--- /dev/null
+++ b/web/ui/src/views/agent-flow/utils.ts
@@ -0,0 +1,34 @@
+function copyFallback(string: string) {
+ function handler(event: ClipboardEvent) {
+ const clipboardData = event.clipboardData || (window as any).clipboardData;
+ clipboardData.setData('text/plain', string);
+ event.preventDefault();
+ document.removeEventListener('copy', handler, true);
+ }
+
+ document.addEventListener('copy', handler, true);
+ document.execCommand('copy');
+}
+// 复制到剪贴板
+export const copy2clipboard = (string: string) => {
+ navigator.permissions
+ .query({
+ name: 'clipboard-write' as any,
+ })
+ .then((result) => {
+ if (result.state === 'granted' || result.state === 'prompt') {
+ if (window.navigator && window.navigator.clipboard) {
+ window.navigator.clipboard.writeText(string);
+ } else {
+ console.warn('navigator is not exist');
+ }
+ } else {
+ console.warn('浏览器权限不允许复制');
+ copyFallback(string);
+ }
+ return;
+ })
+ .catch(() => {
+ //
+ });
+};
diff --git a/web/ui/src/views/agents/view.tsx b/web/ui/src/views/agents/view.tsx
index a4220a2..e79ce0a 100644
--- a/web/ui/src/views/agents/view.tsx
+++ b/web/ui/src/views/agents/view.tsx
@@ -17,7 +17,7 @@ import './index.less';
import { AgentIcon } from '../../modules/agent/agent-icon.js';
import { AgentMarket } from '../../modules/agent/agent-market.js';
-import { AgentCreateModal, agentCreateModalId } from './modal/create.js';
+import { AgentCreateModal } from './modal/create.js';
const viewId = 'magent-agents';
export const slot = `${viewId}-slot`;
@@ -65,7 +65,7 @@ const AgentsViewComponent = forwardRef(
))}
- {/*
+
-
*/}
+
);
},
From d910bb63d6bfacba413f0ad522b71ddbb5556b13 Mon Sep 17 00:00:00 2001
From: "yukun.wyk"
Date: Tue, 27 Aug 2024 19:05:24 +0800
Subject: [PATCH 04/78] feat(ui): add agent & workflow creation api
---
.../src/magent_ui/routers/agents/router.py | 3 +++
.../magent-ui/src/magent_ui/routers/main.py | 2 ++
.../magent_ui/routers/workflow/__init__.py | 0
.../src/magent_ui/routers/workflow/router.py | 20 +++++++++++++++++++
4 files changed, 25 insertions(+)
create mode 100644 packages/magent-ui/src/magent_ui/routers/workflow/__init__.py
create mode 100644 packages/magent-ui/src/magent_ui/routers/workflow/router.py
diff --git a/packages/magent-ui/src/magent_ui/routers/agents/router.py b/packages/magent-ui/src/magent_ui/routers/agents/router.py
index aebbe3e..3647360 100644
--- a/packages/magent-ui/src/magent_ui/routers/agents/router.py
+++ b/packages/magent-ui/src/magent_ui/routers/agents/router.py
@@ -26,6 +26,9 @@ async def get_agent_detail(agent_id):
async def update_agent(agent_id, agent: AgentDTO):
return AgentService.update_agent(agent)
+@router.post("/agents", response_model=AgentDTO)
+async def create_agent(agent: AgentDTO):
+ return AgentService.create_agent(agent)
class MessageSenderType(enum.Enum):
AI = "ai"
diff --git a/packages/magent-ui/src/magent_ui/routers/main.py b/packages/magent-ui/src/magent_ui/routers/main.py
index 76855a7..3d59900 100644
--- a/packages/magent-ui/src/magent_ui/routers/main.py
+++ b/packages/magent-ui/src/magent_ui/routers/main.py
@@ -5,6 +5,7 @@
from magent_ui.routers.sessions.router import sessions_router
from magent_ui.routers.tools.router import tools_router
from magent_ui.routers.resource.router import resource_router
+from magent_ui.routers.workflow.router import workflow_router
api_router = APIRouter()
@@ -14,3 +15,4 @@
api_router.include_router(sessions_router, prefix="/v1", tags=["session"])
api_router.include_router(tools_router, prefix="/v1", tags=["tool"])
api_router.include_router(resource_router, prefix="/v1", tags=["resource"])
+api_router.include_router(workflow_router, prefix="/v1", tags=["workflow"])
diff --git a/packages/magent-ui/src/magent_ui/routers/workflow/__init__.py b/packages/magent-ui/src/magent_ui/routers/workflow/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/packages/magent-ui/src/magent_ui/routers/workflow/router.py b/packages/magent-ui/src/magent_ui/routers/workflow/router.py
new file mode 100644
index 0000000..2235c83
--- /dev/null
+++ b/packages/magent-ui/src/magent_ui/routers/workflow/router.py
@@ -0,0 +1,20 @@
+from fastapi import APIRouter
+from agentuniverse_product.service.workflow_service.workflow_service import WorkflowService
+from agentuniverse_product.service.model.workflow_dto import WorkflowDTO
+
+router = APIRouter()
+workflow_router = router
+
+
+@router.get("/workflows/{workflow_id}", response_model=WorkflowDTO | None)
+async def get_agent_detail(workflow_id):
+ return WorkflowService.get_workflow_detail(workflow_id)
+
+
+@router.put("/workflows/{workflow_id}", response_model=WorkflowDTO | None)
+async def update_agent(workflow_id, workflow: WorkflowDTO):
+ return WorkflowService.update_workflow(workflow)
+
+@router.post("/workflows", response_model=WorkflowDTO)
+async def create_agent(workflow: WorkflowDTO):
+ return WorkflowService.create_workflow(workflow)
From 05bab7a93eccd853b5b6a8edf141a4c357578fc6 Mon Sep 17 00:00:00 2001
From: "yukun.wyk"
Date: Tue, 27 Aug 2024 19:06:00 +0800
Subject: [PATCH 05/78] feat(ui): model icon & import path alias
---
.../src/modules/model/model-icon/baichuan.svg | 1 +
.../src/modules/model/model-icon/deepseek.svg | 1 +
web/ui/src/modules/model/model-icon/ernie.svg | 1 +
web/ui/src/modules/model/model-icon/index.tsx | 65 +++++++++++++++++
.../src/modules/model/model-icon/moonshot.svg | 1 +
.../src/modules/model/model-icon/openai.svg | 5 ++
web/ui/src/modules/model/model-icon/qwen.svg | 12 ++++
.../components/model-selector/index.tsx | 22 +-----
.../components/model-selector/logos.tsx | 69 -------------------
web/ui/src/views/agent-dev/debug-modal.tsx | 7 +-
web/ui/tsconfig.json | 3 +
web/ui/typings/index.d.ts | 1 +
12 files changed, 96 insertions(+), 92 deletions(-)
create mode 100644 web/ui/src/modules/model/model-icon/baichuan.svg
create mode 100644 web/ui/src/modules/model/model-icon/deepseek.svg
create mode 100644 web/ui/src/modules/model/model-icon/ernie.svg
create mode 100644 web/ui/src/modules/model/model-icon/index.tsx
create mode 100644 web/ui/src/modules/model/model-icon/moonshot.svg
create mode 100644 web/ui/src/modules/model/model-icon/openai.svg
create mode 100644 web/ui/src/modules/model/model-icon/qwen.svg
delete mode 100644 web/ui/src/views/agent-config/components/model-selector/logos.tsx
diff --git a/web/ui/src/modules/model/model-icon/baichuan.svg b/web/ui/src/modules/model/model-icon/baichuan.svg
new file mode 100644
index 0000000..ebd9800
--- /dev/null
+++ b/web/ui/src/modules/model/model-icon/baichuan.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/ui/src/modules/model/model-icon/deepseek.svg b/web/ui/src/modules/model/model-icon/deepseek.svg
new file mode 100644
index 0000000..658e9dd
--- /dev/null
+++ b/web/ui/src/modules/model/model-icon/deepseek.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/ui/src/modules/model/model-icon/ernie.svg b/web/ui/src/modules/model/model-icon/ernie.svg
new file mode 100644
index 0000000..36ff641
--- /dev/null
+++ b/web/ui/src/modules/model/model-icon/ernie.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/ui/src/modules/model/model-icon/index.tsx b/web/ui/src/modules/model/model-icon/index.tsx
new file mode 100644
index 0000000..5532dfe
--- /dev/null
+++ b/web/ui/src/modules/model/model-icon/index.tsx
@@ -0,0 +1,65 @@
+import { lazy, Suspense } from 'react';
+
+import type { ModelMeta } from '@/modules/model/protocol.js';
+
+const LazyIcon = (props: { loader: () => Promise }) => {
+ const Component = lazy(async () => {
+ const icon = await props.loader();
+ return { default: () => };
+ });
+ return (
+ }>
+
+
+ );
+};
+
+export const DefaultLLMIcon = () => {
+ return (
+
+ );
+};
+
+const match = (data: ModelMeta, name: string): boolean => {
+ if (
+ data.id.toLowerCase().includes(name) ||
+ data.nickname.toLowerCase().includes(name) ||
+ data.model_name[0].toLowerCase().includes(name)
+ ) {
+ return true;
+ }
+ return false;
+};
+
+export const LLMIcon = (props: { data: ModelMeta }) => {
+ const { data } = props;
+ if (match(data, 'qwen')) {
+ return import('./qwen.svg')} />;
+ }
+ if (match(data, 'openai')) {
+ return import('./openai.svg')} />;
+ }
+ if (match(data, 'baichuan')) {
+ return import('./baichuan.svg')} />;
+ }
+ if (match(data, 'deepseek')) {
+ return import('./deepseek.svg')} />;
+ }
+ if (match(data, 'ernie')) {
+ return import('./ernie.svg')} />;
+ }
+ if (match(data, 'moonshot')) {
+ return import('./moonshot.svg')} />;
+ }
+ return ;
+};
diff --git a/web/ui/src/modules/model/model-icon/moonshot.svg b/web/ui/src/modules/model/model-icon/moonshot.svg
new file mode 100644
index 0000000..ac19383
--- /dev/null
+++ b/web/ui/src/modules/model/model-icon/moonshot.svg
@@ -0,0 +1 @@
+
diff --git a/web/ui/src/modules/model/model-icon/openai.svg b/web/ui/src/modules/model/model-icon/openai.svg
new file mode 100644
index 0000000..eea83cb
--- /dev/null
+++ b/web/ui/src/modules/model/model-icon/openai.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/web/ui/src/modules/model/model-icon/qwen.svg b/web/ui/src/modules/model/model-icon/qwen.svg
new file mode 100644
index 0000000..b5dff55
--- /dev/null
+++ b/web/ui/src/modules/model/model-icon/qwen.svg
@@ -0,0 +1,12 @@
+
+
+
diff --git a/web/ui/src/views/agent-config/components/model-selector/index.tsx b/web/ui/src/views/agent-config/components/model-selector/index.tsx
index 9d33d61..e177152 100644
--- a/web/ui/src/views/agent-config/components/model-selector/index.tsx
+++ b/web/ui/src/views/agent-config/components/model-selector/index.tsx
@@ -3,34 +3,16 @@ import { ViewInstance, useInject } from '@difizen/mana-app';
import { Button, Form, Select, Popover, Avatar, Slider } from 'antd';
import { forwardRef, useEffect } from 'react';
+import { LLMIcon } from '@/modules/model/model-icon/index.js';
+
import { LLMManager } from '../../../../modules/model/llm-manager.js';
import type { ModelMeta } from '../../../../modules/model/protocol.js';
import type { AgentConfigView } from '../../view.js';
import './index.less';
-import { DefaultLogo, OpenAILogo, QwenLogo } from './logos.js';
const clsPrefix = 'agent-config-model-selector';
-const LLMIcon = (props: { data: ModelMeta }) => {
- const { data } = props;
- if (
- data.id.toLowerCase().includes('qwen') ||
- data.nickname.toLowerCase().includes('qwen') ||
- data.model_name[0].toLowerCase().includes('qwen')
- ) {
- return ;
- }
- if (
- data.id.toLowerCase().includes('openai') ||
- data.nickname.toLowerCase().includes('openai') ||
- data.model_name[0].toLowerCase().includes('openai')
- ) {
- return ;
- }
- return ;
-};
-
const ModelSelectorOption = (props: { model: ModelMeta; flat?: boolean }) => {
const { model, flat } = props;
return (
diff --git a/web/ui/src/views/agent-config/components/model-selector/logos.tsx b/web/ui/src/views/agent-config/components/model-selector/logos.tsx
deleted file mode 100644
index 020aaed..0000000
--- a/web/ui/src/views/agent-config/components/model-selector/logos.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-export const OpenAILogo = () => {
- return (
-
- );
-};
-
-export const QwenLogo = () => {
- return (
-
- );
-};
-
-export const MoonshotLogo = () => {
- return (
-
- );
-};
-
-export const DefaultLogo = () => {
- return (
-
- );
-};
diff --git a/web/ui/src/views/agent-dev/debug-modal.tsx b/web/ui/src/views/agent-dev/debug-modal.tsx
index 50d327b..d1a3066 100644
--- a/web/ui/src/views/agent-dev/debug-modal.tsx
+++ b/web/ui/src/views/agent-dev/debug-modal.tsx
@@ -7,8 +7,9 @@ import { Avatar } from 'antd';
import { Col, Drawer, Row, Select, Tree } from 'antd';
import { useState } from 'react';
+import { DefaultLLMIcon } from '@/modules/model/model-icon/index.js';
+
import { DefaultToolIcon } from '../../modules/tool/tool-icon.js';
-import { DefaultLogo } from '../agent-config/components/model-selector/logos.js';
import { HumanIcon } from '../chat/components/message/human-message.js';
import type { ChatView } from '../chat/view.js';
@@ -45,10 +46,10 @@ export function DebugModalComponent({
children: invocationChain.map((item) => {
let iconSrc = undefined;
if (item.type === 'llm') {
- iconSrc = ;
+ iconSrc = ;
}
if (item.type === 'agent') {
- iconSrc = ;
+ iconSrc = ;
}
if (item.type === 'tool') {
iconSrc = ;
diff --git a/web/ui/tsconfig.json b/web/ui/tsconfig.json
index df7da4f..1ac0e79 100644
--- a/web/ui/tsconfig.json
+++ b/web/ui/tsconfig.json
@@ -1,6 +1,9 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
+ "paths": {
+ "@/*": ["./src/*"]
+ },
/* interop */
"allowJs": true,
"allowSyntheticDefaultImports": true,
diff --git a/web/ui/typings/index.d.ts b/web/ui/typings/index.d.ts
index ad32997..adb8688 100644
--- a/web/ui/typings/index.d.ts
+++ b/web/ui/typings/index.d.ts
@@ -14,3 +14,4 @@ interface Pagination {
}
declare module '*.jpg';
+declare module '*.svg';
From 6c04d837db15270acdf41e56a8a8529241d39056 Mon Sep 17 00:00:00 2001
From: "yukun.wyk"
Date: Tue, 27 Aug 2024 19:41:28 +0800
Subject: [PATCH 06/78] feat(ui): performance of llm temperature slider
---
web/ui/src/modules/agent/agent-model.ts | 11 +++--
web/ui/src/modules/model/llm-manager.ts | 19 +++++--
web/ui/src/modules/model/llm-model.ts | 3 +-
.../components/model-selector/index.tsx | 49 ++++++++++++-------
4 files changed, 57 insertions(+), 25 deletions(-)
diff --git a/web/ui/src/modules/agent/agent-model.ts b/web/ui/src/modules/agent/agent-model.ts
index 1e2bb68..20215f8 100644
--- a/web/ui/src/modules/agent/agent-model.ts
+++ b/web/ui/src/modules/agent/agent-model.ts
@@ -3,6 +3,8 @@ import { inject, prop, transient } from '@difizen/mana-app';
import { AsyncModel } from '../../common/async-model.js';
import { AxiosClient } from '../axios-client/index.js';
import type { KnowledgeModelOption } from '../knowledge/protocol.js';
+import { LLMManager } from '../model/llm-manager.js';
+import type { LLMModel } from '../model/llm-model.js';
import type { ToolModelOption } from '../tool/index.js';
import { ToolManager } from '../tool/index.js';
@@ -40,6 +42,7 @@ export class AgentModel extends AsyncModel {
axios: AxiosClient;
// configManager: AgentConfigManager;
+ protected llmManager: LLMManager;
id: string;
@@ -53,7 +56,7 @@ export class AgentModel extends AsyncModel {
description?: string;
@prop()
- llm?: LLMMeta;
+ llm?: LLMModel;
@prop()
prompt?: Prompt;
@@ -79,12 +82,14 @@ export class AgentModel extends AsyncModel {
constructor(
@inject(AgentModelOption) option: AgentModelOption,
@inject(AgentConfigManager) configManager: AgentConfigManager,
+ @inject(LLMManager) llmManager: LLMManager,
@inject(AxiosClient) axios: AxiosClient,
) {
super();
this.option = option;
// this.configManager = configManager;
this.axios = axios;
+ this.llmManager = llmManager;
this.id = option.id;
this.initialize(option);
@@ -105,7 +110,7 @@ export class AgentModel extends AsyncModel {
this.description = option.description;
this.prompt = option.prompt ? new Prompt(option.prompt) : undefined;
- this.llm = option.llm;
+ this.llm = option.llm ? this.llmManager.getOrCreate(option.llm) : option.llm;
this.memory = option.memory ?? '';
this.planner = option.planner;
this.knowledge = option.knowledge;
@@ -139,7 +144,7 @@ export class AgentModel extends AsyncModel {
avatar: this.avatar,
description: this.description,
prompt: this.prompt?.toMeta(),
- llm: this.llm,
+ llm: this.llm?.toMeta(),
planner: this.planner,
tool: this.tool,
memory: this.memory,
diff --git a/web/ui/src/modules/model/llm-manager.ts b/web/ui/src/modules/model/llm-manager.ts
index c0691e5..cf045fc 100644
--- a/web/ui/src/modules/model/llm-manager.ts
+++ b/web/ui/src/modules/model/llm-manager.ts
@@ -8,13 +8,14 @@ import { LLMModelFactory } from './protocol.js';
@singleton()
export class LLMManager {
+ protected cache: Map = new Map();
@inject(LLMModelFactory) factory: LLMModelFactory;
@inject(AxiosClient) axios: AxiosClient;
@prop()
models: LLMModel[] = [];
- // defaultModel?: ModelMeta;
+ defaultModel?: LLMModel;
protected getModelsMeta = async () => {
const defaultValue: ModelMeta[] = [];
@@ -27,10 +28,20 @@ export class LLMManager {
updateModels = async () => {
const metas = await this.getModelsMeta();
- this.models = metas.map((item) => this.factory(item));
+ this.models = metas.map((item) => this.getOrCreate(item));
if (this.models.length > 0) {
- const defaultLLMs = this.models[0];
- this.defaultModel = defaultLLMs.toSingleMeta(defaultLLMs.models[0]);
+ const defaultLLM = this.models[0];
+ this.defaultModel = defaultLLM;
}
};
+
+ getOrCreate = (option: ModelMeta): LLMModel => {
+ const exist = this.cache.get(option.id);
+ if (exist) {
+ return exist;
+ }
+ const llm = this.factory(option);
+ this.cache.set(llm.id, llm);
+ return llm;
+ };
}
diff --git a/web/ui/src/modules/model/llm-model.ts b/web/ui/src/modules/model/llm-model.ts
index dfd2134..849346b 100644
--- a/web/ui/src/modules/model/llm-model.ts
+++ b/web/ui/src/modules/model/llm-model.ts
@@ -1,4 +1,4 @@
-import { inject, transient } from '@difizen/mana-app';
+import { inject, prop, transient } from '@difizen/mana-app';
import { LLMModelOption, type ModelMeta } from './protocol.js';
@@ -8,6 +8,7 @@ export class LLMModel {
name: string;
models: string[] = [];
+ @prop()
temperature: number;
protected configStr: string;
diff --git a/web/ui/src/views/agent-config/components/model-selector/index.tsx b/web/ui/src/views/agent-config/components/model-selector/index.tsx
index e177152..0a145d0 100644
--- a/web/ui/src/views/agent-config/components/model-selector/index.tsx
+++ b/web/ui/src/views/agent-config/components/model-selector/index.tsx
@@ -1,8 +1,11 @@
import { CaretDownOutlined } from '@ant-design/icons';
-import { ViewInstance, useInject } from '@difizen/mana-app';
+import { ViewInstance, useInject, useObserve } from '@difizen/mana-app';
+import type { SliderSingleProps } from 'antd';
import { Button, Form, Select, Popover, Avatar, Slider } from 'antd';
+import type { FC } from 'react';
import { forwardRef, useEffect } from 'react';
+import type { LLMModel } from '@/modules/model/llm-model.js';
import { LLMIcon } from '@/modules/model/model-icon/index.js';
import { LLMManager } from '../../../../modules/model/llm-manager.js';
@@ -35,6 +38,30 @@ const toKey = (model?: ModelMeta) => {
return model.id + model.model_name[0];
};
+interface TemperatureSliderProps extends SliderSingleProps {
+ llm?: LLMModel;
+}
+const TemperatureSlider: FC = (
+ props: TemperatureSliderProps,
+) => {
+ const llm = useObserve(props.llm);
+ const temperature = llm?.temperature;
+ return (
+ {
+ if (llm) {
+ llm.temperature = v;
+ }
+ }}
+ value={temperature === undefined ? 1 : temperature}
+ />
+ );
+};
+
export const ModelSelector = forwardRef(
function ModelSelectorComponent(props, ref) {
const instance = useInject(ViewInstance);
@@ -55,11 +82,9 @@ export const ModelSelector = forwardRef(
}, [modelManager]);
const currentModel = metaModels.find(
- (item) => modelMeta && toKey(item) === toKey(modelMeta),
+ (item) => modelMeta && toKey(item) === toKey(modelMeta.toMeta()),
);
- const temperature = instance.agent.llm?.temperature;
-
return (
(
onSelect={(v) => {
const llm = metaModels.find((i) => toKey(i) === v);
if (instance.agent.llm && llm) {
- instance.agent.llm = llm;
+ instance.agent.llm = modelManager.getOrCreate(llm);
}
}}
- value={toKey(instance.agent.llm)}
+ value={toKey(instance.agent.llm?.toMeta())}
>
{models.map((model) => (
@@ -96,17 +121,7 @@ export const ModelSelector = forwardRef(
- {
- if (instance.agent.llm) {
- instance.agent.llm.temperature = v;
- }
- }}
- value={temperature === undefined ? 1 : temperature}
- />
+
From 09ce5905ad370baf289e2eaa3aba3a1d24e90d8a Mon Sep 17 00:00:00 2001
From: "yukun.wyk"
Date: Tue, 27 Aug 2024 20:03:33 +0800
Subject: [PATCH 07/78] =?UTF-8?q?refactor(ui):=20use=20short=20reference?=
=?UTF-8?q?=20paths=EF=BC=8Cand=20remove=20base=20module=20exports=20file?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/modules/agent/agent-config-manager.ts | 5 ++--
web/ui/src/modules/agent/agent-config.ts | 13 +++++++----
web/ui/src/modules/agent/agent-icon.tsx | 3 ++-
web/ui/src/modules/agent/agent-manager.ts | 6 ++---
web/ui/src/modules/agent/agent-market.ts | 4 ++--
web/ui/src/modules/agent/agent-model.ts | 11 +++++----
web/ui/src/modules/agent/index.ts | 6 -----
web/ui/src/modules/agent/module.ts | 2 --
web/ui/src/modules/app.module.ts | 12 +++++-----
web/ui/src/modules/axios-client/client.ts | 2 +-
web/ui/src/modules/axios-client/index.ts | 2 --
web/ui/src/modules/base-layout/index.ts | 1 -
.../modules/chat-message/ai-message-item.ts | 2 +-
.../modules/chat-message/chat-message-item.ts | 2 +-
.../chat-message/chat-message-manager.ts | 2 +-
.../chat-message/chat-message-model.ts | 4 ++--
web/ui/src/modules/chat-message/index.ts | 2 --
web/ui/src/modules/knowledge/index.ts | 4 ----
.../src/modules/knowledge/knowledge-icon.tsx | 2 +-
.../modules/knowledge/knowledge-manager.ts | 6 ++---
.../src/modules/knowledge/knowledge-model.ts | 4 ++--
.../src/modules/knowledge/knowledge-space.ts | 4 ++--
web/ui/src/modules/session/index.ts | 3 ---
web/ui/src/modules/session/session-manager.ts | 2 +-
web/ui/src/modules/session/session-model.ts | 4 ++--
web/ui/src/modules/tool/index.ts | 6 -----
.../src/modules/tool/tool-config-manager.ts | 2 +-
web/ui/src/modules/tool/tool-config.ts | 4 ++--
web/ui/src/modules/tool/tool-icon.tsx | 2 +-
web/ui/src/modules/tool/tool-manager.ts | 6 ++---
web/ui/src/modules/tool/tool-model.ts | 4 ++--
web/ui/src/modules/tool/tool-space.ts | 4 ++--
.../components/model-selector/index.tsx | 4 ++--
.../agent-config/knowledge-modal/modal.tsx | 8 +++----
.../views/agent-config/tools-modal/modal.tsx | 8 +++----
web/ui/src/views/agent-config/view.tsx | 12 +++++-----
web/ui/src/views/agent-dev/chat-view.tsx | 10 ++++----
web/ui/src/views/agent-dev/debug-modal.tsx | 2 +-
web/ui/src/views/agent-dev/dev-view.tsx | 2 +-
.../src/views/agent-flow/agent-flow-view.tsx | 23 ++++---------------
web/ui/src/views/agent-flow/flow-dev-view.tsx | 2 +-
web/ui/src/views/agents/modal/create.tsx | 4 ++--
web/ui/src/views/agents/view.tsx | 4 ++--
.../chat/components/message/ai-message.tsx | 9 ++++----
.../chat/components/message/exchange.tsx | 2 +-
.../chat/components/message/human-message.tsx | 5 ++--
.../views/chat/components/message/message.tsx | 10 ++++----
.../chat/components/message/peer-message.tsx | 11 +++++----
web/ui/src/views/chat/view.tsx | 21 ++++++++---------
web/ui/src/views/knowledge/module.ts | 2 +-
web/ui/src/views/knowledge/view.tsx | 10 ++++----
.../sessions/conversation-list/index.tsx | 5 ++--
web/ui/src/views/sessions/view.tsx | 7 +++---
web/ui/src/views/tools/module.ts | 2 +-
web/ui/src/views/tools/view.tsx | 4 ++--
55 files changed, 137 insertions(+), 166 deletions(-)
delete mode 100644 web/ui/src/modules/agent/index.ts
delete mode 100644 web/ui/src/modules/axios-client/index.ts
delete mode 100644 web/ui/src/modules/base-layout/index.ts
delete mode 100644 web/ui/src/modules/chat-message/index.ts
delete mode 100644 web/ui/src/modules/knowledge/index.ts
delete mode 100644 web/ui/src/modules/session/index.ts
delete mode 100644 web/ui/src/modules/tool/index.ts
diff --git a/web/ui/src/modules/agent/agent-config-manager.ts b/web/ui/src/modules/agent/agent-config-manager.ts
index 40f4352..d4c2ca9 100644
--- a/web/ui/src/modules/agent/agent-config-manager.ts
+++ b/web/ui/src/modules/agent/agent-config-manager.ts
@@ -1,12 +1,11 @@
import { inject, singleton } from '@difizen/mana-app';
-import { AxiosClient } from '../axios-client/index.js';
+import { AxiosClient } from '../axios-client/protocol.js';
+import { DefaultAgentConfigOptions } from './agent-config.js';
import type { AgentConfig, AgentConfigOption } from './protocol.js';
import { AgentConfigFactory } from './protocol.js';
-import { DefaultAgentConfigOptions } from './index.js';
-
@singleton()
export class AgentConfigManager {
@inject(AgentConfigFactory) configFactory: AgentConfigFactory;
diff --git a/web/ui/src/modules/agent/agent-config.ts b/web/ui/src/modules/agent/agent-config.ts
index 962c444..d1fd4f8 100644
--- a/web/ui/src/modules/agent/agent-config.ts
+++ b/web/ui/src/modules/agent/agent-config.ts
@@ -1,8 +1,10 @@
import { inject, prop, transient } from '@difizen/mana-app';
-import { AxiosClient } from '../axios-client/index.js';
+import { AxiosClient } from '../axios-client/protocol.js';
+import { ToolManager } from '../tool/tool-manager.js';
+import type { ToolModel } from '../tool/tool-model.js';
-import type { LLMMeta, PlannerMeta, PromptMeta, ToolMeta } from './protocol.js';
+import type { LLMMeta, PlannerMeta, PromptMeta } from './protocol.js';
import { AgentConfigOption } from './protocol.js';
export const DefaultAgentConfigOptions: AgentConfigOption = {
@@ -12,6 +14,7 @@ export const DefaultAgentConfigOptions: AgentConfigOption = {
@transient()
export class AgentConfig {
protected axios: AxiosClient;
+ protected toolManager: ToolManager;
isDraft = true;
@prop()
@@ -23,16 +26,18 @@ export class AgentConfig {
planner: PlannerMeta;
@prop()
- tool: ToolMeta[];
+ tool: ToolModel[];
option: AgentConfigOption;
constructor(
@inject(AgentConfigOption) option: AgentConfigOption,
@inject(AxiosClient) axios: AxiosClient,
+ @inject(ToolManager) toolManager: ToolManager,
) {
this.option = option;
this.axios = axios;
+ this.toolManager = toolManager;
this.fromMeta(option);
}
@@ -45,6 +50,6 @@ export class AgentConfig {
id: '',
nickname: 'string',
};
- this.tool = option.tool ?? [];
+ this.tool = option.tool?.map((item) => this.toolManager.getOrCreate(item)) ?? [];
}
}
diff --git a/web/ui/src/modules/agent/agent-icon.tsx b/web/ui/src/modules/agent/agent-icon.tsx
index 1b4ed16..c648754 100644
--- a/web/ui/src/modules/agent/agent-icon.tsx
+++ b/web/ui/src/modules/agent/agent-icon.tsx
@@ -1,7 +1,8 @@
import type { AvatarProps } from 'antd';
import { Avatar } from 'antd';
-import { toResourceUrl } from '../../common/page-config.js';
+import { toResourceUrl } from '@/common/page-config.js';
+
import { MagentLOGO } from '../base-layout/brand/logo.js';
interface IProps extends AvatarProps {
diff --git a/web/ui/src/modules/agent/agent-manager.ts b/web/ui/src/modules/agent/agent-manager.ts
index b149c95..b96fa3f 100644
--- a/web/ui/src/modules/agent/agent-manager.ts
+++ b/web/ui/src/modules/agent/agent-manager.ts
@@ -1,6 +1,6 @@
import { inject, singleton } from '@difizen/mana-app';
-import { AxiosClient } from '../axios-client/index.js';
+import { AxiosClient } from '../axios-client/protocol.js';
import { AgentModelFactory } from './protocol.js';
import type { AgentModel, AgentModelOption } from './protocol.js';
@@ -11,7 +11,7 @@ export class AgentManager {
@inject(AgentModelFactory) botFactory: AgentModelFactory;
@inject(AxiosClient) axios: AxiosClient;
- getAgents = async (): Promise => {
+ getAll = async (): Promise => {
const defaultValue: AgentModelOption[] = [];
const res = await this.axios.get(`/api/v1/agents`);
if (res.status === 200) {
@@ -20,7 +20,7 @@ export class AgentManager {
return defaultValue;
};
- getOrCreateAgent = (option: AgentModelOption): AgentModel => {
+ getOrCreate = (option: AgentModelOption): AgentModel => {
const exist = this.cache.get(option.id);
if (exist) {
return exist;
diff --git a/web/ui/src/modules/agent/agent-market.ts b/web/ui/src/modules/agent/agent-market.ts
index 8191050..f8431f8 100644
--- a/web/ui/src/modules/agent/agent-market.ts
+++ b/web/ui/src/modules/agent/agent-market.ts
@@ -15,8 +15,8 @@ export class AgentMarket {
async update() {
this.loading = true;
- const options = await this.agentManager.getAgents();
- this.list = options.map(this.agentManager.getOrCreateAgent);
+ const options = await this.agentManager.getAll();
+ this.list = options.map(this.agentManager.getOrCreate);
this.loading = false;
}
}
diff --git a/web/ui/src/modules/agent/agent-model.ts b/web/ui/src/modules/agent/agent-model.ts
index 20215f8..c537555 100644
--- a/web/ui/src/modules/agent/agent-model.ts
+++ b/web/ui/src/modules/agent/agent-model.ts
@@ -1,15 +1,16 @@
import { inject, prop, transient } from '@difizen/mana-app';
-import { AsyncModel } from '../../common/async-model.js';
-import { AxiosClient } from '../axios-client/index.js';
+import { AsyncModel } from '@/common/async-model.js';
+
+import { AxiosClient } from '../axios-client/protocol.js';
import type { KnowledgeModelOption } from '../knowledge/protocol.js';
import { LLMManager } from '../model/llm-manager.js';
import type { LLMModel } from '../model/llm-model.js';
-import type { ToolModelOption } from '../tool/index.js';
-import { ToolManager } from '../tool/index.js';
+import type { ToolModelOption } from '../tool/protocol.js';
+import { ToolManager } from '../tool/tool-manager.js';
import { AgentConfigManager } from './agent-config-manager.js';
-import type { LLMMeta, PromptMeta, PlannerMeta } from './protocol.js';
+import type { PromptMeta, PlannerMeta } from './protocol.js';
import { AgentModelType, AgentModelOption } from './protocol.js';
class Prompt implements PromptMeta {
diff --git a/web/ui/src/modules/agent/index.ts b/web/ui/src/modules/agent/index.ts
deleted file mode 100644
index 45a1026..0000000
--- a/web/ui/src/modules/agent/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export * from './module.js';
-export * from './agent-manager.js';
-export * from './agent-model.js';
-export * from './agent-config-manager.js';
-export * from './agent-config.js';
-export * from './protocol.js';
diff --git a/web/ui/src/modules/agent/module.ts b/web/ui/src/modules/agent/module.ts
index 03395a0..4c2e66a 100644
--- a/web/ui/src/modules/agent/module.ts
+++ b/web/ui/src/modules/agent/module.ts
@@ -1,7 +1,5 @@
import { ManaModule } from '@difizen/mana-app';
-import { ToolManager, ToolModel } from '../tool/index.js';
-
import { AgentConfigManager } from './agent-config-manager.js';
import { AgentConfig } from './agent-config.js';
import { AgentManager } from './agent-manager.js';
diff --git a/web/ui/src/modules/app.module.ts b/web/ui/src/modules/app.module.ts
index 61bcbeb..38e1ade 100644
--- a/web/ui/src/modules/app.module.ts
+++ b/web/ui/src/modules/app.module.ts
@@ -1,21 +1,21 @@
import { ManaModule } from '@difizen/mana-app';
-import { AgentConfigViewModule } from '../views/agent-config/index.js';
-import { AgentChatModule } from '../views/agent-dev/index.js';
+import { AgentConfigViewModule } from '../views/agent-config/module.js';
+import { AgentChatModule } from '../views/agent-dev/module.js';
import { AgentFlowModule } from '../views/agent-flow/module.js';
-import { AgentsPageModule } from '../views/agents/index.js';
+import { AgentsPageModule } from '../views/agents/module.js';
import { ChatViewModule } from '../views/chat/module.js';
import { KnowledgePageModule } from '../views/knowledge/module.js';
-import { PortalsModule } from '../views/protal-layout/index.js';
+import { PortalsModule } from '../views/protal-layout/module.js';
import { SessionsViewModule } from '../views/sessions/module.js';
import { ToolPageModule } from '../views/tools/module.js';
import { AgentBotModule } from './agent/module.js';
import { AxiosClientModule } from './axios-client/module.js';
import { BaseLayoutModule } from './base-layout/module.js';
-import { ChatMessageModule } from './chat-message/index.js';
+import { ChatMessageModule } from './chat-message/module.js';
import { ModelModule } from './model/module.js';
-import { SessionModule } from './session/index.js';
+import { SessionModule } from './session/module.js';
import { ToolModule } from './tool/module.js';
export const AppBaseModule = new ManaModule()
diff --git a/web/ui/src/modules/axios-client/client.ts b/web/ui/src/modules/axios-client/client.ts
index ca1c2b6..76e23cf 100644
--- a/web/ui/src/modules/axios-client/client.ts
+++ b/web/ui/src/modules/axios-client/client.ts
@@ -4,7 +4,7 @@ import type { Syringe } from '@difizen/mana-app';
import axios from 'axios';
import qs from 'query-string';
-import { getPageConfig } from '../../common/page-config.js';
+import { getPageConfig } from '@/common/page-config.js';
export const getContextClient = (ctx: Syringe.Context) => {
const pageConfig = getPageConfig();
diff --git a/web/ui/src/modules/axios-client/index.ts b/web/ui/src/modules/axios-client/index.ts
deleted file mode 100644
index e9d8cbd..0000000
--- a/web/ui/src/modules/axios-client/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './module.js';
-export * from './protocol.js';
diff --git a/web/ui/src/modules/base-layout/index.ts b/web/ui/src/modules/base-layout/index.ts
deleted file mode 100644
index 28364cf..0000000
--- a/web/ui/src/modules/base-layout/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './layout.js';
diff --git a/web/ui/src/modules/chat-message/ai-message-item.ts b/web/ui/src/modules/chat-message/ai-message-item.ts
index 1cba30c..fba99a6 100644
--- a/web/ui/src/modules/chat-message/ai-message-item.ts
+++ b/web/ui/src/modules/chat-message/ai-message-item.ts
@@ -46,7 +46,7 @@ export class AIChatMessageItem extends ChatMessageItem {
};
protected getAgent = async () => {
- const agent = await this.agentManager.getOrCreateAgent({ id: this.option.agentId });
+ const agent = await this.agentManager.getOrCreate({ id: this.option.agentId });
this.agent = agent;
this.agent.fetchInfo();
this.agentDeferred.resolve(agent);
diff --git a/web/ui/src/modules/chat-message/chat-message-item.ts b/web/ui/src/modules/chat-message/chat-message-item.ts
index cce58e3..7065626 100644
--- a/web/ui/src/modules/chat-message/chat-message-item.ts
+++ b/web/ui/src/modules/chat-message/chat-message-item.ts
@@ -2,7 +2,7 @@ import { inject, prop, transient } from '@difizen/mana-app';
import type { Dayjs } from 'dayjs';
import dayjs from 'dayjs';
-import { AxiosClient } from '../axios-client/index.js';
+import { AxiosClient } from '../axios-client/protocol.js';
import { ChatMessageItemOption } from './protocol.js';
import type { QuestionState, MessageSender, AnswerState } from './protocol.js';
diff --git a/web/ui/src/modules/chat-message/chat-message-manager.ts b/web/ui/src/modules/chat-message/chat-message-manager.ts
index 31272e6..172497e 100644
--- a/web/ui/src/modules/chat-message/chat-message-manager.ts
+++ b/web/ui/src/modules/chat-message/chat-message-manager.ts
@@ -1,6 +1,6 @@
import { inject, singleton } from '@difizen/mana-app';
-import { AxiosClient } from '../axios-client/index.js';
+import { AxiosClient } from '../axios-client/protocol.js';
import type { ChatMessageModel, ChatMessageOption } from './protocol.js';
import { ChatMessageFactory } from './protocol.js';
diff --git a/web/ui/src/modules/chat-message/chat-message-model.ts b/web/ui/src/modules/chat-message/chat-message-model.ts
index cb07450..0cb1ae0 100644
--- a/web/ui/src/modules/chat-message/chat-message-model.ts
+++ b/web/ui/src/modules/chat-message/chat-message-model.ts
@@ -8,7 +8,7 @@ import type { ParsedEvent } from 'eventsource-parser/stream';
import { AgentManager } from '../agent/agent-manager.js';
import type { AgentModel } from '../agent/agent-model.js';
-import { AxiosClient } from '../axios-client/index.js';
+import { AxiosClient } from '../axios-client/protocol.js';
import { AIChatMessageItem } from './ai-message-item.js';
import type { ChatMessageItem } from './chat-message-item.js';
@@ -99,7 +99,7 @@ export class ChatMessageModel implements Disposable {
}
protected getAgent = async (id: string) => {
- const agent = await this.agentManager.getOrCreateAgent({ id });
+ const agent = await this.agentManager.getOrCreate({ id });
this.agent = agent;
this.agent.fetchInfo();
this.agentDeferred.resolve(agent);
diff --git a/web/ui/src/modules/chat-message/index.ts b/web/ui/src/modules/chat-message/index.ts
deleted file mode 100644
index 6fc1001..0000000
--- a/web/ui/src/modules/chat-message/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './module.js';
-export * from './chat-message-manager.js';
diff --git a/web/ui/src/modules/knowledge/index.ts b/web/ui/src/modules/knowledge/index.ts
deleted file mode 100644
index 192ae7d..0000000
--- a/web/ui/src/modules/knowledge/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './protocol.js';
-export * from './knowledge-model.js';
-export * from './knowledge-manager.js';
-export * from './module.js';
diff --git a/web/ui/src/modules/knowledge/knowledge-icon.tsx b/web/ui/src/modules/knowledge/knowledge-icon.tsx
index f435313..f4a918b 100644
--- a/web/ui/src/modules/knowledge/knowledge-icon.tsx
+++ b/web/ui/src/modules/knowledge/knowledge-icon.tsx
@@ -2,7 +2,7 @@ import { BookTwoTone } from '@ant-design/icons';
import type { AvatarProps } from 'antd';
import { Avatar } from 'antd';
-import { toResourceUrl } from '../../common/page-config.js';
+import { toResourceUrl } from '@/common/page-config.js';
interface IProps extends AvatarProps {
data: { avatar?: string; id?: string };
diff --git a/web/ui/src/modules/knowledge/knowledge-manager.ts b/web/ui/src/modules/knowledge/knowledge-manager.ts
index 7424f4f..57b6490 100644
--- a/web/ui/src/modules/knowledge/knowledge-manager.ts
+++ b/web/ui/src/modules/knowledge/knowledge-manager.ts
@@ -1,6 +1,6 @@
import { inject, prop, singleton } from '@difizen/mana-app';
-import { AxiosClient } from '../axios-client/index.js';
+import { AxiosClient } from '../axios-client/protocol.js';
import {
KnowledgeModelFactory,
@@ -17,7 +17,7 @@ export class KnowledgeManager {
@prop()
knowledgeOptions: KnowledgeModelOption[] = [];
- getKnowledge = async (): Promise => {
+ getAll = async (): Promise => {
const defaultValue: KnowledgeModelOption[] = [];
const res = await this.axios.get(`/api/v1/knowledge`);
if (res.status === 200) {
@@ -26,7 +26,7 @@ export class KnowledgeManager {
return defaultValue;
};
- getOrCreateKnowledge = (option: KnowledgeModelOption): KnowledgeModel => {
+ getOrCreate = (option: KnowledgeModelOption): KnowledgeModel => {
const exist = this.cache.get(option.id);
if (exist) {
return exist;
diff --git a/web/ui/src/modules/knowledge/knowledge-model.ts b/web/ui/src/modules/knowledge/knowledge-model.ts
index 5261f83..193bef3 100644
--- a/web/ui/src/modules/knowledge/knowledge-model.ts
+++ b/web/ui/src/modules/knowledge/knowledge-model.ts
@@ -1,7 +1,7 @@
import { inject, prop, transient } from '@difizen/mana-app';
-import { AsyncModel } from '../../common/async-model.js';
-import { AxiosClient } from '../axios-client/index.js';
+import { AsyncModel } from '@/common/async-model.js';
+import { AxiosClient } from '../axios-client/protocol.js';
import { KnowledgeModelOption } from './protocol.js';
import { KnowledgeModelType } from './protocol.js';
diff --git a/web/ui/src/modules/knowledge/knowledge-space.ts b/web/ui/src/modules/knowledge/knowledge-space.ts
index 8889fc2..e2bcf6d 100644
--- a/web/ui/src/modules/knowledge/knowledge-space.ts
+++ b/web/ui/src/modules/knowledge/knowledge-space.ts
@@ -15,8 +15,8 @@ export class KnowledgeSpace {
async update() {
this.loading = true;
- const options = await this.manager.getKnowledge();
- this.list = options.map(this.manager.getOrCreateKnowledge);
+ const options = await this.manager.getAll();
+ this.list = options.map(this.manager.getOrCreate);
this.loading = false;
}
}
diff --git a/web/ui/src/modules/session/index.ts b/web/ui/src/modules/session/index.ts
deleted file mode 100644
index fcd81e3..0000000
--- a/web/ui/src/modules/session/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './module.js';
-export * from './session-manager.js';
-export * from './protocol.js';
diff --git a/web/ui/src/modules/session/session-manager.ts b/web/ui/src/modules/session/session-manager.ts
index 92b2a6b..eccd974 100644
--- a/web/ui/src/modules/session/session-manager.ts
+++ b/web/ui/src/modules/session/session-manager.ts
@@ -1,7 +1,7 @@
import { inject, singleton } from '@difizen/mana-app';
import qs from 'query-string';
-import { AxiosClient } from '../axios-client/index.js';
+import { AxiosClient } from '../axios-client/protocol.js';
import type {
APISession,
diff --git a/web/ui/src/modules/session/session-model.ts b/web/ui/src/modules/session/session-model.ts
index 274b98d..d6f5248 100644
--- a/web/ui/src/modules/session/session-model.ts
+++ b/web/ui/src/modules/session/session-model.ts
@@ -5,8 +5,8 @@ import { Emitter } from '@difizen/mana-app';
import { inject, prop, transient } from '@difizen/mana-app';
import dayjs from 'dayjs';
-import { AsyncModel } from '../../common/async-model.js';
-import { AxiosClient } from '../axios-client/index.js';
+import { AsyncModel } from '@/common/async-model.js';
+import { AxiosClient } from '../axios-client/protocol.js';
import type { ChatMessageItem } from '../chat-message/chat-message-item.js';
import { ChatMessageManager } from '../chat-message/chat-message-manager.js';
import type { ChatMessageModel, MessageCreate } from '../chat-message/protocol.js';
diff --git a/web/ui/src/modules/tool/index.ts b/web/ui/src/modules/tool/index.ts
deleted file mode 100644
index a196109..0000000
--- a/web/ui/src/modules/tool/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export * from './protocol.js';
-export * from './tool-model.js';
-export * from './tool-manager.js';
-export * from './tool-config.js';
-export * from './tool-config-manager.js';
-export * from './module.js';
diff --git a/web/ui/src/modules/tool/tool-config-manager.ts b/web/ui/src/modules/tool/tool-config-manager.ts
index 4880e33..af36bb8 100644
--- a/web/ui/src/modules/tool/tool-config-manager.ts
+++ b/web/ui/src/modules/tool/tool-config-manager.ts
@@ -1,6 +1,6 @@
import { inject, singleton } from '@difizen/mana-app';
-import { AxiosClient } from '../axios-client/index.js';
+import { AxiosClient } from '../axios-client/protocol.js';
import { ToolConfigFactory, type ToolConfigOption } from './protocol.js';
import type { ToolConfig } from './tool-config.js';
diff --git a/web/ui/src/modules/tool/tool-config.ts b/web/ui/src/modules/tool/tool-config.ts
index ab00c60..55fc2bc 100644
--- a/web/ui/src/modules/tool/tool-config.ts
+++ b/web/ui/src/modules/tool/tool-config.ts
@@ -1,8 +1,8 @@
import { Emitter, inject, prop, transient } from '@difizen/mana-app';
import debounce from 'lodash.debounce';
-import { AsyncModel } from '../../common/async-model.js';
-import { AxiosClient } from '../axios-client/index.js';
+import { AsyncModel } from '@/common/async-model.js';
+import { AxiosClient } from '../axios-client/protocol.js';
import { ToolConfigOption, ToolConfigType } from './protocol.js';
diff --git a/web/ui/src/modules/tool/tool-icon.tsx b/web/ui/src/modules/tool/tool-icon.tsx
index aaa6eb8..bc982b9 100644
--- a/web/ui/src/modules/tool/tool-icon.tsx
+++ b/web/ui/src/modules/tool/tool-icon.tsx
@@ -1,7 +1,7 @@
import type { AvatarProps } from 'antd';
import { Avatar } from 'antd';
-import { toResourceUrl } from '../../common/page-config.js';
+import { toResourceUrl } from '@/common/page-config.js';
interface IProps extends AvatarProps {
data: { avatar?: string; id?: string };
diff --git a/web/ui/src/modules/tool/tool-manager.ts b/web/ui/src/modules/tool/tool-manager.ts
index 7c157bb..5129748 100644
--- a/web/ui/src/modules/tool/tool-manager.ts
+++ b/web/ui/src/modules/tool/tool-manager.ts
@@ -1,6 +1,6 @@
import { inject, singleton } from '@difizen/mana-app';
-import { AxiosClient } from '../axios-client/index.js';
+import { AxiosClient } from '../axios-client/protocol.js';
import { ToolFactory, type ToolModel, type ToolModelOption } from './protocol.js';
@@ -10,7 +10,7 @@ export class ToolManager {
@inject(ToolFactory) toolFactory: ToolFactory;
@inject(AxiosClient) axios: AxiosClient;
- getTools = async (): Promise => {
+ getAll = async (): Promise => {
const defaultValue: ToolModelOption[] = [];
const res = await this.axios.get(`/api/v1/tools`);
if (res.status === 200) {
@@ -19,7 +19,7 @@ export class ToolManager {
return defaultValue;
};
- getOrCreateTool = (option: ToolModelOption): ToolModel => {
+ getOrCreate = (option: ToolModelOption): ToolModel => {
const exist = this.cache.get(option.id);
if (exist) {
return exist;
diff --git a/web/ui/src/modules/tool/tool-model.ts b/web/ui/src/modules/tool/tool-model.ts
index 6d75e37..d668636 100644
--- a/web/ui/src/modules/tool/tool-model.ts
+++ b/web/ui/src/modules/tool/tool-model.ts
@@ -1,7 +1,7 @@
import { Deferred, inject, prop, transient } from '@difizen/mana-app';
-import { AsyncModel } from '../../common/async-model.js';
-import { AxiosClient } from '../axios-client/index.js';
+import { AsyncModel } from '@/common/async-model.js';
+import { AxiosClient } from '../axios-client/protocol.js';
import { ToolModelOption, ToolModelType } from './protocol.js';
import { ToolConfigManager } from './tool-config-manager.js';
diff --git a/web/ui/src/modules/tool/tool-space.ts b/web/ui/src/modules/tool/tool-space.ts
index a823c15..43717fa 100644
--- a/web/ui/src/modules/tool/tool-space.ts
+++ b/web/ui/src/modules/tool/tool-space.ts
@@ -15,8 +15,8 @@ export class ToolSpace {
async update() {
this.loading = true;
- const options = await this.toolManager.getTools();
- this.list = options.map(this.toolManager.getOrCreateTool);
+ const options = await this.toolManager.getAll();
+ this.list = options.map(this.toolManager.getOrCreate);
this.loading = false;
}
}
diff --git a/web/ui/src/views/agent-config/components/model-selector/index.tsx b/web/ui/src/views/agent-config/components/model-selector/index.tsx
index 0a145d0..6869f86 100644
--- a/web/ui/src/views/agent-config/components/model-selector/index.tsx
+++ b/web/ui/src/views/agent-config/components/model-selector/index.tsx
@@ -5,11 +5,11 @@ import { Button, Form, Select, Popover, Avatar, Slider } from 'antd';
import type { FC } from 'react';
import { forwardRef, useEffect } from 'react';
+import { LLMManager } from '@/modules/model/llm-manager.js';
import type { LLMModel } from '@/modules/model/llm-model.js';
import { LLMIcon } from '@/modules/model/model-icon/index.js';
+import type { ModelMeta } from '@/modules/model/protocol.js';
-import { LLMManager } from '../../../../modules/model/llm-manager.js';
-import type { ModelMeta } from '../../../../modules/model/protocol.js';
import type { AgentConfigView } from '../../view.js';
import './index.less';
diff --git a/web/ui/src/views/agent-config/knowledge-modal/modal.tsx b/web/ui/src/views/agent-config/knowledge-modal/modal.tsx
index 7177355..f741115 100644
--- a/web/ui/src/views/agent-config/knowledge-modal/modal.tsx
+++ b/web/ui/src/views/agent-config/knowledge-modal/modal.tsx
@@ -5,10 +5,10 @@ import { Modal, Table } from 'antd';
import type { TableRowSelection } from 'antd/es/table/interface.js';
import { useMemo } from 'react';
-import type { AgentModel } from '../../../modules/agent/protocol.js';
-import { KnowledgeIcon } from '../../../modules/knowledge/knowledge-icon.js';
-import { KnowledgeSpace } from '../../../modules/knowledge/knowledge-space.js';
-import type { KnowledgeModelOption } from '../../../modules/knowledge/protocol.js';
+import type { AgentModel } from '@/modules/agent/protocol.js';
+import { KnowledgeIcon } from '@/modules/knowledge/knowledge-icon.js';
+import { KnowledgeSpace } from '@/modules/knowledge/knowledge-space.js';
+import type { KnowledgeModelOption } from '@/modules/knowledge/protocol.js';
import { KnowledgeModalId } from '../protocol.js';
export const KnowledgeModalComponent = (
diff --git a/web/ui/src/views/agent-config/tools-modal/modal.tsx b/web/ui/src/views/agent-config/tools-modal/modal.tsx
index 6585dbd..89a6cb5 100644
--- a/web/ui/src/views/agent-config/tools-modal/modal.tsx
+++ b/web/ui/src/views/agent-config/tools-modal/modal.tsx
@@ -5,10 +5,10 @@ import { Modal, Table } from 'antd';
import type { TableRowSelection } from 'antd/es/table/interface.js';
import { useMemo } from 'react';
-import type { AgentModel } from '../../../modules/agent/protocol.js';
-import type { ToolModelOption } from '../../../modules/tool/protocol.js';
-import { ToolIcon } from '../../../modules/tool/tool-icon.js';
-import { ToolSpace } from '../../../modules/tool/tool-space.js';
+import type { AgentModel } from '@/modules/agent/protocol.js';
+import type { ToolModelOption } from '@/modules/tool/protocol.js';
+import { ToolIcon } from '@/modules/tool/tool-icon.js';
+import { ToolSpace } from '@/modules/tool/tool-space.js';
import { ToolsModalId } from '../protocol.js';
export const ToolsModalComponent = (props: ModalItemProps<{ agent: AgentModel }>) => {
diff --git a/web/ui/src/views/agent-config/view.tsx b/web/ui/src/views/agent-config/view.tsx
index 35f0e1e..eab0f4f 100644
--- a/web/ui/src/views/agent-config/view.tsx
+++ b/web/ui/src/views/agent-config/view.tsx
@@ -13,10 +13,10 @@ import {
import { Flex } from 'antd';
import { forwardRef } from 'react';
-import { AgentManager } from '../../modules/agent/index.js';
-import type { AgentModel } from '../../modules/agent/index.js';
-import { KnowledgeIcon } from '../../modules/knowledge/knowledge-icon.js';
-import { ToolIcon } from '../../modules/tool/tool-icon.js';
+import { AgentManager } from '@/modules/agent/agent-manager.js';
+import type { AgentModel } from '@/modules/agent/protocol.js';
+import { KnowledgeIcon } from '@/modules/knowledge/knowledge-icon.js';
+import { ToolIcon } from '@/modules/tool/tool-icon.js';
import { CharacterSetting } from './components/character-setting/index.js';
import { ConfigList } from './components/config-selector/index.js';
@@ -131,7 +131,7 @@ export class AgentConfigView extends BaseView {
get modelOptions() {
// TODO 大模型optios列表和对应存取值要怎么取?
return (
- this.agent?.llm?.model_name?.map((item) => {
+ this.agent?.llm?.models?.map((item) => {
return {
label: item,
value: item,
@@ -142,7 +142,7 @@ export class AgentConfigView extends BaseView {
protected initAgent = (agentId = this.agentId) => {
if (agentId) {
- const agent = this.agentManager.getOrCreateAgent({ id: agentId });
+ const agent = this.agentManager.getOrCreate({ id: agentId });
agent.fetchInfo();
this.agent = agent;
return agent;
diff --git a/web/ui/src/views/agent-dev/chat-view.tsx b/web/ui/src/views/agent-dev/chat-view.tsx
index db75bc7..fdfc7b1 100644
--- a/web/ui/src/views/agent-dev/chat-view.tsx
+++ b/web/ui/src/views/agent-dev/chat-view.tsx
@@ -13,10 +13,10 @@ import { forwardRef, useEffect } from 'react';
import { useMatch } from 'react-router-dom';
import { history } from 'umi';
-import { AgentManager } from '../../modules/agent/agent-manager.js';
-import type { AgentModel } from '../../modules/agent/protocol.js';
-import { PageView } from '../../modules/base-layout/page-view.js';
-import type { SessionModel } from '../../modules/session/protocol.js';
+import { AgentManager } from '@/modules/agent/agent-manager.js';
+import type { AgentModel } from '@/modules/agent/protocol.js';
+import { PageView } from '@/modules/base-layout/page-view.js';
+import type { SessionModel } from '@/modules/session/protocol.js';
import { ChatView } from '../chat/view.js';
import { SessionsView } from '../sessions/view.js';
@@ -119,7 +119,7 @@ export class AgentView extends PageView {
};
protected initAgent = () => {
if (this.agentId) {
- const agent = this.agentManager.getOrCreateAgent({ id: this.agentId });
+ const agent = this.agentManager.getOrCreate({ id: this.agentId });
agent.fetchInfo();
this.agent = agent;
return agent;
diff --git a/web/ui/src/views/agent-dev/debug-modal.tsx b/web/ui/src/views/agent-dev/debug-modal.tsx
index d1a3066..42cb452 100644
--- a/web/ui/src/views/agent-dev/debug-modal.tsx
+++ b/web/ui/src/views/agent-dev/debug-modal.tsx
@@ -8,8 +8,8 @@ import { Col, Drawer, Row, Select, Tree } from 'antd';
import { useState } from 'react';
import { DefaultLLMIcon } from '@/modules/model/model-icon/index.js';
+import { DefaultToolIcon } from '@/modules/tool/tool-icon.js';
-import { DefaultToolIcon } from '../../modules/tool/tool-icon.js';
import { HumanIcon } from '../chat/components/message/human-message.js';
import type { ChatView } from '../chat/view.js';
diff --git a/web/ui/src/views/agent-dev/dev-view.tsx b/web/ui/src/views/agent-dev/dev-view.tsx
index eea260b..56c569f 100644
--- a/web/ui/src/views/agent-dev/dev-view.tsx
+++ b/web/ui/src/views/agent-dev/dev-view.tsx
@@ -5,7 +5,7 @@ import { Button } from 'antd';
import { forwardRef, useEffect } from 'react';
import { useMatch } from 'react-router-dom';
-import type { AgentConfigManager } from '../../modules/agent/agent-config-manager.js';
+import type { AgentConfigManager } from '@/modules/agent/agent-config-manager.js';
import { AgentConfigView } from '../agent-config/view.js';
import { AgentView } from './chat-view.js';
diff --git a/web/ui/src/views/agent-flow/agent-flow-view.tsx b/web/ui/src/views/agent-flow/agent-flow-view.tsx
index d0f82f6..ea735c3 100644
--- a/web/ui/src/views/agent-flow/agent-flow-view.tsx
+++ b/web/ui/src/views/agent-flow/agent-flow-view.tsx
@@ -1,20 +1,9 @@
-import { SaveOutlined } from '@ant-design/icons';
import { FlowWithPanel } from '@difizen/magent-flow';
-import {
- BaseView,
- ViewInstance,
- inject,
- prop,
- useInject,
- view,
- ViewOption,
- transient,
-} from '@difizen/mana-app';
-import { Flex } from 'antd';
+import { BaseView, inject, prop, view, ViewOption, transient } from '@difizen/mana-app';
import { forwardRef } from 'react';
-import { AgentManager } from '../../modules/agent/index.js';
-import type { AgentModel } from '../../modules/agent/index.js';
+import { AgentManager } from '@/modules/agent/agent-manager.js';
+import type { AgentModel } from '@/modules/agent/protocol.js';
import './index.less';
@@ -22,8 +11,6 @@ const viewId = 'magent-agent-flow';
const AgentFlowComponent = forwardRef(
function AgentConfigViewComponent(props, ref) {
- const instance = useInject(ViewInstance);
-
return (
@@ -56,7 +43,7 @@ export class AgentFlowView extends BaseView {
get modelOptions() {
// TODO 大模型optios列表和对应存取值要怎么取?
return (
- this.agent?.llm?.model_name?.map((item) => {
+ this.agent?.llm?.models?.map((item) => {
return {
label: item,
value: item,
@@ -67,7 +54,7 @@ export class AgentFlowView extends BaseView {
protected initAgent = (agentId = this.agentId) => {
if (agentId) {
- const agent = this.agentManager.getOrCreateAgent({ id: agentId });
+ const agent = this.agentManager.getOrCreate({ id: agentId });
agent.fetchInfo();
this.agent = agent;
return agent;
diff --git a/web/ui/src/views/agent-flow/flow-dev-view.tsx b/web/ui/src/views/agent-flow/flow-dev-view.tsx
index a892ac4..1c78e92 100644
--- a/web/ui/src/views/agent-flow/flow-dev-view.tsx
+++ b/web/ui/src/views/agent-flow/flow-dev-view.tsx
@@ -4,7 +4,7 @@ import { BoxPanel } from '@difizen/mana-react';
import { forwardRef, useEffect } from 'react';
import { useMatch } from 'react-router-dom';
-import type { AgentConfigManager } from '../../modules/agent/agent-config-manager.js';
+import type { AgentConfigManager } from '@/modules/agent/agent-config-manager.js';
import { AgentView } from '../agent-dev/chat-view.js';
import { AgentFlowView } from './agent-flow-view.js';
diff --git a/web/ui/src/views/agents/modal/create.tsx b/web/ui/src/views/agents/modal/create.tsx
index 5a2ab05..f287d60 100644
--- a/web/ui/src/views/agents/modal/create.tsx
+++ b/web/ui/src/views/agents/modal/create.tsx
@@ -7,8 +7,8 @@ import { Modal } from 'antd';
import type { PropsWithChildren } from 'react';
import { useEffect, useState } from 'react';
-import { AvatarUpload } from '../../../components/avatar-upload/index.js';
-import { AgentIcon } from '../../../modules/agent/agent-icon.js';
+import { AvatarUpload } from '@/components/avatar-upload/index.js';
+import { AgentIcon } from '@/modules/agent/agent-icon.js';
import './index.less';
diff --git a/web/ui/src/views/agents/view.tsx b/web/ui/src/views/agents/view.tsx
index e79ce0a..29f6758 100644
--- a/web/ui/src/views/agents/view.tsx
+++ b/web/ui/src/views/agents/view.tsx
@@ -14,8 +14,8 @@ import { forwardRef } from 'react';
import { history } from 'umi';
import './index.less';
-import { AgentIcon } from '../../modules/agent/agent-icon.js';
-import { AgentMarket } from '../../modules/agent/agent-market.js';
+import { AgentIcon } from '@/modules/agent/agent-icon.js';
+import { AgentMarket } from '@/modules/agent/agent-market.js';
import { AgentCreateModal } from './modal/create.js';
diff --git a/web/ui/src/views/chat/components/message/ai-message.tsx b/web/ui/src/views/chat/components/message/ai-message.tsx
index 6a64f2d..6052263 100644
--- a/web/ui/src/views/chat/components/message/ai-message.tsx
+++ b/web/ui/src/views/chat/components/message/ai-message.tsx
@@ -9,10 +9,11 @@ import classNames from 'classnames';
import copy from 'copy-to-clipboard';
import type { ReactNode } from 'react';
-import { AgentIcon } from '../../../../modules/agent/agent-icon.js';
-import type { AIChatMessageItem } from '../../../../modules/chat-message/ai-message-item.js';
-import type { ChatMessageModel } from '../../../../modules/chat-message/chat-message-model.js';
-import { AnswerState } from '../../../../modules/chat-message/protocol.js';
+import { AgentIcon } from '@/modules/agent/agent-icon.js';
+import type { AIChatMessageItem } from '@/modules/chat-message/ai-message-item.js';
+import type { ChatMessageModel } from '@/modules/chat-message/chat-message-model.js';
+import { AnswerState } from '@/modules/chat-message/protocol.js';
+
import type { ChatView } from '../../view.js';
import { Markdown } from './markdown/index.js';
diff --git a/web/ui/src/views/chat/components/message/exchange.tsx b/web/ui/src/views/chat/components/message/exchange.tsx
index 594fa6f..1f739fc 100644
--- a/web/ui/src/views/chat/components/message/exchange.tsx
+++ b/web/ui/src/views/chat/components/message/exchange.tsx
@@ -1,4 +1,4 @@
-import type { ChatMessageModel } from '../../../../modules/chat-message/chat-message-model.js';
+import type { ChatMessageModel } from '@/modules/chat-message/chat-message-model.js';
import { Message } from './message.js';
diff --git a/web/ui/src/views/chat/components/message/human-message.tsx b/web/ui/src/views/chat/components/message/human-message.tsx
index c50ba96..9112d6f 100644
--- a/web/ui/src/views/chat/components/message/human-message.tsx
+++ b/web/ui/src/views/chat/components/message/human-message.tsx
@@ -4,8 +4,9 @@ import { Avatar, Space } from 'antd';
import classNames from 'classnames';
import type { ReactNode } from 'react';
-import type { HumanChatMessageItem } from '../../../../modules/chat-message/chat-message-item.js';
-import type { ChatMessageModel } from '../../../../modules/chat-message/chat-message-model.js';
+import type { HumanChatMessageItem } from '@/modules/chat-message/chat-message-item.js';
+import type { ChatMessageModel } from '@/modules/chat-message/chat-message-model.js';
+
import type { ChatView } from '../../view.js';
import { TextMessage } from './text/index.js';
diff --git a/web/ui/src/views/chat/components/message/message.tsx b/web/ui/src/views/chat/components/message/message.tsx
index 018cdd0..a87fe77 100644
--- a/web/ui/src/views/chat/components/message/message.tsx
+++ b/web/ui/src/views/chat/components/message/message.tsx
@@ -1,10 +1,10 @@
import { useObserve } from '@difizen/mana-app';
-import { AIChatMessageItem } from '../../../../modules/chat-message/ai-message-item.js';
-import type { ChatMessageItem } from '../../../../modules/chat-message/chat-message-item.js';
-import { HumanChatMessageItem } from '../../../../modules/chat-message/chat-message-item.js';
-import type { ChatMessageModel } from '../../../../modules/chat-message/chat-message-model.js';
-import { PeerChatMessageItem } from '../../../../modules/chat-message/peer-message-item-model.js';
+import { AIChatMessageItem } from '@/modules/chat-message/ai-message-item.js';
+import type { ChatMessageItem } from '@/modules/chat-message/chat-message-item.js';
+import { HumanChatMessageItem } from '@/modules/chat-message/chat-message-item.js';
+import type { ChatMessageModel } from '@/modules/chat-message/chat-message-model.js';
+import { PeerChatMessageItem } from '@/modules/chat-message/peer-message-item-model.js';
import { AIMessage } from './ai-message.js';
import { HumanMessage } from './human-message.js';
diff --git a/web/ui/src/views/chat/components/message/peer-message.tsx b/web/ui/src/views/chat/components/message/peer-message.tsx
index 0579a20..6911553 100644
--- a/web/ui/src/views/chat/components/message/peer-message.tsx
+++ b/web/ui/src/views/chat/components/message/peer-message.tsx
@@ -10,11 +10,12 @@ import classNames from 'classnames';
import copy from 'copy-to-clipboard';
import type { ReactNode } from 'react';
-import { AgentIcon } from '../../../../modules/agent/agent-icon.js';
-import type { ChatMessageModel } from '../../../../modules/chat-message/chat-message-model.js';
-import type { PeerChatMessageItem } from '../../../../modules/chat-message/peer-message-item-model.js';
-import type { ChatEventStepQA } from '../../../../modules/chat-message/protocol.js';
-import { AnswerState } from '../../../../modules/chat-message/protocol.js';
+import { AgentIcon } from '@/modules/agent/agent-icon.js';
+import type { ChatMessageModel } from '@/modules/chat-message/chat-message-model.js';
+import type { PeerChatMessageItem } from '@/modules/chat-message/peer-message-item-model.js';
+import type { ChatEventStepQA } from '@/modules/chat-message/protocol.js';
+import { AnswerState } from '@/modules/chat-message/protocol.js';
+
import type { ChatView } from '../../view.js';
import { Markdown } from './markdown/index.js';
diff --git a/web/ui/src/views/chat/view.tsx b/web/ui/src/views/chat/view.tsx
index fdbbf95..7f2df96 100644
--- a/web/ui/src/views/chat/view.tsx
+++ b/web/ui/src/views/chat/view.tsx
@@ -11,21 +11,20 @@ import {
ViewOption,
} from '@difizen/mana-app';
import { useInject } from '@difizen/mana-app';
-import { Avatar, FloatButton } from 'antd';
+import { FloatButton } from 'antd';
import classnames from 'classnames';
import classNames from 'classnames';
import type { RefObject } from 'react';
import { useEffect, useRef } from 'react';
-import { AgentIcon } from '../../modules/agent/agent-icon.js';
-import { AgentManager } from '../../modules/agent/agent-manager.js';
-import type { AgentModel } from '../../modules/agent/protocol.js';
-import { AxiosClient } from '../../modules/axios-client/index.js';
-import { MagentLOGO } from '../../modules/base-layout/brand/logo.js';
-import { ChatMessageManager } from '../../modules/chat-message/chat-message-manager.js';
-import type { MessageCreate } from '../../modules/chat-message/protocol.js';
-import { SessionManager } from '../../modules/session/session-manager.js';
-import type { SessionModel } from '../../modules/session/session-model.js';
+import { AgentIcon } from '@/modules/agent/agent-icon.js';
+import { AgentManager } from '@/modules/agent/agent-manager.js';
+import type { AgentModel } from '@/modules/agent/protocol.js';
+import { AxiosClient } from '@/modules/axios-client/protocol.js';
+import { ChatMessageManager } from '@/modules/chat-message/chat-message-manager.js';
+import type { MessageCreate } from '@/modules/chat-message/protocol.js';
+import { SessionManager } from '@/modules/session/session-manager.js';
+import type { SessionModel } from '@/modules/session/session-model.js';
import { Input } from './components/input/index.js';
import { MessageExchange } from './components/message/exchange.js';
@@ -174,7 +173,7 @@ export class ChatView extends BaseView {
}
protected getAgent = async (id: string) => {
- this.agent = await this.agentManager.getOrCreateAgent({ id });
+ this.agent = await this.agentManager.getOrCreate({ id });
this.agent.fetchInfo();
this.agentDeferred.resolve(this.agent);
};
diff --git a/web/ui/src/views/knowledge/module.ts b/web/ui/src/views/knowledge/module.ts
index 0dc638b..b21e340 100644
--- a/web/ui/src/views/knowledge/module.ts
+++ b/web/ui/src/views/knowledge/module.ts
@@ -1,6 +1,6 @@
import { createViewPreference, ManaModule } from '@difizen/mana-app';
-import { KnowledgeModule } from '../../modules/knowledge/module.js';
+import { KnowledgeModule } from '@/modules/knowledge/module.js';
import { KnowledgeView, slot } from './view.js';
diff --git a/web/ui/src/views/knowledge/view.tsx b/web/ui/src/views/knowledge/view.tsx
index 95c57b2..6eb4586 100644
--- a/web/ui/src/views/knowledge/view.tsx
+++ b/web/ui/src/views/knowledge/view.tsx
@@ -11,12 +11,12 @@ import {
import { Col, List, Row } from 'antd';
import { forwardRef, useState } from 'react';
-import { KnowledgeIcon } from '../../modules/knowledge/knowledge-icon.js';
-import { KnowledgeManager } from '../../modules/knowledge/knowledge-manager.js';
+import { KnowledgeIcon } from '@/modules/knowledge/knowledge-icon.js';
+import { KnowledgeManager } from '@/modules/knowledge/knowledge-manager.js';
import type {
KnowledgeModel,
KnowledgeModelOption,
-} from '../../modules/knowledge/protocol.js';
+} from '@/modules/knowledge/protocol.js';
import './index.less';
@@ -91,8 +91,8 @@ export class KnowledgeView extends BaseView {
loadig = false;
async update() {
- const options = await this.manager.getKnowledge();
- this.list = options.map(this.manager.getOrCreateKnowledge);
+ const options = await this.manager.getAll();
+ this.list = options.map(this.manager.getOrCreate);
}
override async onViewMount(): Promise
{
diff --git a/web/ui/src/views/sessions/conversation-list/index.tsx b/web/ui/src/views/sessions/conversation-list/index.tsx
index 69665bc..016b1d1 100644
--- a/web/ui/src/views/sessions/conversation-list/index.tsx
+++ b/web/ui/src/views/sessions/conversation-list/index.tsx
@@ -1,11 +1,12 @@
-import { CaretRightOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons';
+import { CaretRightOutlined, DeleteOutlined } from '@ant-design/icons';
import { useInject, ViewInstance } from '@difizen/mana-app';
import { Input, Popconfirm } from 'antd';
import type { TextAreaRef } from 'antd/es/input/TextArea.js';
import classNames from 'classnames';
import { useLayoutEffect, useRef, useState } from 'react';
-import type { SessionModel } from '../../../modules/session/index.js';
+import type { SessionModel } from '@/modules/session/session-model.js';
+
import type { SessionsView } from '../view.js';
import './index.less';
diff --git a/web/ui/src/views/sessions/view.tsx b/web/ui/src/views/sessions/view.tsx
index ee240b2..216c229 100644
--- a/web/ui/src/views/sessions/view.tsx
+++ b/web/ui/src/views/sessions/view.tsx
@@ -14,12 +14,13 @@ import { Button } from 'antd';
import classNames from 'classnames';
import { forwardRef, useMemo } from 'react';
-import type { SessionModel } from '../../modules/session/index.js';
-import { SessionManager } from '../../modules/session/index.js';
+import { SessionManager } from '@/modules/session/session-manager.js';
+import type { SessionModel } from '@/modules/session/session-model.js';
-import './index.less';
import { ConversationItem } from './conversation-list/index.js';
+import './index.less';
+
const viewId = 'magent-sessions';
function isYesterday(inputDateStr: string) {
diff --git a/web/ui/src/views/tools/module.ts b/web/ui/src/views/tools/module.ts
index 9066963..952c665 100644
--- a/web/ui/src/views/tools/module.ts
+++ b/web/ui/src/views/tools/module.ts
@@ -1,6 +1,6 @@
import { createViewPreference, ManaModule } from '@difizen/mana-app';
-import { ToolSpace } from '../../modules/tool/tool-space.js';
+import { ToolSpace } from '@/modules/tool/tool-space.js';
import { ToolsView, slot } from './view.js';
diff --git a/web/ui/src/views/tools/view.tsx b/web/ui/src/views/tools/view.tsx
index 0799dbf..17a06ad 100644
--- a/web/ui/src/views/tools/view.tsx
+++ b/web/ui/src/views/tools/view.tsx
@@ -12,8 +12,8 @@ import { Col, List, Row, Tag, Tooltip } from 'antd';
import { forwardRef, useEffect, useRef, useState } from 'react';
import './index.less';
-import { ToolIcon } from '../../modules/tool/tool-icon.js';
-import { ToolSpace } from '../../modules/tool/tool-space.js';
+import { ToolIcon } from '@/modules/tool/tool-icon.js';
+import { ToolSpace } from '@/modules/tool/tool-space.js';
export interface ToolItem {
nickname: string;
From f750528dd6c30b3aaf43fcb2c166db0560b734c8 Mon Sep 17 00:00:00 2001
From: "yukun.wyk"
Date: Tue, 27 Aug 2024 22:09:20 +0800
Subject: [PATCH 08/78] feat(ui): optmize flow dag style
---
.../src/{views/agent-dev => common}/utils.ts | 0
web/ui/src/modules/app.module.ts | 20 ++++----
web/ui/src/views/agent-dev/dev-view.tsx | 5 +-
web/ui/src/views/agent-dev/module.ts | 2 -
web/ui/src/views/agent-flow/flow-dev-view.tsx | 47 ++++++++++++++---
web/ui/src/views/agent-flow/index.less | 50 +++++++++++++++----
.../debug-drawer-contribution.ts | 4 +-
.../debug-drawer.tsx} | 16 +++---
web/ui/src/views/debug/module.ts | 9 ++++
web/ui/src/views/debug/protocol.ts | 1 +
10 files changed, 114 insertions(+), 40 deletions(-)
rename web/ui/src/{views/agent-dev => common}/utils.ts (100%)
rename web/ui/src/views/{agent-dev => debug}/debug-drawer-contribution.ts (73%)
rename web/ui/src/views/{agent-dev/debug-modal.tsx => debug/debug-drawer.tsx} (92%)
create mode 100644 web/ui/src/views/debug/module.ts
create mode 100644 web/ui/src/views/debug/protocol.ts
diff --git a/web/ui/src/views/agent-dev/utils.ts b/web/ui/src/common/utils.ts
similarity index 100%
rename from web/ui/src/views/agent-dev/utils.ts
rename to web/ui/src/common/utils.ts
diff --git a/web/ui/src/modules/app.module.ts b/web/ui/src/modules/app.module.ts
index 38e1ade..c3dcfee 100644
--- a/web/ui/src/modules/app.module.ts
+++ b/web/ui/src/modules/app.module.ts
@@ -1,14 +1,15 @@
import { ManaModule } from '@difizen/mana-app';
-import { AgentConfigViewModule } from '../views/agent-config/module.js';
-import { AgentChatModule } from '../views/agent-dev/module.js';
-import { AgentFlowModule } from '../views/agent-flow/module.js';
-import { AgentsPageModule } from '../views/agents/module.js';
-import { ChatViewModule } from '../views/chat/module.js';
-import { KnowledgePageModule } from '../views/knowledge/module.js';
-import { PortalsModule } from '../views/protal-layout/module.js';
-import { SessionsViewModule } from '../views/sessions/module.js';
-import { ToolPageModule } from '../views/tools/module.js';
+import { AgentConfigViewModule } from '@/views/agent-config/module.js';
+import { AgentChatModule } from '@/views/agent-dev/module.js';
+import { AgentFlowModule } from '@/views/agent-flow/module.js';
+import { AgentsPageModule } from '@/views/agents/module.js';
+import { ChatViewModule } from '@/views/chat/module.js';
+import { DebugModule } from '@/views/debug/module.js';
+import { KnowledgePageModule } from '@/views/knowledge/module.js';
+import { PortalsModule } from '@/views/protal-layout/module.js';
+import { SessionsViewModule } from '@/views/sessions/module.js';
+import { ToolPageModule } from '@/views/tools/module.js';
import { AgentBotModule } from './agent/module.js';
import { AxiosClientModule } from './axios-client/module.js';
@@ -41,6 +42,7 @@ export const AppBaseModule = new ManaModule()
AgentConfigViewModule,
PortalsModule,
AgentFlowModule,
+ DebugModule,
);
export default AppBaseModule;
diff --git a/web/ui/src/views/agent-dev/dev-view.tsx b/web/ui/src/views/agent-dev/dev-view.tsx
index 56c569f..675184b 100644
--- a/web/ui/src/views/agent-dev/dev-view.tsx
+++ b/web/ui/src/views/agent-dev/dev-view.tsx
@@ -6,10 +6,11 @@ import { forwardRef, useEffect } from 'react';
import { useMatch } from 'react-router-dom';
import type { AgentConfigManager } from '@/modules/agent/agent-config-manager.js';
+
import { AgentConfigView } from '../agent-config/view.js';
+import { DebugDrawer } from '../debug/debug-drawer.js';
import { AgentView } from './chat-view.js';
-import { DebugModal } from './debug-modal.js';
import './index.less';
const viewId = 'magent-agent-dev';
@@ -38,7 +39,7 @@ const AgentDevComponent = forwardRef(
预览
+
+
+ );
+ },
+);
diff --git a/web-apps/ui/src/modules/model/module.ts b/web-apps/ui/src/modules/model/module.ts
index 50f8260..4ae661f 100644
--- a/web-apps/ui/src/modules/model/module.ts
+++ b/web-apps/ui/src/modules/model/module.ts
@@ -1,20 +1,36 @@
import { ManaModule } from '@difizen/mana-app';
import { LLMManager } from './llm-manager.js';
-import { LLMModel } from './llm-model.js';
-import type { ModelMeta } from './protocol.js';
+import { LLMModel, LLMProvider } from './llm-model.js';
+import { LLMProviderManager } from './llm-provider-manager.js';
+import type { LLMMeta, LLMProviderMeta } from './protocol.js';
+import { LLMProviderFactory, LLMProviderOption } from './protocol.js';
import { LLMModelOption } from './protocol.js';
import { LLMModelFactory } from './protocol.js';
-export const ModelModule = ManaModule.create()
- .register(LLMModel, LLMManager)
- .register({
+export const ModelModule = ManaModule.create().register(
+ LLMProvider,
+ LLMProviderManager,
+ LLMModel,
+ LLMManager,
+ {
token: LLMModelFactory,
useFactory: (ctx) => {
- return (meta: ModelMeta) => {
+ return (meta: LLMMeta) => {
const child = ctx.container.createChild();
child.register({ token: LLMModelOption, useValue: meta });
return child.get(LLMModel);
};
},
- });
+ },
+ {
+ token: LLMProviderFactory,
+ useFactory: (ctx) => {
+ return (meta: LLMProviderMeta) => {
+ const child = ctx.container.createChild();
+ child.register({ token: LLMProviderOption, useValue: meta });
+ return child.get(LLMProvider);
+ };
+ },
+ },
+);
diff --git a/web-apps/ui/src/modules/model/protocol.ts b/web-apps/ui/src/modules/model/protocol.ts
index 0f74147..c25e145 100644
--- a/web-apps/ui/src/modules/model/protocol.ts
+++ b/web-apps/ui/src/modules/model/protocol.ts
@@ -1,17 +1,30 @@
import { Syringe } from '@difizen/mana-app';
-import type { LLMModel } from './llm-model.js';
+import type { LLMModel, LLMProvider } from './llm-model.js';
-export interface ModelMeta {
+export interface LLMMeta {
id: string;
nickname: string;
temperature: number;
- model_name: string[];
+ model_name: [string];
}
-export type LLMModelFactory = (option: ModelMeta) => LLMModel;
+export type LLMModelFactory = (option: LLMMeta) => LLMModel;
export const LLMModelFactory = Syringe.defineToken('LLMModelFactory');
export const LLMModelOption = Syringe.defineToken('LLMModelOption', {
multiple: false,
});
+
+export interface LLMProviderMeta {
+ id: string;
+ nickname: string;
+ temperature: number;
+ model_name: string[];
+}
+export type LLMProviderFactory = (option: LLMProviderMeta) => LLMProvider;
+export const LLMProviderFactory = Syringe.defineToken('LLMProviderFactory');
+
+export const LLMProviderOption = Syringe.defineToken('LLMProviderOption', {
+ multiple: false,
+});
diff --git a/web-apps/ui/src/views/agent-config/components/model-selector/index.tsx b/web-apps/ui/src/views/agent-config/components/model-selector/index.tsx
index 6869f86..5c0605c 100644
--- a/web-apps/ui/src/views/agent-config/components/model-selector/index.tsx
+++ b/web-apps/ui/src/views/agent-config/components/model-selector/index.tsx
@@ -5,10 +5,10 @@ import { Button, Form, Select, Popover, Avatar, Slider } from 'antd';
import type { FC } from 'react';
import { forwardRef, useEffect } from 'react';
-import { LLMManager } from '@/modules/model/llm-manager.js';
-import type { LLMModel } from '@/modules/model/llm-model.js';
+import type { LLMProvider } from '@/modules/model/llm-model.js';
+import { LLMProviderManager } from '@/modules/model/llm-provider-manager.js';
import { LLMIcon } from '@/modules/model/model-icon/index.js';
-import type { ModelMeta } from '@/modules/model/protocol.js';
+import type { LLMMeta } from '@/modules/model/protocol.js';
import type { AgentConfigView } from '../../view.js';
@@ -16,7 +16,7 @@ import './index.less';
const clsPrefix = 'agent-config-model-selector';
-const ModelSelectorOption = (props: { model: ModelMeta; flat?: boolean }) => {
+const ModelSelectorOption = (props: { model: LLMMeta; flat?: boolean }) => {
const { model, flat } = props;
return (
@@ -31,7 +31,7 @@ const ModelSelectorOption = (props: { model: ModelMeta; flat?: boolean }) => {
);
};
-const toKey = (model?: ModelMeta) => {
+const toKey = (model?: LLMMeta) => {
if (!model) {
return undefined;
}
@@ -39,7 +39,7 @@ const toKey = (model?: ModelMeta) => {
};
interface TemperatureSliderProps extends SliderSingleProps {
- llm?: LLMModel;
+ llm?: LLMProvider;
}
const TemperatureSlider: FC
= (
props: TemperatureSliderProps,
@@ -65,24 +65,23 @@ const TemperatureSlider: FC = (
export const ModelSelector = forwardRef(
function ModelSelectorComponent(props, ref) {
const instance = useInject(ViewInstance);
- const modelManager = useInject(LLMManager);
- // const defaultModel = modelManager.defaultModel;
+ const modelProviderManager = useInject(LLMProviderManager);
const modelMeta = instance.agent?.llm;
- const models = modelManager.models;
+ const models = modelProviderManager.models;
const metaModels = models
.map((item) => item.toSingleMetas())
.filter((item) => !!item)
- .flat() as ModelMeta[];
+ .flat() as LLMMeta[];
useEffect(() => {
- modelManager.updateModels();
- }, [modelManager]);
+ modelProviderManager.updateProviders();
+ }, [modelProviderManager]);
const currentModel = metaModels.find(
- (item) => modelMeta && toKey(item) === toKey(modelMeta.toMeta()),
+ (item) => modelMeta && toKey(item) === toKey(modelMeta),
);
return (
@@ -101,7 +100,7 @@ export const ModelSelector = forwardRef(
onSelect={(v) => {
const llm = metaModels.find((i) => toKey(i) === v);
if (instance.agent.llm && llm) {
- instance.agent.llm = modelManager.getOrCreate(llm);
+ instance.agent.llm = modelProviderManager.getOrCreate(llm);
}
}}
value={toKey(instance.agent.llm?.toMeta())}
diff --git a/web-apps/ui/src/views/agent-config/view.tsx b/web-apps/ui/src/views/agent-config/view.tsx
index eab0f4f..8af9859 100644
--- a/web-apps/ui/src/views/agent-config/view.tsx
+++ b/web-apps/ui/src/views/agent-config/view.tsx
@@ -16,14 +16,14 @@ import { forwardRef } from 'react';
import { AgentManager } from '@/modules/agent/agent-manager.js';
import type { AgentModel } from '@/modules/agent/protocol.js';
import { KnowledgeIcon } from '@/modules/knowledge/knowledge-icon.js';
+import { ModelSelector } from '@/modules/model/model-selector/index.js';
import { ToolIcon } from '@/modules/tool/tool-icon.js';
import { CharacterSetting } from './components/character-setting/index.js';
import { ConfigList } from './components/config-selector/index.js';
-import { ModelSelector } from './components/model-selector/index.js';
-import './index.less';
import { KnowledgeModal } from './knowledge-modal/modal.js';
import { ToolsModal } from './tools-modal/modal.js';
+import './index.less';
const viewId = 'magent-dev-config';
@@ -48,7 +48,19 @@ const AgentConfigViewComponent = forwardRef(
模型
-
+
{
+ if (meta) {
+ instance.agent.llm?.updateMeta(meta);
+ }
+ }}
+ onConfigChanged={(meta) => {
+ if (meta) {
+ instance.agent.llm?.updateMeta(meta);
+ }
+ }}
+ />
> = (
useEffect(() => {
form
- .validateFields({ validateOnly: true })
+ .validateFields({
+ validateOnly: true,
+ })
.then(() => setSubmittable(true))
.catch(() => setSubmittable(false));
}, [form, values]);
return (
-
+ form.submit()}
+ type="primary"
+ htmlType="submit"
+ disabled={!submittable}
+ >
{children}
);
@@ -51,9 +65,31 @@ const UploadButton = (props: { imageUrl?: string }) => {
};
export const AgentModalComponent = (props: ModalItemProps) => {
+ const agentManager = useInject(AgentManager);
+ const llmManager = useInject(LLMManager);
+ const axios = useInject(AxiosClient);
const { visible, close } = props;
- const [form] = Form.useForm();
- const [idValue, setId] = useState(undefined);
+ const [form] = Form.useForm<{
+ id: string;
+ plannerId: string;
+ avatar?: string;
+ nickname: string;
+ description?: string;
+ llm: LLMMeta;
+ }>();
+ const idValue = Form.useWatch('id', form);
+ const plannerValue = Form.useWatch('plannerId', form);
+ useEffect(() => {
+ llmManager
+ .updateFromProvider()
+ .then(() => {
+ if (form.getFieldValue('llm') === undefined && llmManager.default) {
+ form.setFieldValue('llm', llmManager.default.toMeta());
+ }
+ return;
+ })
+ .catch(console.error);
+ }, [llmManager, form]);
return (
) => {
-
+
+
+
+ ({
+ // async validator(_, value) {
+ // const res = await axios.get(`/api/v1/llms`);
+ // },
+ // }),
+ ]}
+ >
+
-
+
+ {plannerValue !== 'workflow_planner' && (
+
+
+
+ )}
Date: Wed, 28 Aug 2024 20:53:03 +0800
Subject: [PATCH 13/78] feat(ui): agent id validate
---
.../src/magent_ui/routers/common/__init__.py | 0
.../src/magent_ui/routers/common/router.py | 16 +++++++++++++++
.../magent-ui/src/magent_ui/routers/main.py | 2 ++
.../ui/src/modules/axios-client/module.ts | 3 ++-
.../ui/src/modules/axios-client/request.ts | 13 ++++++++++++
web-apps/ui/src/views/agents/modal/create.tsx | 20 ++++++++++++-------
6 files changed, 46 insertions(+), 8 deletions(-)
create mode 100644 packages/magent-ui/src/magent_ui/routers/common/__init__.py
create mode 100644 packages/magent-ui/src/magent_ui/routers/common/router.py
create mode 100644 web-apps/ui/src/modules/axios-client/request.ts
diff --git a/packages/magent-ui/src/magent_ui/routers/common/__init__.py b/packages/magent-ui/src/magent_ui/routers/common/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/packages/magent-ui/src/magent_ui/routers/common/router.py b/packages/magent-ui/src/magent_ui/routers/common/router.py
new file mode 100644
index 0000000..81d912f
--- /dev/null
+++ b/packages/magent-ui/src/magent_ui/routers/common/router.py
@@ -0,0 +1,16 @@
+import asyncio
+import enum
+import json
+from typing import AsyncIterable, List
+from fastapi import APIRouter
+import agentuniverse_product.service.util.product_util as util
+
+router = APIRouter()
+common_router = router
+
+
+@router.get("/common/is_id_unique", response_model=bool)
+async def is_id_unique(id:str, type:str):
+ result = util.is_id_unique(id,type)
+ return result
+
diff --git a/packages/magent-ui/src/magent_ui/routers/main.py b/packages/magent-ui/src/magent_ui/routers/main.py
index 3d59900..949f198 100644
--- a/packages/magent-ui/src/magent_ui/routers/main.py
+++ b/packages/magent-ui/src/magent_ui/routers/main.py
@@ -6,6 +6,7 @@
from magent_ui.routers.tools.router import tools_router
from magent_ui.routers.resource.router import resource_router
from magent_ui.routers.workflow.router import workflow_router
+from magent_ui.routers.common.router import common_router
api_router = APIRouter()
@@ -16,3 +17,4 @@
api_router.include_router(tools_router, prefix="/v1", tags=["tool"])
api_router.include_router(resource_router, prefix="/v1", tags=["resource"])
api_router.include_router(workflow_router, prefix="/v1", tags=["workflow"])
+api_router.include_router(common_router, prefix="/v1", tags=["common"])
diff --git a/web-apps/ui/src/modules/axios-client/module.ts b/web-apps/ui/src/modules/axios-client/module.ts
index e3b4e02..b9d0235 100644
--- a/web-apps/ui/src/modules/axios-client/module.ts
+++ b/web-apps/ui/src/modules/axios-client/module.ts
@@ -2,9 +2,10 @@ import { ManaModule, Syringe } from '@difizen/mana-app';
import { getContextClient } from './client.js';
import { AxiosClient } from './protocol.js';
+import { RequestHelper } from './request.js';
export const AxiosClientModule = ManaModule.create()
- .register({
+ .register(RequestHelper, {
token: AxiosClient,
useDynamic: getContextClient,
lifecycle: Syringe.Lifecycle.singleton,
diff --git a/web-apps/ui/src/modules/axios-client/request.ts b/web-apps/ui/src/modules/axios-client/request.ts
new file mode 100644
index 0000000..f63bc8a
--- /dev/null
+++ b/web-apps/ui/src/modules/axios-client/request.ts
@@ -0,0 +1,13 @@
+import { inject, singleton } from '@difizen/mana-app';
+import qs from 'query-string';
+
+import { AxiosClient } from './protocol.js';
+
+@singleton()
+export class RequestHelper {
+ @inject(AxiosClient) axios: AxiosClient;
+ get(basePath: string, params: Record) {
+ const query = qs.stringify(params);
+ return this.axios.get(`${basePath}?${query}`);
+ }
+}
diff --git a/web-apps/ui/src/views/agents/modal/create.tsx b/web-apps/ui/src/views/agents/modal/create.tsx
index 03739e1..03abb82 100644
--- a/web-apps/ui/src/views/agents/modal/create.tsx
+++ b/web-apps/ui/src/views/agents/modal/create.tsx
@@ -13,7 +13,7 @@ import { AgentTypeSelector } from '@/components/agent-type-selector/index.js';
import { AvatarUpload } from '@/components/avatar-upload/index.js';
import { AgentIcon } from '@/modules/agent/agent-icon.js';
import { AgentManager } from '@/modules/agent/agent-manager.js';
-import { AxiosClient } from '@/modules/axios-client/protocol.js';
+import { RequestHelper } from '@/modules/axios-client/request.js';
import { LLMManager } from '@/modules/model/llm-manager.js';
import { ModelSelector } from '@/modules/model/model-selector/index.js';
import type { LLMMeta } from '@/modules/model/protocol.js';
@@ -67,7 +67,7 @@ const UploadButton = (props: { imageUrl?: string }) => {
export const AgentModalComponent = (props: ModalItemProps) => {
const agentManager = useInject(AgentManager);
const llmManager = useInject(LLMManager);
- const axios = useInject(AxiosClient);
+ const req = useInject(RequestHelper);
const { visible, close } = props;
const [form] = Form.useForm<{
id: string;
@@ -145,11 +145,17 @@ export const AgentModalComponent = (props: ModalItemProps) => {
label="id"
rules={[
{ required: true },
- // ({ getFieldValue }) => ({
- // async validator(_, value) {
- // const res = await axios.get(`/api/v1/llms`);
- // },
- // }),
+ () => ({
+ async validator(_, value) {
+ const res = await req.get(`/api/v1/common/is_id_unique`, {
+ id: value,
+ type: 'agent',
+ });
+ if (res.status !== 200 || res.data === false) {
+ throw new Error(`${value} 已存在,请更换其他 id`);
+ }
+ },
+ }),
]}
>
From cf9bc45865a78561cf2b2c723d6ba8c14e3e00e1 Mon Sep 17 00:00:00 2001
From: "xujianfeng.xjf"
Date: Tue, 27 Aug 2024 20:06:29 +0800
Subject: [PATCH 14/78] feat: update node template in flow
---
.../magent-flow/src/RefForm/index.tsx | 2 +-
.../components/AIBasic/PromptEditor/index.tsx | 2 +-
.../magent-flow/src/components/Flow/index.tsx | 2 +
.../src/components/FlowWithPanel/index.tsx | 54 +++++-------
.../src/components/Node/AgentNode/index.tsx | 69 +++++++++++++--
.../src/components/Node/EndNode/index.tsx | 85 +++++++++++++++----
.../src/components/Node/IfElseNode/index.tsx | 55 ++++++------
.../components/Node/KnowledgeNode/index.tsx | 18 +++-
.../src/components/Node/LLMNode/index.tsx | 60 +++++++++----
.../src/components/Node/NodeWrapper/index.tsx | 5 +-
.../src/components/ReferenceForm/index.tsx | 12 ++-
.../src/components/ReferenceSelect/index.tsx | 25 +++---
.../src/components/VariableForm/index.tsx | 1 +
.../magent-flow/src/interfaces/flow.ts | 42 +++++++--
.../magent-flow/src/stores/useFlowStore.ts | 7 +-
.../src/components/ConditionForm/index.tsx | 56 ++++++++++++
.../src/components/Toolbar/index.tsx | 23 +++++
17 files changed, 375 insertions(+), 143 deletions(-)
create mode 100644 web/packages/magent-flow/src/components/ConditionForm/index.tsx
create mode 100644 web/packages/magent-flow/src/components/Toolbar/index.tsx
diff --git a/web-packages/magent-flow/src/RefForm/index.tsx b/web-packages/magent-flow/src/RefForm/index.tsx
index 0dbe097..b7b66a1 100644
--- a/web-packages/magent-flow/src/RefForm/index.tsx
+++ b/web-packages/magent-flow/src/RefForm/index.tsx
@@ -15,7 +15,7 @@ interface CascaderOptions {
*/
const getCascaderOptions = (node: NodeDataType) => {
const jsonSchema = node.config?.inputs?.jsonschema;
- console.log('🚀 ~ getCascaderOptions ~ jsonSchema:', jsonSchema);
+
const options: CascaderOptions[] = [
{
label: `${node.name}`,
diff --git a/web-packages/magent-flow/src/components/AIBasic/PromptEditor/index.tsx b/web-packages/magent-flow/src/components/AIBasic/PromptEditor/index.tsx
index 8e97314..8c8061c 100644
--- a/web-packages/magent-flow/src/components/AIBasic/PromptEditor/index.tsx
+++ b/web-packages/magent-flow/src/components/AIBasic/PromptEditor/index.tsx
@@ -82,7 +82,7 @@ const PromptEditor: FC = ({
return (
-
+
{miniMap && }
+
);
diff --git a/web-packages/magent-flow/src/components/FlowWithPanel/index.tsx b/web-packages/magent-flow/src/components/FlowWithPanel/index.tsx
index 8ed246c..afd719d 100644
--- a/web-packages/magent-flow/src/components/FlowWithPanel/index.tsx
+++ b/web-packages/magent-flow/src/components/FlowWithPanel/index.tsx
@@ -1,5 +1,4 @@
import yaml from 'js-yaml';
-import React from 'react';
import { EventEmitterContextProvider } from '@/context/event-emitter.js';
import type { NodeDataType } from '@/interfaces/flow.js';
@@ -19,9 +18,6 @@ const yamlContent = `
name: 开始节点
description: 工作流的起始节点,用于设定启动工作流需要的信息
type: start
- position:
- x: 100
- y: 100
data:
outputs:
- name: user_input
@@ -41,19 +37,20 @@ const yamlContent = `
type: string
value:
type: reference
- content: ['llm1', 'output'] # 通过nodeId + paramKey 定位引用变量
prompt:
name: response
type: string
description: 输出内容
- value: '{{response}}'
+ value:
+ type: reference
+ content: '{{response}}'
+ outputs:
+ - name: output
+ type: string
- id: 3
name: 大模型节点
description: 调用大语言模型,使用变量和提示词生成回复
type: llm
- position:
- x: 300
- y: 100
data:
inputs:
input_param:
@@ -78,8 +75,11 @@ const yamlContent = `
name: temperature
value: '0.7'
- type: string
- name: prompt
- value: |
+ prompt:
+ type: string
+ value:
+ type: value
+ content: |
你是一位精通信息分析的ai助手。你的目标是使用中文结合查询的背景信息及你所拥有的知识回答用户提出的问题。
你需要遵守的规则是:
1. 必须使用中文结合查询的背景信息结合你所拥有的知识回答用户提出的问题。
@@ -91,20 +91,17 @@ const yamlContent = `
7. 尽量多的使用数值类信息。
背景信息是:
- {background}
+ {{background}}
开始!
- 需要回答的问题是: {input}
+ 需要回答的问题是: {{input}}
outputs:
- type: string
name: output
- id: 4
- name: 知识库示例
+ name: 知识库
description:
type: knowledge
- position:
- x: 400
- y: 100
data:
inputs:
knowledge_param:
@@ -125,7 +122,7 @@ const yamlContent = `
- name: output
type: string
- id: 5
- name: 谷歌搜索工具
+ name: 工具
description:
type: tool
position:
@@ -142,17 +139,14 @@ const yamlContent = `
name: input
value:
type: value
- content: 'output' # 通过nodeId + paramKey 定位引用变量
+ content: 'output'
outputs:
- name: output
type: string
- id: 6
- name: rag智能体
+ name: Agent智能体
description:
type: agent
- position:
- x: 600
- y: 100
data:
inputs:
agent_param:
@@ -172,12 +166,9 @@ const yamlContent = `
name: 条件判断
description:
type: ifelse
- position:
- x: 700
- y: 100
data:
inputs:
- branches: # 这一期这做一层,不包括 and or 还有我理解默认逻辑不展示在这块对吧,只在edge体现
+ branches:
- name: branch-1
conditions:
- compare: equal
@@ -189,16 +180,14 @@ const yamlContent = `
type: string # 只有 if 和 else,branch-1和branch-default
value:
type: reference
-
-
`;
export const NodeSchemaParser = (obj: Record
) => {
- obj.config = obj.data;
- obj.icon =
+ obj['config'] = obj['data'];
+ obj['icon'] =
'https://mdn.alipayobjects.com/huamei_xbkogb/afts/img/A*PzmdRpvZz58AAAAAAAAAAAAADqarAQ/original';
- delete obj.data;
+ delete obj['data'];
};
const nodeTypes = {
@@ -216,7 +205,6 @@ export const FlowWithPanel = () => {
(yaml_data as Record[]).forEach((item) => {
NodeSchemaParser(item);
});
- console.log('🚀 ~ yaml_data:', yaml_data);
// const setNodes = useFlowStore((state) => state.setNodes);
// const reactFlowInstance = useFlowStore((state) => state.reactFlowInstance);
diff --git a/web-packages/magent-flow/src/components/Node/AgentNode/index.tsx b/web-packages/magent-flow/src/components/Node/AgentNode/index.tsx
index 5ae7932..441830e 100644
--- a/web-packages/magent-flow/src/components/Node/AgentNode/index.tsx
+++ b/web-packages/magent-flow/src/components/Node/AgentNode/index.tsx
@@ -1,7 +1,8 @@
import { CollapseWrapper } from '@/components/AIBasic/CollapseWrapper/index.js';
import { OutputVariable } from '@/components/AIBasic/OutputVariableTree/OutputVariable/index.js';
+import PromptEditor from '@/components/AIBasic/PromptEditor/index.js';
import { ReferenceForm } from '@/components/ReferenceForm/index.js';
-import type { NodeDataType } from '@/interfaces/flow.js';
+import type { BasicSchema, NodeDataType } from '@/interfaces/flow.js';
import { useFlowStore } from '@/stores/useFlowStore.js';
import { NodeWrapper } from '../NodeWrapper/index.js';
@@ -16,9 +17,8 @@ type Props = {
export const AgentNode = (props: Props) => {
const { data } = props;
// const { config } = data;
- const { findUpstreamNodes } = useFlowStore();
+ const { findUpstreamNodes, setNode } = useFlowStore();
const upstreamNodes = findUpstreamNodes(data.id.toString());
- console.log('🚀 ~ AgentNode ~ upstreamNodes:', upstreamNodes);
return (
@@ -26,12 +26,65 @@ export const AgentNode = (props: Props) => {
{
- console.log('ReferenceForm', values);
+ setNode(data.id, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ config: {
+ ...(old.data.config as Record),
+ inputs: {
+ ...old.data.config.inputs,
+ input_param: [...values],
+ },
+ },
+ },
+ }));
}}
/>
-
+
+ {
+ setNode(data.id, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ config: {
+ ...(old.data.config as Record),
+ inputs: {
+ ...old.data.config.inputs,
+ prompt: {
+ ...old.data.config.inputs.prompt,
+ value: values,
+ },
+ },
+ },
+ },
+ }));
+ }}
+ variableBlock={{
+ show: true,
+ variables: data.config?.inputs?.input_param.map((input) => {
+ return {
+ name: input.name,
+ value: input.name,
+ };
+ }),
+ }}
+ />
+
+ }
+ />
{
<>
{(data.config?.outputs || []).map((output) => (
))}
diff --git a/web-packages/magent-flow/src/components/Node/EndNode/index.tsx b/web-packages/magent-flow/src/components/Node/EndNode/index.tsx
index a80f0f7..9c3681b 100644
--- a/web-packages/magent-flow/src/components/Node/EndNode/index.tsx
+++ b/web-packages/magent-flow/src/components/Node/EndNode/index.tsx
@@ -1,7 +1,7 @@
-import { Collapse } from 'antd';
-
+import { CollapseWrapper } from '@/components/AIBasic/CollapseWrapper/index.js';
+import PromptEditor from '@/components/AIBasic/PromptEditor/index.js';
import { ReferenceForm } from '@/components/ReferenceForm/index.js';
-import type { NodeDataType } from '@/interfaces/flow.js';
+import type { BasicSchema, NodeDataType } from '@/interfaces/flow.js';
import { useFlowStore } from '@/stores/useFlowStore.js';
import { NodeWrapper } from '../NodeWrapper/index.js';
@@ -15,21 +15,76 @@ type Props = {
export const EndNode = (props: Props) => {
const { data } = props;
- const { findUpstreamNodes } = useFlowStore();
- const upstreamNode = findUpstreamNodes(data.id.toString());
+ const { findUpstreamNodes, setNode } = useFlowStore();
+ const upstreamNodes = findUpstreamNodes(data.id.toString());
return (
-
- {
- console.log('ReferenceForm', values);
- }}
- />
-
+ {
+ setNode(data.id, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ config: {
+ ...(old.data.config as Record),
+ inputs: {
+ ...old.data.config.inputs,
+ input_param: [...values],
+ },
+ },
+ },
+ }));
+ }}
+ />
+
+
+
+
{
+ setNode(data.id, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ config: {
+ ...(old.data.config as Record),
+ inputs: {
+ ...old.data.config.inputs,
+ prompt: {
+ ...old.data.config.inputs.prompt,
+ value: values,
+ },
+ },
+ },
+ },
+ }));
+ }}
+ variableBlock={{
+ show: true,
+ variables: data.config?.inputs?.input_param.map((input) => {
+ return {
+ name: input.name!,
+ value: input.name!,
+ };
+ }),
+ }}
+ />
+
+ >
+ }
+ >
);
};
diff --git a/web-packages/magent-flow/src/components/Node/IfElseNode/index.tsx b/web-packages/magent-flow/src/components/Node/IfElseNode/index.tsx
index 06ae870..7a99001 100644
--- a/web-packages/magent-flow/src/components/Node/IfElseNode/index.tsx
+++ b/web-packages/magent-flow/src/components/Node/IfElseNode/index.tsx
@@ -1,8 +1,5 @@
-import { Form } from 'antd';
-
-import { SelectInNode } from '@/components/AIBasic/SelectInNode/index.js';
-import { ReferenceSelect } from '@/components/ReferenceSelect/index.js';
-import type { NodeDataType } from '@/interfaces/flow.js';
+import { ConditionForm } from '@/components/ConditionForm/index.js';
+import type { NodeDataType, NodeType } from '@/interfaces/flow.js';
import { useFlowStore } from '@/stores/useFlowStore.js';
import { NodeWrapper } from '../NodeWrapper/index.js';
@@ -16,11 +13,10 @@ type Props = {
export const IfElseNode = (props: Props) => {
const { data } = props;
- const [form] = Form.useForm();
- const compare = Form.useWatch('compare', form);
- const { findUpstreamNodes } = useFlowStore();
+
+ const { findUpstreamNodes, setNode } = useFlowStore();
const upstreamNode = findUpstreamNodes(data.id.toString());
- const options = upstreamNode.map((node) => {
+ const options = upstreamNode.map((node: NodeType) => {
return {
label: node.data.name,
value: node.data.id,
@@ -45,27 +41,26 @@ export const IfElseNode = (props: Props) => {
如果
-
-
-
-
-
-
- {compare !== 'blank' && (
-
-
-
- )}
-
+
{
+ setNode(data.id, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ config: {
+ ...(old.data.config as Record),
+
+ inputs: {
+ ...old.data.config.inputs,
+ branches: [val],
+ },
+ },
+ },
+ }));
+ }}
+ />
diff --git a/web-packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx b/web-packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx
index 076b3c9..fe55f48 100644
--- a/web-packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx
+++ b/web-packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx
@@ -20,7 +20,7 @@ type Props = {
export const KnowledgeNode = (props: Props) => {
const { data } = props;
// const { config } = data;
- const { findUpstreamNodes } = useFlowStore();
+ const { findUpstreamNodes, setNode } = useFlowStore();
const { knowledges } = useKnowledgeStore();
const upstreamNode = findUpstreamNodes(data.id.toString());
@@ -31,9 +31,21 @@ export const KnowledgeNode = (props: Props) => {
{
- console.log('ReferenceForm', values);
+ setNode(data.id, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ config: {
+ ...(old.data.config as Record),
+ inputs: {
+ ...old.data.config.inputs,
+ input_param: [...values],
+ },
+ },
+ },
+ }));
}}
/>
{
const { data } = props;
- // console.log('🚀 ~ LLMNode ~ data:', data);
- // const { config } = data;
- const { findUpstreamNodes } = useFlowStore();
+ const { findUpstreamNodes, setNode } = useFlowStore();
const upstreamNode = findUpstreamNodes(data.id.toString());
const { models, modelConfig } = useModelStore();
- const [value, setValue] = useState('hello');
return (
@@ -67,14 +64,25 @@ export const LLMNode = (props: Props) => {
}
/>
{/* Part2 Ref Form */}
-
{
- console.log('ReferenceForm', values);
+ setNode(data.id, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ config: {
+ ...(old.data.config as Record),
+ inputs: {
+ ...old.data.config.inputs,
+ input_param: [...values],
+ },
+ },
+ },
+ }));
}}
/>
{/* Part3 PromptEditor */}
@@ -82,17 +90,37 @@ export const LLMNode = (props: Props) => {
className="mt-3"
label={'Prompt'}
content={
-
+
setValue(val)}
+ onChange={(values) => {
+ setNode(data.id, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ config: {
+ ...(old.data.config as Record),
+ inputs: {
+ ...old.data.config.inputs,
+ prompt: {
+ ...old.data.config.inputs.prompt,
+ value: values,
+ },
+ },
+ },
+ },
+ }));
+ }}
variableBlock={{
show: true,
variables: data.config?.inputs?.input_param.map((input) => {
return {
- name: input.name!,
- value: input.name!,
+ name: input.name,
+ value: input.name,
};
}),
}}
@@ -103,13 +131,13 @@ export const LLMNode = (props: Props) => {
{/* Part4 Outputer */}
{(data.config?.outputs || []).map((output) => (
))}
diff --git a/web-packages/magent-flow/src/components/Node/NodeWrapper/index.tsx b/web-packages/magent-flow/src/components/Node/NodeWrapper/index.tsx
index 5800c27..fbd4bf8 100644
--- a/web-packages/magent-flow/src/components/Node/NodeWrapper/index.tsx
+++ b/web-packages/magent-flow/src/components/Node/NodeWrapper/index.tsx
@@ -14,7 +14,7 @@ type Props = {
export const NodeWrapper = (props: {
nodeProps: Props;
- children: React.ReactElement;
+ children: React.ReactNode;
leftHandler?: boolean;
rightHandler?: boolean;
rightHandlerConfig?: {
@@ -30,9 +30,6 @@ export const NodeWrapper = (props: {
rightHandlerConfig,
} = props;
const { name, description, icon } = nodeProps.data;
- console.log('🚀 ~ nodeProps.selected:', nodeProps.selected);
- // const runRes = {};
- // const validationStatus = true;
return (
void;
+ value: BasicSchema[];
+ onChange: (values: BasicSchema[]) => void;
nodes: NodeType[];
dynamic?: boolean;
}
export const ReferenceForm = (props: RefrenceFormProps) => {
- const { label, values, onChange, nodes, dynamic = false } = props;
+ const { label, value, onChange, nodes, dynamic = false } = props;
const [form] = Form.useForm();
useEffect(() => {
- form.setFieldValue('variables', values);
+ form.setFieldValue('variables', value);
}, []);
- console.log('🚀 ~ useEffect ~ values:', values);
const options = nodes.map((node) => {
return {
@@ -46,7 +45,6 @@ export const ReferenceForm = (props: RefrenceFormProps) => {
form={form}
autoComplete="off"
onValuesChange={(_, allFields) => {
- console.log('🚀 ~ form.validateFields ~ allFields:', allFields);
form.validateFields().then(() => {
if (allFields.variables) {
onChange(allFields.variables.filter((item: any) => item !== undefined));
diff --git a/web-packages/magent-flow/src/components/ReferenceSelect/index.tsx b/web-packages/magent-flow/src/components/ReferenceSelect/index.tsx
index 28540cc..f4b94cb 100644
--- a/web-packages/magent-flow/src/components/ReferenceSelect/index.tsx
+++ b/web-packages/magent-flow/src/components/ReferenceSelect/index.tsx
@@ -1,29 +1,24 @@
import { Input } from 'antd';
-import React from 'react';
+import type { DefaultOptionType } from 'antd/es/cascader';
+
+import type { SchemaValueType, ValueType } from '@/interfaces/flow.js';
import { CascaderInNode } from '../AIBasic/CascaderInNode/index.js';
import { SelectInNode } from '../AIBasic/SelectInNode/index.js';
export const ReferenceSelect = (props: {
- value?: {
- type: 'reference' | 'value';
- content?: string | [string, string];
- };
- onChange?: (value: {
- type: 'reference' | 'value';
- content?: string | [string, string];
- }) => void;
- refOptions: { label: string; content: string }[];
+ value?: SchemaValueType;
+ onChange?: (value: SchemaValueType) => void;
+ refOptions: DefaultOptionType[];
}) => {
const { value, onChange, refOptions } = props;
- console.log('🚀 ~ value:', value);
return (
+ onChange={(val: ValueType) =>
onChange?.({
type: val,
})
@@ -48,9 +43,9 @@ export const ReferenceSelect = (props: {
+ onChange={(val: [string, string]) =>
onChange?.({
- type: value?.type,
+ type: value?.type || 'reference',
content: val,
})
}
diff --git a/web-packages/magent-flow/src/components/VariableForm/index.tsx b/web-packages/magent-flow/src/components/VariableForm/index.tsx
index eb70954..187cb62 100644
--- a/web-packages/magent-flow/src/components/VariableForm/index.tsx
+++ b/web-packages/magent-flow/src/components/VariableForm/index.tsx
@@ -89,6 +89,7 @@ export const VariableForm = (props: VariableFormProps) => {
className="w-[200px]"
>
((set, get) => {
targetNode: string,
): Node[] => {
const adjList: AdjacencyList = {};
+ console.log('🚀 ~ nodes.forEach ~ nodes:', nodes);
nodes.forEach((node) => {
adjList[node.id] = [];
});
@@ -80,11 +81,8 @@ export const useFlowStore = create((set, get) => {
}
};
- console.log('🚀 ~ useFlowStore ~ nodes:', nodes, edges, targetNode);
- console.log('🚀 ~ adjList', adjList);
-
dfs(targetNode);
- console.log('🚀 ~ result', result);
+
return get().nodes.filter((node) => Array.from(result).includes(node.id));
};
@@ -194,7 +192,6 @@ export const useFlowStore = create((set, get) => {
oldEdges,
);
- console.log('🚀 ~ get ~ newEdges:', newEdges);
return newEdges;
});
},
diff --git a/web/packages/magent-flow/src/components/ConditionForm/index.tsx b/web/packages/magent-flow/src/components/ConditionForm/index.tsx
new file mode 100644
index 0000000..391dedd
--- /dev/null
+++ b/web/packages/magent-flow/src/components/ConditionForm/index.tsx
@@ -0,0 +1,56 @@
+import { Form } from 'antd';
+import type { DefaultOptionType } from 'antd/es/cascader';
+import { memo, useEffect } from 'react';
+
+import type { ConditionBranch } from '@/interfaces/flow.js';
+
+import { SelectInNode } from '../AIBasic/SelectInNode//index.js';
+import { ReferenceSelect } from '../ReferenceSelect/index.js';
+
+export const ConditionForm = (props: {
+ refOptions: DefaultOptionType[];
+ value: ConditionBranch;
+ onChange: (val: ConditionBranch) => void;
+}) => {
+ const { refOptions, value, onChange } = props;
+ const [form] = Form.useForm();
+ const compare = Form.useWatch('compare', form);
+
+ useEffect(() => {
+ form.setFieldsValue(value.conditions[0]);
+ }, []);
+
+ return (
+
+
+
+
+
+
+ {compare !== 'blank' && (
+
+
+
+ )}
+
+ );
+};
diff --git a/web/packages/magent-flow/src/components/Toolbar/index.tsx b/web/packages/magent-flow/src/components/Toolbar/index.tsx
new file mode 100644
index 0000000..bd7b05a
--- /dev/null
+++ b/web/packages/magent-flow/src/components/Toolbar/index.tsx
@@ -0,0 +1,23 @@
+import { Button } from 'antd';
+
+import { useFlowStore } from '@/stores/useFlowStore.js';
+import { classNames } from '@/utils/basic.js';
+
+export const Toolbar = (props: { classname?: string }) => {
+ const { classname } = props;
+ const { getFlow } = useFlowStore();
+ return (
+
+ 运行
+ {
+ const flow = getFlow();
+ console.log('🚀 ~ Toolbar ~ flow:', flow);
+ }}
+ >
+ 保存
+
+
+ );
+};
From 0f491b4fa66f548877fc74e0cc007b3d2c8ec77e Mon Sep 17 00:00:00 2001
From: "xujianfeng.xjf"
Date: Wed, 28 Aug 2024 20:31:44 +0800
Subject: [PATCH 15/78] feat: update flow node ModelSelector &
KnowledgeSelector
---
web-apps/ui/package.json | 2 +
.../components/model-selector/index.tsx | 188 +++++++-------
.../agent-config/knowledge-modal/modal.tsx | 30 ++-
web-apps/ui/src/views/agent-config/view.tsx | 8 +-
.../src/views/agent-flow/agent-flow-view.tsx | 231 +++++++++++++++++-
web-apps/ui/src/views/agent-flow/toolbar.tsx | 28 +++
web-packages/magent-flow/package.json | 1 +
.../magent-flow/src/RefForm/index.tsx | 1 -
.../magent-flow/src/components/Flow/index.tsx | 5 +-
.../src/components/FlowWithPanel/index.tsx | 53 ++--
.../components/Node/KnowledgeNode/index.tsx | 39 +--
.../src/components/Node/LLMNode/index.tsx | 79 +++---
web-packages/magent-flow/src/index.ts | 5 +
.../magent-flow/src/stores/useFlowStore.ts | 2 +-
.../src/stores/useKnowledgeStore.ts | 18 +-
.../magent-flow/src/stores/useModelStore.ts | 27 +-
web-packages/magent-flow/tailwind.config.js | 7 +-
.../src/components/Toolbar/index.tsx | 23 --
.../components/decimal-step/index.tsx | 33 +++
19 files changed, 545 insertions(+), 235 deletions(-)
create mode 100644 web-apps/ui/src/views/agent-flow/toolbar.tsx
delete mode 100644 web/packages/magent-flow/src/components/Toolbar/index.tsx
create mode 100644 web/ui/src/views/agent-config/components/decimal-step/index.tsx
diff --git a/web-apps/ui/package.json b/web-apps/ui/package.json
index 45fc42a..c4a005e 100644
--- a/web-apps/ui/package.json
+++ b/web-apps/ui/package.json
@@ -22,6 +22,7 @@
"deploy": "rimraf ../../packages/magent-ui/src/magent_ui/static && copyfiles -u 1 dist/* ../../packages/magent-ui/src/magent_ui/static/ && copyfiles -u 1 dist/**/* ../../packages/magent-ui/src/magent_ui/static/"
},
"dependencies": {
+ "js-yaml": "^4.1.0",
"@ant-design/icons": "^5.3.6",
"@difizen/libro-jupyter": "^0.2.1",
"@difizen/libro-lab": "^0.2.1",
@@ -49,6 +50,7 @@
"umi": "^4.1.1"
},
"devDependencies": {
+ "@types/js-yaml": "^4.0.9",
"@babel/plugin-proposal-decorators": "^7.23.7",
"@babel/plugin-transform-class-properties": "^7.23.3",
"@babel/plugin-transform-flow-strip-types": "^7.23.3",
diff --git a/web-apps/ui/src/views/agent-config/components/model-selector/index.tsx b/web-apps/ui/src/views/agent-config/components/model-selector/index.tsx
index 5c0605c..d7b263f 100644
--- a/web-apps/ui/src/views/agent-config/components/model-selector/index.tsx
+++ b/web-apps/ui/src/views/agent-config/components/model-selector/index.tsx
@@ -12,6 +12,11 @@ import type { LLMMeta } from '@/modules/model/protocol.js';
import type { AgentConfigView } from '../../view.js';
+import './index.less';
+import { LLMManager } from '../../../../modules/model/llm-manager.js';
+import { DecimalStep } from '../decimal-step/index.js';
+
+import { DefaultLogo, OpenAILogo, QwenLogo } from './logos.js';
import './index.less';
const clsPrefix = 'agent-config-model-selector';
@@ -38,104 +43,101 @@ const toKey = (model?: LLMMeta) => {
return model.id + model.model_name[0];
};
-interface TemperatureSliderProps extends SliderSingleProps {
- llm?: LLMProvider;
-}
-const TemperatureSlider: FC = (
- props: TemperatureSliderProps,
-) => {
- const llm = useObserve(props.llm);
- const temperature = llm?.temperature;
- return (
- {
- if (llm) {
- llm.temperature = v;
- }
- }}
- value={temperature === undefined ? 1 : temperature}
- />
- );
-};
+export const ModelSelector = forwardRef(function ModelSelectorComponent(
+ props: {
+ value?: LLMMeta;
+ onChange?: (value: LLMMeta) => void;
+ },
+ ref,
+) {
+ const { value, onChange } = props;
-export const ModelSelector = forwardRef(
- function ModelSelectorComponent(props, ref) {
- const instance = useInject(ViewInstance);
- const modelProviderManager = useInject(LLMProviderManager);
+ const modelManager = useInject(LLMManager);
+ // const defaultModel = modelManager.defaultModel;
- const modelMeta = instance.agent?.llm;
+ const models = modelManager.models;
- const models = modelProviderManager.models;
+ const metaModels = models
+ .map((item) => item.toSingleMetas())
+ .filter((item) => !!item)
+ .flat() as ModelMeta[];
- const metaModels = models
- .map((item) => item.toSingleMetas())
- .filter((item) => !!item)
- .flat() as LLMMeta[];
+ useEffect(() => {
+ modelManager.updateModels();
+ }, [modelManager]);
- useEffect(() => {
- modelProviderManager.updateProviders();
- }, [modelProviderManager]);
+ const currentModel = metaModels.find((item) => value && toKey(item) === toKey(value));
- const currentModel = metaModels.find(
- (item) => modelMeta && toKey(item) === toKey(modelMeta),
- );
+ const temperature = value?.temperature;
- return (
-
-
-
-
-
-
-
-
-
-
- }
+ return (
+
+
triggerNode.parentElement}
+ arrow={false}
+ placement="bottomLeft"
+ title="模型设置"
+ trigger="click"
+ content={
+
+
+
+
+
+ {
+ if (value) {
+ onChange?.({
+ ...value,
+ temperature: v,
+ });
+ }
+ }}
+ value={temperature === undefined ? 1 : Number(temperature)}
+ />
+
+
+
+ }
+ >
+ }
>
- }
- >
- {currentModel ? : null}
-
-
-
- );
- },
-);
+ {currentModel ? : null}
+
+
+
+ );
+});
diff --git a/web-apps/ui/src/views/agent-config/knowledge-modal/modal.tsx b/web-apps/ui/src/views/agent-config/knowledge-modal/modal.tsx
index f741115..e75c7ac 100644
--- a/web-apps/ui/src/views/agent-config/knowledge-modal/modal.tsx
+++ b/web-apps/ui/src/views/agent-config/knowledge-modal/modal.tsx
@@ -1,22 +1,26 @@
import type { ModalItem, ModalItemProps } from '@difizen/mana-app';
-import { useInject, useMount } from '@difizen/mana-app';
+import { useInject, useMount, useObserve } from '@difizen/mana-app';
import type { TableColumnsType } from 'antd';
import { Modal, Table } from 'antd';
import type { TableRowSelection } from 'antd/es/table/interface.js';
import { useMemo } from 'react';
-import type { AgentModel } from '@/modules/agent/protocol.js';
import { KnowledgeIcon } from '@/modules/knowledge/knowledge-icon.js';
import { KnowledgeSpace } from '@/modules/knowledge/knowledge-space.js';
import type { KnowledgeModelOption } from '@/modules/knowledge/protocol.js';
+
import { KnowledgeModalId } from '../protocol.js';
export const KnowledgeModalComponent = (
- props: ModalItemProps<{ agent: AgentModel }>,
+ props: ModalItemProps<{
+ dataProvider: { knowledge: KnowledgeModelOption[] };
+ onChange: (knowledge: KnowledgeModelOption[]) => void;
+ }>,
) => {
const knowledgeSpace = useInject(KnowledgeSpace);
const { visible, close } = props;
- const { agent } = props.data || {};
+ const { onChange } = props.data || {};
+ const dataProvider = useObserve(props.data?.dataProvider);
const columns = useMemo(() => {
const c: TableColumnsType
= [
@@ -53,21 +57,23 @@ export const KnowledgeModalComponent = (
knowledgeSpace.update();
});
- if (!agent) {
- return null;
- }
-
const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
- agent.knowledge = knowledgeSpace.list
- .filter((item) => newSelectedRowKeys.includes(item.id))
- .map((item) => item.toMeta());
+ onChange?.(
+ knowledgeSpace.list
+ .filter((item) => newSelectedRowKeys.includes(item.id))
+ .map((item) => item.toMeta()),
+ );
};
const rowSelection: TableRowSelection = {
- selectedRowKeys: (agent.knowledge || []).map((item) => item.id),
+ selectedRowKeys: (dataProvider?.knowledge || []).map((item) => item.id),
onChange: onSelectChange,
};
+ if (!dataProvider?.knowledge) {
+ return null;
+ }
+
return (
(
}),
onAdd: () => {
if (instance.agent) {
- modalService.openModal(KnowledgeModal, { agent: instance.agent });
+ modalService.openModal(KnowledgeModal, {
+ dataProvider: instance.agent,
+ onChange: (knowledges: KnowledgeModelOption[]) => {
+ instance.agent.knowledge = [...knowledges];
+ },
+ });
}
},
onDelete: (item) => {
diff --git a/web-apps/ui/src/views/agent-flow/agent-flow-view.tsx b/web-apps/ui/src/views/agent-flow/agent-flow-view.tsx
index ea735c3..3a5de0f 100644
--- a/web-apps/ui/src/views/agent-flow/agent-flow-view.tsx
+++ b/web-apps/ui/src/views/agent-flow/agent-flow-view.tsx
@@ -1,19 +1,238 @@
-import { FlowWithPanel } from '@difizen/magent-flow';
+import { DeleteOutlined } from '@ant-design/icons';
+import type { BasicSchema } from '@difizen/magent-flow';
+import {
+ FlowWithPanel,
+ useFlowStore,
+ useKnowledgeStore,
+ useModelStore,
+} from '@difizen/magent-flow';
import { BaseView, inject, prop, view, ViewOption, transient } from '@difizen/mana-app';
-import { forwardRef } from 'react';
-
-import { AgentManager } from '@/modules/agent/agent-manager.js';
-import type { AgentModel } from '@/modules/agent/protocol.js';
+import { Button } from 'antd';
+import { forwardRef, useEffect, useState } from 'react';
+import { AgentManager } from '../../modules/agent/index.js';
+import type { AgentModel, LLMMeta } from '../../modules/agent/index.js';
import './index.less';
+import type { KnowledgeModelOption } from '../../modules/knowledge/protocol.js';
+import { ModelSelector } from '../agent-config/components/model-selector/index.js';
+import {
+ KnowledgeModal,
+ KnowledgeModalComponent,
+} from '../agent-config/knowledge-modal/modal.js';
+
+import { Toolbar } from './toolbar.js';
const viewId = 'magent-agent-flow';
const AgentFlowComponent = forwardRef(
function AgentConfigViewComponent(props, ref) {
+ const { setModelSelector } = useModelStore();
+ const { setKnowledgeSelector } = useKnowledgeStore();
+ const { setNode } = useFlowStore();
+
+ useEffect(() => {
+ // 注册 flow 中模型选择
+ const Ele = ({
+ nodeId,
+ llmParam,
+ }: {
+ nodeId: string;
+ llmParam: BasicSchema[];
+ }) => {
+ const onChange = (val: LLMMeta) => {
+ setNode(nodeId, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ config: {
+ ...(old.data.config as Record),
+ inputs: {
+ ...old.data.config.inputs,
+ llm_param: [
+ llmParam.find((p) => p.name === 'prompt'),
+ {
+ name: 'id',
+ type: 'string',
+ value: {
+ type: 'value',
+ content: val.id,
+ },
+ },
+ {
+ name: 'temperature',
+ type: 'string',
+ value: {
+ type: 'value',
+ content: val.temperature,
+ },
+ },
+ {
+ name: 'model_name',
+ type: 'string',
+ value: {
+ type: 'value',
+ content: val.model_name,
+ },
+ },
+ ],
+ },
+ },
+ },
+ }));
+ };
+ const value: LLMMeta = {
+ id: llmParam.find((p) => p.name === 'id')?.value?.content as string,
+ temperature: Number(
+ llmParam.find((p) => p.name === 'temperature')?.value?.content as string,
+ ),
+ nickname: '',
+ model_name: [
+ llmParam.find((p) => p.name === 'model_name')?.value?.content as string,
+ ],
+ };
+ return (
+ <>
+
+ >
+ );
+ };
+ setModelSelector(Ele as any);
+ const Ele2 = ({
+ nodeId,
+ knowledgeParam,
+ }: {
+ nodeId: string;
+ knowledgeParam: BasicSchema[];
+ }) => {
+ const [knowledgeModal, setKnowledgeModal] = useState(false);
+
+ const onChange = (val: any) => {
+ setNode(nodeId, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ config: {
+ ...(old.data.config as Record),
+ inputs: {
+ ...old.data.config.inputs,
+ knowledge_param: [
+ {
+ name: 'top_k',
+ type: 'string',
+ value: {
+ type: 'value',
+ content: val.top_k,
+ },
+ },
+ {
+ name: 'id',
+ type: 'string',
+ value: {
+ type: 'value',
+ content: val.id,
+ },
+ },
+ ],
+ },
+ },
+ },
+ }));
+ };
+
+ const value: any = {
+ knowledge: (
+ (knowledgeParam.find((p) => p.name === 'id')?.value?.content ||
+ []) as string[]
+ ).map((k) => ({ id: k })),
+ top_k: knowledgeParam.find((p) => p.name === 'top_k')?.value
+ ?.content as string,
+ };
+
+ return (
+ <>
+ setKnowledgeModal(false)}
+ data={{
+ dataProvider: { knowledge: [...value.knowledge] },
+ onChange: (knowledges: KnowledgeModelOption[]) => {
+ onChange({
+ id: [...knowledges.map((k) => k.id)],
+ top_k: value.top_k,
+ });
+ },
+ }}
+ modalItem={KnowledgeModal}
+ />
+
+
+ {value.knowledge.map((k) => (
+
+
{k.id}
+
}
+ onClick={() => {
+ onChange({
+ id: value.knowledge
+ .filter((kn) => kn.id !== k.id)
+ .map((kn) => kn.id),
+ });
+ }}
+ >
+
+ ))}
+
+
{
+ e.stopPropagation();
+
+ setKnowledgeModal(true);
+ }}
+ >
+ 添加知识库
+
+
+ >
+ );
+ };
+ setKnowledgeSelector(Ele2 as any);
+ }, []);
+
return (
-
+
+ }
+ />
);
},
diff --git a/web-apps/ui/src/views/agent-flow/toolbar.tsx b/web-apps/ui/src/views/agent-flow/toolbar.tsx
new file mode 100644
index 0000000..0021bf5
--- /dev/null
+++ b/web-apps/ui/src/views/agent-flow/toolbar.tsx
@@ -0,0 +1,28 @@
+import { useFlowStore } from '@difizen/magent-flow';
+import { Button } from 'antd';
+import classNames from 'classnames';
+import yaml from 'js-yaml';
+import React from 'react';
+
+export const Toolbar = (props: { classname?: string; style?: React.CSSProperties }) => {
+ const { classname, style } = props;
+ const { getFlow } = useFlowStore();
+ return (
+
+ 运行
+ {
+ const flow = getFlow();
+ const save_yaml = yaml.dump(flow);
+ console.log('🚀 ~ Toolbar ~ flow:', save_yaml);
+ }}
+ >
+ 保存
+
+
+ );
+};
diff --git a/web-packages/magent-flow/package.json b/web-packages/magent-flow/package.json
index 3a1285b..1ce039c 100644
--- a/web-packages/magent-flow/package.json
+++ b/web-packages/magent-flow/package.json
@@ -71,6 +71,7 @@
},
"devDependencies": {
"@types/classnames": "^2.3.1",
+ "@types/js-yaml": "^4.0.9",
"@types/lodash": "^4.17.7",
"@types/react": "^18.2.25",
"@types/uuid": "^10.0.0",
diff --git a/web-packages/magent-flow/src/RefForm/index.tsx b/web-packages/magent-flow/src/RefForm/index.tsx
index b7b66a1..a9bbaf6 100644
--- a/web-packages/magent-flow/src/RefForm/index.tsx
+++ b/web-packages/magent-flow/src/RefForm/index.tsx
@@ -160,7 +160,6 @@ const Parameter = (props: {
className="noflow nowheel nopan nodelete nodrag"
options={options}
onChange={(v) => {
- console.log('🚀 ~ v:', v);
setValue((s) => {
return {
...s,
diff --git a/web-packages/magent-flow/src/components/Flow/index.tsx b/web-packages/magent-flow/src/components/Flow/index.tsx
index 55cb297..6aa46fb 100644
--- a/web-packages/magent-flow/src/components/Flow/index.tsx
+++ b/web-packages/magent-flow/src/components/Flow/index.tsx
@@ -32,10 +32,11 @@ interface FlowProps {
miniMap?: boolean;
classNames?: string;
nodeTypes: any;
+ toolbar: React.ReactNode;
}
function Flow(props: FlowProps) {
- const { miniMap = true, classNames, nodeTypes } = props;
+ const { miniMap = true, classNames, nodeTypes, toolbar } = props;
const position = useRef({ x: 0, y: 0 });
const [lastSelection, setLastSelection] = useState(
null,
@@ -161,7 +162,7 @@ function Flow(props: FlowProps) {
>
{miniMap && }
-
+ {toolbar}
);
diff --git a/web-packages/magent-flow/src/components/FlowWithPanel/index.tsx b/web-packages/magent-flow/src/components/FlowWithPanel/index.tsx
index afd719d..e68272d 100644
--- a/web-packages/magent-flow/src/components/FlowWithPanel/index.tsx
+++ b/web-packages/magent-flow/src/components/FlowWithPanel/index.tsx
@@ -67,34 +67,39 @@ const yamlContent = `
llm_param:
- type: string
name: id
- value: qwen_llm
+ value:
+ type: value
+ content: qwen_llm
- type: string
name: model_name
- value: qwen-max
+ value:
+ content: qwen-max
+ type: value
- type: string
name: temperature
- value: '0.7'
+ value:
+ content: '0.7'
+ type: value
- type: string
- prompt:
- type: string
- value:
- type: value
- content: |
- 你是一位精通信息分析的ai助手。你的目标是使用中文结合查询的背景信息及你所拥有的知识回答用户提出的问题。
- 你需要遵守的规则是:
- 1. 必须使用中文结合查询的背景信息结合你所拥有的知识回答用户提出的问题。
- 2. 结构化答案生成,必要时通过空行提升阅读体验。
- 3. 不采用背景信息中的错误信息。
- 4. 要考虑答案和问题的相关性,不做对问题没有帮助的回答。
- 5. 详尽回答问题,重点突出,不过多花哨词藻。
- 6. 不说模糊的推测。
- 7. 尽量多的使用数值类信息。
+ name: prompt
+ value:
+ type: value
+ content: |
+ 你是一位精通信息分析的ai助手。你的目标是使用中文结合查询的背景信息及你所拥有的知识回答用户提出的问题。
+ 你需要遵守的规则是:
+ 1. 必须使用中文结合查询的背景信息结合你所拥有的知识回答用户提出的问题。
+ 2. 结构化答案生成,必要时通过空行提升阅读体验。
+ 3. 不采用背景信息中的错误信息。
+ 4. 要考虑答案和问题的相关性,不做对问题没有帮助的回答。
+ 5. 详尽回答问题,重点突出,不过多花哨词藻。
+ 6. 不说模糊的推测。
+ 7. 尽量多的使用数值类信息。
- 背景信息是:
- {{background}}
+ 背景信息是:
+ {{background}}
- 开始!
- 需要回答的问题是: {{input}}
+ 开始!
+ 需要回答的问题是: {{input}}
outputs:
- type: string
name: output
@@ -107,7 +112,6 @@ const yamlContent = `
knowledge_param:
- type: string
name: id
- value: demo_knowledge
- type: string
name: top_k
value:
@@ -200,7 +204,8 @@ const nodeTypes = {
[NodeTypeEnum.Agent]: AgentNode,
};
-export const FlowWithPanel = () => {
+export const FlowWithPanel = (props: { toolbar?: React.ReactNode }) => {
+ const { toolbar } = props;
const yaml_data = yaml.load(yamlContent);
(yaml_data as Record[]).forEach((item) => {
NodeSchemaParser(item);
@@ -226,7 +231,7 @@ export const FlowWithPanel = () => {
-
+
);
diff --git a/web-packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx b/web-packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx
index fe55f48..b7c8376 100644
--- a/web-packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx
+++ b/web-packages/magent-flow/src/components/Node/KnowledgeNode/index.tsx
@@ -4,7 +4,7 @@ import { Button, Modal } from 'antd';
import { CollapseWrapper } from '@/components/AIBasic/CollapseWrapper/index.js';
import { OutputVariable } from '@/components/AIBasic/OutputVariableTree/OutputVariable/index.js';
import { ReferenceForm } from '@/components/ReferenceForm/index.js';
-import type { NodeDataType } from '@/interfaces/flow.js';
+import type { BasicSchema, NodeDataType } from '@/interfaces/flow.js';
import { useFlowStore } from '@/stores/useFlowStore.js';
import { useKnowledgeStore } from '@/stores/useKnowledgeStore.js';
@@ -22,9 +22,11 @@ export const KnowledgeNode = (props: Props) => {
// const { config } = data;
const { findUpstreamNodes, setNode } = useFlowStore();
- const { knowledges } = useKnowledgeStore();
+ const { KnowledgeSelector } = useKnowledgeStore();
const upstreamNode = findUpstreamNodes(data.id.toString());
+ const knowledge_param = data.config?.inputs?.knowledge_param as BasicSchema[];
+
return (
@@ -50,31 +52,16 @@ export const KnowledgeNode = (props: Props) => {
/>
- 知识库配置
- }
- className="ml-2"
- onClick={(e) => {
- e.stopPropagation();
- Modal.confirm({
- title: '导入知识库',
- icon: null,
- content: <>>,
- onOk: () => {
- console.log('knowledges', knowledges);
- },
- });
- }}
- >
- 导入
-
-
+ label={'知识库配置'}
+ content={
+ <>
+ {KnowledgeSelector !== null ? (
+
+ ) : (
+ <>知识库配置>
+ )}
+ >
}
- content={<>List>}
/>
{
const { data } = props;
const { findUpstreamNodes, setNode } = useFlowStore();
+ const { ModelSelector, modelOptions, modelConfig } = useModelStore();
+
const upstreamNode = findUpstreamNodes(data.id.toString());
- const { models, modelConfig } = useModelStore();
+ const llm_param = data.config?.inputs?.llm_param as BasicSchema[];
return (
@@ -36,31 +38,35 @@ export const LLMNode = (props: Props) => {
className="mb-3"
label={'模型配置'}
content={
-
-
({
- label: model.name,
- value: model.id,
- }))}
- className="w-full mr-2"
- />
-
- {Object.entries(modelConfig).map(([key, value]) => (
- <>
- {key}
- >
- ))}
-
- }
- >
- {Object.entries(modelConfig).length > 0 && (
- }>
- )}
-
-
+ ModelSelector !== null ? (
+
+ ) : (
+
+
({
+ label: model.name,
+ value: model.id,
+ }))}
+ className="w-full mr-2"
+ />
+
+ {Object.entries(modelConfig).map(([key, value]) => (
+ <>
+ {key}
+ >
+ ))}
+
+ }
+ >
+ {Object.entries(modelConfig).length > 0 && (
+
}>
+ )}
+
+
+ )
}
/>
{/* Part2 Ref Form */}
@@ -68,7 +74,7 @@ export const LLMNode = (props: Props) => {
label="输入变量"
dynamic
nodes={[...(upstreamNode as any)]}
- value={[...(data.config?.inputs?.input_param || [])]}
+ value={[...(data.config.inputs?.input_param || [])]}
onChange={(values) => {
setNode(data.id, (old) => ({
...old,
@@ -93,7 +99,7 @@ export const LLMNode = (props: Props) => {
item.name === 'prompt')?.value
?.content as string) || ''
}
placeholder="请输入 Prompt"
@@ -106,10 +112,17 @@ export const LLMNode = (props: Props) => {
...(old.data.config as Record),
inputs: {
...old.data.config.inputs,
- prompt: {
- ...old.data.config.inputs.prompt,
- value: values,
- },
+ llm_param: [
+ ...llm_param,
+ {
+ name: 'prompt',
+ type: 'string',
+ value: {
+ type: 'value',
+ content: values,
+ },
+ },
+ ],
},
},
},
diff --git a/web-packages/magent-flow/src/index.ts b/web-packages/magent-flow/src/index.ts
index e6d7f38..bd969b6 100644
--- a/web-packages/magent-flow/src/index.ts
+++ b/web-packages/magent-flow/src/index.ts
@@ -3,6 +3,11 @@ export { FlowWithPanel } from './components/FlowWithPanel/index.js';
export { FormSchema } from './FormSchema/index.js';
export { RefForm } from './RefForm/index.js';
export { SchemaConfigForm } from './SchemaConfigForm/index.js';
+export { useFlowStore } from './stores/useFlowStore.js';
+export { useModelStore } from './stores/useModelStore.js';
+export { useKnowledgeStore } from './stores/useKnowledgeStore.js';
export { StartNode } from './spec/node.js';
export * from './utils/index.js';
import './tailwind.out.css';
+
+export * from './interfaces/flow.js';
diff --git a/web-packages/magent-flow/src/stores/useFlowStore.ts b/web-packages/magent-flow/src/stores/useFlowStore.ts
index d9c0158..037c32d 100644
--- a/web-packages/magent-flow/src/stores/useFlowStore.ts
+++ b/web-packages/magent-flow/src/stores/useFlowStore.ts
@@ -56,7 +56,7 @@ export const useFlowStore = create((set, get) => {
targetNode: string,
): Node[] => {
const adjList: AdjacencyList = {};
- console.log('🚀 ~ nodes.forEach ~ nodes:', nodes);
+
nodes.forEach((node) => {
adjList[node.id] = [];
});
diff --git a/web-packages/magent-flow/src/stores/useKnowledgeStore.ts b/web-packages/magent-flow/src/stores/useKnowledgeStore.ts
index 908657a..7c9c063 100644
--- a/web-packages/magent-flow/src/stores/useKnowledgeStore.ts
+++ b/web-packages/magent-flow/src/stores/useKnowledgeStore.ts
@@ -1,19 +1,25 @@
import { create } from 'zustand';
+import type { BasicSchema } from '@/interfaces/flow.js';
+
export interface Knowledge {
name: string;
id: string;
description?: string;
}
+export type KnowledgeSelectorNode =
+ | ((props: { nodeId: string; knowledgeParam: BasicSchema[] }) => React.ReactNode)
+ | null;
+
export interface KnowledgeStoreType {
- knowledges: Knowledge[];
- setKnowledges: (knowledges: Knowledge[]) => void;
+ KnowledgeSelector: KnowledgeSelectorNode | null;
+ setKnowledgeSelector: (KnowledgeSelector: KnowledgeSelectorNode) => void;
}
-export const useKnowledgeStore = create((set, get) => ({
- knowledges: [],
- setKnowledges: (knowledges: Knowledge[]) => {
- set({ knowledges });
+export const useKnowledgeStore = create((set) => ({
+ KnowledgeSelector: null,
+ setKnowledgeSelector: (KnowledgeSelector) => {
+ set({ KnowledgeSelector });
},
}));
diff --git a/web-packages/magent-flow/src/stores/useModelStore.ts b/web-packages/magent-flow/src/stores/useModelStore.ts
index fa9a09e..6326ef6 100644
--- a/web-packages/magent-flow/src/stores/useModelStore.ts
+++ b/web-packages/magent-flow/src/stores/useModelStore.ts
@@ -1,5 +1,9 @@
+import type React from 'react';
import { create } from 'zustand';
+import type { BasicSchema } from '@/interfaces/flow.js';
+
+// 注册 模型选择和配置组件 提供onChange事件
export interface Model {
id: string;
name: string;
@@ -14,17 +18,28 @@ export interface ModelConfig {
[key: string]: number | undefined;
}
+export type ModelSelectorNode =
+ | ((props: { nodeId: string; llmParam: BasicSchema[] }) => React.ReactNode)
+ | null;
+
export interface ModelStoreType {
- models: Model[];
- setModels: (models: Model[]) => void;
+ ModelSelector: ModelSelectorNode;
+ setModelSelector: (ModelSelector: ModelSelectorNode) => void;
+ modelOptions: Model[];
+ setModelOptions: (models: Model[]) => void;
modelConfig: ModelConfig;
setModelConfig: (config: ModelConfig) => void;
}
-export const useModelStore = create((set, get) => ({
- models: [],
- setModels: (models: Model[]) => {
- set({ models });
+export const useModelStore = create((set) => ({
+ ModelSelector: null,
+ setModelSelector: (ModelSelector) => {
+ set({ ModelSelector });
+ },
+
+ modelOptions: [],
+ setModelOptions: (modelOptions: Model[]) => {
+ set({ modelOptions });
},
modelConfig: {},
setModelConfig: (modelConfig: ModelConfig) => {
diff --git a/web-packages/magent-flow/tailwind.config.js b/web-packages/magent-flow/tailwind.config.js
index 9cfd53f..87a3fba 100644
--- a/web-packages/magent-flow/tailwind.config.js
+++ b/web-packages/magent-flow/tailwind.config.js
@@ -1,7 +1,12 @@
-module.exports = {
+/** @type {import('tailwindcss').Config} */
+export default {
content: [
'./src/pages/**/*.tsx',
'./src/components/**/*.tsx',
'./src/layouts/**/*.tsx',
],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
};
diff --git a/web/packages/magent-flow/src/components/Toolbar/index.tsx b/web/packages/magent-flow/src/components/Toolbar/index.tsx
deleted file mode 100644
index bd7b05a..0000000
--- a/web/packages/magent-flow/src/components/Toolbar/index.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { Button } from 'antd';
-
-import { useFlowStore } from '@/stores/useFlowStore.js';
-import { classNames } from '@/utils/basic.js';
-
-export const Toolbar = (props: { classname?: string }) => {
- const { classname } = props;
- const { getFlow } = useFlowStore();
- return (
-
- 运行
- {
- const flow = getFlow();
- console.log('🚀 ~ Toolbar ~ flow:', flow);
- }}
- >
- 保存
-
-
- );
-};
diff --git a/web/ui/src/views/agent-config/components/decimal-step/index.tsx b/web/ui/src/views/agent-config/components/decimal-step/index.tsx
new file mode 100644
index 0000000..17da4a9
--- /dev/null
+++ b/web/ui/src/views/agent-config/components/decimal-step/index.tsx
@@ -0,0 +1,33 @@
+import { InputNumber, Slider } from 'antd';
+
+export const DecimalStep = (props: {
+ min: number;
+ max: number;
+ step: number;
+ value: number;
+ onChange: (value: number) => void;
+}) => {
+ const { min, max, step, value, onChange } = props;
+
+ return (
+
+
+
+
+
+ );
+};
From d1a3b7accb66548589ad7176ecc4229b332f0a57 Mon Sep 17 00:00:00 2001
From: "yukun.wyk"
Date: Thu, 29 Aug 2024 00:51:34 +0800
Subject: [PATCH 16/78] fix(ui): migrate util api
---
packages/magent-ui/src/magent_ui/routers/common/router.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/magent-ui/src/magent_ui/routers/common/router.py b/packages/magent-ui/src/magent_ui/routers/common/router.py
index 81d912f..88c3a12 100644
--- a/packages/magent-ui/src/magent_ui/routers/common/router.py
+++ b/packages/magent-ui/src/magent_ui/routers/common/router.py
@@ -3,7 +3,7 @@
import json
from typing import AsyncIterable, List
from fastapi import APIRouter
-import agentuniverse_product.service.util.product_util as util
+from agentuniverse_product.service.util.agent_util import is_component_id_unique
router = APIRouter()
common_router = router
@@ -11,6 +11,6 @@
@router.get("/common/is_id_unique", response_model=bool)
async def is_id_unique(id:str, type:str):
- result = util.is_id_unique(id,type)
+ result = is_component_id_unique(id,type)
return result
From b418dd7bfe540032220cdaa59ea8fabc5b4911f7 Mon Sep 17 00:00:00 2001
From: "yukun.wyk"
Date: Thu, 29 Aug 2024 00:57:49 +0800
Subject: [PATCH 17/78] fix(ui): remaining issues with code merging
---
.../components/decimal-step/index.tsx | 0
.../components/model-selector/index.tsx | 29 +++++++++----------
.../src/views/agent-flow/agent-flow-view.tsx | 18 +++++++-----
web-apps/ui/src/views/agents/modal/create.tsx | 3 ++
.../src/components/ConditionForm/index.tsx | 20 ++++++++-----
5 files changed, 38 insertions(+), 32 deletions(-)
rename {web => web-apps}/ui/src/views/agent-config/components/decimal-step/index.tsx (100%)
rename {web/packages => web-packages}/magent-flow/src/components/ConditionForm/index.tsx (81%)
diff --git a/web/ui/src/views/agent-config/components/decimal-step/index.tsx b/web-apps/ui/src/views/agent-config/components/decimal-step/index.tsx
similarity index 100%
rename from web/ui/src/views/agent-config/components/decimal-step/index.tsx
rename to web-apps/ui/src/views/agent-config/components/decimal-step/index.tsx
diff --git a/web-apps/ui/src/views/agent-config/components/model-selector/index.tsx b/web-apps/ui/src/views/agent-config/components/model-selector/index.tsx
index d7b263f..042ba2f 100644
--- a/web-apps/ui/src/views/agent-config/components/model-selector/index.tsx
+++ b/web-apps/ui/src/views/agent-config/components/model-selector/index.tsx
@@ -1,22 +1,13 @@
import { CaretDownOutlined } from '@ant-design/icons';
-import { ViewInstance, useInject, useObserve } from '@difizen/mana-app';
-import type { SliderSingleProps } from 'antd';
-import { Button, Form, Select, Popover, Avatar, Slider } from 'antd';
-import type { FC } from 'react';
+import { useInject } from '@difizen/mana-app';
+import { Button, Form, Select, Popover, Avatar } from 'antd';
import { forwardRef, useEffect } from 'react';
-import type { LLMProvider } from '@/modules/model/llm-model.js';
import { LLMProviderManager } from '@/modules/model/llm-provider-manager.js';
import { LLMIcon } from '@/modules/model/model-icon/index.js';
import type { LLMMeta } from '@/modules/model/protocol.js';
-import type { AgentConfigView } from '../../view.js';
-
-import './index.less';
-import { LLMManager } from '../../../../modules/model/llm-manager.js';
import { DecimalStep } from '../decimal-step/index.js';
-
-import { DefaultLogo, OpenAILogo, QwenLogo } from './logos.js';
import './index.less';
const clsPrefix = 'agent-config-model-selector';
@@ -43,7 +34,13 @@ const toKey = (model?: LLMMeta) => {
return model.id + model.model_name[0];
};
-export const ModelSelector = forwardRef(function ModelSelectorComponent(
+export const ModelSelector = forwardRef<
+ HTMLDivElement,
+ {
+ value?: LLMMeta;
+ onChange?: (value: LLMMeta) => void;
+ }
+>(function ModelSelectorComponent(
props: {
value?: LLMMeta;
onChange?: (value: LLMMeta) => void;
@@ -52,7 +49,7 @@ export const ModelSelector = forwardRef(function ModelSelectorCo
) {
const { value, onChange } = props;
- const modelManager = useInject(LLMManager);
+ const modelManager = useInject(LLMProviderManager);
// const defaultModel = modelManager.defaultModel;
const models = modelManager.models;
@@ -60,10 +57,10 @@ export const ModelSelector = forwardRef(function ModelSelectorCo
const metaModels = models
.map((item) => item.toSingleMetas())
.filter((item) => !!item)
- .flat() as ModelMeta[];
+ .flat() as LLMMeta[];
useEffect(() => {
- modelManager.updateModels();
+ modelManager.updateProviders();
}, [modelManager]);
const currentModel = metaModels.find((item) => value && toKey(item) === toKey(value));
@@ -74,7 +71,7 @@ export const ModelSelector = forwardRef(function ModelSelectorCo
triggerNode.parentElement}
+ getPopupContainer={(triggerNode) => triggerNode.parentElement!}
arrow={false}
placement="bottomLeft"
title="模型设置"
diff --git a/web-apps/ui/src/views/agent-flow/agent-flow-view.tsx b/web-apps/ui/src/views/agent-flow/agent-flow-view.tsx
index 3a5de0f..28d936d 100644
--- a/web-apps/ui/src/views/agent-flow/agent-flow-view.tsx
+++ b/web-apps/ui/src/views/agent-flow/agent-flow-view.tsx
@@ -10,10 +10,12 @@ import { BaseView, inject, prop, view, ViewOption, transient } from '@difizen/ma
import { Button } from 'antd';
import { forwardRef, useEffect, useState } from 'react';
-import { AgentManager } from '../../modules/agent/index.js';
-import type { AgentModel, LLMMeta } from '../../modules/agent/index.js';
+import { AgentManager } from '@/modules/agent/agent-manager.js';
+import type { AgentModel } from '@/modules/agent/protocol.js';
import './index.less';
-import type { KnowledgeModelOption } from '../../modules/knowledge/protocol.js';
+import type { KnowledgeModelOption } from '@/modules/knowledge/protocol.js';
+import type { LLMMeta } from '@/modules/model/protocol.js';
+
import { ModelSelector } from '../agent-config/components/model-selector/index.js';
import {
KnowledgeModal,
@@ -45,9 +47,9 @@ const AgentFlowComponent = forwardRef(
data: {
...old.data,
config: {
- ...(old.data.config as Record),
+ ...(old.data['config'] as Record),
inputs: {
- ...old.data.config.inputs,
+ ...old.data['config'].inputs,
llm_param: [
llmParam.find((p) => p.name === 'prompt'),
{
@@ -112,9 +114,9 @@ const AgentFlowComponent = forwardRef(
data: {
...old.data,
config: {
- ...(old.data.config as Record),
+ ...(old.data['config'] as Record),
inputs: {
- ...old.data.config.inputs,
+ ...old.data['config'].inputs,
knowledge_param: [
{
name: 'top_k',
@@ -217,7 +219,7 @@ const AgentFlowComponent = forwardRef(
);
};
setKnowledgeSelector(Ele2 as any);
- }, []);
+ }, [setKnowledgeSelector, setModelSelector, setNode]);
return (
diff --git a/web-apps/ui/src/views/agents/modal/create.tsx b/web-apps/ui/src/views/agents/modal/create.tsx
index 03abb82..6f546ef 100644
--- a/web-apps/ui/src/views/agents/modal/create.tsx
+++ b/web-apps/ui/src/views/agents/modal/create.tsx
@@ -13,6 +13,7 @@ import { AgentTypeSelector } from '@/components/agent-type-selector/index.js';
import { AvatarUpload } from '@/components/avatar-upload/index.js';
import { AgentIcon } from '@/modules/agent/agent-icon.js';
import { AgentManager } from '@/modules/agent/agent-manager.js';
+import { AgentMarket } from '@/modules/agent/agent-market.js';
import { RequestHelper } from '@/modules/axios-client/request.js';
import { LLMManager } from '@/modules/model/llm-manager.js';
import { ModelSelector } from '@/modules/model/model-selector/index.js';
@@ -68,6 +69,7 @@ export const AgentModalComponent = (props: ModalItemProps
) => {
const agentManager = useInject(AgentManager);
const llmManager = useInject(LLMManager);
const req = useInject(RequestHelper);
+ const market = useInject(AgentMarket);
const { visible, close } = props;
const [form] = Form.useForm<{
id: string;
@@ -125,6 +127,7 @@ export const AgentModalComponent = (props: ModalItemProps) => {
const res = await agentManager.create(meta);
if (res.status === 200) {
close();
+ market.update();
history.push(
`/agent/${meta.id}/${meta.planner.id === 'workflow_planner' ? 'flow' : 'dev'}`,
);
diff --git a/web/packages/magent-flow/src/components/ConditionForm/index.tsx b/web-packages/magent-flow/src/components/ConditionForm/index.tsx
similarity index 81%
rename from web/packages/magent-flow/src/components/ConditionForm/index.tsx
rename to web-packages/magent-flow/src/components/ConditionForm/index.tsx
index 391dedd..3c35ddf 100644
--- a/web/packages/magent-flow/src/components/ConditionForm/index.tsx
+++ b/web-packages/magent-flow/src/components/ConditionForm/index.tsx
@@ -1,6 +1,6 @@
import { Form } from 'antd';
import type { DefaultOptionType } from 'antd/es/cascader';
-import { memo, useEffect } from 'react';
+import { useEffect } from 'react';
import type { ConditionBranch } from '@/interfaces/flow.js';
@@ -18,19 +18,23 @@ export const ConditionForm = (props: {
useEffect(() => {
form.setFieldsValue(value.conditions[0]);
- }, []);
+ }, [form, value.conditions]);
return (
From 052d01b554fb7fc89221a75088b038d156017a2f Mon Sep 17 00:00:00 2001
From: "yukun.wyk"
Date: Thu, 29 Aug 2024 03:20:46 +0800
Subject: [PATCH 18/78] feat(ui): project settings are more convenient for
development and optimized flow styles
---
web-apps/ui/config/config.ts | 5 +
.../src/views/agent-flow/agent-flow-view.tsx | 6 +-
.../ui/src/views/agent-flow/flow-dev-view.tsx | 10 +-
web-apps/ui/src/views/agent-flow/index.less | 14 +--
web-apps/ui/src/views/agent-flow/toolbar.tsx | 19 +++-
web-apps/ui/src/views/agents/view.tsx | 18 ++--
web-apps/ui/src/views/chat/view.tsx | 94 ++++++++-----------
web-packages/magent-flow/.eslintignore | 3 +
.../magent-flow/src/FormSchema/index.ts | 3 +-
.../magent-flow/src/RefForm/index.tsx | 5 +-
.../src/SchemaConfigForm/index.tsx | 6 +-
.../AIBasic/CascaderInNode/index.tsx | 2 +-
.../OutputVariable/index.tsx | 2 +-
.../plugins/component-picker-block/index.tsx | 2 +-
.../PromptEditor/plugins/update-block.tsx | 2 +-
.../components/AIBasic/SelectInNode/index.tsx | 2 +-
.../src/components/ConditionForm/index.tsx | 9 +-
.../magent-flow/src/components/Flow/index.tsx | 17 ++--
.../magent-flow/src/components/Flow/keys.ts | 2 +-
.../components/FlowWithPanel/icons/agent.svg | 1 +
.../components/FlowWithPanel/icons/end.svg | 1 +
.../components/FlowWithPanel/icons/ifelse.svg | 1 +
.../FlowWithPanel/icons/knowledge.svg | 1 +
.../components/FlowWithPanel/icons/llm.svg | 1 +
.../components/FlowWithPanel/icons/start.svg | 1 +
.../components/FlowWithPanel/icons/tool.svg | 1 +
.../src/components/FlowWithPanel/index.tsx | 34 +++++--
.../src/components/Node/AgentNode/index.tsx | 12 +--
.../src/components/Node/CommonNode/index.tsx | 2 +-
.../src/components/Node/EndNode/index.tsx | 10 +-
.../src/components/Node/IfElseNode/index.tsx | 8 +-
.../components/Node/KnowledgeNode/index.tsx | 12 +--
.../src/components/Node/LLMNode/index.tsx | 16 ++--
.../Node/NodeWrapper/Status/index.tsx | 2 +-
.../src/components/Node/NodeWrapper/index.tsx | 7 +-
.../src/components/Node/StartNode/index.tsx | 28 +++---
.../src/components/NodePanel/index.tsx | 5 +-
.../src/components/ReferenceForm/index.tsx | 2 +-
.../src/components/ReferenceSelect/index.tsx | 2 +-
.../src/components/VariableForm/index.tsx | 3 +-
.../magent-flow/src/interfaces/flow.ts | 10 +-
.../magent-flow/src/spec/node.test.ts | 3 -
web-packages/magent-flow/src/spec/node.ts | 4 +-
.../magent-flow/src/stores/useFlowStore.ts | 4 +-
.../src/stores/useKnowledgeStore.ts | 2 +-
.../magent-flow/src/stores/useModelStore.ts | 2 +-
.../src/stores/useShortcutsStore.ts | 2 +-
.../src/stores/useUndoRedoStore.ts | 1 -
web-packages/magent-flow/tsconfig.json | 2 +-
49 files changed, 211 insertions(+), 190 deletions(-)
create mode 100644 web-packages/magent-flow/.eslintignore
create mode 100644 web-packages/magent-flow/src/components/FlowWithPanel/icons/agent.svg
create mode 100644 web-packages/magent-flow/src/components/FlowWithPanel/icons/end.svg
create mode 100644 web-packages/magent-flow/src/components/FlowWithPanel/icons/ifelse.svg
create mode 100644 web-packages/magent-flow/src/components/FlowWithPanel/icons/knowledge.svg
create mode 100644 web-packages/magent-flow/src/components/FlowWithPanel/icons/llm.svg
create mode 100644 web-packages/magent-flow/src/components/FlowWithPanel/icons/start.svg
create mode 100644 web-packages/magent-flow/src/components/FlowWithPanel/icons/tool.svg
diff --git a/web-apps/ui/config/config.ts b/web-apps/ui/config/config.ts
index dcc0c35..87a4364 100644
--- a/web-apps/ui/config/config.ts
+++ b/web-apps/ui/config/config.ts
@@ -60,6 +60,11 @@ export default defineConfig({
jsMinifier: 'none',
alias: {
'@/modules': path.join(__dirname, '../src/modules'),
+ '@difizen/magent-flow': path.resolve(
+ __dirname,
+ '../../../web-packages/magent-flow/src',
+ ),
+ '@flow': path.resolve(__dirname, '../../../web-packages/magent-flow/src'),
},
favicons: ['/favicon.ico'],
});
diff --git a/web-apps/ui/src/views/agent-flow/agent-flow-view.tsx b/web-apps/ui/src/views/agent-flow/agent-flow-view.tsx
index 28d936d..71aca26 100644
--- a/web-apps/ui/src/views/agent-flow/agent-flow-view.tsx
+++ b/web-apps/ui/src/views/agent-flow/agent-flow-view.tsx
@@ -202,7 +202,7 @@ const AgentFlowComponent = forwardRef(
width: '100%',
border: '1px dashed #d9d9d9',
padding: '6px',
- zIndex,
+ // zIndex,
}}
type="link"
size="small"
@@ -240,7 +240,7 @@ const AgentFlowComponent = forwardRef(
},
);
-export interface AgentConfigViewOption {
+export interface AgentFlowViewOption {
agentId: string;
}
@transient()
@@ -252,7 +252,7 @@ export class AgentFlowView extends BaseView {
@prop() agent: AgentModel;
protected agentManager: AgentManager;
constructor(
- @inject(ViewOption) option: AgentConfigViewOption,
+ @inject(ViewOption) option: AgentFlowViewOption,
@inject(AgentManager) agentManager: AgentManager,
) {
super();
diff --git a/web-apps/ui/src/views/agent-flow/flow-dev-view.tsx b/web-apps/ui/src/views/agent-flow/flow-dev-view.tsx
index e2a6173..a92d326 100644
--- a/web-apps/ui/src/views/agent-flow/flow-dev-view.tsx
+++ b/web-apps/ui/src/views/agent-flow/flow-dev-view.tsx
@@ -64,14 +64,6 @@ const AgentFlowDevComponent = forwardRef(
{instance.chat && }
- {instance.hideChat && (
- }
- type="text"
- onClick={() => (instance.hideChat = false)}
- className={`${viewId}-layout-chat-switch`}
- >
- )}
);
@@ -82,7 +74,7 @@ const AgentFlowDevComponent = forwardRef(
@view(viewId)
export class AgentFlowDevView extends AgentView {
@prop()
- hideChat = false;
+ hideChat = true;
protected agentConfigManager: AgentConfigManager;
diff --git a/web-apps/ui/src/views/agent-flow/index.less b/web-apps/ui/src/views/agent-flow/index.less
index 5b11ca3..e8e2e9b 100644
--- a/web-apps/ui/src/views/agent-flow/index.less
+++ b/web-apps/ui/src/views/agent-flow/index.less
@@ -35,12 +35,12 @@
width: 55%;
.magent-agent-flow {
- > :first-child {
- > :first-child {
- box-shadow: var(--mana-ant-box-shadow-card);
- z-index: 1;
- }
- }
+ // > :first-child {
+ // > :first-child {
+ // box-shadow: var(--mana-ant-box-shadow-card);
+ // z-index: 1;
+ // }
+ // }
.react-flow {
background-color: var(--mana-ant-color-bg-layout);
@@ -53,7 +53,7 @@
min-width: 416px;
width: 416px;
background-color: var(--mana-color-bg-container);
- box-shadow: var(--mana-ant-box-shadow-card);
+ box-shadow: var(--mana-ant-box-shadow-drawer-left);
&-header {
padding: 0 24px 0 6px;
diff --git a/web-apps/ui/src/views/agent-flow/toolbar.tsx b/web-apps/ui/src/views/agent-flow/toolbar.tsx
index 0021bf5..6848847 100644
--- a/web-apps/ui/src/views/agent-flow/toolbar.tsx
+++ b/web-apps/ui/src/views/agent-flow/toolbar.tsx
@@ -1,24 +1,37 @@
+import { MessageOutlined, SaveOutlined } from '@ant-design/icons';
import { useFlowStore } from '@difizen/magent-flow';
+import { useInject } from '@difizen/mana-app';
import { Button } from 'antd';
import classNames from 'classnames';
import yaml from 'js-yaml';
import React from 'react';
+import { AgentFlowDevView } from './flow-dev-view.js';
+
export const Toolbar = (props: { classname?: string; style?: React.CSSProperties }) => {
const { classname, style } = props;
const { getFlow } = useFlowStore();
+ const flowDevView = useInject(AgentFlowDevView);
return (
-
运行
+ {flowDevView.hideChat && (
+
(flowDevView.hideChat = false)}
+ icon={}
+ >
+ 运行
+
+ )}
}
onClick={() => {
const flow = getFlow();
const save_yaml = yaml.dump(flow);
- console.log('🚀 ~ Toolbar ~ flow:', save_yaml);
+ // console.log('🚀 ~ Toolbar ~ flow:', save_yaml);
}}
>
保存
diff --git a/web-apps/ui/src/views/agents/view.tsx b/web-apps/ui/src/views/agents/view.tsx
index 29f6758..ce359df 100644
--- a/web-apps/ui/src/views/agents/view.tsx
+++ b/web-apps/ui/src/views/agents/view.tsx
@@ -16,6 +16,7 @@ import { history } from 'umi';
import './index.less';
import { AgentIcon } from '@/modules/agent/agent-icon.js';
import { AgentMarket } from '@/modules/agent/agent-market.js';
+import type { AgentModel } from '@/modules/agent/agent-model.js';
import { AgentCreateModal } from './modal/create.js';
@@ -42,14 +43,14 @@ const AgentsViewComponent = forwardRef
(
{
e.stopPropagation();
- instance.toDevPage(item.id);
+ instance.toDevPage(item);
}}
key="dev"
/>,
,
]}
onClick={() => {
- instance.toChatPage(item.id);
+ instance.toChatPage(item);
}}
>
{
- history.push(`/agent/${agentId}/chat`);
+ toChatPage = (agent: AgentModel) => {
+ history.push(`/agent/${agent.id}/chat`);
};
- toDevPage = (agentId: string) => {
- history.push(`/agent/${agentId}/dev`);
+ toDevPage = async (agent: AgentModel) => {
+ await agent.fetchInfo();
+ if (agent.planner?.id === 'workflow_planner') {
+ history.push(`/agent/${agent.id}/flow`);
+ } else {
+ history.push(`/agent/${agent.id}/dev`);
+ }
};
}
diff --git a/web-apps/ui/src/views/chat/view.tsx b/web-apps/ui/src/views/chat/view.tsx
index 7f2df96..1dc3ee7 100644
--- a/web-apps/ui/src/views/chat/view.tsx
+++ b/web-apps/ui/src/views/chat/view.tsx
@@ -5,6 +5,7 @@ import {
inject,
prop,
transient,
+ useObserve,
view,
ViewInstance,
ViewManager,
@@ -34,6 +35,25 @@ export interface ChatProps {
className?: string;
}
+export const OpeningSpeechMessage = (props: { agent: AgentModel | undefined }) => {
+ const agent = useObserve(props.agent);
+ return (
+
+
+
+
+
+
+
+
{agent?.openingSpeech}
+
+
+
+
+
+
+ );
+};
export function ChatComponent(props: ChatProps) {
const listRef = useRef(null);
const { className } = props;
@@ -46,63 +66,31 @@ export function ChatComponent(props: ChatProps) {
return (
- {instance.session && instance.session.messages.length ? (
-
-
-
-
-
-
-
-
-
-
{instance.agent?.openingSpeech}
-
-
-
-
-
-
- {instance.session?.messages.map((msg) => (
-
- ))}
- {instance.showToBottomBtn && (
-
instance.scrollToBottom()}
- className="chat-content-list-to-bottom"
- icon={}
- />
- )}
-
- ) : (
-
-
-
-
-
-
-
-
-
-
{instance.agent?.openingSpeech}
-
-
-
-
-
-
-
- )}
+
+ {instance.agent?.openingSpeech && (
+
+ )}
+ {instance.session && instance.session.messages.length ? (
+ <>
+ {instance.session?.messages.map((msg) => (
+
+ ))}
+ {instance.showToBottomBtn && (
+ instance.scrollToBottom()}
+ className="chat-content-list-to-bottom"
+ icon={}
+ />
+ )}
+ >
+ ) : (
+ <>>
+ )}
+
diff --git a/web-packages/magent-flow/.eslintignore b/web-packages/magent-flow/.eslintignore
new file mode 100644
index 0000000..e2dd15a
--- /dev/null
+++ b/web-packages/magent-flow/.eslintignore
@@ -0,0 +1,3 @@
+**/dist/**/*.js
+**/dist/**/*.cjs
+**/dist/**/*.mjs
diff --git a/web-packages/magent-flow/src/FormSchema/index.ts b/web-packages/magent-flow/src/FormSchema/index.ts
index 51adf0b..b7261ab 100644
--- a/web-packages/magent-flow/src/FormSchema/index.ts
+++ b/web-packages/magent-flow/src/FormSchema/index.ts
@@ -1,3 +1,4 @@
+import { UUID } from '@flow/spec/uuid.js';
import { message } from 'antd';
import type {
JSONSchema7,
@@ -5,8 +6,6 @@ import type {
JSONSchema7TypeName,
} from 'json-schema';
-import { UUID } from '@/spec/uuid.js';
-
export type OrderJSONSchema7 = JSONSchema7 & {
order: number;
};
diff --git a/web-packages/magent-flow/src/RefForm/index.tsx b/web-packages/magent-flow/src/RefForm/index.tsx
index a9bbaf6..c882865 100644
--- a/web-packages/magent-flow/src/RefForm/index.tsx
+++ b/web-packages/magent-flow/src/RefForm/index.tsx
@@ -1,9 +1,8 @@
import { CaretRightOutlined } from '@ant-design/icons';
+import type { NodeDataType } from '@flow/interfaces/flow.js';
import { Button, Cascader, Collapse, Flex, Input, Select, Space, theme } from 'antd';
import React, { useEffect, useMemo, useState } from 'react';
-import type { NodeDataType } from '@/interfaces/flow.js';
-
interface CascaderOptions {
value: string;
label: string;
@@ -26,7 +25,7 @@ const getCascaderOptions = (node: NodeDataType) => {
// 递归解析JSONSchema
const parseSchema = (schema: any): CascaderOptions[] => {
- console.log('🚀 ~ parseSchema ~ schema:', schema);
+ // console.log('🚀 ~ parseSchema ~ schema:', schema);
const parsedOptions: CascaderOptions[] = [];
for (const key in schema.properties) {
diff --git a/web-packages/magent-flow/src/SchemaConfigForm/index.tsx b/web-packages/magent-flow/src/SchemaConfigForm/index.tsx
index ad65dbf..6b975cf 100644
--- a/web-packages/magent-flow/src/SchemaConfigForm/index.tsx
+++ b/web-packages/magent-flow/src/SchemaConfigForm/index.tsx
@@ -7,13 +7,12 @@ import {
CaretRightOutlined,
MinusCircleOutlined,
} from '@ant-design/icons';
+import { variableTypeOptions } from '@flow/FormSchema/index.js';
+import type { FormSchema, OrderJSONSchema7 } from '@flow/FormSchema/index.js';
import { Card, Checkbox, Collapse, Form, Input, Select, Space, theme } from 'antd';
import type { JSONSchema7 } from 'json-schema';
import React, { useState } from 'react';
-import { variableTypeOptions } from '@/FormSchema/index.js';
-import type { FormSchema, OrderJSONSchema7 } from '@/FormSchema/index.js';
-
// import {
// FormSchema,
// OrderJSONSchema7,
@@ -164,7 +163,6 @@ export const SchemaConfigForm = (props: {
const propertiesKeys = Object.keys(schema.properties || {});
propertiesKeys.sort((a, b) => {
const p = schema.properties as { [key: string]: OrderJSONSchema7 };
- console.log(p[a].order, p[b]?.order, '==order');
return (p[a]?.order || 999) - (p[b]?.order || 999);
});
diff --git a/web-packages/magent-flow/src/components/AIBasic/CascaderInNode/index.tsx b/web-packages/magent-flow/src/components/AIBasic/CascaderInNode/index.tsx
index ae4b320..3c65e42 100644
--- a/web-packages/magent-flow/src/components/AIBasic/CascaderInNode/index.tsx
+++ b/web-packages/magent-flow/src/components/AIBasic/CascaderInNode/index.tsx
@@ -2,7 +2,7 @@ import type { CascaderProps } from 'antd';
import { Cascader } from 'antd';
import React from 'react';
-import { classNames } from '@/utils/index.js';
+import { classNames } from '@flow/utils/index.js';
export const CascaderInNode = (props: CascaderProps) => {
return (
diff --git a/web-packages/magent-flow/src/components/AIBasic/OutputVariableTree/OutputVariable/index.tsx b/web-packages/magent-flow/src/components/AIBasic/OutputVariableTree/OutputVariable/index.tsx
index fe2bfb2..6e7d41a 100644
--- a/web-packages/magent-flow/src/components/AIBasic/OutputVariableTree/OutputVariable/index.tsx
+++ b/web-packages/magent-flow/src/components/AIBasic/OutputVariableTree/OutputVariable/index.tsx
@@ -1,4 +1,4 @@
-import { capitalizeFirstLetter } from '@/utils/basic.js';
+import { capitalizeFirstLetter } from '@flow/utils/basic.js';
export const OutputVariable = (props: { name: string; type: string }) => {
const { name, type } = props;
diff --git a/web-packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/index.tsx b/web-packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/index.tsx
index 6d67748..c110db8 100644
--- a/web-packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/index.tsx
+++ b/web-packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/component-picker-block/index.tsx
@@ -6,7 +6,7 @@ import type { TextNode } from 'lexical';
import React, { Fragment, memo, useCallback, useState } from 'react';
import ReactDOM from 'react-dom';
-import { useEventEmitterContextContext } from '@/context/event-emitter.js';
+import { useEventEmitterContextContext } from '@flow/context/event-emitter.js';
import { useBasicTypeaheadTriggerMatch } from '../../hooks.js';
import type { ExternalToolBlockType, VariableBlockType } from '../../types.js';
diff --git a/web-packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/update-block.tsx b/web-packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/update-block.tsx
index e1d5a5c..1f8a36c 100644
--- a/web-packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/update-block.tsx
+++ b/web-packages/magent-flow/src/components/AIBasic/PromptEditor/plugins/update-block.tsx
@@ -1,7 +1,7 @@
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { $insertNodes } from 'lexical';
-import { useEventEmitterContextContext } from '@/context/event-emitter.js';
+import { useEventEmitterContextContext } from '@flow/context/event-emitter.js';
import { textToEditorState } from '../utils.js';
diff --git a/web-packages/magent-flow/src/components/AIBasic/SelectInNode/index.tsx b/web-packages/magent-flow/src/components/AIBasic/SelectInNode/index.tsx
index 26bebc4..de2a69f 100644
--- a/web-packages/magent-flow/src/components/AIBasic/SelectInNode/index.tsx
+++ b/web-packages/magent-flow/src/components/AIBasic/SelectInNode/index.tsx
@@ -1,7 +1,7 @@
import type { SelectProps } from 'antd';
import { Select } from 'antd';
-import { classNames } from '@/utils/index.js';
+import { classNames } from '@flow/utils/index.js';
export const SelectInNode = (props: SelectProps) => {
return (
diff --git a/web-packages/magent-flow/src/components/ConditionForm/index.tsx b/web-packages/magent-flow/src/components/ConditionForm/index.tsx
index 3c35ddf..19c9dd5 100644
--- a/web-packages/magent-flow/src/components/ConditionForm/index.tsx
+++ b/web-packages/magent-flow/src/components/ConditionForm/index.tsx
@@ -1,9 +1,8 @@
+import type { ConditionBranch } from '@flow/interfaces/flow.js';
import { Form } from 'antd';
import type { DefaultOptionType } from 'antd/es/cascader';
import { useEffect } from 'react';
-import type { ConditionBranch } from '@/interfaces/flow.js';
-
import { SelectInNode } from '../AIBasic/SelectInNode//index.js';
import { ReferenceSelect } from '../ReferenceSelect/index.js';
@@ -17,8 +16,10 @@ export const ConditionForm = (props: {
const compare = Form.useWatch('compare', form);
useEffect(() => {
- form.setFieldsValue(value.conditions[0]);
- }, [form, value.conditions]);
+ if (value) {
+ form.setFieldsValue(value.conditions[0]);
+ }
+ }, [form, value, value?.conditions]);
return (