From c14ea90c30ff0102d28349743780c90137fc220f Mon Sep 17 00:00:00 2001 From: ZhaoYongchao <152259278+ZhaoYongchao@users.noreply.github.com> Date: Thu, 20 Jun 2024 12:40:12 +0800 Subject: [PATCH 01/36] update create-callgent name Signed-off-by: ZhaoYongchao <152259278+ZhaoYongchao@users.noreply.github.com> --- src/components/user-as-a-service/create-callgent.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/user-as-a-service/create-callgent.tsx b/src/components/user-as-a-service/create-callgent.tsx index 5643a40..83594cd 100644 --- a/src/components/user-as-a-service/create-callgent.tsx +++ b/src/components/user-as-a-service/create-callgent.tsx @@ -32,7 +32,7 @@ const CreateCallgent = () => { + + + + )} + + ); +}; + +export default Popconfirm; \ No newline at end of file diff --git a/src/components/tree/endpoints.tsx b/src/components/tree/endpoints.tsx new file mode 100644 index 0000000..f087d13 --- /dev/null +++ b/src/components/tree/endpoints.tsx @@ -0,0 +1,75 @@ +import useIsBrowser from '@docusaurus/useIsBrowser'; +import React, { useState, useEffect } from 'react'; + +interface ModalFormProps { + initialData?: { adaptor: string; definition: string; host: string }; + onSubmit: (data: { adaptor: string; definition: string; host: string }) => void; + onClose: () => void; +} + +const Endpoints: React.FC = ({ initialData, onSubmit, onClose }) => { + const isBrowser = useIsBrowser(); + if (!isBrowser) { return null; } + const [adaptor, setAdaptor] = useState(initialData?.adaptor || 'RestAPI'); + const [definition, setDefinition] = useState(initialData?.definition || ''); + const [host, setHost] = useState(initialData?.host || ''); + + useEffect(() => { + if (initialData) { + setAdaptor(initialData.adaptor); + setDefinition(initialData.definition); + setHost(initialData.host); + } + }, [initialData]); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + onSubmit({ adaptor, definition, host }); + }; + + return ( +
+
+ + +
+
+ + +
+
+ {importState === true && Successfully {type}!} + {importState !== true && importState !== null && {importState}} +
+
+ + +
+
+ ); +}; + +export default Import; diff --git a/src/components/tree/index.scss b/src/components/tree/index.scss index b63ba9d..3f14d16 100644 --- a/src/components/tree/index.scss +++ b/src/components/tree/index.scss @@ -8,7 +8,7 @@ .popconfirm-container { position: relative; - display: inline-block; + right: -5px; .popconfirm { position: absolute; @@ -150,6 +150,7 @@ .modal-body .form-group { margin-bottom: 15px; + max-height: 200px; } .modal-body .form-group label { @@ -167,8 +168,8 @@ .modal-body .form-group select { width: 100%; padding: 8px; - border: 1px solid #ccc; - border-radius: 4px; + border: 1px solid var(--default); + border-radius: 3px; box-sizing: border-box; } @@ -260,8 +261,10 @@ } } -// Tree +/* Tree */ .tree-node { + width: 100%; + .children { margin-left: 20px; } @@ -270,46 +273,71 @@ display: flex; justify-content: space-between; align-items: center; + padding: 8px; + cursor: pointer; + border-radius: 4px; margin-bottom: 5px; + + &:hover { + background-color: var(--popconfirm-border-color); + + .toggle { + color: var(--ifm-color-primary-lightest); + } + } } - .node-left, - .node-right { - display: flex; - align-items: center; + .toggle { + width: 95%; + text-align: left; + background-color: transparent; + cursor: pointer; + border: none; + font-size: 16px; } .node-left { - cursor: pointer; - width: 100%; + display: flex; + align-items: center; + flex: 1; + overflow: hidden; } - .node-left:hover { - .toggle { - color: #007bff; - } + .icon-text { + display: flex; + align-items: center; + overflow: hidden; + flex: 1; } - .node-right div { - cursor: pointer; - margin: 0 3px; + .icon-text img { + margin-right: 8px; } - button { - border: none; + .left-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; + flex: 1; } - .toggle { - background-color: transparent; - cursor: pointer; - border: none; - font-size: 16px; + .node-right { + display: flex; + align-items: center; - &:hover { - color: #007bff; + div { + cursor: pointer; + margin: 0 3px; } } + button { + border: none; + background: none; + cursor: pointer; + } + .toggle_button { display: inline-block; width: 16px; @@ -322,5 +350,6 @@ .icon-text img { margin-right: 8px; + filter: var(--icon-invert); } } \ No newline at end of file diff --git a/src/components/tree/index.tsx b/src/components/tree/index.tsx index 76a044a..2b3c928 100644 --- a/src/components/tree/index.tsx +++ b/src/components/tree/index.tsx @@ -7,6 +7,7 @@ import { TreeNode } from './tree'; import Callgent from './callgent'; import Modal from './modal'; import './index.scss'; +import Import from './import'; const CascadingMenu: React.FC = ({ adaptorKey, name }: { adaptorKey?: string, name?: string }) => { const isBrowser = useIsBrowser(); @@ -17,20 +18,26 @@ const CascadingMenu: React.FC = ({ adaptorKey, name }: { adaptorKey?: string, na const [treeData, setTreeData] = useState([]); const handleAdd = (item: TreeNodeType, level: number) => { const { id } = item; - setModalData({ ...modalData, title: id, id, type: 'Create', endpoint: true, initialData: item }); + if (level === 2) { + setModalData({ ...modalData, title: id, id, type: 'Create', endpoint: true, initialData: item }); + } else if (level === 3) { + setModalData({ ...modalData, title: id, id, type: 'Import', import: true, initialData: item }); + } + }; const handleEdit = (item: TreeNodeType, level: number) => { const { id } = item; if (level === 1) { setModalData({ ...modalData, title: item.title, id, type: 'Edit', callgent: true, initialData: item }); - } else { + } else if (level === 3) { setModalData({ ...modalData, title: item.title, id, type: 'Edit', endpoint: true, initialData: item }); + } else if (level === 4) { + setModalData({ ...modalData, title: item.title, id, type: 'Edit', import: true, initialData: item }); } }; - const handleModalSubmit = (data: TreeNodeType) => { - if (modalData?.type === 'Create') { + if (modalData?.type === 'Create' || modalData?.type === 'Import') { const newTreeData = [...treeData]; const addNode = (nodes: TreeNodeType[]) => { nodes.forEach((node) => { @@ -69,8 +76,7 @@ const CascadingMenu: React.FC = ({ adaptorKey, name }: { adaptorKey?: string, na let enhancedNode = { ...node }; if (level === 1 || level === 3) { enhancedNode = { ...enhancedNode, edit: true, delete: true }; - } - if (level === 2) { + } else if (level === 2) { enhancedNode = { ...enhancedNode, add: true }; } if (node.children) { @@ -109,6 +115,16 @@ const CascadingMenu: React.FC = ({ adaptorKey, name }: { adaptorKey?: string, na onClose={() => setModalData({ ...modalData, endpoint: false })} /> + setModalData({ ...modalData, import: false })} title={modalData?.type + " Api"}> + setModalData({ ...modalData, import: false })} + /> + ); }; diff --git a/src/components/tree/tree.tsx b/src/components/tree/tree.tsx index 4efca12..689e25d 100644 --- a/src/components/tree/tree.tsx +++ b/src/components/tree/tree.tsx @@ -1,7 +1,7 @@ import { TreeNodeProps, TreeNodeType } from '@site/src/types/components'; import useIsBrowser from '@docusaurus/useIsBrowser'; import React, { useState, useEffect } from 'react'; -import { Add, Delete, Edit } from './icon'; +import { Add, Delete, Edit, Import } from './icon'; import Popconfirm from './confirm-delete'; import './index.scss'; @@ -35,38 +35,64 @@ export const TreeNode: React.FC = ({ nodes, onAdd, onEdit, treeDa }); }; + const getIconSrc = (level: number, node: TreeNodeType) => { + switch (level) { + case 1: + return '/icons/Recruitment.svg'; + case 2: + return `/icons/${node?.id}.svg`; + case 3: + return `/icons/${node?.adaptorKey}.svg`; + case 4: + return `/icons/api.svg`; + default: + return '/icons/default.svg'; + } + }; + const renderNodes = (nodes: TreeNodeType[], level: number = 1, parentId: string | null = null) => { return nodes.map((node) => (
-
handleToggle(node.id, level)}> +
handleToggle(node.id, level)}>
-
onAdd(node, level)}> - {node?.add && } -
-
onEdit({ ...node, title: parentId }, level)}> - {node?.edit && } -
- { - node?.delete && { }} - treeData={treeData} - setTreeData={setTreeData} - > - - + {node?.add && +
onAdd(node, level)}> + +
+ } + {node?.import && +
onAdd(node, level)}> + {node?.type === "SERVER" && } +
+ } + {node?.edit && +
onEdit({ ...node, title: parentId }, level)}> + +
+ } + {node?.delete && +
+ { }} + treeData={treeData} + setTreeData={setTreeData} + > + + +
}
@@ -80,4 +106,4 @@ export const TreeNode: React.FC = ({ nodes, onAdd, onEdit, treeDa }; return
{renderNodes(nodes)}
; -}; \ No newline at end of file +}; diff --git a/src/components/user-as-a-service/import-api.tsx b/src/components/user-as-a-service/import-api.tsx index c2f903a..2a81a1f 100644 --- a/src/components/user-as-a-service/import-api.tsx +++ b/src/components/user-as-a-service/import-api.tsx @@ -43,16 +43,17 @@ const ImportApi = () => { return (
- */} + {/* Import {importState === true && Import successful!} - {importState !== true && importState !== null && {importState}} + {importState !== true && importState !== null && {importState}} */}
); }; diff --git a/src/css/custom.css b/src/css/custom.css index c4a4e27..aa89650 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -23,6 +23,8 @@ --modal-bg-color: white; --modal-border-color: #eaeaea; --modal-shadow-color: rgba(0, 0, 0, 0.1); + --default: rgba(0, 0, 0); + --icon-invert: invert(0); } [data-theme='dark'] { @@ -43,6 +45,8 @@ --modal-bg-color: #444; --modal-border-color: #555; --modal-shadow-color: rgba(0, 0, 0, 0.5); + --default: rgba(255, 255, 255); + --icon-invert: invert(1); } .teal-img, diff --git a/src/hooks/submit.tsx b/src/hooks/submit.tsx new file mode 100644 index 0000000..5e22363 --- /dev/null +++ b/src/hooks/submit.tsx @@ -0,0 +1,38 @@ +import { useState } from 'react'; + +interface UseSubmitFormResult { + isSubmitting: boolean; + error: string | null; + handleSubmit: (submitFunction: () => Promise) => void; + setError?: (error: string | null) => void; +} + +const useSubmitForm = (): UseSubmitFormResult => { + const [isSubmitting, setIsSubmitting] = useState(false); + const [error, setErrorState] = useState(null); + + const handleSubmit = async (submitFunction: () => Promise) => { + setIsSubmitting(true); + setErrorState(null); + try { + await submitFunction(); + setIsSubmitting(false); + } catch (err: any) { + setErrorState(err.message || 'An error occurred'); + setIsSubmitting(false); + } + }; + + const setError = (error: string | null) => { + setErrorState(error); + }; + + return { + isSubmitting, + error, + handleSubmit, + setError, + }; +}; + +export default useSubmitForm; diff --git a/src/types/components.ts b/src/types/components.ts index 499e947..cda0802 100644 --- a/src/types/components.ts +++ b/src/types/components.ts @@ -8,6 +8,7 @@ export interface TreeNodeType { add?: boolean; edit?: boolean; delete?: boolean; + import?: boolean; adaptorKey?: string; children: TreeNodeType[]; } @@ -17,11 +18,12 @@ export interface HostType { } export interface ModalType { - type: 'Create' | 'Edit'; + type: string; title?: string; id?: string; callgent?: boolean; endpoint?: boolean; + import?: boolean; initialData?: TreeNodeType; } diff --git a/static/icons/RestAPI.svg b/static/icons/RestAPI.svg new file mode 100644 index 0000000..7b6839b --- /dev/null +++ b/static/icons/RestAPI.svg @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/static/icons/api.svg b/static/icons/api.svg new file mode 100644 index 0000000..d7b3b55 --- /dev/null +++ b/static/icons/api.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file From 4c3659d1ac707ba5a6a769f0b12dfadc12a5488e Mon Sep 17 00:00:00 2001 From: ZhaoYongchao Date: Thu, 4 Jul 2024 13:48:16 +0800 Subject: [PATCH 31/36] style: background Signed-off-by: ZhaoYongchao --- src/css/custom.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/css/custom.css b/src/css/custom.css index aa89650..4cf087c 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -15,7 +15,7 @@ --ifm-code-font-size: 95%; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); --popconfirm-bg-color: white; - --popconfirm-border-color: #ccc; + --popconfirm-border-color: #ededed; --popconfirm-button-bg-color: #25c2a0; --popconfirm-button-text-color: white; --popconfirm-cancel-button-bg-color: #ccc; From fff8513c1ae592df914b08acec690a5da243050c Mon Sep 17 00:00:00 2001 From: ZhaoYongchao Date: Sun, 7 Jul 2024 12:44:42 +0800 Subject: [PATCH 32/36] fix: import Signed-off-by: ZhaoYongchao --- src/components/tree/index.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/tree/index.tsx b/src/components/tree/index.tsx index 2b3c928..d52d898 100644 --- a/src/components/tree/index.tsx +++ b/src/components/tree/index.tsx @@ -74,10 +74,12 @@ const CascadingMenu: React.FC = ({ adaptorKey, name }: { adaptorKey?: string, na const enhanceNode = (node: TreeNodeType, level: number): TreeNodeType => { let enhancedNode = { ...node }; - if (level === 1 || level === 3) { - enhancedNode = { ...enhancedNode, edit: true, delete: true }; - } else if (level === 2) { + if (level === 2) { enhancedNode = { ...enhancedNode, add: true }; + } else if (level === 3 && node?.type === "SERVER") { + enhancedNode = { ...enhancedNode, edit: true, delete: true, import: true }; + } else if (level === 1 || level === 3) { + enhancedNode = { ...enhancedNode, edit: true, delete: true }; } if (node.children) { enhancedNode.children = node.children.map(child => enhanceNode(child, level + 1)); From a3239d478163f9ac7d472964835b7f3ad935cacb Mon Sep 17 00:00:00 2001 From: ZhaoYongchao Date: Thu, 25 Jul 2024 13:38:20 +0800 Subject: [PATCH 33/36] fix: import Signed-off-by: ZhaoYongchao --- src/components/tree/import.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/tree/import.tsx b/src/components/tree/import.tsx index 0f9c041..8539eae 100644 --- a/src/components/tree/import.tsx +++ b/src/components/tree/import.tsx @@ -31,12 +31,13 @@ const Import: React.FC = ({ initialData, type, adaptorKey, treeD // }); null : - await axios.post('/api/callgent-functions/import', formValues).then(req => { + await axios.post('/api/bff/callgent-functions/import', formValues).then(req => { setImportState(true); setTimeout(() => { onClose(); }, 350); let { data } = req.data; data.id = data.uuid; data.type = "Import"; + data.name = formValues?.text onSubmit(data); }).catch(error => { const { data } = error.response; From f3a9fd801a2b0b67287f38d8e740b5d29465cdbb Mon Sep 17 00:00:00 2001 From: dev-callgent Date: Sun, 7 Jul 2024 12:52:03 +0800 Subject: [PATCH 34/36] feat: callgent tree Signed-off-by: dev-callgent --- .../index.md | 2 +- src/components/tree/import.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/2024-05-09-5-reasons-why-callgent-is-revolutionizing-business-operations/index.md b/blog/2024-05-09-5-reasons-why-callgent-is-revolutionizing-business-operations/index.md index b20f422..f3c3a56 100644 --- a/blog/2024-05-09-5-reasons-why-callgent-is-revolutionizing-business-operations/index.md +++ b/blog/2024-05-09-5-reasons-why-callgent-is-revolutionizing-business-operations/index.md @@ -3,7 +3,7 @@ slug: 5-reasons-why-callgent.com-is-revolutionizing-business-operations title: 🚀 5 Reasons Why Callgent is Revolutionizing Business Operations authors: jamesp tags: [Industry Trends, Architecture Patterns, Product Design] -keywords: [AI-powered business operation platform, seamless system integration solutions, natural language workflow automation, integrate business systems without coding, AI integration in enterprise operations, no-code AI tools for businesses, automate business operations with AI, Callgent open-source enterprise solutions, AI iPaaS] +keywords: [Customer Service, Help Desk, IT Service Management, AI-powered business operation platform, natural language workflow automation, AI integration in enterprise operations, no-code AI tools for businesses, automate business operations with AI, AI iPaaS] description: Uncover how Callgent revolutionizes business operations by simplifying complex processes with its innovative no-code, AI-driven platform. Learn about its features, integrations, and benefits for various business environments. --- diff --git a/src/components/tree/import.tsx b/src/components/tree/import.tsx index 8539eae..f678c5a 100644 --- a/src/components/tree/import.tsx +++ b/src/components/tree/import.tsx @@ -48,7 +48,7 @@ const Import: React.FC = ({ initialData, type, adaptorKey, treeD return (
- +
From afb45bfc9fc02f353907cf865093fec6423549ae Mon Sep 17 00:00:00 2001 From: dev-callgent Date: Wed, 14 Aug 2024 09:48:25 +0800 Subject: [PATCH 35/36] docs: group-invocation Signed-off-by: dev-callgent --- .../generative-ui.md | 2 +- solutions/showcase/user-as-a-service/_category_.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/2024-06-17-generative-ui-home-cooked-software-development/generative-ui.md b/blog/2024-06-17-generative-ui-home-cooked-software-development/generative-ui.md index 5b09711..b474c20 100644 --- a/blog/2024-06-17-generative-ui-home-cooked-software-development/generative-ui.md +++ b/blog/2024-06-17-generative-ui-home-cooked-software-development/generative-ui.md @@ -11,7 +11,7 @@ AI Large Language Models (LLMs) are ushering in a new golden age of [Home-Cooked ## What is Generative UI? -From now on, forget the traditional software paradigm. +From now on, forget about the traditional software paradigm. Imagine if we treated every interaction between a user and an app as a chat, with the only difference being that the content of the chat is not text, but rather a collection of widgets. diff --git a/solutions/showcase/user-as-a-service/_category_.json b/solutions/showcase/user-as-a-service/_category_.json index 36962d0..08c7cc6 100644 --- a/solutions/showcase/user-as-a-service/_category_.json +++ b/solutions/showcase/user-as-a-service/_category_.json @@ -4,6 +4,6 @@ "collapsed": true, "link": { "type": "generated-index", - "description": "Now, let's encapsulate a user as a REST-API service. By default, the user may respond to invocations by email. And user can respond from Slack channels and other scenarios easily." + "description": "Now, let's encapsulate a user as a REST-API service. By default, the user may respond to invocations by email. Also user can respond from Slack channels and other scenarios easily." } } From 0acf9d83b4d8b83558ef25322ef588807c37f73e Mon Sep 17 00:00:00 2001 From: dev-callgent Date: Wed, 14 Aug 2024 13:35:29 +0800 Subject: [PATCH 36/36] docs: composite callgent Signed-off-by: dev-callgent --- docs/advanced-topics/callgent-hub.md | 2 +- docs/advanced-topics/composite-callgent.md | 49 ++++++++++++++++++ .../_category_.json | 2 +- .../advanced-topics/composite-callgent.md | 51 +++++++++++++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 docs/advanced-topics/composite-callgent.md create mode 100644 i18n/zh/docusaurus-plugin-content-docs/current/advanced-topics/composite-callgent.md diff --git a/docs/advanced-topics/callgent-hub.md b/docs/advanced-topics/callgent-hub.md index 0631fc5..439c478 100644 --- a/docs/advanced-topics/callgent-hub.md +++ b/docs/advanced-topics/callgent-hub.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 4 --- # Callgent Hub diff --git a/docs/advanced-topics/composite-callgent.md b/docs/advanced-topics/composite-callgent.md new file mode 100644 index 0000000..5c2bd17 --- /dev/null +++ b/docs/advanced-topics/composite-callgent.md @@ -0,0 +1,49 @@ +--- +sidebar_position: 2 +keywords: [composite callgent, group callgent, Nested Callgents] +description: Learn how to create and manage a Composite Callgent. Discover how to handle complex call requests, utilize nested callgents, and perform map/reduce operations. Simplify your call process with a single call endpoint and efficient callgent orchestration.. +--- + +# Group of Callgents + +Multiple callgents can naturally be combined to form a new composite callgent, working together to handle a complex call request. + +## Creating a Composite Callgent + +Similar to a regular callgent, which maintains a list of `function entries` to automatically map each request to a function entry, call it, and return the result, a composite callgent maintains a list of callgents. This allows each request to be automatically mapped to a `callgent entry`, called, and the result returned. + +:::tip +Callgent entries come in two types: `function entries` and `callgent entries`. These two types of entries can be mixed together. + +A callgent that contains `callgent entries` is typically referred to as a composite callgent. +::: + +## Composite Callgent Invocation Process + +When a request reaches a composite callgent, the composite callgent automatically selects a `callgent entry` based on the semantic information in the request and invokes that callgent entry. + +The callgent entry can be a regular callgent or another composite callgent. If the `callgent entry` is another composite callgent, that composite callgent will recursively process the request until it is fully handled. + +:::tip +Composite callgents can be nested, forming a call tree. Each node in the call tree is a callgent, and each node can call other nodes. +::: + +## Multiple Internal Invocations + +A callgent automatically maps a single request to an entry for processing and retrieves the response result. Based on the original request, the callgent decides whether to return the response to the caller or continue calling the next entry. This process repeats until the final result is returned to the caller. + +### Request with Collection Data + +If the request contains collection data, the callgent may automatically perform map/reduce operations on the collection and map it to entry calls as needed. + +## Advantages of Composite Callgent + +Composite Callgent allows multiple callgents to work together while maintaining a single call endpoint, enabling the handling of complex call requests. + +:::info +Composite Callgent allows you to interact with a single callgent to invoke multiple callgents, simplifying the call process. +::: + +:::tip +If you prefer to decide which callgents handle each task, i.e., you manually orchestrate multiple callgents, you can choose not to rely on Composite Callgent. +::: diff --git a/docs/advanced-topics/event-driven-orchestration/_category_.json b/docs/advanced-topics/event-driven-orchestration/_category_.json index 5bbf9e4..af6b1b9 100644 --- a/docs/advanced-topics/event-driven-orchestration/_category_.json +++ b/docs/advanced-topics/event-driven-orchestration/_category_.json @@ -1,6 +1,6 @@ { "label": "Event Driven Orchestration", - "position": 2, + "position": 3, "link": { "type": "doc", "id": "orchestration" diff --git a/i18n/zh/docusaurus-plugin-content-docs/current/advanced-topics/composite-callgent.md b/i18n/zh/docusaurus-plugin-content-docs/current/advanced-topics/composite-callgent.md new file mode 100644 index 0000000..81b3bd2 --- /dev/null +++ b/i18n/zh/docusaurus-plugin-content-docs/current/advanced-topics/composite-callgent.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 2 +keywords: [组合式Callgent, 复杂调用请求, 嵌套Callgent, Callgent编排] +description: 了解如何创建和管理组合式Callgent。发现如何处理复杂调用请求,利用嵌套Callgent和Map/Reduce操作。通过单一调用端点和高效的Callgent编排简化您的调用流程。 +--- + +# Group of Callgents + +多个callgents可以自然地组合起来,形成一个新的组合式callgent,共同处理一个复杂的调用请求。 + +## 创建一个Group Callgent + +类比一下普通callgent,其内部会维护一个function entries列表,从而使得每个请求可以自动映射到一个function entry上,调用并返回结果。 + +同理,创建一个group callgent,其内部会维护一个callgents列表,从而使得每个请求可以自动映射到一个callgent entry上,调用并返回结果。 + +:::tip +callgent内部的entry有2个类型:function entry和callgent entry。两种entries可以混合一起。 + +具有callgent entry的的callgent,我们通常称之为group callgent。 +::: + +## Group Callgent的调用流程 + +当请求到达group callgent时,group callgent会根据请求中的语义信息,自动选择一个callgent entry,并调用该callgent entry。 + +callgent entry可以是普通的callgent,也可以是另一个group callgent。如果callgent entry是另一个group callgent,那么该group callgent会递归地处理请求,直到请求被处理完毕。 + +:::tip +group callgent可以嵌套调用,从而形成一个调用树。调用树中的每个节点都是一个callgent,每个节点都可以调用其他节点。 +::: + +## Multiple Internal Invocations + +Callgent会自动将单个请求,映射到一个entry上处理并拿到响应结果,基于原始的请求,Callgent会决定是否返回响应给调用者,还是继续调用下一个entry;如此循环,直至最终返回结果给调用者。 + +### Request with Collection Data + +如果请求中包含集合数据,那么callgent可能会根据需求,自动将集合做map/reduce,并映射到entry调用上。 + +## Group Callgent的优势 + +Group Callgent在保持单一调用端点的前提下,可以使得多个callgent协同工作,从而处理复杂的调用请求。 + +:::info +Group Callgent使得你只需与单个callgent交互,就可以调用多个callgent,从而简化了调用流程。 +::: + +:::tip +如果你希望自行决定每个任务希望由哪些callgent处理,也就是说你自行编排多个Callgents,则你也可以不依赖Group Callgent。 +:::